Bug 1559564 - RFE: generate "/etc/crypto-policies/back-ends/edk2.config" [NICE TO HAVE]
Summary: RFE: generate "/etc/crypto-policies/back-ends/edk2.config" [NICE TO HAVE]
Keywords:
Status: NEW
Alias: None
Product: Fedora
Classification: Fedora
Component: crypto-policies
Version: rawhide
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: ---
Assignee: Alexander Sosedkin
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks: 1559586 1688978
TreeView+ depends on / blocked
 
Reported: 2018-03-22 18:57 UTC by Laszlo Ersek
Modified: 2022-11-10 08:58 UTC (History)
6 users (show)

Fixed In Version:
Doc Type: Enhancement
Doc Text:
Clone Of:
Environment:
Last Closed:
Type: Bug
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Gitlab redhat-crypto/fedora-crypto-policies/issues/12 0 None None None 2019-01-03 17:35:58 UTC
TianoCore 2424 0 None None None 2020-01-03 18:37:29 UTC

Description Laszlo Ersek 2018-03-22 18:57:30 UTC
This feature request is for a new back-end generator in the crypto-policies
package <https://fedoraproject.org/wiki/Changes/CryptoPolicy>; more
precisely in the update-crypto-policies(8) tool.

The current back-ends are listed in the update-crypto-policies(8) manual
page. A new back-end, called "EDK2", is being requested. The output file
should be "edk2.config".

EDK2 stands for "EFI Development Kit II". It is a project for the
development of firmware that conforms to the PI (Platform Init) and/or UEFI
specifications.

Such firmware is available for QEMU/KVM virtual machines. The firmware
platforms are usually known as "OVMF" (for x86 VMs) and "ArmVirtQemu" or
"AAVMF" (for ARM/ARM64 VMs).

UEFI supports HTTPS boot; that is, the above-mentioned virtual firmware can
boot a virtual machine off the network, and not just via PXE, but also via
HTTPS. For this, the firmware uses OpenSSL internally, but the configuration
interface is peculiar. The subject of this RFE is to expose "the acceptable
ciphersuites and the preferred order" from the *host* side, in the file
"/etc/crypto-policies/back-ends/edk2.config", such that the userspace part
of the VMM (namely QEMU) can pass it to the virtual firmware without any
processing. This way the crypto policy configured on the virt host will also
apply to the HTTPS boot carried out by the UEFI VM.

Section "28.10.2 EFI TLS Protocol" of the UEFI-2.7 spec
<http://uefi.org/specifications> defines the following structure:

> typedef struct {
>   UINT8 Data1;
>   UINT8 Data2;
> } EFI_TLS_CIPHER;
>
> Note: The definition of EFI_TLS_CIPHER is from RFC 5246 A.4.1.Hello
> Messages. The value of EFI_TLS_CIPHER is from TLS Cipher Suite Registry of
> IANA.

The "update-crypto-policies" utility should please transform the cipher list
to an array of EFI_TLS_CIPHER elements, and store that array in
"edk2.config". The size need not be stored separately (it can be deduced
from the file size).

Thanks.

Comment 5 Laszlo Ersek 2018-03-30 23:05:30 UTC
OK, I've taken a good look at the "fedora-crypto-policies" tree. While I get
the general idea (with thanks to the developers for the good description in
"README.md"), I would really like to avoid writing a patch for this code
myself, for two reasons:

- I have near zero Perl experience,

- the consequences of messing up here are grim -- this is not a project
  where I should try to refresh my Perl memories from approx. 20 years ago.

On the other hand, *conceptually* the change is not hard, so I believe
asking for upstream maintainers to write this patch "for me" isn't really
asking much. These are the steps, logically speaking:

(1) Configure OpenSSL as the selected profile (the "policy") dictates.

    This step produces "/etc/crypto-policies/back-ends/openssl.config" in
    the textual OpenSSL cipher list format. (The format is defined in the
    ciphers(1) manual, under CIPHER LIST FORMAT and CIPHER STRINGS.)

    This is already done by "fedora-crypto-policies".

(2) Make OpenSSL print the resultant ordered SSL cipher preference list, and
    not just the names of the cipher suites, but also their codes.

    The ciphers(1) utility already supports this, with the "-V" option.
    Quoting a few lines of it (be sure to click "Unwrap comments" at the top
    to appreciate the list):

    $ openssl ciphers -V | head

>           0xC0,0x2C - ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AESGCM(256) Mac=AEAD
>           0xC0,0x30 - ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH     Au=RSA  Enc=AESGCM(256) Mac=AEAD
>           0xCC,0xA9 - ECDHE-ECDSA-CHACHA20-POLY1305 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=CHACHA20/POLY1305(256) Mac=AEAD
>           0xCC,0xA8 - ECDHE-RSA-CHACHA20-POLY1305 TLSv1.2 Kx=ECDH     Au=RSA  Enc=CHACHA20/POLY1305(256) Mac=AEAD
>           0xC0,0xAF - ECDHE-ECDSA-AES256-CCM8 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AESCCM8(256) Mac=AEAD
>           0xC0,0xAD - ECDHE-ECDSA-AES256-CCM  TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AESCCM(256) Mac=AEAD
>           0xC0,0x2B - ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AESGCM(128) Mac=AEAD
>           0xC0,0x2F - ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH     Au=RSA  Enc=AESGCM(128) Mac=AEAD
>           0xC0,0xAE - ECDHE-ECDSA-AES128-CCM8 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AESCCM8(128) Mac=AEAD
>           0xC0,0xAC - ECDHE-ECDSA-AES128-CCM  TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AESCCM(128) Mac=AEAD

    The hex codes to the left are exactly the EFI_TLS_CIPHER fields (Data1,
    Data2) that edk2 needs (see comment 0).

(3) Turn the hex codes into bytes. This produces the EFI_TLS_CIPHER array
    needed by edk2.

For example, the following shell script produces the binary file needed,
using the current OpenSSL crypto policy ("hexdump" added at the end for
readability):

  export LC_ALL=C
  openssl ciphers -V \
  | sed -r -n \
      -e 's/^ *0x([0-9A-F]{2}),0x([0-9A-F]{2}) - .*$/\\\\x\1 \\\\x\2/p' \
  | xargs -r -- printf -- '%b' \
  | hexdump -C

> 00000000  c0 2c c0 30 cc a9 cc a8  c0 af c0 ad c0 2b c0 2f  |.,.0.........+./|
> 00000010  c0 ae c0 ac c0 24 c0 28  c0 73 c0 77 c0 23 c0 27  |.....$.(.s.w.#.'|
> 00000020  c0 72 c0 76 c0 0a c0 14  c0 09 c0 13 c0 08 c0 12  |.r.v............|
> 00000030  00 9d c0 a1 c0 9d 00 9c  c0 a0 c0 9c 00 3d 00 c0  |.............=..|
> 00000040  00 3c 00 ba 00 35 00 84  00 2f 00 41 00 0a 00 a3  |.<...5.../.A....|
> 00000050  00 9f cc aa c0 a3 c0 9f  00 a2 00 9e c0 a2 c0 9e  |................|
> 00000060  00 6b 00 6a 00 c4 00 c3  00 67 00 40 00 be 00 bd  |.k.j.....g.@....|
> 00000070  00 39 00 38 00 88 00 87  00 33 00 32 00 45 00 44  |.9.8.....3.2.E.D|
> 00000080  00 16 00 13 00 a9 cc ab  c0 a9 c0 a5 00 a8 c0 a8  |................|
> 00000090  c0 a4 00 af 00 8d c0 95  00 ae 00 8c c0 94 00 8b  |................|
> 000000a0  00 ab cc ad c0 ab c0 a7  00 aa c0 aa c0 a6 00 b3  |................|
> 000000b0  00 91 c0 97 00 b2 00 90  c0 96 00 8f cc ac c0 38  |...............8|
> 000000c0  c0 36 c0 9b c0 37 c0 35  c0 9a c0 34              |.6...7.5...4|
> 000000cc

Thanks.

Comment 7 Nikos Mavrogiannopoulos 2018-04-03 06:41:49 UTC
It seems like a reasonable request. I've added it to crypto team plan. However to the point, that interface to set ciphers isn't sufficient. One cannot specify the protocol version (e.g., TLS1.2 or TLS1.3), and ciphersuite numbers mean very little under TLS1.3 (there are only 3-4 ciphersuites). Can the interface to set these options be modified to something else? Otherwise this will be an uphill battle with more and more changes to come.

btw. The medium to communicate for crypto policies upstream is the issue tracker.

Comment 8 Laszlo Ersek 2018-04-03 10:19:24 UTC
(In reply to Nikos Mavrogiannopoulos from comment #7)
> It seems like a reasonable request. I've added it to crypto team plan.

Thank you, Nikos!

> However to the point, that interface to set ciphers isn't sufficient. One
> cannot specify the protocol version (e.g., TLS1.2 or TLS1.3), and
> ciphersuite numbers mean very little under TLS1.3 (there are only 3-4
> ciphersuites). Can the interface to set these options be modified to
> something else?

Unfortunately, this is the core of the problem. The interface is very unwieldy, but it is part of the UEFI-2.7 specification, and any changes or extensions to it require standardization work (in the UEFI Specification Working Group). While Red Hat is a member company on the USWG, and I'm personally an "Observer" there (with some other Red Hatters holding higher "rank" such as voting rights), the process to get anything into the UEFI spec is *glacial*.

I have "been there" several times, and my educated opinion is that the standardization process -- with the Engineering Change Requests that need to be filed in Mantis and then sold verbally on the conference calls, and then the voting process weeks or months later -- is an extreme time sink, fraught with politics and proprietary considerations. (The UEFI forum and the USWG list are closed fora to begin with.) Just last week I had to write up the same experience for a different topic [1] [2].

[1] http://post-office.corp.redhat.com/archives/virt-arm/2018-March/msg00029.html
[2] http://post-office.corp.redhat.com/archives/virt-arm/2018-March/msg00030.html

Unfortunately, this is a general pattern with all UEFI interfaces, not just the crypto interfaces. UEFI is meant to enable inter-operation between proprietary (binary only) vendors. Many of the interfaces are ossified, and require firmware implementations to dance around them delicately, for compatibility.

In this specific instance, the simplest solution to the actual problem would be passing in the contents of "/etc/crypto-policies/back-ends/openssl.config". But OVMF cannot do that because that's not what the UEFI spec defines for the interface. I cannot avoid the interface and I cannot extend the interface either.

To my understanding, UEFI / edk2 currently targets TLSv1.0 through TLSv1.2. I'm sure once TLSv1.3 is out, the UEFI spec will be extended to match TLSv1.3 as well. It will take several months of course for the specification to settle, and then core edk2 code can be written for it, and then (as the last step) I might be able to write OVMF platform enablement code to exercise the new core feature.

> Otherwise this will be an uphill battle with more and more
> changes to come.

Yes, I totally expect that; this is how UEFI works. The only way for us to expedite the process would be to delegate a crypto / TLS expert to the UEFI forum, who'd have this assignment as first priority.

Until then the operating idea is to do anything possible to stay within the framework of existing (already specified) interfaces, even if they suck. :(

> btw. The medium to communicate for crypto policies upstream is the issue
> tracker.

Do you want me to duplicate this RFE there? (From your comment 2 I can find the upstream tracker.)

Thank you, Nikos!

Comment 13 Nikos Mavrogiannopoulos 2018-04-13 10:44:37 UTC
We had a phone discussion with Laszlo to understand what is going on/needed, and we checked the UEFI spec [0] for TLS configuration. I'll provide a quick summary.

It provides a way to configure
 1. TLS protocol version (EFI_TLS_VERSION)
 2. TLS ciphersuites (EFI_TLS_CIPHER)
 3. Arbitrary TLS extension (EFI_TLS_EXTENSION)

For a complete crypto policies coverage we need:
 a. TLS protocol version
 b. Acceptable ciphers
 c. Acceptable groups (secp256r1/ffdhe etc)
 d. Acceptable signature algorithms (rsa-sha1, rsa-sha256, ...)
 e. Minimum acceptable DH parameters (for <tls1.2)

The mapping of 1-a, 2-b is quite straightforward.
For (c) and (d) a solution would be to map to the 'Supported Groups Extension' [1] and to 'signature algorithms extension' [2]. (e) is not currently available, but we could address it by eliminating DH support (without groups) from UEFI firmware.

Laszlo took an action item to figure whether the mapping of (c) and (d) to an extension, makes sense from the UEFI perspective on the committee.

If that makes sense, we can have (a quite elaborate) plan to address the issue.

[0].
http://www.uefi.org/sites/default/files/resources/UEFI_Spec_2_7.pdf

[1]
https://tools.ietf.org/html/draft-ietf-tls-tls13-28#section-4.2.7

[2].
https://tools.ietf.org/html/draft-ietf-tls-tls13-28#section-4.2.3

Comment 17 Laszlo Ersek 2018-04-25 17:37:37 UTC
From the discussion thus far:

> For a complete crypto policies coverage we need:
>  a. TLS protocol version

- current spec interface: allows for a single version setting (such as 1.1)

- desired spec interface: allows for a set of versions (not a range). It
                          maps to EFI_TLS_PROTOCOL.SetSessionData() with
                          DataType=EfiTlsExtensionData, ExtensionType=43,
                          so any spec changes for this are not a hard
                          requirement.

- current edk2 implementation: on par with the *current* spec interface,
                               DataType=EfiTlsExtensionData missing

- integration with OVMF: nonexistent; in practice we start out with 1.2 and
                         the server can negotiate down to 1.0 (as I
                         understand)

>  b. Acceptable ciphers

- current spec interface: allows for a list of cipher IDs
- desired spec interface: no changes required
- current edk2 implementation: on par with the current spec interface
- integration with OVMF: complete (bug 1536624)
- integration with QEMU: none (bug 1559586)

>  c. Acceptable groups (secp256r1/ffdhe etc)

- current spec interface: EFI_TLS_PROTOCOL.SetSessionData() with
                          DataType=EfiTlsExtensionData, ExtensionType=10
- desired spec interface: no changes required
- current edk2 implementation: DataType=EfiTlsExtensionData missing

>  d. Acceptable signature algorithms (rsa-sha1, rsa-sha256, ...)

- current spec interface: EFI_TLS_PROTOCOL.SetSessionData() with
                          DataType=EfiTlsExtensionData, ExtensionType=13/50
- desired spec interface: no changes required
- current edk2 implementation: DataType=EfiTlsExtensionData missing

>  e. Minimum acceptable DH parameters (for <tls1.2)

- current spec interface: none for key length; the permitted groups map to
                          (c)

- desired spec interface: no changes required
                          (setting the permitted groups suffices)

- current edk2 implementation: none, but DH can be disabled via filtering
                               out TLS cipher suites that use DH key
                               exchange -- hence see (b). The filtering
                               should presumably occur in
                               "fedora-crypto-policies".

- integration with OVMF: complete (bug 1536624)

- integration with QEMU: none (bug 1559586)

Comment 19 Tomas Mraz 2018-12-20 15:40:02 UTC
This RFE should be tracked in upstream https://gitlab.com/redhat-crypto/fedora-crypto-policies.

Comment 23 Laszlo Ersek 2020-11-19 09:37:54 UTC
new upstream discussion:

https://edk2.groups.io/g/devel/message/67698
https://www.redhat.com/archives/edk2-devel-archive/2020-November/msg00856.html
msgid: <59631a69-a285-b195-8f8c-de135e877def>

Comment 24 Alexander Sosedkin 2022-10-19 11:54:51 UTC
So, is this actionable?

On my side, I can offer to generate a config in any format you want in /etc/crypto-policies/back-ends/. Is the other side ready to consume one?

Comment 26 Gerd Hoffmann 2022-11-08 12:19:48 UTC
[ just back online from sick leave ]

Ok, so state of affairs is that edk2 accepts etc/edk2/https/cacerts + etc/edk2/https/ciphers via fw_cfg,
where as far I know cacerts is just a standard efi siglist (/etc/pki/ca-trust/extracted/edk2/cacerts.bin
can be used as-is).

If I read this bug correctly /etc/crypto-policies/back-ends/edk2.config should be a file which can be
passed to edk2 as 'chipers' file via fw_cfg, simliar to the cacert list we already have.  The format
simply an EFI_TLS_CHIPER array.

[ from MdePkg/Include/Protocol/Tls.h ]
///
/// EFI_TLS_CIPHER
/// Note: The definition of EFI_TLS_CIPHER definition is from "RFC 5246, A.4.1.
///       Hello Messages". The value of EFI_TLS_CIPHER is from TLS Cipher
///       Suite Registry of IANA.
///
#pragma pack (1)
typedef struct {
  UINT8    Data1;
  UINT8    Data2;
} EFI_TLS_CIPHER;
#pragma pack ()

[ from CryptoPkg/Library/TlsLib/TlsConfig.c ]
typedef struct {
  //
  // IANA/IETF defined Cipher Suite ID
  //
  UINT16         IanaCipher;
  //
  // OpenSSL-used Cipher Suite String
  //
  CONST CHAR8    *OpensslCipher;
  //
  // Length of OpensslCipher
  //
  UINTN          OpensslCipherLength;
} TLS_CIPHER_MAPPING;

//
// Create a TLS_CIPHER_MAPPING initializer from IanaCipher and OpensslCipher so
// that OpensslCipherLength is filled in automatically. IanaCipher must be an
// integer constant expression, and OpensslCipher must be a string literal.
//
#define MAP(IanaCipher, OpensslCipher) \
  { (IanaCipher), (OpensslCipher), sizeof (OpensslCipher) - 1 }

//
// The mapping table between IANA/IETF Cipher Suite definitions and
// OpenSSL-used Cipher Suite name.
//
// Keep the table uniquely sorted by the IanaCipher field, in increasing order.
//
STATIC CONST TLS_CIPHER_MAPPING  TlsCipherMappingTable[] = {
  MAP (0x0001, "NULL-MD5"),                         /// TLS_RSA_WITH_NULL_MD5
  MAP (0x0002, "NULL-SHA"),                         /// TLS_RSA_WITH_NULL_SHA
  MAP (0x0004, "RC4-MD5"),                          /// TLS_RSA_WITH_RC4_128_MD5
  MAP (0x0005, "RC4-SHA"),                          /// TLS_RSA_WITH_RC4_128_SHA
  MAP (0x000A, "DES-CBC3-SHA"),                     /// TLS_RSA_WITH_3DES_EDE_CBC_SHA, mandatory TLS 1.1
  MAP (0x0016, "DHE-RSA-DES-CBC3-SHA"),             /// TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
  MAP (0x002F, "AES128-SHA"),                       /// TLS_RSA_WITH_AES_128_CBC_SHA, mandatory TLS 1.2
  MAP (0x0030, "DH-DSS-AES128-SHA"),                /// TLS_DH_DSS_WITH_AES_128_CBC_SHA
  MAP (0x0031, "DH-RSA-AES128-SHA"),                /// TLS_DH_RSA_WITH_AES_128_CBC_SHA
  MAP (0x0033, "DHE-RSA-AES128-SHA"),               /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA
  MAP (0x0035, "AES256-SHA"),                       /// TLS_RSA_WITH_AES_256_CBC_SHA
  MAP (0x0036, "DH-DSS-AES256-SHA"),                /// TLS_DH_DSS_WITH_AES_256_CBC_SHA
  MAP (0x0037, "DH-RSA-AES256-SHA"),                /// TLS_DH_RSA_WITH_AES_256_CBC_SHA
  MAP (0x0039, "DHE-RSA-AES256-SHA"),               /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA
  MAP (0x003B, "NULL-SHA256"),                      /// TLS_RSA_WITH_NULL_SHA256
  MAP (0x003C, "AES128-SHA256"),                    /// TLS_RSA_WITH_AES_128_CBC_SHA256
  MAP (0x003D, "AES256-SHA256"),                    /// TLS_RSA_WITH_AES_256_CBC_SHA256
  MAP (0x003E, "DH-DSS-AES128-SHA256"),             /// TLS_DH_DSS_WITH_AES_128_CBC_SHA256
  MAP (0x003F, "DH-RSA-AES128-SHA256"),             /// TLS_DH_RSA_WITH_AES_128_CBC_SHA256
  MAP (0x0067, "DHE-RSA-AES128-SHA256"),            /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
  MAP (0x0068, "DH-DSS-AES256-SHA256"),             /// TLS_DH_DSS_WITH_AES_256_CBC_SHA256
  MAP (0x0069, "DH-RSA-AES256-SHA256"),             /// TLS_DH_RSA_WITH_AES_256_CBC_SHA256
  MAP (0x006B, "DHE-RSA-AES256-SHA256"),            /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
  MAP (0x009F, "DHE-RSA-AES256-GCM-SHA384"),        /// TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
  MAP (0xC02B, "ECDHE-ECDSA-AES128-GCM-SHA256"),    /// TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  MAP (0xC02C, "ECDHE-ECDSA-AES256-GCM-SHA384"),    /// TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
  MAP (0xC030, "ECDHE-RSA-AES256-GCM-SHA384"),      /// TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
};

Comment 27 Laszlo Ersek 2022-11-08 15:04:39 UTC
Hi Gerd,

the trusted CA certificates *and* the permitted cipher suites are *already* passed down to edk2 via fw_cfg. All that is functional.

The problem is that OpenSSL 3 / TLS-1.3 have a much more refined configuration interface. Nikos and myself had collected the "configuration artifacts" in question [*], and unfortunately, even if those *additional* config aspects / artifacts were exposed by "update-crypto-policies" on the host side in some edk2-specific way, and passed down to OVMF platform code via fw_cfg, still no information channel seems to exist *within* edk2 where those settings can be made "stick".

[*] The most "direct" reference at this time is the link in comment 23 on this ticket. Namely:

https://listman.redhat.com/archives/edk2-devel-archive/2020-November/msg00856.html

Please start reading it at:

> There are five aspects of TLSv1.3 that we would like to control.

Now let me summarize it quickly here. For the remaining discussion, the CA certificates should be put aside totally. The "five aspects" are entirely separate from the trusted CA certs -- the CA certs stuff is a "done deal" altogether.

So:

(a) TLS protocol version
(b) Acceptable ciphers
(c) Acceptable groups (secp256r1/ffdhe etc)
(d) Acceptable signature algorithms (rsa-sha1, rsa-sha256, ...)
(e) Minimum acceptable DH parameters (for <tls1.2)

From these items, item (b) Acceptable ciphers is already covered, end-to-end. The remaining items are (a), (c), (d), and (e).

If you read my linked analysis / summary, you'll find that (e) can be ignored -- it is covered by (b) and (c). Therefore the actually missing items (in edk2) are:

(a) TLS protocol version
(c) Acceptable groups (secp256r1/ffdhe etc)
(d) Acceptable signature algorithms (rsa-sha1, rsa-sha256, ...)

For implementing (a), edk2 needs to grow support for DataType=EfiTlsExtensionData in EFI_TLS_PROTOCOL.SetSessionData, ExtensionType=43.
For implementing (c), the same applies but with ExtensionType=10.
For implementing (d), the same applies but with ExtensionType=13/50.

To be clear, this is all "core edk2" development. No UEFI spec changes appear necessary, but EFI_TLS_PROTOCOL.SetSessionData needs to be able to interpret the above calls, and actually hook them up to OpenSSL APIs.

Once that is done, then a new fw_cfg-based wire-format should be designed for passing down (a), (c), and (d) from host to guest. In OVMF platform code, this fw_cfg content should be turned into the appropriate EFI_TLS_PROTOCOL.SetSessionData() calls, possibly in "OvmfPkg/Library/TlsAuthConfigLib".

That is the guest-side info channel. The corresponding host-side work would be for "update-crypto-policies" to extract (a), (c) and (d) into such a format that QEMU can expose over fw_cfg, so that OVMF can parse it (or at least pass it on to EFI_TLS_PROTOCOL.SetSessionData()).

Something like:

  update-crypto-policies ->
  /etc/crypto-policies/back-ends/edk2.config -- containing artifacts (a), (c) and (d) -->
  QEMU -->
  fw_cfg [host/guest interface] -->
  OVMF platform code -->
  possibly some internal / core edk2 configuration interface -->
  EFI_TLS_PROTOCOL.SetSessionData() -->
  OpenSSL APIs

Comment 28 Laszlo Ersek 2022-11-08 15:20:19 UTC
Regarding the existent functionality (as background): the QEMU options to pass down the CA certs and the cipher suites are documented in OvmfPkg/README, section "HTTPS Boot":

-fw_cfg name=etc/edk2/https/cacerts,file=/etc/pki/ca-trust/extracted/edk2/cacerts.bin \
\
-object tls-cipher-suites,id=mysuite0,priority=NORMAL \
-fw_cfg name=etc/edk2/https/ciphers,gen_id=mysuite0 \

The first fw_cfg file of these covers the trusted CA certs; the host-side file "/etc/pki/ca-trust/extracted/edk2/cacerts.bin" is created by "update-ca-trust" (which in turn calls "p11-kit extract --format=edk2-cacerts").

The second fw_cfg file covers item (b). It needs no separate host-side file, as QEMU's own TLS client code (for option "-object tls-cipher-suites") prepares the necessary fw_cfg file, using the right TLS APIs (for the initial introduction in QEMU, see commit range 4abf70a661a5..69699f3055a5).

Both interfaces (CA certs and cipher suites) are testable via UEFI HTTPS Boot, refer to <https://bugzilla.redhat.com/show_bug.cgi?id=1536624#c58> for example.

Thus, in theory anyway, it is possible that "update-crypto-policies" will not need a new output module / formatter, for exposing items (a), (c), (d). If QEMU can fetch those dynamically, via normal TLS APIs (I don't know), then the info chain would be something like this:

  QEMU -- collect artifacts (a), (c) and (d) -->
  fw_cfg [host/guest interface] -->
  OVMF platform code -->
  possibly some internal / core edk2 configuration interface -->
  EFI_TLS_PROTOCOL.SetSessionData() -->
  OpenSSL APIs

Comment 29 Gerd Hoffmann 2022-11-09 18:51:30 UTC
> The problem is that OpenSSL 3 / TLS-1.3 have a much more refined
> configuration interface. Nikos and myself had collected the "configuration
> artifacts" in question [*], and unfortunately, even if those *additional*
> config aspects / artifacts were exposed by "update-crypto-policies" on the
> host side in some edk2-specific way, and passed down to OVMF platform code
> via fw_cfg, still no information channel seems to exist *within* edk2 where
> those settings can be made "stick".

Ok, understood.  Right now OVMF is compiled without EC support, which
effectively disables TLS-1.3.  So I think this isn't a problem at all
right now.

My attempts to move edk2 to openssl3 are effectively stalled right now.
Moving to openssl3 is a significant bump in size which upstream finds
unacceptable and I don't see an easy way out.  My current approach is
'wait and see', right now I have neither the time nor the energy to
push this forward somehow.

rhel sec team has to maintain openssl11 for quite a while anyway (for
rhel-8), so openssl11 eol coming closer isn't that much of a headace.
Also edk2 doesn't expose openssl api directly, so the crypto library
used is just an implementation detail and we should be able to switch
at any time without compatibility problems.  But for the time being
we'll talk about openssl11 in edk2.

There is upstream activity for EC support (optional at compile time).
The patches I've seen so far seem to not include code for TLS 1.3 crypto
configuration though (Disclaimer: I'm a bit behind on emails right now
though due to sick leave).

> (a) TLS protocol version
> (b) Acceptable ciphers
> (c) Acceptable groups (secp256r1/ffdhe etc)
> (d) Acceptable signature algorithms (rsa-sha1, rsa-sha256, ...)
> (e) Minimum acceptable DH parameters (for <tls1.2)
> 
> From these items, item (b) Acceptable ciphers is already covered,
> end-to-end. The remaining items are (a), (c), (d), and (e).
> 
> If you read my linked analysis / summary, you'll find that (e) can be
> ignored -- it is covered by (b) and (c). Therefore the actually missing
> items (in edk2) are:
> 
> (a) TLS protocol version
> (c) Acceptable groups (secp256r1/ffdhe etc)
> (d) Acceptable signature algorithms (rsa-sha1, rsa-sha256, ...)

Ok, thanks for clarifying.  I think (c) matters for TLS-1.3 only, correct?
Not sure about (d), is this about ca cert signatures?

> For implementing (a), edk2 needs to grow support for
> DataType=EfiTlsExtensionData in EFI_TLS_PROTOCOL.SetSessionData,
> ExtensionType=43.
> For implementing (c), the same applies but with ExtensionType=10.
> For implementing (d), the same applies but with ExtensionType=13/50.
> 
> To be clear, this is all "core edk2" development. No UEFI spec changes
> appear necessary, but EFI_TLS_PROTOCOL.SetSessionData needs to be able to
> interpret the above calls, and actually hook them up to OpenSSL APIs.

OK.

Comment 30 Laszlo Ersek 2022-11-10 08:58:19 UTC
- Yes, my understanding is that "(c) Acceptable groups (secp256r1/ffdhe
  etc)" is only relevant for TLS-1.3; the earlier API does not expose
  this as configurable (IIUC). IIRC, Nikos pointed at this aspect as one
  that TLS-1.3 had brought about, sort of creating a "need for
  configuration" that had not been there before. So I think it's not
  urgent at all, given the (lack of) openssl version change in upstream
  edk2.

- "(d) Acceptable signature algorithms" may actually refer to two config
  knobs, "signature_algorithms" and "signature_algorithms_cert" (that's
  why I mentioned "ExtensionType=13/50"). The section in the TLS-1.3 RFC
  that covers those is at
  <https://www.rfc-editor.org/rfc/rfc8446#section-4.2.3>:

>    TLS 1.3 provides two extensions for indicating which signature
>    algorithms may be used in digital signatures.  The
>    "signature_algorithms_cert" extension applies to signatures in
>    certificates, and the "signature_algorithms" extension, which
>    originally appeared in TLS 1.2, applies to signatures in
>    CertificateVerify messages.  The keys found in certificates MUST
>    also be of appropriate type for the signature algorithms they are
>    used with.  This is a particular issue for RSA keys and PSS
>    signatures, as described below.  If no "signature_algorithms_cert"
>    extension is present, then the "signature_algorithms" extension
>    also applies to signatures appearing in certificates.  Clients
>    which desire the server to authenticate itself via a certificate
>    MUST send the "signature_algorithms" extension.  If a server is
>    authenticating via a certificate and the client has not sent a
>    "signature_algorithms" extension, then the server MUST abort the
>    handshake with a "missing_extension" alert (see Section 9.2).
>
>    The "signature_algorithms_cert" extension was added to allow
>    implementations which supported different sets of algorithms for
>    certificates and in TLS itself to clearly signal their
>    capabilities. TLS 1.2 implementations SHOULD also process this
>    extension. Implementations which have the same policy in both cases
>    MAY omit the "signature_algorithms_cert" extension. [...]


Note You need to log in before you can comment on or make changes to this bug.