Skip to content

Commit cf7f104

Browse files
claucecejhoyla
authored andcommitted
crypto/tls: implement draft-ietf-tls-subcerts-10
* Define API for delegated credentials so they are fetched using the same mechanisms used to fetch certificates * Allow the usage of other keyUsage when checking for the dc extension. Fixes issues in earlier patch, addressing #127, #128, #129, #130, and #131. Add tool for generating delegated credentials. Co-authored-by: jhoyla <jhoyla@users.noreply.github.com>
1 parent 7286b3a commit cf7f104

19 files changed

+1874
-34
lines changed

src/crypto/tls/auth.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,28 @@ func signatureSchemesForCertificate(version uint16, cert *Certificate) []Signatu
259259
return sigAlgs
260260
}
261261

262+
// selectSignatureSchemeDC picks a SignatureScheme from the peer's preference list
263+
// that works with the selected delegated credential. It's only called for protocol
264+
// versions that support delegated credential, so TLS 1.3.
265+
func selectSignatureSchemeDC(vers uint16, dc *DelegatedCredential, peerAlgs []SignatureScheme, peerAlgsDC []SignatureScheme) (SignatureScheme, error) {
266+
if vers != VersionTLS13 {
267+
return 0, errors.New("unsupported TLS version for dc")
268+
}
269+
270+
if !isSupportedSignatureAlgorithm(dc.algorithm, peerAlgs) {
271+
return undefinedSignatureScheme, errors.New("tls: peer doesn't support the delegated credential's signature")
272+
}
273+
274+
// Pick signature scheme in the peer's preference order, as our
275+
// preference order is not configurable.
276+
for _, preferredAlg := range peerAlgsDC {
277+
if preferredAlg == dc.cred.expCertVerfAlgo {
278+
return preferredAlg, nil
279+
}
280+
}
281+
return 0, errors.New("tls: peer doesn't support the delegated credential's signature algorithm")
282+
}
283+
262284
// selectSignatureScheme picks a SignatureScheme from the peer's preference list
263285
// that works with the selected certificate. It's only called for protocol
264286
// versions that support signature algorithms, so TLS 1.2 and 1.3.

src/crypto/tls/common.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ const (
9191
extensionSignatureAlgorithms uint16 = 13
9292
extensionALPN uint16 = 16
9393
extensionSCT uint16 = 18
94+
extensionDelegatedCredentials uint16 = 34
9495
extensionSessionTicket uint16 = 35
9596
extensionPreSharedKey uint16 = 41
9697
extensionEarlyData uint16 = 42
@@ -192,6 +193,16 @@ var supportedSignatureAlgorithms = []SignatureScheme{
192193
ECDSAWithSHA1,
193194
}
194195

196+
// supportedSignatureAlgorithmsDC contains the signature and hash algorithms that
197+
// the code advertises as supported in a TLS 1.3 ClientHello and in a TLS 1.3
198+
// CertificateRequest. This excludes 'rsa_pss_rsae_' algorithms.
199+
var supportedSignatureAlgorithmsDC = []SignatureScheme{
200+
ECDSAWithP256AndSHA256,
201+
Ed25519,
202+
ECDSAWithP384AndSHA384,
203+
ECDSAWithP521AndSHA512,
204+
}
205+
195206
// helloRetryRequestRandom is set as the Random value of a ServerHello
196207
// to signal that the message is actually a HelloRetryRequest.
197208
var helloRetryRequestRandom = []byte{ // See RFC 8446, Section 4.1.3.
@@ -259,6 +270,11 @@ type ConnectionState struct {
259270
// (and the peer provided a certificate) or RequireAndVerifyClientCert.
260271
VerifiedChains [][]*x509.Certificate
261272

273+
// VerifiedDC indicates that the Delegated Credential sent by the peer (if advertised
274+
// and correctly processed), which has been verified against the leaf certificate,
275+
// has been used.
276+
VerifiedDC bool
277+
262278
// SignedCertificateTimestamps is a list of SCTs provided by the peer
263279
// through the TLS handshake for the leaf certificate, if any.
264280
SignedCertificateTimestamps [][]byte
@@ -428,6 +444,13 @@ type ClientHelloInfo struct {
428444
// Algorithms Extension is being used (see RFC 5246, Section 7.4.1.4.1).
429445
SignatureSchemes []SignatureScheme
430446

447+
// SignatureSchemesDC lists the signature schemes that the client
448+
// is willing to verify when using Delegated Credentials.
449+
// This is and can be different from SignatureSchemes. SignatureSchemesDC
450+
// is set only if the DelegatedCredentials Extension is being used.
451+
// If Delegated Credentials are supported, this list should not be nil.
452+
SignatureSchemesDC []SignatureScheme
453+
431454
// SupportedProtos lists the application protocols supported by the client.
432455
// SupportedProtos is set only if the Application-Layer Protocol
433456
// Negotiation Extension is being used (see RFC 7301, Section 3.1).
@@ -442,6 +465,10 @@ type ClientHelloInfo struct {
442465
// might be rejected if used.
443466
SupportedVersions []uint16
444467

468+
// SupportDelegatedCredential is true if the client indicated willingness
469+
// to negotiate the Delegated Credential extension.
470+
SupportsDelegatedCredential bool
471+
445472
// Conn is the underlying net.Conn for the connection. Do not read
446473
// from, or write to, this connection; that will cause the TLS
447474
// connection to fail.
@@ -472,10 +499,21 @@ type CertificateRequestInfo struct {
472499
// empty slice indicates that the server has no preference.
473500
AcceptableCAs [][]byte
474501

502+
// SupportDelegatedCredential is true if the server indicated willingness
503+
// to negotiate the Delegated Credential extension.
504+
SupportsDelegatedCredential bool
505+
475506
// SignatureSchemes lists the signature schemes that the server is
476507
// willing to verify.
477508
SignatureSchemes []SignatureScheme
478509

510+
// SignatureSchemesDC lists the signature schemes that the server
511+
// is willing to verify when using Delegated Credentials.
512+
// This is and can be different from SignatureSchemes. SignatureSchemesDC
513+
// is set only if the DelegatedCredentials Extension is being used.
514+
// If Delegated Credentials are supported, this list should not be nil.
515+
SignatureSchemesDC []SignatureScheme
516+
479517
// Version is the TLS version that was negotiated for this connection.
480518
Version uint16
481519

@@ -752,6 +790,13 @@ type Config struct {
752790
// This feature is unstable and applications MUST NOT depend on it.
753791
CFControl interface{}
754792

793+
// SupportDelegatedCredential is true if the client or server is willing
794+
// to negotiate the delegated credential extension.
795+
// This can only be used with TLS 1.3.
796+
//
797+
// See https://tools.ietf.org/html/draft-ietf-tls-subcerts.
798+
SupportDelegatedCredential bool
799+
755800
// mutex protects sessionTicketKeys and autoSessionTicketKeys.
756801
mutex sync.RWMutex
757802
// sessionTicketKeys contains zero or more ticket keys. If set, it means the
@@ -842,6 +887,7 @@ func (c *Config) Clone() *Config {
842887
DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled,
843888
Renegotiation: c.Renegotiation,
844889
KeyLogWriter: c.KeyLogWriter,
890+
SupportDelegatedCredential: c.SupportDelegatedCredential,
845891
CFEventHandler: c.CFEventHandler,
846892
CFControl: c.CFControl,
847893
sessionTicketKeys: c.sessionTicketKeys,
@@ -1377,6 +1423,16 @@ func (c *Config) writeKeyLog(label string, clientRandom, secret []byte) error {
13771423
// and is only for debugging, so a global mutex saves space.
13781424
var writerMutex sync.Mutex
13791425

1426+
// A DelegatedCredentialPair contains a Delegated Credential and its
1427+
// associated private key.
1428+
type DelegatedCredentialPair struct {
1429+
// DC is the delegated credential.
1430+
DC *DelegatedCredential
1431+
// PrivateKey is the private key used to derive the public key of
1432+
// contained in DC. PrivateKey must implement crypto.Signer.
1433+
PrivateKey crypto.PrivateKey
1434+
}
1435+
13801436
// A Certificate is a chain of one or more certificates, leaf first.
13811437
type Certificate struct {
13821438
Certificate [][]byte
@@ -1394,6 +1450,16 @@ type Certificate struct {
13941450
// SignedCertificateTimestamps contains an optional list of Signed
13951451
// Certificate Timestamps which will be served to clients that request it.
13961452
SignedCertificateTimestamps [][]byte
1453+
// DelegatedCredentials are a list of Delegated Credentials with their
1454+
// corresponding private keys, signed by the leaf certificate.
1455+
// If there are no delegated credentials, this field is nil.
1456+
DelegatedCredentials []DelegatedCredentialPair
1457+
// DelegatedCredential is the delegated credential to be used in the
1458+
// handshake.
1459+
// If there are no delegated credentials, this field is nil.
1460+
// NOTE: Do not fill this field, as it will be filled depending on
1461+
// the provided list of delegated credentials.
1462+
DelegatedCredential []byte
13971463
// Leaf is the parsed form of the leaf certificate, which may be initialized
13981464
// using x509.ParseCertificate to reduce per-handshake processing. If nil,
13991465
// the leaf certificate will be parsed as needed.

src/crypto/tls/conn.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ type Conn struct {
5353
// verifiedChains contains the certificate chains that we built, as
5454
// opposed to the ones presented by the server.
5555
verifiedChains [][]*x509.Certificate
56+
// verifiedDC contains the Delegated Credential sent by the peer (if advertised
57+
// and correctly processed), which has been verified against the leaf certificate.
58+
verifiedDC *DelegatedCredential
5659
// serverName contains the server name indicated by the client, if any.
5760
serverName string
5861
// secureRenegotiation is true if the server echoed the secure
@@ -1494,6 +1497,9 @@ func (c *Conn) connectionStateLocked() ConnectionState {
14941497
state.CipherSuite = c.cipherSuite
14951498
state.PeerCertificates = c.peerCertificates
14961499
state.VerifiedChains = c.verifiedChains
1500+
if c.verifiedDC != nil {
1501+
state.VerifiedDC = true
1502+
}
14971503
state.SignedCertificateTimestamps = c.scts
14981504
state.OCSPResponse = c.ocspResponse
14991505
state.CFControl = c.config.CFControl

0 commit comments

Comments
 (0)