diff options
Diffstat (limited to 'security/nss/lib/ssl/tls13con.c')
-rw-r--r-- | security/nss/lib/ssl/tls13con.c | 1048 |
1 files changed, 672 insertions, 376 deletions
diff --git a/security/nss/lib/ssl/tls13con.c b/security/nss/lib/ssl/tls13con.c index c3528a52f..5d51d3c5c 100644 --- a/security/nss/lib/ssl/tls13con.c +++ b/security/nss/lib/ssl/tls13con.c @@ -25,28 +25,11 @@ #include "tls13exthandle.h" #include "tls13hashstate.h" #include "tls13subcerts.h" +#include "tls13psk.h" static SECStatus tls13_SetCipherSpec(sslSocket *ss, PRUint16 epoch, SSLSecretDirection install, PRBool deleteSecret); -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); @@ -83,13 +66,15 @@ tls13_DeriveSecret(sslSocket *ss, PK11SymKey *key, const char *label, unsigned int labelLen, const SSL3Hashes *hashes, - PK11SymKey **dest); + PK11SymKey **dest, + SSLHashType hash); static SECStatus tls13_SendEndOfEarlyData(sslSocket *ss); -static SECStatus tls13_HandleEndOfEarlyData(sslSocket *ss, PRUint8 *b, +static SECStatus tls13_HandleEndOfEarlyData(sslSocket *ss, const PRUint8 *b, PRUint32 length); +static SECStatus tls13_MaybeHandleSuppressedEndOfEarlyData(sslSocket *ss); static SECStatus tls13_SendFinished(sslSocket *ss, PK11SymKey *baseKey); static SECStatus tls13_ComputePskBinderHash(sslSocket *ss, unsigned int prefix, - SSL3Hashes *hashes); + SSL3Hashes *hashes, SSLHashType type); static SECStatus tls13_VerifyFinished(sslSocket *ss, SSLHandshakeType message, PK11SymKey *secret, PRUint8 *b, PRUint32 length, @@ -103,14 +88,14 @@ static SECStatus tls13_SendNewSessionTicket(sslSocket *ss, unsigned int appTokenLen); static SECStatus tls13_HandleNewSessionTicket(sslSocket *ss, PRUint8 *b, PRUint32 length); -static SECStatus tls13_ComputeEarlySecrets(sslSocket *ss); +static SECStatus tls13_ComputeEarlySecretsWithPsk(sslSocket *ss); static SECStatus tls13_ComputeHandshakeSecrets(sslSocket *ss); static SECStatus tls13_ComputeApplicationSecrets(sslSocket *ss); static SECStatus tls13_ComputeFinalSecrets(sslSocket *ss); static SECStatus tls13_ComputeFinished( - sslSocket *ss, PK11SymKey *baseKey, const SSL3Hashes *hashes, - PRBool sending, PRUint8 *output, unsigned int *outputLen, - unsigned int maxOutputLen); + sslSocket *ss, PK11SymKey *baseKey, SSLHashType hashType, + const SSL3Hashes *hashes, PRBool sending, PRUint8 *output, + unsigned int *outputLen, unsigned int maxOutputLen); static SECStatus tls13_SendClientSecondRound(sslSocket *ss); static SECStatus tls13_SendClientSecondFlight(sslSocket *ss, PRBool sendClientCert, @@ -120,7 +105,8 @@ static SECStatus tls13_FinishHandshake(sslSocket *ss); const char kHkdfLabelClient[] = "c"; const char kHkdfLabelServer[] = "s"; const char kHkdfLabelDerivedSecret[] = "derived"; -const char kHkdfLabelPskBinderKey[] = "res binder"; +const char kHkdfLabelResPskBinderKey[] = "res binder"; +const char kHkdfLabelExtPskBinderKey[] = "ext binder"; const char kHkdfLabelEarlyTrafficSecret[] = "e traffic"; const char kHkdfLabelEarlyExporterSecret[] = "e exp master"; const char kHkdfLabelHandshakeTrafficSecret[] = "hs traffic"; @@ -131,6 +117,7 @@ const char kHkdfLabelExporterMasterSecret[] = "exp master"; const char kHkdfLabelResumption[] = "resumption"; const char kHkdfLabelTrafficUpdate[] = "traffic upd"; const char kHkdfPurposeKey[] = "key"; +const char kHkdfPurposeSn[] = "sn"; const char kHkdfPurposeIv[] = "iv"; const char keylogLabelClientEarlyTrafficSecret[] = "CLIENT_EARLY_TRAFFIC_SECRET"; @@ -281,11 +268,49 @@ tls13_GetHashForCipherSuite(ssl3CipherSuite suite) SSLHashType tls13_GetHash(const sslSocket *ss) { + /* suite_def may not be set yet when doing EPSK 0-Rtt. */ + if (!ss->ssl3.hs.suite_def) { + if (ss->xtnData.selectedPsk) { + return ss->xtnData.selectedPsk->hash; + } + /* This should never happen. */ + PORT_Assert(0); + return ssl_hash_none; + } + /* All TLS 1.3 cipher suites must have an explict PRF hash. */ PORT_Assert(ss->ssl3.hs.suite_def->prf_hash != ssl_hash_none); return ss->ssl3.hs.suite_def->prf_hash; } +SECStatus +tls13_GetHashAndCipher(PRUint16 version, PRUint16 cipherSuite, + SSLHashType *hash, const ssl3BulkCipherDef **cipher) +{ + if (version < SSL_LIBRARY_VERSION_TLS_1_3) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + // Lookup and check the suite. + SSLVersionRange vrange = { version, version }; + if (!ssl3_CipherSuiteAllowedForVersionRange(cipherSuite, &vrange)) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + const ssl3CipherSuiteDef *suiteDef = ssl_LookupCipherSuiteDef(cipherSuite); + const ssl3BulkCipherDef *cipherDef = ssl_GetBulkCipherDef(suiteDef); + if (cipherDef->type != type_aead) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + *hash = suiteDef->prf_hash; + if (cipher != NULL) { + *cipher = cipherDef; + } + return SECSuccess; +} + unsigned int tls13_GetHashSizeForHash(SSLHashType hash) { @@ -306,30 +331,10 @@ tls13_GetHashSize(const sslSocket *ss) return tls13_GetHashSizeForHash(tls13_GetHash(ss)); } -CK_MECHANISM_TYPE -tls13_GetHkdfMechanismForHash(SSLHashType hash) -{ - switch (hash) { - case ssl_hash_sha256: - return CKM_NSS_HKDF_SHA256; - case ssl_hash_sha384: - return CKM_NSS_HKDF_SHA384; - default: - PORT_Assert(0); - } - return CKM_NSS_HKDF_SHA256; -} - -CK_MECHANISM_TYPE -tls13_GetHkdfMechanism(sslSocket *ss) -{ - return tls13_GetHkdfMechanismForHash(tls13_GetHash(ss)); -} - static CK_MECHANISM_TYPE -tls13_GetHmacMechanism(sslSocket *ss) +tls13_GetHmacMechanismFromHash(SSLHashType hashType) { - switch (tls13_GetHash(ss)) { + switch (hashType) { case ssl_hash_sha256: return CKM_SHA256_HMAC; case ssl_hash_sha384: @@ -340,19 +345,25 @@ tls13_GetHmacMechanism(sslSocket *ss) return CKM_SHA256_HMAC; } +static CK_MECHANISM_TYPE +tls13_GetHmacMechanism(const sslSocket *ss) +{ + return tls13_GetHmacMechanismFromHash(tls13_GetHash(ss)); +} + SECStatus tls13_ComputeHash(sslSocket *ss, SSL3Hashes *hashes, - const PRUint8 *buf, unsigned int len) + const PRUint8 *buf, unsigned int len, + SSLHashType hash) { SECStatus rv; - rv = PK11_HashBuf(ssl3_HashTypeToOID(tls13_GetHash(ss)), - hashes->u.raw, buf, len); + rv = PK11_HashBuf(ssl3_HashTypeToOID(hash), hashes->u.raw, buf, len); if (rv != SECSuccess) { FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); return SECFailure; } - hashes->len = tls13_GetHashSize(ss); + hashes->len = tls13_GetHashSizeForHash(hash); return SECSuccess; } @@ -470,40 +481,50 @@ tls13_SetupClientHello(sslSocket *ss, sslClientHelloType chType) return SECFailure; } - /* Below here checks if we can do stateless resumption. */ - if (sid->cached == never_cached || - sid->version < SSL_LIBRARY_VERSION_TLS_1_3) { - return SECSuccess; - } + /* Try to do stateless resumption, if we can. */ + if (sid->cached != never_cached && + sid->version >= SSL_LIBRARY_VERSION_TLS_1_3) { + /* The caller must be holding sid->u.ssl3.lock for reading. */ + session_ticket = &sid->u.ssl3.locked.sessionTicket; + PORT_Assert(session_ticket && session_ticket->ticket.data); - /* The caller must be holding sid->u.ssl3.lock for reading. */ - session_ticket = &sid->u.ssl3.locked.sessionTicket; - PORT_Assert(session_ticket && session_ticket->ticket.data); + if (ssl_TicketTimeValid(ss, session_ticket)) { + ss->statelessResume = PR_TRUE; + } - if (ssl_TicketTimeValid(ss, session_ticket)) { - ss->statelessResume = PR_TRUE; - } + if (ss->statelessResume) { + PORT_Assert(ss->sec.ci.sid); + rv = tls13_RecoverWrappedSharedSecret(ss, ss->sec.ci.sid); + if (rv != SECSuccess) { + FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); + SSL_AtomicIncrementLong(&ssl3stats->sch_sid_cache_not_ok); + ssl_UncacheSessionID(ss); + ssl_FreeSID(ss->sec.ci.sid); + ss->sec.ci.sid = NULL; + return SECFailure; + } - if (ss->statelessResume) { - PORT_Assert(ss->sec.ci.sid); - rv = tls13_RecoverWrappedSharedSecret(ss, ss->sec.ci.sid); - if (rv != SECSuccess) { - FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); - SSL_AtomicIncrementLong(&ssl3stats->sch_sid_cache_not_ok); - ssl_UncacheSessionID(ss); - ssl_FreeSID(ss->sec.ci.sid); - ss->sec.ci.sid = NULL; - return SECFailure; + ss->ssl3.hs.cipher_suite = ss->sec.ci.sid->u.ssl3.cipherSuite; + rv = ssl3_SetupCipherSuite(ss, PR_FALSE); + if (rv != SECSuccess) { + FATAL_ERROR(ss, PORT_GetError(), internal_error); + return SECFailure; + } + PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks)); } + } - ss->ssl3.hs.cipher_suite = ss->sec.ci.sid->u.ssl3.cipherSuite; - rv = ssl3_SetupCipherSuite(ss, PR_FALSE); - if (rv != SECSuccess) { - FATAL_ERROR(ss, PORT_GetError(), internal_error); - return SECFailure; + /* Derive the binder keys if any PSKs. */ + if (!PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks)) { + /* If an External PSK specified a suite, use that. */ + sslPsk *psk = (sslPsk *)PR_LIST_HEAD(&ss->ssl3.hs.psks); + if (!ss->statelessResume && + psk->type == ssl_psk_external && + psk->zeroRttSuite != TLS_NULL_WITH_NULL_NULL) { + ss->ssl3.hs.cipher_suite = psk->zeroRttSuite; } - rv = tls13_ComputeEarlySecrets(ss); + rv = tls13_ComputeEarlySecretsWithPsk(ss); if (rv != SECSuccess) { FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); return SECFailure; @@ -595,7 +616,7 @@ tls13_HandleKeyShare(sslSocket *ss, key = PK11_PubDeriveWithKDF( keyPair->privKey, peerKey, PR_FALSE, NULL, NULL, mechanism, - tls13_GetHkdfMechanismForHash(hash), CKA_DERIVE, keySize, CKD_NULL, NULL, NULL); + CKM_HKDF_DERIVE, CKA_DERIVE, keySize, CKD_NULL, NULL, NULL); if (!key) { ssl_MapLowLevelError(SSL_ERROR_KEY_EXCHANGE_FAILURE); goto loser; @@ -641,6 +662,7 @@ tls13_UpdateTrafficKeys(sslSocket *ss, SSLSecretDirection direction) strlen(kHkdfLabelTrafficUpdate), tls13_GetHmacMechanism(ss), tls13_GetHashSize(ss), + ss->protocolVariant, &updatedSecret); if (rv != SECSuccess) { return SECFailure; @@ -884,6 +906,12 @@ SSLExp_SendCertificateRequest(PRFileDesc *fd) return SECFailure; } + /* Disallow a CertificateRequest if this connection uses an external PSK. */ + if (ss->sec.authType == ssl_auth_psk) { + PORT_SetError(SSL_ERROR_FEATURE_DISABLED); + return SECFailure; + } + rv = TLS13_CHECK_HS_STATE(ss, SEC_ERROR_INVALID_ARGS, idle_handshake); if (rv != SECSuccess) { @@ -997,20 +1025,34 @@ tls13_RecoverWrappedSharedSecret(sslSocket *ss, sslSessionID *sid) wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; - /* unwrap the "master secret" which is actually RMS. */ - 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, ss->pkcs11PinArg); + PK11SymKey *unwrappedPsk = ssl_unwrapSymKey(wrapKey, sid->u.ssl3.masterWrapMech, + NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE, + CKA_DERIVE, tls13_GetHashSizeForHash(hashType), + CKF_SIGN | CKF_VERIFY, ss->pkcs11PinArg); PK11_FreeSymKey(wrapKey); - if (!ss->ssl3.hs.resumptionMasterSecret) { + if (!unwrappedPsk) { return SECFailure; } + sslPsk *rpsk = tls13_MakePsk(unwrappedPsk, ssl_psk_resume, hashType, NULL); + if (!rpsk) { + PK11_FreeSymKey(unwrappedPsk); + return SECFailure; + } + if (sid->u.ssl3.locked.sessionTicket.flags & ticket_allow_early_data) { + rpsk->maxEarlyData = sid->u.ssl3.locked.sessionTicket.max_early_data_size; + rpsk->zeroRttSuite = sid->u.ssl3.cipherSuite; + } + PRINT_KEY(50, (ss, "Recovered RMS", rpsk->key)); + PORT_Assert(PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks) || + ((sslPsk *)PR_LIST_HEAD(&ss->ssl3.hs.psks))->type != ssl_psk_resume); - PRINT_KEY(50, (ss, "Recovered RMS", ss->ssl3.hs.resumptionMasterSecret)); + if (ss->sec.isServer) { + /* In server, we couldn't select the RPSK in the extension handler + * since it was not unwrapped yet. We're committed now, so select + * it and add it to the list (to ensure it is freed). */ + ss->xtnData.selectedPsk = rpsk; + } + PR_APPEND_LINK(&rpsk->link, &ss->ssl3.hs.psks); return SECSuccess; } @@ -1068,38 +1110,45 @@ tls13_RecoverWrappedSharedSecret(sslSocket *ss, sslSessionID *sid) * = resumption_master_secret * */ - static SECStatus -tls13_ComputeEarlySecrets(sslSocket *ss) +tls13_ComputeEarlySecretsWithPsk(sslSocket *ss) { - SECStatus rv = SECSuccess; + SECStatus rv; SSL_TRC(5, ("%d: TLS13[%d]: compute early secrets (%s)", SSL_GETPID(), ss->fd, SSL_ROLE(ss))); - /* Extract off the resumptionMasterSecret (if present), else pass the NULL - * resumptionMasterSecret which will be internally translated to zeroes. */ PORT_Assert(!ss->ssl3.hs.currentSecret); - rv = tls13_HkdfExtract(NULL, ss->ssl3.hs.resumptionMasterSecret, - tls13_GetHash(ss), &ss->ssl3.hs.currentSecret); + sslPsk *psk = NULL; + + if (ss->sec.isServer) { + psk = ss->xtnData.selectedPsk; + } else { + /* Client to use the first PSK for early secrets. */ + PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks)); + psk = (sslPsk *)PR_LIST_HEAD(&ss->ssl3.hs.psks); + } + PORT_Assert(psk && psk->key); + PORT_Assert(psk->hash != ssl_hash_none); + + PK11SymKey *earlySecret = NULL; + rv = tls13_HkdfExtract(NULL, psk->key, psk->hash, &earlySecret); if (rv != SECSuccess) { return SECFailure; } - PORT_Assert(ss->statelessResume == (ss->ssl3.hs.resumptionMasterSecret != NULL)); - if (ss->statelessResume) { - PK11_FreeSymKey(ss->ssl3.hs.resumptionMasterSecret); - ss->ssl3.hs.resumptionMasterSecret = NULL; - - rv = tls13_DeriveSecretNullHash(ss, ss->ssl3.hs.currentSecret, - kHkdfLabelPskBinderKey, - strlen(kHkdfLabelPskBinderKey), - &ss->ssl3.hs.pskBinderKey); - if (rv != SECSuccess) { - return SECFailure; - } + /* No longer need the raw input key */ + PK11_FreeSymKey(psk->key); + psk->key = NULL; + const char *label = (psk->type == ssl_psk_resume) ? kHkdfLabelResPskBinderKey : kHkdfLabelExtPskBinderKey; + rv = tls13_DeriveSecretNullHash(ss, earlySecret, + label, strlen(label), + &psk->binderKey, psk->hash); + if (rv != SECSuccess) { + PK11_FreeSymKey(earlySecret); + return SECFailure; } - PORT_Assert(!ss->ssl3.hs.resumptionMasterSecret); + ss->ssl3.hs.currentSecret = earlySecret; return SECSuccess; } @@ -1109,7 +1158,7 @@ static SECStatus tls13_DeriveEarlySecrets(sslSocket *ss) { SECStatus rv; - + PORT_Assert(ss->ssl3.hs.currentSecret); rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret, kHkdfLabelClient, kHkdfLabelEarlyTrafficSecret, @@ -1147,7 +1196,15 @@ tls13_ComputeHandshakeSecrets(sslSocket *ss) SSL_TRC(5, ("%d: TLS13[%d]: compute handshake secrets (%s)", SSL_GETPID(), ss->fd, SSL_ROLE(ss))); - /* First update |currentSecret| to add |dheSecret|, if any. */ + /* If no PSK, generate the default early secret. */ + if (!ss->ssl3.hs.currentSecret) { + PORT_Assert(!ss->xtnData.selectedPsk); + rv = tls13_HkdfExtract(NULL, NULL, + tls13_GetHash(ss), &ss->ssl3.hs.currentSecret); + if (rv != SECSuccess) { + return SECFailure; + } + } PORT_Assert(ss->ssl3.hs.currentSecret); PORT_Assert(ss->ssl3.hs.dheSecret); @@ -1155,7 +1212,7 @@ tls13_ComputeHandshakeSecrets(sslSocket *ss) rv = tls13_DeriveSecretNullHash(ss, ss->ssl3.hs.currentSecret, kHkdfLabelDerivedSecret, strlen(kHkdfLabelDerivedSecret), - &derivedSecret); + &derivedSecret, tls13_GetHash(ss)); if (rv != SECSuccess) { LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE); return rv; @@ -1214,7 +1271,7 @@ tls13_ComputeHandshakeSecrets(sslSocket *ss) rv = tls13_DeriveSecretNullHash(ss, ss->ssl3.hs.currentSecret, kHkdfLabelDerivedSecret, strlen(kHkdfLabelDerivedSecret), - &derivedSecret); + &derivedSecret, tls13_GetHash(ss)); if (rv != SECSuccess) { LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE); return rv; @@ -1286,7 +1343,7 @@ tls13_ComputeFinalSecrets(sslSocket *ss) PORT_Assert(!ss->ssl3.crSpec->masterSecret); PORT_Assert(!ss->ssl3.cwSpec->masterSecret); - + PORT_Assert(ss->ssl3.hs.currentSecret); rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret, NULL, kHkdfLabelResumptionMasterSecret, NULL, @@ -1327,7 +1384,14 @@ tls13_CanResume(sslSocket *ss, const sslSessionID *sid) return PR_FALSE; } +#ifdef UNSAFE_FUZZER_MODE + /* When fuzzing, sid could contain garbage that will crash tls13_GetHashForCipherSuite. + * Do a direct comparison of cipher suites. This makes us refuse to resume when the + * protocol allows it, but resumption is discretionary anyway. */ + if (sid->u.ssl3.cipherSuite != ss->ssl3.hs.cipher_suite) { +#else if (tls13_GetHashForCipherSuite(sid->u.ssl3.cipherSuite) != tls13_GetHashForCipherSuite(ss->ssl3.hs.cipher_suite)) { +#endif return PR_FALSE; } @@ -1347,21 +1411,40 @@ static PRBool tls13_CanNegotiateZeroRtt(sslSocket *ss, const sslSessionID *sid) { PORT_Assert(ss->ssl3.hs.zeroRttState == ssl_0rtt_sent); + sslPsk *psk = ss->xtnData.selectedPsk; - if (!sid) + if (!ss->opt.enable0RttData) { return PR_FALSE; - PORT_Assert(ss->statelessResume); - if (!ss->statelessResume) + } + if (!psk) { return PR_FALSE; - if (ss->ssl3.hs.cipher_suite != sid->u.ssl3.cipherSuite) + } + if (psk->zeroRttSuite == TLS_NULL_WITH_NULL_NULL) { return PR_FALSE; - if (!ss->opt.enable0RttData) + } + if (!psk->maxEarlyData) { return PR_FALSE; - if (!(sid->u.ssl3.locked.sessionTicket.flags & ticket_allow_early_data)) + } + if (ss->ssl3.hs.cipher_suite != psk->zeroRttSuite) { return PR_FALSE; - if (SECITEM_CompareItem(&ss->xtnData.nextProto, - &sid->u.ssl3.alpnSelection) != 0) + } + if (psk->type == ssl_psk_resume) { + if (!sid) { + return PR_FALSE; + } + PORT_Assert(sid->u.ssl3.locked.sessionTicket.flags & ticket_allow_early_data); + PORT_Assert(ss->statelessResume); + if (!ss->statelessResume) { + return PR_FALSE; + } + if (SECITEM_CompareItem(&ss->xtnData.nextProto, + &sid->u.ssl3.alpnSelection) != 0) { + return PR_FALSE; + } + } else if (psk->type != ssl_psk_external) { + PORT_Assert(0); return PR_FALSE; + } if (tls13_IsReplay(ss, sid)) { return PR_FALSE; @@ -1414,7 +1497,7 @@ tls13_NegotiateZeroRtt(sslSocket *ss, const sslSessionID *sid) } SSL_TRC(3, ("%d: TLS13[%d]: enable 0-RTT", SSL_GETPID(), ss->fd)); - PORT_Assert(ss->statelessResume); + PORT_Assert(ss->xtnData.selectedPsk); ss->ssl3.hs.zeroRttState = ssl_0rtt_accepted; ss->ssl3.hs.zeroRttIgnore = ssl_0rtt_ignore_none; ss->ssl3.hs.zeroRttSuite = ss->ssl3.hs.cipher_suite; @@ -1466,7 +1549,7 @@ tls13_NegotiateKeyExchange(sslSocket *ss, const sslNamedGroupDef *preferredGroup = NULL; /* We insist on DHE. */ - if (ss->statelessResume) { + if (ssl3_ExtensionNegotiated(ss, ssl_tls13_pre_shared_key_xtn)) { if (!ssl3_ExtensionNegotiated(ss, ssl_tls13_psk_key_exchange_modes_xtn)) { FATAL_ERROR(ss, SSL_ERROR_MISSING_PSK_KEY_EXCHANGE_MODES, missing_extension); @@ -1490,8 +1573,8 @@ tls13_NegotiateKeyExchange(sslSocket *ss, return SECFailure; } - SSL_TRC(3, ("%d: TLS13[%d]: selected KE = %s", - SSL_GETPID(), ss->fd, ss->statelessResume ? "PSK + (EC)DHE" : "(EC)DHE")); + SSL_TRC(3, ("%d: TLS13[%d]: selected KE = %s", SSL_GETPID(), + ss->fd, ss->statelessResume || ss->xtnData.selectedPsk ? "PSK + (EC)DHE" : "(EC)DHE")); /* Find the preferred group and an according client key share available. */ for (index = 0; index < SSL_NAMED_GROUP_COUNT; ++index) { @@ -1679,26 +1762,42 @@ tls13_MaybeSendHelloRetry(sslSocket *ss, const sslNamedGroupDef *requestedGroup, static SECStatus tls13_NegotiateAuthentication(sslSocket *ss) { - SECStatus rv; - if (ss->statelessResume) { - SSL_TRC(3, ("%d: TLS13[%d]: selected PSK authentication", + SSL_TRC(3, ("%d: TLS13[%d]: selected resumption PSK authentication", SSL_GETPID(), ss->fd)); ss->ssl3.hs.signatureScheme = ssl_sig_none; ss->ssl3.hs.kea_def_mutable.authKeyType = ssl_auth_psk; + /* Overwritten by tls13_RestoreCipherInfo. */ + ss->sec.authType = ssl_auth_psk; return SECSuccess; + } else if (ss->xtnData.selectedPsk) { + /* If the EPSK doesn't specify a suite, use what was negotiated. + * Else, only use the EPSK if we negotiated that suite. */ + if (ss->xtnData.selectedPsk->zeroRttSuite == TLS_NULL_WITH_NULL_NULL || + ss->ssl3.hs.cipher_suite == ss->xtnData.selectedPsk->zeroRttSuite) { + SSL_TRC(3, ("%d: TLS13[%d]: selected external PSK authentication", + SSL_GETPID(), ss->fd)); + ss->ssl3.hs.signatureScheme = ssl_sig_none; + ss->ssl3.hs.kea_def_mutable.authKeyType = ssl_auth_psk; + ss->sec.authType = ssl_auth_psk; + return SECSuccess; + } + } + + /* If there were PSKs, they are no longer needed. */ + if (ss->xtnData.selectedPsk) { + tls13_DestroyPskList(&ss->ssl3.hs.psks); + ss->xtnData.selectedPsk = NULL; } SSL_TRC(3, ("%d: TLS13[%d]: selected certificate authentication", SSL_GETPID(), ss->fd)); - /* We've now established that we need to sign.... */ - rv = tls13_SelectServerCert(ss); + SECStatus rv = tls13_SelectServerCert(ss); if (rv != SECSuccess) { return SECFailure; } return SECSuccess; } - /* Called from ssl3_HandleClientHello after we have parsed the * ClientHello and are sure that we are going to do TLS 1.3 * or fail. */ @@ -1862,40 +1961,51 @@ tls13_HandleClientHelloPart2(sslSocket *ss, goto loser; } - if (ss->statelessResume) { - /* We are now committed to trying to resume. */ - PORT_Assert(sid); - - /* Check that the negotiated SNI and the cached SNI match. */ - if (SECITEM_CompareItem(&sid->u.ssl3.srvName, - &ss->ssl3.hs.srvVirtName) != SECEqual) { - FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, - handshake_failure); - goto loser; - } + if (ss->sec.authType == ssl_auth_psk) { + if (ss->statelessResume) { + /* We are now committed to trying to resume. */ + PORT_Assert(sid); + /* Check that the negotiated SNI and the cached SNI match. */ + if (SECITEM_CompareItem(&sid->u.ssl3.srvName, + &ss->ssl3.hs.srvVirtName) != SECEqual) { + FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, + handshake_failure); + goto loser; + } - ss->sec.serverCert = ssl_FindServerCert(ss, sid->authType, - sid->namedCurve); - PORT_Assert(ss->sec.serverCert); + ss->sec.serverCert = ssl_FindServerCert(ss, sid->authType, + sid->namedCurve); + PORT_Assert(ss->sec.serverCert); - rv = tls13_RecoverWrappedSharedSecret(ss, sid); - if (rv != SECSuccess) { - SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_not_ok); - FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); - goto loser; - } - tls13_RestoreCipherInfo(ss, sid); + rv = tls13_RecoverWrappedSharedSecret(ss, sid); + if (rv != SECSuccess) { + SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_not_ok); + FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); + goto loser; + } + tls13_RestoreCipherInfo(ss, sid); - ss->sec.localCert = CERT_DupCertificate(ss->sec.serverCert->serverCert); - if (sid->peerCert != NULL) { - ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); + ss->sec.localCert = CERT_DupCertificate(ss->sec.serverCert->serverCert); + if (sid->peerCert != NULL) { + ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); + } + } else if (sid) { + /* We should never have a SID in the non-resumption case. */ + PORT_Assert(0); + ssl_UncacheSessionID(ss); + ssl_FreeSID(sid); + sid = NULL; } - ssl3_RegisterExtensionSender( ss, &ss->xtnData, ssl_tls13_pre_shared_key_xtn, tls13_ServerSendPreSharedKeyXtn); - tls13_NegotiateZeroRtt(ss, sid); + + rv = tls13_ComputeEarlySecretsWithPsk(ss); + if (rv != SECSuccess) { + FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); + return SECFailure; + } } else { if (sid) { /* we had a sid, but it's no longer valid, free it */ SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_not_ok); @@ -1906,35 +2016,34 @@ tls13_HandleClientHelloPart2(sslSocket *ss, tls13_NegotiateZeroRtt(ss, NULL); } - /* Need to compute early secrets. */ - rv = tls13_ComputeEarlySecrets(ss); - if (rv != SECSuccess) { - FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); - return SECFailure; + if (ss->statelessResume) { + PORT_Assert(ss->xtnData.selectedPsk); + PORT_Assert(ss->ssl3.hs.kea_def_mutable.authKeyType == ssl_auth_psk); } - /* Now that we have the binder key check the binder. */ - if (ss->statelessResume) { + /* Now that we have the binder key, check the binder. */ + if (ss->xtnData.selectedPsk) { SSL3Hashes hashes; - PORT_Assert(ss->ssl3.hs.messages.len > ss->xtnData.pskBindersLen); rv = tls13_ComputePskBinderHash( ss, ss->ssl3.hs.messages.len - ss->xtnData.pskBindersLen, - &hashes); + &hashes, tls13_GetHash(ss)); if (rv != SECSuccess) { FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); goto loser; } + PORT_Assert(ss->xtnData.selectedPsk->hash == tls13_GetHash(ss)); + PORT_Assert(ss->ssl3.hs.suite_def); rv = tls13_VerifyFinished(ss, ssl_hs_client_hello, - ss->ssl3.hs.pskBinderKey, + ss->xtnData.selectedPsk->binderKey, ss->xtnData.pskBinder.data, ss->xtnData.pskBinder.len, &hashes); - if (rv != SECSuccess) { - goto loser; - } + } + if (rv != SECSuccess) { + goto loser; } /* This needs to go after we verify the psk binder. */ @@ -1961,7 +2070,7 @@ tls13_HandleClientHelloPart2(sslSocket *ss, SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_not_ok); ssl_UncacheSessionID(ss); ssl_FreeSID(sid); - } else { + } else if (!ss->xtnData.selectedPsk) { SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_misses); } @@ -1991,6 +2100,10 @@ tls13_HandleClientHelloPart2(sslSocket *ss, return SECFailure; } + /* We're done with PSKs */ + tls13_DestroyPskList(&ss->ssl3.hs.psks); + ss->xtnData.selectedPsk = NULL; + return SECSuccess; loser: @@ -2322,7 +2435,8 @@ tls13_ReinjectHandshakeTranscript(sslSocket *ss) // First compute the hash. rv = tls13_ComputeHash(ss, &hashes, ss->ssl3.hs.messages.buf, - ss->ssl3.hs.messages.len); + ss->ssl3.hs.messages.len, + tls13_GetHash(ss)); if (rv != SECSuccess) { return SECFailure; } @@ -2339,7 +2453,6 @@ tls13_ReinjectHandshakeTranscript(sslSocket *ss) return SECSuccess; } - static unsigned int ssl_ListCount(PRCList *list) { @@ -2462,6 +2575,12 @@ tls13_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length) return SECFailure; } + /* MUST NOT combine external PSKs with certificate authentication. */ + if (ss->sec.authType == ssl_auth_psk) { + FATAL_ERROR(ss, SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST, unexpected_message); + return SECFailure; + } + if (tls13_IsPostHandshake(ss)) { PORT_Assert(ss->ssl3.hs.shaPostHandshake == NULL); ss->ssl3.hs.shaPostHandshake = PK11_CloneContext(ss->ssl3.hs.sha); @@ -2577,6 +2696,8 @@ tls13_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length) PRBool tls13_ShouldRequestClientAuth(sslSocket *ss) { + /* Even if we are configured to request a certificate, we can't + * if this handshake used a PSK, even when we are resuming. */ return ss->opt.requestCertificate && ss->ssl3.hs.kea_def->authKeyType != ssl_auth_psk; } @@ -2745,7 +2866,9 @@ tls13_SendServerHelloSequence(sslSocket *ss) } } - ss->ssl3.hs.serverHelloTime = ssl_Time(ss); + /* Here we set a baseline value for our RTT estimation. + * This value is updated when we get a response from the client. */ + ss->ssl3.hs.rttEstimate = ssl_Time(ss); return SECSuccess; } @@ -2757,14 +2880,22 @@ tls13_HandleServerHelloPart2(sslSocket *ss) SSL3Statistics *ssl3stats = SSL_GetStatistics(); if (ssl3_ExtensionNegotiated(ss, ssl_tls13_pre_shared_key_xtn)) { - PORT_Assert(ss->statelessResume); + PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks)); + PORT_Assert(ss->xtnData.selectedPsk); + + if (ss->xtnData.selectedPsk->type != ssl_psk_resume) { + ss->statelessResume = PR_FALSE; + } } else { + /* We may have offered a PSK. If the server didn't negotiate + * it, clear this state to re-extract the Early Secret. */ if (ss->ssl3.hs.currentSecret) { - PORT_Assert(ss->statelessResume); + PORT_Assert(ssl3_ExtensionAdvertised(ss, ssl_tls13_pre_shared_key_xtn)); PK11_FreeSymKey(ss->ssl3.hs.currentSecret); ss->ssl3.hs.currentSecret = NULL; } ss->statelessResume = PR_FALSE; + ss->xtnData.selectedPsk = NULL; } if (ss->statelessResume) { @@ -2781,19 +2912,22 @@ tls13_HandleServerHelloPart2(sslSocket *ss) ss->ssl3.hs.kea_def_mutable = *ss->ssl3.hs.kea_def; ss->ssl3.hs.kea_def = &ss->ssl3.hs.kea_def_mutable; - if (ss->statelessResume) { - /* PSK */ + if (ss->xtnData.selectedPsk) { ss->ssl3.hs.kea_def_mutable.authKeyType = ssl_auth_psk; - tls13_RestoreCipherInfo(ss, sid); - if (sid->peerCert) { - ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); - } + if (ss->statelessResume) { + tls13_RestoreCipherInfo(ss, sid); + if (sid->peerCert) { + ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); + } - SSL_AtomicIncrementLong(&ssl3stats->hsh_sid_cache_hits); - SSL_AtomicIncrementLong(&ssl3stats->hsh_sid_stateless_resumes); + SSL_AtomicIncrementLong(&ssl3stats->hsh_sid_cache_hits); + SSL_AtomicIncrementLong(&ssl3stats->hsh_sid_stateless_resumes); + } else { + ss->sec.authType = ssl_auth_psk; + } } else { - /* !PSK */ - if (ssl3_ExtensionAdvertised(ss, ssl_tls13_pre_shared_key_xtn)) { + if (ss->statelessResume && + ssl3_ExtensionAdvertised(ss, ssl_tls13_pre_shared_key_xtn)) { SSL_AtomicIncrementLong(&ssl3stats->hsh_sid_cache_misses); } if (sid->cached == in_client_cache) { @@ -2802,18 +2936,6 @@ tls13_HandleServerHelloPart2(sslSocket *ss) } } - if (!ss->ssl3.hs.currentSecret) { - PORT_Assert(!ss->statelessResume); - - /* If we don't already have the Early Secret we need to make it - * now. */ - rv = tls13_ComputeEarlySecrets(ss); - if (rv != SECSuccess) { - FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); - return SECFailure; - } - } - /* Discard current SID and make a new one, though it may eventually * end up looking a lot like the old one. */ @@ -3113,6 +3235,13 @@ tls13_HandleCertificate(sslSocket *ss, PRUint8 *b, PRUint32 length) PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); if (ss->sec.isServer) { + /* Receiving this message might be the first sign we have that + * early data is over, so pretend we received EOED. */ + rv = tls13_MaybeHandleSuppressedEndOfEarlyData(ss); + if (rv != SECSuccess) { + return SECFailure; /* Code already set. */ + } + if (ss->ssl3.clientCertRequested) { rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERTIFICATE, idle_handshake); @@ -3124,8 +3253,9 @@ tls13_HandleCertificate(sslSocket *ss, PRUint8 *b, PRUint32 length) rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERTIFICATE, wait_cert_request, wait_server_cert); } - if (rv != SECSuccess) + if (rv != SECSuccess) { return SECFailure; + } /* We can ignore any other cleartext from the client. */ if (ss->sec.isServer && IS_DTLS(ss)) { @@ -3139,6 +3269,11 @@ tls13_HandleCertificate(sslSocket *ss, PRUint8 *b, PRUint32 length) PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } + } else if (ss->sec.isServer) { + /* Our first shot an getting an RTT estimate. If the client took extra + * time to fetch a certificate, this will be bad, but we can't do much + * about that. */ + ss->ssl3.hs.rttEstimate = ssl_Time(ss) - ss->ssl3.hs.rttEstimate; } /* Process the context string */ @@ -3310,15 +3445,15 @@ tls13_DeriveSecret(sslSocket *ss, PK11SymKey *key, const char *label, unsigned int labelLen, const SSL3Hashes *hashes, - PK11SymKey **dest) + PK11SymKey **dest, + SSLHashType hash) { SECStatus rv; - rv = tls13_HkdfExpandLabel(key, tls13_GetHash(ss), - hashes->u.raw, hashes->len, - label, labelLen, - tls13_GetHkdfMechanism(ss), - tls13_GetHashSize(ss), dest); + rv = tls13_HkdfExpandLabel(key, hash, hashes->u.raw, hashes->len, + label, labelLen, CKM_HKDF_DERIVE, + tls13_GetHashSizeForHash(hash), + ss->protocolVariant, dest); if (rv != SECSuccess) { LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -3331,18 +3466,19 @@ SECStatus tls13_DeriveSecretNullHash(sslSocket *ss, PK11SymKey *key, const char *label, unsigned int labelLen, - PK11SymKey **dest) + PK11SymKey **dest, + SSLHashType hash) { SSL3Hashes hashes; SECStatus rv; PRUint8 buf[] = { 0 }; - rv = tls13_ComputeHash(ss, &hashes, buf, 0); + rv = tls13_ComputeHash(ss, &hashes, buf, 0, hash); if (rv != SECSuccess) { return SECFailure; } - return tls13_DeriveSecret(ss, key, label, labelLen, &hashes, dest); + return tls13_DeriveSecret(ss, key, label, labelLen, &hashes, dest, hash); } /* Convenience wrapper that lets us supply a separate prefix and suffix. */ @@ -3381,7 +3517,7 @@ tls13_DeriveSecretWrap(sslSocket *ss, PK11SymKey *key, } rv = tls13_DeriveSecret(ss, key, label, strlen(label), - &hashes, dest); + &hashes, dest, tls13_GetHash(ss)); if (rv != SECSuccess) { return SECFailure; } @@ -3467,6 +3603,7 @@ tls13_DeriveTrafficKeys(sslSocket *ss, ssl3CipherSpec *spec, NULL, 0, kHkdfPurposeKey, strlen(kHkdfPurposeKey), bulkAlgorithm, keySize, + ss->protocolVariant, &spec->keyMaterial.key); if (rv != SECSuccess) { LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE); @@ -3474,9 +3611,21 @@ tls13_DeriveTrafficKeys(sslSocket *ss, ssl3CipherSpec *spec, goto loser; } + if (IS_DTLS(ss) && spec->epoch > 0) { + rv = ssl_CreateMaskingContextInner(spec->version, ss->ssl3.hs.cipher_suite, + ss->protocolVariant, prk, kHkdfPurposeSn, + strlen(kHkdfPurposeSn), &spec->maskContext); + if (rv != SECSuccess) { + LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE); + PORT_Assert(0); + goto loser; + } + } + rv = tls13_HkdfExpandLabelRaw(prk, tls13_GetHash(ss), NULL, 0, kHkdfPurposeIv, strlen(kHkdfPurposeIv), + ss->protocolVariant, spec->keyMaterial.iv, ivSize); if (rv != SECSuccess) { LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE); @@ -3507,21 +3656,6 @@ tls13_SetSpecRecordVersion(sslSocket *ss, ssl3CipherSpec *spec) SSL_GETPID(), ss->fd, spec, spec->recordVersion)); } -SSLAEADCipher -tls13_GetAead(const ssl3BulkCipherDef *cipherDef) -{ - switch (cipherDef->calg) { - case ssl_calg_aes_gcm: - return tls13_AESGCM; - case ssl_calg_chacha20: - return tls13_ChaCha20Poly1305; - default: - PORT_Assert(PR_FALSE); - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return NULL; - } -} - static SECStatus tls13_SetupPendingCipherSpec(sslSocket *ss, ssl3CipherSpec *spec) { @@ -3545,14 +3679,12 @@ tls13_SetupPendingCipherSpec(sslSocket *ss, ssl3CipherSpec *spec) SSL_GETPID(), ss->fd, suite)); spec->cipherDef = ssl_GetBulkCipherDef(ssl_LookupCipherSuiteDef(suite)); - spec->aead = tls13_GetAead(spec->cipherDef); - if (!spec->aead) { - return SECFailure; - } if (spec->epoch == TrafficKeyEarlyApplicationData) { - spec->earlyDataRemaining = - ss->sec.ci.sid->u.ssl3.locked.sessionTicket.max_early_data_size; + if (ss->xtnData.selectedPsk && + ss->xtnData.selectedPsk->zeroRttSuite != TLS_NULL_WITH_NULL_NULL) { + spec->earlyDataRemaining = ss->xtnData.selectedPsk->maxEarlyData; + } } tls13_SetSpecRecordVersion(ss, spec); @@ -3571,6 +3703,38 @@ tls13_SetupPendingCipherSpec(sslSocket *ss, ssl3CipherSpec *spec) } /* + * Initialize the cipher context. All TLS 1.3 operations are AEAD, + * so they are all message contexts. + */ +static SECStatus +tls13_InitPendingContext(sslSocket *ss, ssl3CipherSpec *spec) +{ + CK_MECHANISM_TYPE encMechanism; + CK_ATTRIBUTE_TYPE encMode; + SECItem iv; + SSLCipherAlgorithm calg; + + calg = spec->cipherDef->calg; + + encMechanism = ssl3_Alg2Mech(calg); + encMode = CKA_NSS_MESSAGE | ((spec->direction == ssl_secret_write) ? CKA_ENCRYPT : CKA_DECRYPT); + iv.data = NULL; + iv.len = 0; + + /* + * build the context + */ + spec->cipherContext = PK11_CreateContextBySymKey(encMechanism, encMode, + spec->keyMaterial.key, + &iv); + if (!spec->cipherContext) { + ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE); + return SECFailure; + } + return SECSuccess; +} + +/* * Called before sending alerts to set up the right key on the client. * We might encounter errors during the handshake where the current * key is ClearText or EarlyApplicationData. This @@ -3649,6 +3813,11 @@ tls13_SetCipherSpec(sslSocket *ss, PRUint16 epoch, goto loser; } + rv = tls13_InitPendingContext(ss, spec); + if (rv != SECSuccess) { + goto loser; + } + /* Now that we've set almost everything up, finally cut over. */ specp = (direction == ssl_secret_read) ? &ss->ssl3.crSpec : &ss->ssl3.cwSpec; ssl_GetSpecWriteLock(ss); @@ -3811,100 +3980,113 @@ 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(const ssl3KeyMaterial *keys, - const unsigned char *seqNumBuf, unsigned int seqNumLen, - unsigned char *nonce, unsigned int nonceLen) +tls13_WriteNonce(const unsigned char *ivIn, unsigned int ivInLen, + const unsigned char *nonce, unsigned int nonceLen, + unsigned char *ivOut, unsigned int ivOutLen) { size_t i; + unsigned int offset = ivOutLen - nonceLen; - PORT_Assert(nonceLen == 12); - memcpy(nonce, keys->iv, 12); + PORT_Assert(ivInLen <= ivOutLen); + PORT_Assert(nonceLen <= ivOutLen); + PORT_Memset(ivOut, 0, ivOutLen); + PORT_Memcpy(ivOut, ivIn, ivInLen); - /* XOR the last 8 bytes of the IV with the sequence number. */ - PORT_Assert(seqNumLen == 8); - for (i = 0; i < 8; ++i) { - nonce[4 + i] ^= seqNumBuf[i]; + /* XOR the last n bytes of the IV with the nonce (should be a counter). */ + for (i = 0; i < nonceLen; ++i) { + ivOut[offset + i] ^= nonce[i]; } - PRINT_BUF(50, (NULL, "Nonce", nonce, nonceLen)); + PRINT_BUF(50, (NULL, "Nonce", ivOut, ivOutLen)); } -/* Implement the SSLAEADCipher interface defined in sslimpl.h. - * - * That interface takes the additional data (see below) and reinterprets that as - * a sequence number. In TLS 1.3 there is no additional data so this value is - * just the encoded sequence number. +/* Setup the IV for AEAD encrypt. The PKCS #11 module will add the + * counter, but it doesn't know about the DTLS epic, so we add it here. */ -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) +unsigned int +tls13_SetupAeadIv(PRBool isDTLS, unsigned char *ivOut, unsigned char *ivIn, + unsigned int offset, unsigned int ivLen, DTLSEpoch epoch) { - SECItem param = { - siBuffer, aeadParams, aeadParamLength - }; - - if (doDecrypt) { - return PK11_Decrypt(keys->key, mechanism, ¶m, - out, outlen, maxout, in, inlen); + PORT_Memcpy(ivOut, ivIn, ivLen); + if (isDTLS) { + /* handle the tls 1.2 counter mode case, the epoc is copied + * instead of xored. We accomplish this by clearing ivOut + * before running xor. */ + if (offset >= ivLen) { + ivOut[offset] = ivOut[offset + 1] = 0; + } + ivOut[offset] ^= (unsigned char)(epoch >> BPB) & 0xff; + ivOut[offset + 1] ^= (unsigned char)(epoch)&0xff; + offset += 2; } - return PK11_Encrypt(keys->key, mechanism, ¶m, - out, outlen, maxout, in, inlen); + return offset; } -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) +/* + * Do a single AEAD for TLS. This differs from PK11_AEADOp in the following + * ways. + * 1) If context is not supplied, it treats the operation as a single shot + * and creates a context from symKey and mech. + * 2) It always assumes the tag will be at the end of the buffer + * (in on decrypt, out on encrypt) just like the old single shot. + * 3) If we aren't generating an IV, it uses tls13_WriteNonce to create the + * nonce. + * NOTE is context is supplied, symKey and mech are ignored + */ +SECStatus +tls13_AEAD(PK11Context *context, PRBool decrypt, + CK_GENERATOR_FUNCTION ivGen, unsigned int fixedbits, + const unsigned char *ivIn, unsigned char *ivOut, unsigned int ivLen, + const unsigned char *nonceIn, unsigned int nonceLen, + const unsigned char *aad, unsigned int aadLen, + unsigned char *out, unsigned int *outLen, unsigned int maxout, + unsigned int tagLen, const unsigned char *in, unsigned int inLen) { - CK_GCM_PARAMS gcmParams; - unsigned char nonce[12]; - - PORT_Assert(additionalDataLen >= 8); - memset(&gcmParams, 0, sizeof(gcmParams)); - gcmParams.pIv = nonce; - gcmParams.ulIvLen = sizeof(nonce); - gcmParams.pAAD = (PRUint8 *)(additionalData + 8); - gcmParams.ulAADLen = additionalDataLen - 8; - gcmParams.ulTagBits = 128; /* GCM measures tag length in bits. */ - - tls13_WriteNonce(keys, additionalData, 8, - nonce, sizeof(nonce)); - return tls13_AEAD(keys, doDecrypt, out, outlen, maxout, in, inlen, - CKM_AES_GCM, - (unsigned char *)&gcmParams, sizeof(gcmParams)); -} + unsigned char *tag; + unsigned char iv[MAX_IV_LENGTH]; + unsigned char tagbuf[HASH_LENGTH_MAX]; + SECStatus rv; -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) -{ - CK_NSS_AEAD_PARAMS aeadParams; - unsigned char nonce[12]; - - PORT_Assert(additionalDataLen > 8); - memset(&aeadParams, 0, sizeof(aeadParams)); - aeadParams.pNonce = nonce; - aeadParams.ulNonceLen = sizeof(nonce); - aeadParams.pAAD = (PRUint8 *)(additionalData + 8); - aeadParams.ulAADLen = additionalDataLen - 8; - aeadParams.ulTagLen = 16; /* The Poly1305 tag is 16 octets. */ - - tls13_WriteNonce(keys, additionalData, 8, - nonce, sizeof(nonce)); - return tls13_AEAD(keys, doDecrypt, out, outlen, maxout, in, inlen, - CKM_NSS_CHACHA20_POLY1305, - (unsigned char *)&aeadParams, sizeof(aeadParams)); + /* must have either context or the symKey set */ + if (!context) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + PORT_Assert(ivLen <= MAX_IV_LENGTH); + PORT_Assert(tagLen <= HASH_LENGTH_MAX); + if (!ivOut) { + ivOut = iv; /* caller doesn't need a returned, iv */ + } + + if (ivGen == CKG_NO_GENERATE) { + tls13_WriteNonce(ivIn, ivLen, nonceIn, nonceLen, ivOut, ivLen); + } else if (ivIn != ivOut) { + PORT_Memcpy(ivOut, ivIn, ivLen); + } + if (decrypt) { + inLen = inLen - tagLen; + tag = (unsigned char *)in + inLen; + /* tag is const on decrypt, but returned on encrypt */ + } else { + /* tag is written to a separate buffer, then added to the end + * of the actual output buffer. This allows output buffer to be larger + * than the input buffer and everything still work */ + tag = tagbuf; + } + rv = PK11_AEADOp(context, ivGen, fixedbits, ivOut, ivLen, aad, aadLen, + out, (int *)outLen, maxout, tag, tagLen, in, inLen); + /* on encrypt SSL always puts the tag at the end of the buffer */ + if ((rv == SECSuccess) && !(decrypt)) { + unsigned int len = *outLen; + /* make sure there is still space */ + if (len + tagLen > maxout) { + PORT_SetError(SEC_ERROR_OUTPUT_LEN); + return SECFailure; + } + PORT_Memcpy(out + len, tag, tagLen); + *outLen += tagLen; + } + return rv; } static SECStatus @@ -3968,7 +4150,7 @@ tls13_HandleEncryptedExtensions(sslSocket *ss, PRUint8 *b, PRUint32 length) /* We can only get here if we offered 0-RTT. */ if (ssl3_ExtensionNegotiated(ss, ssl_tls13_early_data_xtn)) { PORT_Assert(ss->ssl3.hs.zeroRttState == ssl_0rtt_sent); - if (!ss->statelessResume) { + if (!ss->xtnData.selectedPsk) { /* Illegal to accept 0-RTT without also accepting PSK. */ FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_ENCRYPTED_EXTENSIONS, illegal_parameter); @@ -4006,6 +4188,10 @@ tls13_HandleEncryptedExtensions(sslSocket *ss, PRUint8 *b, PRUint32 length) TLS13_SET_HS_STATE(ss, wait_cert_request); } + /* Client is done with any PSKs */ + tls13_DestroyPskList(&ss->ssl3.hs.psks); + ss->xtnData.selectedPsk = NULL; + return SECSuccess; } @@ -4285,7 +4471,7 @@ loser: static SECStatus tls13_ComputePskBinderHash(sslSocket *ss, unsigned int prefixLength, - SSL3Hashes *hashes) + SSL3Hashes *hashes, SSLHashType hashType) { SECStatus rv; @@ -4295,14 +4481,14 @@ tls13_ComputePskBinderHash(sslSocket *ss, unsigned int prefixLength, PRINT_BUF(10, (NULL, "Handshake hash computed over ClientHello prefix", ss->ssl3.hs.messages.buf, prefixLength)); - rv = PK11_HashBuf(ssl3_HashTypeToOID(tls13_GetHash(ss)), + rv = PK11_HashBuf(ssl3_HashTypeToOID(hashType), hashes->u.raw, ss->ssl3.hs.messages.buf, prefixLength); if (rv != SECSuccess) { ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); return SECFailure; } - hashes->len = tls13_GetHashSize(ss); + hashes->len = tls13_GetHashSizeForHash(hashType); PRINT_BUF(10, (NULL, "PSK Binder hash", hashes->u.raw, hashes->len)); return SECSuccess; @@ -4320,7 +4506,10 @@ tls13_WriteExtensionsWithBinder(sslSocket *ss, sslBuffer *extensions) { SSL3Hashes hashes; SECStatus rv; - unsigned int size = tls13_GetHashSize(ss); + + PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks)); + sslPsk *psk = (sslPsk *)PR_LIST_HEAD(&ss->ssl3.hs.psks); + unsigned int size = tls13_GetHashSizeForHash(psk->hash); unsigned int prefixLen = extensions->len - size - 3; unsigned int finishedLen; @@ -4341,15 +4530,18 @@ tls13_WriteExtensionsWithBinder(sslSocket *ss, sslBuffer *extensions) } /* Calculate the binder based on what has been written out. */ - rv = tls13_ComputePskBinderHash(ss, ss->ssl3.hs.messages.len, &hashes); + rv = tls13_ComputePskBinderHash(ss, ss->ssl3.hs.messages.len, + &hashes, psk->hash); if (rv != SECSuccess) { return SECFailure; } /* Write the binder into the extensions buffer, over the zeros we reserved - * previously. This avoids an allocation and means that we don't need a + * previously. This avoids an allocation and means that we don't need a * separate write for the extra bits that precede the binder. */ - rv = tls13_ComputeFinished(ss, ss->ssl3.hs.pskBinderKey, &hashes, PR_TRUE, + PORT_Assert(psk->binderKey); + rv = tls13_ComputeFinished(ss, psk->binderKey, + psk->hash, &hashes, PR_TRUE, extensions->buf + extensions->len - size, &finishedLen, size); if (rv != SECSuccess) { @@ -4369,13 +4561,13 @@ tls13_WriteExtensionsWithBinder(sslSocket *ss, sslBuffer *extensions) static SECStatus tls13_ComputeFinished(sslSocket *ss, PK11SymKey *baseKey, - const SSL3Hashes *hashes, + SSLHashType hashType, const SSL3Hashes *hashes, PRBool sending, PRUint8 *output, unsigned int *outputLen, unsigned int maxOutputLen) { SECStatus rv; PK11Context *hmacCtx = NULL; - CK_MECHANISM_TYPE macAlg = tls13_GetHmacMechanism(ss); + CK_MECHANISM_TYPE macAlg = tls13_GetHmacMechanismFromHash(hashType); SECItem param = { siBuffer, NULL, 0 }; unsigned int outputLenUint; const char *label = kHkdfLabelFinishedSecret; @@ -4387,17 +4579,16 @@ tls13_ComputeFinished(sslSocket *ss, PK11SymKey *baseKey, PRINT_BUF(50, (ss, "Handshake hash", hashes->u.raw, hashes->len)); /* Now derive the appropriate finished secret from the base secret. */ - rv = tls13_HkdfExpandLabel(baseKey, - tls13_GetHash(ss), - NULL, 0, - label, strlen(label), - tls13_GetHmacMechanism(ss), - tls13_GetHashSize(ss), &secret); + rv = tls13_HkdfExpandLabel(baseKey, hashType, + NULL, 0, label, strlen(label), + tls13_GetHmacMechanismFromHash(hashType), + tls13_GetHashSizeForHash(hashType), + ss->protocolVariant, &secret); if (rv != SECSuccess) { goto abort; } - PORT_Assert(hashes->len == tls13_GetHashSize(ss)); + PORT_Assert(hashes->len == tls13_GetHashSizeForHash(hashType)); hmacCtx = PK11_CreateContextBySymKey(macAlg, CKA_SIGN, secret, ¶m); if (!hmacCtx) { @@ -4412,7 +4603,7 @@ tls13_ComputeFinished(sslSocket *ss, PK11SymKey *baseKey, if (rv != SECSuccess) goto abort; - PORT_Assert(maxOutputLen >= tls13_GetHashSize(ss)); + PORT_Assert(maxOutputLen >= tls13_GetHashSizeForHash(hashType)); rv = PK11_DigestFinal(hmacCtx, output, &outputLenUint, maxOutputLen); if (rv != SECSuccess) goto abort; @@ -4456,7 +4647,7 @@ tls13_SendFinished(sslSocket *ss, PK11SymKey *baseKey) } ssl_GetSpecReadLock(ss); - rv = tls13_ComputeFinished(ss, baseKey, &hashes, PR_TRUE, + rv = tls13_ComputeFinished(ss, baseKey, tls13_GetHash(ss), &hashes, PR_TRUE, finishedBuf, &finishedLen, sizeof(finishedBuf)); ssl_ReleaseSpecReadLock(ss); if (rv != SECSuccess) { @@ -4493,7 +4684,7 @@ tls13_VerifyFinished(sslSocket *ss, SSLHandshakeType message, return SECFailure; } - rv = tls13_ComputeFinished(ss, secret, hashes, PR_FALSE, + rv = tls13_ComputeFinished(ss, secret, tls13_GetHash(ss), hashes, PR_FALSE, finishedBuf, &finishedLen, sizeof(finishedBuf)); if (rv != SECSuccess) { FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); @@ -4583,6 +4774,20 @@ tls13_ServerHandleFinished(sslSocket *ss, PRUint8 *b, PRUint32 length) SSL_TRC(3, ("%d: TLS13[%d]: server handle finished handshake", SSL_GETPID(), ss->fd)); + if (!tls13_ShouldRequestClientAuth(ss)) { + /* Receiving this message might be the first sign we have that + * early data is over, so pretend we received EOED. */ + rv = tls13_MaybeHandleSuppressedEndOfEarlyData(ss); + if (rv != SECSuccess) { + return SECFailure; /* Code already set. */ + } + + if (!tls13_IsPostHandshake(ss)) { + /* Finalize the RTT estimate. */ + ss->ssl3.hs.rttEstimate = ssl_Time(ss) - ss->ssl3.hs.rttEstimate; + } + } + rv = tls13_CommonHandleFinished(ss, ss->firstHsDone ? ss->ssl3.hs.clientTrafficSecret : ss->ssl3.hs.clientHsTrafficSecret, b, length); @@ -4646,7 +4851,8 @@ tls13_ServerHandleFinished(sslSocket *ss, PRUint8 *b, PRUint32 length) } ssl_GetXmitBufLock(ss); - if (ss->opt.enableSessionTickets) { + /* If resumption, authType is the original value and not ssl_auth_psk. */ + if (ss->opt.enableSessionTickets && ss->sec.authType != ssl_auth_psk) { rv = tls13_SendNewSessionTicket(ss, NULL, 0); if (rv != SECSuccess) { goto loser; @@ -4929,8 +5135,9 @@ tls13_SendNewSessionTicket(sslSocket *ss, const PRUint8 *appToken, ticketNonce, sizeof(ticketNonce), kHkdfLabelResumption, strlen(kHkdfLabelResumption), - tls13_GetHkdfMechanism(ss), - tls13_GetHashSize(ss), &secret); + CKM_HKDF_DERIVE, + tls13_GetHashSize(ss), + ss->protocolVariant, &secret); if (rv != SECSuccess) { goto loser; } @@ -5028,6 +5235,14 @@ SSLExp_SendSessionTicket(PRFileDesc *fd, const PRUint8 *token, return SECFailure; } + /* Disable tickets if we can trace this connection back to a PSK. + * We aren't able to issue tickets (currently) without a certificate. + * As PSK =~ resumption, there is no reason to do this. */ + if (ss->sec.authType == ssl_auth_psk) { + PORT_SetError(SSL_ERROR_FEATURE_DISABLED); + return SECFailure; + } + ssl_GetSSL3HandshakeLock(ss); ssl_GetXmitBufLock(ss); rv = tls13_SendNewSessionTicket(ss, token, tokenLen); @@ -5163,8 +5378,9 @@ tls13_HandleNewSessionTicket(sslSocket *ss, PRUint8 *b, PRUint32 length) ticket_nonce.data, ticket_nonce.len, kHkdfLabelResumption, strlen(kHkdfLabelResumption), - tls13_GetHkdfMechanism(ss), - tls13_GetHashSize(ss), &secret); + CKM_HKDF_DERIVE, + tls13_GetHashSize(ss), + ss->protocolVariant, &secret); if (rv != SECSuccess) { return SECFailure; } @@ -5348,11 +5564,20 @@ tls13_ProtectRecord(sslSocket *ss, sslBuffer buf = SSL_BUFFER_FIXED(hdr, sizeof(hdr)); PRBool needsLength; PRUint8 aad[21]; + const int ivLen = cipher_def->iv_size + cipher_def->explicit_nonce_size; + unsigned int ivOffset = ivLen - sizeof(sslSequenceNumber); + unsigned char ivOut[MAX_IV_LENGTH]; + unsigned int aadLen; unsigned int len; PORT_Assert(cipher_def->type == type_aead); + /* If the following condition holds, we can skip the padding logic for + * DTLS 1.3 (4.2.3). This will be the case until we support a cipher + * with tag length < 15B. */ + PORT_Assert(tagLen + 1 /* cType */ >= 16); + /* Add the content type at the end. */ *(SSL_BUFFER_NEXT(wrBuf) + contentLen) = type; @@ -5363,9 +5588,7 @@ tls13_ProtectRecord(sslSocket *ss, return SECFailure; } if (needsLength) { - rv = sslBuffer_AppendNumber(&buf, contentLen + 1 + - cwSpec->cipherDef->tag_size, - 2); + rv = sslBuffer_AppendNumber(&buf, contentLen + 1 + tagLen, 2); if (rv != SECSuccess) { return SECFailure; } @@ -5376,14 +5599,22 @@ tls13_ProtectRecord(sslSocket *ss, if (rv != SECSuccess) { return SECFailure; } - rv = cwSpec->aead(&cwSpec->keyMaterial, - PR_FALSE, /* do encrypt */ - SSL_BUFFER_NEXT(wrBuf), /* output */ - &len, /* out len */ - SSL_BUFFER_SPACE(wrBuf), /* max out */ - SSL_BUFFER_NEXT(wrBuf), /* input */ - contentLen + 1, /* input len */ - aad, aadLen); + /* set up initial IV value */ + ivOffset = tls13_SetupAeadIv(IS_DTLS(ss), ivOut, cwSpec->keyMaterial.iv, + ivOffset, ivLen, cwSpec->epoch); + + rv = tls13_AEAD(cwSpec->cipherContext, PR_FALSE, + CKG_GENERATE_COUNTER_XOR, ivOffset * BPB, + ivOut, ivOut, ivLen, /* iv */ + NULL, 0, /* nonce */ + aad + sizeof(sslSequenceNumber), /* aad */ + aadLen - sizeof(sslSequenceNumber), + SSL_BUFFER_NEXT(wrBuf), /* output */ + &len, /* out len */ + SSL_BUFFER_SPACE(wrBuf), /* max out */ + tagLen, + SSL_BUFFER_NEXT(wrBuf), /* input */ + contentLen + 1); /* input len */ if (rv != SECSuccess) { PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); return SECFailure; @@ -5413,6 +5644,9 @@ tls13_UnprotectRecord(sslSocket *ss, SSL3AlertDescription *alert) { const ssl3BulkCipherDef *cipher_def = spec->cipherDef; + const int ivLen = cipher_def->iv_size + cipher_def->explicit_nonce_size; + const int tagLen = cipher_def->tag_size; + PRUint8 aad[21]; unsigned int aadLen; SECStatus rv; @@ -5440,7 +5674,7 @@ tls13_UnprotectRecord(sslSocket *ss, /* We can perform this test in variable time because the record's total * length and the ciphersuite are both public knowledge. */ - if (cText->buf->len < cipher_def->tag_size) { + if (cText->buf->len < tagLen) { SSL_TRC(3, ("%d: TLS13[%d]: record too short to contain valid AEAD data", SSL_GETPID(), ss->fd)); @@ -5467,17 +5701,26 @@ tls13_UnprotectRecord(sslSocket *ss, spec->epoch, cText->seqNum, aad, &aadLen, sizeof(aad)); if (rv != SECSuccess) { + return SECFailure; } - rv = spec->aead(&spec->keyMaterial, - PR_TRUE, /* do decrypt */ - plaintext->buf, /* out */ + rv = tls13_AEAD(spec->cipherContext, PR_TRUE, + CKG_NO_GENERATE, 0, /* ignored for decrypt */ + spec->keyMaterial.iv, NULL, ivLen, /* iv */ + aad, sizeof(sslSequenceNumber), /* nonce */ + aad + sizeof(sslSequenceNumber), /* aad */ + aadLen - sizeof(sslSequenceNumber), + plaintext->buf, /* output */ &plaintext->len, /* outlen */ plaintext->space, /* maxout */ + tagLen, cText->buf->buf, /* in */ - cText->buf->len, /* inlen */ - aad, aadLen); + cText->buf->len); /* inlen */ if (rv != SECSuccess) { + if (IS_DTLS(ss)) { + spec->deprotectionFailures++; + } + SSL_TRC(3, ("%d: TLS13[%d]: record has bogus MAC", SSL_GETPID(), ss->fd)); @@ -5538,9 +5781,10 @@ tls13_UnprotectRecord(sslSocket *ss, * 1. We are doing TLS 1.3 * 2. This isn't a second ClientHello (in response to HelloRetryRequest) * 3. The 0-RTT option is set. - * 4. We have a valid ticket. - * 5. The server is willing to accept 0-RTT. - * 6. We have not changed our ALPN settings to disallow the ALPN tag + * 4. We have a valid ticket or an External PSK. + * 5. If resuming: + * 5a. The server is willing to accept 0-RTT. + * 5b. We have not changed our ALPN settings to disallow the ALPN tag * in the ticket. * * Called from tls13_ClientSendEarlyDataXtn(). @@ -5550,17 +5794,39 @@ tls13_ClientAllow0Rtt(const sslSocket *ss, const sslSessionID *sid) { /* We checked that the cipher suite was still allowed back in * ssl3_SendClientHello. */ - if (sid->version < SSL_LIBRARY_VERSION_TLS_1_3) + if (sid->version < SSL_LIBRARY_VERSION_TLS_1_3) { return PR_FALSE; - if (ss->ssl3.hs.helloRetry) + } + if (ss->ssl3.hs.helloRetry) { return PR_FALSE; - if (!ss->opt.enable0RttData) + } + if (!ss->opt.enable0RttData) { return PR_FALSE; - if (!ss->statelessResume) + } + if (PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks)) { return PR_FALSE; - if ((sid->u.ssl3.locked.sessionTicket.flags & ticket_allow_early_data) == 0) + } + sslPsk *psk = (sslPsk *)PR_LIST_HEAD(&ss->ssl3.hs.psks); + + if (psk->zeroRttSuite == TLS_NULL_WITH_NULL_NULL) { return PR_FALSE; - return ssl_AlpnTagAllowed(ss, &sid->u.ssl3.alpnSelection); + } + if (!psk->maxEarlyData) { + return PR_FALSE; + } + + if (psk->type == ssl_psk_external) { + return psk->hash == tls13_GetHashForCipherSuite(psk->zeroRttSuite); + } + if (psk->type == ssl_psk_resume) { + if (!ss->statelessResume) + return PR_FALSE; + if ((sid->u.ssl3.locked.sessionTicket.flags & ticket_allow_early_data) == 0) + return PR_FALSE; + return ssl_AlpnTagAllowed(ss, &sid->u.ssl3.alpnSelection); + } + PORT_Assert(0); + return PR_FALSE; } SECStatus @@ -5607,6 +5873,9 @@ tls13_MaybeDo0RTTHandshake(sslSocket *ss) } } + /* If we're trying 0-RTT, derive from the first PSK */ + PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks) && !ss->xtnData.selectedPsk); + ss->xtnData.selectedPsk = (sslPsk *)PR_LIST_HEAD(&ss->ssl3.hs.psks); rv = tls13_DeriveEarlySecrets(ss); if (rv != SECSuccess) { return SECFailure; @@ -5618,6 +5887,7 @@ tls13_MaybeDo0RTTHandshake(sslSocket *ss) rv = tls13_SetCipherSpec(ss, TrafficKeyEarlyApplicationData, ssl_secret_write, PR_TRUE); + ss->xtnData.selectedPsk = NULL; if (rv != SECSuccess) { return SECFailure; } @@ -5672,12 +5942,14 @@ tls13_SendEndOfEarlyData(sslSocket *ss) { SECStatus rv; - SSL_TRC(3, ("%d: TLS13[%d]: send EndOfEarlyData", SSL_GETPID(), ss->fd)); PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); - rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_end_of_early_data, 0); - if (rv != SECSuccess) { - return rv; /* err set by AppendHandshake. */ + if (!ss->opt.suppressEndOfEarlyData) { + SSL_TRC(3, ("%d: TLS13[%d]: send EndOfEarlyData", SSL_GETPID(), ss->fd)); + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_end_of_early_data, 0); + if (rv != SECSuccess) { + return rv; /* err set by AppendHandshake. */ + } } ss->ssl3.hs.zeroRttState = ssl_0rtt_done; @@ -5685,7 +5957,7 @@ tls13_SendEndOfEarlyData(sslSocket *ss) } static SECStatus -tls13_HandleEndOfEarlyData(sslSocket *ss, PRUint8 *b, PRUint32 length) +tls13_HandleEndOfEarlyData(sslSocket *ss, const PRUint8 *b, PRUint32 length) { SECStatus rv; @@ -5728,6 +6000,18 @@ tls13_HandleEndOfEarlyData(sslSocket *ss, PRUint8 *b, PRUint32 length) return SECSuccess; } +static SECStatus +tls13_MaybeHandleSuppressedEndOfEarlyData(sslSocket *ss) +{ + PORT_Assert(ss->sec.isServer); + if (!ss->opt.suppressEndOfEarlyData || + ss->ssl3.hs.zeroRttState != ssl_0rtt_accepted) { + return SECSuccess; + } + + return tls13_HandleEndOfEarlyData(ss, NULL, 0); +} + SECStatus tls13_HandleEarlyApplicationData(sslSocket *ss, sslBuffer *origBuf) { @@ -5763,14 +6047,26 @@ tls13_HandleEarlyApplicationData(sslSocket *ss, sslBuffer *origBuf) } PRUint16 -tls13_EncodeDraftVersion(SSL3ProtocolVersion version, SSLProtocolVariant variant) +tls13_EncodeVersion(SSL3ProtocolVersion version, SSLProtocolVariant variant) { + if (variant == ssl_variant_datagram) { + /* TODO: When DTLS 1.3 is out of draft, replace this with + * dtls_TLSVersionToDTLSVersion(). */ + switch (version) { #ifdef DTLS_1_3_DRAFT_VERSION - if (version == SSL_LIBRARY_VERSION_TLS_1_3 && - variant == ssl_variant_datagram) { - return 0x7f00 | DTLS_1_3_DRAFT_VERSION; - } + case SSL_LIBRARY_VERSION_TLS_1_3: + return 0x7f00 | DTLS_1_3_DRAFT_VERSION; #endif + case SSL_LIBRARY_VERSION_TLS_1_2: + return SSL_LIBRARY_VERSION_DTLS_1_2_WIRE; + case SSL_LIBRARY_VERSION_TLS_1_1: + /* TLS_1_1 maps to DTLS_1_0, see sslproto.h. */ + return SSL_LIBRARY_VERSION_DTLS_1_0_WIRE; + default: + PORT_Assert(0); + } + } + /* Stream-variant encodings do not change. */ return (PRUint16)version; } @@ -5800,8 +6096,8 @@ tls13_ClientReadSupportedVersion(sslSocket *ss) return SECFailure; } - if (temp != tls13_EncodeDraftVersion(SSL_LIBRARY_VERSION_TLS_1_3, - ss->protocolVariant)) { + if (temp != tls13_EncodeVersion(SSL_LIBRARY_VERSION_TLS_1_3, + ss->protocolVariant)) { /* You cannot negotiate < TLS 1.3 with supported_versions. */ FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_SERVER_HELLO, illegal_parameter); return SECFailure; @@ -5840,7 +6136,7 @@ tls13_NegotiateVersion(sslSocket *ss, const TLSExtension *supportedVersions) return SECFailure; } - PRUint16 wire = tls13_EncodeDraftVersion(version, ss->protocolVariant); + PRUint16 wire = tls13_EncodeVersion(version, ss->protocolVariant); unsigned long offset; for (offset = 0; offset < versions.len; offset += 2) { |