diff options
Diffstat (limited to 'security/nss/lib/ssl/ssl3con.c')
-rw-r--r-- | security/nss/lib/ssl/ssl3con.c | 794 |
1 files changed, 382 insertions, 412 deletions
diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index 186ce23f3..5cbe2bd09 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/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); @@ -64,7 +57,7 @@ static SECStatus ssl3_HandleServerHelloPart2(sslSocket *ss, const SECItem *sidBytes, int *retErrCode); static SECStatus ssl3_HandlePostHelloHandshakeMessage(sslSocket *ss, - SSL3Opaque *b, + PRUint8 *b, PRUint32 length, SSL3Hashes *hashesPtr); static SECStatus ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags); @@ -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; } @@ -1084,14 +1072,15 @@ ssl3_NegotiateVersion(sslSocket *ss, SSL3ProtocolVersion peerVersion, /* Used by the client when the server produces a version number. * This reads, validates, and normalizes the value. */ SECStatus -ssl_ClientReadVersion(sslSocket *ss, SSL3Opaque **b, unsigned int *len, +ssl_ClientReadVersion(sslSocket *ss, PRUint8 **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; @@ -2256,7 +2216,7 @@ ssl3_ComputeRecordMAC( PRBool useServerMacKey, const unsigned char *header, unsigned int headerLen, - const SSL3Opaque *input, + const PRUint8 *input, int inputLength, unsigned char *outbuf, unsigned int *outLength) @@ -2303,7 +2263,7 @@ ssl3_ComputeRecordMACConstantTime( PRBool useServerMacKey, const unsigned char *header, unsigned int headerLen, - const SSL3Opaque *input, + const PRUint8 *input, int inputLen, int originalLen, unsigned char *outbuf, @@ -2408,7 +2368,7 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec *cwSpec, PRBool isDTLS, PRBool capRecordVersion, SSL3ContentType type, - const SSL3Opaque *pIn, + const PRUint8 *pIn, PRUint32 contentLen, sslBuffer *wrBuf) { @@ -2577,7 +2537,7 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec *cwSpec, SECStatus ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, PRBool capRecordVersion, SSL3ContentType type, - const SSL3Opaque *pIn, PRUint32 contentLen, sslBuffer *wrBuf) + const PRUint8 *pIn, PRUint32 contentLen, sslBuffer *wrBuf) { const ssl3BulkCipherDef *cipher_def = cwSpec->cipher_def; PRUint16 headerLen; @@ -2694,14 +2654,15 @@ PRInt32 ssl3_SendRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, /* non-NULL for DTLS retransmits */ SSL3ContentType type, - const SSL3Opaque *pIn, /* input buffer */ - PRInt32 nIn, /* bytes of input */ + const PRUint8 *pIn, /* input buffer */ + PRInt32 nIn, /* bytes of input */ PRInt32 flags) { sslBuffer *wrBuf = &ss->sec.writeBuf; 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; } /* @@ -4243,7 +4219,7 @@ ssl3_AppendHandshakeNumber(sslSocket *ss, PRInt32 num, PRInt32 lenSize) SECStatus ssl3_AppendHandshakeVariable( - sslSocket *ss, const SSL3Opaque *src, PRInt32 bytes, PRInt32 lenSize) + sslSocket *ss, const PRUint8 *src, PRInt32 bytes, PRInt32 lenSize) { SECStatus 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, PRUint8 **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, + PRUint8 **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, - SSL3Opaque **b, PRUint32 *length) +ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i, PRUint32 bytes, + PRUint8 **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; @@ -4421,19 +4394,6 @@ ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i, PRInt32 bytes, return SECSuccess; } -/* Helper function to encode an unsigned integer into a buffer. */ -PRUint8 * -ssl_EncodeUintX(PRUint64 value, unsigned int bytes, PRUint8 *to) -{ - PRUint64 encoded; - - PORT_Assert(bytes > 0 && bytes <= sizeof(encoded)); - - encoded = PR_htonll(value); - memcpy(to, ((unsigned char *)(&encoded)) + (sizeof(encoded) - bytes), bytes); - return to + bytes; -} - /* ssl3_TLSHashAlgorithmToOID converts a TLS hash identifier into an OID value. * If the hash is not recognised, SEC_OID_UNKNOWN is returned. * @@ -4678,13 +4638,14 @@ ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme) * * See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */ SECStatus -ssl_ConsumeSignatureScheme(sslSocket *ss, SSL3Opaque **b, +ssl_ConsumeSignatureScheme(sslSocket *ss, PRUint8 **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)) { @@ -4743,8 +4704,8 @@ ssl3_ComputeHandshakeHashes(sslSocket *ss, SECStatus rv = SECSuccess; PRBool isTLS = (PRBool)(spec->version > SSL_LIBRARY_VERSION_3_0); unsigned int outLength; - SSL3Opaque md5_inner[MAX_MAC_LENGTH]; - SSL3Opaque sha_inner[MAX_MAC_LENGTH]; + PRUint8 md5_inner[MAX_MAC_LENGTH]; + PRUint8 sha_inner[MAX_MAC_LENGTH]; PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); if (ss->ssl3.hs.hashType == handshake_hash_unknown) { @@ -4990,7 +4951,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 +4973,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 +5246,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 +5422,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 +5516,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 +5531,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; +} - while (mech != *pMech && *pMech != UNKNOWN_WRAP_MECHANISM) { - ++pMech; +/* 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 +}; + +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 +5594,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 +5604,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 +5677,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 +5706,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 +5740,6 @@ ssl_InitSymWrapKeysLock(void) PK11SymKey * ssl3_GetWrappingKey(sslSocket *ss, PK11SlotInfo *masterSecretSlot, - const sslServerCert *serverCert, CK_MECHANISM_TYPE masterWrapMech, void *pwArg) { @@ -5791,7 +5750,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 +5759,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 +5771,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 +5801,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 +5954,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 +5964,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 +5973,7 @@ ssl3_GetWrappingKey(sslSocket *ss, PK11_FreeSymKey(unwrappedWrappingKey); unwrappedWrappingKey = - ssl_UnwrapSymWrappingKey(&wswk, svrPrivKey, authType, + ssl_UnwrapSymWrappingKey(&wswk, svrPrivKey, wrapKeyIndex, masterWrapMech, pwArg); } @@ -6411,6 +6377,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 +6417,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 +6435,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) { @@ -6604,9 +6590,9 @@ ssl3_SetCipherSuite(sslSocket *ss, ssl3CipherSuite chosenSuite, * Caller must hold Handshake and RecvBuf locks. */ static SECStatus -ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) +ssl3_HandleServerHello(sslSocket *ss, PRUint8 *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 +6635,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 +6717,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 +6763,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 +7006,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); @@ -7062,7 +7071,7 @@ loser: } static SECStatus -ssl_HandleDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) +ssl_HandleDHServerKeyExchange(sslSocket *ss, PRUint8 *b, PRUint32 length) { SECStatus rv; int errCode = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH; @@ -7222,7 +7231,7 @@ loser: * Caller must hold Handshake and RecvBuf locks. */ static SECStatus -ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) +ssl3_HandleServerKeyExchange(sslSocket *ss, PRUint8 *b, PRUint32 length) { SECStatus rv; @@ -7273,19 +7282,20 @@ typedef struct dnameNode { * tls13_HandleCertificateRequest */ SECStatus -ssl3_ParseCertificateRequestCAs(sslSocket *ss, SSL3Opaque **b, PRUint32 *length, +ssl3_ParseCertificateRequestCAs(sslSocket *ss, PRUint8 **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 +7303,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 +7363,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 +7371,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 +7396,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 +7415,7 @@ ssl_ParseSignatureSchemes(const sslSocket *ss, PLArenaPool *arena, schemes = NULL; } +done: *schemesOut = schemes; *numSchemesOut = numSchemes; return SECSuccess; @@ -7410,7 +7426,7 @@ ssl_ParseSignatureSchemes(const sslSocket *ss, PLArenaPool *arena, * Caller must hold Handshake and RecvBuf locks. */ static SECStatus -ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) +ssl3_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length) { PLArenaPool *arena = NULL; PRBool isTLS = PR_FALSE; @@ -8227,19 +8243,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. */ @@ -8258,10 +8272,10 @@ ssl3_SelectServerCert(sslSocket *ss) * Caller must hold Handshake and RecvBuf locks. */ static SECStatus -ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) +ssl3_HandleClientHello(sslSocket *ss, PRUint8 *b, PRUint32 length) { sslSessionID *sid = NULL; - PRInt32 tmp; + PRUint32 tmp; unsigned int i; SECStatus rv; int errCode = SSL_ERROR_RX_MALFORMED_CLIENT_HELLO; @@ -8321,8 +8335,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. */ @@ -8375,9 +8389,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) { @@ -8479,7 +8493,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) @@ -8505,7 +8519,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) for (i = 0; i + 1 < suites.len; i += 2) { PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1]; if (suite_i == TLS_EMPTY_RENEGOTIATION_INFO_SCSV) { - SSL3Opaque *b2 = (SSL3Opaque *)emptyRIext; + PRUint8 *b2 = (PRUint8 *)emptyRIext; PRUint32 L2 = sizeof emptyRIext; (void)ssl3_HandleExtensions(ss, &b2, &L2, client_hello); break; @@ -8763,7 +8777,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 || @@ -8771,8 +8784,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. */ @@ -8820,7 +8838,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) { @@ -8879,13 +8897,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 && @@ -9077,16 +9090,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; @@ -9202,7 +9207,7 @@ suite_found: for (i = 0; i + 2 < suite_length; i += 3) { PRUint32 suite_i = (suites[i] << 16) | (suites[i + 1] << 8) | suites[i + 2]; if (suite_i == TLS_EMPTY_RENEGOTIATION_INFO_SCSV) { - SSL3Opaque *b2 = (SSL3Opaque *)emptyRIext; + PRUint8 *b2 = (PRUint8 *)emptyRIext; PRUint32 L2 = sizeof emptyRIext; (void)ssl3_HandleExtensions(ss, &b2, &L2, client_hello); break; @@ -9603,34 +9608,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) { @@ -9639,8 +9616,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; @@ -9655,7 +9632,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; @@ -9723,7 +9703,7 @@ ssl3_SendServerHelloDone(sslSocket *ss) * Caller must hold Handshake and RecvBuf locks. */ static SECStatus -ssl3_HandleCertificateVerify(sslSocket *ss, SSL3Opaque *b, PRUint32 length, +ssl3_HandleCertificateVerify(sslSocket *ss, PRUint8 *b, PRUint32 length, SSL3Hashes *hashes) { SECItem signed_hash = { siBuffer, NULL, 0 }; @@ -9741,17 +9721,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; @@ -9798,6 +9776,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) { @@ -9910,7 +9890,7 @@ ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec, */ static SECStatus ssl3_HandleRSAClientKeyExchange(sslSocket *ss, - SSL3Opaque *b, + PRUint8 *b, PRUint32 length, sslKeyPair *serverKeyPair) { @@ -9928,9 +9908,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; } @@ -10037,7 +10017,7 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss, static SECStatus ssl3_HandleDHClientKeyExchange(sslSocket *ss, - SSL3Opaque *b, + PRUint8 *b, PRUint32 length, sslKeyPair *serverKeyPair) { @@ -10095,7 +10075,7 @@ ssl3_HandleDHClientKeyExchange(sslSocket *ss, * Caller must hold Handshake and RecvBuf locks. */ static SECStatus -ssl3_HandleClientKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) +ssl3_HandleClientKeyExchange(sslSocket *ss, PRUint8 *b, PRUint32 length) { sslKeyPair *serverKeyPair = NULL; SECStatus rv; @@ -10227,7 +10207,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; @@ -10246,10 +10226,11 @@ loser: } static SECStatus -ssl3_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length) +ssl3_HandleNewSessionTicket(sslSocket *ss, PRUint8 *b, PRUint32 length) { SECStatus rv; SECItem ticketData; + PRUint32 temp; SSL_TRC(3, ("%d: SSL3[%d]: handle session_ticket handshake", SSL_GETPID(), ss->fd)); @@ -10270,14 +10251,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) { @@ -10551,7 +10537,7 @@ ssl3_CleanupPeerCerts(sslSocket *ss) * Caller must hold Handshake and RecvBuf locks. */ static SECStatus -ssl3_HandleCertificateStatus(sslSocket *ss, SSL3Opaque *b, PRUint32 length) +ssl3_HandleCertificateStatus(sslSocket *ss, PRUint8 *b, PRUint32 length) { SECStatus rv; @@ -10570,23 +10556,22 @@ ssl3_HandleCertificateStatus(sslSocket *ss, SSL3Opaque *b, PRUint32 length) } SECStatus -ssl_ReadCertificateStatus(sslSocket *ss, SSL3Opaque *b, PRUint32 length) +ssl_ReadCertificateStatus(sslSocket *ss, PRUint8 *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 */ @@ -10619,7 +10604,7 @@ ssl_ReadCertificateStatus(sslSocket *ss, SSL3Opaque *b, PRUint32 length) * Caller must hold Handshake and RecvBuf locks. */ static SECStatus -ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) +ssl3_HandleCertificate(sslSocket *ss, PRUint8 *b, PRUint32 length) { SSL_TRC(3, ("%d: SSL3[%d]: handle certificate handshake", SSL_GETPID(), ss->fd)); @@ -10639,12 +10624,12 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) /* Called from ssl3_HandleCertificate */ SECStatus -ssl3_CompleteHandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) +ssl3_CompleteHandleCertificate(sslSocket *ss, PRUint8 *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; @@ -10660,10 +10645,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; } @@ -10694,15 +10679,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; @@ -10722,15 +10706,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; @@ -10759,9 +10742,6 @@ ssl3_CompleteHandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) lastCert = c; } - if (remaining != 0) - goto decode_loser; - SECKEY_UpdateCertPQG(ss->sec.peerCert); if (!isServer && @@ -11049,13 +11029,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) { @@ -11088,9 +11065,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; @@ -11101,6 +11079,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, @@ -11143,9 +11127,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 */ } @@ -11298,7 +11280,7 @@ fail: */ SECStatus ssl3_CacheWrappedMasterSecret(sslSocket *ss, sslSessionID *sid, - ssl3CipherSpec *spec, SSLAuthType authType) + ssl3CipherSpec *spec) { PK11SymKey *wrappingKey = NULL; PK11SlotInfo *symKeySlot; @@ -11352,8 +11334,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. */ } @@ -11382,7 +11363,7 @@ ssl3_CacheWrappedMasterSecret(sslSocket *ss, sslSessionID *sid, * Caller must hold Handshake and RecvBuf locks. */ static SECStatus -ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length, +ssl3_HandleFinished(sslSocket *ss, PRUint8 *b, PRUint32 length, const SSL3Hashes *hashes) { sslSessionID *sid = ss->sec.ci.sid; @@ -11560,9 +11541,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 && @@ -11586,8 +11565,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); /*************************************/ @@ -11646,7 +11624,7 @@ ssl3_FinishHandshake(sslSocket *ss) * Caller must hold Handshake and RecvBuf locks. */ SECStatus -ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length, +ssl3_HandleHandshakeMessage(sslSocket *ss, PRUint8 *b, PRUint32 length, PRBool endOfRecord) { SECStatus rv = SECSuccess; @@ -11732,10 +11710,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 */ @@ -11835,7 +11810,7 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length, } static SECStatus -ssl3_HandlePostHelloHandshakeMessage(sslSocket *ss, SSL3Opaque *b, +ssl3_HandlePostHelloHandshakeMessage(sslSocket *ss, PRUint8 *b, PRUint32 length, SSL3Hashes *hashesPtr) { SECStatus rv; @@ -12203,7 +12178,7 @@ ssl_RemoveTLSCBCPadding(sslBuffer *plaintext, unsigned int macSize) static void ssl_CBCExtractMAC(sslBuffer *plaintext, unsigned int originalLength, - SSL3Opaque *out, + PRUint8 *out, unsigned int macSize) { unsigned char rotatedMac[MAX_MAC_LENGTH]; @@ -12314,9 +12289,9 @@ ssl3_UnprotectRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *plaintext, unsigned int originalLen = 0; unsigned char header[13]; unsigned int headerLen; - SSL3Opaque hash[MAX_MAC_LENGTH]; - SSL3Opaque givenHashBuf[MAX_MAC_LENGTH]; - SSL3Opaque *givenHash; + PRUint8 hash[MAX_MAC_LENGTH]; + PRUint8 givenHashBuf[MAX_MAC_LENGTH]; + PRUint8 *givenHash; unsigned int hashBytes = MAX_MAC_LENGTH + 1; SECStatus rv; @@ -12347,7 +12322,7 @@ ssl3_UnprotectRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *plaintext, * component." Instead, we decrypt the first cipher block and then * discard it before decrypting the rest. */ - SSL3Opaque iv[MAX_IV_LENGTH]; + PRUint8 iv[MAX_IV_LENGTH]; int decoded; ivLen = cipher_def->iv_size; @@ -12521,17 +12496,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 */ @@ -12578,25 +12550,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. @@ -12611,6 +12569,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); @@ -12632,6 +12602,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)) { @@ -12676,7 +12649,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; } } @@ -12714,12 +12687,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); } /* @@ -12849,16 +12822,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; @@ -12913,7 +12884,6 @@ ssl3_InitState(sslSocket *ss) ssl_FilterSupportedGroups(ss); ss->ssl3.initialized = PR_TRUE; - return SECSuccess; } /* record the export policy for this cipher suite */ @@ -13136,7 +13106,7 @@ SSL_SignaturePrefGet(PRFileDesc *fd, SSLSignatureAndHashAlg *algorithms, } unsigned int -SSL_SignatureMaxCount() +SSL_SignatureMaxCount(void) { return MAX_SIGNATURE_SCHEMES; } |