diff options
Diffstat (limited to 'src/ssl/test/runner/key_agreement.go')
-rw-r--r-- | src/ssl/test/runner/key_agreement.go | 99 |
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 } |