diff options
Diffstat (limited to 'security/nss/lib/ssl/tls13con.c')
-rw-r--r-- | security/nss/lib/ssl/tls13con.c | 773 |
1 files changed, 605 insertions, 168 deletions
diff --git a/security/nss/lib/ssl/tls13con.c b/security/nss/lib/ssl/tls13con.c index 461cd2eb9..c3528a52f 100644 --- a/security/nss/lib/ssl/tls13con.c +++ b/security/nss/lib/ssl/tls13con.c @@ -24,22 +24,29 @@ #include "tls13esni.h" #include "tls13exthandle.h" #include "tls13hashstate.h" +#include "tls13subcerts.h" static SECStatus tls13_SetCipherSpec(sslSocket *ss, PRUint16 epoch, - CipherSpecDirection install, + SSLSecretDirection install, PRBool deleteSecret); -static SECStatus tls13_AESGCM( - ssl3KeyMaterial *keys, - PRBool doDecrypt, - unsigned char *out, int *outlen, int maxout, - const unsigned char *in, int inlen, - const unsigned char *additionalData, int additionalDataLen); -static SECStatus tls13_ChaCha20Poly1305( - ssl3KeyMaterial *keys, - PRBool doDecrypt, - unsigned char *out, int *outlen, int maxout, - const unsigned char *in, int inlen, - const unsigned char *additionalData, int additionalDataLen); +static SECStatus tls13_AESGCM(const ssl3KeyMaterial *keys, + PRBool doDecrypt, + unsigned char *out, + unsigned int *outlen, + unsigned int maxout, + const unsigned char *in, + unsigned int inlen, + const unsigned char *additionalData, + unsigned int additionalDataLen); +static SECStatus tls13_ChaCha20Poly1305(const ssl3KeyMaterial *keys, + PRBool doDecrypt, + unsigned char *out, + unsigned int *outlen, + unsigned int maxout, + const unsigned char *in, + unsigned int inlen, + const unsigned char *additionalData, + unsigned int additionalDataLen); static SECStatus tls13_SendServerHelloSequence(sslSocket *ss); static SECStatus tls13_SendEncryptedExtensions(sslSocket *ss); static void tls13_SetKeyExchangeType(sslSocket *ss, const sslNamedGroupDef *group); @@ -56,6 +63,7 @@ static SECStatus tls13_SendCertificate(sslSocket *ss); static SECStatus tls13_HandleCertificate( sslSocket *ss, PRUint8 *b, PRUint32 length); static SECStatus tls13_ReinjectHandshakeTranscript(sslSocket *ss); +static SECStatus tls13_SendCertificateRequest(sslSocket *ss); static SECStatus tls13_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length); static SECStatus @@ -104,6 +112,9 @@ static SECStatus tls13_ComputeFinished( PRBool sending, PRUint8 *output, unsigned int *outputLen, unsigned int maxOutputLen); static SECStatus tls13_SendClientSecondRound(sslSocket *ss); +static SECStatus tls13_SendClientSecondFlight(sslSocket *ss, + PRBool sendClientCert, + SSL3AlertDescription *sendAlert); static SECStatus tls13_FinishHandshake(sslSocket *ss); const char kHkdfLabelClient[] = "c"; @@ -249,6 +260,12 @@ tls13_CheckHsState(sslSocket *ss, int err, const char *error_name, return SECFailure; } +PRBool +tls13_IsPostHandshake(const sslSocket *ss) +{ + return ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 && ss->firstHsDone; +} + SSLHashType tls13_GetHashForCipherSuite(ssl3CipherSuite suite) { @@ -289,7 +306,7 @@ tls13_GetHashSize(const sslSocket *ss) return tls13_GetHashSizeForHash(tls13_GetHash(ss)); } -static CK_MECHANISM_TYPE +CK_MECHANISM_TYPE tls13_GetHkdfMechanismForHash(SSLHashType hash) { switch (hash) { @@ -406,7 +423,7 @@ SSL_SendAdditionalKeyShares(PRFileDesc *fd, unsigned int count) * Called from ssl3_SendClientHello. */ SECStatus -tls13_SetupClientHello(sslSocket *ss) +tls13_SetupClientHello(sslSocket *ss, sslClientHelloType chType) { unsigned int i; SSL3Statistics *ssl3stats = SSL_GetStatistics(); @@ -417,17 +434,24 @@ tls13_SetupClientHello(sslSocket *ss) PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); - PORT_Assert(PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs)); - /* Do encrypted SNI. This may create a key share as a side effect. */ + /* Do encrypted SNI. + * Note: this makes a new key even though we don't need one. + * Maybe remove this in future for efficiency. */ rv = tls13_ClientSetupESNI(ss); if (rv != SECSuccess) { return SECFailure; } + /* Everything below here is only run on the first CH. */ + if (chType != client_hello_initial) { + return SECSuccess; + } + /* Select the first enabled group. * TODO(ekr@rtfm.com): be smarter about offering the group * that the other side negotiated if we are resuming. */ + PORT_Assert(PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs)); for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) { if (!ss->namedGroupPreferences[i]) { continue; @@ -456,7 +480,7 @@ tls13_SetupClientHello(sslSocket *ss) session_ticket = &sid->u.ssl3.locked.sessionTicket; PORT_Assert(session_ticket && session_ticket->ticket.data); - if (ssl_TicketTimeValid(session_ticket)) { + if (ssl_TicketTimeValid(ss, session_ticket)) { ss->statelessResume = PR_TRUE; } @@ -588,13 +612,13 @@ loser: } static PRBool -tls13_UseServerSecret(sslSocket *ss, CipherSpecDirection direction) +tls13_UseServerSecret(sslSocket *ss, SSLSecretDirection direction) { - return ss->sec.isServer == (direction == CipherSpecWrite); + return ss->sec.isServer == (direction == ssl_secret_write); } static PK11SymKey ** -tls13_TrafficSecretRef(sslSocket *ss, CipherSpecDirection direction) +tls13_TrafficSecretRef(sslSocket *ss, SSLSecretDirection direction) { if (tls13_UseServerSecret(ss, direction)) { return &ss->ssl3.hs.serverTrafficSecret; @@ -603,7 +627,7 @@ tls13_TrafficSecretRef(sslSocket *ss, CipherSpecDirection direction) } SECStatus -tls13_UpdateTrafficKeys(sslSocket *ss, CipherSpecDirection direction) +tls13_UpdateTrafficKeys(sslSocket *ss, SSLSecretDirection direction) { PK11SymKey **secret; PK11SymKey *updatedSecret; @@ -626,7 +650,7 @@ tls13_UpdateTrafficKeys(sslSocket *ss, CipherSpecDirection direction) *secret = updatedSecret; ssl_GetSpecReadLock(ss); - if (direction == CipherSpecRead) { + if (direction == ssl_secret_read) { epoch = ss->ssl3.crSpec->epoch; } else { epoch = ss->ssl3.cwSpec->epoch; @@ -640,6 +664,11 @@ tls13_UpdateTrafficKeys(sslSocket *ss, CipherSpecDirection direction) } ++epoch; + if (ss->secretCallback) { + ss->secretCallback(ss->fd, epoch, direction, updatedSecret, + ss->secretCallbackArg); + } + rv = tls13_SetCipherSpec(ss, epoch, direction, PR_FALSE); if (rv != SECSuccess) { FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); @@ -660,8 +689,9 @@ tls13_SendKeyUpdate(sslSocket *ss, tls13KeyUpdateRequest request, PRBool buffer) : "not requested")); PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); + PORT_Assert(!ss->sec.isServer || !ss->ssl3.clientCertRequested); - if (!ss->firstHsDone) { + if (!tls13_IsPostHandshake(ss)) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } @@ -698,7 +728,7 @@ tls13_SendKeyUpdate(sslSocket *ss, tls13KeyUpdateRequest request, PRBool buffer) } ssl_ReleaseXmitBufLock(ss); - rv = tls13_UpdateTrafficKeys(ss, CipherSpecWrite); + rv = tls13_UpdateTrafficKeys(ss, ssl_secret_write); if (rv != SECSuccess) { goto loser; /* error code set by tls13_UpdateTrafficKeys */ } @@ -719,11 +749,16 @@ SSLExp_KeyUpdate(PRFileDesc *fd, PRBool requestUpdate) return SECFailure; } - if (!ss->firstHsDone) { + if (!tls13_IsPostHandshake(ss)) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } + if (ss->ssl3.clientCertRequested) { + PORT_SetError(PR_WOULD_BLOCK_ERROR); + return SECFailure; + } + rv = TLS13_CHECK_HS_STATE(ss, SEC_ERROR_INVALID_ARGS, idle_handshake); if (rv != SECSuccess) { @@ -763,8 +798,7 @@ tls13_HandleKeyUpdate(sslSocket *ss, PRUint8 *b, unsigned int length) PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); - PORT_Assert(ss->firstHsDone); - if (!ss->firstHsDone) { + if (!tls13_IsPostHandshake(ss)) { FATAL_ERROR(ss, SSL_ERROR_RX_UNEXPECTED_KEY_UPDATE, unexpected_message); return SECFailure; } @@ -791,14 +825,19 @@ tls13_HandleKeyUpdate(sslSocket *ss, PRUint8 *b, unsigned int length) return SECFailure; } - rv = tls13_UpdateTrafficKeys(ss, CipherSpecRead); + rv = tls13_UpdateTrafficKeys(ss, ssl_secret_read); if (rv != SECSuccess) { return SECFailure; /* Error code set by tls13_UpdateTrafficKeys. */ } if (update == update_requested) { PRBool sendUpdate; - if (ss->ssl3.peerRequestedKeyUpdate) { + if (ss->ssl3.clientCertRequested) { + /* Post-handshake auth is in progress; defer sending a key update. */ + ss->ssl3.keyUpdateDeferred = PR_TRUE; + ss->ssl3.deferredKeyUpdateRequest = update_not_requested; + sendUpdate = PR_FALSE; + } else if (ss->ssl3.peerRequestedKeyUpdate) { /* Only send an update if we have sent with the current spec. This * prevents us from being forced to crank forward pointlessly. */ ssl_GetSpecReadLock(ss); @@ -821,10 +860,60 @@ tls13_HandleKeyUpdate(sslSocket *ss, PRUint8 *b, unsigned int length) } SECStatus +SSLExp_SendCertificateRequest(PRFileDesc *fd) +{ + SECStatus rv; + sslSocket *ss = ssl_FindSocket(fd); + if (!ss) { + return SECFailure; + } + + /* Not supported. */ + if (IS_DTLS(ss)) { + PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION); + return SECFailure; + } + + if (!tls13_IsPostHandshake(ss)) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + if (ss->ssl3.clientCertRequested) { + PORT_SetError(PR_WOULD_BLOCK_ERROR); + return SECFailure; + } + + rv = TLS13_CHECK_HS_STATE(ss, SEC_ERROR_INVALID_ARGS, + idle_handshake); + if (rv != SECSuccess) { + return SECFailure; + } + + if (!ssl3_ExtensionNegotiated(ss, ssl_tls13_post_handshake_auth_xtn)) { + PORT_SetError(SSL_ERROR_MISSING_POST_HANDSHAKE_AUTH_EXTENSION); + return SECFailure; + } + + ssl_GetSSL3HandshakeLock(ss); + + rv = tls13_SendCertificateRequest(ss); + if (rv == SECSuccess) { + ssl_GetXmitBufLock(ss); + rv = ssl3_FlushHandshake(ss, 0); + ssl_ReleaseXmitBufLock(ss); + ss->ssl3.clientCertRequested = PR_TRUE; + } + + ssl_ReleaseSSL3HandshakeLock(ss); + return rv; +} + +SECStatus tls13_HandlePostHelloHandshakeMessage(sslSocket *ss, PRUint8 *b, PRUint32 length) { if (ss->sec.isServer && ss->ssl3.hs.zeroRttIgnore != ssl_0rtt_ignore_none) { - SSL_TRC(3, ("%d: TLS13[%d]: %s successfully decrypted handshake after" + SSL_TRC(3, ("%d: TLS13[%d]: successfully decrypted handshake after " "failed 0-RTT", SSL_GETPID(), ss->fd)); ss->ssl3.hs.zeroRttIgnore = ssl_0rtt_ignore_none; @@ -909,13 +998,13 @@ tls13_RecoverWrappedSharedSecret(sslSocket *ss, sslSessionID *sid) wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; /* unwrap the "master secret" which is actually RMS. */ - ss->ssl3.hs.resumptionMasterSecret = PK11_UnwrapSymKeyWithFlags( + ss->ssl3.hs.resumptionMasterSecret = ssl_unwrapSymKey( wrapKey, sid->u.ssl3.masterWrapMech, NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE, CKA_DERIVE, tls13_GetHashSizeForHash(hashType), - CKF_SIGN | CKF_VERIFY); + CKF_SIGN | CKF_VERIFY, ss->pkcs11PinArg); PK11_FreeSymKey(wrapKey); if (!ss->ssl3.hs.resumptionMasterSecret) { return SECFailure; @@ -1030,6 +1119,13 @@ tls13_DeriveEarlySecrets(sslSocket *ss) return SECFailure; } + if (ss->secretCallback) { + ss->secretCallback(ss->fd, (PRUint16)TrafficKeyEarlyApplicationData, + ss->sec.isServer ? ssl_secret_read : ssl_secret_write, + ss->ssl3.hs.clientEarlyTrafficSecret, + ss->secretCallbackArg); + } + rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret, NULL, kHkdfLabelEarlyExporterSecret, keylogLabelEarlyExporterSecret, @@ -1098,6 +1194,18 @@ tls13_ComputeHandshakeSecrets(sslSocket *ss) return rv; } + if (ss->secretCallback) { + SSLSecretDirection dir = + ss->sec.isServer ? ssl_secret_read : ssl_secret_write; + ss->secretCallback(ss->fd, (PRUint16)TrafficKeyHandshake, dir, + ss->ssl3.hs.clientHsTrafficSecret, + ss->secretCallbackArg); + dir = ss->sec.isServer ? ssl_secret_write : ssl_secret_read; + ss->secretCallback(ss->fd, (PRUint16)TrafficKeyHandshake, dir, + ss->ssl3.hs.serverHsTrafficSecret, + ss->secretCallbackArg); + } + SSL_TRC(5, ("%d: TLS13[%d]: compute master secret (%s)", SSL_GETPID(), ss->fd, SSL_ROLE(ss))); @@ -1148,6 +1256,18 @@ tls13_ComputeApplicationSecrets(sslSocket *ss) return SECFailure; } + if (ss->secretCallback) { + SSLSecretDirection dir = + ss->sec.isServer ? ssl_secret_read : ssl_secret_write; + ss->secretCallback(ss->fd, (PRUint16)TrafficKeyApplicationData, + dir, ss->ssl3.hs.clientTrafficSecret, + ss->secretCallbackArg); + dir = ss->sec.isServer ? ssl_secret_write : ssl_secret_read; + ss->secretCallback(ss->fd, (PRUint16)TrafficKeyApplicationData, + dir, ss->ssl3.hs.serverTrafficSecret, + ss->secretCallbackArg); + } + rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret, NULL, kHkdfLabelExporterMasterSecret, keylogLabelExporterSecret, @@ -1271,29 +1391,34 @@ tls13_NegotiateZeroRtt(sslSocket *ss, const sslSessionID *sid) return; } - /* If we rejected 0-RTT on the first ClientHello, then we can just say that - * there is no 0-RTT for the second. We shouldn't get any more. Reset the - * ignore state so that we treat decryption failure normally. */ - if (ss->ssl3.hs.zeroRttIgnore == ssl_0rtt_ignore_hrr) { - PORT_Assert(ss->ssl3.hs.helloRetry); - ss->ssl3.hs.zeroRttState = ssl_0rtt_none; - ss->ssl3.hs.zeroRttIgnore = ssl_0rtt_ignore_none; + if (ss->ssl3.hs.zeroRttState == ssl_0rtt_ignored) { + /* HelloRetryRequest causes 0-RTT to be ignored. On the second + * ClientHello, reset the ignore state so that decryption failure is + * handled normally. */ + if (ss->ssl3.hs.zeroRttIgnore == ssl_0rtt_ignore_hrr) { + PORT_Assert(ss->ssl3.hs.helloRetry); + ss->ssl3.hs.zeroRttState = ssl_0rtt_none; + ss->ssl3.hs.zeroRttIgnore = ssl_0rtt_ignore_none; + } else { + SSL_TRC(3, ("%d: TLS13[%d]: application ignored 0-RTT", + SSL_GETPID(), ss->fd)); + } return; } if (!tls13_CanNegotiateZeroRtt(ss, sid)) { - SSL_TRC(3, ("%d: TLS13[%d]: ignore 0-RTT", - SSL_GETPID(), ss->fd)); + SSL_TRC(3, ("%d: TLS13[%d]: ignore 0-RTT", SSL_GETPID(), ss->fd)); ss->ssl3.hs.zeroRttState = ssl_0rtt_ignored; ss->ssl3.hs.zeroRttIgnore = ssl_0rtt_ignore_trial; return; } - SSL_TRC(3, ("%d: TLS13[%d]: enable 0-RTT", - SSL_GETPID(), ss->fd)); + SSL_TRC(3, ("%d: TLS13[%d]: enable 0-RTT", SSL_GETPID(), ss->fd)); PORT_Assert(ss->statelessResume); ss->ssl3.hs.zeroRttState = ssl_0rtt_accepted; ss->ssl3.hs.zeroRttIgnore = ssl_0rtt_ignore_none; + ss->ssl3.hs.zeroRttSuite = ss->ssl3.hs.cipher_suite; + ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_0rtt_cipher_suite; } /* Check if the offered group is acceptable. */ @@ -1464,6 +1589,20 @@ tls13_SelectServerCert(sslSocket *ss) if (rv == SECSuccess) { /* Found one. */ ss->sec.serverCert = cert; + + /* If we can use a delegated credential (DC) for authentication in + * the current handshake, then commit to using it now. We'll send a + * DC as an extension and use the DC private key to sign the + * handshake. + * + * This sets the signature scheme to be the signature scheme + * indicated by the DC. + */ + rv = tls13_MaybeSetDelegatedCredential(ss); + if (rv != SECSuccess) { + return SECFailure; /* Failure indicates an internal error. */ + } + ss->sec.authType = ss->ssl3.hs.kea_def_mutable.authKeyType = ssl_SignatureSchemeToAuthType(ss->ssl3.hs.signatureScheme); ss->sec.authKeyBits = cert->serverKeyBits; @@ -1519,6 +1658,11 @@ tls13_MaybeSendHelloRetry(sslSocket *ss, const sslNamedGroupDef *requestedGroup, return SECFailure; } + if (action == ssl_hello_retry_reject_0rtt) { + ss->ssl3.hs.zeroRttState = ssl_0rtt_ignored; + ss->ssl3.hs.zeroRttIgnore = ssl_0rtt_ignore_trial; + } + if (!requestedGroup && action != ssl_hello_retry_request) { return SECSuccess; } @@ -1573,24 +1717,23 @@ tls13_HandleClientHelloPart2(sslSocket *ss, const sslNamedGroupDef *previousGroup = NULL; PRBool hrr = PR_FALSE; + /* If the legacy_version field is set to 0x300 or smaller, + * reject the connection with protocol_version alert. */ + if (ss->clientHelloVersion <= SSL_LIBRARY_VERSION_3_0) { + FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, protocol_version); + goto loser; + } + ss->ssl3.hs.endOfFlight = PR_TRUE; if (ssl3_ExtensionNegotiated(ss, ssl_tls13_early_data_xtn)) { ss->ssl3.hs.zeroRttState = ssl_0rtt_sent; } -#ifndef PARANOID - /* Look for a matching cipher suite. */ - if (ssl3_config_match_init(ss) == 0) { /* no ciphers are working/supported by PK11 */ - FATAL_ERROR(ss, PORT_GetError(), internal_error); - goto loser; - } -#endif - /* Negotiate cipher suite. */ rv = ssl3_NegotiateCipherSuite(ss, suites, PR_FALSE); if (rv != SECSuccess) { - FATAL_ERROR(ss, SSL_ERROR_NO_CYPHER_OVERLAP, handshake_failure); + FATAL_ERROR(ss, PORT_GetError(), handshake_failure); goto loser; } @@ -2083,10 +2226,20 @@ tls13_SendCertificateRequest(sslSocket *ss) { SECStatus rv; sslBuffer extensionBuf = SSL_BUFFER_EMPTY; + unsigned int offset = 0; SSL_TRC(3, ("%d: TLS13[%d]: begin send certificate_request", SSL_GETPID(), ss->fd)); + if (ss->firstHsDone) { + PORT_Assert(ss->ssl3.hs.shaPostHandshake == NULL); + ss->ssl3.hs.shaPostHandshake = PK11_CloneContext(ss->ssl3.hs.sha); + if (ss->ssl3.hs.shaPostHandshake == NULL) { + ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); + return SECFailure; + } + } + rv = ssl_ConstructExtensions(ss, &extensionBuf, ssl_hs_certificate_request); if (rv != SECSuccess) { return SECFailure; /* Code already set. */ @@ -2094,8 +2247,29 @@ tls13_SendCertificateRequest(sslSocket *ss) /* We should always have at least one of these. */ PORT_Assert(SSL_BUFFER_LEN(&extensionBuf) > 0); + /* Create a new request context for post-handshake authentication */ + if (ss->firstHsDone) { + PRUint8 context[16]; + SECItem contextItem = { siBuffer, context, sizeof(context) }; + + rv = PK11_GenerateRandom(context, sizeof(context)); + if (rv != SECSuccess) { + goto loser; + } + + SECITEM_FreeItem(&ss->xtnData.certReqContext, PR_FALSE); + rv = SECITEM_CopyItem(NULL, &ss->xtnData.certReqContext, &contextItem); + if (rv != SECSuccess) { + FATAL_ERROR(ss, SEC_ERROR_NO_MEMORY, internal_error); + goto loser; + } + + offset = SSL_BUFFER_LEN(&ss->sec.ci.sendBuf); + } + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_certificate_request, - 1 + 0 + /* empty request context */ + 1 + /* request context length */ + ss->xtnData.certReqContext.len + 2 + /* extension length */ SSL_BUFFER_LEN(&extensionBuf)); if (rv != SECSuccess) { @@ -2103,7 +2277,8 @@ tls13_SendCertificateRequest(sslSocket *ss) } /* Context. */ - rv = ssl3_AppendHandshakeNumber(ss, 0, 1); + rv = ssl3_AppendHandshakeVariable(ss, ss->xtnData.certReqContext.data, + ss->xtnData.certReqContext.len, 1); if (rv != SECSuccess) { goto loser; /* err set by AppendHandshake. */ } @@ -2113,6 +2288,15 @@ tls13_SendCertificateRequest(sslSocket *ss) goto loser; /* err set by AppendHandshake. */ } + if (ss->firstHsDone) { + rv = ssl3_UpdatePostHandshakeHashes(ss, + SSL_BUFFER_BASE(&ss->sec.ci.sendBuf) + offset, + SSL_BUFFER_LEN(&ss->sec.ci.sendBuf) - offset); + if (rv != SECSuccess) { + goto loser; + } + } + sslBuffer_Clear(&extensionBuf); return SECSuccess; @@ -2191,7 +2375,7 @@ tls13_HandleHelloRetryRequest(sslSocket *ss, const PRUint8 *savedMsg, /* Restore the null cipher spec for writing. */ ssl_GetSpecWriteLock(ss); ssl_CipherSpecRelease(ss->ssl3.cwSpec); - ss->ssl3.cwSpec = ssl_FindCipherSpecByEpoch(ss, CipherSpecWrite, + ss->ssl3.cwSpec = ssl_FindCipherSpecByEpoch(ss, ssl_secret_write, TrafficKeyClearText); PORT_Assert(ss->ssl3.cwSpec); ssl_ReleaseSpecWriteLock(ss); @@ -2267,25 +2451,61 @@ tls13_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length) PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); /* Client */ - rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST, - wait_cert_request); + if (ss->opt.enablePostHandshakeAuth) { + rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST, + wait_cert_request, idle_handshake); + } else { + rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST, + wait_cert_request); + } if (rv != SECSuccess) { return SECFailure; } - PORT_Assert(ss->ssl3.clientCertChain == NULL); - PORT_Assert(ss->ssl3.clientCertificate == NULL); - PORT_Assert(ss->ssl3.clientPrivateKey == NULL); - PORT_Assert(!ss->ssl3.hs.clientCertRequested); + if (tls13_IsPostHandshake(ss)) { + PORT_Assert(ss->ssl3.hs.shaPostHandshake == NULL); + ss->ssl3.hs.shaPostHandshake = PK11_CloneContext(ss->ssl3.hs.sha); + if (ss->ssl3.hs.shaPostHandshake == NULL) { + ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); + return SECFailure; + } + rv = ssl_HashPostHandshakeMessage(ss, ssl_hs_certificate_request, b, length); + if (rv != SECSuccess) { + FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); + return SECFailure; + } + + /* clean up anything left from previous handshake. */ + if (ss->ssl3.clientCertChain != NULL) { + CERT_DestroyCertificateList(ss->ssl3.clientCertChain); + ss->ssl3.clientCertChain = NULL; + } + if (ss->ssl3.clientCertificate != NULL) { + CERT_DestroyCertificate(ss->ssl3.clientCertificate); + ss->ssl3.clientCertificate = NULL; + } + if (ss->ssl3.clientPrivateKey != NULL) { + SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); + ss->ssl3.clientPrivateKey = NULL; + } + SECITEM_FreeItem(&ss->xtnData.certReqContext, PR_FALSE); + ss->xtnData.certReqContext.data = NULL; + } else { + PORT_Assert(ss->ssl3.clientCertChain == NULL); + PORT_Assert(ss->ssl3.clientCertificate == NULL); + PORT_Assert(ss->ssl3.clientPrivateKey == NULL); + PORT_Assert(!ss->ssl3.hs.clientCertRequested); + PORT_Assert(ss->xtnData.certReqContext.data == NULL); + } rv = ssl3_ConsumeHandshakeVariable(ss, &context, 1, &b, &length); if (rv != SECSuccess) { return SECFailure; } - /* We don't support post-handshake client auth, the certificate request - * context must always be empty. */ - if (context.len > 0) { + /* Unless it is a post-handshake client auth, the certificate + * request context must be empty. */ + if (!tls13_IsPostHandshake(ss) && context.len > 0) { FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_REQUEST, illegal_parameter); return SECFailure; } @@ -2319,7 +2539,38 @@ tls13_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length) } ss->ssl3.hs.clientCertRequested = PR_TRUE; - TLS13_SET_HS_STATE(ss, wait_server_cert); + + if (ss->firstHsDone) { + SSL3AlertDescription sendAlert = no_alert; + + /* Request a client certificate. */ + 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; + } + + ssl_GetXmitBufLock(ss); + rv = tls13_SendClientSecondFlight(ss, !ss->ssl3.sendEmptyCert, + &sendAlert); + ssl_ReleaseXmitBufLock(ss); + if (rv != SECSuccess) { + if (sendAlert != no_alert) { + FATAL_ERROR(ss, PORT_GetError(), sendAlert); + } else { + LOG_ERROR(ss, PORT_GetError()); + } + return SECFailure; + } + PORT_Assert(ss->ssl3.hs.ws == idle_handshake); + PORT_Assert(ss->ssl3.hs.shaPostHandshake != NULL); + PK11_DestroyContext(ss->ssl3.hs.shaPostHandshake, PR_TRUE); + ss->ssl3.hs.shaPostHandshake = NULL; + } else { + TLS13_SET_HS_STATE(ss, wait_server_cert); + } return SECSuccess; } @@ -2341,7 +2592,7 @@ tls13_SendEncryptedServerSequence(sslSocket *ss) } rv = tls13_SetCipherSpec(ss, TrafficKeyHandshake, - CipherSpecWrite, PR_FALSE); + ssl_secret_write, PR_FALSE); if (rv != SECSuccess) { LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -2375,7 +2626,14 @@ tls13_SendEncryptedServerSequence(sslSocket *ss) return SECFailure; /* error code is set. */ } - svrPrivKey = ss->sec.serverCert->serverKeyPair->privKey; + if (tls13_IsSigningWithDelegatedCredential(ss)) { + SSL_TRC(3, ("%d: TLS13[%d]: Signing with delegated credential", + SSL_GETPID(), ss->fd)); + svrPrivKey = ss->sec.serverCert->delegCredKeyPair->privKey; + } else { + svrPrivKey = ss->sec.serverCert->serverKeyPair->privKey; + } + rv = tls13_SendCertificateVerify(ss, svrPrivKey); if (rv != SECSuccess) { return SECFailure; /* err code is set. */ @@ -2451,7 +2709,7 @@ tls13_SendServerHelloSequence(sslSocket *ss) } rv = tls13_SetCipherSpec(ss, TrafficKeyApplicationData, - CipherSpecWrite, PR_FALSE); + ssl_secret_write, PR_FALSE); if (rv != SECSuccess) { LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -2463,7 +2721,7 @@ tls13_SendServerHelloSequence(sslSocket *ss) } if (ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted) { rv = tls13_SetCipherSpec(ss, TrafficKeyEarlyApplicationData, - CipherSpecRead, PR_TRUE); + ssl_secret_read, PR_TRUE); if (rv != SECSuccess) { LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -2475,7 +2733,7 @@ tls13_SendServerHelloSequence(sslSocket *ss) rv = tls13_SetCipherSpec(ss, TrafficKeyHandshake, - CipherSpecRead, PR_FALSE); + ssl_secret_read, PR_FALSE); if (rv != SECSuccess) { LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -2487,7 +2745,7 @@ tls13_SendServerHelloSequence(sslSocket *ss) } } - ss->ssl3.hs.serverHelloTime = ssl_TimeUsec(); + ss->ssl3.hs.serverHelloTime = ssl_Time(ss); return SECSuccess; } @@ -2584,11 +2842,11 @@ tls13_HandleServerHelloPart2(sslSocket *ss) /* When we send 0-RTT, we saved the null spec in case we needed it to * send another ClientHello in response to a HelloRetryRequest. Now * that we won't be receiving a HelloRetryRequest, release the spec. */ - ssl_CipherSpecReleaseByEpoch(ss, CipherSpecWrite, TrafficKeyClearText); + ssl_CipherSpecReleaseByEpoch(ss, ssl_secret_write, TrafficKeyClearText); } rv = tls13_SetCipherSpec(ss, TrafficKeyHandshake, - CipherSpecRead, PR_FALSE); + ssl_secret_read, PR_FALSE); if (rv != SECSuccess) { FATAL_ERROR(ss, SSL_ERROR_INIT_CIPHER_SUITE_FAILURE, internal_error); return SECFailure; @@ -2855,8 +3113,13 @@ tls13_HandleCertificate(sslSocket *ss, PRUint8 *b, PRUint32 length) PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); if (ss->sec.isServer) { - rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERTIFICATE, - wait_client_cert); + if (ss->ssl3.clientCertRequested) { + rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERTIFICATE, + idle_handshake); + } else { + rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERTIFICATE, + wait_client_cert); + } } else { rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERTIFICATE, wait_cert_request, wait_server_cert); @@ -2866,18 +3129,29 @@ tls13_HandleCertificate(sslSocket *ss, PRUint8 *b, PRUint32 length) /* We can ignore any other cleartext from the client. */ if (ss->sec.isServer && IS_DTLS(ss)) { - ssl_CipherSpecReleaseByEpoch(ss, CipherSpecRead, TrafficKeyClearText); + ssl_CipherSpecReleaseByEpoch(ss, ssl_secret_read, TrafficKeyClearText); dtls_ReceivedFirstMessageInFlight(ss); } + + if (ss->firstHsDone) { + rv = ssl_HashPostHandshakeMessage(ss, ssl_hs_certificate, b, length); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + } + /* Process the context string */ rv = ssl3_ConsumeHandshakeVariable(ss, &context, 1, &b, &length); if (rv != SECSuccess) return SECFailure; - if (context.len) { - /* The context string MUST be empty */ - FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERTIFICATE, illegal_parameter); - return SECFailure; + if (ss->ssl3.clientCertRequested) { + PORT_Assert(ss->sec.isServer); + if (SECITEM_CompareItem(&context, &ss->xtnData.certReqContext) != 0) { + FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERTIFICATE, illegal_parameter); + return SECFailure; + } } rv = ssl3_ConsumeHandshakeVariable(ss, &certList, 3, &b, &length); @@ -3118,6 +3392,25 @@ tls13_DeriveSecretWrap(sslSocket *ss, PK11SymKey *key, return SECSuccess; } +SECStatus +SSLExp_SecretCallback(PRFileDesc *fd, SSLSecretCallback cb, void *arg) +{ + sslSocket *ss = ssl_FindSocket(fd); + if (!ss) { + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SecretCallback", + SSL_GETPID(), fd)); + return SECFailure; + } + + ssl_Get1stHandshakeLock(ss); + ssl_GetSSL3HandshakeLock(ss); + ss->secretCallback = cb; + ss->secretCallbackArg = arg; + ssl_ReleaseSSL3HandshakeLock(ss); + ssl_Release1stHandshakeLock(ss); + return SECSuccess; +} + /* Derive traffic keys for the next cipher spec in the queue. */ static SECStatus tls13_DeriveTrafficKeys(sslSocket *ss, ssl3CipherSpec *spec, @@ -3244,7 +3537,7 @@ tls13_SetupPendingCipherSpec(sslSocket *ss, ssl3CipherSpec *spec) /* We want to keep read cipher specs around longer because * there are cases where we might get either epoch N or * epoch N+1. */ - if (IS_DTLS(ss) && spec->direction == CipherSpecRead) { + if (IS_DTLS(ss) && spec->direction == ssl_secret_read) { ssl_CipherSpecAddRef(spec); } @@ -3267,7 +3560,7 @@ tls13_SetupPendingCipherSpec(sslSocket *ss, ssl3CipherSpec *spec) /* The record size limit is reduced by one so that the remainder of the * record handling code can use the same checks for all versions. */ if (ssl3_ExtensionNegotiated(ss, ssl_record_size_limit_xtn)) { - spec->recordSizeLimit = ((spec->direction == CipherSpecRead) + spec->recordSizeLimit = ((spec->direction == ssl_secret_read) ? ss->opt.recordSizeLimit : ss->xtnData.recordSizeLimit) - 1; @@ -3303,7 +3596,7 @@ tls13_SetAlertCipherSpec(sslSocket *ss) } rv = tls13_SetCipherSpec(ss, TrafficKeyHandshake, - CipherSpecWrite, PR_FALSE); + ssl_secret_write, PR_FALSE); if (rv != SECSuccess) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -3318,7 +3611,7 @@ tls13_SetAlertCipherSpec(sslSocket *ss) */ static SECStatus tls13_SetCipherSpec(sslSocket *ss, PRUint16 epoch, - CipherSpecDirection direction, PRBool deleteSecret) + SSLSecretDirection direction, PRBool deleteSecret) { TrafficKeyType type; SECStatus rv; @@ -3357,7 +3650,7 @@ tls13_SetCipherSpec(sslSocket *ss, PRUint16 epoch, } /* Now that we've set almost everything up, finally cut over. */ - specp = (direction == CipherSpecRead) ? &ss->ssl3.crSpec : &ss->ssl3.cwSpec; + specp = (direction == ssl_secret_read) ? &ss->ssl3.crSpec : &ss->ssl3.cwSpec; ssl_GetSpecWriteLock(ss); ssl_CipherSpecRelease(*specp); /* May delete old cipher. */ *specp = spec; /* Overwrite. */ @@ -3366,11 +3659,6 @@ tls13_SetCipherSpec(sslSocket *ss, PRUint16 epoch, SSL_TRC(3, ("%d: TLS13[%d]: %s installed key for epoch=%d (%s) dir=%s", SSL_GETPID(), ss->fd, SSL_ROLE(ss), spec->epoch, spec->phase, SPEC_DIR(spec))); - - if (ss->ssl3.changedCipherSpecFunc) { - ss->ssl3.changedCipherSpecFunc(ss->ssl3.changedCipherSpecArg, - direction == CipherSpecWrite, spec); - } return SECSuccess; loser: @@ -3410,7 +3698,11 @@ tls13_ComputeHandshakeHashes(sslSocket *ss, SSL3Hashes *hashes) goto loser; } } else { - ctx = PK11_CloneContext(ss->ssl3.hs.sha); + if (ss->firstHsDone) { + ctx = PK11_CloneContext(ss->ssl3.hs.shaPostHandshake); + } else { + ctx = PK11_CloneContext(ss->ssl3.hs.sha); + } if (!ctx) { ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); return SECFailure; @@ -3519,7 +3811,7 @@ tls13_DestroyEarlyData(PRCList *list) * See RFC 5288 and https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305-04#section-2 */ static void -tls13_WriteNonce(ssl3KeyMaterial *keys, +tls13_WriteNonce(const ssl3KeyMaterial *keys, const unsigned char *seqNumBuf, unsigned int seqNumLen, unsigned char *nonce, unsigned int nonceLen) { @@ -3542,41 +3834,35 @@ tls13_WriteNonce(ssl3KeyMaterial *keys, * a sequence number. In TLS 1.3 there is no additional data so this value is * just the encoded sequence number. */ -static SECStatus -tls13_AEAD(ssl3KeyMaterial *keys, PRBool doDecrypt, - unsigned char *out, int *outlen, int maxout, - const unsigned char *in, int inlen, +SECStatus +tls13_AEAD(const ssl3KeyMaterial *keys, PRBool doDecrypt, + unsigned char *out, unsigned int *outlen, unsigned int maxout, + const unsigned char *in, unsigned int inlen, CK_MECHANISM_TYPE mechanism, unsigned char *aeadParams, unsigned int aeadParamLength) { - SECStatus rv; - unsigned int uOutLen = 0; SECItem param = { siBuffer, aeadParams, aeadParamLength }; if (doDecrypt) { - rv = PK11_Decrypt(keys->key, mechanism, ¶m, - out, &uOutLen, maxout, in, inlen); - } else { - rv = PK11_Encrypt(keys->key, mechanism, ¶m, - out, &uOutLen, maxout, in, inlen); + return PK11_Decrypt(keys->key, mechanism, ¶m, + out, outlen, maxout, in, inlen); } - *outlen = (int)uOutLen; - - return rv; + return PK11_Encrypt(keys->key, mechanism, ¶m, + out, outlen, maxout, in, inlen); } static SECStatus -tls13_AESGCM(ssl3KeyMaterial *keys, +tls13_AESGCM(const ssl3KeyMaterial *keys, PRBool doDecrypt, unsigned char *out, - int *outlen, - int maxout, + unsigned int *outlen, + unsigned int maxout, const unsigned char *in, - int inlen, + unsigned int inlen, const unsigned char *additionalData, - int additionalDataLen) + unsigned int additionalDataLen) { CK_GCM_PARAMS gcmParams; unsigned char nonce[12]; @@ -3597,11 +3883,11 @@ tls13_AESGCM(ssl3KeyMaterial *keys, } static SECStatus -tls13_ChaCha20Poly1305(ssl3KeyMaterial *keys, PRBool doDecrypt, - unsigned char *out, int *outlen, int maxout, - const unsigned char *in, int inlen, +tls13_ChaCha20Poly1305(const ssl3KeyMaterial *keys, PRBool doDecrypt, + unsigned char *out, unsigned int *outlen, unsigned int maxout, + const unsigned char *in, unsigned int inlen, const unsigned char *additionalData, - int additionalDataLen) + unsigned int additionalDataLen) { CK_NSS_AEAD_PARAMS aeadParams; unsigned char nonce[12]; @@ -3847,6 +4133,9 @@ done: SECStatus tls13_HandleCertificateVerify(sslSocket *ss, PRUint8 *b, PRUint32 length) { + sslDelegatedCredential *dc = ss->xtnData.peerDelegCred; + CERTSubjectPublicKeyInfo *spki; + SECKEYPublicKey *pubKey = NULL; SECItem signed_hash = { siBuffer, NULL, 0 }; SECStatus rv; SSLSignatureScheme sigScheme; @@ -3870,7 +4159,11 @@ tls13_HandleCertificateVerify(sslSocket *ss, PRUint8 *b, PRUint32 length) return SECFailure; } - rv = ssl_HashHandshakeMessage(ss, ssl_hs_certificate_verify, b, length); + if (ss->firstHsDone) { + rv = ssl_HashPostHandshakeMessage(ss, ssl_hs_certificate_verify, b, length); + } else { + rv = ssl_HashHandshakeMessage(ss, ssl_hs_certificate_verify, b, length); + } if (rv != SECSuccess) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -3882,7 +4175,40 @@ tls13_HandleCertificateVerify(sslSocket *ss, PRUint8 *b, PRUint32 length) return SECFailure; } - rv = ssl_CheckSignatureSchemeConsistency(ss, sigScheme, ss->sec.peerCert); + /* Set the |spki| used to verify the handshake. When verifying with a + * delegated credential (DC), this corresponds to the DC public key; + * otherwise it correspond to the public key of the peer's end-entity + * certificate. + */ + if (tls13_IsVerifyingWithDelegatedCredential(ss)) { + /* DelegatedCredential.cred.expected_cert_verify_algorithm is expected + * to match CertificateVerify.scheme. + * DelegatedCredential.cred.expected_cert_verify_algorithm must also be + * the same as was reported in ssl3_AuthCertificate. + */ + if (sigScheme != dc->expectedCertVerifyAlg || sigScheme != ss->sec.signatureScheme) { + FATAL_ERROR(ss, SSL_ERROR_DC_CERT_VERIFY_ALG_MISMATCH, illegal_parameter); + return SECFailure; + } + + /* Verify the DC has three steps: (1) use the peer's end-entity + * certificate to verify DelegatedCredential.signature, (2) check that + * the certificate has the correct key usage, and (3) check that the DC + * hasn't expired. + */ + rv = tls13_VerifyDelegatedCredential(ss, dc); + if (rv != SECSuccess) { /* Calls FATAL_ERROR() */ + return SECFailure; + } + + SSL_TRC(3, ("%d: TLS13[%d]: Verifying with delegated credential", + SSL_GETPID(), ss->fd)); + spki = dc->spki; + } else { + spki = &ss->sec.peerCert->subjectPublicKeyInfo; + } + + rv = ssl_CheckSignatureSchemeConsistency(ss, sigScheme, spki); if (rv != SECSuccess) { /* Error set already */ FATAL_ERROR(ss, PORT_GetError(), illegal_parameter); @@ -3907,15 +4233,33 @@ tls13_HandleCertificateVerify(sslSocket *ss, PRUint8 *b, PRUint32 length) return SECFailure; } - rv = ssl3_VerifySignedHashes(ss, sigScheme, &tbsHash, &signed_hash); + pubKey = SECKEY_ExtractPublicKey(spki); + if (pubKey == NULL) { + ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE); + return SECFailure; + } + + rv = ssl_VerifySignedHashesWithPubKey(ss, pubKey, sigScheme, + &tbsHash, &signed_hash); if (rv != SECSuccess) { FATAL_ERROR(ss, PORT_GetError(), decrypt_error); - return SECFailure; + goto loser; } - /* Set the auth type. */ + /* Set the auth type and verify it is what we captured in ssl3_AuthCertificate */ if (!ss->sec.isServer) { ss->sec.authType = ssl_SignatureSchemeToAuthType(sigScheme); + + uint32_t prelimAuthKeyBits = ss->sec.authKeyBits; + rv = ssl_SetAuthKeyBits(ss, pubKey); + if (rv != SECSuccess) { + goto loser; /* Alert sent and code set. */ + } + + if (prelimAuthKeyBits != ss->sec.authKeyBits) { + FATAL_ERROR(ss, SSL_ERROR_DC_CERT_VERIFY_ALG_MISMATCH, illegal_parameter); + goto loser; + } } /* Request a client certificate now if one was requested. */ @@ -3926,13 +4270,17 @@ tls13_HandleCertificateVerify(sslSocket *ss, PRUint8 *b, PRUint32 length) &ss->xtnData.certReqAuthorities); if (rv != SECSuccess) { FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); - return rv; + goto loser; } } + SECKEY_DestroyPublicKey(pubKey); TLS13_SET_HS_STATE(ss, wait_finished); - return SECSuccess; + +loser: + SECKEY_DestroyPublicKey(pubKey); + return SECFailure; } static SECStatus @@ -4190,7 +4538,11 @@ tls13_CommonHandleFinished(sslSocket *ss, PK11SymKey *key, return SECFailure; } - rv = ssl_HashHandshakeMessage(ss, ssl_hs_finished, b, length); + if (ss->firstHsDone) { + rv = ssl_HashPostHandshakeMessage(ss, ssl_hs_finished, b, length); + } else { + rv = ssl_HashHandshakeMessage(ss, ssl_hs_finished, b, length); + } if (rv != SECSuccess) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -4231,26 +4583,48 @@ tls13_ServerHandleFinished(sslSocket *ss, PRUint8 *b, PRUint32 length) SSL_TRC(3, ("%d: TLS13[%d]: server handle finished handshake", SSL_GETPID(), ss->fd)); - rv = tls13_CommonHandleFinished(ss, ss->ssl3.hs.clientHsTrafficSecret, + rv = tls13_CommonHandleFinished(ss, + ss->firstHsDone ? ss->ssl3.hs.clientTrafficSecret : ss->ssl3.hs.clientHsTrafficSecret, b, length); if (rv != SECSuccess) { return SECFailure; } + if (ss->firstHsDone) { + TLS13_SET_HS_STATE(ss, idle_handshake); + + PORT_Assert(ss->ssl3.hs.shaPostHandshake != NULL); + PK11_DestroyContext(ss->ssl3.hs.shaPostHandshake, PR_TRUE); + ss->ssl3.hs.shaPostHandshake = NULL; + + ss->ssl3.clientCertRequested = PR_FALSE; + + if (ss->ssl3.keyUpdateDeferred) { + rv = tls13_SendKeyUpdate(ss, ss->ssl3.deferredKeyUpdateRequest, + PR_FALSE); + if (rv != SECSuccess) { + return SECFailure; /* error is set. */ + } + ss->ssl3.keyUpdateDeferred = PR_FALSE; + } + + return SECSuccess; + } + if (!tls13_ShouldRequestClientAuth(ss) && (ss->ssl3.hs.zeroRttState != ssl_0rtt_done)) { dtls_ReceivedFirstMessageInFlight(ss); } rv = tls13_SetCipherSpec(ss, TrafficKeyApplicationData, - CipherSpecRead, PR_FALSE); + ssl_secret_read, PR_FALSE); if (rv != SECSuccess) { FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); return SECFailure; } if (IS_DTLS(ss)) { - ssl_CipherSpecReleaseByEpoch(ss, CipherSpecRead, TrafficKeyClearText); + ssl_CipherSpecReleaseByEpoch(ss, ssl_secret_read, TrafficKeyClearText); /* We need to keep the handshake cipher spec so we can * read re-transmitted client Finished. */ rv = dtls_StartTimer(ss, ss->ssl3.hs.hdTimer, @@ -4266,6 +4640,11 @@ tls13_ServerHandleFinished(sslSocket *ss, PRUint8 *b, PRUint32 length) return SECFailure; } + rv = tls13_FinishHandshake(ss); + if (rv != SECSuccess) { + return SECFailure; + } + ssl_GetXmitBufLock(ss); if (ss->opt.enableSessionTickets) { rv = tls13_SendNewSessionTicket(ss, NULL, 0); @@ -4278,8 +4657,7 @@ tls13_ServerHandleFinished(sslSocket *ss, PRUint8 *b, PRUint32 length) } } ssl_ReleaseXmitBufLock(ss); - - return tls13_FinishHandshake(ss); + return SECSuccess; loser: ssl_ReleaseXmitBufLock(ss); @@ -4316,11 +4694,16 @@ tls13_SendClientSecondFlight(sslSocket *ss, PRBool sendClientCert, SSL3AlertDescription *sendAlert) { SECStatus rv; + unsigned int offset = 0; PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); *sendAlert = internal_error; + if (ss->firstHsDone) { + offset = SSL_BUFFER_LEN(&ss->sec.ci.sendBuf); + } + if (ss->ssl3.sendEmptyCert) { ss->ssl3.sendEmptyCert = PR_FALSE; rv = ssl3_SendEmptyCertificate(ss); @@ -4334,6 +4717,16 @@ tls13_SendClientSecondFlight(sslSocket *ss, PRBool sendClientCert, return SECFailure; /* error code is set. */ } } + + if (ss->firstHsDone) { + rv = ssl3_UpdatePostHandshakeHashes(ss, + SSL_BUFFER_BASE(&ss->sec.ci.sendBuf) + offset, + SSL_BUFFER_LEN(&ss->sec.ci.sendBuf) - offset); + if (rv != SECSuccess) { + return SECFailure; /* error code is set. */ + } + } + if (ss->ssl3.hs.clientCertRequested) { SECITEM_FreeItem(&ss->xtnData.certReqContext, PR_FALSE); if (ss->xtnData.certReqAuthorities.arena) { @@ -4346,15 +4739,28 @@ tls13_SendClientSecondFlight(sslSocket *ss, PRBool sendClientCert, } if (sendClientCert) { + if (ss->firstHsDone) { + offset = SSL_BUFFER_LEN(&ss->sec.ci.sendBuf); + } + rv = tls13_SendCertificateVerify(ss, ss->ssl3.clientPrivateKey); SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); ss->ssl3.clientPrivateKey = NULL; if (rv != SECSuccess) { return SECFailure; /* err is set. */ } + + if (ss->firstHsDone) { + rv = ssl3_UpdatePostHandshakeHashes(ss, + SSL_BUFFER_BASE(&ss->sec.ci.sendBuf) + offset, + SSL_BUFFER_LEN(&ss->sec.ci.sendBuf) - offset); + if (rv != SECSuccess) { + return SECFailure; /* error is set. */ + } + } } - rv = tls13_SendFinished(ss, ss->ssl3.hs.clientHsTrafficSecret); + rv = tls13_SendFinished(ss, ss->firstHsDone ? ss->ssl3.hs.clientTrafficSecret : ss->ssl3.hs.clientHsTrafficSecret); if (rv != SECSuccess) { return SECFailure; /* err code was set. */ } @@ -4397,7 +4803,8 @@ tls13_SendClientSecondRound(sslSocket *ss) " certificate authentication is still pending.", SSL_GETPID(), ss->fd)); ss->ssl3.hs.restartTarget = tls13_SendClientSecondRound; - return SECWouldBlock; + PORT_SetError(PR_WOULD_BLOCK_ERROR); + return SECFailure; } rv = tls13_ComputeApplicationSecrets(ss); @@ -4425,14 +4832,14 @@ tls13_SendClientSecondRound(sslSocket *ss) } rv = tls13_SetCipherSpec(ss, TrafficKeyHandshake, - CipherSpecWrite, PR_FALSE); + ssl_secret_write, PR_FALSE); if (rv != SECSuccess) { FATAL_ERROR(ss, SSL_ERROR_INIT_CIPHER_SUITE_FAILURE, internal_error); return SECFailure; } rv = tls13_SetCipherSpec(ss, TrafficKeyApplicationData, - CipherSpecRead, PR_FALSE); + ssl_secret_read, PR_FALSE); if (rv != SECSuccess) { FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); return SECFailure; @@ -4450,7 +4857,7 @@ tls13_SendClientSecondRound(sslSocket *ss) return SECFailure; } rv = tls13_SetCipherSpec(ss, TrafficKeyApplicationData, - CipherSpecWrite, PR_FALSE); + ssl_secret_write, PR_FALSE); if (rv != SECSuccess) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -4615,8 +5022,7 @@ SSLExp_SendSessionTicket(PRFileDesc *fd, const PRUint8 *token, return SECFailure; } - if (!ss->sec.isServer || !ss->firstHsDone || - ss->version < SSL_LIBRARY_VERSION_TLS_1_3 || + if (!ss->sec.isServer || !tls13_IsPostHandshake(ss) || tokenLen > 0xffff) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; @@ -4652,13 +5058,13 @@ tls13_HandleNewSessionTicket(sslSocket *ss, PRUint8 *b, PRUint32 length) if (rv != SECSuccess) { return SECFailure; } - if (!ss->firstHsDone || ss->sec.isServer) { + if (!tls13_IsPostHandshake(ss) || ss->sec.isServer) { FATAL_ERROR(ss, SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET, unexpected_message); return SECFailure; } - ticket.received_timestamp = ssl_TimeUsec(); + ticket.received_timestamp = ssl_Time(ss); rv = ssl3_ConsumeHandshakeNumber(ss, &ticket.ticket_lifetime_hint, 4, &b, &length); if (rv != SECSuccess) { @@ -4803,12 +5209,14 @@ static const struct { certificate) }, { ssl_cert_status_xtn, _M3(client_hello, certificate_request, certificate) }, + { ssl_delegated_credentials_xtn, _M2(client_hello, certificate) }, { ssl_tls13_cookie_xtn, _M2(client_hello, hello_retry_request) }, { ssl_tls13_certificate_authorities_xtn, _M1(certificate_request) }, { ssl_tls13_supported_versions_xtn, _M3(client_hello, server_hello, hello_retry_request) }, { ssl_record_size_limit_xtn, _M2(client_hello, encrypted_extensions) }, - { ssl_tls13_encrypted_sni_xtn, _M2(client_hello, encrypted_extensions) } + { ssl_tls13_encrypted_sni_xtn, _M2(client_hello, encrypted_extensions) }, + { ssl_tls13_post_handshake_auth_xtn, _M1(client_hello) } }; tls13ExtensionStatus @@ -4917,7 +5325,7 @@ tls13_ProtectRecord(sslSocket *ss, const int tagLen = cipher_def->tag_size; SECStatus rv; - PORT_Assert(cwSpec->direction == CipherSpecWrite); + PORT_Assert(cwSpec->direction == ssl_secret_write); SSL_TRC(3, ("%d: TLS13[%d]: spec=%d epoch=%d (%s) protect 0x%0llx len=%u", SSL_GETPID(), ss->fd, cwSpec, cwSpec->epoch, cwSpec->phase, cwSpec->nextSeqNum, contentLen)); @@ -4941,7 +5349,7 @@ tls13_ProtectRecord(sslSocket *ss, PRBool needsLength; PRUint8 aad[21]; unsigned int aadLen; - int len; + unsigned int len; PORT_Assert(cipher_def->type == type_aead); @@ -5011,7 +5419,7 @@ tls13_UnprotectRecord(sslSocket *ss, *alert = bad_record_mac; /* Default alert for most issues. */ - PORT_Assert(spec->direction == CipherSpecRead); + PORT_Assert(spec->direction == ssl_secret_read); SSL_TRC(3, ("%d: TLS13[%d]: spec=%d epoch=%d (%s) unprotect 0x%0llx len=%u", SSL_GETPID(), ss->fd, spec, spec->epoch, spec->phase, cText->seqNum, cText->buf->len)); @@ -5062,12 +5470,12 @@ tls13_UnprotectRecord(sslSocket *ss, return SECFailure; } rv = spec->aead(&spec->keyMaterial, - PR_TRUE, /* do decrypt */ - plaintext->buf, /* out */ - (int *)&plaintext->len, /* outlen */ - plaintext->space, /* maxout */ - cText->buf->buf, /* in */ - cText->buf->len, /* inlen */ + PR_TRUE, /* do decrypt */ + plaintext->buf, /* out */ + &plaintext->len, /* outlen */ + plaintext->space, /* maxout */ + cText->buf->buf, /* in */ + cText->buf->len, /* inlen */ aad, aadLen); if (rv != SECSuccess) { SSL_TRC(3, @@ -5168,6 +5576,9 @@ tls13_MaybeDo0RTTHandshake(sslSocket *ss) ss->ssl3.hs.zeroRttState = ssl_0rtt_sent; ss->ssl3.hs.zeroRttSuite = ss->ssl3.hs.cipher_suite; + /* Note: Reset the preliminary info here rather than just add 0-RTT. We are + * only guessing what might happen at this point.*/ + ss->ssl3.hs.preliminaryInfo = ssl_preinfo_0rtt_cipher_suite; SSL_TRC(3, ("%d: TLS13[%d]: in 0-RTT mode", SSL_GETPID(), ss->fd)); @@ -5196,9 +5607,6 @@ tls13_MaybeDo0RTTHandshake(sslSocket *ss) } } - /* Cipher suite already set in tls13_SetupClientHello. */ - ss->ssl3.hs.preliminaryInfo = 0; - rv = tls13_DeriveEarlySecrets(ss); if (rv != SECSuccess) { return SECFailure; @@ -5209,7 +5617,7 @@ tls13_MaybeDo0RTTHandshake(sslSocket *ss) ssl_CipherSpecAddRef(ss->ssl3.cwSpec); rv = tls13_SetCipherSpec(ss, TrafficKeyEarlyApplicationData, - CipherSpecWrite, PR_TRUE); + ssl_secret_write, PR_TRUE); if (rv != SECSuccess) { return SECFailure; } @@ -5218,25 +5626,45 @@ tls13_MaybeDo0RTTHandshake(sslSocket *ss) } PRInt32 -tls13_Read0RttData(sslSocket *ss, void *buf, PRInt32 len) +tls13_Read0RttData(sslSocket *ss, PRUint8 *buf, PRInt32 len) { - TLS13EarlyData *msg; - PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ssl3.hs.bufferedEarlyData)); - msg = (TLS13EarlyData *)PR_NEXT_LINK(&ss->ssl3.hs.bufferedEarlyData); + PRInt32 offset = 0; + while (!PR_CLIST_IS_EMPTY(&ss->ssl3.hs.bufferedEarlyData)) { + TLS13EarlyData *msg = + (TLS13EarlyData *)PR_NEXT_LINK(&ss->ssl3.hs.bufferedEarlyData); + unsigned int tocpy = msg->data.len - msg->consumed; + + if (tocpy > (len - offset)) { + if (IS_DTLS(ss)) { + /* In DTLS, we only return entire records. + * So offset and consumed are always zero. */ + PORT_Assert(offset == 0); + PORT_Assert(msg->consumed == 0); + PORT_SetError(SSL_ERROR_RX_SHORT_DTLS_READ); + return -1; + } - PR_REMOVE_LINK(&msg->link); - if (msg->data.len > len) { - PORT_SetError(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); - return SECFailure; - } - len = msg->data.len; + tocpy = len - offset; + } + + PORT_Memcpy(buf + offset, msg->data.data + msg->consumed, tocpy); + offset += tocpy; + msg->consumed += tocpy; - PORT_Memcpy(buf, msg->data.data, msg->data.len); - SECITEM_ZfreeItem(&msg->data, PR_FALSE); - PORT_ZFree(msg, sizeof(*msg)); + if (msg->consumed == msg->data.len) { + PR_REMOVE_LINK(&msg->link); + SECITEM_ZfreeItem(&msg->data, PR_FALSE); + PORT_ZFree(msg, sizeof(*msg)); + } + + /* We are done after one record for DTLS; otherwise, when the buffer fills up. */ + if (IS_DTLS(ss) || offset == len) { + break; + } + } - return len; + return offset; } static SECStatus @@ -5272,7 +5700,7 @@ tls13_HandleEndOfEarlyData(sslSocket *ss, PRUint8 *b, PRUint32 length) /* We shouldn't be getting any more early data, and if we do, * it is because of reordering and we drop it. */ if (IS_DTLS(ss)) { - ssl_CipherSpecReleaseByEpoch(ss, CipherSpecRead, + ssl_CipherSpecReleaseByEpoch(ss, ssl_secret_read, TrafficKeyEarlyApplicationData); dtls_ReceivedFirstMessageInFlight(ss); } @@ -5285,7 +5713,7 @@ tls13_HandleEndOfEarlyData(sslSocket *ss, PRUint8 *b, PRUint32 length) } rv = tls13_SetCipherSpec(ss, TrafficKeyHandshake, - CipherSpecRead, PR_FALSE); + ssl_secret_read, PR_FALSE); if (rv != SECSuccess) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -5403,6 +5831,15 @@ tls13_NegotiateVersion(sslSocket *ss, const TLSExtension *supportedVersions) return SECFailure; } for (version = ss->vrange.max; version >= ss->vrange.min; --version) { + if (ss->ssl3.hs.helloRetry && version < SSL_LIBRARY_VERSION_TLS_1_3) { + /* Prevent negotiating to a lower version in response to a TLS 1.3 HRR. + * Since we check in descending (local) order, this will only fail if + * our vrange has changed or the client didn't offer 1.3 in response. */ + PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION); + FATAL_ERROR(ss, SSL_ERROR_UNSUPPORTED_VERSION, protocol_version); + return SECFailure; + } + PRUint16 wire = tls13_EncodeDraftVersion(version, ss->protocolVariant); unsigned long offset; |