FIPS mode and TLS

From OpenSSLWiki
Revision as of 08:32, 2 February 2024 by Matt (talk | contribs) (Added sentence about the new FIPS module)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

This page discusses the use of FIPS with OpenSSL 1.0.x. It is NOT relevant to the FIPS provider in OpenSSL 3.0 or above.

The new SP800-131A and FIPS 186-4 restrictions on algorithms and key sizes complicate the use of ciphersuites for TLS considerably. This page is intended to answer the question "can I configure an OpenSSL cipherstring for TLS to comply with the new FIPS restrictions?".

This discussion assumes use of a "FIPS capable" OpenSSL 1.0.1f or later.

A new security framework in development for future versions will make enforcing these types of restrictions easier and the algorithm restrictions are performed all in one place.

Quick Summary[edit]

The preferred cipherstring for OpenSSL 1.0.1f+ for all versions of TLS subject to the new FIPS restrictions is:

	'TLSv1.2+FIPS:kRSA+FIPS:!eNULL:!aNULL'

However, multiple caveats apply as discussed below.

Workarounds for OpenSSL releases prior to 1.0.1f are discussed below.

Detailed discussion[edit]

The general rule is you can't use SHA1 for digital signatures any more nor a combination like MD5+SHA1. You *can* use SHA1 for HMAC so there's no need to force the use of SHA256 HMAC ciphersuites.

A cipherstring in OpenSSL also known as a "cipher list" https://www.openssl.org/docs/apps/ciphers.html#CIPHER_STRINGS A cipherstring in OpenSSL is a compact notation for a set of cryptographic algorithms (public key, symmetric key, and digest algorithms) in order of preference.

The cipherstring notation is discussed at https://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT Briefly, a cipherstring is a series of elements each designating either a specific ciphersuite or a set of ciphersuites. The "+" operator designates a logical and operation, so "element1+element1" represents that set of ciphersuites containing the algorithms in both element1 and element2. The "!" operator permanently all the algorithms in the following element.

TLS 1.0 and 1.1[edit]

All TLS 1.0/1.1 authenticated PFS (Perfect Forward Secrecy) ciphersuites use SHA1 alone or MD5+SHA1. That leaves only unauthenticated ones (which are vulnerable to MiTM so we discount them) or those using static keys. Theoretically that would permit RSA, DH or ECDH keys in certificates but in practice everyone uses RSA.

The corresponding cipherstring is:

openssl ciphers -v 'kRSA+FIPS:!TLSv1.2'
AES256-SHA              SSLv3 Kx=RSA      Au=RSA  Enc=AES(256)  Mac=SHA1
DES-CBC3-SHA            SSLv3 Kx=RSA      Au=RSA  Enc=3DES(168) Mac=SHA1
AES128-SHA              SSLv3 Kx=RSA      Au=RSA  Enc=AES(128)  Mac=SHA1

That cipherstring specifies three possible ciphersuites allowable in FIPS mode for TLS 1.0 and 1.1. The RSA key in the certificate has to be of suitable size (2048 bits minimum) as do all other keys in the chain and none of the CAs can sign using SHA1. Also those kRSA ciphersuites are allowed for server certificates only; client authentication is never allowed with the new rules for TLS 1.0 and 1.1.

In a real application when FIPS mode is enabled then only FIPS ciphersuites are allowed no matter what you use in the string. So in FIPS mode "kRSA:!TLSv1.2" will be functionally equivalent to "kRSA+FIPS!TLSv1.2".

Note the "TLSv1.2" string was only added to OpenSSL recently, as of OpenSSL 1.0.1f. It designates the ciphers for TLSv1.2 subject to the FIPS 140-2 and FIPS 186-4 restrictions.

Note the cipherstring 'FIPS:!TLSv1.2' would also allow fixed DH and fixed ECDH certificates but those are not encountered in the wild. The key exchange component "kRSA" specifies just those algorithms that support RSA key exchange.

TLS 1.2[edit]

TLS 1.2 provides more options as the signature can use an algorithm other than SHA1. "kRSA+FIPS" specifies those ciphersuites that use RSA key exchange, including TLS v1.2, *and* are allowed in FIPS mode, and including anonymous ones which may be undesirable:

openssl ciphers -v 'kRSA+FIPS'
AES256-GCM-SHA384       TLSv1.2 Kx=RSA      Au=RSA  Enc=AESGCM(256) Mac=AEAD
AES256-SHA256           TLSv1.2 Kx=RSA      Au=RSA  Enc=AES(256)  Mac=SHA256
AES256-SHA              SSLv3 Kx=RSA        Au=RSA  Enc=AES(256)  Mac=SHA1
DES-CBC3-SHA            SSLv3 Kx=RSA        Au=RSA  Enc=3DES(168) Mac=SHA1
AES128-GCM-SHA256       TLSv1.2 Kx=RSA      Au=RSA  Enc=AESGCM(128) Mac=AEAD
AES128-SHA256           TLSv1.2 Kx=RSA      Au=RSA  Enc=AES(128)  Mac=SHA256
AES128-SHA              SSLv3 Kx=RSA        Au=RSA  Enc=AES(128)  Mac=SHA1

The ephemeral key for the now permitted PFS keys must be at least 2048 bits (DH) or 256 bits (ECDH) in size. Anything supporting ECDH will probably set P-256 as a default so that should be OK (Apache does).

There's a snag though. The ciphersuite ECDH-RSA-AES128-SHA can (outside FIPS) be used for TLS 1.0 and later whereas in FIPS mode it can only be used for TLS v1.2. A TLS client can't advertise ciphersuites in that way (i.e. you can use this for TLS1.2 only and nothing earlier) so you're left with the situation where a FIPS compliant client might say it wants ECDH-RSA-AES128-SHA and TLS 1.2 and the server only supports TLS 1.0 so it will choke when it tries to use the prohibited ciphersuite+version combination. Servers are fine because they can theoretically select based on version (except in practice OpenSSL doesn't support that).

If that wasn't enough there's another complication. For TLS v1.2 you have to restrict the supported signature algorithms to exclude SHA1, allowing only SHA256 and above. There is no way to do that in OpenSSL 1.0.1 clients. Similarly the supported EC curves have to be restricted to exclude some which are of insufficient field size.

In summary: it's a bloody mess.

The list of allowable ciphers for all versions of TLS, 1.0/1/1/1.2 is 'TLSv1.2:kRSA' which includes those with no encryption or no authentication which are generally undesirable and should be excluded. In full with explicit "+FIPS" qualification that becomes:

'TLSv1.2+FIPS:kRSA+FIPS:!eNULL:!aNULL'
ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH        Au=RSA  Enc=AESGCM(256) Mac=AEAD
ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH      Au=ECDSA Enc=AESGCM(256) Mac=AEAD
ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH            Au=RSA  Enc=AES(256)  Mac=SHA384
ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH          Au=ECDSA Enc=AES(256)  Mac=SHA384
DHE-DSS-AES256-GCM-SHA384 TLSv1.2 Kx=DH            Au=DSS  Enc=AESGCM(256) Mac=AEAD
DHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=DH            Au=RSA  Enc=AESGCM(256) Mac=AEAD
DHE-RSA-AES256-SHA256   TLSv1.2 Kx=DH              Au=RSA  Enc=AES(256)  Mac=SHA256
DHE-DSS-AES256-SHA256   TLSv1.2 Kx=DH              Au=DSS  Enc=AES(256)  Mac=SHA256
ECDH-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH/RSA     Au=ECDH Enc=AESGCM(256) Mac=AEAD
ECDH-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH/ECDSA Au=ECDH Enc=AESGCM(256) Mac=AEAD
ECDH-RSA-AES256-SHA384  TLSv1.2 Kx=ECDH/RSA        Au=ECDH Enc=AES(256)  Mac=SHA384
ECDH-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH/ECDSA     Au=ECDH Enc=AES(256)  Mac=SHA384
AES256-GCM-SHA384       TLSv1.2 Kx=RSA             Au=RSA  Enc=AESGCM(256) Mac=AEAD
AES256-SHA256           TLSv1.2 Kx=RSA             Au=RSA  Enc=AES(256)  Mac=SHA256
ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH        Au=RSA  Enc=AESGCM(128) Mac=AEAD
ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH      Au=ECDSA Enc=AESGCM(128) Mac=AEAD
ECDHE-RSA-AES128-SHA256 TLSv1.2 Kx=ECDH            Au=RSA  Enc=AES(128)  Mac=SHA256
ECDHE-ECDSA-AES128-SHA256 TLSv1.2 Kx=ECDH          Au=ECDSA Enc=AES(128)  Mac=SHA256
DHE-DSS-AES128-GCM-SHA256 TLSv1.2 Kx=DH            Au=DSS  Enc=AESGCM(128) Mac=AEAD
DHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=DH            Au=RSA  Enc=AESGCM(128) Mac=AEAD
DHE-RSA-AES128-SHA256   TLSv1.2 Kx=DH              Au=RSA  Enc=AES(128)  Mac=SHA256
DHE-DSS-AES128-SHA256   TLSv1.2 Kx=DH              Au=DSS  Enc=AES(128)  Mac=SHA256
ECDH-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH/RSA     Au=ECDH Enc=AESGCM(128) Mac=AEAD
ECDH-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH/ECDSA Au=ECDH Enc=AESGCM(128) Mac=AEAD
ECDH-RSA-AES128-SHA256  TLSv1.2 Kx=ECDH/RSA        Au=ECDH Enc=AES(128)  Mac=SHA256
ECDH-ECDSA-AES128-SHA256 TLSv1.2 Kx=ECDH/ECDSA     Au=ECDH Enc=AES(128)  Mac=SHA256
AES128-GCM-SHA256       TLSv1.2 Kx=RSA             Au=RSA  Enc=AESGCM(128) Mac=AEAD
AES128-SHA256           TLSv1.2 Kx=RSA             Au=RSA  Enc=AES(128)  Mac=SHA256
AES256-SHA              SSLv3 Kx=RSA               Au=RSA  Enc=AES(256)  Mac=SHA1
DES-CBC3-SHA            SSLv3 Kx=RSA               Au=RSA  Enc=3DES(168) Mac=SHA1
AES128-SHA              SSLv3 Kx=RSA               Au=RSA  Enc=AES(128)  Mac=SHA1

What does this ciphersuite specification mean in practice?

If the peer supports TLS v1.2 it will use a TLS v1.2 ciphersuite which is FIPS 186-4 compliant (with the curve and signature restrictions I mentioned) or non-PFS RSA otherwise.

If the peer only supports TLS 1.1 or 1.0 it will fall back to the non-PFS RSA ciphersuites which again will be FIPS 186-4 compliant subject to the silly key and certificate signing restrictions.

The ciphersuite (for 1.0.1f+) of 'TLSv1.2+FIPS:kRSA+FIPS:!eNULL:!aNULL' will satisfy FIPS 186-4 for any version of TLS 1.0/1.1/1.2 with caveats as noted.

To specify a list of allowable ciphers for TLS 1.0/1.1 only append !TLSv1.2 which permanently deletes those which are only usable for TLS v1.2, giving 'kRSA+FIPS:!TLSv1.2'.

Cipherstrings[edit]

Commentary on what the cipherstrings components mean and their relevance:

"TLSv1.2": list of ciphersuites only allowed for TLS 1.2. This means if TLS 1.2 is negotiated they can be used and if not they won't. They also happen to be permitted by FIPS 186-4 because TLS 1.2 can use signature algorithms stronger that SHA1. That means that it is "safe" to include this in a cipher string because (a) they are compliant with FIPS 186-4 in for TLS 1.2 and (b) they can never be used for TLS 1.1 or 1.0.

"kRSA": list of ciphersuites which support RSA key exchange. Because TLS 1.1 and 1.0 can only use SHA1+MD5 in signatures these are the only ones allowed because they don't use signatures.

"FIPS": list of ciphersuites allowed in FIPS mode excluding those offering no encryption. This is for informational purposes only because if you *are* in FIPS mode you can only use those ciphersuites anyway (but including the no encryption ones).

The lists above all include ciphersuites which you wouldn't normally use: no encryption or no authentication. So those need to be disabled. This is done by appending '!eNULL:!aNULL': this means "disable any ciphersuites present which include no encryption or authentication".

So combining these we get the following cipher string in FIPS mode:

	'TLSv1.2:kRSA:!eNULL:!aNULL'

which with the functionally redundant "+FIPS" qualifiers is equivant to:

	'TLSv1.2+FIPS:kRSA+FIPS:!eNULL:!aNULL'

Without the "+FIPS" qualifiers and outside FIPS mode you'll will see weak export grade ciphersuites which would be disabled in FIPS mode. Those can be seen with:

	openssl ciphers -v 'TLSv1.2:kRSA:!eNULL:!aNULL'

To see the actual set of ciphersuites in FIPS mode, without the explicit "+FIPS" qualifiers, do:

	OPENSSL_FIPS=1 openssl ciphers -v 'TLSv1.2:kRSA:!eNULL:!aNULL'

So in summary "in FIPS mode use the cipherstring 'TLSv1.2:kRSA:!eNULL:!aNULL'"

Note this important disclaimer though: This cipherstring *only* restricts the ciphersuites to those not explicitly excluded by FIPS 186-4. There are other conditions which must be enforced such as key size, permitted curves and permitted signature algorithms. Just because a ciphersuite has been negotiated in this range does not guaranteed compliance.

The "FIPS capable" OpenSSL does not currently provide a means to automatically enforce the new FIPS 186-4 restrictions.

A quick overview of TLS[edit]

The primary purpose of the handshake is to enable both peers to securely obtain a shared secret value called the pre-master secret. They then use that to generate session keys (encryption and MAC) which are used for the exchange of actual application data. The handshake is the only place public key algorithms are used.

In the case of PFS ciphersuites both ends generate a temporary key (ECDH or DH) and exchange the public bits with each other. They use the algorithm to generate the shared DH/ECDH secret value which is used later on. The new FIPS restrictions interfere with this because those keys have to be large enough. For ECDH an extension can be used to ensure this. For DH you just have to hope the server has a big enough key and abort if not.

For anonymous algorithms that's all you get. They are vulnerable to man in the middle (MitM) attacks and so are rarely used.

In the real world algorithms include authentication. In those the server digitally signs its ECDH or DH key using the key in its certificate. This is to ensure the temporary ECDH or DH key can't be forged. It is that digital signature that is important here and the one which the new FIPS restrictions disrupt.

How that temporary key is signed depends on the cipher suite and the key in the server's certificate. The whole process is called server authentication.

In the case of TLS 1.0 and 1.1 that signature uses a MD5+SHA1 hybrid for RSA keys and just SHA1 for DSA and ECDSA. That's why PFS is prohibited by the new FIPS rules: there is no option but to use SHA1.

In the case of TLS 1.2 any valid combination can be used and the MD5+SHA1 hybrid is no longer present for RSA. RSA just uses the same signature format that certificates use (PKCS#1).

For TLS 1.2 the client sends the set of signature algorithms it supports in preference order in the supported signature algorithms extensions. The server then selects one and uses that for that signature. For new FIPS it would just use SHA256 as a minimum or abort the connection if the client only supported SHA1 (unlikely).

Client authentication in TLS is a secondary concern. In this case the client signs some data related to the handshake and sends the result back. The server then checks that signature.

As with server authentication TLS 1.1/1.0 has to use either MD5+SHA1 for RSA or just SHA1 for other algorithms. So client authentication violates the new FIPS restrictions and cannot be used for TLs 1.0/1.1.

TLS 1.2 removes the restriction to SHA1. In this case the server sends back the algorithms it supports and the client selects one. Again SHA256 or better s needed to comply with new FIPS restrictions.

Next consider the non-PFS case. We consider RSA key exchange only as is the only practical option. This is completely different from PFS. In this case the client generates the pre master secret and encrypts it using the servers key. The server decrypts it and then uses that to complete the handshake. No additional signing is used here so no place for SHA1 to be used. The server is authenticated because if it didn't have the right key it couldn't decrypt the pre-master secret. It's a bit unusual in that authentication (which is normally associated with signatures) is performed using an RSA decryption operation.

Some further discussion in case that wasn't confusing enough:

Some people say that it is implied that TLS 1.1 and 1.0 must use SHA1 in digital signatures in all certificates. If so then TLS 1.1 and 1.0 can never be compliant with new FIPS.

Assuming that is not true, what does it mean in practice? A a public webserver would require a certificate signed by CAs that use SHA256 minimum and large enough keys. Not a trivial task in itself.

Aside from that, problems will be encountered if your server needs to use anything outside of the new FIPS restrictions (e.g. to talk to other clients). Some older browsers (e.g. IE on XP is one which is still very common) don't support SHA2 at all. So they'll fail when they talk to that server because the can't verify the signatures.

TLS 1.2 is a bit better, at least in theory. The supported signatures should apply to the whole certificate chain. So a client advertising only SHA1+RSA receive a chain supporting SHA1+RSA only (if the server has one) and a client supporting SHA256+RSA will receive a "new FIPS" friendly chain.

However, in practice that requirement is generally ignored and implementations serve up whatever chain is configured regardless of signature algorithms sent by the client because many implementers consider that a slly restriction. For interoperability OpenSSL is similarly lax if a "strict" option isn't set. In fact configuring multiple chains like that can't be directly done in OpenSSL without application support which nothing other than s_server can currently handle.

Digests in TLS[edit]

There are different purposes that digest algorithms are put to.

In TLS 1.2 something called the supported signature algorithms extension determines the supported digests as a public key + algorithm pair. It's that usage that FIPS 186-4 (and SP800-57) has an impact on. So you can't use RSA+SHA1 any more. For digital signatures the strength of SHA1 is at most 80 bits: it can be less with a weak key.

That digital signature is used to maintain the integrity of the handshake messages and certificate chains in PFS ciphersuites: basically server and client authentication.

For TLS 1.2 you can specify any digest to be used to maintain handshake integrity for digital signatures: for TLS 1.1 and below you could only use SHA1+MD5. It's that reason why PFS ciphersuites are banned in TLS 1.1 and below.

Digests use HMAC. For HMAC use the key strength is the digest length so SHA1 is 160 bits.

Before TLS 1.2 all cipher suites used SHA1 HMAC (or in legacy cases MD5) for the HMAC.

TLS 1.2 introduced some ciphersuites which used SHA256 and SHA384 for the HMAC and the AEAD ones like AES-GCM which have a mac as part of the algorithm itself.

Note that TLS 1.2 also permits all the ciphersuites for TLS 1.1, 1.0 too. For details see Table 2 and 3 in SP800-57.

Those tables make a lot more sense when you realise for digital signatures it's half the digest size. So SHA1 is 20 bytes which is 160 bits and so 80 bits of strength so it only appears in the "80 bits" box for digital signatures. Whereas for other uses it is the full digest size so SHA1 appears in the 80, 112 and 128 bit boxes.

Unfortunately the FIPS terminology unnecessarily obfuscated the issue. It would have been easier to just say in SP800-57 that SHA1 HMAC is 160 bits of equivalent security instead of placing it in the :Security Strenght 128" row of Table 3.

TLS 1.2 can use SHA1 in two different places. One is the signature algorithms on certificates: i.e. the algorithm the CA signs with. The second place is temporary key signature (server authentication) as described below.

Digital Signatures in TLS[edit]

There are three places digital signatures are used in TLS.

1. The signatures on certificates.

The certificates' signatures are set by the CA so to comply with new FIPS whatever else you do you need a certificate chain that uses SHA256 at least.

2. Server Key Exchange.

The Server Key Exchange message contains a signature in any authenticated PFS ciphersuite. The algorithm used depends on the version of TLS.

For TLS 1.1 and 1.0 the algorithm is either a MD5+SHA1 hybrid (RSA) or SHA1 (DSA, ECDSA). Both of these are prohibited by new FIPS so TLS 1.1 and 1.0 authenticated PFS ciphersuites are not allowed.

For TLS 1.2 any appropriate algorithm can be used to sign Server Key Exchange messages. So PFS authenticated ciphersuites *are* allowed under new FIPS as long as SHA1 is not used to sign Server Key Exchange. MD5 is of course a double no-no.

3. Certificate Verify.

The Certificate Verify message is used whenever client authentication is enabled for any applicable ciphersuite (not just PFS). The same digest algorithms are used as Server Key Exchange.

Therefore new FIPS and TLS 1.1 and 1.0 prohibits client authentication outright in *any* ciphersuite.

TLS 1.2 is more flexible and can use any appropriate algorithm so client authentication is permitted as long as SHA1 and MD5 are not used.

What about versions of OpenSSL prior to 1.0.1f?[edit]

The "TLSv1.2" ciphersuite designation was added at 1.0.1f. For earlier versions of OpenSSL the current equivalent of the cipherstring

	'TLSv1.2:kRSA:!eNULL:!aNULL'

can be "brute forced" as the unwieldy

	'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:ADH-AES256-GCM-SHA384:ADH-AES256-SHA256:ECDH-RSA-AES256-GCM-SHA384:ECDH-ECDSA-AES256-GCM-SHA384:ECDH-RSA-AES256-SHA384:ECDH-ECDSA-AES256-SHA384:AES256-GCM-SHA384:AES256-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:ADH-AES128-GCM-SHA256:ADH-AES128-SHA256:ECDH-RSA-AES128-GCM-SHA256:ECDH-ECDSA-AES128-GCM-SHA256:ECDH-RSA-AES128-SHA256:ECDH-ECDSA-AES128-SHA256:AES128-GCM-SHA256:AES128-SHA256:NULL-SHA256:kRSA:!eNULL:!aNULL'

However, as new ciphersuites get added to the 'TLSv1.2' ciphersuite that brute force equivalent might end up not being equivalent any more.

Since TLSv1.2 only ciphers use SHA256, SHA384 and AES in GCM mode so one string is:

	'AESGCM:SHA384:SHA256'

There are other ways to get the same effect. One is to disable any ciphers which use SHA1. So "FIPS:-SHA" is currently equivalent to "FIPS+TLSv1.2". The use of the "-SHA" is necessary here because it only *temporarily* disables SHA1 MACs. That means you can do: "FIPS:-SHA:FIPS+kRSA" to add back the RSA key exchange ciphersuites that use SHA1. Contrast that with using "!SHA" instead which permanently removes SHA1 from the cipherstring.