Skip to content

Commit d363534

Browse files
committed
crypto/tls: align FIPS-only mode with BoringSSL policy
This enables TLS 1.3, disables P-521, and disables non-ECDHE suites. Reapplies CL 549975. Updates #64717 Updates #62372 Change-Id: I6c608704638d59a063a657fbd4eb1126027112dd Reviewed-on: https://go-review.googlesource.com/c/go/+/603376 Reviewed-by: Roland Shoemaker <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: David Chase <[email protected]>
1 parent 83d9afe commit d363534

9 files changed

+93
-44
lines changed

src/crypto/internal/boring/aes.go

+22-7
Original file line numberDiff line numberDiff line change
@@ -228,26 +228,41 @@ func (c *aesCipher) NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) {
228228
if tagSize != gcmTagSize {
229229
return cipher.NewGCMWithTagSize(&noGCM{c}, tagSize)
230230
}
231-
return c.newGCM(false)
231+
return c.newGCM(0)
232232
}
233233

234+
const (
235+
VersionTLS12 = 0x0303
236+
VersionTLS13 = 0x0304
237+
)
238+
234239
func NewGCMTLS(c cipher.Block) (cipher.AEAD, error) {
235-
return c.(*aesCipher).newGCM(true)
240+
return c.(*aesCipher).newGCM(VersionTLS12)
241+
}
242+
243+
func NewGCMTLS13(c cipher.Block) (cipher.AEAD, error) {
244+
return c.(*aesCipher).newGCM(VersionTLS13)
236245
}
237246

238-
func (c *aesCipher) newGCM(tls bool) (cipher.AEAD, error) {
247+
func (c *aesCipher) newGCM(tlsVersion uint16) (cipher.AEAD, error) {
239248
var aead *C.GO_EVP_AEAD
240249
switch len(c.key) * 8 {
241250
case 128:
242-
if tls {
251+
switch tlsVersion {
252+
case VersionTLS12:
243253
aead = C._goboringcrypto_EVP_aead_aes_128_gcm_tls12()
244-
} else {
254+
case VersionTLS13:
255+
aead = C._goboringcrypto_EVP_aead_aes_128_gcm_tls13()
256+
default:
245257
aead = C._goboringcrypto_EVP_aead_aes_128_gcm()
246258
}
247259
case 256:
248-
if tls {
260+
switch tlsVersion {
261+
case VersionTLS12:
249262
aead = C._goboringcrypto_EVP_aead_aes_256_gcm_tls12()
250-
} else {
263+
case VersionTLS13:
264+
aead = C._goboringcrypto_EVP_aead_aes_256_gcm_tls13()
265+
default:
251266
aead = C._goboringcrypto_EVP_aead_aes_256_gcm()
252267
}
253268
default:

src/crypto/internal/boring/notboring.go

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ func NewHMAC(h func() hash.Hash, key []byte) hash.Hash { panic("boringcrypto: no
5050

5151
func NewAESCipher(key []byte) (cipher.Block, error) { panic("boringcrypto: not available") }
5252
func NewGCMTLS(cipher.Block) (cipher.AEAD, error) { panic("boringcrypto: not available") }
53+
func NewGCMTLS13(cipher.Block) (cipher.AEAD, error) { panic("boringcrypto: not available") }
5354

5455
type PublicKeyECDSA struct{ _ int }
5556
type PrivateKeyECDSA struct{ _ int }

src/crypto/tls/boring_test.go

+48-22
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,31 @@ import (
2525
"time"
2626
)
2727

28+
func allCipherSuitesIncludingTLS13() []uint16 {
29+
s := allCipherSuites()
30+
for _, suite := range cipherSuitesTLS13 {
31+
s = append(s, suite.id)
32+
}
33+
return s
34+
}
35+
36+
func isTLS13CipherSuite(id uint16) bool {
37+
for _, suite := range cipherSuitesTLS13 {
38+
if id == suite.id {
39+
return true
40+
}
41+
}
42+
return false
43+
}
44+
45+
func generateKeyShare(group CurveID) keyShare {
46+
key, err := generateECDHEKey(rand.Reader, group)
47+
if err != nil {
48+
panic(err)
49+
}
50+
return keyShare{group: group, data: key.PublicKey().Bytes()}
51+
}
52+
2853
func TestBoringServerProtocolVersion(t *testing.T) {
2954
test := func(t *testing.T, name string, v uint16, msg string) {
3055
t.Run(name, func(t *testing.T) {
@@ -60,30 +85,30 @@ func TestBoringServerProtocolVersion(t *testing.T) {
6085
test(t, "VersionTLS10", VersionTLS10, "supported versions")
6186
test(t, "VersionTLS11", VersionTLS11, "supported versions")
6287
test(t, "VersionTLS12", VersionTLS12, "")
63-
test(t, "VersionTLS13", VersionTLS13, "supported versions")
88+
test(t, "VersionTLS13", VersionTLS13, "")
6489
})
6590
}
6691

6792
func isBoringVersion(v uint16) bool {
68-
return v == VersionTLS12
93+
return v == VersionTLS12 || v == VersionTLS13
6994
}
7095

7196
func isBoringCipherSuite(id uint16) bool {
7297
switch id {
73-
case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
98+
case TLS_AES_128_GCM_SHA256,
99+
TLS_AES_256_GCM_SHA384,
100+
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
74101
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
75102
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
76-
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
77-
TLS_RSA_WITH_AES_128_GCM_SHA256,
78-
TLS_RSA_WITH_AES_256_GCM_SHA384:
103+
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
79104
return true
80105
}
81106
return false
82107
}
83108

84109
func isBoringCurve(id CurveID) bool {
85110
switch id {
86-
case CurveP256, CurveP384, CurveP521:
111+
case CurveP256, CurveP384:
87112
return true
88113
}
89114
return false
@@ -95,7 +120,7 @@ func isECDSA(id uint16) bool {
95120
return suite.flags&suiteECSign == suiteECSign
96121
}
97122
}
98-
panic(fmt.Sprintf("unknown cipher suite %#x", id))
123+
return false // TLS 1.3 cipher suites are not tied to the signature algorithm.
99124
}
100125

101126
func isBoringSignatureScheme(alg SignatureScheme) bool {
@@ -107,7 +132,6 @@ func isBoringSignatureScheme(alg SignatureScheme) bool {
107132
PKCS1WithSHA384,
108133
ECDSAWithP384AndSHA384,
109134
PKCS1WithSHA512,
110-
ECDSAWithP521AndSHA512,
111135
PSSWithSHA256,
112136
PSSWithSHA384,
113137
PSSWithSHA512:
@@ -118,10 +142,9 @@ func isBoringSignatureScheme(alg SignatureScheme) bool {
118142

119143
func TestBoringServerCipherSuites(t *testing.T) {
120144
serverConfig := testConfig.Clone()
121-
serverConfig.CipherSuites = allCipherSuites()
122145
serverConfig.Certificates = make([]Certificate, 1)
123146

124-
for _, id := range allCipherSuites() {
147+
for _, id := range allCipherSuitesIncludingTLS13() {
125148
if isECDSA(id) {
126149
serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate}
127150
serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey
@@ -130,14 +153,20 @@ func TestBoringServerCipherSuites(t *testing.T) {
130153
serverConfig.Certificates[0].PrivateKey = testRSAPrivateKey
131154
}
132155
serverConfig.BuildNameToCertificate()
133-
t.Run(fmt.Sprintf("suite=%#x", id), func(t *testing.T) {
156+
t.Run(fmt.Sprintf("suite=%s", CipherSuiteName(id)), func(t *testing.T) {
134157
clientHello := &clientHelloMsg{
135-
vers: VersionTLS12,
136-
random: make([]byte, 32),
137-
cipherSuites: []uint16{id},
138-
compressionMethods: []uint8{compressionNone},
139-
supportedCurves: defaultCurvePreferences(),
140-
supportedPoints: []uint8{pointFormatUncompressed},
158+
vers: VersionTLS12,
159+
random: make([]byte, 32),
160+
cipherSuites: []uint16{id},
161+
compressionMethods: []uint8{compressionNone},
162+
supportedCurves: defaultCurvePreferences(),
163+
keyShares: []keyShare{generateKeyShare(CurveP256)},
164+
supportedPoints: []uint8{pointFormatUncompressed},
165+
supportedVersions: []uint16{VersionTLS12},
166+
supportedSignatureAlgorithms: defaultSupportedSignatureAlgorithmsFIPS,
167+
}
168+
if isTLS13CipherSuite(id) {
169+
clientHello.supportedVersions = []uint16{VersionTLS13}
141170
}
142171

143172
testClientHello(t, serverConfig, clientHello)
@@ -156,9 +185,6 @@ func TestBoringServerCipherSuites(t *testing.T) {
156185

157186
func TestBoringServerCurves(t *testing.T) {
158187
serverConfig := testConfig.Clone()
159-
serverConfig.Certificates = make([]Certificate, 1)
160-
serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate}
161-
serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey
162188
serverConfig.BuildNameToCertificate()
163189

164190
for _, curveid := range defaultCurvePreferences() {
@@ -288,7 +314,7 @@ func TestBoringClientHello(t *testing.T) {
288314
}
289315

290316
if !isBoringVersion(hello.vers) {
291-
t.Errorf("client vers=%#x, want %#x (TLS 1.2)", hello.vers, VersionTLS12)
317+
t.Errorf("client vers=%#x", hello.vers)
292318
}
293319
for _, v := range hello.supportedVersions {
294320
if !isBoringVersion(v) {

src/crypto/tls/cipher_suites.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,13 @@ func aeadAESGCMTLS13(key, nonceMask []byte) aead {
552552
if err != nil {
553553
panic(err)
554554
}
555-
aead, err := cipher.NewGCM(aes)
555+
var aead cipher.AEAD
556+
if boring.Enabled {
557+
aead, err = boring.NewGCMTLS13(aes)
558+
} else {
559+
boring.Unreachable()
560+
aead, err = cipher.NewGCM(aes)
561+
}
556562
if err != nil {
557563
panic(err)
558564
}

src/crypto/tls/defaults.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,16 @@ var defaultCipherSuitesTLS13NoAES = []uint16{
9090
TLS_AES_256_GCM_SHA384,
9191
}
9292

93+
// The FIPS-only policies below match BoringSSL's ssl_policy_fips_202205.
94+
9395
var defaultSupportedVersionsFIPS = []uint16{
9496
VersionTLS12,
97+
VersionTLS13,
9598
}
9699

97100
// defaultCurvePreferencesFIPS are the FIPS-allowed curves,
98101
// in preference order (most preferable first).
99-
var defaultCurvePreferencesFIPS = []CurveID{CurveP256, CurveP384, CurveP521}
102+
var defaultCurvePreferencesFIPS = []CurveID{CurveP256, CurveP384}
100103

101104
// defaultSupportedSignatureAlgorithmsFIPS currently are a subset of
102105
// defaultSupportedSignatureAlgorithms without Ed25519 and SHA-1.
@@ -109,7 +112,6 @@ var defaultSupportedSignatureAlgorithmsFIPS = []SignatureScheme{
109112
PKCS1WithSHA384,
110113
ECDSAWithP384AndSHA384,
111114
PKCS1WithSHA512,
112-
ECDSAWithP521AndSHA512,
113115
}
114116

115117
// defaultCipherSuitesFIPS are the FIPS-allowed cipher suites.
@@ -118,8 +120,6 @@ var defaultCipherSuitesFIPS = []uint16{
118120
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
119121
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
120122
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
121-
TLS_RSA_WITH_AES_128_GCM_SHA256,
122-
TLS_RSA_WITH_AES_256_GCM_SHA384,
123123
}
124124

125125
// defaultCipherSuitesTLS13FIPS are the FIPS-allowed cipher suites for TLS 1.3.

src/crypto/tls/handshake_client.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -141,13 +141,18 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *keySharePrivateKeys, *echCon
141141
if len(hello.supportedVersions) == 1 {
142142
hello.cipherSuites = nil
143143
}
144-
if hasAESGCMHardwareSupport {
144+
if needFIPS() {
145+
hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13FIPS...)
146+
} else if hasAESGCMHardwareSupport {
145147
hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13...)
146148
} else {
147149
hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13NoAES...)
148150
}
149151

150-
curveID := config.curvePreferences(maxVersion)[0]
152+
if len(hello.supportedCurves) == 0 {
153+
return nil, nil, nil, errors.New("tls: no supported elliptic curves for ECDHE")
154+
}
155+
curveID := hello.supportedCurves[0]
151156
keyShareKeys = &keySharePrivateKeys{curveID: curveID}
152157
if curveID == x25519Kyber768Draft00 {
153158
keyShareKeys.ecdhe, err = generateECDHEKey(config.rand(), X25519)

src/crypto/tls/handshake_client_tls13.go

-4
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,6 @@ type clientHandshakeStateTLS13 struct {
4545
func (hs *clientHandshakeStateTLS13) handshake() error {
4646
c := hs.c
4747

48-
if needFIPS() {
49-
return errors.New("tls: internal error: TLS 1.3 reached in FIPS mode")
50-
}
51-
5248
// The server must not select TLS 1.3 in a renegotiation. See RFC 8446,
5349
// sections 4.1.2 and 4.1.3.
5450
if c.handshakes > 0 {

src/crypto/tls/handshake_server_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
)
3030

3131
func testClientHello(t *testing.T, serverConfig *Config, m handshakeMessage) {
32+
t.Helper()
3233
testClientHelloFailure(t, serverConfig, m, "")
3334
}
3435

src/crypto/tls/handshake_server_tls13.go

+3-4
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,6 @@ type serverHandshakeStateTLS13 struct {
4747
func (hs *serverHandshakeStateTLS13) handshake() error {
4848
c := hs.c
4949

50-
if needFIPS() {
51-
return errors.New("tls: internal error: TLS 1.3 reached in FIPS mode")
52-
}
53-
5450
// For an overview of the TLS 1.3 handshake, see RFC 8446, Section 2.
5551
if err := hs.processClientHello(); err != nil {
5652
return err
@@ -165,6 +161,9 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error {
165161
if !hasAESGCMHardwareSupport || !aesgcmPreferred(hs.clientHello.cipherSuites) {
166162
preferenceList = defaultCipherSuitesTLS13NoAES
167163
}
164+
if needFIPS() {
165+
preferenceList = defaultCipherSuitesTLS13FIPS
166+
}
168167
for _, suiteID := range preferenceList {
169168
hs.suite = mutualCipherSuiteTLS13(hs.clientHello.cipherSuites, suiteID)
170169
if hs.suite != nil {

0 commit comments

Comments
 (0)