]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[dev.boringcrypto] all: merge master into dev.boringcrypto
authorDmitri Shuralyov <dmitshur@golang.org>
Wed, 2 Dec 2020 02:15:51 +0000 (21:15 -0500)
committerDmitri Shuralyov <dmitshur@golang.org>
Wed, 2 Dec 2020 17:57:07 +0000 (12:57 -0500)
Add BoringCrypto-specific test data to TestAESCipherReordering
and TestAESCipherReordering13.

Change-Id: Id1def4cf166d5059920741f045e3e61bb17c23c8

1  2 
src/crypto/tls/common.go
src/crypto/tls/handshake_server.go
src/crypto/tls/handshake_server_test.go
src/crypto/tls/handshake_server_tls13.go

index f8bbc3004d0542c278a800d303efcd5c0aa38111,5b68742975cd079d25b3b8e4e56111e441cb2f8e..1e724fcb3c0df3432cca245c78c4fe20412da7af
@@@ -1466,19 -1470,7 +1479,8 @@@ var 
  func initDefaultCipherSuites() {
        var topCipherSuites []uint16
  
-       // Check the cpu flags for each platform that has optimized GCM implementations.
-       // Worst case, these variables will just all be false.
-       var (
-               hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ
-               hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL
-               // Keep in sync with crypto/aes/cipher_s390x.go.
-               hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR && (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM)
-               hasGCMAsm = hasGCMAsmAMD64 || hasGCMAsmARM64 || hasGCMAsmS390X
-       )
-       if hasGCMAsm || boringEnabled {
 -      if hasAESGCMHardwareSupport {
++      if hasAESGCMHardwareSupport || boringEnabled {
 +              // If BoringCrypto is enabled, always prioritize AES-GCM.
                // If AES-GCM hardware is provided then prioritise AES-GCM
                // cipher suites.
                topCipherSuites = []uint16{
index 8095ed1708616606e269e24960dab1161080d43b,5a572a9db10f62d5da87cbd5e66f99f8286518a0..52bb4d6844bff39b74b63d675cfa0fecfe1aba89
@@@ -306,6 -314,12 +314,13 @@@ func (hs *serverHandshakeState) pickCip
        } else {
                preferenceList = hs.clientHello.cipherSuites
                supportedList = c.config.cipherSuites()
 -              if !hasAESGCMHardwareSupport {
+               // If we don't have hardware support for AES-GCM, prefer other AEAD
+               // ciphers even if the client prioritized AES-GCM.
++              // If BoringCrypto is enabled, always prioritize AES-GCM.
++              if !hasAESGCMHardwareSupport && !boringEnabled {
+                       preferenceList = deprioritizeAES(preferenceList)
+               }
        }
  
        hs.suite = selectCipherSuite(preferenceList, supportedList, hs.cipherSuiteOk)
index c4416c379a4baeecd090fa001db8bb388752b49b,ad851b6edf0a58b219baccbedc2b102c9bba572c..36d48bc942ca03f63281d3212b660ef4f1bf180b
@@@ -1719,3 -1722,266 +1722,281 @@@ func TestServerHandshakeContextCancella
                t.Error("Server connection was not closed when the context was canceled")
        }
  }
 -                      serverHasAESGCM: false,
 -                      expectedCipher:  TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+ func TestAESCipherReordering(t *testing.T) {
+       currentAESSupport := hasAESGCMHardwareSupport
+       defer func() { hasAESGCMHardwareSupport = currentAESSupport; initDefaultCipherSuites() }()
+       tests := []struct {
+               name                     string
+               clientCiphers            []uint16
+               serverHasAESGCM          bool
+               preferServerCipherSuites bool
+               serverCiphers            []uint16
+               expectedCipher           uint16
++              boringExpectedCipher     uint16 // If non-zero, used when BoringCrypto is enabled.
+       }{
+               {
+                       name: "server has hardware AES, client doesn't (pick ChaCha)",
+                       clientCiphers: []uint16{
+                               TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+                               TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+                               TLS_RSA_WITH_AES_128_CBC_SHA,
+                       },
+                       serverHasAESGCM:          true,
+                       preferServerCipherSuites: true,
+                       expectedCipher:           TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+               },
+               {
+                       name: "server strongly prefers AES-GCM, client doesn't (pick AES-GCM)",
+                       clientCiphers: []uint16{
+                               TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+                               TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+                               TLS_RSA_WITH_AES_128_CBC_SHA,
+                       },
+                       serverHasAESGCM:          true,
+                       preferServerCipherSuites: true,
+                       serverCiphers: []uint16{
+                               TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+                               TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+                               TLS_RSA_WITH_AES_128_CBC_SHA,
+                       },
+                       expectedCipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+               },
+               {
+                       name: "client prefers AES-GCM, server doesn't have hardware AES (pick ChaCha)",
+                       clientCiphers: []uint16{
+                               TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+                               TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+                               TLS_RSA_WITH_AES_128_CBC_SHA,
+                       },
 -                      serverHasAESGCM: false,
 -                      expectedCipher:  TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
++                      serverHasAESGCM:      false,
++                      expectedCipher:       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
++                      boringExpectedCipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, // When BoringCrypto is enabled, AES-GCM is prioritized even without server hardware.
+               },
+               {
+                       name: "client prefers AES-GCM, server has hardware AES (pick AES-GCM)",
+                       clientCiphers: []uint16{
+                               TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+                               TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+                               TLS_RSA_WITH_AES_128_CBC_SHA,
+                       },
+                       serverHasAESGCM: true,
+                       expectedCipher:  TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+               },
+               {
+                       name: "client prefers AES-GCM and sends GREASE, server has hardware AES (pick AES-GCM)",
+                       clientCiphers: []uint16{
+                               0x0A0A, // GREASE value
+                               TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+                               TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+                               TLS_RSA_WITH_AES_128_CBC_SHA,
+                       },
+                       serverHasAESGCM: true,
+                       expectedCipher:  TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+               },
+               {
+                       name: "client prefers AES-GCM and doesn't support ChaCha, server doesn't have hardware AES (pick AES-GCM)",
+                       clientCiphers: []uint16{
+                               TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+                               TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+                               TLS_RSA_WITH_AES_128_CBC_SHA,
+                       },
+                       serverHasAESGCM: false,
+                       expectedCipher:  TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+               },
+               {
+                       name: "client prefers AES-GCM and AES-CBC over ChaCha, server doesn't have hardware AES (pick AES-GCM)",
+                       clientCiphers: []uint16{
+                               TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+                               TLS_RSA_WITH_AES_128_CBC_SHA,
+                               TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+                       },
+                       serverHasAESGCM: false,
+                       expectedCipher:  TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+               },
+               {
+                       name: "client prefers AES-GCM over ChaCha and sends GREASE, server doesn't have hardware AES (pick ChaCha)",
+                       clientCiphers: []uint16{
+                               0x0A0A, // GREASE value
+                               TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+                               TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+                               TLS_RSA_WITH_AES_128_CBC_SHA,
+                       },
 -                      if tc.expectedCipher != hs.suite.id {
 -                              t.Errorf("unexpected cipher chosen: want %d, got %d", tc.expectedCipher, hs.suite.id)
++                      serverHasAESGCM:      false,
++                      expectedCipher:       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
++                      boringExpectedCipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, // When BoringCrypto is enabled, AES-GCM is prioritized even without server hardware.
+               },
+               {
+                       name: "client supports multiple AES-GCM, server doesn't have hardware AES and doesn't support ChaCha (pick corrent AES-GCM)",
+                       clientCiphers: []uint16{
+                               TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+                               TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+                               TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+                       },
+                       serverHasAESGCM: false,
+                       serverCiphers: []uint16{
+                               TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+                               TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+                       },
+                       expectedCipher: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+               },
+       }
+       for _, tc := range tests {
+               t.Run(tc.name, func(t *testing.T) {
+                       hasAESGCMHardwareSupport = tc.serverHasAESGCM
+                       initDefaultCipherSuites()
+                       hs := &serverHandshakeState{
+                               c: &Conn{
+                                       config: &Config{
+                                               PreferServerCipherSuites: tc.preferServerCipherSuites,
+                                               CipherSuites:             tc.serverCiphers,
+                                       },
+                                       vers: VersionTLS12,
+                               },
+                               clientHello: &clientHelloMsg{
+                                       cipherSuites: tc.clientCiphers,
+                                       vers:         VersionTLS12,
+                               },
+                               ecdheOk:      true,
+                               rsaSignOk:    true,
+                               rsaDecryptOk: true,
+                       }
+                       err := hs.pickCipherSuite()
+                       if err != nil {
+                               t.Errorf("pickCipherSuite failed: %s", err)
+                       }
 -                      serverHasAESGCM: false,
 -                      expectedCipher:  TLS_CHACHA20_POLY1305_SHA256,
++                      want := tc.expectedCipher
++                      if boringEnabled && tc.boringExpectedCipher != 0 {
++                              want = tc.boringExpectedCipher
++                      }
++                      if want != hs.suite.id {
++                              t.Errorf("unexpected cipher chosen: want %d, got %d", want, hs.suite.id)
+                       }
+               })
+       }
+ }
+ func TestAESCipherReordering13(t *testing.T) {
+       currentAESSupport := hasAESGCMHardwareSupport
+       defer func() { hasAESGCMHardwareSupport = currentAESSupport; initDefaultCipherSuites() }()
+       tests := []struct {
+               name                     string
+               clientCiphers            []uint16
+               serverHasAESGCM          bool
+               preferServerCipherSuites bool
+               expectedCipher           uint16
++              boringExpectedCipher     uint16 // If non-zero, used when BoringCrypto is enabled.
+       }{
+               {
+                       name: "server has hardware AES, client doesn't (pick ChaCha)",
+                       clientCiphers: []uint16{
+                               TLS_CHACHA20_POLY1305_SHA256,
+                               TLS_AES_128_GCM_SHA256,
+                       },
+                       serverHasAESGCM:          true,
+                       preferServerCipherSuites: true,
+                       expectedCipher:           TLS_CHACHA20_POLY1305_SHA256,
+               },
+               {
+                       name: "neither server nor client have hardware AES (pick ChaCha)",
+                       clientCiphers: []uint16{
+                               TLS_CHACHA20_POLY1305_SHA256,
+                               TLS_AES_128_GCM_SHA256,
+                       },
+                       serverHasAESGCM:          false,
+                       preferServerCipherSuites: true,
+                       expectedCipher:           TLS_CHACHA20_POLY1305_SHA256,
+               },
+               {
+                       name: "client prefers AES, server doesn't have hardware, prefer server ciphers (pick ChaCha)",
+                       clientCiphers: []uint16{
+                               TLS_AES_128_GCM_SHA256,
+                               TLS_CHACHA20_POLY1305_SHA256,
+                       },
+                       serverHasAESGCM:          false,
+                       preferServerCipherSuites: true,
+                       expectedCipher:           TLS_CHACHA20_POLY1305_SHA256,
++                      boringExpectedCipher:     TLS_AES_128_GCM_SHA256, // When BoringCrypto is enabled, AES-GCM is prioritized even without server hardware.
+               },
+               {
+                       name: "client prefers AES and sends GREASE, server doesn't have hardware, prefer server ciphers (pick ChaCha)",
+                       clientCiphers: []uint16{
+                               0x0A0A, // GREASE value
+                               TLS_AES_128_GCM_SHA256,
+                               TLS_CHACHA20_POLY1305_SHA256,
+                       },
+                       serverHasAESGCM:          false,
+                       preferServerCipherSuites: true,
+                       expectedCipher:           TLS_CHACHA20_POLY1305_SHA256,
++                      boringExpectedCipher:     TLS_AES_128_GCM_SHA256, // When BoringCrypto is enabled, AES-GCM is prioritized even without server hardware.
+               },
+               {
+                       name: "client prefers AES, server doesn't (pick ChaCha)",
+                       clientCiphers: []uint16{
+                               TLS_AES_128_GCM_SHA256,
+                               TLS_CHACHA20_POLY1305_SHA256,
+                       },
 -                      if tc.expectedCipher != hs.suite.id {
 -                              t.Errorf("unexpected cipher chosen: want %d, got %d", tc.expectedCipher, hs.suite.id)
++                      serverHasAESGCM:      false,
++                      expectedCipher:       TLS_CHACHA20_POLY1305_SHA256,
++                      boringExpectedCipher: TLS_AES_128_GCM_SHA256, // When BoringCrypto is enabled, AES-GCM is prioritized even without server hardware.
+               },
+               {
+                       name: "client prefers AES, server has hardware AES (pick AES)",
+                       clientCiphers: []uint16{
+                               TLS_AES_128_GCM_SHA256,
+                               TLS_CHACHA20_POLY1305_SHA256,
+                       },
+                       serverHasAESGCM: true,
+                       expectedCipher:  TLS_AES_128_GCM_SHA256,
+               },
+               {
+                       name: "client prefers AES and sends GREASE, server has hardware AES (pick AES)",
+                       clientCiphers: []uint16{
+                               0x0A0A, // GREASE value
+                               TLS_AES_128_GCM_SHA256,
+                               TLS_CHACHA20_POLY1305_SHA256,
+                       },
+                       serverHasAESGCM: true,
+                       expectedCipher:  TLS_AES_128_GCM_SHA256,
+               },
+       }
+       for _, tc := range tests {
+               t.Run(tc.name, func(t *testing.T) {
+                       hasAESGCMHardwareSupport = tc.serverHasAESGCM
+                       initDefaultCipherSuites()
+                       hs := &serverHandshakeStateTLS13{
+                               c: &Conn{
+                                       config: &Config{
+                                               PreferServerCipherSuites: tc.preferServerCipherSuites,
+                                       },
+                                       vers: VersionTLS13,
+                               },
+                               clientHello: &clientHelloMsg{
+                                       cipherSuites:       tc.clientCiphers,
+                                       supportedVersions:  []uint16{VersionTLS13},
+                                       compressionMethods: []uint8{compressionNone},
+                                       keyShares:          []keyShare{{group: X25519, data: curve25519.Basepoint}},
+                               },
+                       }
+                       err := hs.processClientHello()
+                       if err != nil {
+                               t.Errorf("pickCipherSuite failed: %s", err)
+                       }
++                      want := tc.expectedCipher
++                      if boringEnabled && tc.boringExpectedCipher != 0 {
++                              want = tc.boringExpectedCipher
++                      }
++                      if want != hs.suite.id {
++                              t.Errorf("unexpected cipher chosen: want %d, got %d", want, hs.suite.id)
+                       }
+               })
+       }
+ }
index b4ad5e18979aeb2e08795b426c6b9830f6ac0302,c7837d2955d5aa7cda93d4e3840fca075f2fd4ea..c3e3efbd11520691917682cbde15c0c6926268da
@@@ -160,6 -163,12 +167,13 @@@ func (hs *serverHandshakeStateTLS13) pr
        } else {
                preferenceList = hs.clientHello.cipherSuites
                supportedList = defaultCipherSuitesTLS13()
 -              if !hasAESGCMHardwareSupport {
+               // If we don't have hardware support for AES-GCM, prefer other AEAD
+               // ciphers even if the client prioritized AES-GCM.
++              // If BoringCrypto is enabled, always prioritize AES-GCM.
++              if !hasAESGCMHardwareSupport && !boringEnabled {
+                       preferenceList = deprioritizeAES(preferenceList)
+               }
        }
        for _, suiteID := range preferenceList {
                hs.suite = mutualCipherSuiteTLS13(supportedList, suiteID)