aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/crypto/tls
diff options
context:
space:
mode:
authorAdam Langley <agl@golang.org>2014-08-29 12:36:30 -0700
committerAdam Langley <agl@golang.org>2014-08-29 12:36:30 -0700
commit7f2e68e9822ce8736d66035d0a3ed3677c2db459 (patch)
treed33066c0b1d4776980140aed02513bef7dfdc9af /src/pkg/crypto/tls
parent7dc2b3cbd1ecc4d703a403924a77d01c8d01bd5a (diff)
downloadgo-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.go7
-rw-r--r--src/pkg/crypto/tls/handshake_client.go30
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)