diff --git a/src/crypto/internal/boring/Dockerfile b/src/crypto/internal/boring/Dockerfile index 58eb028e8aa286..327e4f65d7d7ea 100644 --- a/src/crypto/internal/boring/Dockerfile +++ b/src/crypto/internal/boring/Dockerfile @@ -13,7 +13,7 @@ WORKDIR /boring ENV LANG=C ENV LANGUAGE= -# Following NIST submission draft dated July 3, 2021. +# Following NIST submission dated May 6, 2022. # This corresponds to boringssl.googlesource.com/boringssl tag fips-20210429. ENV ClangV=12 RUN apt-get update && \ diff --git a/src/crypto/internal/boring/LICENSE b/src/crypto/internal/boring/LICENSE index 38990bdb771494..bcb913e04683f5 100644 --- a/src/crypto/internal/boring/LICENSE +++ b/src/crypto/internal/boring/LICENSE @@ -6,7 +6,7 @@ When building with GOEXPERIMENT=boringcrypto, the following applies. The goboringcrypto_linux_amd64.syso object file is built from BoringSSL source code by build/build.sh and is covered by the BoringSSL license reproduced below and also at -https://boringssl.googlesource.com/boringssl/+/fips-20190808/LICENSE. +https://boringssl.googlesource.com/boringssl/+/fips-20210429/LICENSE. BoringSSL is a fork of OpenSSL. As such, large parts of it fall under OpenSSL licensing. Files that are completely new have a Google copyright and an ISC diff --git a/src/crypto/internal/boring/aes.go b/src/crypto/internal/boring/aes.go index 8819f576f4f4c5..9b163f9db1fbf5 100644 --- a/src/crypto/internal/boring/aes.go +++ b/src/crypto/internal/boring/aes.go @@ -228,26 +228,44 @@ func (c *aesCipher) NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) { if tagSize != gcmTagSize { return cipher.NewGCMWithTagSize(&noGCM{c}, tagSize) } - return c.newGCM(false) + return c.newGCM(0) } +// Copied from crypto/tls/common.go, but values don't actually matter here. +const ( + VersionTLS12 = 0x0303 + VersionTLS13 = 0x0304 +) + func NewGCMTLS(c cipher.Block) (cipher.AEAD, error) { - return c.(*aesCipher).newGCM(true) + return c.(*aesCipher).newGCM(VersionTLS12) +} + +func NewGCMTLS13(c cipher.Block) (cipher.AEAD, error) { + return c.(*aesCipher).newGCM(VersionTLS13) } -func (c *aesCipher) newGCM(tls bool) (cipher.AEAD, error) { +func (c *aesCipher) newGCM(tlsVersion uint16) (cipher.AEAD, error) { var aead *C.GO_EVP_AEAD switch len(c.key) * 8 { case 128: - if tls { + switch tlsVersion { + case VersionTLS12: aead = C._goboringcrypto_EVP_aead_aes_128_gcm_tls12() - } else { + case VersionTLS13: + aead = C._goboringcrypto_EVP_aead_aes_128_gcm_tls13() + default: + // Not TLS. aead = C._goboringcrypto_EVP_aead_aes_128_gcm() } case 256: - if tls { + switch tlsVersion { + case VersionTLS12: aead = C._goboringcrypto_EVP_aead_aes_256_gcm_tls12() - } else { + case VersionTLS13: + aead = C._goboringcrypto_EVP_aead_aes_256_gcm_tls13() + default: + // Not TLS. aead = C._goboringcrypto_EVP_aead_aes_256_gcm() } default: diff --git a/src/crypto/internal/boring/goboringcrypto.h b/src/crypto/internal/boring/goboringcrypto.h index 2b11049728c5bb..3663a1b1c358e2 100644 --- a/src/crypto/internal/boring/goboringcrypto.h +++ b/src/crypto/internal/boring/goboringcrypto.h @@ -125,7 +125,9 @@ void _goboringcrypto_EVP_AEAD_CTX_cleanup(GO_EVP_AEAD_CTX*); int _goboringcrypto_EVP_AEAD_CTX_seal(const GO_EVP_AEAD_CTX*, uint8_t*, size_t*, size_t, const uint8_t*, size_t, const uint8_t*, size_t, const uint8_t*, size_t); int _goboringcrypto_EVP_AEAD_CTX_open(const GO_EVP_AEAD_CTX*, uint8_t*, size_t*, size_t, const uint8_t*, size_t, const uint8_t*, size_t, const uint8_t*, size_t); const GO_EVP_AEAD* _goboringcrypto_EVP_aead_aes_128_gcm_tls12(void); +const GO_EVP_AEAD* _goboringcrypto_EVP_aead_aes_128_gcm_tls13(void); const GO_EVP_AEAD* _goboringcrypto_EVP_aead_aes_256_gcm_tls12(void); +const GO_EVP_AEAD* _goboringcrypto_EVP_aead_aes_256_gcm_tls13(void); enum go_evp_aead_direction_t { go_evp_aead_open = 0, go_evp_aead_seal = 1 diff --git a/src/crypto/internal/boring/notboring.go b/src/crypto/internal/boring/notboring.go index 361dec9672ff55..02bc468a0de8e7 100644 --- a/src/crypto/internal/boring/notboring.go +++ b/src/crypto/internal/boring/notboring.go @@ -50,6 +50,7 @@ func NewHMAC(h func() hash.Hash, key []byte) hash.Hash { panic("boringcrypto: no func NewAESCipher(key []byte) (cipher.Block, error) { panic("boringcrypto: not available") } func NewGCMTLS(cipher.Block) (cipher.AEAD, error) { panic("boringcrypto: not available") } +func NewGCMTLS13(cipher.Block) (cipher.AEAD, error) { panic("boringcrypto: not available") } type PublicKeyECDSA struct{ _ int } type PrivateKeyECDSA struct{ _ int } diff --git a/src/crypto/tls/boring.go b/src/crypto/tls/boring.go index 1827f764589b58..d8a025a8cc83d0 100644 --- a/src/crypto/tls/boring.go +++ b/src/crypto/tls/boring.go @@ -17,18 +17,19 @@ func needFIPS() bool { // fipsMinVersion replaces c.minVersion in FIPS-only mode. func fipsMinVersion(c *Config) uint16 { - // FIPS requires TLS 1.2. + // FIPS required minimum of TLS 1.2 (see NIST SP 800-52). return VersionTLS12 } // fipsMaxVersion replaces c.maxVersion in FIPS-only mode. func fipsMaxVersion(c *Config) uint16 { - // FIPS requires TLS 1.2. - return VersionTLS12 + // FIPS required maximum of TLS 1.3 (see NIST SP 800-52). + return VersionTLS13 } // default defaultFIPSCurvePreferences is the FIPS-allowed curves, // in preference order (most preferable first). +// See NIST SP 800-186. var defaultFIPSCurvePreferences = []CurveID{CurveP256, CurveP384, CurveP521} // fipsCurvePreferences replaces c.curvePreferences in FIPS-only mode. @@ -49,7 +50,10 @@ func fipsCurvePreferences(c *Config) []CurveID { } // defaultCipherSuitesFIPS are the FIPS-allowed cipher suites. +// See NIST SP 800-52. var defaultCipherSuitesFIPS = []uint16{ + TLS_AES_128_GCM_SHA256, + TLS_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, @@ -77,6 +81,7 @@ func fipsCipherSuites(c *Config) []uint16 { // fipsSupportedSignatureAlgorithms currently are a subset of // defaultSupportedSignatureAlgorithms without Ed25519 and SHA-1. +// See FIPS 186-5. var fipsSupportedSignatureAlgorithms = []SignatureScheme{ PSSWithSHA256, PSSWithSHA384, diff --git a/src/crypto/tls/boring_test.go b/src/crypto/tls/boring_test.go index ba68f355eb037c..0b49c9cc2aae98 100644 --- a/src/crypto/tls/boring_test.go +++ b/src/crypto/tls/boring_test.go @@ -52,16 +52,22 @@ func TestBoringServerProtocolVersion(t *testing.T) { test("VersionTLS10", VersionTLS10, "client offered only unsupported versions") test("VersionTLS11", VersionTLS11, "client offered only unsupported versions") test("VersionTLS12", VersionTLS12, "") - test("VersionTLS13", VersionTLS13, "client offered only unsupported versions") + test("VersionTLS13", VersionTLS13, "") } func isBoringVersion(v uint16) bool { - return v == VersionTLS12 + switch v { + case VersionTLS12, VersionTLS13: + return true + } + return false } func isBoringCipherSuite(id uint16) bool { switch id { - case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + case TLS_AES_128_GCM_SHA256, + TLS_AES_256_GCM_SHA384, + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, diff --git a/src/crypto/tls/cipher_suites.go b/src/crypto/tls/cipher_suites.go index 589e8b6fafbba3..fd538da0f78d60 100644 --- a/src/crypto/tls/cipher_suites.go +++ b/src/crypto/tls/cipher_suites.go @@ -532,7 +532,13 @@ func aeadAESGCMTLS13(key, nonceMask []byte) aead { if err != nil { panic(err) } - aead, err := cipher.NewGCM(aes) + var aead cipher.AEAD + if boring.Enabled { + aead, err = boring.NewGCMTLS13(aes) + } else { + boring.Unreachable() + aead, err = cipher.NewGCM(aes) + } if err != nil { panic(err) } diff --git a/src/crypto/x509/boring.go b/src/crypto/x509/boring.go index 095b58c31590d4..53e2845549e4af 100644 --- a/src/crypto/x509/boring.go +++ b/src/crypto/x509/boring.go @@ -23,6 +23,7 @@ func boringAllowCert(c *Certificate) bool { // The key must be RSA 2048, RSA 3072, RSA 4096, // or ECDSA P-256, P-384, P-521. + // See FIPS 186-5 and NIST SP 800-186. switch k := c.PublicKey.(type) { default: return false