4c3ddf7ec0
In preparation for TLS 1.3 using its actual handshake, switch most tests to TLS 1.3 and add liberal TODOs for the tests which will need TLS 1.3 variants. In doing so, move a few tests from basic tests into one of the groups. Also rename BadECDSACurve to BadECDHECurve (it was never ECDSA) and add a test to make sure FALLBACK_SCSV is correctly sensitive to the maximum version. Change-Id: Ifca6cf8f7a48d6f069483c0aab192ae691b1dd8e Reviewed-on: https://boringssl-review.googlesource.com/8560 Reviewed-by: David Benjamin <davidben@google.com>
1015 lines
33 KiB
Go
1015 lines
33 KiB
Go
// Copyright 2010 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package runner
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"crypto/elliptic"
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/subtle"
|
|
"crypto/x509"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"math/big"
|
|
|
|
"./curve25519"
|
|
"./newhope"
|
|
)
|
|
|
|
type keyType int
|
|
|
|
const (
|
|
keyTypeRSA keyType = iota + 1
|
|
keyTypeECDSA
|
|
)
|
|
|
|
var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message")
|
|
var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message")
|
|
|
|
// rsaKeyAgreement implements the standard TLS key agreement where the client
|
|
// encrypts the pre-master secret to the server's public key.
|
|
type rsaKeyAgreement struct {
|
|
version uint16
|
|
clientVersion uint16
|
|
exportKey *rsa.PrivateKey
|
|
}
|
|
|
|
func (ka *rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
|
|
// Save the client version for comparison later.
|
|
ka.clientVersion = versionToWire(clientHello.vers, clientHello.isDTLS)
|
|
|
|
if !config.Bugs.RSAEphemeralKey {
|
|
return nil, nil
|
|
}
|
|
|
|
// Generate an ephemeral RSA key to use instead of the real
|
|
// one, as in RSA_EXPORT.
|
|
key, err := rsa.GenerateKey(config.rand(), 512)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ka.exportKey = key
|
|
|
|
modulus := key.N.Bytes()
|
|
exponent := big.NewInt(int64(key.E)).Bytes()
|
|
serverRSAParams := make([]byte, 0, 2+len(modulus)+2+len(exponent))
|
|
serverRSAParams = append(serverRSAParams, byte(len(modulus)>>8), byte(len(modulus)))
|
|
serverRSAParams = append(serverRSAParams, modulus...)
|
|
serverRSAParams = append(serverRSAParams, byte(len(exponent)>>8), byte(len(exponent)))
|
|
serverRSAParams = append(serverRSAParams, exponent...)
|
|
|
|
var sigAlg signatureAlgorithm
|
|
if ka.version >= VersionTLS12 {
|
|
sigAlg, err = selectSignatureAlgorithm(ka.version, cert.PrivateKey, clientHello.signatureAlgorithms, config.signatureAlgorithmsForServer())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
sig, err := signMessage(ka.version, cert.PrivateKey, config, sigAlg, serverRSAParams)
|
|
if err != nil {
|
|
return nil, errors.New("failed to sign RSA parameters: " + err.Error())
|
|
}
|
|
|
|
skx := new(serverKeyExchangeMsg)
|
|
sigAlgsLen := 0
|
|
if ka.version >= VersionTLS12 {
|
|
sigAlgsLen = 2
|
|
}
|
|
skx.key = make([]byte, len(serverRSAParams)+sigAlgsLen+2+len(sig))
|
|
copy(skx.key, serverRSAParams)
|
|
k := skx.key[len(serverRSAParams):]
|
|
if ka.version >= VersionTLS12 {
|
|
k[0] = byte(sigAlg >> 8)
|
|
k[1] = byte(sigAlg)
|
|
k = k[2:]
|
|
}
|
|
k[0] = byte(len(sig) >> 8)
|
|
k[1] = byte(len(sig))
|
|
copy(k[2:], sig)
|
|
|
|
return skx, nil
|
|
}
|
|
|
|
func (ka *rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
|
|
preMasterSecret := make([]byte, 48)
|
|
_, err := io.ReadFull(config.rand(), preMasterSecret[2:])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(ckx.ciphertext) < 2 {
|
|
return nil, errClientKeyExchange
|
|
}
|
|
|
|
ciphertext := ckx.ciphertext
|
|
if version != VersionSSL30 {
|
|
ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
|
|
if ciphertextLen != len(ckx.ciphertext)-2 {
|
|
return nil, errClientKeyExchange
|
|
}
|
|
ciphertext = ckx.ciphertext[2:]
|
|
}
|
|
|
|
key := cert.PrivateKey.(*rsa.PrivateKey)
|
|
if ka.exportKey != nil {
|
|
key = ka.exportKey
|
|
}
|
|
err = rsa.DecryptPKCS1v15SessionKey(config.rand(), key, ciphertext, preMasterSecret)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// This check should be done in constant-time, but this is a testing
|
|
// implementation. See the discussion at the end of section 7.4.7.1 of
|
|
// RFC 4346.
|
|
vers := uint16(preMasterSecret[0])<<8 | uint16(preMasterSecret[1])
|
|
if ka.clientVersion != vers {
|
|
return nil, errors.New("tls: invalid version in RSA premaster")
|
|
}
|
|
return preMasterSecret, nil
|
|
}
|
|
|
|
func (ka *rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
|
|
return errors.New("tls: unexpected ServerKeyExchange")
|
|
}
|
|
|
|
func (ka *rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
|
|
bad := config.Bugs.BadRSAClientKeyExchange
|
|
preMasterSecret := make([]byte, 48)
|
|
vers := clientHello.vers
|
|
if bad == RSABadValueWrongVersion {
|
|
vers ^= 1
|
|
}
|
|
vers = versionToWire(vers, clientHello.isDTLS)
|
|
preMasterSecret[0] = byte(vers >> 8)
|
|
preMasterSecret[1] = byte(vers)
|
|
_, err := io.ReadFull(config.rand(), preMasterSecret[2:])
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
sentPreMasterSecret := preMasterSecret
|
|
if bad == RSABadValueTooLong {
|
|
sentPreMasterSecret = make([]byte, len(sentPreMasterSecret)+1)
|
|
copy(sentPreMasterSecret, preMasterSecret)
|
|
} else if bad == RSABadValueTooShort {
|
|
sentPreMasterSecret = sentPreMasterSecret[:len(sentPreMasterSecret)-1]
|
|
}
|
|
|
|
encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), sentPreMasterSecret)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if bad == RSABadValueCorrupt {
|
|
encrypted[len(encrypted)-1] ^= 1
|
|
// Clear the high byte to ensure |encrypted| is still below the RSA modulus.
|
|
encrypted[0] = 0
|
|
}
|
|
ckx := new(clientKeyExchangeMsg)
|
|
if clientHello.vers != VersionSSL30 {
|
|
ckx.ciphertext = make([]byte, len(encrypted)+2)
|
|
ckx.ciphertext[0] = byte(len(encrypted) >> 8)
|
|
ckx.ciphertext[1] = byte(len(encrypted))
|
|
copy(ckx.ciphertext[2:], encrypted)
|
|
} else {
|
|
ckx.ciphertext = encrypted
|
|
}
|
|
return preMasterSecret, ckx, nil
|
|
}
|
|
|
|
func (ka *rsaKeyAgreement) peerSignatureAlgorithm() signatureAlgorithm {
|
|
return 0
|
|
}
|
|
|
|
// A ecdhCurve is an instance of ECDH-style key agreement for TLS.
|
|
type ecdhCurve interface {
|
|
// offer generates a keypair using rand. It returns the encoded |publicKey|.
|
|
offer(rand io.Reader) (publicKey []byte, err error)
|
|
|
|
// accept responds to the |peerKey| generated by |offer| with the acceptor's
|
|
// |publicKey|, and returns agreed-upon |preMasterSecret| to the acceptor.
|
|
accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error)
|
|
|
|
// finish returns the computed |preMasterSecret|, given the |peerKey|
|
|
// generated by |accept|.
|
|
finish(peerKey []byte) (preMasterSecret []byte, err error)
|
|
}
|
|
|
|
// ellipticECDHCurve implements ecdhCurve with an elliptic.Curve.
|
|
type ellipticECDHCurve struct {
|
|
curve elliptic.Curve
|
|
privateKey []byte
|
|
}
|
|
|
|
func (e *ellipticECDHCurve) offer(rand io.Reader) (publicKey []byte, err error) {
|
|
var x, y *big.Int
|
|
e.privateKey, x, y, err = elliptic.GenerateKey(e.curve, rand)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return elliptic.Marshal(e.curve, x, y), nil
|
|
}
|
|
|
|
func (e *ellipticECDHCurve) accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error) {
|
|
publicKey, err = e.offer(rand)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
preMasterSecret, err = e.finish(peerKey)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return
|
|
}
|
|
|
|
func (e *ellipticECDHCurve) finish(peerKey []byte) (preMasterSecret []byte, err error) {
|
|
x, y := elliptic.Unmarshal(e.curve, peerKey)
|
|
if x == nil {
|
|
return nil, errors.New("tls: invalid peer key")
|
|
}
|
|
x, _ = e.curve.ScalarMult(x, y, e.privateKey)
|
|
preMasterSecret = make([]byte, (e.curve.Params().BitSize+7)>>3)
|
|
xBytes := x.Bytes()
|
|
copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
|
|
|
|
return preMasterSecret, nil
|
|
}
|
|
|
|
// x25519ECDHCurve implements ecdhCurve with X25519.
|
|
type x25519ECDHCurve struct {
|
|
privateKey [32]byte
|
|
}
|
|
|
|
func (e *x25519ECDHCurve) offer(rand io.Reader) (publicKey []byte, err error) {
|
|
_, err = io.ReadFull(rand, e.privateKey[:])
|
|
if err != nil {
|
|
return
|
|
}
|
|
var out [32]byte
|
|
curve25519.ScalarBaseMult(&out, &e.privateKey)
|
|
return out[:], nil
|
|
}
|
|
|
|
func (e *x25519ECDHCurve) accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error) {
|
|
publicKey, err = e.offer(rand)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
preMasterSecret, err = e.finish(peerKey)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return
|
|
}
|
|
|
|
func (e *x25519ECDHCurve) finish(peerKey []byte) (preMasterSecret []byte, err error) {
|
|
if len(peerKey) != 32 {
|
|
return nil, errors.New("tls: invalid peer key")
|
|
}
|
|
var out, peerKeyCopy [32]byte
|
|
copy(peerKeyCopy[:], peerKey)
|
|
curve25519.ScalarMult(&out, &e.privateKey, &peerKeyCopy)
|
|
|
|
// Per RFC 7748, reject the all-zero value in constant time.
|
|
var zeros [32]byte
|
|
if subtle.ConstantTimeCompare(zeros[:], out[:]) == 1 {
|
|
return nil, errors.New("tls: X25519 value with wrong order")
|
|
}
|
|
|
|
return out[:], nil
|
|
}
|
|
|
|
// cecpq1Curve is combined elliptic curve (X25519) and post-quantum (new hope) key
|
|
// agreement.
|
|
type cecpq1Curve struct {
|
|
x25519 *x25519ECDHCurve
|
|
newhope *newhope.Poly
|
|
}
|
|
|
|
func (e *cecpq1Curve) offer(rand io.Reader) (publicKey []byte, err error) {
|
|
var x25519OfferMsg, newhopeOfferMsg []byte
|
|
|
|
e.x25519 = new(x25519ECDHCurve)
|
|
if x25519OfferMsg, err = e.x25519.offer(rand); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
newhopeOfferMsg, e.newhope = newhope.Offer(rand)
|
|
|
|
return append(x25519OfferMsg, newhopeOfferMsg[:]...), nil
|
|
}
|
|
|
|
func (e *cecpq1Curve) accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error) {
|
|
if len(peerKey) != 32+newhope.OfferMsgLen {
|
|
return nil, nil, errors.New("cecpq1: invalid offer message")
|
|
}
|
|
|
|
var x25519AcceptMsg, newhopeAcceptMsg []byte
|
|
var x25519Secret []byte
|
|
var newhopeSecret newhope.Key
|
|
|
|
x25519 := new(x25519ECDHCurve)
|
|
if x25519AcceptMsg, x25519Secret, err = x25519.accept(rand, peerKey[:32]); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
if newhopeSecret, newhopeAcceptMsg, err = newhope.Accept(rand, peerKey[32:]); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
return append(x25519AcceptMsg, newhopeAcceptMsg[:]...), append(x25519Secret, newhopeSecret[:]...), nil
|
|
}
|
|
|
|
func (e *cecpq1Curve) finish(peerKey []byte) (preMasterSecret []byte, err error) {
|
|
if len(peerKey) != 32+newhope.AcceptMsgLen {
|
|
return nil, errors.New("cecpq1: invalid accept message")
|
|
}
|
|
|
|
var x25519Secret []byte
|
|
var newhopeSecret newhope.Key
|
|
|
|
if x25519Secret, err = e.x25519.finish(peerKey[:32]); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if newhopeSecret, err = e.newhope.Finish(peerKey[32:]); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return append(x25519Secret, newhopeSecret[:]...), nil
|
|
}
|
|
|
|
func curveForCurveID(id CurveID) (ecdhCurve, bool) {
|
|
switch id {
|
|
case CurveP224:
|
|
return &ellipticECDHCurve{curve: elliptic.P224()}, true
|
|
case CurveP256:
|
|
return &ellipticECDHCurve{curve: elliptic.P256()}, true
|
|
case CurveP384:
|
|
return &ellipticECDHCurve{curve: elliptic.P384()}, true
|
|
case CurveP521:
|
|
return &ellipticECDHCurve{curve: elliptic.P521()}, true
|
|
case CurveX25519:
|
|
return &x25519ECDHCurve{}, true
|
|
default:
|
|
return nil, false
|
|
}
|
|
|
|
}
|
|
|
|
// 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 {
|
|
keyType keyType
|
|
version uint16
|
|
peerSignatureAlgorithm signatureAlgorithm
|
|
}
|
|
|
|
func (ka *signedKeyAgreement) signParameters(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, params []byte) (*serverKeyExchangeMsg, error) {
|
|
// The message to be signed is prepended by the randoms.
|
|
var msg []byte
|
|
msg = append(msg, clientHello.random...)
|
|
msg = append(msg, hello.random...)
|
|
msg = append(msg, params...)
|
|
|
|
if config.Bugs.InvalidSKXSignature {
|
|
msg[0] ^= 0x80
|
|
}
|
|
|
|
var sigAlg signatureAlgorithm
|
|
var err error
|
|
if ka.version >= VersionTLS12 {
|
|
sigAlg, err = selectSignatureAlgorithm(ka.version, cert.PrivateKey, clientHello.signatureAlgorithms, config.signatureAlgorithmsForServer())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
sig, err := signMessage(ka.version, cert.PrivateKey, config, sigAlg, msg)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
skx := new(serverKeyExchangeMsg)
|
|
if config.Bugs.UnauthenticatedECDH {
|
|
skx.key = params
|
|
} else {
|
|
sigAlgsLen := 0
|
|
if ka.version >= VersionTLS12 {
|
|
sigAlgsLen = 2
|
|
}
|
|
skx.key = make([]byte, len(params)+sigAlgsLen+2+len(sig))
|
|
copy(skx.key, params)
|
|
k := skx.key[len(params):]
|
|
if ka.version >= VersionTLS12 {
|
|
k[0] = byte(sigAlg >> 8)
|
|
k[1] = byte(sigAlg)
|
|
k = k[2:]
|
|
}
|
|
k[0] = byte(len(sig) >> 8)
|
|
k[1] = byte(len(sig))
|
|
copy(k[2:], sig)
|
|
}
|
|
|
|
return skx, nil
|
|
}
|
|
|
|
func (ka *signedKeyAgreement) verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) error {
|
|
// The peer's key must match the cipher type.
|
|
switch ka.keyType {
|
|
case keyTypeECDSA:
|
|
_, ok := cert.PublicKey.(*ecdsa.PublicKey)
|
|
if !ok {
|
|
return errors.New("tls: ECDHE ECDSA requires a ECDSA server public key")
|
|
}
|
|
case keyTypeRSA:
|
|
_, ok := cert.PublicKey.(*rsa.PublicKey)
|
|
if !ok {
|
|
return errors.New("tls: ECDHE RSA requires a RSA server public key")
|
|
}
|
|
default:
|
|
return errors.New("tls: unknown key type")
|
|
}
|
|
|
|
// The message to be signed is prepended by the randoms.
|
|
var msg []byte
|
|
msg = append(msg, clientHello.random...)
|
|
msg = append(msg, serverHello.random...)
|
|
msg = append(msg, params...)
|
|
|
|
var sigAlg signatureAlgorithm
|
|
if ka.version >= VersionTLS12 {
|
|
if len(sig) < 2 {
|
|
return errServerKeyExchange
|
|
}
|
|
sigAlg = signatureAlgorithm(sig[0])<<8 | signatureAlgorithm(sig[1])
|
|
sig = sig[2:]
|
|
if !isSupportedSignatureAlgorithm(sigAlg, config.signatureAlgorithmsForClient()) {
|
|
return errors.New("tls: unsupported signature algorithm for ServerKeyExchange")
|
|
}
|
|
// Stash the signature algorithm to be extracted by the handshake.
|
|
ka.peerSignatureAlgorithm = sigAlg
|
|
}
|
|
|
|
if len(sig) < 2 {
|
|
return errServerKeyExchange
|
|
}
|
|
sigLen := int(sig[0])<<8 | int(sig[1])
|
|
if sigLen+2 != len(sig) {
|
|
return errServerKeyExchange
|
|
}
|
|
sig = sig[2:]
|
|
|
|
return verifyMessage(ka.version, cert.PublicKey, sigAlg, msg, sig)
|
|
}
|
|
|
|
// ecdheRSAKeyAgreement implements a TLS key agreement where the server
|
|
// generates a ephemeral EC public/private key pair and signs it. The
|
|
// pre-master secret is then calculated using ECDH. The signature may
|
|
// either be ECDSA or RSA.
|
|
type ecdheKeyAgreement struct {
|
|
auth keyAgreementAuthentication
|
|
curve ecdhCurve
|
|
peerKey []byte
|
|
}
|
|
|
|
func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
|
|
var curveid CurveID
|
|
preferredCurves := config.curvePreferences()
|
|
|
|
NextCandidate:
|
|
for _, candidate := range preferredCurves {
|
|
for _, c := range clientHello.supportedCurves {
|
|
if candidate == c {
|
|
curveid = c
|
|
break NextCandidate
|
|
}
|
|
}
|
|
}
|
|
|
|
if curveid == 0 {
|
|
return nil, errors.New("tls: no supported elliptic curves offered")
|
|
}
|
|
|
|
var ok bool
|
|
if ka.curve, ok = curveForCurveID(curveid); !ok {
|
|
return nil, errors.New("tls: preferredCurves includes unsupported curve")
|
|
}
|
|
|
|
publicKey, err := ka.curve.offer(config.rand())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// http://tools.ietf.org/html/rfc4492#section-5.4
|
|
serverECDHParams := make([]byte, 1+2+1+len(publicKey))
|
|
serverECDHParams[0] = 3 // named curve
|
|
if config.Bugs.SendCurve != 0 {
|
|
curveid = config.Bugs.SendCurve
|
|
}
|
|
serverECDHParams[1] = byte(curveid >> 8)
|
|
serverECDHParams[2] = byte(curveid)
|
|
serverECDHParams[3] = byte(len(publicKey))
|
|
copy(serverECDHParams[4:], publicKey)
|
|
if config.Bugs.InvalidECDHPoint {
|
|
serverECDHParams[4] ^= 0xff
|
|
}
|
|
|
|
return ka.auth.signParameters(config, cert, clientHello, hello, serverECDHParams)
|
|
}
|
|
|
|
func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
|
|
if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
|
|
return nil, errClientKeyExchange
|
|
}
|
|
return ka.curve.finish(ckx.ciphertext[1:])
|
|
}
|
|
|
|
func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
|
|
if len(skx.key) < 4 {
|
|
return errServerKeyExchange
|
|
}
|
|
if skx.key[0] != 3 { // named curve
|
|
return errors.New("tls: server selected unsupported curve")
|
|
}
|
|
curveid := CurveID(skx.key[1])<<8 | CurveID(skx.key[2])
|
|
|
|
var ok bool
|
|
if ka.curve, ok = curveForCurveID(curveid); !ok {
|
|
return errors.New("tls: server selected unsupported curve")
|
|
}
|
|
|
|
publicLen := int(skx.key[3])
|
|
if publicLen+4 > len(skx.key) {
|
|
return errServerKeyExchange
|
|
}
|
|
// Save the peer key for later.
|
|
ka.peerKey = skx.key[4 : 4+publicLen]
|
|
|
|
// Check the signature.
|
|
serverECDHParams := skx.key[:4+publicLen]
|
|
sig := skx.key[4+publicLen:]
|
|
return ka.auth.verifyParameters(config, clientHello, serverHello, cert, serverECDHParams, sig)
|
|
}
|
|
|
|
func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
|
|
if ka.curve == nil {
|
|
return nil, nil, errors.New("missing ServerKeyExchange message")
|
|
}
|
|
|
|
publicKey, preMasterSecret, err := ka.curve.accept(config.rand(), ka.peerKey)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
ckx := new(clientKeyExchangeMsg)
|
|
ckx.ciphertext = make([]byte, 1+len(publicKey))
|
|
ckx.ciphertext[0] = byte(len(publicKey))
|
|
copy(ckx.ciphertext[1:], publicKey)
|
|
if config.Bugs.InvalidECDHPoint {
|
|
ckx.ciphertext[1] ^= 0xff
|
|
}
|
|
|
|
return preMasterSecret, ckx, nil
|
|
}
|
|
|
|
func (ka *ecdheKeyAgreement) peerSignatureAlgorithm() signatureAlgorithm {
|
|
if auth, ok := ka.auth.(*signedKeyAgreement); ok {
|
|
return auth.peerSignatureAlgorithm
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// cecpq1RSAKeyAgreement is like an ecdheKeyAgreement, but using the cecpq1Curve
|
|
// pseudo-curve, and without any parameters (e.g. curve name) other than the
|
|
// keys being exchanged. The signature may either be ECDSA or RSA.
|
|
type cecpq1KeyAgreement struct {
|
|
auth keyAgreementAuthentication
|
|
curve ecdhCurve
|
|
peerKey []byte
|
|
}
|
|
|
|
func (ka *cecpq1KeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
|
|
ka.curve = &cecpq1Curve{}
|
|
publicKey, err := ka.curve.offer(config.rand())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if config.Bugs.CECPQ1BadX25519Part {
|
|
publicKey[0] ^= 1
|
|
}
|
|
if config.Bugs.CECPQ1BadNewhopePart {
|
|
publicKey[32] ^= 1
|
|
publicKey[33] ^= 1
|
|
publicKey[34] ^= 1
|
|
publicKey[35] ^= 1
|
|
}
|
|
|
|
var params []byte
|
|
params = append(params, byte(len(publicKey)>>8))
|
|
params = append(params, byte(len(publicKey)&0xff))
|
|
params = append(params, publicKey[:]...)
|
|
|
|
return ka.auth.signParameters(config, cert, clientHello, hello, params)
|
|
}
|
|
|
|
func (ka *cecpq1KeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
|
|
if len(ckx.ciphertext) < 2 {
|
|
return nil, errClientKeyExchange
|
|
}
|
|
peerKeyLen := int(ckx.ciphertext[0])<<8 + int(ckx.ciphertext[1])
|
|
peerKey := ckx.ciphertext[2:]
|
|
if peerKeyLen != len(peerKey) {
|
|
return nil, errClientKeyExchange
|
|
}
|
|
return ka.curve.finish(peerKey)
|
|
}
|
|
|
|
func (ka *cecpq1KeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
|
|
if len(skx.key) < 2 {
|
|
return errServerKeyExchange
|
|
}
|
|
peerKeyLen := int(skx.key[0])<<8 + int(skx.key[1])
|
|
// Save the peer key for later.
|
|
if len(skx.key) < 2+peerKeyLen {
|
|
return errServerKeyExchange
|
|
}
|
|
ka.peerKey = skx.key[2 : 2+peerKeyLen]
|
|
if peerKeyLen != len(ka.peerKey) {
|
|
return errServerKeyExchange
|
|
}
|
|
|
|
// Check the signature.
|
|
params := skx.key[:2+peerKeyLen]
|
|
sig := skx.key[2+peerKeyLen:]
|
|
return ka.auth.verifyParameters(config, clientHello, serverHello, cert, params, sig)
|
|
}
|
|
|
|
func (ka *cecpq1KeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
|
|
curve := &cecpq1Curve{}
|
|
publicKey, preMasterSecret, err := curve.accept(config.rand(), ka.peerKey)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
if config.Bugs.CECPQ1BadX25519Part {
|
|
publicKey[0] ^= 1
|
|
}
|
|
if config.Bugs.CECPQ1BadNewhopePart {
|
|
publicKey[32] ^= 1
|
|
publicKey[33] ^= 1
|
|
publicKey[34] ^= 1
|
|
publicKey[35] ^= 1
|
|
}
|
|
|
|
ckx := new(clientKeyExchangeMsg)
|
|
ckx.ciphertext = append(ckx.ciphertext, byte(len(publicKey)>>8))
|
|
ckx.ciphertext = append(ckx.ciphertext, byte(len(publicKey)&0xff))
|
|
ckx.ciphertext = append(ckx.ciphertext, publicKey[:]...)
|
|
|
|
return preMasterSecret, ckx, nil
|
|
}
|
|
|
|
func (ka *cecpq1KeyAgreement) peerSignatureAlgorithm() signatureAlgorithm {
|
|
if auth, ok := ka.auth.(*signedKeyAgreement); ok {
|
|
return auth.peerSignatureAlgorithm
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// dheRSAKeyAgreement implements a TLS key agreement where the server generates
|
|
// an ephemeral Diffie-Hellman public/private key pair and signs it. The
|
|
// pre-master secret is then calculated using Diffie-Hellman.
|
|
type dheKeyAgreement struct {
|
|
auth keyAgreementAuthentication
|
|
p, g *big.Int
|
|
yTheirs *big.Int
|
|
xOurs *big.Int
|
|
}
|
|
|
|
func (ka *dheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
|
|
var q *big.Int
|
|
if p := config.Bugs.DHGroupPrime; p != nil {
|
|
ka.p = p
|
|
ka.g = big.NewInt(2)
|
|
q = p
|
|
} else {
|
|
// 2048-bit MODP Group with 256-bit Prime Order Subgroup (RFC
|
|
// 5114, Section 2.3)
|
|
ka.p, _ = new(big.Int).SetString("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597", 16)
|
|
ka.g, _ = new(big.Int).SetString("3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659", 16)
|
|
q, _ = new(big.Int).SetString("8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3", 16)
|
|
}
|
|
|
|
var err error
|
|
ka.xOurs, err = rand.Int(config.rand(), q)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
yOurs := new(big.Int).Exp(ka.g, ka.xOurs, ka.p)
|
|
|
|
// http://tools.ietf.org/html/rfc5246#section-7.4.3
|
|
pBytes := ka.p.Bytes()
|
|
gBytes := ka.g.Bytes()
|
|
yBytes := yOurs.Bytes()
|
|
serverDHParams := make([]byte, 0, 2+len(pBytes)+2+len(gBytes)+2+len(yBytes))
|
|
serverDHParams = append(serverDHParams, byte(len(pBytes)>>8), byte(len(pBytes)))
|
|
serverDHParams = append(serverDHParams, pBytes...)
|
|
serverDHParams = append(serverDHParams, byte(len(gBytes)>>8), byte(len(gBytes)))
|
|
serverDHParams = append(serverDHParams, gBytes...)
|
|
serverDHParams = append(serverDHParams, byte(len(yBytes)>>8), byte(len(yBytes)))
|
|
serverDHParams = append(serverDHParams, yBytes...)
|
|
|
|
return ka.auth.signParameters(config, cert, clientHello, hello, serverDHParams)
|
|
}
|
|
|
|
func (ka *dheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
|
|
if len(ckx.ciphertext) < 2 {
|
|
return nil, errClientKeyExchange
|
|
}
|
|
yLen := (int(ckx.ciphertext[0]) << 8) | int(ckx.ciphertext[1])
|
|
if yLen != len(ckx.ciphertext)-2 {
|
|
return nil, errClientKeyExchange
|
|
}
|
|
yTheirs := new(big.Int).SetBytes(ckx.ciphertext[2:])
|
|
if yTheirs.Sign() <= 0 || yTheirs.Cmp(ka.p) >= 0 {
|
|
return nil, errClientKeyExchange
|
|
}
|
|
return new(big.Int).Exp(yTheirs, ka.xOurs, ka.p).Bytes(), nil
|
|
}
|
|
|
|
func (ka *dheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
|
|
// Read dh_p
|
|
k := skx.key
|
|
if len(k) < 2 {
|
|
return errServerKeyExchange
|
|
}
|
|
pLen := (int(k[0]) << 8) | int(k[1])
|
|
k = k[2:]
|
|
if len(k) < pLen {
|
|
return errServerKeyExchange
|
|
}
|
|
ka.p = new(big.Int).SetBytes(k[:pLen])
|
|
k = k[pLen:]
|
|
|
|
// Read dh_g
|
|
if len(k) < 2 {
|
|
return errServerKeyExchange
|
|
}
|
|
gLen := (int(k[0]) << 8) | int(k[1])
|
|
k = k[2:]
|
|
if len(k) < gLen {
|
|
return errServerKeyExchange
|
|
}
|
|
ka.g = new(big.Int).SetBytes(k[:gLen])
|
|
k = k[gLen:]
|
|
|
|
// Read dh_Ys
|
|
if len(k) < 2 {
|
|
return errServerKeyExchange
|
|
}
|
|
yLen := (int(k[0]) << 8) | int(k[1])
|
|
k = k[2:]
|
|
if len(k) < yLen {
|
|
return errServerKeyExchange
|
|
}
|
|
ka.yTheirs = new(big.Int).SetBytes(k[:yLen])
|
|
k = k[yLen:]
|
|
if ka.yTheirs.Sign() <= 0 || ka.yTheirs.Cmp(ka.p) >= 0 {
|
|
return errServerKeyExchange
|
|
}
|
|
|
|
if l := config.Bugs.RequireDHPublicValueLen; l != 0 && l != yLen {
|
|
return fmt.Errorf("RequireDHPublicValueLen set to %d, but server's public value was %d bytes on the wire and %d bytes if minimal", l, yLen, (ka.yTheirs.BitLen()+7)/8)
|
|
}
|
|
|
|
sig := k
|
|
serverDHParams := skx.key[:len(skx.key)-len(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) {
|
|
if ka.p == nil || ka.g == nil || ka.yTheirs == nil {
|
|
return nil, nil, errors.New("missing ServerKeyExchange message")
|
|
}
|
|
|
|
xOurs, err := rand.Int(config.rand(), ka.p)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
preMasterSecret := new(big.Int).Exp(ka.yTheirs, xOurs, ka.p).Bytes()
|
|
|
|
yOurs := new(big.Int).Exp(ka.g, xOurs, ka.p)
|
|
yBytes := yOurs.Bytes()
|
|
ckx := new(clientKeyExchangeMsg)
|
|
ckx.ciphertext = make([]byte, 2+len(yBytes))
|
|
ckx.ciphertext[0] = byte(len(yBytes) >> 8)
|
|
ckx.ciphertext[1] = byte(len(yBytes))
|
|
copy(ckx.ciphertext[2:], yBytes)
|
|
|
|
return preMasterSecret, ckx, nil
|
|
}
|
|
|
|
func (ka *dheKeyAgreement) peerSignatureAlgorithm() signatureAlgorithm {
|
|
if auth, ok := ka.auth.(*signedKeyAgreement); ok {
|
|
return auth.peerSignatureAlgorithm
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
func (ka *nilKeyAgreement) peerSignatureAlgorithm() signatureAlgorithm {
|
|
return 0
|
|
}
|
|
|
|
// 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)))
|
|
out = append(out, otherSecret...)
|
|
out = append(out, byte(len(psk)>>8), byte(len(psk)))
|
|
out = append(out, psk...)
|
|
return out
|
|
}
|
|
|
|
// 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) {
|
|
// 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) {
|
|
return nil, errClientKeyExchange
|
|
}
|
|
identity := string(ckx.ciphertext[2 : 2+identityLen])
|
|
|
|
if identity != config.PreSharedKeyIdentity {
|
|
return nil, errors.New("tls: unexpected identity")
|
|
}
|
|
|
|
if config.PreSharedKey == nil {
|
|
return nil, errors.New("tls: pre-shared key not configured")
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
func (ka *pskKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
|
|
if len(skx.key) < 2 {
|
|
return errServerKeyExchange
|
|
}
|
|
identityLen := (int(skx.key[0]) << 8) | int(skx.key[1])
|
|
if 2+identityLen > len(skx.key) {
|
|
return errServerKeyExchange
|
|
}
|
|
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) {
|
|
// The server only sends an identity hint but, for purposes of
|
|
// test code, the server always sends the hint and it is
|
|
// required to match.
|
|
if ka.identityHint != config.PreSharedKeyIdentity {
|
|
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 = append(bytes, baseCkx.ciphertext...)
|
|
|
|
if config.PreSharedKey == nil {
|
|
return nil, nil, errors.New("tls: pre-shared key not configured")
|
|
}
|
|
if otherSecret == nil {
|
|
otherSecret = make([]byte, len(config.PreSharedKey))
|
|
}
|
|
return makePSKPremaster(otherSecret, config.PreSharedKey), ckx, nil
|
|
}
|
|
|
|
func (ka *pskKeyAgreement) peerSignatureAlgorithm() signatureAlgorithm {
|
|
return 0
|
|
}
|