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
This commit is contained in:
parent
16b2f42015
commit
b88cd69926
@ -487,7 +487,12 @@ 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, *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
|
// OCSPStaple contains an optional OCSP response which will be served
|
||||||
// to clients that request it.
|
// to clients that request it.
|
||||||
OCSPStaple []byte
|
OCSPStaple []byte
|
||||||
|
@ -6,11 +6,11 @@ package tls
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/asn1"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -345,8 +345,8 @@ func (hs *clientHandshakeState) doFullHandshake() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We need to search our list of client certs for one
|
// We need to search our list of client certs for one
|
||||||
// where SignatureAlgorithm is RSA and the Issuer is in
|
// where SignatureAlgorithm is acceptable to the server and the
|
||||||
// certReq.certificateAuthorities
|
// Issuer is in certReq.certificateAuthorities
|
||||||
findCert:
|
findCert:
|
||||||
for i, chain := range c.config.Certificates {
|
for i, chain := range c.config.Certificates {
|
||||||
if !rsaAvail && !ecdsaAvail {
|
if !rsaAvail && !ecdsaAvail {
|
||||||
@ -373,7 +373,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
|
|||||||
|
|
||||||
if len(certReq.certificateAuthorities) == 0 {
|
if len(certReq.certificateAuthorities) == 0 {
|
||||||
// they gave us an empty list, so just take the
|
// 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
|
chainToSend = &chain
|
||||||
break findCert
|
break findCert
|
||||||
}
|
}
|
||||||
@ -428,22 +428,24 @@ func (hs *clientHandshakeState) doFullHandshake() error {
|
|||||||
hasSignatureAndHash: c.vers >= VersionTLS12,
|
hasSignatureAndHash: c.vers >= VersionTLS12,
|
||||||
}
|
}
|
||||||
|
|
||||||
switch key := c.config.Certificates[0].PrivateKey.(type) {
|
key, ok := chainToSend.PrivateKey.(crypto.Signer)
|
||||||
case *ecdsa.PrivateKey:
|
if !ok {
|
||||||
digest, _, hashId := hs.finishedHash.hashForClientCertificate(signatureECDSA)
|
c.sendAlert(alertInternalError)
|
||||||
r, s, err := ecdsa.Sign(c.config.rand(), key, digest)
|
return fmt.Errorf("tls: client certificate private key of type %T does not implement crypto.Signer", chainToSend.PrivateKey)
|
||||||
if err == nil {
|
|
||||||
signed, err = asn1.Marshal(ecdsaSignature{r, s})
|
|
||||||
}
|
}
|
||||||
|
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.signature = signatureECDSA
|
||||||
certVerify.signatureAndHash.hash = hashId
|
certVerify.signatureAndHash.hash = hashId
|
||||||
case *rsa.PrivateKey:
|
case *rsa.PublicKey:
|
||||||
digest, hashFunc, hashId := hs.finishedHash.hashForClientCertificate(signatureRSA)
|
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.signature = signatureRSA
|
||||||
certVerify.signatureAndHash.hash = hashId
|
certVerify.signatureAndHash.hash = hashId
|
||||||
default:
|
default:
|
||||||
err = errors.New("unknown private key type")
|
err = fmt.Errorf("tls: unknown client certificate key type: %T", key)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.sendAlert(alertInternalError)
|
c.sendAlert(alertInternalError)
|
||||||
|
Loading…
Reference in New Issue
Block a user