diff options
Diffstat (limited to 'nss/lib/ssl/ssl3con.c')
-rw-r--r-- | nss/lib/ssl/ssl3con.c | 721 |
1 files changed, 358 insertions, 363 deletions
diff --git a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c index 154d22a..5d3bd07 100644 --- a/nss/lib/ssl/ssl3con.c +++ b/nss/lib/ssl/ssl3con.c @@ -38,13 +38,6 @@ #include "zlib.h" #endif -#ifndef PK11_SETATTRS -#define PK11_SETATTRS(x, id, v, l) \ - (x)->type = (id); \ - (x)->pValue = (v); \ - (x)->ulValueLen = (l); -#endif - static PK11SymKey *ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec, PK11SlotInfo *serverKeySlot); static SECStatus ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms); @@ -273,10 +266,6 @@ static const /*SSL3ClientCertificateType */ PRUint8 certificate_types[] = { ct_DSS_sign, }; -/* This global item is used only in servers. It is is initialized by -** SSL_ConfigSecureServer(), and is used in ssl3_SendCertificateRequest(). -*/ -CERTDistNames *ssl3_server_ca_list = NULL; static SSL3Statistics ssl3stats; /* Record protection algorithms, indexed by SSL3BulkCipher. @@ -863,12 +852,10 @@ ssl_HasCert(const sslSocket *ss, SSLAuthType authType) cursor != &ss->serverCerts; cursor = PR_NEXT_LINK(cursor)) { sslServerCert *cert = (sslServerCert *)cursor; - if (cert->certType.authType != authType) { - continue; - } if (!cert->serverKeyPair || !cert->serverKeyPair->privKey || - !cert->serverCertChain) { + !cert->serverCertChain || + !SSL_CERT_IS(cert, authType)) { continue; } /* When called from ssl3_config_match_init(), all the EC curves will be @@ -879,7 +866,7 @@ ssl_HasCert(const sslSocket *ss, SSLAuthType authType) if ((authType == ssl_auth_ecdsa || authType == ssl_auth_ecdh_ecdsa || authType == ssl_auth_ecdh_rsa) && - !ssl_NamedGroupEnabled(ss, cert->certType.namedCurve)) { + !ssl_NamedGroupEnabled(ss, cert->namedCurve)) { continue; } return PR_TRUE; @@ -1044,8 +1031,9 @@ Null_Cipher(void *ctx, unsigned char *output, int *outputLen, int maxOutputLen, return SECFailure; } *outputLen = inputLen; - if (input != output) + if (inputLen > 0 && input != output) { PORT_Memcpy(output, input, inputLen); + } return SECSuccess; } @@ -1088,10 +1076,11 @@ ssl_ClientReadVersion(sslSocket *ss, SSL3Opaque **b, unsigned int *len, SSL3ProtocolVersion *version) { SSL3ProtocolVersion v; - PRInt32 temp; + PRUint32 temp; + SECStatus rv; - temp = ssl3_ConsumeHandshakeNumber(ss, 2, b, len); - if (temp < 0) { + rv = ssl3_ConsumeHandshakeNumber(ss, &temp, 2, b, len); + if (rv != SECSuccess) { return SECFailure; /* alert has been sent */ } @@ -1624,10 +1613,6 @@ ssl3_SetupPendingCipherSpec(sslSocket *ss) pwSpec->compressContext = NULL; pwSpec->decompressContext = NULL; - if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) { - PORT_Assert(ss->ssl3.hs.kea_def->ephemeral); - PORT_Assert(pwSpec->cipher_def->type == type_aead); - } ssl_ReleaseSpecWriteLock(ss); /*******************************/ return SECSuccess; } @@ -1777,29 +1762,6 @@ ssl3_InitCompressionContext(ssl3CipherSpec *pwSpec) return SECSuccess; } -/* This function should probably be moved to pk11wrap and be named - * PK11_ParamFromIVAndEffectiveKeyBits - */ -static SECItem * -ssl3_ParamFromIV(CK_MECHANISM_TYPE mtype, SECItem *iv, CK_ULONG ulEffectiveBits) -{ - SECItem *param = PK11_ParamFromIV(mtype, iv); - if (param && param->data && param->len >= sizeof(CK_RC2_PARAMS)) { - switch (mtype) { - case CKM_RC2_KEY_GEN: - case CKM_RC2_ECB: - case CKM_RC2_CBC: - case CKM_RC2_MAC: - case CKM_RC2_MAC_GENERAL: - case CKM_RC2_CBC_PAD: - *(CK_RC2_PARAMS *)param->data = ulEffectiveBits; - default: - break; - } - } - return param; -} - /* ssl3_BuildRecordPseudoHeader writes the SSL/TLS pseudo-header (the data * which is included in the MAC or AEAD additional data) to |out| and returns * its length. See https://tools.ietf.org/html/rfc5246#section-6.2.3.3 for the @@ -1981,7 +1943,6 @@ ssl3_InitPendingContexts(sslSocket *ss) CK_MECHANISM_TYPE mechanism; CK_MECHANISM_TYPE mac_mech; CK_ULONG macLength; - CK_ULONG effKeyBits; SECItem iv; SECItem mac_param; SSLCipherAlgorithm calg; @@ -2051,14 +2012,13 @@ ssl3_InitPendingContexts(sslSocket *ss) return SECSuccess; } mechanism = ssl3_Alg2Mech(calg); - effKeyBits = cipher_def->key_size * BPB; /* * build the server context */ iv.data = pwSpec->server.write_iv; iv.len = cipher_def->iv_size; - param = ssl3_ParamFromIV(mechanism, &iv, effKeyBits); + param = PK11_ParamFromIV(mechanism, &iv); if (param == NULL) { ssl_MapLowLevelError(SSL_ERROR_IV_PARAM_FAILURE); goto fail; @@ -2082,7 +2042,7 @@ ssl3_InitPendingContexts(sslSocket *ss) iv.data = pwSpec->client.write_iv; iv.len = cipher_def->iv_size; - param = ssl3_ParamFromIV(mechanism, &iv, effKeyBits); + param = PK11_ParamFromIV(mechanism, &iv); if (param == NULL) { ssl_MapLowLevelError(SSL_ERROR_IV_PARAM_FAILURE); goto fail; @@ -2702,6 +2662,7 @@ ssl3_SendRecord(sslSocket *ss, SECStatus rv; PRInt32 totalSent = 0; PRBool capRecordVersion; + ssl3CipherSpec *spec; SSL_TRC(3, ("%d: SSL3[%d] SendRecord type: %s nIn=%d", SSL_GETPID(), ss->fd, ssl3_DecodeContentType(type), @@ -2733,10 +2694,7 @@ ssl3_SendRecord(sslSocket *ss, ** trying to send an alert. */ PR_ASSERT(type == content_alert); - rv = ssl3_InitState(ss); - if (rv != SECSuccess) { - return SECFailure; /* ssl3_InitState has set the error code. */ - } + ssl3_InitState(ss); } /* check for Token Presence */ @@ -2806,11 +2764,12 @@ ssl3_SendRecord(sslSocket *ss, PORT_Assert(IS_DTLS(ss) && (type == content_handshake || type == content_change_cipher_spec)); + spec = cwSpec; } else { - cwSpec = ss->ssl3.cwSpec; + spec = ss->ssl3.cwSpec; } - rv = ssl_ProtectRecord(ss, cwSpec, !IS_DTLS(ss) && capRecordVersion, + rv = ssl_ProtectRecord(ss, spec, !IS_DTLS(ss) && capRecordVersion, type, pIn, contentLen, wrBuf); if (rv == SECSuccess) { PRINT_BUF(50, (ss, "send (encrypted) record data:", @@ -2941,6 +2900,7 @@ ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in, ssl_GetXmitBufLock(ss); } toSend = PR_MIN(len - totalSent, MAX_FRAGMENT_LENGTH); + /* * Note that the 0 epoch is OK because flags will never require * its use, as guaranteed by the PORT_Assert above. @@ -3077,7 +3037,9 @@ ssl3_HandleNoCertificate(sslSocket *ss) (ss->opt.requireCertificate == SSL_REQUIRE_FIRST_HANDSHAKE))) { PRFileDesc *lower; - ss->sec.uncache(ss->sec.ci.sid); + if (!ss->opt.noCache) { + ss->sec.uncache(ss->sec.ci.sid); + } SSL3_SendAlert(ss, alert_fatal, bad_certificate); lower = ss->fd->lower; @@ -3124,6 +3086,10 @@ SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level, SSL3AlertDescription desc) { PRUint8 bytes[2]; SECStatus rv; + PRBool needHsLock = !ssl_HaveSSL3HandshakeLock(ss); + + /* Check that if I need the HS lock I also need the Xmit lock */ + PORT_Assert(!needHsLock || !ssl_HaveXmitBufLock(ss)); SSL_TRC(3, ("%d: SSL3[%d]: send alert record, level=%d desc=%d", SSL_GETPID(), ss->fd, level, desc)); @@ -3131,7 +3097,9 @@ SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level, SSL3AlertDescription desc) bytes[0] = level; bytes[1] = desc; - ssl_GetSSL3HandshakeLock(ss); + if (needHsLock) { + ssl_GetSSL3HandshakeLock(ss); + } if (level == alert_fatal) { if (!ss->opt.noCache && ss->sec.ci.sid) { ss->sec.uncache(ss->sec.ci.sid); @@ -3149,7 +3117,13 @@ SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level, SSL3AlertDescription desc) ss->ssl3.fatalAlertSent = PR_TRUE; } ssl_ReleaseXmitBufLock(ss); - ssl_ReleaseSSL3HandshakeLock(ss); + if (needHsLock) { + ssl_ReleaseSSL3HandshakeLock(ss); + } + if (rv == SECSuccess && ss->alertSentCallback) { + SSLAlert alert = { level, desc }; + ss->alertSentCallback(ss->fd, ss->alertSentCallbackArg, &alert); + } return rv; /* error set by ssl3_FlushHandshake or ssl3_SendRecord */ } @@ -3262,6 +3236,11 @@ ssl3_HandleAlert(sslSocket *ss, sslBuffer *buf) SSL_TRC(5, ("%d: SSL3[%d] received alert, level = %d, description = %d", SSL_GETPID(), ss->fd, level, desc)); + if (ss->alertReceivedCallback) { + SSLAlert alert = { level, desc }; + ss->alertReceivedCallback(ss->fd, ss->alertReceivedCallbackArg, &alert); + } + switch (desc) { case close_notify: ss->recvdCloseNotify = 1; @@ -4088,11 +4067,9 @@ ssl3_InitHandshakeHashes(sslSocket *ss) return SECSuccess; } -SECStatus +void ssl3_RestartHandshakeHashes(sslSocket *ss) { - SECStatus rv = SECSuccess; - SSL_TRC(30, ("%d: SSL3[%d]: reset handshake hashes", SSL_GETPID(), ss->fd)); ss->ssl3.hs.hashType = handshake_hash_unknown; @@ -4105,7 +4082,6 @@ ssl3_RestartHandshakeHashes(sslSocket *ss) PK11_DestroyContext(ss->ssl3.hs.sha, PR_TRUE); ss->ssl3.hs.sha = NULL; } - return rv; } /* @@ -4330,7 +4306,7 @@ ssl3_AppendHandshakeHeader(sslSocket *ss, SSL3HandshakeType t, PRUint32 length) * override the generic error code by setting another. */ SECStatus -ssl3_ConsumeHandshake(sslSocket *ss, void *v, PRInt32 bytes, SSL3Opaque **b, +ssl3_ConsumeHandshake(sslSocket *ss, void *v, PRUint32 bytes, SSL3Opaque **b, PRUint32 *length) { PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); @@ -4348,37 +4324,33 @@ ssl3_ConsumeHandshake(sslSocket *ss, void *v, PRInt32 bytes, SSL3Opaque **b, /* Read up the next "bytes" number of bytes from the (decrypted) input * stream "b" (which is *length bytes long), and interpret them as an - * integer in network byte order. Returns the received value. + * integer in network byte order. Sets *num to the received value. * Reduces *length by bytes. Advances *b by bytes. * - * Returns SECFailure (-1) on failure. - * This value is indistinguishable from the equivalent received value. - * Only positive numbers are to be received this way. - * Thus, the largest value that may be sent this way is 0x7fffffff. * On error, an alert has been sent, and a generic error code has been set. */ -PRInt32 -ssl3_ConsumeHandshakeNumber(sslSocket *ss, PRInt32 bytes, SSL3Opaque **b, - PRUint32 *length) +SECStatus +ssl3_ConsumeHandshakeNumber(sslSocket *ss, PRUint32 *num, PRUint32 bytes, + SSL3Opaque **b, PRUint32 *length) { PRUint8 *buf = *b; int i; - PRInt32 num = 0; PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); - PORT_Assert(bytes <= sizeof num); - if ((PRUint32)bytes > *length) { + *num = 0; + if (bytes > *length || bytes > sizeof(*num)) { return ssl3_DecodeError(ss); } PRINT_BUF(60, (ss, "consume bytes:", *b, bytes)); - for (i = 0; i < bytes; i++) - num = (num << 8) + buf[i]; + for (i = 0; i < bytes; i++) { + *num = (*num << 8) + buf[i]; + } *b += bytes; *length -= bytes; - return num; + return SECSuccess; } /* Read in two values from the incoming decrypted byte stream "b", which is @@ -4396,21 +4368,22 @@ ssl3_ConsumeHandshakeNumber(sslSocket *ss, PRInt32 bytes, SSL3Opaque **b, * point to the values in the buffer **b. */ SECStatus -ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i, PRInt32 bytes, +ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i, PRUint32 bytes, SSL3Opaque **b, PRUint32 *length) { - PRInt32 count; + PRUint32 count; + SECStatus rv; PORT_Assert(bytes <= 3); i->len = 0; i->data = NULL; i->type = siBuffer; - count = ssl3_ConsumeHandshakeNumber(ss, bytes, b, length); - if (count < 0) { /* Can't test for SECSuccess here. */ + rv = ssl3_ConsumeHandshakeNumber(ss, &count, bytes, b, length); + if (rv != SECSuccess) { return SECFailure; } if (count > 0) { - if ((PRUint32)count > *length) { + if (count > *length) { return ssl3_DecodeError(ss); } i->data = *b; @@ -4681,10 +4654,11 @@ SECStatus ssl_ConsumeSignatureScheme(sslSocket *ss, SSL3Opaque **b, PRUint32 *length, SSLSignatureScheme *out) { - PRInt32 tmp; + PRUint32 tmp; + SECStatus rv; - tmp = ssl3_ConsumeHandshakeNumber(ss, 2, b, length); - if (tmp < 0) { + rv = ssl3_ConsumeHandshakeNumber(ss, &tmp, 2, b, length); + if (rv != SECSuccess) { return SECFailure; /* Error code set already. */ } if (!ssl_IsSupportedSignatureScheme((SSLSignatureScheme)tmp)) { @@ -4990,7 +4964,6 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) PRBool isTLS = PR_FALSE; PRBool requestingResume = PR_FALSE, fallbackSCSV = PR_FALSE; PRInt32 total_exten_len = 0; - unsigned paddingExtensionLen; unsigned numCompressionMethods; PRUint16 version; PRInt32 flags; @@ -5013,15 +4986,8 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) if (ss->ssl3.hs.helloRetry) { PORT_Assert(type == client_hello_retry); } else { - rv = ssl3_InitState(ss); - if (rv != SECSuccess) { - return rv; /* ssl3_InitState has set the error code. */ - } - - rv = ssl3_RestartHandshakeHashes(ss); - if (rv != SECSuccess) { - return rv; - } + ssl3_InitState(ss); + ssl3_RestartHandshakeHashes(ss); } /* These must be reset every handshake. */ @@ -5293,19 +5259,12 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) length += 1 + ss->ssl3.hs.cookie.len; } - /* A padding extension may be included to ensure that the record containing - * the ClientHello doesn't have a length between 256 and 511 bytes - * (inclusive). Initial, ClientHello records with such lengths trigger bugs - * in F5 devices. - * - * This is not done for DTLS, for renegotiation, or when there are no - * extensions. */ - if (!IS_DTLS(ss) && isTLS && !ss->firstHsDone && total_exten_len) { - paddingExtensionLen = ssl3_CalculatePaddingExtensionLength(length); - total_exten_len += paddingExtensionLen; - length += paddingExtensionLen; - } else { - paddingExtensionLen = 0; + if (total_exten_len > 0) { + ssl3_CalculatePaddingExtLen(ss, length); + if (ss->xtnData.paddingLen) { + total_exten_len += 4 + ss->xtnData.paddingLen; + length += 4 + ss->xtnData.paddingLen; + } } rv = ssl3_AppendHandshakeHeader(ss, client_hello, length); @@ -5476,15 +5435,6 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) return rv; /* err set by AppendHandshake. */ } - extLen = ssl3_AppendPaddingExtension(ss, paddingExtensionLen, maxBytes); - if (extLen < 0) { - if (sid->u.ssl3.lock) { - PR_RWLock_Unlock(sid->u.ssl3.lock); - } - return SECFailure; - } - maxBytes -= extLen; - extLen = ssl3_CallHelloExtensionSenders(ss, PR_TRUE, maxBytes, NULL); if (extLen < 0) { if (sid->u.ssl3.lock) { @@ -5579,8 +5529,6 @@ ssl3_HandleHelloRequest(sslSocket *ss) return rv; } -#define UNKNOWN_WRAP_MECHANISM 0x7fffffff - static const CK_MECHANISM_TYPE wrapMechanismList[SSL_NUM_WRAP_MECHS] = { CKM_DES3_ECB, CKM_CAST5_ECB, @@ -5596,27 +5544,58 @@ static const CK_MECHANISM_TYPE wrapMechanismList[SSL_NUM_WRAP_MECHS] = { CKM_SKIPJACK_CBC64, CKM_AES_ECB, CKM_CAMELLIA_ECB, - CKM_SEED_ECB, - UNKNOWN_WRAP_MECHANISM + CKM_SEED_ECB }; -static int -ssl_FindIndexByWrapMechanism(CK_MECHANISM_TYPE mech) +static SECStatus +ssl_FindIndexByWrapMechanism(CK_MECHANISM_TYPE mech, unsigned int *wrapMechIndex) { - const CK_MECHANISM_TYPE *pMech = wrapMechanismList; + unsigned int i; + for (i = 0; i < SSL_NUM_WRAP_MECHS; ++i) { + if (wrapMechanismList[i] == mech) { + *wrapMechIndex = i; + return SECSuccess; + } + } + PORT_Assert(0); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; +} + +/* Each process sharing the server session ID cache has its own array of SymKey + * pointers for the symmetric wrapping keys that are used to wrap the master + * secrets. There is one key for each authentication type. These Symkeys + * correspond to the wrapped SymKeys kept in the server session cache. + */ +const SSLAuthType ssl_wrap_key_auth_type[SSL_NUM_WRAP_KEYS] = { + ssl_auth_rsa_decrypt, + ssl_auth_rsa_sign, + ssl_auth_rsa_pss, + ssl_auth_ecdsa, + ssl_auth_ecdh_rsa, + ssl_auth_ecdh_ecdsa +}; - while (mech != *pMech && *pMech != UNKNOWN_WRAP_MECHANISM) { - ++pMech; +static SECStatus +ssl_FindIndexByWrapKey(const sslServerCert *serverCert, unsigned int *wrapKeyIndex) +{ + unsigned int i; + for (i = 0; i < SSL_NUM_WRAP_KEYS; ++i) { + if (SSL_CERT_IS(serverCert, ssl_wrap_key_auth_type[i])) { + *wrapKeyIndex = i; + return SECSuccess; + } } - return (*pMech == UNKNOWN_WRAP_MECHANISM) ? -1 - : (pMech - wrapMechanismList); + /* Can't assert here because we still get people using DSA certificates. */ + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; } static PK11SymKey * ssl_UnwrapSymWrappingKey( SSLWrappedSymWrappingKey *pWswk, SECKEYPrivateKey *svrPrivKey, - SSLAuthType authType, + unsigned int wrapKeyIndex, CK_MECHANISM_TYPE masterWrapMech, void *pwArg) { @@ -5628,9 +5607,9 @@ ssl_UnwrapSymWrappingKey( /* found the wrapping key on disk. */ PORT_Assert(pWswk->symWrapMechanism == masterWrapMech); - PORT_Assert(pWswk->authType == authType); + PORT_Assert(pWswk->wrapKeyIndex == wrapKeyIndex); if (pWswk->symWrapMechanism != masterWrapMech || - pWswk->authType != authType) { + pWswk->wrapKeyIndex != wrapKeyIndex) { goto loser; } wrappedKey.type = siBuffer; @@ -5638,7 +5617,7 @@ ssl_UnwrapSymWrappingKey( wrappedKey.len = pWswk->wrappedSymKeyLen; PORT_Assert(wrappedKey.len <= sizeof pWswk->wrappedSymmetricWrappingkey); - switch (authType) { + switch (ssl_wrap_key_auth_type[wrapKeyIndex]) { case ssl_auth_rsa_decrypt: case ssl_auth_rsa_sign: /* bad: see Bug 1248320 */ @@ -5711,14 +5690,8 @@ loser: return unwrappedWrappingKey; } -/* Each process sharing the server session ID cache has its own array of SymKey - * pointers for the symmetric wrapping keys that are used to wrap the master - * secrets. There is one key for each authentication type. These Symkeys - * correspond to the wrapped SymKeys kept in the server session cache. - */ - typedef struct { - PK11SymKey *symWrapKey[ssl_auth_size]; + PK11SymKey *symWrapKey[SSL_NUM_WRAP_KEYS]; } ssl3SymWrapKey; static PZLock *symWrapKeysLock = NULL; @@ -5746,7 +5719,7 @@ SSL3_ShutdownServerCache(void) PZ_Lock(symWrapKeysLock); /* get rid of all symWrapKeys */ for (i = 0; i < SSL_NUM_WRAP_MECHS; ++i) { - for (j = 0; j < ssl_auth_size; ++j) { + for (j = 0; j < SSL_NUM_WRAP_KEYS; ++j) { PK11SymKey **pSymWrapKey; pSymWrapKey = &symWrapKeys[i].symWrapKey[j]; if (*pSymWrapKey) { @@ -5780,7 +5753,6 @@ ssl_InitSymWrapKeysLock(void) PK11SymKey * ssl3_GetWrappingKey(sslSocket *ss, PK11SlotInfo *masterSecretSlot, - const sslServerCert *serverCert, CK_MECHANISM_TYPE masterWrapMech, void *pwArg) { @@ -5791,7 +5763,8 @@ ssl3_GetWrappingKey(sslSocket *ss, PK11SymKey **pSymWrapKey; CK_MECHANISM_TYPE asymWrapMechanism = CKM_INVALID_MECHANISM; int length; - int symWrapMechIndex; + unsigned int wrapMechIndex; + unsigned int wrapKeyIndex; SECStatus rv; SECItem wrappedKey; SSLWrappedSymWrappingKey wswk; @@ -5799,6 +5772,7 @@ ssl3_GetWrappingKey(sslSocket *ss, SECKEYPublicKey *pubWrapKey = NULL; SECKEYPrivateKey *privWrapKey = NULL; ECCWrappedKeyInfo *ecWrapped; + const sslServerCert *serverCert = ss->sec.serverCert; PORT_Assert(serverCert); PORT_Assert(serverCert->serverKeyPair); @@ -5810,15 +5784,18 @@ ssl3_GetWrappingKey(sslSocket *ss, PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return NULL; /* hmm */ } - authType = serverCert->certType.authType; - svrPrivKey = serverCert->serverKeyPair->privKey; - symWrapMechIndex = ssl_FindIndexByWrapMechanism(masterWrapMech); - PORT_Assert(symWrapMechIndex >= 0); - if (symWrapMechIndex < 0) + rv = ssl_FindIndexByWrapKey(serverCert, &wrapKeyIndex); + if (rv != SECSuccess) + return NULL; /* unusable wrapping key. */ + + rv = ssl_FindIndexByWrapMechanism(masterWrapMech, &wrapMechIndex); + if (rv != SECSuccess) return NULL; /* invalid masterWrapMech. */ - pSymWrapKey = &symWrapKeys[symWrapMechIndex].symWrapKey[authType]; + authType = ssl_wrap_key_auth_type[wrapKeyIndex]; + svrPrivKey = serverCert->serverKeyPair->privKey; + pSymWrapKey = &symWrapKeys[wrapMechIndex].symWrapKey[wrapKeyIndex]; ssl_InitSessionCacheLocks(PR_TRUE); @@ -5837,10 +5814,11 @@ ssl3_GetWrappingKey(sslSocket *ss, /* Try to get wrapped SymWrapping key out of the (disk) cache. */ /* Following call fills in wswk on success. */ - if (ssl_GetWrappingKey(symWrapMechIndex, authType, &wswk)) { + rv = ssl_GetWrappingKey(wrapMechIndex, wrapKeyIndex, &wswk); + if (rv == SECSuccess) { /* found the wrapped sym wrapping key on disk. */ unwrappedWrappingKey = - ssl_UnwrapSymWrappingKey(&wswk, svrPrivKey, authType, + ssl_UnwrapSymWrappingKey(&wswk, svrPrivKey, wrapKeyIndex, masterWrapMech, pwArg); if (unwrappedWrappingKey) { goto install; @@ -5989,9 +5967,9 @@ ssl3_GetWrappingKey(sslSocket *ss, PORT_Assert(asymWrapMechanism != CKM_INVALID_MECHANISM); wswk.symWrapMechanism = masterWrapMech; - wswk.symWrapMechIndex = symWrapMechIndex; wswk.asymWrapMechanism = asymWrapMechanism; - wswk.authType = authType; + wswk.wrapMechIndex = wrapMechIndex; + wswk.wrapKeyIndex = wrapKeyIndex; wswk.wrappedSymKeyLen = wrappedKey.len; /* put it on disk. */ @@ -5999,7 +5977,8 @@ ssl3_GetWrappingKey(sslSocket *ss, * then abandon the value we just computed and * use the one we got from the disk. */ - if (ssl_SetWrappingKey(&wswk)) { + rv = ssl_SetWrappingKey(&wswk); + if (rv == SECSuccess) { /* somebody beat us to it. The original contents of our wswk * has been replaced with the content on disk. Now, discard * the key we just created and unwrap this new one. @@ -6007,7 +5986,7 @@ ssl3_GetWrappingKey(sslSocket *ss, PK11_FreeSymKey(unwrappedWrappingKey); unwrappedWrappingKey = - ssl_UnwrapSymWrappingKey(&wswk, svrPrivKey, authType, + ssl_UnwrapSymWrappingKey(&wswk, svrPrivKey, wrapKeyIndex, masterWrapMech, pwArg); } @@ -6377,7 +6356,7 @@ ssl_PickSignatureScheme(sslSocket *ss, PRUint32 policy; if (!ssl_SignatureSchemeValidForKey(!isTLS13 /* allowSha1 */, - PR_TRUE /* matchGroup */, + isTLS13 /* matchGroup */, keyType, group, preferred)) { continue; } @@ -6411,6 +6390,33 @@ ssl_PickSignatureScheme(sslSocket *ss, return SECFailure; } +static SECStatus +ssl_PickFallbackSignatureScheme(sslSocket *ss, SECKEYPublicKey *pubKey) +{ + PRBool isTLS12 = ss->version >= SSL_LIBRARY_VERSION_TLS_1_2; + + switch (SECKEY_GetPublicKeyType(pubKey)) { + case rsaKey: + if (isTLS12) { + ss->ssl3.hs.signatureScheme = ssl_sig_rsa_pkcs1_sha1; + } else { + ss->ssl3.hs.signatureScheme = ssl_sig_rsa_pkcs1_sha1md5; + } + break; + case ecKey: + ss->ssl3.hs.signatureScheme = ssl_sig_ecdsa_sha1; + break; + case dsaKey: + ss->ssl3.hs.signatureScheme = ssl_sig_dsa_sha1; + break; + default: + PORT_Assert(0); + PORT_SetError(SEC_ERROR_INVALID_KEY); + return SECFailure; + } + return SECSuccess; +} + /* ssl3_PickServerSignatureScheme selects a signature scheme for signing the * handshake. Most of this is determined by the key pair we are using. * Prior to TLS 1.2, the MD5/SHA1 combination is always used. With TLS 1.2, a @@ -6424,26 +6430,7 @@ ssl3_PickServerSignatureScheme(sslSocket *ss) if (!isTLS12 || !ssl3_ExtensionNegotiated(ss, ssl_signature_algorithms_xtn)) { /* If the client didn't provide any signature_algorithms extension then * we can assume that they support SHA-1: RFC5246, Section 7.4.1.4.1. */ - switch (SECKEY_GetPublicKeyType(keyPair->pubKey)) { - case rsaKey: - if (isTLS12) { - ss->ssl3.hs.signatureScheme = ssl_sig_rsa_pkcs1_sha1; - } else { - ss->ssl3.hs.signatureScheme = ssl_sig_rsa_pkcs1_sha1md5; - } - break; - case ecKey: - ss->ssl3.hs.signatureScheme = ssl_sig_ecdsa_sha1; - break; - case dsaKey: - ss->ssl3.hs.signatureScheme = ssl_sig_dsa_sha1; - break; - default: - PORT_Assert(0); - PORT_SetError(SEC_ERROR_INVALID_KEY); - return SECFailure; - } - return SECSuccess; + return ssl_PickFallbackSignatureScheme(ss, keyPair->pubKey); } /* Sets error code, if needed. */ @@ -6461,9 +6448,21 @@ ssl_PickClientSignatureScheme(sslSocket *ss, const SSLSignatureScheme *schemes, SECKEYPublicKey *pubKey; SECStatus rv; + PRBool isTLS13 = (PRBool)ss->version >= SSL_LIBRARY_VERSION_TLS_1_3; pubKey = CERT_ExtractPublicKey(ss->ssl3.clientCertificate); PORT_Assert(pubKey); - if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3 && + + if (!isTLS13 && numSchemes == 0) { + /* If the server didn't provide any signature algorithms + * then let's assume they support SHA-1. */ + rv = ssl_PickFallbackSignatureScheme(ss, pubKey); + SECKEY_DestroyPublicKey(pubKey); + return rv; + } + + PORT_Assert(schemes && numSchemes > 0); + + if (!isTLS13 && (SECKEY_GetPublicKeyType(pubKey) == rsaKey || SECKEY_GetPublicKeyType(pubKey) == dsaKey) && SECKEY_PublicKeyStrengthInBits(pubKey) <= 1024) { @@ -6606,7 +6605,7 @@ ssl3_SetCipherSuite(sslSocket *ss, ssl3CipherSuite chosenSuite, static SECStatus ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) { - PRInt32 temp; /* allow for consume number failure */ + PRUint32 temp; PRBool suite_found = PR_FALSE; int i; int errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO; @@ -6649,11 +6648,21 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) goto loser; /* alert has been sent */ } - /* We got a HelloRetryRequest, but the server didn't pick 1.3. Scream. */ - if (ss->ssl3.hs.helloRetry && ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { - desc = illegal_parameter; - errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO; - goto alert_loser; + /* The server didn't pick 1.3 although we either received a + * HelloRetryRequest, or we prepared to send early app data. */ + if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { + if (ss->ssl3.hs.helloRetry) { + /* SSL3_SendAlert() will uncache the SID. */ + desc = illegal_parameter; + errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO; + goto alert_loser; + } + if (ss->ssl3.hs.zeroRttState == ssl_0rtt_sent) { + /* SSL3_SendAlert() will uncache the SID. */ + desc = illegal_parameter; + errCode = SSL_ERROR_DOWNGRADE_WITH_EARLY_DATA; + goto alert_loser; + } } /* Check that the server negotiated the same version as it did @@ -6721,8 +6730,8 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) } /* find selected cipher suite in our list. */ - temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length); - if (temp < 0) { + rv = ssl3_ConsumeHandshakeNumber(ss, &temp, 2, &b, &length); + if (rv != SECSuccess) { goto loser; /* alert has been sent */ } i = ssl3_config_match_init(ss); @@ -6767,8 +6776,8 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { /* find selected compression method in our list. */ - temp = ssl3_ConsumeHandshakeNumber(ss, 1, &b, &length); - if (temp < 0) { + rv = ssl3_ConsumeHandshakeNumber(ss, &temp, 1, &b, &length); + if (rv != SECSuccess) { goto loser; /* alert has been sent */ } suite_found = PR_FALSE; @@ -7010,6 +7019,19 @@ ssl3_HandleServerHelloPart2(sslSocket *ss, const SECItem *sidBytes, else SSL_AtomicIncrementLong(&ssl3stats.hsh_sid_cache_misses); + /* We tried to resume a 1.3 session but the server negotiated 1.2. */ + if (ss->statelessResume) { + PORT_Assert(sid->version == SSL_LIBRARY_VERSION_TLS_1_3); + PORT_Assert(ss->ssl3.hs.currentSecret); + + /* Reset resumption state, only used by 1.3 code. */ + ss->statelessResume = PR_FALSE; + + /* Clear TLS 1.3 early data traffic key. */ + PK11_FreeSymKey(ss->ssl3.hs.currentSecret); + ss->ssl3.hs.currentSecret = NULL; + } + /* throw the old one away */ sid->u.ssl3.keys.resumable = PR_FALSE; ss->sec.uncache(sid); @@ -7276,16 +7298,17 @@ SECStatus ssl3_ParseCertificateRequestCAs(sslSocket *ss, SSL3Opaque **b, PRUint32 *length, PLArenaPool *arena, CERTDistNames *ca_list) { - PRInt32 remaining; + PRUint32 remaining; int nnames = 0; dnameNode *node; + SECStatus rv; int i; - remaining = ssl3_ConsumeHandshakeNumber(ss, 2, b, length); - if (remaining < 0) + rv = ssl3_ConsumeHandshakeNumber(ss, &remaining, 2, b, length); + if (rv != SECSuccess) return SECFailure; /* malformed, alert has been sent */ - if ((PRUint32)remaining > *length) + if (remaining > *length) goto alert_loser; ca_list->head = node = PORT_ArenaZNew(arena, dnameNode); @@ -7293,19 +7316,19 @@ ssl3_ParseCertificateRequestCAs(sslSocket *ss, SSL3Opaque **b, PRUint32 *length, goto no_mem; while (remaining > 0) { - PRInt32 len; + PRUint32 len; if (remaining < 2) goto alert_loser; /* malformed */ - node->name.len = len = ssl3_ConsumeHandshakeNumber(ss, 2, b, length); - if (len <= 0) + rv = ssl3_ConsumeHandshakeNumber(ss, &len, 2, b, length); + if (rv != SECSuccess) return SECFailure; /* malformed, alert has been sent */ - - remaining -= 2; - if (remaining < len) + if (len == 0 || remaining < len + 2) goto alert_loser; /* malformed */ + remaining -= 2; + node->name.len = len; node->name.data = *b; *b += len; *length -= len; @@ -7353,7 +7376,7 @@ ssl_ParseSignatureSchemes(const sslSocket *ss, PLArenaPool *arena, { SECStatus rv; SECItem buf; - SSLSignatureScheme *schemes; + SSLSignatureScheme *schemes = NULL; unsigned int numSchemes = 0; unsigned int max; @@ -7361,12 +7384,17 @@ ssl_ParseSignatureSchemes(const sslSocket *ss, PLArenaPool *arena, if (rv != SECSuccess) { return SECFailure; } - /* An empty or odd-length value is invalid. */ - if (buf.len == 0 || (buf.len & 1) != 0) { + /* An odd-length value is invalid. */ + if ((buf.len & 1) != 0) { ssl3_ExtSendAlert(ss, alert_fatal, decode_error); return SECFailure; } + /* Let the caller decide whether to alert here. */ + if (buf.len == 0) { + goto done; + } + /* Limit the number of schemes we read. */ max = PR_MIN(buf.len / 2, MAX_SIGNATURE_SCHEMES); @@ -7381,9 +7409,9 @@ ssl_ParseSignatureSchemes(const sslSocket *ss, PLArenaPool *arena, } for (; max; --max) { - PRInt32 tmp; - tmp = ssl3_ExtConsumeHandshakeNumber(ss, 2, &buf.data, &buf.len); - if (tmp < 0) { + PRUint32 tmp; + rv = ssl3_ExtConsumeHandshakeNumber(ss, &tmp, 2, &buf.data, &buf.len); + if (rv != SECSuccess) { PORT_Assert(0); PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -7400,6 +7428,7 @@ ssl_ParseSignatureSchemes(const sslSocket *ss, PLArenaPool *arena, schemes = NULL; } +done: *schemesOut = schemes; *numSchemesOut = numSchemes; return SECSuccess; @@ -8203,6 +8232,20 @@ ssl3_SelectServerCert(sslSocket *ss) const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def; PRCList *cursor; + /* If the client didn't include the supported groups extension, assume just + * P-256 support and disable all the other ECDHE groups. This also affects + * ECDHE group selection, but this function is called first. */ + if (!ssl3_ExtensionNegotiated(ss, ssl_supported_groups_xtn)) { + unsigned int i; + for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) { + if (ss->namedGroupPreferences[i] && + ss->namedGroupPreferences[i]->keaType == ssl_kea_ecdh && + ss->namedGroupPreferences[i]->name != ssl_grp_ec_secp256r1) { + ss->namedGroupPreferences[i] = NULL; + } + } + } + /* This picks the first certificate that has: * a) the right authentication method, and * b) the right named curve (EC only) @@ -8213,19 +8256,17 @@ ssl3_SelectServerCert(sslSocket *ss) cursor != &ss->serverCerts; cursor = PR_NEXT_LINK(cursor)) { sslServerCert *cert = (sslServerCert *)cursor; - if (cert->certType.authType != kea_def->authKeyType) { + if (!SSL_CERT_IS(cert, kea_def->authKeyType)) { continue; } - if ((cert->certType.authType == ssl_auth_ecdsa || - cert->certType.authType == ssl_auth_ecdh_rsa || - cert->certType.authType == ssl_auth_ecdh_ecdsa) && - !ssl_NamedGroupEnabled(ss, cert->certType.namedCurve)) { + if (SSL_CERT_IS_EC(cert) && + !ssl_NamedGroupEnabled(ss, cert->namedCurve)) { continue; } /* Found one. */ ss->sec.serverCert = cert; - ss->sec.authType = cert->certType.authType; + ss->sec.authType = kea_def->authKeyType; ss->sec.authKeyBits = cert->serverKeyBits; /* Don't pick a signature scheme if we aren't going to use it. */ @@ -8247,7 +8288,7 @@ static SECStatus ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) { sslSessionID *sid = NULL; - PRInt32 tmp; + PRUint32 tmp; unsigned int i; SECStatus rv; int errCode = SSL_ERROR_RX_MALFORMED_CLIENT_HELLO; @@ -8307,8 +8348,8 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) dtls_RehandshakeCleanup(ss); } - tmp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length); - if (tmp < 0) + rv = ssl3_ConsumeHandshakeNumber(ss, &tmp, 2, &b, &length); + if (rv != SECSuccess) goto loser; /* malformed, alert already sent */ /* Translate the version. */ @@ -8361,9 +8402,9 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) if (length) { /* Get length of hello extensions */ - PRInt32 extension_length; - extension_length = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length); - if (extension_length < 0) { + PRUint32 extension_length; + rv = ssl3_ConsumeHandshakeNumber(ss, &extension_length, 2, &b, &length); + if (rv != SECSuccess) { goto loser; /* alert already sent */ } if (extension_length != length) { @@ -8465,7 +8506,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) /* If the ClientHello version is less than our maximum version, check for a * TLS_FALLBACK_SCSV and reject the connection if found. */ - if (ss->vrange.max > ss->clientHelloVersion) { + if (ss->vrange.max > ss->version) { for (i = 0; i + 1 < suites.len; i += 2) { PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1]; if (suite_i != TLS_FALLBACK_SCSV) @@ -8749,7 +8790,6 @@ compression_found: do { ssl3CipherSpec *pwSpec; SECItem wrappedMS; /* wrapped key */ - const sslServerCert *serverCert; if (sid->version != ss->version || sid->u.ssl3.cipherSuite != ss->ssl3.hs.cipher_suite || @@ -8757,8 +8797,13 @@ compression_found: break; /* not an error */ } - serverCert = ssl_FindServerCert(ss, &sid->certType); - if (!serverCert || !serverCert->serverCert) { + /* server sids don't remember the server cert we previously sent, + ** but they do remember the slot we originally used, so we + ** can locate it again, provided that the current ssl socket + ** has had its server certs configured the same as the previous one. + */ + ss->sec.serverCert = ssl_FindServerCert(ss, sid->authType, sid->namedCurve); + if (!ss->sec.serverCert || !ss->sec.serverCert->serverCert) { /* A compatible certificate must not have been configured. It * might not be the same certificate, but we only find that out * when the ticket fails to decrypt. */ @@ -8806,7 +8851,7 @@ compression_found: PK11SymKey *wrapKey; /* wrapping key */ CK_FLAGS keyFlags = 0; - wrapKey = ssl3_GetWrappingKey(ss, NULL, serverCert, + wrapKey = ssl3_GetWrappingKey(ss, NULL, sid->u.ssl3.masterWrapMech, ss->pkcs11PinArg); if (!wrapKey) { @@ -8865,13 +8910,8 @@ compression_found: ss->sec.keaType = sid->keaType; ss->sec.keaKeyBits = sid->keaKeyBits; - /* server sids don't remember the server cert we previously sent, - ** but they do remember the slot we originally used, so we - ** can locate it again, provided that the current ssl socket - ** has had its server certs configured the same as the previous one. - */ - ss->sec.serverCert = serverCert; - ss->sec.localCert = CERT_DupCertificate(serverCert->serverCert); + ss->sec.localCert = + CERT_DupCertificate(ss->sec.serverCert->serverCert); /* Copy cached name in to pending spec */ if (sid != NULL && @@ -9063,16 +9103,8 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length, goto loser; } - rv = ssl3_InitState(ss); - if (rv != SECSuccess) { - ssl_ReleaseSSL3HandshakeLock(ss); - return rv; /* ssl3_InitState has set the error code. */ - } - rv = ssl3_RestartHandshakeHashes(ss); - if (rv != SECSuccess) { - ssl_ReleaseSSL3HandshakeLock(ss); - return rv; - } + ssl3_InitState(ss); + ssl3_RestartHandshakeHashes(ss); if (ss->ssl3.hs.ws != wait_client_hello) { desc = unexpected_message; @@ -9589,34 +9621,6 @@ ssl3_EncodeSigAlgs(const sslSocket *ss, PRUint8 *buf, unsigned maxLen, PRUint32 return SECSuccess; } -void -ssl3_GetCertificateRequestCAs(sslSocket *ss, int *calen, SECItem **names, - int *nnames) -{ - SECItem *name; - CERTDistNames *ca_list; - int i; - - *calen = 0; - *names = NULL; - *nnames = 0; - - /* ssl3.ca_list is initialized to NULL, and never changed. */ - ca_list = ss->ssl3.ca_list; - if (!ca_list) { - ca_list = ssl3_server_ca_list; - } - - if (ca_list != NULL) { - *names = ca_list->names; - *nnames = ca_list->nnames; - } - - for (i = 0, name = *names; i < *nnames; i++, name++) { - *calen += 2 + name->len; - } -} - static SECStatus ssl3_SendCertificateRequest(sslSocket *ss) { @@ -9625,8 +9629,8 @@ ssl3_SendCertificateRequest(sslSocket *ss) SECStatus rv; int length; SECItem *names; - int calen; - int nnames; + unsigned int calen; + unsigned int nnames; SECItem *name; int i; int certTypesLength; @@ -9641,7 +9645,10 @@ ssl3_SendCertificateRequest(sslSocket *ss) isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2); - ssl3_GetCertificateRequestCAs(ss, &calen, &names, &nnames); + rv = ssl_GetCertificateRequestCAs(ss, &calen, &names, &nnames); + if (rv != SECSuccess) { + return rv; + } certTypes = certificate_types; certTypesLength = sizeof certificate_types; @@ -9727,17 +9734,15 @@ ssl3_HandleCertificateVerify(sslSocket *ss, SSL3Opaque *b, PRUint32 length, PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); - /* TLS 1.3 is handled by tls13_HandleCertificateVerify */ - PORT_Assert(ss->ssl3.prSpec->version <= SSL_LIBRARY_VERSION_TLS_1_2); - - isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0); - if (ss->ssl3.hs.ws != wait_cert_verify) { desc = unexpected_message; errCode = SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY; goto alert_loser; } + /* TLS 1.3 is handled by tls13_HandleCertificateVerify */ + PORT_Assert(ss->ssl3.prSpec->version <= SSL_LIBRARY_VERSION_TLS_1_2); + if (!hashes) { PORT_Assert(0); desc = internal_error; @@ -9785,6 +9790,8 @@ ssl3_HandleCertificateVerify(sslSocket *ss, SSL3Opaque *b, PRUint32 length, goto loser; /* malformed. */ } + isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0); + /* XXX verify that the key & kea match */ rv = ssl3_VerifySignedHashes(ss, sigScheme, hashesForVerify, &signed_hash); if (rv != SECSuccess) { @@ -9915,9 +9922,9 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss, enc_pms.len = length; if (ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */ - PRInt32 kLen; - kLen = ssl3_ConsumeHandshakeNumber(ss, 2, &enc_pms.data, &enc_pms.len); - if (kLen < 0) { + PRUint32 kLen; + rv = ssl3_ConsumeHandshakeNumber(ss, &kLen, 2, &enc_pms.data, &enc_pms.len); + if (rv != SECSuccess) { PORT_SetError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); return SECFailure; } @@ -10214,7 +10221,7 @@ ssl3_SendNewSessionTicket(sslSocket *ss) goto loser; /* This is a fixed value. */ - rv = ssl3_AppendHandshakeNumber(ss, TLS_EX_SESS_TICKET_LIFETIME_HINT, 4); + rv = ssl3_AppendHandshakeNumber(ss, ssl_ticket_lifetime, 4); if (rv != SECSuccess) goto loser; @@ -10237,6 +10244,7 @@ ssl3_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length) { SECStatus rv; SECItem ticketData; + PRUint32 temp; SSL_TRC(3, ("%d: SSL3[%d]: handle session_ticket handshake", SSL_GETPID(), ss->fd)); @@ -10257,14 +10265,19 @@ ssl3_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length) * until it has verified the server's Finished message." See the comment in * ssl3_FinishHandshake for more details. */ - ss->ssl3.hs.newSessionTicket.received_timestamp = ssl_Time(); + ss->ssl3.hs.newSessionTicket.received_timestamp = PR_Now(); if (length < 4) { (void)SSL3_SendAlert(ss, alert_fatal, decode_error); PORT_SetError(SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET); return SECFailure; } - ss->ssl3.hs.newSessionTicket.ticket_lifetime_hint = - (PRUint32)ssl3_ConsumeHandshakeNumber(ss, 4, &b, &length); + + rv = ssl3_ConsumeHandshakeNumber(ss, &temp, 4, &b, &length); + if (rv != SECSuccess) { + PORT_SetError(SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET); + return SECFailure; + } + ss->ssl3.hs.newSessionTicket.ticket_lifetime_hint = temp; rv = ssl3_ConsumeHandshakeVariable(ss, &ticketData, 2, &b, &length); if (rv != SECSuccess || length != 0) { @@ -10559,21 +10572,20 @@ ssl3_HandleCertificateStatus(sslSocket *ss, SSL3Opaque *b, PRUint32 length) SECStatus ssl_ReadCertificateStatus(sslSocket *ss, SSL3Opaque *b, PRUint32 length) { - PRInt32 status, len; + PRUint32 status, len; + SECStatus rv; PORT_Assert(!ss->sec.isServer); /* Consume the CertificateStatusType enum */ - status = ssl3_ConsumeHandshakeNumber(ss, 1, &b, &length); - if (status != 1 /* ocsp */) { - ssl3_DecodeError(ss); /* sets error code */ - return SECFailure; + rv = ssl3_ConsumeHandshakeNumber(ss, &status, 1, &b, &length); + if (rv != SECSuccess || status != 1 /* ocsp */) { + return ssl3_DecodeError(ss); } - len = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length); - if (len != length) { - ssl3_DecodeError(ss); /* sets error code */ - return SECFailure; + rv = ssl3_ConsumeHandshakeNumber(ss, &len, 3, &b, &length); + if (rv != SECSuccess || len != length) { + return ssl3_DecodeError(ss); } #define MAX_CERTSTATUS_LEN 0x1ffff /* 128k - 1 */ @@ -10630,8 +10642,8 @@ ssl3_CompleteHandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) { ssl3CertNode *c; ssl3CertNode *lastCert = NULL; - PRInt32 remaining = 0; - PRInt32 size; + PRUint32 remaining = 0; + PRUint32 size; SECStatus rv; PRBool isServer = ss->sec.isServer; PRBool isTLS; @@ -10647,10 +10659,10 @@ ssl3_CompleteHandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) ** normal no_certificates message to maximize interoperability. */ if (length) { - remaining = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length); - if (remaining < 0) + rv = ssl3_ConsumeHandshakeNumber(ss, &remaining, 3, &b, &length); + if (rv != SECSuccess) goto loser; /* fatal alert already sent by ConsumeHandshake. */ - if ((PRUint32)remaining > length) + if (remaining > length) goto decode_loser; } @@ -10681,15 +10693,14 @@ ssl3_CompleteHandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) } /* First get the peer cert. */ - remaining -= 3; - if (remaining < 0) + if (remaining < 3) goto decode_loser; - size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length); - if (size <= 0) + remaining -= 3; + rv = ssl3_ConsumeHandshakeNumber(ss, &size, 3, &b, &length); + if (rv != SECSuccess) goto loser; /* fatal alert already sent by ConsumeHandshake. */ - - if (remaining < size) + if (size == 0 || remaining < size) goto decode_loser; certItem.data = b; @@ -10709,15 +10720,14 @@ ssl3_CompleteHandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) /* Now get all of the CA certs. */ while (remaining > 0) { - remaining -= 3; - if (remaining < 0) + if (remaining < 3) goto decode_loser; - size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length); - if (size <= 0) + remaining -= 3; + rv = ssl3_ConsumeHandshakeNumber(ss, &size, 3, &b, &length); + if (rv != SECSuccess) goto loser; /* fatal alert already sent by ConsumeHandshake. */ - - if (remaining < size) + if (size == 0 || remaining < size) goto decode_loser; certItem.data = b; @@ -10746,9 +10756,6 @@ ssl3_CompleteHandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) lastCert = c; } - if (remaining != 0) - goto decode_loser; - SECKEY_UpdateCertPQG(ss->sec.peerCert); if (!isServer && @@ -11036,13 +11043,10 @@ ssl3_ComputeTLSFinished(sslSocket *ss, ssl3CipherSpec *spec, PK11Context *prf_context; unsigned int retLen; + PORT_Assert(spec->master_secret); if (!spec->master_secret) { - const char *label = isServer ? "server finished" : "client finished"; - unsigned int len = 15; - HASH_HashType hashType = ssl3_GetTls12HashType(ss); - return ssl3_TLSPRFWithMasterSecret(spec, label, len, hashes->u.raw, - hashes->len, tlsFinished->verify_data, - sizeof tlsFinished->verify_data, hashType); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; } if (spec->version < SSL_LIBRARY_VERSION_TLS_1_2) { @@ -11075,9 +11079,10 @@ ssl3_ComputeTLSFinished(sslSocket *ss, ssl3CipherSpec *spec, * ss->ssl3.crSpec). */ SECStatus -ssl3_TLSPRFWithMasterSecret(ssl3CipherSpec *spec, const char *label, - unsigned int labelLen, const unsigned char *val, unsigned int valLen, - unsigned char *out, unsigned int outLen, HASH_HashType tls12HashType) +ssl3_TLSPRFWithMasterSecret(sslSocket *ss, ssl3CipherSpec *spec, + const char *label, unsigned int labelLen, + const unsigned char *val, unsigned int valLen, + unsigned char *out, unsigned int outLen) { SECStatus rv = SECSuccess; @@ -11088,6 +11093,12 @@ ssl3_TLSPRFWithMasterSecret(ssl3CipherSpec *spec, const char *label, unsigned int retLen; if (spec->version >= SSL_LIBRARY_VERSION_TLS_1_2) { + /* Bug 1312976 non-SHA256 exporters are broken. */ + if (ssl3_GetPrfHashMechanism(ss) != CKM_SHA256) { + PORT_Assert(0); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } mech = CKM_NSS_TLS_PRF_GENERAL_SHA256; } prf_context = PK11_CreateContextBySymKey(mech, CKA_SIGN, @@ -11130,9 +11141,7 @@ ssl3_SendNextProto(sslSocket *ss) padding_len = 32 - ((ss->xtnData.nextProto.len + 2) % 32); - rv = ssl3_AppendHandshakeHeader(ss, next_proto, ss->xtnData.nextProto.len + - 2 + - padding_len); + rv = ssl3_AppendHandshakeHeader(ss, next_proto, ss->xtnData.nextProto.len + 2 + padding_len); if (rv != SECSuccess) { return rv; /* error code set by AppendHandshakeHeader */ } @@ -11285,7 +11294,7 @@ fail: */ SECStatus ssl3_CacheWrappedMasterSecret(sslSocket *ss, sslSessionID *sid, - ssl3CipherSpec *spec, SSLAuthType authType) + ssl3CipherSpec *spec) { PK11SymKey *wrappingKey = NULL; PK11SlotInfo *symKeySlot; @@ -11339,8 +11348,7 @@ ssl3_CacheWrappedMasterSecret(sslSocket *ss, sslSessionID *sid, mechanism = PK11_GetBestWrapMechanism(symKeySlot); if (mechanism != CKM_INVALID_MECHANISM) { wrappingKey = - ssl3_GetWrappingKey(ss, symKeySlot, ss->sec.serverCert, - mechanism, pwArg); + ssl3_GetWrappingKey(ss, symKeySlot, mechanism, pwArg); if (wrappingKey) { mechanism = PK11_GetMechanism(wrappingKey); /* can't fail. */ } @@ -11547,9 +11555,7 @@ ssl3_FillInCachedSID(sslSocket *ss, sslSessionID *sid) sid->expirationTime = sid->creationTime + ssl3_sid_timeout; sid->localCert = CERT_DupCertificate(ss->sec.localCert); if (ss->sec.isServer) { - memcpy(&sid->certType, &ss->sec.serverCert->certType, sizeof(sid->certType)); - } else { - sid->certType.authType = ssl_auth_null; + sid->namedCurve = ss->sec.serverCert->namedCurve; } if (ss->xtnData.nextProtoState != SSL_NEXT_PROTO_NO_SUPPORT && @@ -11573,8 +11579,7 @@ ssl3_FillInCachedSID(sslSocket *ss, sslSessionID *sid) rv = SECSuccess; } else { rv = ssl3_CacheWrappedMasterSecret(ss, ss->sec.ci.sid, - ss->ssl3.crSpec, - ss->ssl3.hs.kea_def->authKeyType); + ss->ssl3.crSpec); sid->u.ssl3.keys.msIsWrapped = PR_TRUE; } ssl_ReleaseSpecReadLock(ss); /*************************************/ @@ -11719,10 +11724,7 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length, /* Start new handshake hashes when we start a new handshake. Unless this is * TLS 1.3 and we sent a HelloRetryRequest. */ if (ss->ssl3.hs.msg_type == client_hello && !ss->ssl3.hs.helloRetry) { - rv = ssl3_RestartHandshakeHashes(ss); - if (rv != SECSuccess) { - return rv; - } + ssl3_RestartHandshakeHashes(ss); } /* We should not include hello_request and hello_verify_request messages * in the handshake hashes */ @@ -12508,17 +12510,14 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) ssl3CipherSpec *crSpec; SSL3ContentType rType; sslBuffer *plaintext; - sslBuffer temp_buf; + sslBuffer temp_buf = { NULL, 0, 0 }; SSL3AlertDescription alert = internal_error; PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); if (!ss->ssl3.initialized) { ssl_GetSSL3HandshakeLock(ss); - rv = ssl3_InitState(ss); + ssl3_InitState(ss); ssl_ReleaseSSL3HandshakeLock(ss); - if (rv != SECSuccess) { - return rv; /* ssl3_InitState has set the error code. */ - } } /* check for Token Presence */ @@ -12565,25 +12564,11 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) /* If we will be decompressing the buffer we need to decrypt somewhere * other than into databuf */ if (crSpec->decompressor) { - temp_buf.buf = NULL; - temp_buf.space = 0; plaintext = &temp_buf; } else { plaintext = databuf; } - plaintext->len = 0; /* filled in by Unprotect call below. */ - if (plaintext->space < MAX_FRAGMENT_LENGTH) { - rv = sslBuffer_Grow(plaintext, MAX_FRAGMENT_LENGTH + 2048); - if (rv != SECSuccess) { - ssl_ReleaseSpecReadLock(ss); /*************************/ - SSL_DBG(("%d: SSL3[%d]: HandleRecord, tried to get %d bytes", - SSL_GETPID(), ss->fd, MAX_FRAGMENT_LENGTH + 2048)); - /* sslBuffer_Grow has set a memory error code. */ - /* Perhaps we should send an alert. (but we have no memory!) */ - return SECFailure; - } - } /* We're waiting for another ClientHello, which will appear unencrypted. * Use the content type to tell whether this is should be discarded. @@ -12598,6 +12583,18 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) return SECSuccess; } + if (plaintext->space < MAX_FRAGMENT_LENGTH) { + rv = sslBuffer_Grow(plaintext, MAX_FRAGMENT_LENGTH + 2048); + if (rv != SECSuccess) { + ssl_ReleaseSpecReadLock(ss); /*************************/ + SSL_DBG(("%d: SSL3[%d]: HandleRecord, tried to get %d bytes", + SSL_GETPID(), ss->fd, MAX_FRAGMENT_LENGTH + 2048)); + /* sslBuffer_Grow has set a memory error code. */ + /* Perhaps we should send an alert. (but we have no memory!) */ + return SECFailure; + } + } + #ifdef UNSAFE_FUZZER_MODE rv = Null_Cipher(NULL, plaintext->buf, (int *)&plaintext->len, plaintext->space, cText->buf->buf, cText->buf->len); @@ -12619,6 +12616,9 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) SSL_DBG(("%d: SSL3[%d]: decryption failed", SSL_GETPID(), ss->fd)); + /* Clear the temp buffer used for decompression upon failure. */ + sslBuffer_Clear(&temp_buf); + if (IS_DTLS(ss) || (ss->sec.isServer && ss->ssl3.hs.zeroRttIgnore == ssl_0rtt_ignore_trial)) { @@ -12663,7 +12663,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) SSL3_COMPRESSION_MAX_EXPANSION)); /* sslBuffer_Grow has set a memory error code. */ /* Perhaps we should send an alert. (but we have no memory!) */ - PORT_Free(plaintext->buf); + sslBuffer_Clear(&temp_buf); return SECFailure; } } @@ -12701,12 +12701,12 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) } } - PORT_Free(plaintext->buf); + sslBuffer_Clear(&temp_buf); PORT_SetError(err); return SECFailure; } - PORT_Free(plaintext->buf); + sslBuffer_Clear(&temp_buf); } /* @@ -12836,16 +12836,14 @@ ssl3_InitCipherSpec(ssl3CipherSpec *spec) ** ssl3_HandleRecord() ** ** This function should perhaps acquire and release the SpecWriteLock. -** -** */ -SECStatus +void ssl3_InitState(sslSocket *ss) { PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); if (ss->ssl3.initialized) - return SECSuccess; /* Function should be idempotent */ + return; /* Function should be idempotent */ ss->ssl3.policy = SSL_ALLOWED; @@ -12900,7 +12898,6 @@ ssl3_InitState(sslSocket *ss) ssl_FilterSupportedGroups(ss); ss->ssl3.initialized = PR_TRUE; - return SECSuccess; } /* record the export policy for this cipher suite */ @@ -13280,8 +13277,6 @@ ssl3_DestroySSL3Info(sslSocket *ss) tls13_DestroyEarlyData(&ss->ssl3.hs.bufferedEarlyData); ss->ssl3.initialized = PR_FALSE; - - SECITEM_FreeItem(&ss->xtnData.nextProto, PR_FALSE); } #define MAP_NULL(x) (((x) != 0) ? (x) : SEC_OID_NULL_CIPHER) |