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}, |
@@ -474,6 +473,8 @@ |
#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. */ |
@@ -484,6 +485,9 @@ |
{hmac_md5, mmech_md5_hmac, 0, MD5_LENGTH }, |
{hmac_sha, mmech_sha_hmac, 0, SHA1_LENGTH}, |
{hmac_sha256, mmech_sha256_hmac, 0, SHA256_LENGTH}, |
+ {hmac_sha384, mmech_sha384_hmac, 0, SHA384_LENGTH}, |
+ {hmac_sha512, mmech_sha512_hmac, 0, SHA512_LENGTH}, |
+ { mac_aead, mmech_null, 0, 0 }, |
wtc
2013/08/17 00:21:15
This array element for mac_aead needs to exist but
|
}; |
/* indexed by SSL3BulkCipher */ |
@@ -1766,8 +1770,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 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 +1895,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 */, |
wtc
2013/08/17 00:21:15
Note that we had to pass PR_FALSE as the |isDTLS|
|
- 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 +1933,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 +1958,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 +1970,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 +1998,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 +2299,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 +2308,8 @@ |
{ |
const ssl3MACDef * mac_def; |
SECStatus rv; |
- PRBool isTLS; |
- unsigned int tempLen; |
- unsigned char temp[MAX_MAC_LENGTH]; |
wtc
2013/08/17 00:21:15
|isTLS| is only used once, so I just inline it.
I
|
- /* 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 +2354,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 +2369,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 +2400,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 +2414,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 +2454,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 +2467,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 +2483,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 +2524,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 +2577,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 +2624,11 @@ |
contentLen = outlen; |
} |
+ pseudoHeaderLen = ssl3_BuildRecordPseudoHeader(pseudoHeader, |
Ryan Sleevi
2013/08/17 02:00:23
This is really weird indentation of that first par
wtc
2013/08/19 23:31:56
Done.
|
+ 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 +2646,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 +2655,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 +11361,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 +11516,14 @@ |
rType = cText->type; |
if (cipher_def->type == type_aead) { |
+ /* XXX Is this true for all AEAD ciphers? */ |
Ryan Sleevi
2013/08/17 02:00:23
No.
This is covered in http://tools.ietf.org/html
wtc
2013/08/19 23:31:56
Done. Thank you for the research. I updated the co
|
+ 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 +11532,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 +11559,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 +11569,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 +11594,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. */ |