summaryrefslogtreecommitdiff
path: root/src/ssl/test/runner/key_agreement.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/ssl/test/runner/key_agreement.go')
-rw-r--r--src/ssl/test/runner/key_agreement.go99
1 files changed, 97 insertions, 2 deletions
diff --git a/src/ssl/test/runner/key_agreement.go b/src/ssl/test/runner/key_agreement.go
index 13e78bc4..f4789b66 100644
--- a/src/ssl/test/runner/key_agreement.go
+++ b/src/ssl/test/runner/key_agreement.go
@@ -19,6 +19,7 @@ import (
"boringssl.googlesource.com/boringssl/ssl/test/runner/curve25519"
"boringssl.googlesource.com/boringssl/ssl/test/runner/ed25519"
"boringssl.googlesource.com/boringssl/ssl/test/runner/hrss"
+ "boringssl.googlesource.com/boringssl/ssl/test/runner/sike"
)
type keyType int
@@ -433,6 +434,98 @@ func (e *cecpq2Curve) finish(peerKey []byte) (preMasterSecret []byte, err error)
return preMasterSecret, nil
}
+// cecpq2BCurve implements CECPQ2b, which is SIKE combined with X25519.
+type cecpq2BCurve struct {
+ // Both public key and shared secret size
+ x25519PrivateKey [32]byte
+ sikePrivateKey *sike.PrivateKey
+}
+
+func (e *cecpq2BCurve) offer(rand io.Reader) (publicKey []byte, err error) {
+ if _, err = io.ReadFull(rand, e.x25519PrivateKey[:]); err != nil {
+ return nil, err
+ }
+
+ var x25519Public [32]byte
+ curve25519.ScalarBaseMult(&x25519Public, &e.x25519PrivateKey)
+
+ e.sikePrivateKey = sike.NewPrivateKey(sike.KeyVariant_SIKE)
+ if err = e.sikePrivateKey.Generate(rand); err != nil {
+ return nil, err
+ }
+
+ sikePublic := e.sikePrivateKey.GeneratePublicKey().Export()
+ var ret []byte
+ ret = append(ret, x25519Public[:]...)
+ ret = append(ret, sikePublic...)
+ return ret, nil
+}
+
+func (e *cecpq2BCurve) accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error) {
+ if len(peerKey) != 32+sike.Params.PublicKeySize {
+ return nil, nil, errors.New("tls: bad length CECPQ2b offer")
+ }
+
+ if _, err = io.ReadFull(rand, e.x25519PrivateKey[:]); err != nil {
+ return nil, nil, err
+ }
+
+ var x25519Shared, x25519PeerKey, x25519Public [32]byte
+ copy(x25519PeerKey[:], peerKey)
+ curve25519.ScalarBaseMult(&x25519Public, &e.x25519PrivateKey)
+ curve25519.ScalarMult(&x25519Shared, &e.x25519PrivateKey, &x25519PeerKey)
+
+ // Per RFC 7748, reject the all-zero value in constant time.
+ var zeros [32]byte
+ if subtle.ConstantTimeCompare(zeros[:], x25519Shared[:]) == 1 {
+ return nil, nil, errors.New("tls: X25519 value with wrong order")
+ }
+
+ var sikePubKey = sike.NewPublicKey(sike.KeyVariant_SIKE)
+ if err = sikePubKey.Import(peerKey[32:]); err != nil {
+ // should never happen as size was already checked
+ return nil, nil, errors.New("tls: implementation error")
+ }
+ sikeCiphertext, sikeShared, err := sike.Encapsulate(rand, sikePubKey)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ publicKey = append(publicKey, x25519Public[:]...)
+ publicKey = append(publicKey, sikeCiphertext...)
+ preMasterSecret = append(preMasterSecret, x25519Shared[:]...)
+ preMasterSecret = append(preMasterSecret, sikeShared...)
+
+ return publicKey, preMasterSecret, nil
+}
+
+func (e *cecpq2BCurve) finish(peerKey []byte) (preMasterSecret []byte, err error) {
+ if len(peerKey) != 32+(sike.Params.PublicKeySize+sike.Params.MsgLen) {
+ return nil, errors.New("tls: bad length CECPQ2b reply")
+ }
+
+ var x25519Shared, x25519PeerKey [32]byte
+ copy(x25519PeerKey[:], peerKey)
+ curve25519.ScalarMult(&x25519Shared, &e.x25519PrivateKey, &x25519PeerKey)
+
+ // Per RFC 7748, reject the all-zero value in constant time.
+ var zeros [32]byte
+ if subtle.ConstantTimeCompare(zeros[:], x25519Shared[:]) == 1 {
+ return nil, errors.New("tls: X25519 value with wrong order")
+ }
+
+ var sikePubKey = e.sikePrivateKey.GeneratePublicKey()
+ sikeShared, err := sike.Decapsulate(e.sikePrivateKey, sikePubKey, peerKey[32:])
+ if err != nil {
+ return nil, errors.New("tls: invalid SIKE ciphertext")
+ }
+
+ preMasterSecret = append(preMasterSecret, x25519Shared[:]...)
+ preMasterSecret = append(preMasterSecret, sikeShared...)
+
+ return preMasterSecret, nil
+}
+
func curveForCurveID(id CurveID, config *Config) (ecdhCurve, bool) {
switch id {
case CurveP224:
@@ -447,6 +540,8 @@ func curveForCurveID(id CurveID, config *Config) (ecdhCurve, bool) {
return &x25519ECDHCurve{setHighBit: config.Bugs.SetX25519HighBit}, true
case CurveCECPQ2:
return &cecpq2Curve{}, true
+ case CurveCECPQ2b:
+ return &cecpq2BCurve{}, true
default:
return nil, false
}
@@ -594,8 +689,8 @@ func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Cer
NextCandidate:
for _, candidate := range preferredCurves {
- if candidate == CurveCECPQ2 && version < VersionTLS13 {
- // CECPQ2 is TLS 1.3-only.
+ if isPqGroup(candidate) && version < VersionTLS13 {
+ // CECPQ2 and CECPQ2b is TLS 1.3-only.
continue
}