| Index: net/third_party/nss/ssl/ssl3con.c
|
| ===================================================================
|
| --- net/third_party/nss/ssl/ssl3con.c (revision 218090)
|
| +++ net/third_party/nss/ssl/ssl3con.c (working copy)
|
| @@ -85,9 +85,8 @@
|
| static SECStatus ssl3_AESGCMBypass(ssl3KeyMaterial *keys, PRBool doDecrypt,
|
| unsigned char *out, int *outlen, int maxout,
|
| const unsigned char *in, int inlen,
|
| - SSL3ContentType type,
|
| - SSL3ProtocolVersion version,
|
| - SSL3SequenceNumber seq_num);
|
| + const unsigned char *additionalData,
|
| + int additionalDataLen);
|
| #endif
|
|
|
| #define MAX_SEND_BUF_LENGTH 32000 /* watch for 16-bit integer overflow */
|
| @@ -396,10 +395,10 @@
|
| {SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, cipher_3des, mac_sha, kea_rsa_fips},
|
| {SSL_RSA_FIPS_WITH_DES_CBC_SHA, cipher_des, mac_sha, kea_rsa_fips},
|
|
|
| - {TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_null, kea_dhe_rsa},
|
| - {TLS_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_null, kea_rsa},
|
| - {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_null, kea_ecdhe_rsa},
|
| - {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_null, kea_ecdhe_ecdsa},
|
| + {TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_dhe_rsa},
|
| + {TLS_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_rsa},
|
| + {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_ecdhe_rsa},
|
| + {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_ecdhe_ecdsa},
|
|
|
| #ifdef NSS_ENABLE_ECC
|
| {TLS_ECDH_ECDSA_WITH_NULL_SHA, cipher_null, mac_sha, kea_ecdh_ecdsa},
|
| @@ -468,22 +467,25 @@
|
| /* { calg_init , (CK_MECHANISM_TYPE)0x7fffffffL } */
|
| };
|
|
|
| -#define mmech_null (CK_MECHANISM_TYPE)0x80000000L
|
| +#define mmech_invalid (CK_MECHANISM_TYPE)0x80000000L
|
| #define mmech_md5 CKM_SSL3_MD5_MAC
|
| #define mmech_sha CKM_SSL3_SHA1_MAC
|
| #define mmech_md5_hmac CKM_MD5_HMAC
|
| #define mmech_sha_hmac CKM_SHA_1_HMAC
|
| #define mmech_sha256_hmac CKM_SHA256_HMAC
|
| +#define mmech_sha384_hmac CKM_SHA384_HMAC
|
| +#define mmech_sha512_hmac CKM_SHA512_HMAC
|
|
|
| static const ssl3MACDef mac_defs[] = { /* indexed by SSL3MACAlgorithm */
|
| /* pad_size is only used for SSL 3.0 MAC. See RFC 6101 Sec. 5.2.3.1. */
|
| /* mac mmech pad_size mac_size */
|
| - { mac_null, mmech_null, 0, 0 },
|
| + { mac_null, mmech_invalid, 0, 0 },
|
| { mac_md5, mmech_md5, 48, MD5_LENGTH },
|
| { mac_sha, mmech_sha, 40, SHA1_LENGTH},
|
| {hmac_md5, mmech_md5_hmac, 0, MD5_LENGTH },
|
| {hmac_sha, mmech_sha_hmac, 0, SHA1_LENGTH},
|
| {hmac_sha256, mmech_sha256_hmac, 0, SHA256_LENGTH},
|
| + { mac_aead, mmech_invalid, 0, 0 },
|
| };
|
|
|
| /* indexed by SSL3BulkCipher */
|
| @@ -1766,8 +1768,18 @@
|
| return param;
|
| }
|
|
|
| -/* ssl3_BuildRecordPseudoHeader writes the TLS pseudo-header (the data which
|
| - * is included in the MAC) to |out| and returns its length. */
|
| +/* 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
|
| + * definition of the AEAD additional data.
|
| + *
|
| + * TLS pseudo-header includes the record's version field, SSL's doesn't. Which
|
| + * pseudo-header defintiion to use should be decided based on the version of
|
| + * the protocol that was negotiated when the cipher spec became current, NOT
|
| + * based on the version value in the record itself, and the decision is passed
|
| + * to this function as the |includesVersion| argument. But, the |version|
|
| + * argument should be the record's version value.
|
| + */
|
| static unsigned int
|
| ssl3_BuildRecordPseudoHeader(unsigned char *out,
|
| SSL3SequenceNumber seq_num,
|
| @@ -1881,29 +1893,18 @@
|
| int maxout,
|
| const unsigned char *in,
|
| int inlen,
|
| - SSL3ContentType type,
|
| - SSL3ProtocolVersion version,
|
| - SSL3SequenceNumber seq_num)
|
| + const unsigned char *additionalData,
|
| + int additionalDataLen)
|
| {
|
| SECItem param;
|
| SECStatus rv = SECFailure;
|
| unsigned char nonce[12];
|
| - unsigned char additionalData[13];
|
| - unsigned int additionalDataLen;
|
| unsigned int uOutLen;
|
| CK_GCM_PARAMS gcmParams;
|
|
|
| static const int tagSize = 16;
|
| static const int explicitNonceLen = 8;
|
|
|
| - /* See https://tools.ietf.org/html/rfc5246#section-6.2.3.3 for the
|
| - * definition of the AEAD additional data. */
|
| - additionalDataLen = ssl3_BuildRecordPseudoHeader(
|
| - additionalData, seq_num, type, PR_TRUE /* includes version */,
|
| - version, PR_FALSE /* not DTLS */,
|
| - inlen - (doDecrypt ? explicitNonceLen + tagSize : 0));
|
| - PORT_Assert(additionalDataLen <= sizeof(additionalData));
|
| -
|
| /* See https://tools.ietf.org/html/rfc5288#section-3 for details of how the
|
| * nonce is formed. */
|
| memcpy(nonce, keys->write_iv, 4);
|
| @@ -1930,7 +1931,7 @@
|
| param.len = sizeof(gcmParams);
|
| gcmParams.pIv = nonce;
|
| gcmParams.ulIvLen = sizeof(nonce);
|
| - gcmParams.pAAD = additionalData;
|
| + gcmParams.pAAD = (unsigned char *)additionalData; /* const cast */
|
| gcmParams.ulAADLen = additionalDataLen;
|
| gcmParams.ulTagBits = tagSize * 8;
|
|
|
| @@ -1955,14 +1956,11 @@
|
| int maxout,
|
| const unsigned char *in,
|
| int inlen,
|
| - SSL3ContentType type,
|
| - SSL3ProtocolVersion version,
|
| - SSL3SequenceNumber seq_num)
|
| + const unsigned char *additionalData,
|
| + int additionalDataLen)
|
| {
|
| SECStatus rv = SECFailure;
|
| unsigned char nonce[12];
|
| - unsigned char additionalData[13];
|
| - unsigned int additionalDataLen;
|
| unsigned int uOutLen;
|
| AESContext *cx;
|
| CK_GCM_PARAMS gcmParams;
|
| @@ -1970,14 +1968,6 @@
|
| static const int tagSize = 16;
|
| static const int explicitNonceLen = 8;
|
|
|
| - /* See https://tools.ietf.org/html/rfc5246#section-6.2.3.3 for the
|
| - * definition of the AEAD additional data. */
|
| - additionalDataLen = ssl3_BuildRecordPseudoHeader(
|
| - additionalData, seq_num, type, PR_TRUE /* includes version */,
|
| - version, PR_FALSE /* not DTLS */,
|
| - inlen - (doDecrypt ? explicitNonceLen + tagSize : 0));
|
| - PORT_Assert(additionalDataLen <= sizeof(additionalData));
|
| -
|
| /* See https://tools.ietf.org/html/rfc5288#section-3 for details of how the
|
| * nonce is formed. */
|
| PORT_Assert(keys->write_iv_item.len == 4);
|
| @@ -2006,7 +1996,7 @@
|
|
|
| gcmParams.pIv = nonce;
|
| gcmParams.ulIvLen = sizeof(nonce);
|
| - gcmParams.pAAD = additionalData;
|
| + gcmParams.pAAD = (unsigned char *)additionalData; /* const cast */
|
| gcmParams.ulAADLen = additionalDataLen;
|
| gcmParams.ulTagBits = tagSize * 8;
|
|
|
| @@ -2307,10 +2297,8 @@
|
| ssl3_ComputeRecordMAC(
|
| ssl3CipherSpec * spec,
|
| PRBool useServerMacKey,
|
| - PRBool isDTLS,
|
| - SSL3ContentType type,
|
| - SSL3ProtocolVersion version,
|
| - SSL3SequenceNumber seq_num,
|
| + const unsigned char *header,
|
| + unsigned int headerLen,
|
| const SSL3Opaque * input,
|
| int inputLength,
|
| unsigned char * outbuf,
|
| @@ -2318,22 +2306,8 @@
|
| {
|
| const ssl3MACDef * mac_def;
|
| SECStatus rv;
|
| - PRBool isTLS;
|
| - unsigned int tempLen;
|
| - unsigned char temp[MAX_MAC_LENGTH];
|
|
|
| - /* TLS MAC includes the record's version field, SSL's doesn't.
|
| - ** We decide which MAC defintiion to use based on the version of
|
| - ** the protocol that was negotiated when the spec became current,
|
| - ** NOT based on the version value in the record itself.
|
| - ** But, we use the record's version value in the computation.
|
| - */
|
| - isTLS = spec->version > SSL_LIBRARY_VERSION_3_0;
|
| - tempLen = ssl3_BuildRecordPseudoHeader(temp, seq_num, type, isTLS,
|
| - version, isDTLS, inputLength);
|
| - PORT_Assert(tempLen <= sizeof(temp));
|
| -
|
| - PRINT_BUF(95, (NULL, "frag hash1: temp", temp, tempLen));
|
| + PRINT_BUF(95, (NULL, "frag hash1: header", header, headerLen));
|
| PRINT_BUF(95, (NULL, "frag hash1: input", input, inputLength));
|
|
|
| mac_def = spec->mac_def;
|
| @@ -2378,7 +2352,10 @@
|
| return SECFailure;
|
| }
|
|
|
| - if (!isTLS) {
|
| + if (spec->version <= SSL_LIBRARY_VERSION_3_0) {
|
| + unsigned int tempLen;
|
| + unsigned char temp[MAX_MAC_LENGTH];
|
| +
|
| /* compute "inner" part of SSL3 MAC */
|
| hashObj->begin(write_mac_context);
|
| if (useServerMacKey)
|
| @@ -2390,7 +2367,7 @@
|
| spec->client.write_mac_key_item.data,
|
| spec->client.write_mac_key_item.len);
|
| hashObj->update(write_mac_context, mac_pad_1, pad_bytes);
|
| - hashObj->update(write_mac_context, temp, tempLen);
|
| + hashObj->update(write_mac_context, header, headerLen);
|
| hashObj->update(write_mac_context, input, inputLength);
|
| hashObj->end(write_mac_context, temp, &tempLen, sizeof temp);
|
|
|
| @@ -2421,7 +2398,7 @@
|
| }
|
| if (rv == SECSuccess) {
|
| HMAC_Begin(cx);
|
| - HMAC_Update(cx, temp, tempLen);
|
| + HMAC_Update(cx, header, headerLen);
|
| HMAC_Update(cx, input, inputLength);
|
| rv = HMAC_Finish(cx, outbuf, outLength, spec->mac_size);
|
| HMAC_Destroy(cx, PR_FALSE);
|
| @@ -2435,7 +2412,7 @@
|
| (useServerMacKey ? spec->server.write_mac_context
|
| : spec->client.write_mac_context);
|
| rv = PK11_DigestBegin(mac_context);
|
| - rv |= PK11_DigestOp(mac_context, temp, tempLen);
|
| + rv |= PK11_DigestOp(mac_context, header, headerLen);
|
| rv |= PK11_DigestOp(mac_context, input, inputLength);
|
| rv |= PK11_DigestFinal(mac_context, outbuf, outLength, spec->mac_size);
|
| }
|
| @@ -2475,10 +2452,8 @@
|
| ssl3_ComputeRecordMACConstantTime(
|
| ssl3CipherSpec * spec,
|
| PRBool useServerMacKey,
|
| - PRBool isDTLS,
|
| - SSL3ContentType type,
|
| - SSL3ProtocolVersion version,
|
| - SSL3SequenceNumber seq_num,
|
| + const unsigned char *header,
|
| + unsigned int headerLen,
|
| const SSL3Opaque * input,
|
| int inputLen,
|
| int originalLen,
|
| @@ -2490,9 +2465,7 @@
|
| PK11Context * mac_context;
|
| SECItem param;
|
| SECStatus rv;
|
| - unsigned char header[13];
|
| PK11SymKey * key;
|
| - int recordLength;
|
|
|
| PORT_Assert(inputLen >= spec->mac_size);
|
| PORT_Assert(originalLen >= inputLen);
|
| @@ -2508,42 +2481,15 @@
|
| return SECSuccess;
|
| }
|
|
|
| - header[0] = (unsigned char)(seq_num.high >> 24);
|
| - header[1] = (unsigned char)(seq_num.high >> 16);
|
| - header[2] = (unsigned char)(seq_num.high >> 8);
|
| - header[3] = (unsigned char)(seq_num.high >> 0);
|
| - header[4] = (unsigned char)(seq_num.low >> 24);
|
| - header[5] = (unsigned char)(seq_num.low >> 16);
|
| - header[6] = (unsigned char)(seq_num.low >> 8);
|
| - header[7] = (unsigned char)(seq_num.low >> 0);
|
| - header[8] = type;
|
| -
|
| macType = CKM_NSS_HMAC_CONSTANT_TIME;
|
| - recordLength = inputLen - spec->mac_size;
|
| if (spec->version <= SSL_LIBRARY_VERSION_3_0) {
|
| macType = CKM_NSS_SSL3_MAC_CONSTANT_TIME;
|
| - header[9] = recordLength >> 8;
|
| - header[10] = recordLength;
|
| - params.ulHeaderLen = 11;
|
| - } else {
|
| - if (isDTLS) {
|
| - SSL3ProtocolVersion dtls_version;
|
| -
|
| - dtls_version = dtls_TLSVersionToDTLSVersion(version);
|
| - header[9] = dtls_version >> 8;
|
| - header[10] = dtls_version;
|
| - } else {
|
| - header[9] = version >> 8;
|
| - header[10] = version;
|
| - }
|
| - header[11] = recordLength >> 8;
|
| - header[12] = recordLength;
|
| - params.ulHeaderLen = 13;
|
| }
|
|
|
| params.macAlg = spec->mac_def->mmech;
|
| params.ulBodyTotalLen = originalLen;
|
| - params.pHeader = header;
|
| + params.pHeader = (unsigned char *) header; /* const cast */
|
| + params.ulHeaderLen = headerLen;
|
|
|
| param.data = (unsigned char*) ¶ms;
|
| param.len = sizeof(params);
|
| @@ -2576,9 +2522,8 @@
|
| /* ssl3_ComputeRecordMAC expects the MAC to have been removed from the
|
| * length already. */
|
| inputLen -= spec->mac_size;
|
| - return ssl3_ComputeRecordMAC(spec, useServerMacKey, isDTLS, type,
|
| - version, seq_num, input, inputLen,
|
| - outbuf, outLen);
|
| + return ssl3_ComputeRecordMAC(spec, useServerMacKey, header, headerLen,
|
| + input, inputLen, outbuf, outLen);
|
| }
|
|
|
| static PRBool
|
| @@ -2630,6 +2575,8 @@
|
| PRUint16 headerLen;
|
| int ivLen = 0;
|
| int cipherBytes = 0;
|
| + unsigned char pseudoHeader[13];
|
| + unsigned int pseudoHeaderLen;
|
|
|
| cipher_def = cwSpec->cipher_def;
|
| headerLen = isDTLS ? DTLS_RECORD_HEADER_LENGTH : SSL3_RECORD_HEADER_LENGTH;
|
| @@ -2675,6 +2622,11 @@
|
| contentLen = outlen;
|
| }
|
|
|
| + pseudoHeaderLen = ssl3_BuildRecordPseudoHeader(
|
| + pseudoHeader, cwSpec->write_seq_num, type,
|
| + cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_0, cwSpec->version,
|
| + isDTLS, contentLen);
|
| + PORT_Assert(pseudoHeaderLen <= sizeof(pseudoHeader));
|
| if (cipher_def->type == type_aead) {
|
| const int nonceLen = cipher_def->explicit_nonce_size;
|
| const int tagLen = cipher_def->tag_size;
|
| @@ -2692,7 +2644,7 @@
|
| &cipherBytes, /* out len */
|
| wrBuf->space - headerLen, /* max out */
|
| pIn, contentLen, /* input */
|
| - type, cwSpec->version, cwSpec->write_seq_num);
|
| + pseudoHeader, pseudoHeaderLen);
|
| if (rv != SECSuccess) {
|
| PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
|
| return SECFailure;
|
| @@ -2701,8 +2653,8 @@
|
| /*
|
| * Add the MAC
|
| */
|
| - rv = ssl3_ComputeRecordMAC( cwSpec, isServer, isDTLS,
|
| - type, cwSpec->version, cwSpec->write_seq_num, pIn, contentLen,
|
| + rv = ssl3_ComputeRecordMAC(cwSpec, isServer,
|
| + pseudoHeader, pseudoHeaderLen, pIn, contentLen,
|
| wrBuf->buf + headerLen + ivLen + contentLen, &macLen);
|
| if (rv != SECSuccess) {
|
| ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
|
| @@ -11407,6 +11359,8 @@
|
| unsigned int originalLen = 0;
|
| unsigned int good;
|
| unsigned int minLength;
|
| + unsigned char header[13];
|
| + unsigned int headerLen;
|
|
|
| PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
|
|
|
| @@ -11560,6 +11514,17 @@
|
|
|
| rType = cText->type;
|
| if (cipher_def->type == type_aead) {
|
| + /* XXX For many AEAD ciphers, the plaintext is shorter than the
|
| + * ciphertext by a fixed byte count, but it is not true in general.
|
| + * Each AEAD cipher should provide a function that returns the
|
| + * plaintext length for a given ciphertext. */
|
| + unsigned int decryptedLen =
|
| + cText->buf->len - cipher_def->explicit_nonce_size -
|
| + cipher_def->tag_size;
|
| + headerLen = ssl3_BuildRecordPseudoHeader(
|
| + header, IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num,
|
| + rType, isTLS, cText->version, IS_DTLS(ss), decryptedLen);
|
| + PORT_Assert(headerLen <= sizeof(header));
|
| rv = crSpec->aead(
|
| ss->sec.isServer ? &crSpec->client : &crSpec->server,
|
| PR_TRUE, /* do decrypt */
|
| @@ -11568,9 +11533,7 @@
|
| plaintext->space, /* maxout */
|
| cText->buf->buf, /* in */
|
| cText->buf->len, /* inlen */
|
| - rType, /* record type */
|
| - cText->version,
|
| - IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num);
|
| + header, headerLen);
|
| if (rv != SECSuccess) {
|
| good = 0;
|
| }
|
| @@ -11597,7 +11560,7 @@
|
| const unsigned int blockSize = cipher_def->block_size;
|
| const unsigned int macSize = crSpec->mac_size;
|
|
|
| - if (crSpec->version <= SSL_LIBRARY_VERSION_3_0) {
|
| + if (!isTLS) {
|
| good &= SECStatusToMask(ssl_RemoveSSLv3CBCPadding(
|
| plaintext, blockSize, macSize));
|
| } else {
|
| @@ -11607,11 +11570,14 @@
|
| }
|
|
|
| /* compute the MAC */
|
| + headerLen = ssl3_BuildRecordPseudoHeader(
|
| + header, IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num,
|
| + rType, isTLS, cText->version, IS_DTLS(ss),
|
| + plaintext->len - crSpec->mac_size);
|
| + PORT_Assert(headerLen <= sizeof(header));
|
| if (cipher_def->type == type_block) {
|
| rv = ssl3_ComputeRecordMACConstantTime(
|
| - crSpec, (PRBool)(!ss->sec.isServer),
|
| - IS_DTLS(ss), rType, cText->version,
|
| - IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num,
|
| + crSpec, (PRBool)(!ss->sec.isServer), header, headerLen,
|
| plaintext->buf, plaintext->len, originalLen,
|
| hash, &hashBytes);
|
|
|
| @@ -11629,11 +11595,8 @@
|
| plaintext->len -= crSpec->mac_size;
|
|
|
| rv = ssl3_ComputeRecordMAC(
|
| - crSpec, (PRBool)(!ss->sec.isServer),
|
| - IS_DTLS(ss), rType, cText->version,
|
| - IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num,
|
| - plaintext->buf, plaintext->len,
|
| - hash, &hashBytes);
|
| + crSpec, (PRBool)(!ss->sec.isServer), header, headerLen,
|
| + plaintext->buf, plaintext->len, hash, &hashBytes);
|
|
|
| /* We can read the MAC directly from the record because its location
|
| * is public when a stream cipher is used. */
|
|
|