Commit 7b7dac5e authored by Joel Sing's avatar Joel Sing Committed by Adam Langley

crypto/tls: Add support for ECDHE-ECDSA

Add support for ECDHE-ECDSA (RFC4492), which uses an ephemeral server
key pair to perform ECDH with ECDSA signatures. Like ECDHE-RSA,
ECDHE-ECDSA also provides PFS.

R=agl
CC=golang-dev
https://golang.org/cl/7006047
parent 85a7c090
...@@ -77,5 +77,8 @@ func RegisterHash(h Hash, f func() hash.Hash) { ...@@ -77,5 +77,8 @@ func RegisterHash(h Hash, f func() hash.Hash) {
hashes[h] = f hashes[h] = f
} }
// PublicKey represents a public key using an unspecified algorithm.
type PublicKey interface{}
// PrivateKey represents a private key using an unspecified algorithm. // PrivateKey represents a private key using an unspecified algorithm.
type PrivateKey interface{} type PrivateKey interface{}
...@@ -55,8 +55,11 @@ var cipherSuites = []*cipherSuite{ ...@@ -55,8 +55,11 @@ var cipherSuites = []*cipherSuite{
// Ciphersuite order is chosen so that ECDHE comes before plain RSA // Ciphersuite order is chosen so that ECDHE comes before plain RSA
// and RC4 comes before AES (because of the Lucky13 attack). // and RC4 comes before AES (because of the Lucky13 attack).
{TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, true, cipherRC4, macSHA1}, {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, true, cipherRC4, macSHA1},
{TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, true, cipherRC4, macSHA1},
{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1}, {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1},
{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, true, cipherAES, macSHA1},
{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1}, {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1},
{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, true, cipherAES, macSHA1},
{TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, false, cipherRC4, macSHA1}, {TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, false, cipherRC4, macSHA1},
{TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, false, cipherAES, macSHA1}, {TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, false, cipherAES, macSHA1},
{TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, false, cipherAES, macSHA1}, {TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, false, cipherAES, macSHA1},
...@@ -161,8 +164,16 @@ func rsaKA(version uint16) keyAgreement { ...@@ -161,8 +164,16 @@ func rsaKA(version uint16) keyAgreement {
return rsaKeyAgreement{} return rsaKeyAgreement{}
} }
func ecdheECDSAKA(version uint16) keyAgreement {
return &ecdheKeyAgreement{
sigType: signatureECDSA,
version: version,
}
}
func ecdheRSAKA(version uint16) keyAgreement { func ecdheRSAKA(version uint16) keyAgreement {
return &ecdheRSAKeyAgreement{ return &ecdheKeyAgreement{
sigType: signatureRSA,
version: version, version: version,
} }
} }
...@@ -190,6 +201,9 @@ const ( ...@@ -190,6 +201,9 @@ const (
TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a
TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f
TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035 TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xc007
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xc009
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xc00a
TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011 TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"crypto/rand" "crypto/rand"
"crypto/x509" "crypto/x509"
"io" "io"
"math/big"
"strings" "strings"
"sync" "sync"
"time" "time"
...@@ -98,6 +99,12 @@ const ( ...@@ -98,6 +99,12 @@ const (
certTypeDSSSign = 2 // A certificate containing a DSA key certTypeDSSSign = 2 // A certificate containing a DSA key
certTypeRSAFixedDH = 3 // A certificate containing a static DH key certTypeRSAFixedDH = 3 // A certificate containing a static DH key
certTypeDSSFixedDH = 4 // A certificate containing a static DH key certTypeDSSFixedDH = 4 // A certificate containing a static DH key
// See RFC4492 sections 3 and 5.5.
certTypeECDSASign = 64 // A certificate containing an ECDSA-capable public key, signed with ECDSA.
certTypeRSAFixedECDH = 65 // A certificate containing an ECDH-capable public key, signed with RSA.
certTypeECDSAFixedECDH = 66 // A certificate containing an ECDH-capable public key, signed with ECDSA.
// Rest of these are reserved by the TLS spec // Rest of these are reserved by the TLS spec
) )
...@@ -120,10 +127,11 @@ type signatureAndHash struct { ...@@ -120,10 +127,11 @@ type signatureAndHash struct {
} }
// supportedSignatureAlgorithms contains the signature and hash algorithms that // supportedSignatureAlgorithms contains the signature and hash algorithms that
// the code will adverse as supported both in a TLS 1.2 ClientHello and // the code can advertise as supported both in a TLS 1.2 ClientHello and
// CertificateRequest. // CertificateRequest.
var supportedSignatureAlgorithms = []signatureAndHash{ var supportedSignatureAlgorithms = []signatureAndHash{
{hashSHA256, signatureRSA}, {hashSHA256, signatureRSA},
{hashSHA256, signatureECDSA},
} }
// ConnectionState records basic TLS details about the connection. // ConnectionState records basic TLS details about the connection.
...@@ -372,7 +380,7 @@ func (c *Config) BuildNameToCertificate() { ...@@ -372,7 +380,7 @@ func (c *Config) BuildNameToCertificate() {
// A Certificate is a chain of one or more certificates, leaf first. // A Certificate is a chain of one or more certificates, leaf first.
type Certificate struct { type Certificate struct {
Certificate [][]byte Certificate [][]byte
PrivateKey crypto.PrivateKey // supported types: *rsa.PrivateKey PrivateKey crypto.PrivateKey // supported types: *rsa.PrivateKey, *ecdsa.PrivateKey
// OCSPStaple contains an optional OCSP response which will be served // OCSPStaple contains an optional OCSP response which will be served
// to clients that request it. // to clients that request it.
OCSPStaple []byte OCSPStaple []byte
...@@ -395,6 +403,13 @@ type handshakeMessage interface { ...@@ -395,6 +403,13 @@ type handshakeMessage interface {
unmarshal([]byte) bool unmarshal([]byte) bool
} }
// TODO(jsing): Make these available to both crypto/x509 and crypto/tls.
type dsaSignature struct {
R, S *big.Int
}
type ecdsaSignature dsaSignature
var emptyConfig Config var emptyConfig Config
func defaultConfig() *Config { func defaultConfig() *Config {
......
...@@ -6,9 +6,11 @@ package tls ...@@ -6,9 +6,11 @@ package tls
import ( import (
"bytes" "bytes"
"crypto/ecdsa"
"crypto/rsa" "crypto/rsa"
"crypto/subtle" "crypto/subtle"
"crypto/x509" "crypto/x509"
"encoding/asn1"
"errors" "errors"
"io" "io"
"strconv" "strconv"
...@@ -124,7 +126,10 @@ func (c *Conn) clientHandshake() error { ...@@ -124,7 +126,10 @@ func (c *Conn) clientHandshake() error {
} }
} }
if _, ok := certs[0].PublicKey.(*rsa.PublicKey); !ok { switch certs[0].PublicKey.(type) {
case *rsa.PublicKey, *ecdsa.PublicKey:
break
default:
return c.sendAlert(alertUnsupportedCertificate) return c.sendAlert(alertUnsupportedCertificate)
} }
...@@ -187,12 +192,13 @@ func (c *Conn) clientHandshake() error { ...@@ -187,12 +192,13 @@ func (c *Conn) clientHandshake() error {
finishedHash.Write(certReq.marshal()) finishedHash.Write(certReq.marshal())
// For now, we only know how to sign challenges with RSA var rsaAvail, ecdsaAvail bool
rsaAvail := false
for _, certType := range certReq.certificateTypes { for _, certType := range certReq.certificateTypes {
if certType == certTypeRSASign { switch certType {
case certTypeRSASign:
rsaAvail = true rsaAvail = true
break case certTypeECDSASign:
ecdsaAvail = true
} }
} }
...@@ -201,7 +207,7 @@ func (c *Conn) clientHandshake() error { ...@@ -201,7 +207,7 @@ func (c *Conn) clientHandshake() error {
// certReq.certificateAuthorities // certReq.certificateAuthorities
findCert: findCert:
for i, chain := range c.config.Certificates { for i, chain := range c.config.Certificates {
if !rsaAvail { if !rsaAvail && !ecdsaAvail {
continue continue
} }
...@@ -216,7 +222,10 @@ func (c *Conn) clientHandshake() error { ...@@ -216,7 +222,10 @@ func (c *Conn) clientHandshake() error {
} }
} }
if x509Cert.PublicKeyAlgorithm != x509.RSA { switch {
case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
default:
continue findCert continue findCert
} }
...@@ -271,9 +280,21 @@ func (c *Conn) clientHandshake() error { ...@@ -271,9 +280,21 @@ func (c *Conn) clientHandshake() error {
} }
if chainToSend != nil { if chainToSend != nil {
var signed []byte
certVerify := new(certificateVerifyMsg) certVerify := new(certificateVerifyMsg)
digest, hashFunc := finishedHash.hashForClientCertificate() switch key := c.config.Certificates[0].PrivateKey.(type) {
signed, err := rsa.SignPKCS1v15(c.config.rand(), c.config.Certificates[0].PrivateKey.(*rsa.PrivateKey), hashFunc, digest) case *ecdsa.PrivateKey:
digest, _ := finishedHash.hashForClientCertificate(signatureECDSA)
r, s, err := ecdsa.Sign(c.config.rand(), key, digest)
if err == nil {
signed, err = asn1.Marshal(ecdsaSignature{r, s})
}
case *rsa.PrivateKey:
digest, hashFunc := finishedHash.hashForClientCertificate(signatureRSA)
signed, err = rsa.SignPKCS1v15(c.config.rand(), key, hashFunc, digest)
default:
err = errors.New("unknown private key type")
}
if err != nil { if err != nil {
return c.sendAlert(alertInternalError) return c.sendAlert(alertInternalError)
} }
......
This diff is collapsed.
...@@ -5,9 +5,12 @@ ...@@ -5,9 +5,12 @@
package tls package tls
import ( import (
"crypto"
"crypto/ecdsa"
"crypto/rsa" "crypto/rsa"
"crypto/subtle" "crypto/subtle"
"crypto/x509" "crypto/x509"
"encoding/asn1"
"errors" "errors"
"io" "io"
) )
...@@ -305,7 +308,10 @@ func (hs *serverHandshakeState) doFullHandshake() error { ...@@ -305,7 +308,10 @@ func (hs *serverHandshakeState) doFullHandshake() error {
if config.ClientAuth >= RequestClientCert { if config.ClientAuth >= RequestClientCert {
// Request a client certificate // Request a client certificate
certReq := new(certificateRequestMsg) certReq := new(certificateRequestMsg)
certReq.certificateTypes = []byte{certTypeRSASign} certReq.certificateTypes = []byte{
byte(certTypeRSASign),
byte(certTypeECDSASign),
}
if c.vers >= VersionTLS12 { if c.vers >= VersionTLS12 {
certReq.hasSignatureAndHash = true certReq.hasSignatureAndHash = true
certReq.signatureAndHashes = supportedSignatureAlgorithms certReq.signatureAndHashes = supportedSignatureAlgorithms
...@@ -327,7 +333,7 @@ func (hs *serverHandshakeState) doFullHandshake() error { ...@@ -327,7 +333,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
hs.finishedHash.Write(helloDone.marshal()) hs.finishedHash.Write(helloDone.marshal())
c.writeRecord(recordTypeHandshake, helloDone.marshal()) c.writeRecord(recordTypeHandshake, helloDone.marshal())
var pub *rsa.PublicKey // public key for client auth, if any var pub crypto.PublicKey // public key for client auth, if any
msg, err := c.readHandshake() msg, err := c.readHandshake()
if err != nil { if err != nil {
...@@ -372,7 +378,7 @@ func (hs *serverHandshakeState) doFullHandshake() error { ...@@ -372,7 +378,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
// If we received a client cert in response to our certificate request message, // If we received a client cert in response to our certificate request message,
// the client will send us a certificateVerifyMsg immediately after the // the client will send us a certificateVerifyMsg immediately after the
// clientKeyExchangeMsg. This message is a MD5SHA1 digest of all preceding // clientKeyExchangeMsg. This message is a digest of all preceding
// handshake-layer messages that is signed using the private key corresponding // handshake-layer messages that is signed using the private key corresponding
// to the client's certificate. This allows us to verify that the client is in // to the client's certificate. This allows us to verify that the client is in
// possession of the private key of the certificate. // possession of the private key of the certificate.
...@@ -386,8 +392,25 @@ func (hs *serverHandshakeState) doFullHandshake() error { ...@@ -386,8 +392,25 @@ func (hs *serverHandshakeState) doFullHandshake() error {
return c.sendAlert(alertUnexpectedMessage) return c.sendAlert(alertUnexpectedMessage)
} }
digest, hashFunc := hs.finishedHash.hashForClientCertificate() switch key := pub.(type) {
err = rsa.VerifyPKCS1v15(pub, hashFunc, digest, certVerify.signature) case *ecdsa.PublicKey:
ecdsaSig := new(ecdsaSignature)
if _, err = asn1.Unmarshal(certVerify.signature, ecdsaSig); err != nil {
break
}
if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
err = errors.New("ECDSA signature contained zero or negative values")
break
}
digest, _ := hs.finishedHash.hashForClientCertificate(signatureECDSA)
if !ecdsa.Verify(key, digest, ecdsaSig.R, ecdsaSig.S) {
err = errors.New("ECDSA verification failure")
break
}
case *rsa.PublicKey:
digest, hashFunc := hs.finishedHash.hashForClientCertificate(signatureRSA)
err = rsa.VerifyPKCS1v15(key, hashFunc, digest, certVerify.signature)
}
if err != nil { if err != nil {
c.sendAlert(alertBadCertificate) c.sendAlert(alertBadCertificate)
return errors.New("could not validate signature of connection nonces: " + err.Error()) return errors.New("could not validate signature of connection nonces: " + err.Error())
...@@ -507,7 +530,7 @@ func (hs *serverHandshakeState) sendFinished() error { ...@@ -507,7 +530,7 @@ func (hs *serverHandshakeState) sendFinished() error {
// processCertsFromClient takes a chain of client certificates either from a // processCertsFromClient takes a chain of client certificates either from a
// Certificates message or from a sessionState and verifies them. It returns // Certificates message or from a sessionState and verifies them. It returns
// the public key of the leaf certificate. // the public key of the leaf certificate.
func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (*rsa.PublicKey, error) { func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (crypto.PublicKey, error) {
c := hs.c c := hs.c
hs.certsFromClient = certificates hs.certsFromClient = certificates
...@@ -554,8 +577,11 @@ func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (* ...@@ -554,8 +577,11 @@ func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (*
} }
if len(certs) > 0 { if len(certs) > 0 {
pub, ok := certs[0].PublicKey.(*rsa.PublicKey) var pub crypto.PublicKey
if !ok { switch key := certs[0].PublicKey.(type) {
case *ecdsa.PublicKey, *rsa.PublicKey:
pub = key
default:
return nil, c.sendAlert(alertUnsupportedCertificate) return nil, c.sendAlert(alertUnsupportedCertificate)
} }
c.peerCertificates = certs c.peerCertificates = certs
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -6,12 +6,14 @@ package tls ...@@ -6,12 +6,14 @@ package tls
import ( import (
"crypto" "crypto"
"crypto/ecdsa"
"crypto/elliptic" "crypto/elliptic"
"crypto/md5" "crypto/md5"
"crypto/rsa" "crypto/rsa"
"crypto/sha1" "crypto/sha1"
"crypto/sha256" "crypto/sha256"
"crypto/x509" "crypto/x509"
"encoding/asn1"
"errors" "errors"
"io" "io"
"math/big" "math/big"
...@@ -83,6 +85,15 @@ func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello ...@@ -83,6 +85,15 @@ func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello
return preMasterSecret, ckx, nil return preMasterSecret, ckx, nil
} }
// sha1Hash calculates a SHA1 hash over the given byte slices.
func sha1Hash(slices [][]byte) []byte {
hsha1 := sha1.New()
for _, slice := range slices {
hsha1.Write(slice)
}
return hsha1.Sum(nil)
}
// md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the // md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the
// concatenation of an MD5 and SHA1 hash. // concatenation of an MD5 and SHA1 hash.
func md5SHA1Hash(slices [][]byte) []byte { func md5SHA1Hash(slices [][]byte) []byte {
...@@ -92,12 +103,7 @@ func md5SHA1Hash(slices [][]byte) []byte { ...@@ -92,12 +103,7 @@ func md5SHA1Hash(slices [][]byte) []byte {
hmd5.Write(slice) hmd5.Write(slice)
} }
copy(md5sha1, hmd5.Sum(nil)) copy(md5sha1, hmd5.Sum(nil))
copy(md5sha1[md5.Size:], sha1Hash(slices))
hsha1 := sha1.New()
for _, slice := range slices {
hsha1.Write(slice)
}
copy(md5sha1[md5.Size:], hsha1.Sum(nil))
return md5sha1 return md5sha1
} }
...@@ -112,24 +118,29 @@ func sha256Hash(slices [][]byte) []byte { ...@@ -112,24 +118,29 @@ func sha256Hash(slices [][]byte) []byte {
// hashForServerKeyExchange hashes the given slices and returns their digest // hashForServerKeyExchange hashes the given slices and returns their digest
// and the identifier of the hash function used. // and the identifier of the hash function used.
func hashForServerKeyExchange(version uint16, slices ...[]byte) ([]byte, crypto.Hash) { func hashForServerKeyExchange(sigType uint8, version uint16, slices ...[]byte) ([]byte, crypto.Hash) {
if version >= VersionTLS12 { if version >= VersionTLS12 {
return sha256Hash(slices), crypto.SHA256 return sha256Hash(slices), crypto.SHA256
} }
if sigType == signatureECDSA {
return sha1Hash(slices), crypto.SHA1
}
return md5SHA1Hash(slices), crypto.MD5SHA1 return md5SHA1Hash(slices), crypto.MD5SHA1
} }
// ecdheRSAKeyAgreement implements a TLS key agreement where the server // ecdheRSAKeyAgreement implements a TLS key agreement where the server
// generates a ephemeral EC public/private key pair and signs it. The // generates a ephemeral EC public/private key pair and signs it. The
// pre-master secret is then calculated using ECDH. // pre-master secret is then calculated using ECDH. The signature may
type ecdheRSAKeyAgreement struct { // either be ECDSA or RSA.
type ecdheKeyAgreement struct {
version uint16 version uint16
sigType uint8
privateKey []byte privateKey []byte
curve elliptic.Curve curve elliptic.Curve
x, y *big.Int x, y *big.Int
} }
func (ka *ecdheRSAKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
var curveid uint16 var curveid uint16
Curve: Curve:
...@@ -170,11 +181,31 @@ Curve: ...@@ -170,11 +181,31 @@ Curve:
serverECDHParams[3] = byte(len(ecdhePublic)) serverECDHParams[3] = byte(len(ecdhePublic))
copy(serverECDHParams[4:], ecdhePublic) copy(serverECDHParams[4:], ecdhePublic)
digest, hashFunc := hashForServerKeyExchange(ka.version, clientHello.random, hello.random, serverECDHParams) digest, hashFunc := hashForServerKeyExchange(ka.sigType, ka.version, clientHello.random, hello.random, serverECDHParams)
sig, err := rsa.SignPKCS1v15(config.rand(), cert.PrivateKey.(*rsa.PrivateKey), hashFunc, digest) var sig []byte
switch ka.sigType {
case signatureECDSA:
privKey, ok := cert.PrivateKey.(*ecdsa.PrivateKey)
if !ok {
return nil, errors.New("ECDHE ECDSA requires an ECDSA server private key")
}
r, s, err := ecdsa.Sign(config.rand(), privKey, digest)
if err != nil {
return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
}
sig, err = asn1.Marshal(ecdsaSignature{r, s})
case signatureRSA:
privKey, ok := cert.PrivateKey.(*rsa.PrivateKey)
if !ok {
return nil, errors.New("ECDHE RSA requires a RSA server private key")
}
sig, err = rsa.SignPKCS1v15(config.rand(), privKey, hashFunc, digest)
if err != nil { if err != nil {
return nil, errors.New("failed to sign ECDHE parameters: " + err.Error()) return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
} }
default:
return nil, errors.New("unknown ECDHE signature algorithm")
}
skx := new(serverKeyExchangeMsg) skx := new(serverKeyExchangeMsg)
sigAndHashLen := 0 sigAndHashLen := 0
...@@ -186,7 +217,7 @@ Curve: ...@@ -186,7 +217,7 @@ Curve:
k := skx.key[len(serverECDHParams):] k := skx.key[len(serverECDHParams):]
if ka.version >= VersionTLS12 { if ka.version >= VersionTLS12 {
k[0] = hashSHA256 k[0] = hashSHA256
k[1] = signatureRSA k[1] = ka.sigType
k = k[2:] k = k[2:]
} }
k[0] = byte(len(sig) >> 8) k[0] = byte(len(sig) >> 8)
...@@ -196,7 +227,7 @@ Curve: ...@@ -196,7 +227,7 @@ Curve:
return skx, nil return skx, nil
} }
func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { 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 { if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
return nil, errors.New("bad ClientKeyExchange") return nil, errors.New("bad ClientKeyExchange")
} }
...@@ -214,7 +245,7 @@ func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, cert *C ...@@ -214,7 +245,7 @@ func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, cert *C
var errServerKeyExchange = errors.New("invalid ServerKeyExchange") var errServerKeyExchange = errors.New("invalid ServerKeyExchange")
func (ka *ecdheRSAKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
if len(skx.key) < 4 { if len(skx.key) < 4 {
return errServerKeyExchange return errServerKeyExchange
} }
...@@ -261,11 +292,39 @@ func (ka *ecdheRSAKeyAgreement) processServerKeyExchange(config *Config, clientH ...@@ -261,11 +292,39 @@ func (ka *ecdheRSAKeyAgreement) processServerKeyExchange(config *Config, clientH
} }
sig = sig[2:] sig = sig[2:]
digest, hashFunc := hashForServerKeyExchange(ka.version, clientHello.random, serverHello.random, serverECDHParams) digest, hashFunc := hashForServerKeyExchange(ka.sigType, ka.version, clientHello.random, serverHello.random, serverECDHParams)
return rsa.VerifyPKCS1v15(cert.PublicKey.(*rsa.PublicKey), hashFunc, digest, sig) switch ka.sigType {
case signatureECDSA:
pubKey, ok := cert.PublicKey.(*ecdsa.PublicKey)
if !ok {
return errors.New("ECDHE ECDSA requires a ECDSA server public key")
}
ecdsaSig := new(ecdsaSignature)
if _, err := asn1.Unmarshal(sig, ecdsaSig); err != nil {
return err
}
if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
return errors.New("ECDSA signature contained zero or negative values")
}
if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) {
return errors.New("ECDSA verification failure")
}
case signatureRSA:
pubKey, ok := cert.PublicKey.(*rsa.PublicKey)
if !ok {
return errors.New("ECDHE RSA requires a RSA server public key")
}
if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, digest, sig); err != nil {
return err
}
default:
return errors.New("unknown ECDHE signature algorithm")
}
return nil
} }
func (ka *ecdheRSAKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
if ka.curve == nil { if ka.curve == nil {
return nil, nil, errors.New("missing ServerKeyExchange message") return nil, nil, errors.New("missing ServerKeyExchange message")
} }
......
...@@ -274,11 +274,15 @@ func (h finishedHash) serverSum(masterSecret []byte) []byte { ...@@ -274,11 +274,15 @@ func (h finishedHash) serverSum(masterSecret []byte) []byte {
// hashForClientCertificate returns a digest and hash function identifier // hashForClientCertificate returns a digest and hash function identifier
// suitable for signing by a TLS client certificate. // suitable for signing by a TLS client certificate.
func (h finishedHash) hashForClientCertificate() ([]byte, crypto.Hash) { func (h finishedHash) hashForClientCertificate(sigType uint8) ([]byte, crypto.Hash) {
if h.version >= VersionTLS12 { if h.version >= VersionTLS12 {
digest := h.server.Sum(nil) digest := h.server.Sum(nil)
return digest, crypto.SHA256 return digest, crypto.SHA256
} }
if sigType == signatureECDSA {
digest := h.server.Sum(nil)
return digest, crypto.SHA1
}
digest := make([]byte, 0, 36) digest := make([]byte, 0, 36)
digest = h.serverMD5.Sum(digest) digest = h.serverMD5.Sum(digest)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment