diff options
| author | Adam Langley <agl@golang.org> | 2014-08-29 12:36:30 -0700 |
|---|---|---|
| committer | Adam Langley <agl@golang.org> | 2014-08-29 12:36:30 -0700 |
| commit | 7f2e68e9822ce8736d66035d0a3ed3677c2db459 (patch) | |
| tree | d33066c0b1d4776980140aed02513bef7dfdc9af /src/pkg/crypto/tls | |
| parent | 7dc2b3cbd1ecc4d703a403924a77d01c8d01bd5a (diff) | |
| download | go-7f2e68e9822ce8736d66035d0a3ed3677c2db459.tar.xz | |
crypto: add Signer
Signer is an interface to support opaque private keys.
These keys typically result from being kept in special hardware
(i.e. a TPM) although sometimes operating systems provide a
similar interface using process isolation for security rather
than hardware boundaries.
This changes provides interfaces for representing them and
alters crypto/tls so that client certificates can use
opaque keys.
LGTM=bradfitz
R=bradfitz
CC=golang-codereviews, jdeprez
https://golang.org/cl/114680043
Diffstat (limited to 'src/pkg/crypto/tls')
| -rw-r--r-- | src/pkg/crypto/tls/common.go | 7 | ||||
| -rw-r--r-- | src/pkg/crypto/tls/handshake_client.go | 30 |
2 files changed, 22 insertions, 15 deletions
diff --git a/src/pkg/crypto/tls/common.go b/src/pkg/crypto/tls/common.go index f926d57728..776b70c93c 100644 --- a/src/pkg/crypto/tls/common.go +++ b/src/pkg/crypto/tls/common.go @@ -487,7 +487,12 @@ func (c *Config) BuildNameToCertificate() { // A Certificate is a chain of one or more certificates, leaf first. type Certificate struct { Certificate [][]byte - PrivateKey crypto.PrivateKey // supported types: *rsa.PrivateKey, *ecdsa.PrivateKey + // PrivateKey contains the private key corresponding to the public key + // in Leaf. For a server, this must be a *rsa.PrivateKey or + // *ecdsa.PrivateKey. For a client doing client authentication, this + // can be any type that implements crypto.Signer (which includes RSA + // and ECDSA private keys). + PrivateKey crypto.PrivateKey // OCSPStaple contains an optional OCSP response which will be served // to clients that request it. OCSPStaple []byte diff --git a/src/pkg/crypto/tls/handshake_client.go b/src/pkg/crypto/tls/handshake_client.go index 3d9ef9b14e..7f662e9c9f 100644 --- a/src/pkg/crypto/tls/handshake_client.go +++ b/src/pkg/crypto/tls/handshake_client.go @@ -6,11 +6,11 @@ package tls import ( "bytes" + "crypto" "crypto/ecdsa" "crypto/rsa" "crypto/subtle" "crypto/x509" - "encoding/asn1" "errors" "fmt" "io" @@ -345,8 +345,8 @@ func (hs *clientHandshakeState) doFullHandshake() error { } // We need to search our list of client certs for one - // where SignatureAlgorithm is RSA and the Issuer is in - // certReq.certificateAuthorities + // where SignatureAlgorithm is acceptable to the server and the + // Issuer is in certReq.certificateAuthorities findCert: for i, chain := range c.config.Certificates { if !rsaAvail && !ecdsaAvail { @@ -373,7 +373,7 @@ func (hs *clientHandshakeState) doFullHandshake() error { if len(certReq.certificateAuthorities) == 0 { // they gave us an empty list, so just take the - // first RSA cert from c.config.Certificates + // first cert from c.config.Certificates chainToSend = &chain break findCert } @@ -428,22 +428,24 @@ func (hs *clientHandshakeState) doFullHandshake() error { hasSignatureAndHash: c.vers >= VersionTLS12, } - switch key := c.config.Certificates[0].PrivateKey.(type) { - case *ecdsa.PrivateKey: - digest, _, hashId := hs.finishedHash.hashForClientCertificate(signatureECDSA) - r, s, err := ecdsa.Sign(c.config.rand(), key, digest) - if err == nil { - signed, err = asn1.Marshal(ecdsaSignature{r, s}) - } + key, ok := chainToSend.PrivateKey.(crypto.Signer) + if !ok { + c.sendAlert(alertInternalError) + return fmt.Errorf("tls: client certificate private key of type %T does not implement crypto.Signer", chainToSend.PrivateKey) + } + switch key.Public().(type) { + case *ecdsa.PublicKey: + digest, hashFunc, hashId := hs.finishedHash.hashForClientCertificate(signatureECDSA) + signed, err = key.Sign(c.config.rand(), digest, hashFunc) certVerify.signatureAndHash.signature = signatureECDSA certVerify.signatureAndHash.hash = hashId - case *rsa.PrivateKey: + case *rsa.PublicKey: digest, hashFunc, hashId := hs.finishedHash.hashForClientCertificate(signatureRSA) - signed, err = rsa.SignPKCS1v15(c.config.rand(), key, hashFunc, digest) + signed, err = key.Sign(c.config.rand(), digest, hashFunc) certVerify.signatureAndHash.signature = signatureRSA certVerify.signatureAndHash.hash = hashId default: - err = errors.New("unknown private key type") + err = fmt.Errorf("tls: unknown client certificate key type: %T", key) } if err != nil { c.sendAlert(alertInternalError) |
