Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(459)

Unified Diff: net/third_party/nss/ssl/ssl3con.c

Issue 23299002: Make the AES-GCM cipher suites work in DTLS, by moving the (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Fix comments and update patch files Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/third_party/nss/ssl/dtlscon.c ('k') | net/third_party/nss/ssl/sslimpl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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*) &params;
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. */
« no previous file with comments | « net/third_party/nss/ssl/dtlscon.c ('k') | net/third_party/nss/ssl/sslimpl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698