Update delegated credentials to the final RFC
Although the comments say draft-03, we're currently on draft-06.
dcd6e447eba4f32f49c22c6196ed0e714cc522c1 forgot to update all the
comments.
The final RFC is identical to draft-06, except
expected_cert_verify_algorithm was renamed to dc_cert_verify_algorithm,
so this is just changing comment and renaming something.
While I'm here, write the codepoint in decimal instead of hex, to match
the document and how the other IANA codepoints are written out.
Change-Id: I6d1f362a21eecafeef5bba5879f4158e31c8def4
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/66367
Reviewed-by: Bob Beck <bbe@google.com>
Commit-Queue: Bob Beck <bbe@google.com>
Auto-Submit: David Benjamin <davidben@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 839cf2f..97fe96e 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -3342,27 +3342,24 @@
//
// *** EXPERIMENTAL — PRONE TO CHANGE ***
//
-// draft-ietf-tls-subcerts is a proposed extension for TLS 1.3 and above that
-// allows an end point to use its certificate to delegate credentials for
-// authentication. If the peer indicates support for this extension, then this
-// host may use a delegated credential to sign the handshake. Once issued,
-// credentials can't be revoked. In order to mitigate the damage in case the
-// credential secret key is compromised, the credential is only valid for a
-// short time (days, hours, or even minutes). This library implements draft-03
-// of the protocol spec.
+// Delegated credentials (RFC 9345) allow a TLS 1.3 end point to use its
+// certificate to issue new credentials for authentication. If the peer
+// indicates support for this extension, then this host may use a delegated
+// credential to sign the handshake. Once issued, credentials can't be revoked.
+// In order to mitigate the damage in case the credential secret key is
+// compromised, the credential is only valid for a short time (days, hours, or
+// even minutes).
//
-// The extension ID has not been assigned; we're using 0xff02 for the time
-// being. Currently only the server side is implemented.
+// Currently only the server side is implemented.
//
// Servers configure a DC for use in the handshake via
// |SSL_set1_delegated_credential|. It must be signed by the host's end-entity
-// certificate as defined in draft-ietf-tls-subcerts-03.
+// certificate as defined in RFC 9345.
// SSL_set1_delegated_credential configures the delegated credential (DC) that
// will be sent to the peer for the current connection. |dc| is the DC in wire
// format, and |pkey| or |key_method| is the corresponding private key.
-// Currently (as of draft-03), only servers may configure a DC to use in the
-// handshake.
+// Currently, only servers may configure a DC to use in the handshake.
//
// The DC will only be used if the protocol version is correct and the signature
// scheme is supported by the peer. If not, the DC will not be negotiated and
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index c1207a3..6030188 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/tls1.h
@@ -239,8 +239,8 @@
// ExtensionType value from RFC 5746
#define TLSEXT_TYPE_renegotiate 0xff01
-// ExtensionType value from draft-ietf-tls-subcerts.
-#define TLSEXT_TYPE_delegated_credential 0x22
+// ExtensionType value from RFC 9345
+#define TLSEXT_TYPE_delegated_credential 34
// ExtensionType value from draft-vvv-tls-alps. This is not an IANA defined
// extension number.
diff --git a/ssl/extensions.cc b/ssl/extensions.cc
index b134000..73adf74 100644
--- a/ssl/extensions.cc
+++ b/ssl/extensions.cc
@@ -2752,7 +2752,7 @@
// Delegated credentials.
//
-// https://tools.ietf.org/html/draft-ietf-tls-subcerts
+// https://www.rfc-editor.org/rfc/rfc9345.html
static bool ext_delegated_credential_add_clienthello(
const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
@@ -4122,7 +4122,7 @@
Span<const uint16_t> sigalgs = kSignSignatureAlgorithms;
if (ssl_signing_with_dc(hs)) {
- sigalgs = MakeConstSpan(&dc->expected_cert_verify_algorithm, 1);
+ sigalgs = MakeConstSpan(&dc->dc_cert_verify_algorithm, 1);
} else if (!cert->sigalgs.empty()) {
sigalgs = cert->sigalgs;
}
diff --git a/ssl/internal.h b/ssl/internal.h
index d9972dc..2896a32 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -1574,8 +1574,7 @@
// Delegated credentials.
-// This structure stores a delegated credential (DC) as defined by
-// draft-ietf-tls-subcerts-03.
+// This structure stores a delegated credential (DC) as defined by RFC 9345.
struct DC {
static constexpr bool kAllowUniquePtr = true;
~DC();
@@ -1588,13 +1587,11 @@
// |*out_alert|.
static UniquePtr<DC> Parse(CRYPTO_BUFFER *in, uint8_t *out_alert);
- // raw is the delegated credential encoded as specified in draft-ietf-tls-
- // subcerts-03.
+ // raw is the delegated credential encoded as specified in RFC 9345.
UniquePtr<CRYPTO_BUFFER> raw;
- // expected_cert_verify_algorithm is the signature scheme of the DC public
- // key.
- uint16_t expected_cert_verify_algorithm = 0;
+ // dc_cert_verify_algorithm is the signature scheme of the DC public key.
+ uint16_t dc_cert_verify_algorithm = 0;
// pkey is the public key parsed from |public_key|.
UniquePtr<EVP_PKEY> pkey;
diff --git a/ssl/ssl_cert.cc b/ssl/ssl_cert.cc
index 1b6b574..6c6ae7b 100644
--- a/ssl/ssl_cert.cc
+++ b/ssl/ssl_cert.cc
@@ -755,7 +755,7 @@
}
ret->raw = UpRef(raw);
- ret->expected_cert_verify_algorithm = expected_cert_verify_algorithm;
+ ret->dc_cert_verify_algorithm = dc_cert_verify_algorithm;
ret->pkey = UpRef(pkey);
return ret;
}
@@ -775,7 +775,7 @@
uint16_t algorithm;
CRYPTO_BUFFER_init_CBS(dc->raw.get(), &deleg);
if (!CBS_get_u32(&deleg, &valid_time) ||
- !CBS_get_u16(&deleg, &dc->expected_cert_verify_algorithm) ||
+ !CBS_get_u16(&deleg, &dc->dc_cert_verify_algorithm) ||
!CBS_get_u24_length_prefixed(&deleg, &pubkey) ||
!CBS_get_u16(&deleg, &algorithm) ||
!CBS_get_u16_length_prefixed(&deleg, &sig) ||
@@ -817,7 +817,7 @@
// Check that the DC signature algorithm is supported by the peer.
Span<const uint16_t> peer_sigalgs = hs->peer_delegated_credential_sigalgs;
for (uint16_t peer_sigalg : peer_sigalgs) {
- if (dc->expected_cert_verify_algorithm == peer_sigalg) {
+ if (dc->dc_cert_verify_algorithm == peer_sigalg) {
return true;
}
}
@@ -825,8 +825,7 @@
}
bool ssl_signing_with_dc(const SSL_HANDSHAKE *hs) {
- // As of draft-ietf-tls-subcert-03, only the server may use delegated
- // credentials to authenticate itself.
+ // We only support delegated credentials as a server.
return hs->ssl->server &&
hs->delegated_credential_requested &&
ssl_can_serve_dc(hs);
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index ce080ee..676826f 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -110,6 +110,7 @@
extensionPadding uint16 = 21
extensionExtendedMasterSecret uint16 = 23
extensionCompressedCertAlgs uint16 = 27
+ extensionDelegatedCredentials uint16 = 34
extensionSessionTicket uint16 = 35
extensionPreSharedKey uint16 = 41
extensionEarlyData uint16 = 42
@@ -127,7 +128,6 @@
extensionRenegotiationInfo uint16 = 0xff01
extensionQUICTransportParamsLegacy uint16 = 0xffa5 // draft-ietf-quic-tls-32 and earlier
extensionChannelID uint16 = 30032 // not IANA assigned
- extensionDelegatedCredentials uint16 = 0x22 // draft-ietf-tls-subcerts-06
extensionDuplicate uint16 = 0xffff // not IANA assigned
extensionEncryptedClientHello uint16 = 0xfe0d // not IANA assigned
extensionECHOuterExtensions uint16 = 0xfd00 // not IANA assigned
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go
index d074bb5..e6db3f4 100644
--- a/ssl/test/runner/handshake_client.go
+++ b/ssl/test/runner/handshake_client.go
@@ -1803,7 +1803,7 @@
// delegatedCredentialSignedMessage returns the bytes that are signed in order
// to authenticate a delegated credential.
func delegatedCredentialSignedMessage(credBytes []byte, algorithm signatureAlgorithm, leafDER []byte) []byte {
- // https://tools.ietf.org/html/draft-ietf-tls-subcerts-03#section-3
+ // https://www.rfc-editor.org/rfc/rfc9345.html#section-4
ret := make([]byte, 64, 128)
for i := range ret {
ret[i] = 0x20
diff --git a/ssl/test/runner/handshake_messages.go b/ssl/test/runner/handshake_messages.go
index 991f08a..26e1257 100644
--- a/ssl/test/runner/handshake_messages.go
+++ b/ssl/test/runner/handshake_messages.go
@@ -1923,13 +1923,13 @@
}
type delegatedCredential struct {
- // https://tools.ietf.org/html/draft-ietf-tls-subcerts-03#section-3
- signedBytes []byte
- lifetimeSecs uint32
- expectedCertVerifyAlgo signatureAlgorithm
- pkixPublicKey []byte
- algorithm signatureAlgorithm
- signature []byte
+ // https://www.rfc-editor.org/rfc/rfc9345.html#section-4
+ signedBytes []byte
+ lifetimeSecs uint32
+ dcCertVerifyAlgo signatureAlgorithm
+ pkixPublicKey []byte
+ algorithm signatureAlgorithm
+ signature []byte
}
type certificateMsg struct {
@@ -2030,17 +2030,17 @@
case extensionSignedCertificateTimestamp:
cert.sctList = []byte(body)
case extensionDelegatedCredentials:
- // https://tools.ietf.org/html/draft-ietf-tls-subcerts-03#section-3
+ // https://www.rfc-editor.org/rfc/rfc9345.html#section-4
if cert.delegatedCredential != nil {
return false
}
dc := new(delegatedCredential)
origBody := body
- var expectedCertVerifyAlgo, algorithm uint16
+ var dcCertVerifyAlgo, algorithm uint16
if !body.ReadUint32(&dc.lifetimeSecs) ||
- !body.ReadUint16(&expectedCertVerifyAlgo) ||
+ !body.ReadUint16(&dcCertVerifyAlgo) ||
!readUint24LengthPrefixedBytes(&body, &dc.pkixPublicKey) ||
!body.ReadUint16(&algorithm) ||
!readUint16LengthPrefixedBytes(&body, &dc.signature) ||
@@ -2048,7 +2048,7 @@
return false
}
- dc.expectedCertVerifyAlgo = signatureAlgorithm(expectedCertVerifyAlgo)
+ dc.dcCertVerifyAlgo = signatureAlgorithm(dcCertVerifyAlgo)
dc.algorithm = signatureAlgorithm(algorithm)
dc.signedBytes = []byte(origBody)[:4+2+3+len(dc.pkixPublicKey)]
cert.delegatedCredential = dc
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 286a4be..cfccdcb 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -282,9 +282,9 @@
// certificate, that the delegated credential is valid for. If zero, then 24
// hours is assumed.
lifetime time.Duration
- // expectedAlgo is the signature scheme that should be used with this
- // delegated credential. If zero, ECDSA with P-256 is assumed.
- expectedAlgo signatureAlgorithm
+ // dcAlgo is the signature scheme that should be used with this delegated
+ // credential. If zero, ECDSA with P-256 is assumed.
+ dcAlgo signatureAlgorithm
// tlsVersion is the version of TLS that should be used with this delegated
// credential. If zero, TLS 1.3 is assumed.
tlsVersion uint16
@@ -320,14 +320,14 @@
}
func createDelegatedCredential(config delegatedCredentialConfig, parentDER []byte, parentPriv crypto.PrivateKey) (dc, privPKCS8 []uint8, err error) {
- expectedAlgo := config.expectedAlgo
- if expectedAlgo == signatureAlgorithm(0) {
- expectedAlgo = signatureECDSAWithP256AndSHA256
+ dcAlgo := config.dcAlgo
+ if dcAlgo == signatureAlgorithm(0) {
+ dcAlgo = signatureECDSAWithP256AndSHA256
}
var pub crypto.PublicKey
- switch expectedAlgo {
+ switch dcAlgo {
case signatureRSAPKCS1WithMD5, signatureRSAPKCS1WithSHA1, signatureRSAPKCS1WithSHA256, signatureRSAPKCS1WithSHA384, signatureRSAPKCS1WithSHA512, signatureRSAPSSWithSHA256, signatureRSAPSSWithSHA384, signatureRSAPSSWithSHA512:
// RSA keys are expensive to generate so load from disk instead.
var priv *rsa.PrivateKey
@@ -339,7 +339,7 @@
case signatureECDSAWithSHA1, signatureECDSAWithP256AndSHA256, signatureECDSAWithP384AndSHA384, signatureECDSAWithP521AndSHA512:
var curve elliptic.Curve
- switch expectedAlgo {
+ switch dcAlgo {
case signatureECDSAWithSHA1, signatureECDSAWithP256AndSHA256:
curve = elliptic.P256()
case signatureECDSAWithP384AndSHA384:
@@ -362,7 +362,7 @@
pub = &priv.PublicKey
default:
- return nil, nil, fmt.Errorf("unsupported expected signature algorithm: %x", expectedAlgo)
+ return nil, nil, fmt.Errorf("unsupported DC signature algorithm: %x", dcAlgo)
}
lifetime := config.lifetime
@@ -382,9 +382,9 @@
return nil, nil, fmt.Errorf("delegated credentials require TLS 1.3")
}
- // https://tools.ietf.org/html/draft-ietf-tls-subcerts-03#section-3
+ // https://www.rfc-editor.org/rfc/rfc9345.html#section-4
dc = append(dc, byte(lifetimeSecs>>24), byte(lifetimeSecs>>16), byte(lifetimeSecs>>8), byte(lifetimeSecs))
- dc = append(dc, byte(expectedAlgo>>8), byte(expectedAlgo))
+ dc = append(dc, byte(dcAlgo>>8), byte(dcAlgo))
pubBytes, err := x509.MarshalPKIXPublicKey(pub)
if err != nil {
@@ -7490,7 +7490,7 @@
ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
ALPSUseNewCodepoint: clientSends,
},
- resumeSession: true,
+ resumeSession: true,
flags: append([]string{
"-select-alpn", "proto",
"-on-initial-application-settings", "proto,shim1",