summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Benjamin <davidben@chromium.org>2014-10-27 02:23:15 -0400
committerAdam Langley <agl@google.com>2014-10-29 20:33:09 +0000
commit2af684fa92a4bab4f59da12b58b03cd15b963623 (patch)
treeadfca255891a0a7fb52b0b8e3878bb3f8fb4e10c
parent491956c8668a4a5da13120212a10b0c3183dec63 (diff)
downloadsrc-2af684fa92a4bab4f59da12b58b03cd15b963623.tar.gz
Add tests for ECDHE_PSK.
pskKeyAgreement is now a wrapper over a base key agreement. Change-Id: Ic18862d3e98f7513476f878b8df5dcd8d36a0eac Reviewed-on: https://boringssl-review.googlesource.com/2053 Reviewed-by: Adam Langley <agl@google.com>
-rw-r--r--ssl/test/runner/cipher_suites.go24
-rw-r--r--ssl/test/runner/key_agreement.go139
-rw-r--r--ssl/test/runner/runner.go1
3 files changed, 138 insertions, 26 deletions
diff --git a/ssl/test/runner/cipher_suites.go b/ssl/test/runner/cipher_suites.go
index a0e6b94..5a3ac80 100644
--- a/ssl/test/runner/cipher_suites.go
+++ b/ssl/test/runner/cipher_suites.go
@@ -112,6 +112,7 @@ var cipherSuites = []*cipherSuite{
{TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil},
{TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, dheRSAKA, 0, cipher3DES, macSHA1, nil},
{TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil},
+ {TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdhePSKKA, suiteECDHE | suiteTLS12 | suitePSK, nil, nil, aeadAESGCM},
{TLS_PSK_WITH_RC4_128_SHA, 16, 20, 0, pskKA, suiteNoDTLS | suitePSK, cipherRC4, macSHA1, nil},
{TLS_PSK_WITH_AES_128_CBC_SHA, 16, 20, 16, pskKA, suitePSK, cipherAES, macSHA1, nil},
{TLS_PSK_WITH_AES_256_CBC_SHA, 32, 20, 16, pskKA, suitePSK, cipherAES, macSHA1, nil},
@@ -293,7 +294,7 @@ func rsaKA(version uint16) keyAgreement {
func ecdheECDSAKA(version uint16) keyAgreement {
return &ecdheKeyAgreement{
- signedKeyAgreement: signedKeyAgreement{
+ auth: &signedKeyAgreement{
sigType: signatureECDSA,
version: version,
},
@@ -302,7 +303,7 @@ func ecdheECDSAKA(version uint16) keyAgreement {
func ecdheRSAKA(version uint16) keyAgreement {
return &ecdheKeyAgreement{
- signedKeyAgreement: signedKeyAgreement{
+ auth: &signedKeyAgreement{
sigType: signatureRSA,
version: version,
},
@@ -311,7 +312,7 @@ func ecdheRSAKA(version uint16) keyAgreement {
func dheRSAKA(version uint16) keyAgreement {
return &dheKeyAgreement{
- signedKeyAgreement: signedKeyAgreement{
+ auth: &signedKeyAgreement{
sigType: signatureRSA,
version: version,
},
@@ -319,7 +320,17 @@ func dheRSAKA(version uint16) keyAgreement {
}
func pskKA(version uint16) keyAgreement {
- return &pskKeyAgreement{}
+ return &pskKeyAgreement{
+ base: &nilKeyAgreement{},
+ }
+}
+
+func ecdhePSKKA(version uint16) keyAgreement {
+ return &pskKeyAgreement{
+ base: &ecdheKeyAgreement{
+ auth: &nilKeyAgreementAuthentication{},
+ },
+ }
}
// mutualCipherSuite returns a cipherSuite given a list of supported
@@ -377,3 +388,8 @@ const (
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc030
fallbackSCSV uint16 = 0x5600
)
+
+// Additional cipher suite IDs, not IANA-assigned.
+const (
+ TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0xcafe
+)
diff --git a/ssl/test/runner/key_agreement.go b/ssl/test/runner/key_agreement.go
index 4f76cb1..af54a8f 100644
--- a/ssl/test/runner/key_agreement.go
+++ b/ssl/test/runner/key_agreement.go
@@ -187,8 +187,29 @@ func curveForCurveID(id CurveID) (elliptic.Curve, bool) {
}
-// signedKeyAgreement implements helper functions for key agreement
-// methods that involve signed parameters in the ServerKeyExchange.
+// keyAgreementAuthentication is a helper interface that specifies how
+// to authenticate the ServerKeyExchange parameters.
+type keyAgreementAuthentication interface {
+ signParameters(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, params []byte) (*serverKeyExchangeMsg, error)
+ verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) error
+}
+
+// nilKeyAgreementAuthentication does not authenticate the key
+// agreement parameters.
+type nilKeyAgreementAuthentication struct{}
+
+func (ka *nilKeyAgreementAuthentication) signParameters(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, params []byte) (*serverKeyExchangeMsg, error) {
+ skx := new(serverKeyExchangeMsg)
+ skx.key = params
+ return skx, nil
+}
+
+func (ka *nilKeyAgreementAuthentication) verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) error {
+ return nil
+}
+
+// signedKeyAgreement signs the ServerKeyExchange parameters with the
+// server's private key.
type signedKeyAgreement struct {
version uint16
sigType uint8
@@ -328,7 +349,7 @@ func (ka *signedKeyAgreement) verifyParameters(config *Config, clientHello *clie
// pre-master secret is then calculated using ECDH. The signature may
// either be ECDSA or RSA.
type ecdheKeyAgreement struct {
- signedKeyAgreement
+ auth keyAgreementAuthentication
privateKey []byte
curve elliptic.Curve
x, y *big.Int
@@ -394,7 +415,7 @@ NextCandidate:
serverECDHParams[3] = byte(len(ecdhePublic))
copy(serverECDHParams[4:], ecdhePublic)
- return ka.signParameters(config, cert, clientHello, hello, serverECDHParams)
+ return ka.auth.signParameters(config, cert, clientHello, hello, serverECDHParams)
}
func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
@@ -438,7 +459,7 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell
serverECDHParams := skx.key[:4+publicLen]
sig := skx.key[4+publicLen:]
- return ka.verifyParameters(config, clientHello, serverHello, cert, serverECDHParams, sig)
+ return ka.auth.verifyParameters(config, clientHello, serverHello, cert, serverECDHParams, sig)
}
func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
@@ -468,7 +489,7 @@ func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHel
// an ephemeral Diffie-Hellman public/private key pair and signs it. The
// pre-master secret is then calculated using Diffie-Hellman.
type dheKeyAgreement struct {
- signedKeyAgreement
+ auth keyAgreementAuthentication
p, g *big.Int
yTheirs *big.Int
xOurs *big.Int
@@ -500,7 +521,7 @@ func (ka *dheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certi
serverDHParams = append(serverDHParams, byte(len(yBytes)>>8), byte(len(yBytes)))
serverDHParams = append(serverDHParams, yBytes...)
- return ka.signParameters(config, cert, clientHello, hello, serverDHParams)
+ return ka.auth.signParameters(config, cert, clientHello, hello, serverDHParams)
}
func (ka *dheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
@@ -562,7 +583,7 @@ func (ka *dheKeyAgreement) processServerKeyExchange(config *Config, clientHello
sig := k
serverDHParams := skx.key[:len(skx.key)-len(sig)]
- return ka.verifyParameters(config, clientHello, serverHello, cert, serverDHParams, sig)
+ return ka.auth.verifyParameters(config, clientHello, serverHello, cert, serverDHParams, sig)
}
func (ka *dheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
@@ -587,8 +608,43 @@ func (ka *dheKeyAgreement) generateClientKeyExchange(config *Config, clientHello
return preMasterSecret, ckx, nil
}
-// makePSKPremaster formats a PSK pre-master secret based on
-// otherSecret from the base key exchange and psk.
+// nilKeyAgreement is a fake key agreement used to implement the plain PSK key
+// exchange.
+type nilKeyAgreement struct{}
+
+func (ka *nilKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
+ return nil, nil
+}
+
+func (ka *nilKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
+ if len(ckx.ciphertext) != 0 {
+ return nil, errClientKeyExchange
+ }
+
+ // Although in plain PSK, otherSecret is all zeros, the base key
+ // agreement does not access to the length of the pre-shared
+ // key. pskKeyAgreement instead interprets nil to mean to use all zeros
+ // of the appropriate length.
+ return nil, nil
+}
+
+func (ka *nilKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
+ if len(skx.key) != 0 {
+ return errServerKeyExchange
+ }
+ return nil
+}
+
+func (ka *nilKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
+ // Although in plain PSK, otherSecret is all zeros, the base key
+ // agreement does not access to the length of the pre-shared
+ // key. pskKeyAgreement instead interprets nil to mean to use all zeros
+ // of the appropriate length.
+ return nil, &clientKeyExchangeMsg{}, nil
+}
+
+// makePSKPremaster formats a PSK pre-master secret based on otherSecret from
+// the base key exchange and psk.
func makePSKPremaster(otherSecret, psk []byte) []byte {
out := make([]byte, 0, 2+len(otherSecret)+2+len(psk))
out = append(out, byte(len(otherSecret)>>8), byte(len(otherSecret)))
@@ -600,33 +656,47 @@ func makePSKPremaster(otherSecret, psk []byte) []byte {
// pskKeyAgreement implements the PSK key agreement.
type pskKeyAgreement struct {
+ base keyAgreement
identityHint string
}
func (ka *pskKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
- // ServerKeyExchange is optional if the identity hint is empty.
- if config.PreSharedKeyIdentity == "" {
- return nil, nil
- }
+ // Assemble the identity hint.
bytes := make([]byte, 2+len(config.PreSharedKeyIdentity))
bytes[0] = byte(len(config.PreSharedKeyIdentity) >> 8)
bytes[1] = byte(len(config.PreSharedKeyIdentity))
copy(bytes[2:], []byte(config.PreSharedKeyIdentity))
+ // If there is one, append the base key agreement's
+ // ServerKeyExchange.
+ baseSkx, err := ka.base.generateServerKeyExchange(config, cert, clientHello, hello)
+ if err != nil {
+ return nil, err
+ }
+
+ if baseSkx != nil {
+ bytes = append(bytes, baseSkx.key...)
+ } else if config.PreSharedKeyIdentity == "" {
+ // ServerKeyExchange is optional if the identity hint is empty
+ // and there would otherwise be no ServerKeyExchange.
+ return nil, nil
+ }
+
skx := new(serverKeyExchangeMsg)
skx.key = bytes
return skx, nil
}
func (ka *pskKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
+ // First, process the PSK identity.
if len(ckx.ciphertext) < 2 {
return nil, errClientKeyExchange
}
identityLen := (int(ckx.ciphertext[0]) << 8) | int(ckx.ciphertext[1])
- if 2+identityLen != len(ckx.ciphertext) {
+ if 2+identityLen > len(ckx.ciphertext) {
return nil, errClientKeyExchange
}
- identity := string(ckx.ciphertext[2:])
+ identity := string(ckx.ciphertext[2 : 2+identityLen])
if identity != config.PreSharedKeyIdentity {
return nil, errors.New("tls: unexpected identity")
@@ -635,7 +705,20 @@ func (ka *pskKeyAgreement) processClientKeyExchange(config *Config, cert *Certif
if config.PreSharedKey == nil {
return nil, errors.New("tls: pre-shared key not configured")
}
- otherSecret := make([]byte, len(config.PreSharedKey))
+
+ // Process the remainder of the ClientKeyExchange to compute the base
+ // pre-master secret.
+ newCkx := new(clientKeyExchangeMsg)
+ newCkx.ciphertext = ckx.ciphertext[2+identityLen:]
+ otherSecret, err := ka.base.processClientKeyExchange(config, cert, newCkx, version)
+ if err != nil {
+ return nil, err
+ }
+
+ if otherSecret == nil {
+ // Special-case for the plain PSK key exchanges.
+ otherSecret = make([]byte, len(config.PreSharedKey))
+ }
return makePSKPremaster(otherSecret, config.PreSharedKey), nil
}
@@ -644,11 +727,15 @@ func (ka *pskKeyAgreement) processServerKeyExchange(config *Config, clientHello
return errServerKeyExchange
}
identityLen := (int(skx.key[0]) << 8) | int(skx.key[1])
- if 2+identityLen != len(skx.key) {
+ if 2+identityLen > len(skx.key) {
return errServerKeyExchange
}
- ka.identityHint = string(skx.key[2:])
- return nil
+ ka.identityHint = string(skx.key[2 : 2+identityLen])
+
+ // Process the remainder of the ServerKeyExchange.
+ newSkx := new(serverKeyExchangeMsg)
+ newSkx.key = skx.key[2+identityLen:]
+ return ka.base.processServerKeyExchange(config, clientHello, serverHello, cert, newSkx)
}
func (ka *pskKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
@@ -659,17 +746,25 @@ func (ka *pskKeyAgreement) generateClientKeyExchange(config *Config, clientHello
return nil, nil, errors.New("tls: unexpected identity")
}
+ // Serialize the identity.
bytes := make([]byte, 2+len(config.PreSharedKeyIdentity))
bytes[0] = byte(len(config.PreSharedKeyIdentity) >> 8)
bytes[1] = byte(len(config.PreSharedKeyIdentity))
copy(bytes[2:], []byte(config.PreSharedKeyIdentity))
+ // Append the base key exchange's ClientKeyExchange.
+ otherSecret, baseCkx, err := ka.base.generateClientKeyExchange(config, clientHello, cert)
+ if err != nil {
+ return nil, nil, err
+ }
ckx := new(clientKeyExchangeMsg)
- ckx.ciphertext = bytes
+ ckx.ciphertext = append(bytes, baseCkx.ciphertext...)
if config.PreSharedKey == nil {
return nil, nil, errors.New("tls: pre-shared key not configured")
}
- otherSecret := make([]byte, len(config.PreSharedKey))
+ if otherSecret == nil {
+ otherSecret = make([]byte, len(config.PreSharedKey))
+ }
return makePSKPremaster(otherSecret, config.PreSharedKey), ckx, nil
}
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 6f4562a..1b461e2 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -828,6 +828,7 @@ var testCipherSuites = []struct {
{"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
{"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
{"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
+ {"ECDHE-PSK-WITH-AES-128-GCM-SHA256", TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256},
{"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
{"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
{"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},