From 0328af0b7e6714a54846651ca76519da491cd591 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 6 Apr 2017 10:56:46 +1000 Subject: [PATCH] Bug 1350602 - TLS 1.3 draft-19 - CertificateRequest, r=ekr I ended up changing the extension handler function a little to deal with messages that allow unknown extensions better. I also changed tls13_ExtensionAllowed to only deal with those extensions that TLS 1.3 cares about. We now don't send point formats in TLS 1.3; I considered doing the same for renegotiation info, but decided against it. Differential Revision: https://nss-review.dev.mozaws.net/D280 --HG-- branch : NSS_TLS13_DRAFT19_BRANCH extra : rebase_source : 41533ac1e794b11925fc3b8b0f9424700fdc0f8b --- gtests/ssl_gtest/ssl_extension_unittest.cc | 11 +- gtests/ssl_gtest/tls_filter.cc | 7 - lib/ssl/ssl3con.c | 32 ++-- lib/ssl/ssl3ext.c | 96 ++++++---- lib/ssl/ssl3ext.h | 11 +- lib/ssl/ssl3exthandle.c | 39 +++-- lib/ssl/ssl3exthandle.h | 8 +- lib/ssl/sslcert.c | 10 +- lib/ssl/sslimpl.h | 37 ++-- lib/ssl/sslt.h | 1 + lib/ssl/tls13con.c | 195 ++++++++------------- lib/ssl/tls13con.h | 9 +- lib/ssl/tls13exthandle.c | 94 ++++++++++ lib/ssl/tls13exthandle.h | 7 + 14 files changed, 328 insertions(+), 229 deletions(-) diff --git a/gtests/ssl_gtest/ssl_extension_unittest.cc b/gtests/ssl_gtest/ssl_extension_unittest.cc index 23842f7263..06ec428ee5 100644 --- a/gtests/ssl_gtest/ssl_extension_unittest.cc +++ b/gtests/ssl_gtest/ssl_extension_unittest.cc @@ -1037,12 +1037,16 @@ class TlsBogusExtensionTest13 : public TlsBogusExtensionTest { return; } + FailWithAlert(kTlsAlertUnsupportedExtension); + } + + void FailWithAlert(uint8_t alert) { client_->StartConnect(); server_->StartConnect(); client_->Handshake(); // ClientHello server_->Handshake(); // ServerHello - client_->ExpectSendAlert(kTlsAlertUnsupportedExtension); + client_->ExpectSendAlert(alert); client_->Handshake(); if (mode_ == STREAM) { server_->ExpectSendAlert(kTlsAlertBadRecordMac); @@ -1067,9 +1071,12 @@ TEST_P(TlsBogusExtensionTest13, AddBogusExtensionCertificate) { Run(kTlsHandshakeCertificate); } +// It's perfectly valid to set unknown extensions in CertificateRequest. TEST_P(TlsBogusExtensionTest13, AddBogusExtensionCertificateRequest) { server_->RequestClientAuth(false); - Run(kTlsHandshakeCertificateRequest); + AddFilter(kTlsHandshakeCertificateRequest, 0xff); + FailWithAlert(kTlsAlertDecryptError); + client_->CheckErrorCode(SEC_ERROR_BAD_SIGNATURE); } TEST_P(TlsBogusExtensionTest13, AddBogusExtensionHelloRetryRequest) { diff --git a/gtests/ssl_gtest/tls_filter.cc b/gtests/ssl_gtest/tls_filter.cc index 76d9aaaffc..4c303c57e4 100644 --- a/gtests/ssl_gtest/tls_filter.cc +++ b/gtests/ssl_gtest/tls_filter.cc @@ -448,13 +448,6 @@ static bool FindCertReqExtensions(TlsParser* parser, if (!parser->SkipVariable(1)) { // request context return false; } - // TODO remove the next two for -19 - if (!parser->SkipVariable(2)) { // signature_algorithms - return false; - } - if (!parser->SkipVariable(2)) { // certificate_authorities - return false; - } return true; } diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c index c6757e60e2..d67ee513ca 100644 --- a/lib/ssl/ssl3con.c +++ b/lib/ssl/ssl3con.c @@ -6442,8 +6442,8 @@ ssl3_PickServerSignatureScheme(sslSocket *ss) /* Sets error code, if needed. */ return ssl_PickSignatureScheme(ss, keyPair->pubKey, keyPair->privKey, - ss->xtnData.clientSigSchemes, - ss->xtnData.numClientSigScheme, + ss->xtnData.sigSchemes, + ss->xtnData.numSigSchemes, PR_FALSE /* requireSha1 */); } @@ -7303,7 +7303,7 @@ typedef struct dnameNode { */ SECStatus ssl3_ParseCertificateRequestCAs(sslSocket *ss, SSL3Opaque **b, PRUint32 *length, - PLArenaPool *arena, CERTDistNames *ca_list) + CERTDistNames *ca_list) { PRUint32 remaining; int nnames = 0; @@ -7318,7 +7318,7 @@ ssl3_ParseCertificateRequestCAs(sslSocket *ss, SSL3Opaque **b, PRUint32 *length, if (remaining > *length) goto alert_loser; - ca_list->head = node = PORT_ArenaZNew(arena, dnameNode); + ca_list->head = node = PORT_ArenaZNew(ca_list->arena, dnameNode); if (node == NULL) goto no_mem; @@ -7344,14 +7344,14 @@ ssl3_ParseCertificateRequestCAs(sslSocket *ss, SSL3Opaque **b, PRUint32 *length, if (remaining <= 0) break; /* success */ - node->next = PORT_ArenaZNew(arena, dnameNode); + node->next = PORT_ArenaZNew(ca_list->arena, dnameNode); node = node->next; if (node == NULL) goto no_mem; } ca_list->nnames = nnames; - ca_list->names = PORT_ArenaNewArray(arena, SECItem, nnames); + ca_list->names = PORT_ArenaNewArray(ca_list->arena, SECItem, nnames); if (nnames > 0 && ca_list->names == NULL) goto no_mem; @@ -7495,7 +7495,7 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) } } - rv = ssl3_ParseCertificateRequestCAs(ss, &b, &length, arena, &ca_list); + rv = ssl3_ParseCertificateRequestCAs(ss, &b, &length, &ca_list); if (rv != SECSuccess) goto done; /* alert sent in ssl3_ParseCertificateRequestCAs */ @@ -9635,10 +9635,10 @@ ssl3_SendCertificateRequest(sslSocket *ss) const PRUint8 *certTypes; SECStatus rv; int length; - SECItem *names; + const SECItem *names; unsigned int calen; unsigned int nnames; - SECItem *name; + const SECItem *name; int i; int certTypesLength; PRUint8 sigAlgs[MAX_SIGNATURE_SCHEMES * 2]; @@ -10184,8 +10184,8 @@ ssl3_SendEmptyCertificate(sslSocket *ss) const SECItem *context; if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) { - PORT_Assert(ss->ssl3.hs.certificateRequest); - context = &ss->ssl3.hs.certificateRequest->context; + PORT_Assert(ss->ssl3.hs.clientCertRequested); + context = &ss->xtnData.certReqContext; len = context->len + 1; isTLS13 = PR_TRUE; } @@ -10414,8 +10414,8 @@ ssl3_SendCertificate(sslSocket *ss) if (isTLS13) { contextLen = 1; /* Size of the context length */ if (!ss->sec.isServer) { - PORT_Assert(ss->ssl3.hs.certificateRequest); - context = ss->ssl3.hs.certificateRequest->context; + PORT_Assert(ss->ssl3.hs.clientCertRequested); + context = ss->xtnData.certReqContext; contextLen += context.len; } } @@ -12889,7 +12889,6 @@ ssl3_InitState(sslSocket *ss) ss->ssl3.hs.serverHsTrafficSecret = NULL; ss->ssl3.hs.clientTrafficSecret = NULL; ss->ssl3.hs.serverTrafficSecret = NULL; - ss->ssl3.hs.certificateRequest = NULL; PR_INIT_CLIST(&ss->ssl3.hs.cipherSpecs); PORT_Assert(!ss->ssl3.hs.messages.buf && !ss->ssl3.hs.messages.space); @@ -13231,11 +13230,6 @@ ssl3_DestroySSL3Info(sslSocket *ss) SECITEM_FreeItem(&ss->ssl3.hs.newSessionTicket.ticket, PR_FALSE); SECITEM_FreeItem(&ss->ssl3.hs.srvVirtName, PR_FALSE); - if (ss->ssl3.hs.certificateRequest) { - PORT_FreeArena(ss->ssl3.hs.certificateRequest->arena, PR_FALSE); - ss->ssl3.hs.certificateRequest = NULL; - } - /* free up the CipherSpecs */ ssl3_DestroyCipherSpec(&ss->ssl3.specs[0], PR_TRUE /*freeSrvName*/); ssl3_DestroyCipherSpec(&ss->ssl3.specs[1], PR_TRUE /*freeSrvName*/); diff --git a/lib/ssl/ssl3ext.c b/lib/ssl/ssl3ext.c index 57f5ce76e0..4941de5b60 100644 --- a/lib/ssl/ssl3ext.c +++ b/lib/ssl/ssl3ext.c @@ -31,7 +31,7 @@ static const ssl3ExtensionHandler clientHelloHandlers[] = { { ssl_app_layer_protocol_xtn, &ssl3_ServerHandleAppProtoXtn }, { ssl_use_srtp_xtn, &ssl3_ServerHandleUseSRTPXtn }, { ssl_cert_status_xtn, &ssl3_ServerHandleStatusRequestXtn }, - { ssl_signature_algorithms_xtn, &ssl3_ServerHandleSigAlgsXtn }, + { ssl_signature_algorithms_xtn, &ssl3_HandleSigAlgsXtn }, { ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn }, { ssl_signed_cert_timestamp_xtn, &ssl3_ServerHandleSignedCertTimestampXtn }, { ssl_tls13_key_share_xtn, &tls13_ServerHandleKeyShareXtn }, @@ -88,6 +88,9 @@ static const ssl3ExtensionHandler serverCertificateHandlers[] = { }; static const ssl3ExtensionHandler certificateRequestHandlers[] = { + { ssl_signature_algorithms_xtn, &ssl3_HandleSigAlgsXtn }, + { ssl_tls13_certificate_authorities_xtn, + &tls13_ClientHandleCertAuthoritiesXtn }, { -1, NULL } }; @@ -101,7 +104,7 @@ static const ssl3ExtensionHandler certificateRequestHandlers[] = { * the client hello is empty (for example, the extended master secret * extension, if it were listed last). See bug 1243641. */ -static const ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = +static const ssl3HelloExtensionSender clientHelloSendersTLS[] = { { ssl_server_name_xtn, &ssl3_SendServerNameXtn }, { ssl_extended_master_secret_xtn, &ssl3_SendExtendedMasterSecretXtn }, @@ -122,19 +125,19 @@ static const ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] * signature_algorithms at the end. See bug 1243641. */ { ssl_tls13_supported_versions_xtn, &tls13_ClientSendSupportedVersionsXtn }, { ssl_tls13_short_header_xtn, &tls13_SendShortHeaderXtn }, - { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn }, + { ssl_signature_algorithms_xtn, &ssl3_SendSigAlgsXtn }, { ssl_tls13_cookie_xtn, &tls13_ClientSendHrrCookieXtn }, { ssl_tls13_psk_key_exchange_modes_xtn, &tls13_ClientSendPskKeyExchangeModesXtn }, { ssl_padding_xtn, &ssl3_ClientSendPaddingExtension }, /* The pre_shared_key extension MUST be last. */ { ssl_tls13_pre_shared_key_xtn, &tls13_ClientSendPreSharedKeyXtn }, - /* any extra entries will appear as { 0, NULL } */ + { 0, NULL } }; -static const ssl3HelloExtensionSender clientHelloSendersSSL3[SSL_MAX_EXTENSIONS] = { - { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn } - /* any extra entries will appear as { 0, NULL } */ +static const ssl3HelloExtensionSender clientHelloSendersSSL3[] = { + { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn }, + { 0, NULL } }; static PRBool @@ -258,6 +261,11 @@ ssl3_HandleParsedExtensions(sslSocket *ss, * do so, but we weren't entirely sure. TODO(ekr@rtfm.com). */ PRBool isTLS13 = (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) || (handshakeMessage == hello_retry_request); + /* The following messages can include extensions that were not included in + * the original ClientHello. */ + PRBool allowNotOffered = (handshakeMessage == client_hello) || + (handshakeMessage == certificate_request) || + (handshakeMessage == new_session_ticket); PRCList *cursor; switch (handshakeMessage) { @@ -302,25 +310,35 @@ ssl3_HandleParsedExtensions(sslSocket *ss, const ssl3ExtensionHandler *handler; /* Check whether the server sent an extension which was not advertised - * in the ClientHello */ - if (!ss->sec.isServer && - !ssl3_ClientExtensionAdvertised(ss, extension->type) && - (handshakeMessage != new_session_ticket) && - (extension->type != ssl_tls13_cookie_xtn)) { + * in the ClientHello. + * + * Note that a TLS 1.3 server should check if CertificateRequest + * extensions were sent. But the extensions used for CertificateRequest + * do not have any response, so we rely on + * ssl3_ClientExtensionAdvertised to return false on the server. That + * results in the server only rejecting any extension. */ + if (!allowNotOffered && (extension->type != ssl_tls13_cookie_xtn) && + !ssl3_ClientExtensionAdvertised(ss, extension->type)) { (void)SSL3_SendAlert(ss, alert_fatal, unsupported_extension); PORT_SetError(SSL_ERROR_RX_UNEXPECTED_EXTENSION); return SECFailure; } /* Check that this is a legal extension in TLS 1.3 */ - if (isTLS13 && !tls13_ExtensionAllowed(extension->type, handshakeMessage)) { - if (handshakeMessage == client_hello) { - /* Skip extensions not used in TLS 1.3 */ - continue; + if (isTLS13) { + switch (tls13_ExtensionStatus(extension->type, handshakeMessage)) { + case tls13_extension_allowed: + break; + case tls13_extension_unknown: + if (allowNotOffered) { + continue; /* Skip over unknown extensions. */ + } + /* Fall through. */ + case tls13_extension_disallowed: + tls13_FatalError(ss, SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION, + unsupported_extension); + return SECFailure; } - tls13_FatalError(ss, SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION, - unsupported_extension); - return SECFailure; } /* Special check for this being the last extension if it's @@ -350,6 +368,7 @@ ssl3_HandleParsedExtensions(sslSocket *ss, } return SECFailure; } + break; } } } @@ -390,14 +409,21 @@ ssl3_RegisterExtensionSender(const sslSocket *ss, if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { sender = &xtnData->serverHelloSenders[0]; } else { - if (tls13_ExtensionAllowed(ex_type, server_hello)) { - PORT_Assert(!tls13_ExtensionAllowed(ex_type, encrypted_extensions)); + if (tls13_ExtensionStatus(ex_type, server_hello) == + tls13_extension_allowed) { + PORT_Assert(tls13_ExtensionStatus(ex_type, encrypted_extensions) == + tls13_extension_disallowed); sender = &xtnData->serverHelloSenders[0]; - } else if (tls13_ExtensionAllowed(ex_type, certificate)) { + } else if (tls13_ExtensionStatus(ex_type, encrypted_extensions) == + tls13_extension_allowed) { + sender = &xtnData->encryptedExtensionsSenders[0]; + } else if (tls13_ExtensionStatus(ex_type, certificate) == + tls13_extension_allowed) { sender = &xtnData->certificateSenders[0]; } else { - PORT_Assert(tls13_ExtensionAllowed(ex_type, encrypted_extensions)); - sender = &xtnData->encryptedExtensionsSenders[0]; + PORT_Assert(0); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; } } for (i = 0; i < SSL_MAX_EXTENSIONS; ++i, ++sender) { @@ -424,7 +450,6 @@ ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes, const ssl3HelloExtensionSender *sender) { PRInt32 total_exten_len = 0; - int i; if (!sender) { if (ss->vrange.max > SSL_LIBRARY_VERSION_3_0) { @@ -434,14 +459,14 @@ ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes, } } - for (i = 0; i < SSL_MAX_EXTENSIONS; ++i, ++sender) { - if (sender->ex_sender) { - PRInt32 extLen = (*sender->ex_sender)(ss, &ss->xtnData, append, maxBytes); - if (extLen < 0) - return -1; - maxBytes -= extLen; - total_exten_len += extLen; + while (sender->ex_sender) { + PRInt32 extLen = (*sender->ex_sender)(ss, &ss->xtnData, append, maxBytes); + if (extLen < 0) { + return -1; } + maxBytes -= extLen; + total_exten_len += extLen; + ++sender; } return total_exten_len; } @@ -475,9 +500,14 @@ ssl3_ResetExtensionData(TLSExtensionData *xtnData) { /* Clean up. */ ssl3_FreeSniNameArray(xtnData); - PORT_Free(xtnData->clientSigSchemes); + PORT_Free(xtnData->sigSchemes); SECITEM_FreeItem(&xtnData->nextProto, PR_FALSE); tls13_DestroyKeyShares(&xtnData->remoteKeyShares); + SECITEM_FreeItem(&xtnData->certReqContext, PR_FALSE); + if (xtnData->certReqAuthorities.arena) { + PORT_FreeArena(xtnData->certReqAuthorities.arena, PR_FALSE); + xtnData->certReqAuthorities.arena = NULL; + } /* Now reinit. */ ssl3_InitExtensionData(xtnData); diff --git a/lib/ssl/ssl3ext.h b/lib/ssl/ssl3ext.h index 0aff52399e..4589701f9c 100644 --- a/lib/ssl/ssl3ext.h +++ b/lib/ssl/ssl3ext.h @@ -86,10 +86,13 @@ struct TLSExtensionDataStr { PRBool peerSupportsFfdheGroups; /* if the peer supports named ffdhe groups */ /* clientSigAndHash contains the contents of the signature_algorithms - * extension (if any) from the client. This is only valid for TLS 1.2 - * or later. */ - SSLSignatureScheme *clientSigSchemes; - unsigned int numClientSigScheme; + * extension (if any) the other side supports. This is only valid for TLS + * 1.2 or later. In TLS 1.3, it is also used for CertificateRequest. */ + SSLSignatureScheme *sigSchemes; + unsigned int numSigSchemes; + + SECItem certReqContext; + CERTDistNames certReqAuthorities; /* In a client: if the server supports Next Protocol Negotiation, then * this is the protocol that was negotiated. diff --git a/lib/ssl/ssl3exthandle.c b/lib/ssl/ssl3exthandle.c index bbec1c74fe..28c73cbbf1 100644 --- a/lib/ssl/ssl3exthandle.c +++ b/lib/ssl/ssl3exthandle.c @@ -380,6 +380,8 @@ SECStatus ssl3_ServerHandleNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { + PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3); + if (ss->firstHsDone || data->len != 0) { /* Clients MUST send an empty NPN extension, if any. */ PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); @@ -521,6 +523,7 @@ SECStatus ssl3_ClientHandleNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { + PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3); PORT_Assert(!ss->firstHsDone); if (ssl3_ExtensionNegotiated(ss, ssl_app_layer_protocol_xtn)) { @@ -1276,6 +1279,8 @@ SECStatus ssl3_ClientHandleSessionTicketXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { + PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3); + if (data->len != 0) { return SECSuccess; /* Ignore the extension. */ } @@ -1740,6 +1745,7 @@ SECStatus ssl3_ServerHandleSessionTicketXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { + PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3); /* Ignore the SessionTicket extension if processing is disabled. */ if (!ss->opt.enableSessionTickets) { @@ -1839,11 +1845,14 @@ ssl3_SendRenegotiationInfoXtn( /* This function runs in both the client and server. */ SECStatus -ssl3_HandleRenegotiationInfoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) +ssl3_HandleRenegotiationInfoXtn(const sslSocket *ss, TLSExtensionData *xtnData, + PRUint16 ex_type, SECItem *data) { SECStatus rv = SECSuccess; PRUint32 len = 0; + PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3); + if (ss->firstHsDone) { len = ss->sec.isServer ? ss->ssl3.hs.finishedBytes : ss->ssl3.hs.finishedBytes * 2; @@ -2092,11 +2101,12 @@ ssl3_ServerHandleUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUi ssl3_ServerSendUseSRTPXtn); } -/* ssl3_ServerHandleSigAlgsXtn handles the signature_algorithms extension - * from a client. - * See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */ +/* ssl3_HandleSigAlgsXtn handles the signature_algorithms extension from a + * client. In TLS 1.3, the client uses this to parse CertificateRequest + * extensions. See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */ SECStatus -ssl3_ServerHandleSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) +ssl3_HandleSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, + PRUint16 ex_type, SECItem *data) { SECStatus rv; @@ -2105,15 +2115,15 @@ ssl3_ServerHandleSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUi return SECSuccess; } - if (xtnData->clientSigSchemes) { - PORT_Free(xtnData->clientSigSchemes); - xtnData->clientSigSchemes = NULL; + if (xtnData->sigSchemes) { + PORT_Free(xtnData->sigSchemes); + xtnData->sigSchemes = NULL; } rv = ssl_ParseSignatureSchemes(ss, NULL, - &xtnData->clientSigSchemes, - &xtnData->numClientSigScheme, + &xtnData->sigSchemes, + &xtnData->numSigSchemes, &data->data, &data->len); - if (rv != SECSuccess || xtnData->numClientSigScheme == 0) { + if (rv != SECSuccess || xtnData->numSigSchemes == 0) { ssl3_ExtSendAlert(ss, alert_fatal, decode_error); PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); return SECFailure; @@ -2133,7 +2143,8 @@ ssl3_ServerHandleSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUi /* ssl3_ClientSendSigAlgsXtn sends the signature_algorithm extension for TLS * 1.2 ClientHellos. */ PRInt32 -ssl3_ClientSendSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) +ssl3_SendSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, + PRBool append, PRUint32 maxBytes) { PRInt32 extension_length; PRUint8 buf[MAX_SIGNATURE_SCHEMES * 2]; @@ -2297,6 +2308,8 @@ SECStatus ssl3_HandleExtendedMasterSecretXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { + PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3); + if (ss->version < SSL_LIBRARY_VERSION_TLS_1_0) { return SECSuccess; } @@ -2448,6 +2461,8 @@ ssl3_HandleSupportedPointFormatsXtn(const sslSocket *ss, TLSExtensionData *xtnDa { int i; + PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3); + if (data->len < 2 || data->len > 255 || !data->data || data->len != (unsigned int)data->data[0] + 1) { ssl3_ExtDecodeError(ss); diff --git a/lib/ssl/ssl3exthandle.h b/lib/ssl/ssl3exthandle.h index 5fdbe9053a..281020b953 100644 --- a/lib/ssl/ssl3exthandle.h +++ b/lib/ssl/ssl3exthandle.h @@ -44,10 +44,10 @@ SECStatus ssl3_ClientHandleStatusRequestXtn(const sslSocket *ss, TLSExtensionDat SECItem *data); PRInt32 ssl3_ClientSendStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes); -PRInt32 ssl3_ClientSendSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, - PRUint32 maxBytes); -SECStatus ssl3_ServerHandleSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, - SECItem *data); +PRInt32 ssl3_SendSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, + PRBool append, PRUint32 maxBytes); +SECStatus ssl3_HandleSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, + PRUint16 ex_type, SECItem *data); PRInt32 ssl3_ClientSendPaddingExtension(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes); diff --git a/lib/ssl/sslcert.c b/lib/ssl/sslcert.c index 388fc09501..b262487c16 100644 --- a/lib/ssl/sslcert.c +++ b/lib/ssl/sslcert.c @@ -46,7 +46,7 @@ ssl_SetupCAListOnce(void *arg) } SECStatus -ssl_SetupCAList(sslSocket *ss) +ssl_SetupCAList(const sslSocket *ss) { if (PR_SUCCESS != PR_CallOnceWithArg(&ssl_server_ca_list.setup, &ssl_SetupCAListOnce, @@ -58,11 +58,11 @@ ssl_SetupCAList(sslSocket *ss) } SECStatus -ssl_GetCertificateRequestCAs(sslSocket *ss, unsigned int *calen, - SECItem **names, unsigned int *nnames) +ssl_GetCertificateRequestCAs(const sslSocket *ss, unsigned int *calen, + const SECItem **names, unsigned int *nnames) { - SECItem *name; - CERTDistNames *ca_list; + const SECItem *name; + const CERTDistNames *ca_list; unsigned int i; *calen = 0; diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h index 7cb25836da..ffd4f20f42 100644 --- a/lib/ssl/sslimpl.h +++ b/lib/ssl/sslimpl.h @@ -760,15 +760,6 @@ typedef enum { handshake_hash_record } SSL3HandshakeHashType; -/* This holds state for TLS 1.3 CertificateRequest handling. */ -typedef struct TLS13CertificateRequestStr { - PLArenaPool *arena; - SECItem context; - SSLSignatureScheme *signatureSchemes; - unsigned int signatureSchemeCount; - CERTDistNames ca_list; -} TLS13CertificateRequest; - /* ** This is the "hs" member of the "ssl3" struct. ** This entire struct is protected by ssl3HandshakeLock @@ -869,20 +860,19 @@ typedef struct SSL3HandshakeStateStr { PK11SymKey *serverTrafficSecret; /* traffic keys */ PK11SymKey *earlyExporterSecret; /* for 0-RTT exporters */ PK11SymKey *exporterSecret; /* for exporters */ - /* The certificate request from the server. */ - TLS13CertificateRequest *certificateRequest; - PRCList cipherSpecs; /* The cipher specs in the sequence they + PRCList cipherSpecs; /* The cipher specs in the sequence they * will be applied. */ - sslZeroRttState zeroRttState; /* Are we doing a 0-RTT handshake? */ - sslZeroRttIgnore zeroRttIgnore; /* Are we ignoring 0-RTT? */ - ssl3CipherSuite zeroRttSuite; /* The cipher suite we used for 0-RTT. */ - PRCList bufferedEarlyData; /* Buffered TLS 1.3 early data + sslZeroRttState zeroRttState; /* Are we doing a 0-RTT handshake? */ + sslZeroRttIgnore zeroRttIgnore; /* Are we ignoring 0-RTT? */ + ssl3CipherSuite zeroRttSuite; /* The cipher suite we used for 0-RTT. */ + PRCList bufferedEarlyData; /* Buffered TLS 1.3 early data * on server.*/ - PRBool helloRetry; /* True if HelloRetryRequest has been sent + PRBool helloRetry; /* True if HelloRetryRequest has been sent * or received. */ - ssl3KEADef kea_def_mutable; /* Used to hold the writable kea_def + PRBool clientCertRequested; /* True if CertificateRequest received. */ + ssl3KEADef kea_def_mutable; /* Used to hold the writable kea_def * we use for TLS 1.3 */ - PRBool shortHeaders; /* Assigned if we are doing short headers. */ + PRBool shortHeaders; /* Assigned if we are doing short headers. */ } SSL3HandshakeState; /* @@ -1792,11 +1782,12 @@ SECStatus ssl_ReadCertificateStatus(sslSocket *ss, SSL3Opaque *b, PRUint32 length); SECStatus ssl3_EncodeSigAlgs(const sslSocket *ss, PRUint8 *buf, unsigned maxLen, PRUint32 *len); -SECStatus ssl_GetCertificateRequestCAs(sslSocket *ss, unsigned int *calenp, - SECItem **namesp, unsigned int *nnamesp); +SECStatus ssl_GetCertificateRequestCAs(const sslSocket *ss, + unsigned int *calenp, + const SECItem **namesp, + unsigned int *nnamesp); SECStatus ssl3_ParseCertificateRequestCAs(sslSocket *ss, SSL3Opaque **b, - PRUint32 *length, PLArenaPool *arena, - CERTDistNames *ca_list); + PRUint32 *length, CERTDistNames *ca_list); SECStatus ssl3_CompleteHandleCertificateRequest( sslSocket *ss, const SSLSignatureScheme *signatureSchemes, unsigned int signatureSchemeCount, CERTDistNames *ca_list); diff --git a/lib/ssl/sslt.h b/lib/ssl/sslt.h index 6ae31f3f06..3b298faf12 100644 --- a/lib/ssl/sslt.h +++ b/lib/ssl/sslt.h @@ -402,6 +402,7 @@ typedef enum { ssl_tls13_cookie_xtn = 44, ssl_tls13_psk_key_exchange_modes_xtn = 45, ssl_tls13_ticket_early_data_info_xtn = 46, /* Deprecated. */ + ssl_tls13_certificate_authorities_xtn = 47, ssl_next_proto_nego_xtn = 13172, ssl_renegotiation_info_xtn = 0xff01, ssl_tls13_short_header_xtn = 0xff03 diff --git a/lib/ssl/tls13con.c b/lib/ssl/tls13con.c index 3c5e9ebda2..2dcb2b692b 100644 --- a/lib/ssl/tls13con.c +++ b/lib/ssl/tls13con.c @@ -17,6 +17,7 @@ #include "sslimpl.h" #include "sslproto.h" #include "sslerr.h" +#include "ssl3exthandle.h" #include "tls13hkdf.h" #include "tls13con.h" #include "tls13exthandle.h" @@ -1204,8 +1205,8 @@ tls13_SelectServerCert(sslSocket *ss) rv = ssl_PickSignatureScheme(ss, cert->serverKeyPair->pubKey, cert->serverKeyPair->privKey, - ss->xtnData.clientSigSchemes, - ss->xtnData.numClientSigScheme, + ss->xtnData.sigSchemes, + ss->xtnData.numSigSchemes, PR_FALSE); if (rv == SECSuccess) { /* Found one. */ @@ -1598,6 +1599,12 @@ tls13_HandleClientKeyShare(sslSocket *ss, TLS13KeyShareEntry *peerShare) return rv; /* Error code set already. */ } +static const ssl3HelloExtensionSender tls13_cert_req_senders[] = { + { ssl_signature_algorithms_xtn, &ssl3_SendSigAlgsXtn }, + { ssl_tls13_certificate_authorities_xtn, &tls13_SendCertAuthoritiesXtn }, + { 0, NULL } +}; + /* * [draft-ietf-tls-tls13-11] Section 6.3.3.2 * @@ -1620,56 +1627,36 @@ static SECStatus tls13_SendCertificateRequest(sslSocket *ss) { SECStatus rv; - unsigned int calen; - SECItem *names; - unsigned int nnames; - SECItem *name; - int i; - PRUint8 sigSchemes[MAX_SIGNATURE_SCHEMES * 2]; - unsigned int sigSchemesLength = 0; - int length; + PRInt32 extLen; SSL_TRC(3, ("%d: TLS13[%d]: begin send certificate_request", SSL_GETPID(), ss->fd)); - rv = ssl3_EncodeSigAlgs(ss, sigSchemes, sizeof(sigSchemes), - &sigSchemesLength); - if (rv != SECSuccess) { - return rv; - } - - rv = ssl_GetCertificateRequestCAs(ss, &calen, &names, &nnames); - if (rv != SECSuccess) { - return rv; - } - length = 1 + 0 /* length byte for empty request context */ + - 2 + sigSchemesLength + 2 + calen + 2; + extLen = ssl3_CallHelloExtensionSenders(ss, PR_FALSE, 0xffff, + tls13_cert_req_senders); + PORT_Assert(extLen > 0); /* These can't be empty. */ - rv = ssl3_AppendHandshakeHeader(ss, certificate_request, length); + rv = ssl3_AppendHandshakeHeader(ss, certificate_request, + 1 + 0 + /* empty request context */ + 2 + extLen /* len + extensions */); if (rv != SECSuccess) { return rv; /* err set by AppendHandshake. */ } + + /* Context. */ rv = ssl3_AppendHandshakeNumber(ss, 0, 1); if (rv != SECSuccess) { return rv; /* err set by AppendHandshake. */ } - rv = ssl3_AppendHandshakeVariable(ss, sigSchemes, sigSchemesLength, 2); - if (rv != SECSuccess) { - return rv; /* err set by AppendHandshake. */ - } - rv = ssl3_AppendHandshakeNumber(ss, calen, 2); + /* Extensions. */ + rv = ssl3_AppendHandshakeNumber(ss, extLen, 2); if (rv != SECSuccess) { return rv; /* err set by AppendHandshake. */ } - for (i = 0, name = names; i < nnames; i++, name++) { - rv = ssl3_AppendHandshakeVariable(ss, name->data, name->len, 2); - if (rv != SECSuccess) { - return rv; /* err set by AppendHandshake. */ - } - } - rv = ssl3_AppendHandshakeNumber(ss, 0, 2); - if (rv != SECSuccess) { - return rv; /* err set by AppendHandshake. */ + extLen = ssl3_CallHelloExtensionSenders(ss, PR_TRUE, extLen, + tls13_cert_req_senders); + if (extLen < 0) { + return SECFailure; /* rely on the extension sender setting code */ } return SECSuccess; @@ -1768,9 +1755,7 @@ static SECStatus tls13_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) { SECStatus rv; - TLS13CertificateRequest *certRequest = NULL; SECItem context = { siBuffer, NULL, 0 }; - PLArenaPool *arena; SECItem extensionsData = { siBuffer, NULL, 0 }; SSL_TRC(3, ("%d: TLS13[%d]: handle certificate_request sequence", @@ -1789,71 +1774,51 @@ tls13_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) PORT_Assert(ss->ssl3.clientCertChain == NULL); PORT_Assert(ss->ssl3.clientCertificate == NULL); PORT_Assert(ss->ssl3.clientPrivateKey == NULL); - PORT_Assert(ss->ssl3.hs.certificateRequest == NULL); + PORT_Assert(!ss->ssl3.hs.clientCertRequested); - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (!arena) { - FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); + rv = ssl3_ConsumeHandshakeVariable(ss, &context, 1, &b, &length); + if (rv != SECSuccess) { return SECFailure; } - rv = ssl3_ConsumeHandshakeVariable(ss, &context, 1, &b, &length); - if (rv != SECSuccess) - goto loser; - /* We don't support post-handshake client auth, the certificate request - * context must always be null. */ + * context must always be empty. */ if (context.len > 0) { FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_REQUEST, illegal_parameter); - goto loser; - } - - certRequest = PORT_ArenaZNew(arena, TLS13CertificateRequest); - if (!certRequest) - goto loser; - certRequest->arena = arena; - certRequest->ca_list.arena = arena; - - rv = ssl_ParseSignatureSchemes(ss, arena, - &certRequest->signatureSchemes, - &certRequest->signatureSchemeCount, - &b, &length); - if (rv != SECSuccess || certRequest->signatureSchemeCount == 0) { - FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_REQUEST, - decode_error); - goto loser; + return SECFailure; } - rv = ssl3_ParseCertificateRequestCAs(ss, &b, &length, arena, - &certRequest->ca_list); - if (rv != SECSuccess) - goto loser; /* alert already sent */ - - /* Verify that the extensions are sane. */ rv = ssl3_ConsumeHandshakeVariable(ss, &extensionsData, 2, &b, &length); if (rv != SECSuccess) { - goto loser; + return SECFailure; } - /* Process all the extensions (note: currently a no-op). */ + if (length) { + FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_REQUEST, decode_error); + return SECFailure; + } + + /* Process all the extensions. */ rv = ssl3_HandleExtensions(ss, &extensionsData.data, &extensionsData.len, certificate_request); if (rv != SECSuccess) { - goto loser; + return SECFailure; } - rv = SECITEM_CopyItem(arena, &certRequest->context, &context); - if (rv != SECSuccess) - goto loser; + if (!ss->xtnData.numSigSchemes) { + FATAL_ERROR(ss, SSL_ERROR_MISSING_SIGNATURE_ALGORITHMS_EXTENSION, + missing_extension); + return SECFailure; + } - TLS13_SET_HS_STATE(ss, wait_server_cert); - ss->ssl3.hs.certificateRequest = certRequest; + rv = SECITEM_CopyItem(NULL, &ss->xtnData.certReqContext, &context); + if (rv != SECSuccess) { + return SECFailure; + } + ss->ssl3.hs.clientCertRequested = PR_TRUE; + TLS13_SET_HS_STATE(ss, wait_server_cert); return SECSuccess; - -loser: - PORT_FreeArena(arena, PR_FALSE); - return SECFailure; } static SECStatus @@ -2215,8 +2180,8 @@ tls13_SendCertificate(sslSocket *ss) ss, PR_FALSE, maxBytes, &ss->xtnData.certificateSenders[0]); if (!ss->sec.isServer) { - PORT_Assert(ss->ssl3.hs.certificateRequest); - context = ss->ssl3.hs.certificateRequest->context; + PORT_Assert(ss->ssl3.hs.clientCertRequested); + context = ss->xtnData.certReqContext; } if (certChain) { for (i = 0; i < certChain->len; i++) { @@ -2227,8 +2192,7 @@ tls13_SendCertificate(sslSocket *ss) } rv = ssl3_AppendHandshakeHeader(ss, certificate, - 1 + context.len + - 3 + certChainLen); + 1 + context.len + 3 + certChainLen); if (rv != SECSuccess) { return SECFailure; /* err set by AppendHandshake. */ } @@ -3329,13 +3293,11 @@ tls13_HandleCertificateVerify(sslSocket *ss, SSL3Opaque *b, PRUint32 length, } /* Request a client certificate now if one was requested. */ - if (ss->ssl3.hs.certificateRequest) { - TLS13CertificateRequest *req = ss->ssl3.hs.certificateRequest; - + if (ss->ssl3.hs.clientCertRequested) { PORT_Assert(!ss->sec.isServer); - rv = ssl3_CompleteHandleCertificateRequest(ss, req->signatureSchemes, - req->signatureSchemeCount, - &req->ca_list); + rv = ssl3_CompleteHandleCertificateRequest( + ss, ss->xtnData.sigSchemes, ss->xtnData.numSigSchemes, + &ss->xtnData.certReqAuthorities); if (rv != SECSuccess) { FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); return rv; @@ -3680,9 +3642,15 @@ tls13_SendClientSecondFlight(sslSocket *ss, PRBool sendClientCert, return SECFailure; /* error code is set. */ } } - if (ss->ssl3.hs.certificateRequest) { - PORT_FreeArena(ss->ssl3.hs.certificateRequest->arena, PR_FALSE); - ss->ssl3.hs.certificateRequest = NULL; + if (ss->ssl3.hs.clientCertRequested) { + SECITEM_FreeItem(&ss->xtnData.certReqContext, PR_FALSE); + if (ss->xtnData.certReqAuthorities.arena) { + PORT_FreeArena(ss->xtnData.certReqAuthorities.arena, PR_FALSE); + ss->xtnData.certReqAuthorities.arena = NULL; + } + PORT_Memset(&ss->xtnData.certReqAuthorities, 0, + sizeof(ss->xtnData.certReqAuthorities)); + ss->ssl3.hs.clientCertRequested = PR_FALSE; } if (sendClientCert) { @@ -3946,7 +3914,7 @@ tls13_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length) /* Parse extensions. */ rv = ssl3_ConsumeHandshakeVariable(ss, &data, 2, &b, &length); - if (rv != SECSuccess) { + if (rv != SECSuccess || length) { FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET, decode_error); return SECFailure; @@ -3964,12 +3932,6 @@ tls13_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length) ticket.max_early_data_size = ss->xtnData.max_early_data_size; } - if (length != 0) { - FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET, - decode_error); - return SECFailure; - } - if (!ss->opt.noCache) { PORT_Assert(ss->sec.ci.sid); rv = SECITEM_CopyItem(NULL, &ticket.ticket, &ticket_data); @@ -4028,31 +3990,28 @@ static const struct { } KnownExtensions[] = { { ssl_server_name_xtn, _M2(client_hello, encrypted_extensions) }, { ssl_supported_groups_xtn, _M2(client_hello, encrypted_extensions) }, - { ssl_ec_point_formats_xtn, 0 }, { ssl_signature_algorithms_xtn, _M2(client_hello, certificate_request) }, { ssl_use_srtp_xtn, _M2(client_hello, encrypted_extensions) }, { ssl_app_layer_protocol_xtn, _M2(client_hello, encrypted_extensions) }, { ssl_padding_xtn, _M1(client_hello) }, - { ssl_extended_master_secret_xtn, 0 }, - { ssl_session_ticket_xtn, 0 }, { ssl_tls13_key_share_xtn, _M3(client_hello, server_hello, hello_retry_request) }, { ssl_tls13_pre_shared_key_xtn, _M2(client_hello, server_hello) }, { ssl_tls13_psk_key_exchange_modes_xtn, _M1(client_hello) }, { ssl_tls13_early_data_xtn, _M3(client_hello, encrypted_extensions, new_session_ticket) }, - { ssl_next_proto_nego_xtn, 0 }, - { ssl_renegotiation_info_xtn, 0 }, { ssl_signed_cert_timestamp_xtn, _M3(client_hello, certificate_request, certificate) }, { ssl_cert_status_xtn, _M3(client_hello, certificate_request, certificate) }, { ssl_tls13_cookie_xtn, _M2(client_hello, hello_retry_request) }, { ssl_tls13_short_header_xtn, _M2(client_hello, server_hello) }, + { ssl_tls13_certificate_authorities_xtn, _M1(certificate_request) }, + { ssl_tls13_supported_versions_xtn, _M1(client_hello) } }; -PRBool -tls13_ExtensionAllowed(PRUint16 extension, SSL3HandshakeType message) +tls13ExtensionStatus +tls13_ExtensionStatus(PRUint16 extension, SSL3HandshakeType message) { unsigned int i; @@ -4067,25 +4026,23 @@ tls13_ExtensionAllowed(PRUint16 extension, SSL3HandshakeType message) for (i = 0; i < PR_ARRAY_SIZE(KnownExtensions); i++) { /* Hacky check for message numbers > 30. */ PORT_Assert(!(KnownExtensions[i].messages & (1U << 31))); - if (KnownExtensions[i].ex_value == extension) + if (KnownExtensions[i].ex_value == extension) { break; + } } - if (i == PR_ARRAY_SIZE(KnownExtensions)) { - /* We have never heard of this extension which is OK - * in client_hello and new_session_ticket. */ - return (message == client_hello) || - (message == new_session_ticket); + if (i >= PR_ARRAY_SIZE(KnownExtensions)) { + return tls13_extension_unknown; } - /* Return PR_TRUE iff the message mask bit is set. */ + /* Return "disallowed" if the message mask bit isn't set. */ if (!(_M1(message) & KnownExtensions[i].messages)) { SSL_TRC(3, ("%d: TLS13: unexpected extension %d in message %d", SSL_GETPID(), extension, message)); - return PR_FALSE; + return tls13_extension_disallowed; } - return PR_TRUE; + return tls13_extension_allowed; } #undef _M1 diff --git a/lib/ssl/tls13con.h b/lib/ssl/tls13con.h index 112e2fd275..7ccf6ec195 100644 --- a/lib/ssl/tls13con.h +++ b/lib/ssl/tls13con.h @@ -14,6 +14,12 @@ typedef enum { EphemeralSharedSecret } SharedSecretType; +typedef enum { + tls13_extension_allowed, + tls13_extension_disallowed, + tls13_extension_unknown +} tls13ExtensionStatus; + #define TLS13_MAX_FINISHED_SIZE 64 SECStatus tls13_UnprotectRecord( @@ -76,7 +82,8 @@ void tls13_DestroyEarlyData(PRCList *list); void tls13_CipherSpecAddRef(ssl3CipherSpec *spec); void tls13_CipherSpecRelease(ssl3CipherSpec *spec); void tls13_DestroyCipherSpecs(PRCList *list); -PRBool tls13_ExtensionAllowed(PRUint16 extension, SSL3HandshakeType message); +tls13ExtensionStatus tls13_ExtensionStatus(PRUint16 extension, + SSL3HandshakeType message); SECStatus tls13_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, SSL3ContentType type, diff --git a/lib/ssl/tls13exthandle.c b/lib/ssl/tls13exthandle.c index eb2aef42b5..107a4719ec 100644 --- a/lib/ssl/tls13exthandle.c +++ b/lib/ssl/tls13exthandle.c @@ -1185,3 +1185,97 @@ tls13_HandleShortHeaderXtn( return SECSuccess; } + +PRInt32 +tls13_SendCertAuthoritiesXtn(const sslSocket *ss, TLSExtensionData *xtnData, + PRBool append, PRUint32 maxBytes) +{ + unsigned int extensionLen; + unsigned int calen; + const SECItem *name; + unsigned int nnames; + SECStatus rv; + + PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3); + + rv = ssl_GetCertificateRequestCAs(ss, &calen, &name, &nnames); + if (rv != SECSuccess) { + return -1; + } + + if (!calen) { + return 0; + } + + extensionLen = 2 + 2 + 2 + calen; /* type, length, inner length, CA list */ + if (maxBytes < extensionLen) { + PORT_Assert(0); + return 0; + } + + if (append) { + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_certificate_authorities_xtn, 2); + if (rv != SECSuccess) { + return -1; + } + rv = ssl3_ExtAppendHandshakeNumber(ss, calen + 2, 2); + if (rv != SECSuccess) { + return -1; + } + rv = ssl3_ExtAppendHandshakeNumber(ss, calen, 2); + if (rv != SECSuccess) { + return -1; + } + + while (nnames) { + rv = ssl3_ExtAppendHandshakeVariable(ss, name->data, name->len, 2); + if (rv != SECSuccess) { + return -1; + } + ++name; + --nnames; + } + } + + return extensionLen; +} + +SECStatus +tls13_ClientHandleCertAuthoritiesXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + PRUint16 ex_type, SECItem *data) +{ + SECStatus rv; + PLArenaPool *arena; + + if (!data->len) { + ssl3_ExtSendAlert(ss, alert_fatal, decode_error); + PORT_SetError(SSL_ERROR_RX_MALFORMED_CERT_REQUEST); + return SECFailure; + } + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (!arena) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + + xtnData->certReqAuthorities.arena = arena; + rv = ssl3_ParseCertificateRequestCAs((sslSocket *)ss, + &data->data, &data->len, + &xtnData->certReqAuthorities); + if (rv != SECSuccess) { + goto loser; + } + if (data->len) { + ssl3_ExtSendAlert(ss, alert_fatal, decode_error); + PORT_SetError(SSL_ERROR_RX_MALFORMED_CERT_REQUEST); + goto loser; + } + return SECSuccess; + +loser: + PORT_FreeArena(arena, PR_FALSE); + xtnData->certReqAuthorities.arena = NULL; + return SECFailure; +} diff --git a/lib/ssl/tls13exthandle.h b/lib/ssl/tls13exthandle.h index f06d3e6949..7b7b3f8743 100644 --- a/lib/ssl/tls13exthandle.h +++ b/lib/ssl/tls13exthandle.h @@ -71,4 +71,11 @@ SECStatus tls13_HandleShortHeaderXtn( const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); +PRInt32 tls13_SendCertAuthoritiesXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + PRBool append, PRUint32 maxBytes); +SECStatus tls13_ClientHandleCertAuthoritiesXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + PRUint16 ex_type, SECItem *data); + #endif