Update implementation of draft-ietf-tls-subcerts to draft 02 (#108)
Drops support for delegated credentials with TLS 1.2 and adds the protocol version and signature algorithm to the credential structure.
This commit is contained in:
parent
77d1fbf262
commit
174a68a0fb
36
13.go
36
13.go
@ -405,10 +405,10 @@ func (hs *serverHandshakeState) sendCertificate13() error {
|
||||
}
|
||||
|
||||
// If hs.delegatedCredential is set (see hs.readClientHello()) then the
|
||||
// server is using the delegated credential extension. In TLS 1.3, the DC is
|
||||
// added as an extension to the end-entity certificate, i.e., the last
|
||||
// CertificateEntry of Certificate.certficate_list (see
|
||||
// https://tools.ietf.org/html/draft-ietf-tls-subcerts-01).
|
||||
// server is using the delegated credential extension. The DC is added as an
|
||||
// extension to the end-entity certificate, i.e., the last CertificateEntry
|
||||
// of Certificate.certficate_list. (For details, see
|
||||
// https://tools.ietf.org/html/draft-ietf-tls-subcerts-02.)
|
||||
if len(certEntries) > 0 && hs.clientHello.delegatedCredential && hs.delegatedCredential != nil {
|
||||
certEntries[0].delegatedCredential = hs.delegatedCredential
|
||||
}
|
||||
@ -1051,13 +1051,24 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Receive CertificateVerify message.
|
||||
msg, err = c.readHandshake()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
certVerifyMsg, ok := msg.(*certificateVerifyMsg)
|
||||
if !ok {
|
||||
c.sendAlert(alertUnexpectedMessage)
|
||||
return unexpectedMessageError(certVerifyMsg, msg)
|
||||
}
|
||||
|
||||
// Validate the DC if present. The DC is only processed if the extension was
|
||||
// indicated by the ClientHello; otherwise this call will result in an
|
||||
// "illegal_parameter" alert. The call also asserts that the DC extension
|
||||
// did not appear in the ServerHello.
|
||||
// "illegal_parameter" alert.
|
||||
if len(certMsg.certificates) > 0 {
|
||||
if err := hs.processDelegatedCredentialFromServer(
|
||||
certMsg.certificates[0].delegatedCredential); err != nil {
|
||||
certMsg.certificates[0].delegatedCredential,
|
||||
certVerifyMsg.signatureAlgorithm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -1072,16 +1083,7 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
|
||||
pk = hs.c.verifiedDc.cred.publicKey
|
||||
}
|
||||
|
||||
// Receive CertificateVerify message.
|
||||
msg, err = c.readHandshake()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
certVerifyMsg, ok := msg.(*certificateVerifyMsg)
|
||||
if !ok {
|
||||
c.sendAlert(alertUnexpectedMessage)
|
||||
return unexpectedMessageError(certVerifyMsg, msg)
|
||||
}
|
||||
// Verify the handshake signature.
|
||||
err, alertCode := verifyPeerHandshakeSignature(
|
||||
certVerifyMsg,
|
||||
pk,
|
||||
|
@ -620,16 +620,16 @@ type Config struct {
|
||||
//
|
||||
// This value has no meaning for the server.
|
||||
//
|
||||
// See https://tools.ietf.org/html/draft-ietf-tls-subcerts-01.
|
||||
// See https://tools.ietf.org/html/draft-ietf-tls-subcerts-02.
|
||||
AcceptDelegatedCredential bool
|
||||
|
||||
// GetDelegatedCredential returns a DC and its private key for use in the
|
||||
// delegated credential extension. The inputs to the callback are some
|
||||
// information parsed from the ClientHello, as well as the protocol version
|
||||
// selected by the server. This is necessary because the DC is bound to
|
||||
// selected by the server. This is necessary because the DC is bound to the
|
||||
// protocol version in which it's used. The return value is the raw DC
|
||||
// encoded in the wire format specified in
|
||||
// https://tools.ietf.org/html/draft-ietf-tls-subcerts-01. If the return
|
||||
// https://tools.ietf.org/html/draft-ietf-tls-subcerts-02. If the return
|
||||
// value is nil, then the server will not offer negotiate the extension.
|
||||
//
|
||||
// This value has no meaning for the client.
|
||||
|
@ -415,27 +415,21 @@ func (hs *clientHandshakeState) processCertsFromServer(certificates [][]byte) er
|
||||
|
||||
// processDelegatedCredentialFromServer unmarshals the delegated credential
|
||||
// offered by the server (if present) and validates it using the peer
|
||||
// certificate.
|
||||
func (hs *clientHandshakeState) processDelegatedCredentialFromServer(serialized []byte) error {
|
||||
// certificate and the signature scheme (`scheme`) indicated by the server in
|
||||
// the "signature_scheme" extension.
|
||||
func (hs *clientHandshakeState) processDelegatedCredentialFromServer(serialized []byte, scheme SignatureScheme) error {
|
||||
c := hs.c
|
||||
|
||||
var dc *delegatedCredential
|
||||
var err error
|
||||
if serialized != nil {
|
||||
|
||||
// Assert that the DC extension was indicated by the client.
|
||||
if !hs.hello.delegatedCredential {
|
||||
c.sendAlert(alertUnexpectedMessage)
|
||||
return errors.New("tls: got delegated credential extension without indication")
|
||||
}
|
||||
|
||||
// Assert that the DC was sent in the ServerHello in (and only in)
|
||||
// version 1.2.
|
||||
if hs.serverHello.delegatedCredential != nil && hs.serverHello.vers != VersionTLS12 {
|
||||
c.sendAlert(alertIllegalParameter)
|
||||
return errors.New("tls: ServerHello with delegated credential extension in TLS != 1.2")
|
||||
}
|
||||
|
||||
// Parse the delegated credential.
|
||||
dc, err = unmarshalDelegatedCredential(serialized)
|
||||
if err != nil {
|
||||
c.sendAlert(alertDecodeError)
|
||||
@ -444,12 +438,18 @@ func (hs *clientHandshakeState) processDelegatedCredentialFromServer(serialized
|
||||
}
|
||||
|
||||
if dc != nil && !c.config.InsecureSkipVerify {
|
||||
if v, err := dc.validate(c.peerCertificates[0], hs.c.vers, c.config.time()); err != nil {
|
||||
if v, err := dc.validate(c.peerCertificates[0], c.config.time()); err != nil {
|
||||
c.sendAlert(alertIllegalParameter)
|
||||
return fmt.Errorf("delegated credential: %s", err)
|
||||
} else if !v {
|
||||
c.sendAlert(alertIllegalParameter)
|
||||
return errors.New("delegated credential: signature invalid")
|
||||
} else if dc.cred.expectedVersion != hs.c.vers {
|
||||
c.sendAlert(alertIllegalParameter)
|
||||
return errors.New("delegated credential: protocol version mismatch")
|
||||
} else if dc.cred.expectedCertVerifyAlgorithm != scheme {
|
||||
c.sendAlert(alertIllegalParameter)
|
||||
return errors.New("delegated credential: signature scheme mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
@ -477,13 +477,6 @@ func (hs *clientHandshakeState) doFullHandshake() error {
|
||||
if err := hs.processCertsFromServer(certMsg.certificates); err != nil {
|
||||
return err
|
||||
}
|
||||
// Validate the DC if present. The DC is only processed if the
|
||||
// extension was indicated by the ClientHello; otherwise this call will
|
||||
// result in an "illegal_parameter" alert. It also asserts that the DC
|
||||
// was sent in the ServerHello if and only if TLS 1.2 is in use.
|
||||
if err := hs.processDelegatedCredentialFromServer(hs.serverHello.delegatedCredential); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// This is a renegotiation handshake. We require that the
|
||||
// server's identity (i.e. leaf certificate) is unchanged and
|
||||
@ -532,13 +525,6 @@ func (hs *clientHandshakeState) doFullHandshake() error {
|
||||
// Set the public key used to verify the handshake.
|
||||
pk := c.peerCertificates[0].PublicKey
|
||||
|
||||
// If the delegated credential extension has successfully been negotiated,
|
||||
// then the ServerKeyExchange is signed with delegated credential private
|
||||
// key.
|
||||
if c.verifiedDc != nil {
|
||||
pk = c.verifiedDc.cred.publicKey
|
||||
}
|
||||
|
||||
skx, ok := msg.(*serverKeyExchangeMsg)
|
||||
if ok {
|
||||
hs.finishedHash.Write(skx.marshal())
|
||||
|
@ -759,7 +759,7 @@ func (m *clientHelloMsg) unmarshal(data []byte) alert {
|
||||
// https://tools.ietf.org/html/draft-ietf-tls-tls13-18#section-4.2.8
|
||||
m.earlyData = true
|
||||
case extensionDelegatedCredential:
|
||||
// https://tools.ietf.org/html/draft-ietf-tls-subcerts-01
|
||||
// https://tools.ietf.org/html/draft-ietf-tls-subcerts-02
|
||||
m.delegatedCredential = true
|
||||
}
|
||||
data = data[length:]
|
||||
@ -789,10 +789,6 @@ type serverHelloMsg struct {
|
||||
secureRenegotiationSupported bool
|
||||
alpnProtocol string
|
||||
|
||||
// TLS 1.2. In TLS 1.3, the DC extension is included in of the end-entity
|
||||
// certificate in the Certificate message.
|
||||
delegatedCredential []byte
|
||||
|
||||
// TLS 1.3
|
||||
keyShare keyShare
|
||||
psk bool
|
||||
@ -828,7 +824,6 @@ func (m *serverHelloMsg) equal(i interface{}) bool {
|
||||
bytes.Equal(m.secureRenegotiation, m1.secureRenegotiation) &&
|
||||
m.alpnProtocol == m1.alpnProtocol &&
|
||||
m.keyShare.group == m1.keyShare.group &&
|
||||
bytes.Equal(m.delegatedCredential, m1.delegatedCredential) &&
|
||||
bytes.Equal(m.keyShare.data, m1.keyShare.data) &&
|
||||
m.psk == m1.psk &&
|
||||
m.pskIdentity == m1.pskIdentity
|
||||
@ -882,10 +877,6 @@ func (m *serverHelloMsg) marshal() []byte {
|
||||
extensionsLength += 2 + sctLen
|
||||
numExtensions++
|
||||
}
|
||||
if dcLen := len(m.delegatedCredential); dcLen > 0 && m.vers == VersionTLS12 {
|
||||
extensionsLength += 4 + dcLen
|
||||
numExtensions++
|
||||
}
|
||||
if m.keyShare.group != 0 {
|
||||
extensionsLength += 4 + len(m.keyShare.data)
|
||||
numExtensions++
|
||||
@ -1015,13 +1006,6 @@ func (m *serverHelloMsg) marshal() []byte {
|
||||
z = z[len(sct)+2:]
|
||||
}
|
||||
}
|
||||
if dcLen := len(m.delegatedCredential); dcLen > 0 && m.vers == VersionTLS12 {
|
||||
binary.BigEndian.PutUint16(z, extensionDelegatedCredential)
|
||||
binary.BigEndian.PutUint16(z[2:], uint16(dcLen))
|
||||
z = z[4:]
|
||||
copy(z, m.delegatedCredential)
|
||||
z = z[dcLen:]
|
||||
}
|
||||
if m.keyShare.group != 0 {
|
||||
z[0] = uint8(extensionKeyShare >> 8)
|
||||
z[1] = uint8(extensionKeyShare)
|
||||
@ -1209,11 +1193,6 @@ func (m *serverHelloMsg) unmarshal(data []byte) alert {
|
||||
m.scts = append(m.scts, d[:sctLen])
|
||||
d = d[sctLen:]
|
||||
}
|
||||
case extensionDelegatedCredential:
|
||||
if m.vers != VersionTLS12 {
|
||||
return alertUnexpectedMessage
|
||||
}
|
||||
m.delegatedCredential = data[:length]
|
||||
case extensionKeyShare:
|
||||
d := data[:length]
|
||||
|
||||
|
@ -330,11 +330,6 @@ Curves:
|
||||
if dc != nil {
|
||||
hs.privateKey = sk
|
||||
hs.delegatedCredential = dc
|
||||
|
||||
// For TLS 1.2, the DC is an extension to the ServerHello.
|
||||
if c.vers == VersionTLS12 {
|
||||
hs.hello.delegatedCredential = hs.delegatedCredential
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
151
subcerts.go
151
subcerts.go
@ -5,7 +5,7 @@
|
||||
package tls
|
||||
|
||||
// Delegated credentials for TLS
|
||||
// (https://tools.ietf.org/html/draft-ietf-tls-subcerts-01) is an IETF Internet
|
||||
// (https://tools.ietf.org/html/draft-ietf-tls-subcerts-02) is an IETF Internet
|
||||
// draft and proposed TLS extension. This allows a backend server to delegate
|
||||
// TLS termination to a trusted frontend. If the client supports this extension,
|
||||
// then the frontend may use a "delegated credential" as the signing key in the
|
||||
@ -14,7 +14,7 @@ package tls
|
||||
// revoked; in order to mitigate risk in case the frontend is compromised, the
|
||||
// credential is only valid for a short time (days, hours, or even minutes).
|
||||
//
|
||||
// This implements draft 01. This draft doesn't specify an object identifier for
|
||||
// This implements draft 02. This draft doesn't specify an object identifier for
|
||||
// the X.509 extension; we use one assigned by Cloudflare. In addition, IANA has
|
||||
// not assigned an extension ID for this extension; we picked up one that's not
|
||||
// yet taken.
|
||||
@ -70,8 +70,11 @@ func canDelegate(cert *x509.Certificate) bool {
|
||||
|
||||
// credential stores the public components of a credential.
|
||||
type credential struct {
|
||||
// The serialized form of the credential.
|
||||
raw []byte
|
||||
|
||||
// The amount of time for which the credential is valid. Specifically, the
|
||||
// credential expires `ValidTime` seconds after the `notBefore` of the
|
||||
// the credential expires `ValidTime` seconds after the `notBefore` of the
|
||||
// delegation certificate. The delegator shall not issue delegated
|
||||
// credentials that are valid for more than 7 days from the current time.
|
||||
//
|
||||
@ -79,14 +82,14 @@ type credential struct {
|
||||
// uint32 representing the duration in seconds.
|
||||
validTime time.Duration
|
||||
|
||||
// The signature scheme associated with the delegated credential public key.
|
||||
expectedCertVerifyAlgorithm SignatureScheme
|
||||
|
||||
// The version of TLS in which the credential will be used.
|
||||
expectedVersion uint16
|
||||
|
||||
// The credential public key.
|
||||
publicKey crypto.PublicKey
|
||||
|
||||
// The signature scheme associated with the credential public key.
|
||||
//
|
||||
// NOTE(cjpatton) This is used for bookkeeping and is not actually part of
|
||||
// the credential structure specified in the standard.
|
||||
scheme SignatureScheme
|
||||
}
|
||||
|
||||
// isExpired returns true if the credential has expired. The end of the validity
|
||||
@ -108,7 +111,7 @@ func (cred *credential) invalidTTL(start, now time.Time) bool {
|
||||
// marshalSubjectPublicKeyInfo returns a DER encoded SubjectPublicKeyInfo structure
|
||||
// (as defined in the X.509 standard) for the credential.
|
||||
func (cred *credential) marshalSubjectPublicKeyInfo() ([]byte, error) {
|
||||
switch cred.scheme {
|
||||
switch cred.expectedCertVerifyAlgorithm {
|
||||
case ECDSAWithP256AndSHA256,
|
||||
ECDSAWithP384AndSHA384,
|
||||
ECDSAWithP521AndSHA512:
|
||||
@ -119,19 +122,26 @@ func (cred *credential) marshalSubjectPublicKeyInfo() ([]byte, error) {
|
||||
return serializedPublicKey, nil
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported signature scheme: 0x%04x", cred.scheme)
|
||||
return nil, fmt.Errorf("unsupported signature scheme: 0x%04x", cred.expectedCertVerifyAlgorithm)
|
||||
}
|
||||
}
|
||||
|
||||
// marshal encodes a credential in the wire format specified in
|
||||
// https://tools.ietf.org/html/draft-ietf-tls-subcerts-01.
|
||||
// https://tools.ietf.org/html/draft-ietf-tls-subcerts-02.
|
||||
func (cred *credential) marshal() ([]byte, error) {
|
||||
// Write the valid_time field.
|
||||
serialized := make([]byte, 6)
|
||||
// The number of bytes comprising the DC parameters, which includes the
|
||||
// validity time (4 bytes), the signature scheme of the public key (2 bytes), and
|
||||
// the protocol version (2 bytes).
|
||||
paramsLen := 8
|
||||
|
||||
// The first 4 bytes are the valid_time, scheme, and version fields.
|
||||
serialized := make([]byte, paramsLen+2)
|
||||
binary.BigEndian.PutUint32(serialized, uint32(cred.validTime/time.Second))
|
||||
binary.BigEndian.PutUint16(serialized[4:], uint16(cred.expectedCertVerifyAlgorithm))
|
||||
binary.BigEndian.PutUint16(serialized[6:], cred.expectedVersion)
|
||||
|
||||
// Encode the public key and assert that the encoding is no longer than 2^16
|
||||
// bytes (per the spect).
|
||||
// bytes (per the spec).
|
||||
serializedPublicKey, err := cred.marshalSubjectPublicKeyInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -140,68 +150,58 @@ func (cred *credential) marshal() ([]byte, error) {
|
||||
return nil, errors.New("public key is too long")
|
||||
}
|
||||
|
||||
// Write the length of the public_key field.
|
||||
binary.BigEndian.PutUint16(serialized[4:], uint16(len(serializedPublicKey)))
|
||||
// The next 2 bytes are the length of the public key field.
|
||||
binary.BigEndian.PutUint16(serialized[paramsLen:], uint16(len(serializedPublicKey)))
|
||||
|
||||
// Write the public key.
|
||||
return append(serialized, serializedPublicKey...), nil
|
||||
// The remaining bytes are the public key itself.
|
||||
serialized = append(serialized, serializedPublicKey...)
|
||||
cred.raw = serialized
|
||||
return serialized, nil
|
||||
}
|
||||
|
||||
// unmarshalCredential decodes a credential and returns it.
|
||||
func unmarshalCredential(serialized []byte) (*credential, error) {
|
||||
// Bytes 0-3 are the validity time field; bytes 4-6 are the length of the
|
||||
// serialized SubjectPublicKeyInfo.
|
||||
if len(serialized) < 6 {
|
||||
// The number of bytes comprising the DC parameters.
|
||||
paramsLen := 8
|
||||
|
||||
if len(serialized) < paramsLen+2 {
|
||||
return nil, errors.New("credential is too short")
|
||||
}
|
||||
|
||||
// Parse the validity time.
|
||||
// Parse the valid_time, scheme, and version fields.
|
||||
validTime := time.Duration(binary.BigEndian.Uint32(serialized)) * time.Second
|
||||
scheme := SignatureScheme(binary.BigEndian.Uint16(serialized[4:]))
|
||||
version := binary.BigEndian.Uint16(serialized[6:])
|
||||
|
||||
// Parse the SubjectPublicKeyInfo.
|
||||
pk, scheme, err := unmarshalSubjectPublicKeyInfo(serialized[6:])
|
||||
pk, err := x509.ParsePKIXPublicKey(serialized[paramsLen+2:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &credential{validTime, pk, scheme}, nil
|
||||
if _, ok := pk.(*ecdsa.PublicKey); !ok {
|
||||
return nil, fmt.Errorf("unsupported delegation key type: %T", pk)
|
||||
}
|
||||
|
||||
// unmarshalSubjectPublicKeyInfo parses a DER encoded SubjectPublicKeyInfo
|
||||
// structure into a public key and its corresponding algorithm.
|
||||
func unmarshalSubjectPublicKeyInfo(serialized []byte) (crypto.PublicKey, SignatureScheme, error) {
|
||||
publicKey, err := x509.ParsePKIXPublicKey(serialized)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
switch pk := publicKey.(type) {
|
||||
case *ecdsa.PublicKey:
|
||||
curveName := pk.Curve.Params().Name
|
||||
if curveName == "P-256" {
|
||||
return pk, ECDSAWithP256AndSHA256, nil
|
||||
} else if curveName == "P-384" {
|
||||
return pk, ECDSAWithP384AndSHA384, nil
|
||||
} else if curveName == "P-521" {
|
||||
return pk, ECDSAWithP521AndSHA512, nil
|
||||
} else {
|
||||
return nil, 0, fmt.Errorf("curve %s s not supported", curveName)
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, 0, fmt.Errorf("unsupported delgation key type: %T", pk)
|
||||
}
|
||||
return &credential{
|
||||
raw: serialized,
|
||||
validTime: validTime,
|
||||
expectedCertVerifyAlgorithm: scheme,
|
||||
expectedVersion: version,
|
||||
publicKey: pk,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// getCredentialLen returns the number of bytes comprising the serialized
|
||||
// credential that starts at the beginning of the input slice. It returns an
|
||||
// error if the input is too short to contain a credential.
|
||||
func getCredentialLen(serialized []byte) (int, error) {
|
||||
if len(serialized) < 6 {
|
||||
paramsLen := 8
|
||||
if len(serialized) < paramsLen+2 {
|
||||
return 0, errors.New("credential is too short")
|
||||
}
|
||||
// First 4 bytes is the validity time.
|
||||
serialized = serialized[4:]
|
||||
// First several bytes are the valid_time, scheme, and version fields.
|
||||
serialized = serialized[paramsLen:]
|
||||
|
||||
// The next 2 bytes are the length of the serialized public key.
|
||||
serializedPublicKeyLen := int(binary.BigEndian.Uint16(serialized))
|
||||
@ -211,7 +211,7 @@ func getCredentialLen(serialized []byte) (int, error) {
|
||||
return 0, errors.New("public key of credential is too short")
|
||||
}
|
||||
|
||||
return 6 + serializedPublicKeyLen, nil
|
||||
return paramsLen + 2 + serializedPublicKeyLen, nil
|
||||
}
|
||||
|
||||
// delegatedCredential stores a credential and its delegation.
|
||||
@ -222,7 +222,7 @@ type delegatedCredential struct {
|
||||
cred *credential
|
||||
|
||||
// The signature scheme used to sign the credential.
|
||||
scheme SignatureScheme
|
||||
algorithm SignatureScheme
|
||||
|
||||
// The credential's delegation.
|
||||
signature []byte
|
||||
@ -246,7 +246,7 @@ func ensureCertificateHasLeaf(cert *Certificate) error {
|
||||
// validate checks that that the signature is valid, that the credential hasn't
|
||||
// expired, and that the TTL is valid. It also checks that certificate can be
|
||||
// used for delegation.
|
||||
func (dc *delegatedCredential) validate(cert *x509.Certificate, vers uint16, now time.Time) (bool, error) {
|
||||
func (dc *delegatedCredential) validate(cert *x509.Certificate, now time.Time) (bool, error) {
|
||||
// Check that the cert can delegate.
|
||||
if !canDelegate(cert) {
|
||||
return false, errNoDelegationUsage
|
||||
@ -261,15 +261,16 @@ func (dc *delegatedCredential) validate(cert *x509.Certificate, vers uint16, now
|
||||
}
|
||||
|
||||
// Prepare the credential for verification.
|
||||
hash := getHash(dc.scheme)
|
||||
in, err := prepareDelegation(hash, dc.cred, cert.Raw, dc.scheme, vers)
|
||||
rawCred, err := dc.cred.marshal()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
hash := getHash(dc.algorithm)
|
||||
in := prepareDelegation(hash, rawCred, cert.Raw, dc.algorithm)
|
||||
|
||||
// TODO(any) This code overlaps signficantly with verifyHandshakeSignature()
|
||||
// TODO(any) This code overlaps significantly with verifyHandshakeSignature()
|
||||
// in ../auth.go. This should be refactored.
|
||||
switch dc.scheme {
|
||||
switch dc.algorithm {
|
||||
case ECDSAWithP256AndSHA256,
|
||||
ECDSAWithP384AndSHA384,
|
||||
ECDSAWithP521AndSHA512:
|
||||
@ -285,7 +286,7 @@ func (dc *delegatedCredential) validate(cert *x509.Certificate, vers uint16, now
|
||||
|
||||
default:
|
||||
return false, fmt.Errorf(
|
||||
"unsupported signature scheme: 0x%04x", dc.scheme)
|
||||
"unsupported signature scheme: 0x%04x", dc.algorithm)
|
||||
}
|
||||
}
|
||||
|
||||
@ -325,7 +326,7 @@ func unmarshalDelegatedCredential(serialized []byte) (*delegatedCredential, erro
|
||||
return &delegatedCredential{
|
||||
raw: serialized,
|
||||
cred: cred,
|
||||
scheme: scheme,
|
||||
algorithm: scheme,
|
||||
signature: sig,
|
||||
}, nil
|
||||
}
|
||||
@ -361,11 +362,10 @@ func getHash(scheme SignatureScheme) crypto.Hash {
|
||||
}
|
||||
|
||||
// prepareDelegation returns a hash of the message that the delegator is to
|
||||
// sign. The inputs are the credential (cred), the DER-encoded delegator
|
||||
// certificate (`delegatorCert`), the signature scheme of the delegator
|
||||
// (`delegatorScheme`), and the protocol version (`vers`) in which the credential
|
||||
// is to be used.
|
||||
func prepareDelegation(hash crypto.Hash, cred *credential, delegatorCert []byte, delegatorScheme SignatureScheme, vers uint16) ([]byte, error) {
|
||||
// sign. The inputs are the credential (`cred`), the DER-encoded delegator
|
||||
// certificate (`delegatorCert`) and the signature scheme of the delegator
|
||||
// (`delegatorAlgorithm`).
|
||||
func prepareDelegation(hash crypto.Hash, cred, delegatorCert []byte, delegatorAlgorithm SignatureScheme) []byte {
|
||||
h := hash.New()
|
||||
|
||||
// The header.
|
||||
@ -373,25 +373,16 @@ func prepareDelegation(hash crypto.Hash, cred *credential, delegatorCert []byte,
|
||||
h.Write([]byte("TLS, server delegated credentials"))
|
||||
h.Write([]byte{0x00})
|
||||
|
||||
// The protocol version.
|
||||
var serializedVers [2]byte
|
||||
binary.BigEndian.PutUint16(serializedVers[:], uint16(vers))
|
||||
h.Write(serializedVers[:])
|
||||
|
||||
// The delegation certificate.
|
||||
h.Write(delegatorCert)
|
||||
|
||||
// The credential.
|
||||
h.Write(cred)
|
||||
|
||||
// The delegator signature scheme.
|
||||
var serializedScheme [2]byte
|
||||
binary.BigEndian.PutUint16(serializedScheme[:], uint16(delegatorScheme))
|
||||
binary.BigEndian.PutUint16(serializedScheme[:], uint16(delegatorAlgorithm))
|
||||
h.Write(serializedScheme[:])
|
||||
|
||||
// The credential.
|
||||
serializedCred, err := cred.marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h.Write(serializedCred)
|
||||
|
||||
return h.Sum(nil), nil
|
||||
return h.Sum(nil)
|
||||
}
|
||||
|
157
subcerts_test.go
157
subcerts_test.go
@ -16,46 +16,46 @@ import (
|
||||
|
||||
// A PEM-encoded "delegation certificate", an X.509 certificate with the
|
||||
// DelegationUsage extension. The extension is defined in
|
||||
// specified in https://tools.ietf.org/html/draft-ietf-tls-subcerts-01.
|
||||
// specified in https://tools.ietf.org/html/draft-ietf-tls-subcerts-02.
|
||||
var dcDelegationCertPEM = `-----BEGIN CERTIFICATE-----
|
||||
MIIBdzCCAR2gAwIBAgIQLVIvEpo0/0TzRja4ImvB1TAKBggqhkjOPQQDAjASMRAw
|
||||
DgYDVQQKEwdBY21lIENvMB4XDTE4MDcwMzE2NTE1M1oXDTE5MDcwMzE2NTE1M1ow
|
||||
EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOhB
|
||||
U6adaAgliLaFc1PAo9HBO4Wish1G4df3IK5EXLy+ooYfmkfzT1FxqbNLZufNYzve
|
||||
25fmpal/1VJAjpVyKq2jVTBTMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggr
|
||||
BgEFBQcDATAMBgNVHRMBAf8EAjAAMA8GA1UdEQQIMAaHBH8AAAEwDQYJKwYBBAGC
|
||||
2kssBAAwCgYIKoZIzj0EAwIDSAAwRQIhAPNwRk6cygm6zO5rjOzohKYWS+1KuWCM
|
||||
OetDIvU4mdyoAiAGN97y3GJccYn9ZOJS4UOqhr9oO8PuZMLgdq4OrMRiiA==
|
||||
MIIBejCCASGgAwIBAgIQXXtl0v50W2OadoW0QwLUlzAKBggqhkjOPQQDAjAUMRIw
|
||||
EAYDVQQKEwlBY21lIEluYy4wHhcNMTgwNzMwMjAxMTE5WhcNMTgwODA2MjAxMTE5
|
||||
WjAUMRIwEAYDVQQKEwlBY21lIEluYy4wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC
|
||||
AATcQuuaUNJ3kqKGs4DBdJVd7zWzyGANT4uBNGVkZ2cgaDsdFnx99fGibfgoWer8
|
||||
HLt9Z+S6Hs+8bDPBHNgTR/Lfo1UwUzAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAww
|
||||
CgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAPBgNVHREECDAGhwR/AAABMA0GCSsG
|
||||
AQQBgtpLLAQAMAoGCCqGSM49BAMCA0cAMEQCIEMdIkwwmzQAJ6RSDT3wcrsySx2B
|
||||
5Lvx5HGzc43Fgu9eAiAi4sFXnizFBVUL43qXZBq4ARw17o0JW3/7eec1xttQhw==
|
||||
-----END CERTIFICATE-----
|
||||
`
|
||||
|
||||
// The PEM-encoded "delegation key", the secret key associated with the
|
||||
// delegation certificate.
|
||||
// delegation certificate. This is a key for ECDSA with P256 and SHA256.
|
||||
var dcDelegationKeyPEM = `-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIJDVlo+sJolMcNjMkfCGDUjMJcE4UgclcXGCrOtbJAi2oAoGCCqGSM49
|
||||
AwEHoUQDQgAE6EFTpp1oCCWItoVzU8Cj0cE7haKyHUbh1/cgrkRcvL6ihh+aR/NP
|
||||
UXGps0tm581jO97bl+alqX/VUkCOlXIqrQ==
|
||||
MHcCAQEEIAS/pGktmxK1hlt3gF4N2nkMrJnoZihvOO63nnNcxXQroAoGCCqGSM49
|
||||
AwEHoUQDQgAE3ELrmlDSd5KihrOAwXSVXe81s8hgDU+LgTRlZGdnIGg7HRZ8ffXx
|
||||
om34KFnq/By7fWfkuh7PvGwzwRzYE0fy3w==
|
||||
-----END EC PRIVATE KEY-----
|
||||
`
|
||||
|
||||
// A certificate without the DelegationUsage extension.
|
||||
var dcCertPEM = `-----BEGIN CERTIFICATE-----
|
||||
MIIBaTCCAQ6gAwIBAgIQSUo+9uaip3qCW+1EPeHZgDAKBggqhkjOPQQDAjASMRAw
|
||||
DgYDVQQKEwdBY21lIENvMB4XDTE4MDYxMjIzNDAyNloXDTE5MDYxMjIzNDAyNlow
|
||||
EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLf7
|
||||
fiznPVdc3V5mM3ymswU2/IoJaq/deA6dgdj50ozdYyRiAPjxzcz9zRsZw1apTF/h
|
||||
yNfiLhV4EE1VrwXcT5OjRjBEMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggr
|
||||
BgEFBQcDATAMBgNVHRMBAf8EAjAAMA8GA1UdEQQIMAaHBH8AAAEwCgYIKoZIzj0E
|
||||
AwIDSQAwRgIhANXG0zmrVtQBK0TNZZoEGMOtSwxmiZzXNe+IjdpxO3TiAiEA5VYx
|
||||
0CWJq5zqpVXbJMeKVMASo2nrXZoA6NhJvFQ97hw=
|
||||
MIIBajCCAQ+gAwIBAgIRAMUg/VFqJaWWJwZ9iHoMjqIwCgYIKoZIzj0EAwIwEjEQ
|
||||
MA4GA1UEChMHQWNtZSBDbzAeFw0xODA3MzAyMDExMTlaFw0xOTA3MzAyMDExMTla
|
||||
MBIxEDAOBgNVBAoTB0FjbWUgQ28wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATA
|
||||
n+oeWSvSNHhEskSRgkkerCQDoV/NA+r3S5AtCOFT5AYLt8xltSTWerFI/YlZLIcL
|
||||
xlJPT7T+XpBnfS6xaAuxo0YwRDAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYI
|
||||
KwYBBQUHAwEwDAYDVR0TAQH/BAIwADAPBgNVHREECDAGhwR/AAABMAoGCCqGSM49
|
||||
BAMCA0kAMEYCIQCFGWnoJmwH1rxNCKBJWVDBKDTSsYhySRk4h9RPyR8bUwIhAJxc
|
||||
KFyrowMTan791RJnyANH/4uYhmvkfhfrFGSTXUli
|
||||
-----END CERTIFICATE-----
|
||||
`
|
||||
|
||||
// The secret key associatted with dcCertPEM.
|
||||
var dcKeyPEM = `-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIMw9DiOfGI1E/XZrrW2huZSjYi0EKwvVjAe+dYtyFsSloAoGCCqGSM49
|
||||
AwEHoUQDQgAEt/t+LOc9V1zdXmYzfKazBTb8iglqr914Dp2B2PnSjN1jJGIA+PHN
|
||||
zP3NGxnDVqlMX+HI1+IuFXgQTVWvBdxPkw==
|
||||
MHcCAQEEIEP82pOhzx0tKkky9t0OmUo9MHgmfdAHxDN2cHmWGqOhoAoGCCqGSM49
|
||||
AwEHoUQDQgAEwJ/qHlkr0jR4RLJEkYJJHqwkA6FfzQPq90uQLQjhU+QGC7fMZbUk
|
||||
1nqxSP2JWSyHC8ZST0+0/l6QZ30usWgLsQ==
|
||||
-----END EC PRIVATE KEY-----
|
||||
`
|
||||
|
||||
@ -71,40 +71,50 @@ type dcTestDC struct {
|
||||
// Test data used for testing the TLS handshake with the delegated creedential
|
||||
// extension. The PEM block encodes a DER encoded slice of dcTestDC's.
|
||||
var dcTestDCsPEM = `-----BEGIN DC TEST DATA-----
|
||||
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
|
||||
HJbn52hmB027JEIMPWsxKxPkr7udk7Q=
|
||||
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
|
||||
-----END DC TEST DATA-----
|
||||
`
|
||||
|
||||
@ -127,10 +137,6 @@ func init() {
|
||||
panic("failed to unmarshal DC test ASN.1 data")
|
||||
}
|
||||
|
||||
// Use a static time for testing. This is the point at which the test DCs
|
||||
// were generated.
|
||||
dcTestNow = time.Date(2018, 07, 03, 18, 0, 0, 234234, time.UTC)
|
||||
|
||||
// The base configuration for the client and server.
|
||||
dcTestConfig = &Config{
|
||||
Time: func() time.Time {
|
||||
@ -163,6 +169,11 @@ func init() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// For testing purposes, use the point at which the test DCs were generated
|
||||
// as the current time. This is the same as the time at which the
|
||||
// delegation certificate was generated.
|
||||
dcTestNow = dcTestDelegationCert.Leaf.NotBefore
|
||||
|
||||
// Make these roots of these certificates the client's trusted CAs.
|
||||
dcTestConfig.RootCAs = x509.NewCertPool()
|
||||
|
||||
@ -251,17 +262,16 @@ var dcTesters = []struct {
|
||||
expectDC bool
|
||||
name string
|
||||
}{
|
||||
{true, true, false, VersionTLS12, VersionTLS12, 0, "tls12", true, true, "tls12"},
|
||||
{true, true, false, VersionTLS13, VersionTLS13, 0, "tls13", true, true, "tls13"},
|
||||
{true, true, false, VersionTLS12, VersionTLS12, 0, "malformed12", false, false, "tls12, malformed dc"},
|
||||
{true, true, false, VersionTLS13, VersionTLS13, 0, "malformed13", false, false, "tls13, malformed dc"},
|
||||
{true, true, true, VersionTLS12, VersionTLS12, 0, "invalid", true, true, "tls12, invalid dc, skip verify"},
|
||||
{true, true, true, VersionTLS13, VersionTLS13, 0, "invalid", true, true, "tls13, invalid dc, skip verify"},
|
||||
{false, true, false, VersionTLS12, VersionTLS12, 0, "tls12", true, false, "client no dc"},
|
||||
{true, false, false, VersionTLS12, VersionTLS12, 0, "tls12", true, false, "server no dc"},
|
||||
{true, true, false, VersionTLS11, VersionTLS12, 0, "tls12", true, false, "client old"},
|
||||
{true, true, false, VersionTLS12, VersionTLS11, 0, "tls12", true, false, "server old"},
|
||||
{true, true, false, VersionTLS13, VersionTLS13, 0, "tls13p256", true, true, "tls13"},
|
||||
{true, true, false, VersionTLS13, VersionTLS13, 0, "tls13p521", true, true, "tls13"},
|
||||
{true, false, false, VersionTLS13, VersionTLS13, 0, "tls13p256", true, false, "server no dc"},
|
||||
{true, true, false, VersionTLS12, VersionTLS13, 0, "tls13p256", true, false, "client old"},
|
||||
{true, true, false, VersionTLS13, VersionTLS12, 0, "tls13p256", true, false, "server old"},
|
||||
{true, true, false, VersionTLS13, VersionTLS13, 0, "badkey", false, false, "bad key"},
|
||||
{true, true, true, VersionTLS13, VersionTLS13, 0, "badsig", true, true, "bad key, skip verify"},
|
||||
{true, true, false, VersionTLS13, VersionTLS13, dcMaxTTL, "tls13", false, false, "expired dc"},
|
||||
{true, true, false, VersionTLS13, VersionTLS13, 0, "badvers", false, false, "dc wrong version"},
|
||||
{true, true, false, VersionTLS12, VersionTLS12, 0, "tls12", true, false, "tls12"},
|
||||
}
|
||||
|
||||
// Tests the handshake with the delegated credential extension for each test
|
||||
@ -283,6 +293,9 @@ func TestDCHandshake(t *testing.T) {
|
||||
if tester.serverDC {
|
||||
serverConfig.GetDelegatedCredential = func(
|
||||
ch *ClientHelloInfo, vers uint16) ([]byte, crypto.PrivateKey, error) {
|
||||
if vers < VersionTLS13 {
|
||||
return nil, nil, nil
|
||||
}
|
||||
for _, test := range dcTestDCs {
|
||||
if test.Name == tester.dcTestName {
|
||||
sk, err := x509.ParseECPrivateKey(test.PrivateKey)
|
||||
|
Loading…
Reference in New Issue
Block a user