summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-15 00:51:34 +0000
committerwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-15 00:51:34 +0000
commit80096fe8895efbbc7b0fe8ca1580b03e03c57f0e (patch)
tree663c6d406852517ee07346d1f3d45f93f8091326
parent206a5f3ed884fd480fde01abca12c40d7886cf58 (diff)
downloadchromium_src-80096fe8895efbbc7b0fe8ca1580b03e03c57f0e.zip
chromium_src-80096fe8895efbbc7b0fe8ca1580b03e03c57f0e.tar.gz
chromium_src-80096fe8895efbbc7b0fe8ca1580b03e03c57f0e.tar.bz2
Implement the AES GCM cipher suites for TLS.
The AES GCM cipher suites are disabled in DTLS. This will be fixed soon. Disable the HMAC-SHA256 cipher suites so that our ClientHello doesn't become too big. Patch by Adam Langley. R=agl@chromium.org,rsleevi@chromium.org BUG=255241 TEST=none Review URL: https://chromiumcodereview.appspot.com/21696002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@217716 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--net/socket/nss_ssl_util.cc5
-rw-r--r--net/third_party/nss/README.chromium10
-rw-r--r--net/third_party/nss/patches/aesgcm.patch1179
-rw-r--r--net/third_party/nss/patches/aesgcmchromium.patch117
-rwxr-xr-xnet/third_party/nss/patches/applypatches.sh4
-rw-r--r--net/third_party/nss/ssl/dtlscon.c7
-rw-r--r--net/third_party/nss/ssl/ssl3con.c745
-rw-r--r--net/third_party/nss/ssl/ssl3ecc.c4
-rw-r--r--net/third_party/nss/ssl/sslenum.c8
-rw-r--r--net/third_party/nss/ssl/sslimpl.h53
-rw-r--r--net/third_party/nss/ssl/sslinfo.c10
-rw-r--r--net/third_party/nss/ssl/sslproto.h9
-rw-r--r--net/third_party/nss/ssl/sslsock.c4
-rw-r--r--net/third_party/nss/ssl/sslt.h5
14 files changed, 1928 insertions, 232 deletions
diff --git a/net/socket/nss_ssl_util.cc b/net/socket/nss_ssl_util.cc
index be33ac5..ae037b1 100644
--- a/net/socket/nss_ssl_util.cc
+++ b/net/socket/nss_ssl_util.cc
@@ -58,12 +58,13 @@ class NSSSSLInitSingleton {
enabled = false;
// Trim the list of cipher suites in order to keep the size of the
- // ClientHello down. DSS, ECDH, CAMELLIA, SEED and ECC+3DES cipher
- // suites are disabled.
+ // ClientHello down. DSS, ECDH, CAMELLIA, SEED, ECC+3DES, and
+ // HMAC-SHA256 cipher suites are disabled.
if (info.symCipher == ssl_calg_camellia ||
info.symCipher == ssl_calg_seed ||
(info.symCipher == ssl_calg_3des && info.keaType != ssl_kea_rsa) ||
info.authAlgorithm == ssl_auth_dsa ||
+ info.macAlgorithm == ssl_hmac_sha256 ||
info.nonStandard ||
strcmp(info.keaTypeName, "ECDH") == 0) {
enabled = false;
diff --git a/net/third_party/nss/README.chromium b/net/third_party/nss/README.chromium
index aad42b5..11a8510 100644
--- a/net/third_party/nss/README.chromium
+++ b/net/third_party/nss/README.chromium
@@ -74,6 +74,8 @@ Patches:
NSS that doesn't contain the CBC constant-time changes.
patches/cbc.patch
https://code.google.com/p/chromium/issues/detail?id=172658#c12
+ TODO(wtc): remove this patch now that NSS 3.14.3 is the minimum
+ compile-time and run-time version.
* Change ssl3_SuiteBOnly to always return PR_TRUE. The softoken in NSS
versions older than 3.15 report an EC key size range of 112 bits to 571
@@ -97,6 +99,14 @@ Patches:
https://bugzilla.mozilla.org/show_bug.cgi?id=903565
patches/sslsock_903565.patch
+ * Implement the AES GCM cipher suites.
+ https://bugzilla.mozilla.org/show_bug.cgi?id=880543
+ patches/aesgcm.patch
+
+ * Add Chromium-specific code to detect AES GCM support in the system NSS
+ libraries at run time.
+ patches/aesgcmchromium.patch
+
Apply the patches to NSS by running the patches/applypatches.sh script. Read
the comments at the top of patches/applypatches.sh for instructions.
diff --git a/net/third_party/nss/patches/aesgcm.patch b/net/third_party/nss/patches/aesgcm.patch
new file mode 100644
index 0000000..8de0a69
--- /dev/null
+++ b/net/third_party/nss/patches/aesgcm.patch
@@ -0,0 +1,1179 @@
+Index: net/third_party/nss/ssl/sslinfo.c
+===================================================================
+--- net/third_party/nss/ssl/sslinfo.c (revision 215189)
++++ net/third_party/nss/ssl/sslinfo.c (working copy)
+@@ -109,7 +109,7 @@
+ #define K_ECDHE "ECDHE", kt_ecdh
+
+ #define C_SEED "SEED", calg_seed
+-#define C_CAMELLIA "CAMELLIA", calg_camellia
++#define C_CAMELLIA "CAMELLIA", calg_camellia
+ #define C_AES "AES", calg_aes
+ #define C_RC4 "RC4", calg_rc4
+ #define C_RC2 "RC2", calg_rc2
+@@ -117,6 +117,7 @@
+ #define C_3DES "3DES", calg_3des
+ #define C_NULL "NULL", calg_null
+ #define C_SJ "SKIPJACK", calg_sj
++#define C_AESGCM "AES-GCM", calg_aes_gcm
+
+ #define B_256 256, 256, 256
+ #define B_128 128, 128, 128
+@@ -130,9 +131,12 @@
+ #define M_SHA256 "SHA256", ssl_hmac_sha256, 256
+ #define M_SHA "SHA1", ssl_mac_sha, 160
+ #define M_MD5 "MD5", ssl_mac_md5, 128
++#define M_NULL "NULL", ssl_mac_null, 0
+
+ static const SSLCipherSuiteInfo suiteInfo[] = {
+ /* <------ Cipher suite --------------------> <auth> <KEA> <bulk cipher> <MAC> <FIPS> */
++{0,CS(TLS_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_RSA, C_AESGCM, B_128, M_NULL, 1, 0, 0, },
++
+ {0,CS(TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_256, M_SHA, 0, 0, 0, },
+ {0,CS(TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_256, M_SHA, 0, 0, 0, },
+ {0,CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_DHE, C_AES, B_256, M_SHA256, 1, 0, 0, },
+@@ -146,6 +150,7 @@
+ {0,CS(TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_128, M_SHA, 0, 0, 0, },
+ {0,CS(TLS_DHE_DSS_WITH_RC4_128_SHA), S_DSA, K_DHE, C_RC4, B_128, M_SHA, 0, 0, 0, },
+ {0,CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_DHE, C_AES, B_128, M_SHA256, 1, 0, 0, },
++{0,CS(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_DHE, C_AESGCM, B_128, M_NULL, 1, 0, 0, },
+ {0,CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_DHE, C_AES, B_128, M_SHA, 1, 0, 0, },
+ {0,CS(TLS_DHE_DSS_WITH_AES_128_CBC_SHA), S_DSA, K_DHE, C_AES, B_128, M_SHA, 1, 0, 0, },
+ {0,CS(TLS_RSA_WITH_SEED_CBC_SHA), S_RSA, K_RSA, C_SEED,B_128, M_SHA, 1, 0, 0, },
+@@ -175,6 +180,9 @@
+
+ #ifdef NSS_ENABLE_ECC
+ /* ECC cipher suites */
++{0,CS(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_ECDHE, C_AESGCM, B_128, M_NULL, 1, 0, 0, },
++{0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), S_ECDSA, K_ECDHE, C_AESGCM, B_128, M_NULL, 1, 0, 0, },
++
+ {0,CS(TLS_ECDH_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDH, C_NULL, B_0, M_SHA, 0, 0, 0, },
+ {0,CS(TLS_ECDH_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDH, C_RC4, B_128, M_SHA, 0, 0, 0, },
+ {0,CS(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDH, C_3DES, B_3DES, M_SHA, 1, 0, 0, },
+Index: net/third_party/nss/ssl/sslimpl.h
+===================================================================
+--- net/third_party/nss/ssl/sslimpl.h (revision 215189)
++++ net/third_party/nss/ssl/sslimpl.h (working copy)
+@@ -64,6 +64,7 @@
+ #define calg_aes ssl_calg_aes
+ #define calg_camellia ssl_calg_camellia
+ #define calg_seed ssl_calg_seed
++#define calg_aes_gcm ssl_calg_aes_gcm
+
+ #define mac_null ssl_mac_null
+ #define mac_md5 ssl_mac_md5
+@@ -290,9 +291,9 @@
+ } ssl3CipherSuiteCfg;
+
+ #ifdef NSS_ENABLE_ECC
+-#define ssl_V3_SUITES_IMPLEMENTED 57
++#define ssl_V3_SUITES_IMPLEMENTED 61
+ #else
+-#define ssl_V3_SUITES_IMPLEMENTED 35
++#define ssl_V3_SUITES_IMPLEMENTED 37
+ #endif /* NSS_ENABLE_ECC */
+
+ #define MAX_DTLS_SRTP_CIPHER_SUITES 4
+@@ -440,20 +441,6 @@
+ #define GS_DATA 3
+ #define GS_PAD 4
+
+-typedef SECStatus (*SSLCipher)(void * context,
+- unsigned char * out,
+- int * outlen,
+- int maxout,
+- const unsigned char *in,
+- int inlen);
+-typedef SECStatus (*SSLCompressor)(void * context,
+- unsigned char * out,
+- int * outlen,
+- int maxout,
+- const unsigned char *in,
+- int inlen);
+-typedef SECStatus (*SSLDestroy)(void *context, PRBool freeit);
+-
+ #if defined(NSS_PLATFORM_CLIENT_AUTH) && defined(XP_WIN32)
+ typedef PCERT_KEY_CONTEXT PlatformKey;
+ #elif defined(NSS_PLATFORM_CLIENT_AUTH) && defined(XP_MACOSX)
+@@ -485,11 +472,12 @@
+ cipher_camellia_128,
+ cipher_camellia_256,
+ cipher_seed,
++ cipher_aes_128_gcm,
+ cipher_missing /* reserved for no such supported cipher */
+ /* This enum must match ssl3_cipherName[] in ssl3con.c. */
+ } SSL3BulkCipher;
+
+-typedef enum { type_stream, type_block } CipherType;
++typedef enum { type_stream, type_block, type_aead } CipherType;
+
+ #define MAX_IV_LENGTH 24
+
+@@ -531,6 +519,31 @@
+ PRUint64 cipher_context[MAX_CIPHER_CONTEXT_LLONGS];
+ } ssl3KeyMaterial;
+
++typedef SECStatus (*SSLCipher)(void * context,
++ unsigned char * out,
++ int * outlen,
++ int maxout,
++ const unsigned char *in,
++ int inlen);
++typedef SECStatus (*SSLAEADCipher)(
++ ssl3KeyMaterial * keys,
++ PRBool doDecrypt,
++ unsigned char * out,
++ int * outlen,
++ int maxout,
++ const unsigned char *in,
++ int inlen,
++ SSL3ContentType type,
++ SSL3ProtocolVersion version,
++ SSL3SequenceNumber seqnum);
++typedef SECStatus (*SSLCompressor)(void * context,
++ unsigned char * out,
++ int * outlen,
++ int maxout,
++ const unsigned char *in,
++ int inlen);
++typedef SECStatus (*SSLDestroy)(void *context, PRBool freeit);
++
+ /* The DTLS anti-replay window. Defined here because we need it in
+ * the cipher spec. Note that this is a ring buffer but left and
+ * right represent the true window, with modular arithmetic used to
+@@ -557,6 +570,7 @@
+ int mac_size;
+ SSLCipher encode;
+ SSLCipher decode;
++ SSLAEADCipher aead;
+ SSLDestroy destroy;
+ void * encodeContext;
+ void * decodeContext;
+@@ -706,8 +720,6 @@
+ PRBool tls_keygen;
+ } ssl3KEADef;
+
+-typedef enum { kg_null, kg_strong, kg_export } SSL3KeyGenMode;
+-
+ /*
+ ** There are tables of these, all const.
+ */
+@@ -719,7 +731,8 @@
+ CipherType type;
+ int iv_size;
+ int block_size;
+- SSL3KeyGenMode keygen_mode;
++ int tag_size; /* authentication tag size for AEAD ciphers. */
++ int explicit_nonce_size; /* for AEAD ciphers. */
+ };
+
+ /*
+Index: net/third_party/nss/ssl/ssl3ecc.c
+===================================================================
+--- net/third_party/nss/ssl/ssl3ecc.c (revision 215189)
++++ net/third_party/nss/ssl/ssl3ecc.c (working copy)
+@@ -911,6 +911,7 @@
+ TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
++ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+ TLS_ECDHE_ECDSA_WITH_NULL_SHA,
+ TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+@@ -921,6 +922,7 @@
+ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
++ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+ TLS_ECDHE_RSA_WITH_NULL_SHA,
+ TLS_ECDHE_RSA_WITH_RC4_128_SHA,
+@@ -932,12 +934,14 @@
+ TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
++ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+ TLS_ECDHE_ECDSA_WITH_NULL_SHA,
+ TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
++ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+ TLS_ECDHE_RSA_WITH_NULL_SHA,
+ TLS_ECDHE_RSA_WITH_RC4_128_SHA,
+Index: net/third_party/nss/ssl/sslsock.c
+===================================================================
+--- net/third_party/nss/ssl/sslsock.c (revision 215189)
++++ net/third_party/nss/ssl/sslsock.c (working copy)
+@@ -67,8 +67,10 @@
+ { TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
+ { TLS_DHE_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
+ { TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
++ { TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
+ { TLS_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
+ { TLS_RSA_WITH_AES_128_CBC_SHA256, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
++ { TLS_RSA_WITH_AES_128_GCM_SHA256, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
+ { TLS_DHE_DSS_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
+ { TLS_DHE_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
+ { TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
+@@ -94,6 +96,7 @@
+ { TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
+ { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
+ { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
++ { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
+ { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
+ { TLS_ECDH_RSA_WITH_NULL_SHA, SSL_ALLOWED, SSL_ALLOWED },
+ { TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
+@@ -105,6 +108,7 @@
+ { TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
+ { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
+ { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
++ { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
+ { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
+ #endif /* NSS_ENABLE_ECC */
+ { 0, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }
+Index: net/third_party/nss/ssl/ssl3con.c
+===================================================================
+--- net/third_party/nss/ssl/ssl3con.c (revision 215189)
++++ net/third_party/nss/ssl/ssl3con.c (working copy)
+@@ -78,6 +78,14 @@
+ static SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen,
+ int maxOutputLen, const unsigned char *input,
+ int inputLen);
++#ifndef NO_PKCS11_BYPASS
++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);
++#endif
+
+ #define MAX_SEND_BUF_LENGTH 32000 /* watch for 16-bit integer overflow */
+ #define MIN_SEND_BUF_LENGTH 4000
+@@ -90,6 +98,13 @@
+ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = {
+ /* cipher_suite policy enabled is_present*/
+ #ifdef NSS_ENABLE_ECC
++ { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
++ { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
++#endif /* NSS_ENABLE_ECC */
++ { TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE},
++ { TLS_RSA_WITH_AES_128_GCM_SHA256, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE},
++
++#ifdef NSS_ENABLE_ECC
+ { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
+ { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
+ #endif /* NSS_ENABLE_ECC */
+@@ -233,23 +248,30 @@
+
+ /* indexed by SSL3BulkCipher */
+ static const ssl3BulkCipherDef bulk_cipher_defs[] = {
+- /* cipher calg keySz secretSz type ivSz BlkSz keygen */
+- {cipher_null, calg_null, 0, 0, type_stream, 0, 0, kg_null},
+- {cipher_rc4, calg_rc4, 16, 16, type_stream, 0, 0, kg_strong},
+- {cipher_rc4_40, calg_rc4, 16, 5, type_stream, 0, 0, kg_export},
+- {cipher_rc4_56, calg_rc4, 16, 7, type_stream, 0, 0, kg_export},
+- {cipher_rc2, calg_rc2, 16, 16, type_block, 8, 8, kg_strong},
+- {cipher_rc2_40, calg_rc2, 16, 5, type_block, 8, 8, kg_export},
+- {cipher_des, calg_des, 8, 8, type_block, 8, 8, kg_strong},
+- {cipher_3des, calg_3des, 24, 24, type_block, 8, 8, kg_strong},
+- {cipher_des40, calg_des, 8, 5, type_block, 8, 8, kg_export},
+- {cipher_idea, calg_idea, 16, 16, type_block, 8, 8, kg_strong},
+- {cipher_aes_128, calg_aes, 16, 16, type_block, 16,16, kg_strong},
+- {cipher_aes_256, calg_aes, 32, 32, type_block, 16,16, kg_strong},
+- {cipher_camellia_128, calg_camellia,16, 16, type_block, 16,16, kg_strong},
+- {cipher_camellia_256, calg_camellia,32, 32, type_block, 16,16, kg_strong},
+- {cipher_seed, calg_seed, 16, 16, type_block, 16,16, kg_strong},
+- {cipher_missing, calg_null, 0, 0, type_stream, 0, 0, kg_null},
++ /* |--------- Lengths --------| */
++ /* cipher calg k s type i b t n */
++ /* e e v l a o */
++ /* y c | o g n */
++ /* | r | c | c */
++ /* | e | k | e */
++ /* | t | | | | */
++ {cipher_null, calg_null, 0, 0, type_stream, 0, 0, 0, 0},
++ {cipher_rc4, calg_rc4, 16,16, type_stream, 0, 0, 0, 0},
++ {cipher_rc4_40, calg_rc4, 16, 5, type_stream, 0, 0, 0, 0},
++ {cipher_rc4_56, calg_rc4, 16, 7, type_stream, 0, 0, 0, 0},
++ {cipher_rc2, calg_rc2, 16,16, type_block, 8, 8, 0, 0},
++ {cipher_rc2_40, calg_rc2, 16, 5, type_block, 8, 8, 0, 0},
++ {cipher_des, calg_des, 8, 8, type_block, 8, 8, 0, 0},
++ {cipher_3des, calg_3des, 24,24, type_block, 8, 8, 0, 0},
++ {cipher_des40, calg_des, 8, 5, type_block, 8, 8, 0, 0},
++ {cipher_idea, calg_idea, 16,16, type_block, 8, 8, 0, 0},
++ {cipher_aes_128, calg_aes, 16,16, type_block, 16,16, 0, 0},
++ {cipher_aes_256, calg_aes, 32,32, type_block, 16,16, 0, 0},
++ {cipher_camellia_128, calg_camellia, 16,16, type_block, 16,16, 0, 0},
++ {cipher_camellia_256, calg_camellia, 32,32, type_block, 16,16, 0, 0},
++ {cipher_seed, calg_seed, 16,16, type_block, 16,16, 0, 0},
++ {cipher_aes_128_gcm, calg_aes_gcm, 16,16, type_aead, 4, 0,16, 8},
++ {cipher_missing, calg_null, 0, 0, type_stream, 0, 0, 0, 0},
+ };
+
+ static const ssl3KEADef kea_defs[] =
+@@ -371,6 +393,11 @@
+ {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},
++
+ #ifdef NSS_ENABLE_ECC
+ {TLS_ECDH_ECDSA_WITH_NULL_SHA, cipher_null, mac_sha, kea_ecdh_ecdsa},
+ {TLS_ECDH_ECDSA_WITH_RC4_128_SHA, cipher_rc4, mac_sha, kea_ecdh_ecdsa},
+@@ -434,6 +461,7 @@
+ { calg_aes , CKM_AES_CBC },
+ { calg_camellia , CKM_CAMELLIA_CBC },
+ { calg_seed , CKM_SEED_CBC },
++ { calg_aes_gcm , CKM_AES_GCM },
+ /* { calg_init , (CK_MECHANISM_TYPE)0x7fffffffL } */
+ };
+
+@@ -472,6 +500,7 @@
+ "Camellia-128",
+ "Camellia-256",
+ "SEED-CBC",
++ "AES-128-GCM",
+ "missing"
+ };
+
+@@ -598,9 +627,13 @@
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
+ case TLS_RSA_WITH_AES_256_CBC_SHA256:
+ case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
++ case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+ case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
++ case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
++ case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+ case TLS_RSA_WITH_AES_128_CBC_SHA256:
++ case TLS_RSA_WITH_AES_128_GCM_SHA256:
+ case TLS_RSA_WITH_NULL_SHA256:
+ return version >= SSL_LIBRARY_VERSION_TLS_1_2;
+ default:
+@@ -1360,7 +1393,7 @@
+ cipher = suite_def->bulk_cipher_alg;
+ kea = suite_def->key_exchange_alg;
+ mac = suite_def->mac_alg;
+- if (mac <= ssl_mac_sha && isTLS)
++ if (mac <= ssl_mac_sha && mac != ssl_mac_null && isTLS)
+ mac += 2;
+
+ ss->ssl3.hs.suite_def = suite_def;
+@@ -1554,7 +1587,6 @@
+ unsigned int optArg2 = 0;
+ PRBool server_encrypts = ss->sec.isServer;
+ SSLCipherAlgorithm calg;
+- SSLCompressionMethod compression_method;
+ SECStatus rv;
+
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+@@ -1565,8 +1597,18 @@
+ cipher_def = pwSpec->cipher_def;
+
+ calg = cipher_def->calg;
+- compression_method = pwSpec->compression_method;
+
++ if (calg == calg_aes_gcm) {
++ pwSpec->encode = NULL;
++ pwSpec->decode = NULL;
++ pwSpec->destroy = NULL;
++ pwSpec->encodeContext = NULL;
++ pwSpec->decodeContext = NULL;
++ pwSpec->aead = ssl3_AESGCMBypass;
++ ssl3_InitCompressionContext(pwSpec);
++ return SECSuccess;
++ }
++
+ serverContext = pwSpec->server.cipher_context;
+ clientContext = pwSpec->client.cipher_context;
+
+@@ -1721,6 +1763,207 @@
+ return param;
+ }
+
++/* ssl3_BuildRecordPseudoHeader writes the TLS pseudo-header (the data which
++ * is included in the MAC) to |out| and returns its length. */
++static unsigned int
++ssl3_BuildRecordPseudoHeader(unsigned char *out,
++ SSL3SequenceNumber seq_num,
++ SSL3ContentType type,
++ PRBool includesVersion,
++ SSL3ProtocolVersion version,
++ PRBool isDTLS,
++ int length)
++{
++ out[0] = (unsigned char)(seq_num.high >> 24);
++ out[1] = (unsigned char)(seq_num.high >> 16);
++ out[2] = (unsigned char)(seq_num.high >> 8);
++ out[3] = (unsigned char)(seq_num.high >> 0);
++ out[4] = (unsigned char)(seq_num.low >> 24);
++ out[5] = (unsigned char)(seq_num.low >> 16);
++ out[6] = (unsigned char)(seq_num.low >> 8);
++ out[7] = (unsigned char)(seq_num.low >> 0);
++ out[8] = type;
++
++ /* SSL3 MAC doesn't include the record's version field. */
++ if (!includesVersion) {
++ out[9] = MSB(length);
++ out[10] = LSB(length);
++ return 11;
++ }
++
++ /* TLS MAC and AEAD additional data include version. */
++ if (isDTLS) {
++ SSL3ProtocolVersion dtls_version;
++
++ dtls_version = dtls_TLSVersionToDTLSVersion(version);
++ out[9] = MSB(dtls_version);
++ out[10] = LSB(dtls_version);
++ } else {
++ out[9] = MSB(version);
++ out[10] = LSB(version);
++ }
++ out[11] = MSB(length);
++ out[12] = LSB(length);
++ return 13;
++}
++
++static SECStatus
++ssl3_AESGCM(ssl3KeyMaterial *keys,
++ PRBool doDecrypt,
++ unsigned char *out,
++ int *outlen,
++ int maxout,
++ const unsigned char *in,
++ int inlen,
++ SSL3ContentType type,
++ SSL3ProtocolVersion version,
++ SSL3SequenceNumber seq_num)
++{
++ 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);
++ if (doDecrypt) {
++ memcpy(nonce + 4, in, explicitNonceLen);
++ in += explicitNonceLen;
++ inlen -= explicitNonceLen;
++ *outlen = 0;
++ } else {
++ if (maxout < explicitNonceLen) {
++ PORT_SetError(SEC_ERROR_INPUT_LEN);
++ return SECFailure;
++ }
++ /* Use the 64-bit sequence number as the explicit nonce. */
++ memcpy(nonce + 4, additionalData, explicitNonceLen);
++ memcpy(out, additionalData, explicitNonceLen);
++ out += explicitNonceLen;
++ maxout -= explicitNonceLen;
++ *outlen = explicitNonceLen;
++ }
++
++ param.type = siBuffer;
++ param.data = (unsigned char *) &gcmParams;
++ param.len = sizeof(gcmParams);
++ gcmParams.pIv = nonce;
++ gcmParams.ulIvLen = sizeof(nonce);
++ gcmParams.pAAD = additionalData;
++ gcmParams.ulAADLen = additionalDataLen;
++ gcmParams.ulTagBits = tagSize * 8;
++
++ if (doDecrypt) {
++ rv = PK11_Decrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
++ maxout, in, inlen);
++ } else {
++ rv = PK11_Encrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
++ maxout, in, inlen);
++ }
++ *outlen += (int) uOutLen;
++
++ return rv;
++}
++
++#ifndef NO_PKCS11_BYPASS
++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)
++{
++ SECStatus rv = SECFailure;
++ unsigned char nonce[12];
++ unsigned char additionalData[13];
++ unsigned int additionalDataLen;
++ unsigned int uOutLen;
++ AESContext *cx;
++ 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. */
++ PORT_Assert(keys->write_iv_item.len == 4);
++ if (keys->write_iv_item.len != 4) {
++ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
++ return SECFailure;
++ }
++ memcpy(nonce, keys->write_iv_item.data, 4);
++ if (doDecrypt) {
++ memcpy(nonce + 4, in, explicitNonceLen);
++ in += explicitNonceLen;
++ inlen -= explicitNonceLen;
++ *outlen = 0;
++ } else {
++ if (maxout < explicitNonceLen) {
++ PORT_SetError(SEC_ERROR_INPUT_LEN);
++ return SECFailure;
++ }
++ /* Use the 64-bit sequence number as the explicit nonce. */
++ memcpy(nonce + 4, additionalData, explicitNonceLen);
++ memcpy(out, additionalData, explicitNonceLen);
++ out += explicitNonceLen;
++ maxout -= explicitNonceLen;
++ *outlen = explicitNonceLen;
++ }
++
++ gcmParams.pIv = nonce;
++ gcmParams.ulIvLen = sizeof(nonce);
++ gcmParams.pAAD = additionalData;
++ gcmParams.ulAADLen = additionalDataLen;
++ gcmParams.ulTagBits = tagSize * 8;
++
++ cx = (AESContext *)keys->cipher_context;
++ rv = AES_InitContext(cx, keys->write_key_item.data,
++ keys->write_key_item.len,
++ (unsigned char *)&gcmParams, NSS_AES_GCM, !doDecrypt,
++ AES_BLOCK_SIZE);
++ if (rv != SECSuccess) {
++ return rv;
++ }
++ if (doDecrypt) {
++ rv = AES_Decrypt(cx, out, &uOutLen, maxout, in, inlen);
++ } else {
++ rv = AES_Encrypt(cx, out, &uOutLen, maxout, in, inlen);
++ }
++ AES_DestroyContext(cx, PR_FALSE);
++ *outlen += (int) uOutLen;
++
++ return rv;
++}
++#endif
++
+ /* Initialize encryption and MAC contexts for pending spec.
+ * Master Secret already is derived.
+ * Caller holds Spec write lock.
+@@ -1748,14 +1991,27 @@
+ pwSpec = ss->ssl3.pwSpec;
+ cipher_def = pwSpec->cipher_def;
+ macLength = pwSpec->mac_size;
++ calg = cipher_def->calg;
++ PORT_Assert(alg2Mech[calg].calg == calg);
+
++ pwSpec->client.write_mac_context = NULL;
++ pwSpec->server.write_mac_context = NULL;
++
++ if (calg == calg_aes_gcm) {
++ pwSpec->encode = NULL;
++ pwSpec->decode = NULL;
++ pwSpec->destroy = NULL;
++ pwSpec->encodeContext = NULL;
++ pwSpec->decodeContext = NULL;
++ pwSpec->aead = ssl3_AESGCM;
++ return SECSuccess;
++ }
++
+ /*
+ ** Now setup the MAC contexts,
+ ** crypto contexts are setup below.
+ */
+
+- pwSpec->client.write_mac_context = NULL;
+- pwSpec->server.write_mac_context = NULL;
+ mac_mech = pwSpec->mac_def->mmech;
+ mac_param.data = (unsigned char *)&macLength;
+ mac_param.len = sizeof(macLength);
+@@ -1778,9 +2034,6 @@
+ ** Now setup the crypto contexts.
+ */
+
+- calg = cipher_def->calg;
+- PORT_Assert(alg2Mech[calg].calg == calg);
+-
+ if (calg == calg_null) {
+ pwSpec->encode = Null_Cipher;
+ pwSpec->decode = Null_Cipher;
+@@ -1999,55 +2252,21 @@
+ {
+ const ssl3MACDef * mac_def;
+ SECStatus rv;
+-#ifndef NO_PKCS11_BYPASS
+ PRBool isTLS;
+-#endif
+ unsigned int tempLen;
+ unsigned char temp[MAX_MAC_LENGTH];
+
+- temp[0] = (unsigned char)(seq_num.high >> 24);
+- temp[1] = (unsigned char)(seq_num.high >> 16);
+- temp[2] = (unsigned char)(seq_num.high >> 8);
+- temp[3] = (unsigned char)(seq_num.high >> 0);
+- temp[4] = (unsigned char)(seq_num.low >> 24);
+- temp[5] = (unsigned char)(seq_num.low >> 16);
+- temp[6] = (unsigned char)(seq_num.low >> 8);
+- temp[7] = (unsigned char)(seq_num.low >> 0);
+- temp[8] = type;
+-
+ /* 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'v version value in the computation.
++ ** But, we use the record's version value in the computation.
+ */
+- if (spec->version <= SSL_LIBRARY_VERSION_3_0) {
+- temp[9] = MSB(inputLength);
+- temp[10] = LSB(inputLength);
+- tempLen = 11;
+-#ifndef NO_PKCS11_BYPASS
+- isTLS = PR_FALSE;
+-#endif
+- } else {
+- /* New TLS hash includes version. */
+- if (isDTLS) {
+- SSL3ProtocolVersion dtls_version;
++ isTLS = spec->version > SSL_LIBRARY_VERSION_3_0;
++ tempLen = ssl3_BuildRecordPseudoHeader(temp, seq_num, type, isTLS,
++ version, isDTLS, inputLength);
++ PORT_Assert(tempLen <= sizeof(temp));
+
+- dtls_version = dtls_TLSVersionToDTLSVersion(version);
+- temp[9] = MSB(dtls_version);
+- temp[10] = LSB(dtls_version);
+- } else {
+- temp[9] = MSB(version);
+- temp[10] = LSB(version);
+- }
+- temp[11] = MSB(inputLength);
+- temp[12] = LSB(inputLength);
+- tempLen = 13;
+-#ifndef NO_PKCS11_BYPASS
+- isTLS = PR_TRUE;
+-#endif
+- }
+-
+ PRINT_BUF(95, (NULL, "frag hash1: temp", temp, tempLen));
+ PRINT_BUF(95, (NULL, "frag hash1: input", input, inputLength));
+
+@@ -2390,86 +2609,112 @@
+ contentLen = outlen;
+ }
+
+- /*
+- * Add the MAC
+- */
+- rv = ssl3_ComputeRecordMAC( cwSpec, isServer, isDTLS,
+- type, cwSpec->version, cwSpec->write_seq_num, pIn, contentLen,
+- wrBuf->buf + headerLen + ivLen + contentLen, &macLen);
+- if (rv != SECSuccess) {
+- ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
+- return SECFailure;
+- }
+- p1Len = contentLen;
+- p2Len = macLen;
+- fragLen = contentLen + macLen; /* needs to be encrypted */
+- PORT_Assert(fragLen <= MAX_FRAGMENT_LENGTH + 1024);
++ if (cipher_def->type == type_aead) {
++ const int nonceLen = cipher_def->explicit_nonce_size;
++ const int tagLen = cipher_def->tag_size;
+
+- /*
+- * Pad the text (if we're doing a block cipher)
+- * then Encrypt it
+- */
+- if (cipher_def->type == type_block) {
+- unsigned char * pBuf;
+- int padding_length;
+- int i;
++ if (headerLen + nonceLen + contentLen + tagLen > wrBuf->space) {
++ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
++ return SECFailure;
++ }
+
+- oddLen = contentLen % cipher_def->block_size;
+- /* Assume blockSize is a power of two */
+- padding_length = cipher_def->block_size - 1 -
+- ((fragLen) & (cipher_def->block_size - 1));
+- fragLen += padding_length + 1;
+- PORT_Assert((fragLen % cipher_def->block_size) == 0);
+-
+- /* Pad according to TLS rules (also acceptable to SSL3). */
+- pBuf = &wrBuf->buf[headerLen + ivLen + fragLen - 1];
+- for (i = padding_length + 1; i > 0; --i) {
+- *pBuf-- = padding_length;
++ cipherBytes = contentLen;
++ rv = cwSpec->aead(
++ isServer ? &cwSpec->server : &cwSpec->client,
++ PR_FALSE, /* do encrypt */
++ wrBuf->buf + headerLen, /* output */
++ &cipherBytes, /* out len */
++ wrBuf->space - headerLen, /* max out */
++ pIn, contentLen, /* input */
++ type, cwSpec->version, cwSpec->write_seq_num);
++ if (rv != SECSuccess) {
++ PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
++ return SECFailure;
+ }
+- /* now, if contentLen is not a multiple of block size, fix it */
+- p2Len = fragLen - p1Len;
+- }
+- if (p1Len < 256) {
+- oddLen = p1Len;
+- p1Len = 0;
+ } else {
+- p1Len -= oddLen;
+- }
+- if (oddLen) {
+- p2Len += oddLen;
+- PORT_Assert( (cipher_def->block_size < 2) || \
+- (p2Len % cipher_def->block_size) == 0);
+- memmove(wrBuf->buf + headerLen + ivLen + p1Len, pIn + p1Len, oddLen);
+- }
+- if (p1Len > 0) {
+- int cipherBytesPart1 = -1;
+- rv = cwSpec->encode( cwSpec->encodeContext,
+- wrBuf->buf + headerLen + ivLen, /* output */
+- &cipherBytesPart1, /* actual outlen */
+- p1Len, /* max outlen */
+- pIn, p1Len); /* input, and inputlen */
+- PORT_Assert(rv == SECSuccess && cipherBytesPart1 == (int) p1Len);
+- if (rv != SECSuccess || cipherBytesPart1 != (int) p1Len) {
+- PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
++ /*
++ * Add the MAC
++ */
++ rv = ssl3_ComputeRecordMAC( cwSpec, isServer, isDTLS,
++ type, cwSpec->version, cwSpec->write_seq_num, pIn, contentLen,
++ wrBuf->buf + headerLen + ivLen + contentLen, &macLen);
++ if (rv != SECSuccess) {
++ ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
+ return SECFailure;
+ }
+- cipherBytes += cipherBytesPart1;
++ p1Len = contentLen;
++ p2Len = macLen;
++ fragLen = contentLen + macLen; /* needs to be encrypted */
++ PORT_Assert(fragLen <= MAX_FRAGMENT_LENGTH + 1024);
++
++ /*
++ * Pad the text (if we're doing a block cipher)
++ * then Encrypt it
++ */
++ if (cipher_def->type == type_block) {
++ unsigned char * pBuf;
++ int padding_length;
++ int i;
++
++ oddLen = contentLen % cipher_def->block_size;
++ /* Assume blockSize is a power of two */
++ padding_length = cipher_def->block_size - 1 -
++ ((fragLen) & (cipher_def->block_size - 1));
++ fragLen += padding_length + 1;
++ PORT_Assert((fragLen % cipher_def->block_size) == 0);
++
++ /* Pad according to TLS rules (also acceptable to SSL3). */
++ pBuf = &wrBuf->buf[headerLen + ivLen + fragLen - 1];
++ for (i = padding_length + 1; i > 0; --i) {
++ *pBuf-- = padding_length;
++ }
++ /* now, if contentLen is not a multiple of block size, fix it */
++ p2Len = fragLen - p1Len;
++ }
++ if (p1Len < 256) {
++ oddLen = p1Len;
++ p1Len = 0;
++ } else {
++ p1Len -= oddLen;
++ }
++ if (oddLen) {
++ p2Len += oddLen;
++ PORT_Assert( (cipher_def->block_size < 2) || \
++ (p2Len % cipher_def->block_size) == 0);
++ memmove(wrBuf->buf + headerLen + ivLen + p1Len, pIn + p1Len,
++ oddLen);
++ }
++ if (p1Len > 0) {
++ int cipherBytesPart1 = -1;
++ rv = cwSpec->encode( cwSpec->encodeContext,
++ wrBuf->buf + headerLen + ivLen, /* output */
++ &cipherBytesPart1, /* actual outlen */
++ p1Len, /* max outlen */
++ pIn, p1Len); /* input, and inputlen */
++ PORT_Assert(rv == SECSuccess && cipherBytesPart1 == (int) p1Len);
++ if (rv != SECSuccess || cipherBytesPart1 != (int) p1Len) {
++ PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
++ return SECFailure;
++ }
++ cipherBytes += cipherBytesPart1;
++ }
++ if (p2Len > 0) {
++ int cipherBytesPart2 = -1;
++ rv = cwSpec->encode( cwSpec->encodeContext,
++ wrBuf->buf + headerLen + ivLen + p1Len,
++ &cipherBytesPart2, /* output and actual outLen */
++ p2Len, /* max outlen */
++ wrBuf->buf + headerLen + ivLen + p1Len,
++ p2Len); /* input and inputLen*/
++ PORT_Assert(rv == SECSuccess && cipherBytesPart2 == (int) p2Len);
++ if (rv != SECSuccess || cipherBytesPart2 != (int) p2Len) {
++ PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
++ return SECFailure;
++ }
++ cipherBytes += cipherBytesPart2;
++ }
+ }
+- if (p2Len > 0) {
+- int cipherBytesPart2 = -1;
+- rv = cwSpec->encode( cwSpec->encodeContext,
+- wrBuf->buf + headerLen + ivLen + p1Len,
+- &cipherBytesPart2, /* output and actual outLen */
+- p2Len, /* max outlen */
+- wrBuf->buf + headerLen + ivLen + p1Len,
+- p2Len); /* input and inputLen*/
+- PORT_Assert(rv == SECSuccess && cipherBytesPart2 == (int) p2Len);
+- if (rv != SECSuccess || cipherBytesPart2 != (int) p2Len) {
+- PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
+- return SECFailure;
+- }
+- cipherBytes += cipherBytesPart2;
+- }
++
+ PORT_Assert(cipherBytes <= MAX_FRAGMENT_LENGTH + 1024);
+
+ wrBuf->len = cipherBytes + headerLen;
+@@ -3012,9 +3257,6 @@
+ static SECStatus
+ ssl3_IllegalParameter(sslSocket *ss)
+ {
+- PRBool isTLS;
+-
+- isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
+ (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
+ PORT_SetError(ss->sec.isServer ? SSL_ERROR_BAD_CLIENT
+ : SSL_ERROR_BAD_SERVER );
+@@ -3538,7 +3780,6 @@
+ }
+
+ key_material_params.bIsExport = (CK_BBOOL)(kea_def->is_limited);
+- /* was: (CK_BBOOL)(cipher_def->keygen_mode != kg_strong); */
+
+ key_material_params.RandomInfo.pClientRandom = cr;
+ key_material_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;
+@@ -9946,7 +10187,6 @@
+ static void
+ ssl3_RecordKeyLog(sslSocket *ss)
+ {
+- sslSessionID *sid;
+ SECStatus rv;
+ SECItem *keyData;
+ char buf[14 /* "CLIENT_RANDOM " */ +
+@@ -9958,8 +10198,6 @@
+
+ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+
+- sid = ss->sec.ci.sid;
+-
+ if (!ssl_keylog_iob)
+ return;
+
+@@ -11171,12 +11409,14 @@
+ /* With >= TLS 1.1, CBC records have an explicit IV. */
+ minLength += cipher_def->iv_size;
+ }
++ } else if (cipher_def->type == type_aead) {
++ minLength = cipher_def->explicit_nonce_size + cipher_def->tag_size;
+ }
+
+ /* We can perform this test in variable time because the record's total
+ * length and the ciphersuite are both public knowledge. */
+ if (cText->buf->len < minLength) {
+- goto decrypt_loser;
++ goto decrypt_loser;
+ }
+
+ if (cipher_def->type == type_block &&
+@@ -11244,78 +11484,95 @@
+ return SECFailure;
+ }
+
+- if (cipher_def->type == type_block &&
+- ((cText->buf->len - ivLen) % cipher_def->block_size) != 0) {
+- goto decrypt_loser;
+- }
++ rType = cText->type;
++ if (cipher_def->type == type_aead) {
++ rv = crSpec->aead(
++ ss->sec.isServer ? &crSpec->client : &crSpec->server,
++ PR_TRUE, /* do decrypt */
++ plaintext->buf, /* out */
++ (int*) &plaintext->len, /* outlen */
++ 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);
++ if (rv != SECSuccess) {
++ good = 0;
++ }
++ } else {
++ if (cipher_def->type == type_block &&
++ ((cText->buf->len - ivLen) % cipher_def->block_size) != 0) {
++ goto decrypt_loser;
++ }
+
+- /* decrypt from cText buf to plaintext. */
+- rv = crSpec->decode(
+- crSpec->decodeContext, plaintext->buf, (int *)&plaintext->len,
+- plaintext->space, cText->buf->buf + ivLen, cText->buf->len - ivLen);
+- if (rv != SECSuccess) {
+- goto decrypt_loser;
+- }
++ /* decrypt from cText buf to plaintext. */
++ rv = crSpec->decode(
++ crSpec->decodeContext, plaintext->buf, (int *)&plaintext->len,
++ plaintext->space, cText->buf->buf + ivLen, cText->buf->len - ivLen);
++ if (rv != SECSuccess) {
++ goto decrypt_loser;
++ }
+
+- PRINT_BUF(80, (ss, "cleartext:", plaintext->buf, plaintext->len));
++ PRINT_BUF(80, (ss, "cleartext:", plaintext->buf, plaintext->len));
+
+- originalLen = plaintext->len;
++ originalLen = plaintext->len;
+
+- /* If it's a block cipher, check and strip the padding. */
+- if (cipher_def->type == type_block) {
+- const unsigned int blockSize = cipher_def->block_size;
+- const unsigned int macSize = crSpec->mac_size;
++ /* If it's a block cipher, check and strip the padding. */
++ if (cipher_def->type == type_block) {
++ const unsigned int blockSize = cipher_def->block_size;
++ const unsigned int macSize = crSpec->mac_size;
+
+- if (crSpec->version <= SSL_LIBRARY_VERSION_3_0) {
+- good &= SECStatusToMask(ssl_RemoveSSLv3CBCPadding(
+- plaintext, blockSize, macSize));
+- } else {
+- good &= SECStatusToMask(ssl_RemoveTLSCBCPadding(
+- plaintext, macSize));
++ if (crSpec->version <= SSL_LIBRARY_VERSION_3_0) {
++ good &= SECStatusToMask(ssl_RemoveSSLv3CBCPadding(
++ plaintext, blockSize, macSize));
++ } else {
++ good &= SECStatusToMask(ssl_RemoveTLSCBCPadding(
++ plaintext, macSize));
++ }
+ }
+- }
+
+- /* compute the MAC */
+- rType = cText->type;
+- 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,
+- plaintext->buf, plaintext->len, originalLen,
+- hash, &hashBytes);
++ /* compute the MAC */
++ 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,
++ plaintext->buf, plaintext->len, originalLen,
++ hash, &hashBytes);
+
+- ssl_CBCExtractMAC(plaintext, originalLen, givenHashBuf,
+- crSpec->mac_size);
+- givenHash = givenHashBuf;
++ ssl_CBCExtractMAC(plaintext, originalLen, givenHashBuf,
++ crSpec->mac_size);
++ givenHash = givenHashBuf;
+
+- /* plaintext->len will always have enough space to remove the MAC
+- * because in ssl_Remove{SSLv3|TLS}CBCPadding we only adjust
+- * plaintext->len if the result has enough space for the MAC and we
+- * tested the unadjusted size against minLength, above. */
+- plaintext->len -= crSpec->mac_size;
+- } else {
+- /* This is safe because we checked the minLength above. */
+- plaintext->len -= crSpec->mac_size;
++ /* plaintext->len will always have enough space to remove the MAC
++ * because in ssl_Remove{SSLv3|TLS}CBCPadding we only adjust
++ * plaintext->len if the result has enough space for the MAC and we
++ * tested the unadjusted size against minLength, above. */
++ plaintext->len -= crSpec->mac_size;
++ } else {
++ /* This is safe because we checked the minLength above. */
++ 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);
++ 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);
+
+- /* We can read the MAC directly from the record because its location is
+- * public when a stream cipher is used. */
+- givenHash = plaintext->buf + plaintext->len;
+- }
++ /* We can read the MAC directly from the record because its location
++ * is public when a stream cipher is used. */
++ givenHash = plaintext->buf + plaintext->len;
++ }
+
+- good &= SECStatusToMask(rv);
++ good &= SECStatusToMask(rv);
+
+- if (hashBytes != (unsigned)crSpec->mac_size ||
+- NSS_SecureMemcmp(givenHash, hash, crSpec->mac_size) != 0) {
+- /* We're allowed to leak whether or not the MAC check was correct */
+- good = 0;
++ if (hashBytes != (unsigned)crSpec->mac_size ||
++ NSS_SecureMemcmp(givenHash, hash, crSpec->mac_size) != 0) {
++ /* We're allowed to leak whether or not the MAC check was correct */
++ good = 0;
++ }
+ }
+
+ if (good == 0) {
+Index: net/third_party/nss/ssl/sslenum.c
+===================================================================
+--- net/third_party/nss/ssl/sslenum.c (revision 215189)
++++ net/third_party/nss/ssl/sslenum.c (working copy)
+@@ -29,6 +29,14 @@
+ * Finally, update the ssl_V3_SUITES_IMPLEMENTED macro in sslimpl.h.
+ */
+ const PRUint16 SSL_ImplementedCiphers[] = {
++ /* AES-GCM */
++#ifdef NSS_ENABLE_ECC
++ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
++ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
++#endif /* NSS_ENABLE_ECC */
++ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
++ TLS_RSA_WITH_AES_128_GCM_SHA256,
++
+ /* 256-bit */
+ #ifdef NSS_ENABLE_ECC
+ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+Index: net/third_party/nss/ssl/sslproto.h
+===================================================================
+--- net/third_party/nss/ssl/sslproto.h (revision 215189)
++++ net/third_party/nss/ssl/sslproto.h (working copy)
+@@ -162,6 +162,10 @@
+
+ #define TLS_RSA_WITH_SEED_CBC_SHA 0x0096
+
++#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C
++#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x009E
++#define TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 0x00A2
++
+ /* TLS "Signaling Cipher Suite Value" (SCSV). May be requested by client.
+ * Must NEVER be chosen by server. SSL 3.0 server acknowledges by sending
+ * back an empty Renegotiation Info (RI) server hello extension.
+@@ -204,6 +208,11 @@
+ #define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023
+ #define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027
+
++#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B
++#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D
++#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F
++#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031
++
+ /* Netscape "experimental" cipher suites. */
+ #define SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA 0xffe0
+ #define SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA 0xffe1
+Index: net/third_party/nss/ssl/sslt.h
+===================================================================
+--- net/third_party/nss/ssl/sslt.h (revision 215189)
++++ net/third_party/nss/ssl/sslt.h (working copy)
+@@ -91,9 +91,10 @@
+ ssl_calg_3des = 4,
+ ssl_calg_idea = 5,
+ ssl_calg_fortezza = 6, /* deprecated, now unused */
+- ssl_calg_aes = 7, /* coming soon */
++ ssl_calg_aes = 7,
+ ssl_calg_camellia = 8,
+- ssl_calg_seed = 9
++ ssl_calg_seed = 9,
++ ssl_calg_aes_gcm = 10
+ } SSLCipherAlgorithm;
+
+ typedef enum {
+Index: net/third_party/nss/ssl/dtlscon.c
+===================================================================
+--- net/third_party/nss/ssl/dtlscon.c (revision 215189)
++++ net/third_party/nss/ssl/dtlscon.c (working copy)
+@@ -30,7 +30,14 @@
+
+ /* List copied from ssl3con.c:cipherSuites */
+ static const ssl3CipherSuite nonDTLSSuites[] = {
++ /* XXX Make AES-GCM work with DTLS. */
+ #ifdef NSS_ENABLE_ECC
++ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
++ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
++#endif /* NSS_ENABLE_ECC */
++ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
++ TLS_RSA_WITH_AES_128_GCM_SHA256,
++#ifdef NSS_ENABLE_ECC
+ TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+ TLS_ECDHE_RSA_WITH_RC4_128_SHA,
+ #endif /* NSS_ENABLE_ECC */
diff --git a/net/third_party/nss/patches/aesgcmchromium.patch b/net/third_party/nss/patches/aesgcmchromium.patch
new file mode 100644
index 0000000..8cd72bb
--- /dev/null
+++ b/net/third_party/nss/patches/aesgcmchromium.patch
@@ -0,0 +1,117 @@
+--- net/third_party/nss/ssl/ssl3con.c.orig 2013-08-14 14:22:50.479780305 -0700
++++ net/third_party/nss/ssl/ssl3con.c 2013-08-14 14:23:57.670788603 -0700
+@@ -44,6 +44,9 @@
+ #ifdef NSS_ENABLE_ZLIB
+ #include "zlib.h"
+ #endif
++#ifdef LINUX
++#include <dlfcn.h>
++#endif
+
+ #ifndef PK11_SETATTRS
+ #define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \
+@@ -1807,6 +1810,69 @@ ssl3_BuildRecordPseudoHeader(unsigned ch
+ return 13;
+ }
+
++typedef SECStatus (*PK11CryptFcn)(
++ PK11SymKey *symKey, CK_MECHANISM_TYPE mechanism, SECItem *param,
++ unsigned char *out, unsigned int *outLen, unsigned int maxLen,
++ const unsigned char *in, unsigned int inLen);
++
++static PK11CryptFcn pk11_encrypt = NULL;
++static PK11CryptFcn pk11_decrypt = NULL;
++
++static PRCallOnceType resolvePK11CryptOnce;
++
++static PRStatus
++ssl3_ResolvePK11CryptFunctions(void)
++{
++#ifdef LINUX
++ /* On Linux we use the system NSS libraries. Look up the PK11_Encrypt and
++ * PK11_Decrypt functions at run time. */
++ void *handle = dlopen(NULL, RTLD_LAZY);
++ if (!handle) {
++ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
++ return PR_FAILURE;
++ }
++ pk11_encrypt = (PK11CryptFcn)dlsym(handle, "PK11_Encrypt");
++ pk11_decrypt = (PK11CryptFcn)dlsym(handle, "PK11_Decrypt");
++ dlclose(handle);
++ return PR_SUCCESS;
++#else
++ /* On other platforms we use our own copy of NSS. PK11_Encrypt and
++ * PK11_Decrypt are known to be available. */
++ pk11_encrypt = PK11_Encrypt;
++ pk11_decrypt = PK11_Decrypt;
++ return PR_SUCCESS;
++#endif
++}
++
++/*
++ * In NSS 3.15, PK11_Encrypt and PK11_Decrypt were added to provide access
++ * to the AES GCM implementation in the NSS softoken. So the presence of
++ * these two functions implies the NSS version supports AES GCM.
++ */
++static PRBool
++ssl3_HasGCMSupport(void)
++{
++ (void)PR_CallOnce(&resolvePK11CryptOnce, ssl3_ResolvePK11CryptFunctions);
++ return pk11_encrypt != NULL;
++}
++
++/* On this socket, disable the GCM cipher suites */
++SECStatus
++ssl3_DisableGCMSuites(sslSocket * ss)
++{
++ unsigned int i;
++
++ for (i = 0; i < PR_ARRAY_SIZE(cipher_suite_defs); i++) {
++ const ssl3CipherSuiteDef *cipher_def = &cipher_suite_defs[i];
++ if (cipher_def->bulk_cipher_alg == cipher_aes_128_gcm) {
++ SECStatus rv = ssl3_CipherPrefSet(ss, cipher_def->cipher_suite,
++ PR_FALSE);
++ PORT_Assert(rv == SECSuccess); /* else is coding error */
++ }
++ }
++ return SECSuccess;
++}
++
+ static SECStatus
+ ssl3_AESGCM(ssl3KeyMaterial *keys,
+ PRBool doDecrypt,
+@@ -1869,10 +1935,10 @@ ssl3_AESGCM(ssl3KeyMaterial *keys,
+ gcmParams.ulTagBits = tagSize * 8;
+
+ if (doDecrypt) {
+- rv = PK11_Decrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
++ rv = pk11_decrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
+ maxout, in, inlen);
+ } else {
+- rv = PK11_Encrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
++ rv = pk11_encrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
+ maxout, in, inlen);
+ }
+ *outlen += (int) uOutLen;
+@@ -5071,6 +5137,10 @@ ssl3_SendClientHello(sslSocket *ss, PRBo
+ ssl3_DisableNonDTLSSuites(ss);
+ }
+
++ if (!ssl3_HasGCMSupport()) {
++ ssl3_DisableGCMSuites(ss);
++ }
++
+ /* how many suites are permitted by policy and user preference? */
+ num_suites = count_cipher_suites(ss, ss->ssl3.policy, PR_TRUE);
+ if (!num_suites)
+@@ -7776,6 +7846,10 @@ ssl3_HandleClientHello(sslSocket *ss, SS
+ ssl3_DisableNonDTLSSuites(ss);
+ }
+
++ if (!ssl3_HasGCMSupport()) {
++ ssl3_DisableGCMSuites(ss);
++ }
++
+ #ifdef PARANOID
+ /* Look for a matching cipher suite. */
+ j = ssl3_config_match_init(ss);
diff --git a/net/third_party/nss/patches/applypatches.sh b/net/third_party/nss/patches/applypatches.sh
index e768a64..14377ac 100755
--- a/net/third_party/nss/patches/applypatches.sh
+++ b/net/third_party/nss/patches/applypatches.sh
@@ -47,3 +47,7 @@ patch -p4 < $patches_dir/tls12chromium.patch
patch -p4 < $patches_dir/alpn.patch
patch -p5 < $patches_dir/sslsock_903565.patch
+
+patch -p4 < $patches_dir/aesgcm.patch
+
+patch -p4 < $patches_dir/aesgcmchromium.patch
diff --git a/net/third_party/nss/ssl/dtlscon.c b/net/third_party/nss/ssl/dtlscon.c
index 78371e6..e86ae01 100644
--- a/net/third_party/nss/ssl/dtlscon.c
+++ b/net/third_party/nss/ssl/dtlscon.c
@@ -30,6 +30,13 @@ static const PRUint16 COMMON_MTU_VALUES[] = {
/* List copied from ssl3con.c:cipherSuites */
static const ssl3CipherSuite nonDTLSSuites[] = {
+ /* XXX Make AES-GCM work with DTLS. */
+#ifdef NSS_ENABLE_ECC
+ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+#endif /* NSS_ENABLE_ECC */
+ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
+ TLS_RSA_WITH_AES_128_GCM_SHA256,
#ifdef NSS_ENABLE_ECC
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
TLS_ECDHE_RSA_WITH_RC4_128_SHA,
diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c
index 98e31d4..e614eab 100644
--- a/net/third_party/nss/ssl/ssl3con.c
+++ b/net/third_party/nss/ssl/ssl3con.c
@@ -44,6 +44,9 @@
#ifdef NSS_ENABLE_ZLIB
#include "zlib.h"
#endif
+#ifdef LINUX
+#include <dlfcn.h>
+#endif
#ifndef PK11_SETATTRS
#define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \
@@ -78,6 +81,14 @@ static int ssl3_OIDToTLSHashAlgorithm(SECOidTag oid);
static SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen,
int maxOutputLen, const unsigned char *input,
int inputLen);
+#ifndef NO_PKCS11_BYPASS
+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);
+#endif
#define MAX_SEND_BUF_LENGTH 32000 /* watch for 16-bit integer overflow */
#define MIN_SEND_BUF_LENGTH 4000
@@ -90,6 +101,13 @@ static SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen,
static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = {
/* cipher_suite policy enabled is_present*/
#ifdef NSS_ENABLE_ECC
+ { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
+ { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
+#endif /* NSS_ENABLE_ECC */
+ { TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE},
+ { TLS_RSA_WITH_AES_128_GCM_SHA256, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE},
+
+#ifdef NSS_ENABLE_ECC
{ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
{ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
#endif /* NSS_ENABLE_ECC */
@@ -233,23 +251,30 @@ static SSL3Statistics ssl3stats;
/* indexed by SSL3BulkCipher */
static const ssl3BulkCipherDef bulk_cipher_defs[] = {
- /* cipher calg keySz secretSz type ivSz BlkSz keygen */
- {cipher_null, calg_null, 0, 0, type_stream, 0, 0, kg_null},
- {cipher_rc4, calg_rc4, 16, 16, type_stream, 0, 0, kg_strong},
- {cipher_rc4_40, calg_rc4, 16, 5, type_stream, 0, 0, kg_export},
- {cipher_rc4_56, calg_rc4, 16, 7, type_stream, 0, 0, kg_export},
- {cipher_rc2, calg_rc2, 16, 16, type_block, 8, 8, kg_strong},
- {cipher_rc2_40, calg_rc2, 16, 5, type_block, 8, 8, kg_export},
- {cipher_des, calg_des, 8, 8, type_block, 8, 8, kg_strong},
- {cipher_3des, calg_3des, 24, 24, type_block, 8, 8, kg_strong},
- {cipher_des40, calg_des, 8, 5, type_block, 8, 8, kg_export},
- {cipher_idea, calg_idea, 16, 16, type_block, 8, 8, kg_strong},
- {cipher_aes_128, calg_aes, 16, 16, type_block, 16,16, kg_strong},
- {cipher_aes_256, calg_aes, 32, 32, type_block, 16,16, kg_strong},
- {cipher_camellia_128, calg_camellia,16, 16, type_block, 16,16, kg_strong},
- {cipher_camellia_256, calg_camellia,32, 32, type_block, 16,16, kg_strong},
- {cipher_seed, calg_seed, 16, 16, type_block, 16,16, kg_strong},
- {cipher_missing, calg_null, 0, 0, type_stream, 0, 0, kg_null},
+ /* |--------- Lengths --------| */
+ /* cipher calg k s type i b t n */
+ /* e e v l a o */
+ /* y c | o g n */
+ /* | r | c | c */
+ /* | e | k | e */
+ /* | t | | | | */
+ {cipher_null, calg_null, 0, 0, type_stream, 0, 0, 0, 0},
+ {cipher_rc4, calg_rc4, 16,16, type_stream, 0, 0, 0, 0},
+ {cipher_rc4_40, calg_rc4, 16, 5, type_stream, 0, 0, 0, 0},
+ {cipher_rc4_56, calg_rc4, 16, 7, type_stream, 0, 0, 0, 0},
+ {cipher_rc2, calg_rc2, 16,16, type_block, 8, 8, 0, 0},
+ {cipher_rc2_40, calg_rc2, 16, 5, type_block, 8, 8, 0, 0},
+ {cipher_des, calg_des, 8, 8, type_block, 8, 8, 0, 0},
+ {cipher_3des, calg_3des, 24,24, type_block, 8, 8, 0, 0},
+ {cipher_des40, calg_des, 8, 5, type_block, 8, 8, 0, 0},
+ {cipher_idea, calg_idea, 16,16, type_block, 8, 8, 0, 0},
+ {cipher_aes_128, calg_aes, 16,16, type_block, 16,16, 0, 0},
+ {cipher_aes_256, calg_aes, 32,32, type_block, 16,16, 0, 0},
+ {cipher_camellia_128, calg_camellia, 16,16, type_block, 16,16, 0, 0},
+ {cipher_camellia_256, calg_camellia, 32,32, type_block, 16,16, 0, 0},
+ {cipher_seed, calg_seed, 16,16, type_block, 16,16, 0, 0},
+ {cipher_aes_128_gcm, calg_aes_gcm, 16,16, type_aead, 4, 0,16, 8},
+ {cipher_missing, calg_null, 0, 0, type_stream, 0, 0, 0, 0},
};
static const ssl3KEADef kea_defs[] =
@@ -371,6 +396,11 @@ static const ssl3CipherSuiteDef cipher_suite_defs[] =
{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},
+
#ifdef NSS_ENABLE_ECC
{TLS_ECDH_ECDSA_WITH_NULL_SHA, cipher_null, mac_sha, kea_ecdh_ecdsa},
{TLS_ECDH_ECDSA_WITH_RC4_128_SHA, cipher_rc4, mac_sha, kea_ecdh_ecdsa},
@@ -434,6 +464,7 @@ static const SSLCipher2Mech alg2Mech[] = {
{ calg_aes , CKM_AES_CBC },
{ calg_camellia , CKM_CAMELLIA_CBC },
{ calg_seed , CKM_SEED_CBC },
+ { calg_aes_gcm , CKM_AES_GCM },
/* { calg_init , (CK_MECHANISM_TYPE)0x7fffffffL } */
};
@@ -472,6 +503,7 @@ const char * const ssl3_cipherName[] = {
"Camellia-128",
"Camellia-256",
"SEED-CBC",
+ "AES-128-GCM",
"missing"
};
@@ -598,9 +630,13 @@ ssl3_CipherSuiteAllowedForVersion(ssl3CipherSuite cipherSuite,
case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
case TLS_RSA_WITH_AES_256_CBC_SHA256:
case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+ case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+ case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+ case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
case TLS_RSA_WITH_AES_128_CBC_SHA256:
+ case TLS_RSA_WITH_AES_128_GCM_SHA256:
case TLS_RSA_WITH_NULL_SHA256:
return version >= SSL_LIBRARY_VERSION_TLS_1_2;
default:
@@ -1360,7 +1396,7 @@ ssl3_SetupPendingCipherSpec(sslSocket *ss)
cipher = suite_def->bulk_cipher_alg;
kea = suite_def->key_exchange_alg;
mac = suite_def->mac_alg;
- if (mac <= ssl_mac_sha && isTLS)
+ if (mac <= ssl_mac_sha && mac != ssl_mac_null && isTLS)
mac += 2;
ss->ssl3.hs.suite_def = suite_def;
@@ -1554,7 +1590,6 @@ ssl3_InitPendingContextsBypass(sslSocket *ss)
unsigned int optArg2 = 0;
PRBool server_encrypts = ss->sec.isServer;
SSLCipherAlgorithm calg;
- SSLCompressionMethod compression_method;
SECStatus rv;
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
@@ -1565,7 +1600,17 @@ ssl3_InitPendingContextsBypass(sslSocket *ss)
cipher_def = pwSpec->cipher_def;
calg = cipher_def->calg;
- compression_method = pwSpec->compression_method;
+
+ if (calg == calg_aes_gcm) {
+ pwSpec->encode = NULL;
+ pwSpec->decode = NULL;
+ pwSpec->destroy = NULL;
+ pwSpec->encodeContext = NULL;
+ pwSpec->decodeContext = NULL;
+ pwSpec->aead = ssl3_AESGCMBypass;
+ ssl3_InitCompressionContext(pwSpec);
+ return SECSuccess;
+ }
serverContext = pwSpec->server.cipher_context;
clientContext = pwSpec->client.cipher_context;
@@ -1721,6 +1766,270 @@ ssl3_ParamFromIV(CK_MECHANISM_TYPE mtype, SECItem *iv, CK_ULONG ulEffectiveBits)
return param;
}
+/* ssl3_BuildRecordPseudoHeader writes the TLS pseudo-header (the data which
+ * is included in the MAC) to |out| and returns its length. */
+static unsigned int
+ssl3_BuildRecordPseudoHeader(unsigned char *out,
+ SSL3SequenceNumber seq_num,
+ SSL3ContentType type,
+ PRBool includesVersion,
+ SSL3ProtocolVersion version,
+ PRBool isDTLS,
+ int length)
+{
+ out[0] = (unsigned char)(seq_num.high >> 24);
+ out[1] = (unsigned char)(seq_num.high >> 16);
+ out[2] = (unsigned char)(seq_num.high >> 8);
+ out[3] = (unsigned char)(seq_num.high >> 0);
+ out[4] = (unsigned char)(seq_num.low >> 24);
+ out[5] = (unsigned char)(seq_num.low >> 16);
+ out[6] = (unsigned char)(seq_num.low >> 8);
+ out[7] = (unsigned char)(seq_num.low >> 0);
+ out[8] = type;
+
+ /* SSL3 MAC doesn't include the record's version field. */
+ if (!includesVersion) {
+ out[9] = MSB(length);
+ out[10] = LSB(length);
+ return 11;
+ }
+
+ /* TLS MAC and AEAD additional data include version. */
+ if (isDTLS) {
+ SSL3ProtocolVersion dtls_version;
+
+ dtls_version = dtls_TLSVersionToDTLSVersion(version);
+ out[9] = MSB(dtls_version);
+ out[10] = LSB(dtls_version);
+ } else {
+ out[9] = MSB(version);
+ out[10] = LSB(version);
+ }
+ out[11] = MSB(length);
+ out[12] = LSB(length);
+ return 13;
+}
+
+typedef SECStatus (*PK11CryptFcn)(
+ PK11SymKey *symKey, CK_MECHANISM_TYPE mechanism, SECItem *param,
+ unsigned char *out, unsigned int *outLen, unsigned int maxLen,
+ const unsigned char *in, unsigned int inLen);
+
+static PK11CryptFcn pk11_encrypt = NULL;
+static PK11CryptFcn pk11_decrypt = NULL;
+
+static PRCallOnceType resolvePK11CryptOnce;
+
+static PRStatus
+ssl3_ResolvePK11CryptFunctions(void)
+{
+#ifdef LINUX
+ /* On Linux we use the system NSS libraries. Look up the PK11_Encrypt and
+ * PK11_Decrypt functions at run time. */
+ void *handle = dlopen(NULL, RTLD_LAZY);
+ if (!handle) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return PR_FAILURE;
+ }
+ pk11_encrypt = (PK11CryptFcn)dlsym(handle, "PK11_Encrypt");
+ pk11_decrypt = (PK11CryptFcn)dlsym(handle, "PK11_Decrypt");
+ dlclose(handle);
+ return PR_SUCCESS;
+#else
+ /* On other platforms we use our own copy of NSS. PK11_Encrypt and
+ * PK11_Decrypt are known to be available. */
+ pk11_encrypt = PK11_Encrypt;
+ pk11_decrypt = PK11_Decrypt;
+ return PR_SUCCESS;
+#endif
+}
+
+/*
+ * In NSS 3.15, PK11_Encrypt and PK11_Decrypt were added to provide access
+ * to the AES GCM implementation in the NSS softoken. So the presence of
+ * these two functions implies the NSS version supports AES GCM.
+ */
+static PRBool
+ssl3_HasGCMSupport(void)
+{
+ (void)PR_CallOnce(&resolvePK11CryptOnce, ssl3_ResolvePK11CryptFunctions);
+ return pk11_encrypt != NULL;
+}
+
+/* On this socket, disable the GCM cipher suites */
+SECStatus
+ssl3_DisableGCMSuites(sslSocket * ss)
+{
+ unsigned int i;
+
+ for (i = 0; i < PR_ARRAY_SIZE(cipher_suite_defs); i++) {
+ const ssl3CipherSuiteDef *cipher_def = &cipher_suite_defs[i];
+ if (cipher_def->bulk_cipher_alg == cipher_aes_128_gcm) {
+ SECStatus rv = ssl3_CipherPrefSet(ss, cipher_def->cipher_suite,
+ PR_FALSE);
+ PORT_Assert(rv == SECSuccess); /* else is coding error */
+ }
+ }
+ return SECSuccess;
+}
+
+static SECStatus
+ssl3_AESGCM(ssl3KeyMaterial *keys,
+ PRBool doDecrypt,
+ unsigned char *out,
+ int *outlen,
+ int maxout,
+ const unsigned char *in,
+ int inlen,
+ SSL3ContentType type,
+ SSL3ProtocolVersion version,
+ SSL3SequenceNumber seq_num)
+{
+ 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);
+ if (doDecrypt) {
+ memcpy(nonce + 4, in, explicitNonceLen);
+ in += explicitNonceLen;
+ inlen -= explicitNonceLen;
+ *outlen = 0;
+ } else {
+ if (maxout < explicitNonceLen) {
+ PORT_SetError(SEC_ERROR_INPUT_LEN);
+ return SECFailure;
+ }
+ /* Use the 64-bit sequence number as the explicit nonce. */
+ memcpy(nonce + 4, additionalData, explicitNonceLen);
+ memcpy(out, additionalData, explicitNonceLen);
+ out += explicitNonceLen;
+ maxout -= explicitNonceLen;
+ *outlen = explicitNonceLen;
+ }
+
+ param.type = siBuffer;
+ param.data = (unsigned char *) &gcmParams;
+ param.len = sizeof(gcmParams);
+ gcmParams.pIv = nonce;
+ gcmParams.ulIvLen = sizeof(nonce);
+ gcmParams.pAAD = additionalData;
+ gcmParams.ulAADLen = additionalDataLen;
+ gcmParams.ulTagBits = tagSize * 8;
+
+ if (doDecrypt) {
+ rv = pk11_decrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
+ maxout, in, inlen);
+ } else {
+ rv = pk11_encrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
+ maxout, in, inlen);
+ }
+ *outlen += (int) uOutLen;
+
+ return rv;
+}
+
+#ifndef NO_PKCS11_BYPASS
+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)
+{
+ SECStatus rv = SECFailure;
+ unsigned char nonce[12];
+ unsigned char additionalData[13];
+ unsigned int additionalDataLen;
+ unsigned int uOutLen;
+ AESContext *cx;
+ 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. */
+ PORT_Assert(keys->write_iv_item.len == 4);
+ if (keys->write_iv_item.len != 4) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ memcpy(nonce, keys->write_iv_item.data, 4);
+ if (doDecrypt) {
+ memcpy(nonce + 4, in, explicitNonceLen);
+ in += explicitNonceLen;
+ inlen -= explicitNonceLen;
+ *outlen = 0;
+ } else {
+ if (maxout < explicitNonceLen) {
+ PORT_SetError(SEC_ERROR_INPUT_LEN);
+ return SECFailure;
+ }
+ /* Use the 64-bit sequence number as the explicit nonce. */
+ memcpy(nonce + 4, additionalData, explicitNonceLen);
+ memcpy(out, additionalData, explicitNonceLen);
+ out += explicitNonceLen;
+ maxout -= explicitNonceLen;
+ *outlen = explicitNonceLen;
+ }
+
+ gcmParams.pIv = nonce;
+ gcmParams.ulIvLen = sizeof(nonce);
+ gcmParams.pAAD = additionalData;
+ gcmParams.ulAADLen = additionalDataLen;
+ gcmParams.ulTagBits = tagSize * 8;
+
+ cx = (AESContext *)keys->cipher_context;
+ rv = AES_InitContext(cx, keys->write_key_item.data,
+ keys->write_key_item.len,
+ (unsigned char *)&gcmParams, NSS_AES_GCM, !doDecrypt,
+ AES_BLOCK_SIZE);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ if (doDecrypt) {
+ rv = AES_Decrypt(cx, out, &uOutLen, maxout, in, inlen);
+ } else {
+ rv = AES_Encrypt(cx, out, &uOutLen, maxout, in, inlen);
+ }
+ AES_DestroyContext(cx, PR_FALSE);
+ *outlen += (int) uOutLen;
+
+ return rv;
+}
+#endif
+
/* Initialize encryption and MAC contexts for pending spec.
* Master Secret already is derived.
* Caller holds Spec write lock.
@@ -1748,14 +2057,27 @@ ssl3_InitPendingContextsPKCS11(sslSocket *ss)
pwSpec = ss->ssl3.pwSpec;
cipher_def = pwSpec->cipher_def;
macLength = pwSpec->mac_size;
+ calg = cipher_def->calg;
+ PORT_Assert(alg2Mech[calg].calg == calg);
+
+ pwSpec->client.write_mac_context = NULL;
+ pwSpec->server.write_mac_context = NULL;
+
+ if (calg == calg_aes_gcm) {
+ pwSpec->encode = NULL;
+ pwSpec->decode = NULL;
+ pwSpec->destroy = NULL;
+ pwSpec->encodeContext = NULL;
+ pwSpec->decodeContext = NULL;
+ pwSpec->aead = ssl3_AESGCM;
+ return SECSuccess;
+ }
/*
** Now setup the MAC contexts,
** crypto contexts are setup below.
*/
- pwSpec->client.write_mac_context = NULL;
- pwSpec->server.write_mac_context = NULL;
mac_mech = pwSpec->mac_def->mmech;
mac_param.data = (unsigned char *)&macLength;
mac_param.len = sizeof(macLength);
@@ -1778,9 +2100,6 @@ ssl3_InitPendingContextsPKCS11(sslSocket *ss)
** Now setup the crypto contexts.
*/
- calg = cipher_def->calg;
- PORT_Assert(alg2Mech[calg].calg == calg);
-
if (calg == calg_null) {
pwSpec->encode = Null_Cipher;
pwSpec->decode = Null_Cipher;
@@ -1999,54 +2318,20 @@ ssl3_ComputeRecordMAC(
{
const ssl3MACDef * mac_def;
SECStatus rv;
-#ifndef NO_PKCS11_BYPASS
PRBool isTLS;
-#endif
unsigned int tempLen;
unsigned char temp[MAX_MAC_LENGTH];
- temp[0] = (unsigned char)(seq_num.high >> 24);
- temp[1] = (unsigned char)(seq_num.high >> 16);
- temp[2] = (unsigned char)(seq_num.high >> 8);
- temp[3] = (unsigned char)(seq_num.high >> 0);
- temp[4] = (unsigned char)(seq_num.low >> 24);
- temp[5] = (unsigned char)(seq_num.low >> 16);
- temp[6] = (unsigned char)(seq_num.low >> 8);
- temp[7] = (unsigned char)(seq_num.low >> 0);
- temp[8] = type;
-
/* 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'v version value in the computation.
+ ** But, we use the record's version value in the computation.
*/
- if (spec->version <= SSL_LIBRARY_VERSION_3_0) {
- temp[9] = MSB(inputLength);
- temp[10] = LSB(inputLength);
- tempLen = 11;
-#ifndef NO_PKCS11_BYPASS
- isTLS = PR_FALSE;
-#endif
- } else {
- /* New TLS hash includes version. */
- if (isDTLS) {
- SSL3ProtocolVersion dtls_version;
-
- dtls_version = dtls_TLSVersionToDTLSVersion(version);
- temp[9] = MSB(dtls_version);
- temp[10] = LSB(dtls_version);
- } else {
- temp[9] = MSB(version);
- temp[10] = LSB(version);
- }
- temp[11] = MSB(inputLength);
- temp[12] = LSB(inputLength);
- tempLen = 13;
-#ifndef NO_PKCS11_BYPASS
- isTLS = PR_TRUE;
-#endif
- }
+ 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: input", input, inputLength));
@@ -2390,86 +2675,112 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec,
contentLen = outlen;
}
- /*
- * Add the MAC
- */
- rv = ssl3_ComputeRecordMAC( cwSpec, isServer, isDTLS,
- type, cwSpec->version, cwSpec->write_seq_num, pIn, contentLen,
- wrBuf->buf + headerLen + ivLen + contentLen, &macLen);
- if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
- return SECFailure;
- }
- p1Len = contentLen;
- p2Len = macLen;
- fragLen = contentLen + macLen; /* needs to be encrypted */
- PORT_Assert(fragLen <= MAX_FRAGMENT_LENGTH + 1024);
+ if (cipher_def->type == type_aead) {
+ const int nonceLen = cipher_def->explicit_nonce_size;
+ const int tagLen = cipher_def->tag_size;
- /*
- * Pad the text (if we're doing a block cipher)
- * then Encrypt it
- */
- if (cipher_def->type == type_block) {
- unsigned char * pBuf;
- int padding_length;
- int i;
-
- oddLen = contentLen % cipher_def->block_size;
- /* Assume blockSize is a power of two */
- padding_length = cipher_def->block_size - 1 -
- ((fragLen) & (cipher_def->block_size - 1));
- fragLen += padding_length + 1;
- PORT_Assert((fragLen % cipher_def->block_size) == 0);
-
- /* Pad according to TLS rules (also acceptable to SSL3). */
- pBuf = &wrBuf->buf[headerLen + ivLen + fragLen - 1];
- for (i = padding_length + 1; i > 0; --i) {
- *pBuf-- = padding_length;
- }
- /* now, if contentLen is not a multiple of block size, fix it */
- p2Len = fragLen - p1Len;
- }
- if (p1Len < 256) {
- oddLen = p1Len;
- p1Len = 0;
- } else {
- p1Len -= oddLen;
- }
- if (oddLen) {
- p2Len += oddLen;
- PORT_Assert( (cipher_def->block_size < 2) || \
- (p2Len % cipher_def->block_size) == 0);
- memmove(wrBuf->buf + headerLen + ivLen + p1Len, pIn + p1Len, oddLen);
- }
- if (p1Len > 0) {
- int cipherBytesPart1 = -1;
- rv = cwSpec->encode( cwSpec->encodeContext,
- wrBuf->buf + headerLen + ivLen, /* output */
- &cipherBytesPart1, /* actual outlen */
- p1Len, /* max outlen */
- pIn, p1Len); /* input, and inputlen */
- PORT_Assert(rv == SECSuccess && cipherBytesPart1 == (int) p1Len);
- if (rv != SECSuccess || cipherBytesPart1 != (int) p1Len) {
- PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
+ if (headerLen + nonceLen + contentLen + tagLen > wrBuf->space) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
- cipherBytes += cipherBytesPart1;
- }
- if (p2Len > 0) {
- int cipherBytesPart2 = -1;
- rv = cwSpec->encode( cwSpec->encodeContext,
- wrBuf->buf + headerLen + ivLen + p1Len,
- &cipherBytesPart2, /* output and actual outLen */
- p2Len, /* max outlen */
- wrBuf->buf + headerLen + ivLen + p1Len,
- p2Len); /* input and inputLen*/
- PORT_Assert(rv == SECSuccess && cipherBytesPart2 == (int) p2Len);
- if (rv != SECSuccess || cipherBytesPart2 != (int) p2Len) {
+
+ cipherBytes = contentLen;
+ rv = cwSpec->aead(
+ isServer ? &cwSpec->server : &cwSpec->client,
+ PR_FALSE, /* do encrypt */
+ wrBuf->buf + headerLen, /* output */
+ &cipherBytes, /* out len */
+ wrBuf->space - headerLen, /* max out */
+ pIn, contentLen, /* input */
+ type, cwSpec->version, cwSpec->write_seq_num);
+ if (rv != SECSuccess) {
PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
return SECFailure;
}
- cipherBytes += cipherBytesPart2;
- }
+ } else {
+ /*
+ * Add the MAC
+ */
+ rv = ssl3_ComputeRecordMAC( cwSpec, isServer, isDTLS,
+ type, cwSpec->version, cwSpec->write_seq_num, pIn, contentLen,
+ wrBuf->buf + headerLen + ivLen + contentLen, &macLen);
+ if (rv != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
+ return SECFailure;
+ }
+ p1Len = contentLen;
+ p2Len = macLen;
+ fragLen = contentLen + macLen; /* needs to be encrypted */
+ PORT_Assert(fragLen <= MAX_FRAGMENT_LENGTH + 1024);
+
+ /*
+ * Pad the text (if we're doing a block cipher)
+ * then Encrypt it
+ */
+ if (cipher_def->type == type_block) {
+ unsigned char * pBuf;
+ int padding_length;
+ int i;
+
+ oddLen = contentLen % cipher_def->block_size;
+ /* Assume blockSize is a power of two */
+ padding_length = cipher_def->block_size - 1 -
+ ((fragLen) & (cipher_def->block_size - 1));
+ fragLen += padding_length + 1;
+ PORT_Assert((fragLen % cipher_def->block_size) == 0);
+
+ /* Pad according to TLS rules (also acceptable to SSL3). */
+ pBuf = &wrBuf->buf[headerLen + ivLen + fragLen - 1];
+ for (i = padding_length + 1; i > 0; --i) {
+ *pBuf-- = padding_length;
+ }
+ /* now, if contentLen is not a multiple of block size, fix it */
+ p2Len = fragLen - p1Len;
+ }
+ if (p1Len < 256) {
+ oddLen = p1Len;
+ p1Len = 0;
+ } else {
+ p1Len -= oddLen;
+ }
+ if (oddLen) {
+ p2Len += oddLen;
+ PORT_Assert( (cipher_def->block_size < 2) || \
+ (p2Len % cipher_def->block_size) == 0);
+ memmove(wrBuf->buf + headerLen + ivLen + p1Len, pIn + p1Len,
+ oddLen);
+ }
+ if (p1Len > 0) {
+ int cipherBytesPart1 = -1;
+ rv = cwSpec->encode( cwSpec->encodeContext,
+ wrBuf->buf + headerLen + ivLen, /* output */
+ &cipherBytesPart1, /* actual outlen */
+ p1Len, /* max outlen */
+ pIn, p1Len); /* input, and inputlen */
+ PORT_Assert(rv == SECSuccess && cipherBytesPart1 == (int) p1Len);
+ if (rv != SECSuccess || cipherBytesPart1 != (int) p1Len) {
+ PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
+ return SECFailure;
+ }
+ cipherBytes += cipherBytesPart1;
+ }
+ if (p2Len > 0) {
+ int cipherBytesPart2 = -1;
+ rv = cwSpec->encode( cwSpec->encodeContext,
+ wrBuf->buf + headerLen + ivLen + p1Len,
+ &cipherBytesPart2, /* output and actual outLen */
+ p2Len, /* max outlen */
+ wrBuf->buf + headerLen + ivLen + p1Len,
+ p2Len); /* input and inputLen*/
+ PORT_Assert(rv == SECSuccess && cipherBytesPart2 == (int) p2Len);
+ if (rv != SECSuccess || cipherBytesPart2 != (int) p2Len) {
+ PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
+ return SECFailure;
+ }
+ cipherBytes += cipherBytesPart2;
+ }
+ }
+
PORT_Assert(cipherBytes <= MAX_FRAGMENT_LENGTH + 1024);
wrBuf->len = cipherBytes + headerLen;
@@ -3012,9 +3323,6 @@ SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level, SSL3AlertDescription desc)
static SECStatus
ssl3_IllegalParameter(sslSocket *ss)
{
- PRBool isTLS;
-
- isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
(void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
PORT_SetError(ss->sec.isServer ? SSL_ERROR_BAD_CLIENT
: SSL_ERROR_BAD_SERVER );
@@ -3538,7 +3846,6 @@ ssl3_DeriveConnectionKeysPKCS11(sslSocket *ss)
}
key_material_params.bIsExport = (CK_BBOOL)(kea_def->is_limited);
- /* was: (CK_BBOOL)(cipher_def->keygen_mode != kg_strong); */
key_material_params.RandomInfo.pClientRandom = cr;
key_material_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;
@@ -4830,6 +5137,10 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
ssl3_DisableNonDTLSSuites(ss);
}
+ if (!ssl3_HasGCMSupport()) {
+ ssl3_DisableGCMSuites(ss);
+ }
+
/* how many suites are permitted by policy and user preference? */
num_suites = count_cipher_suites(ss, ss->ssl3.policy, PR_TRUE);
if (!num_suites)
@@ -7535,6 +7846,10 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
ssl3_DisableNonDTLSSuites(ss);
}
+ if (!ssl3_HasGCMSupport()) {
+ ssl3_DisableGCMSuites(ss);
+ }
+
#ifdef PARANOID
/* Look for a matching cipher suite. */
j = ssl3_config_match_init(ss);
@@ -9946,7 +10261,6 @@ ssl3_SendNextProto(sslSocket *ss)
static void
ssl3_RecordKeyLog(sslSocket *ss)
{
- sslSessionID *sid;
SECStatus rv;
SECItem *keyData;
char buf[14 /* "CLIENT_RANDOM " */ +
@@ -9958,8 +10272,6 @@ ssl3_RecordKeyLog(sslSocket *ss)
PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
- sid = ss->sec.ci.sid;
-
if (!ssl_keylog_iob)
return;
@@ -11171,12 +11483,14 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf)
/* With >= TLS 1.1, CBC records have an explicit IV. */
minLength += cipher_def->iv_size;
}
+ } else if (cipher_def->type == type_aead) {
+ minLength = cipher_def->explicit_nonce_size + cipher_def->tag_size;
}
/* We can perform this test in variable time because the record's total
* length and the ciphersuite are both public knowledge. */
if (cText->buf->len < minLength) {
- goto decrypt_loser;
+ goto decrypt_loser;
}
if (cipher_def->type == type_block &&
@@ -11244,78 +11558,95 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf)
return SECFailure;
}
- if (cipher_def->type == type_block &&
- ((cText->buf->len - ivLen) % cipher_def->block_size) != 0) {
- goto decrypt_loser;
- }
+ rType = cText->type;
+ if (cipher_def->type == type_aead) {
+ rv = crSpec->aead(
+ ss->sec.isServer ? &crSpec->client : &crSpec->server,
+ PR_TRUE, /* do decrypt */
+ plaintext->buf, /* out */
+ (int*) &plaintext->len, /* outlen */
+ 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);
+ if (rv != SECSuccess) {
+ good = 0;
+ }
+ } else {
+ if (cipher_def->type == type_block &&
+ ((cText->buf->len - ivLen) % cipher_def->block_size) != 0) {
+ goto decrypt_loser;
+ }
- /* decrypt from cText buf to plaintext. */
- rv = crSpec->decode(
- crSpec->decodeContext, plaintext->buf, (int *)&plaintext->len,
- plaintext->space, cText->buf->buf + ivLen, cText->buf->len - ivLen);
- if (rv != SECSuccess) {
- goto decrypt_loser;
- }
+ /* decrypt from cText buf to plaintext. */
+ rv = crSpec->decode(
+ crSpec->decodeContext, plaintext->buf, (int *)&plaintext->len,
+ plaintext->space, cText->buf->buf + ivLen, cText->buf->len - ivLen);
+ if (rv != SECSuccess) {
+ goto decrypt_loser;
+ }
- PRINT_BUF(80, (ss, "cleartext:", plaintext->buf, plaintext->len));
+ PRINT_BUF(80, (ss, "cleartext:", plaintext->buf, plaintext->len));
- originalLen = plaintext->len;
+ originalLen = plaintext->len;
- /* If it's a block cipher, check and strip the padding. */
- if (cipher_def->type == type_block) {
- const unsigned int blockSize = cipher_def->block_size;
- const unsigned int macSize = crSpec->mac_size;
+ /* If it's a block cipher, check and strip the padding. */
+ if (cipher_def->type == type_block) {
+ const unsigned int blockSize = cipher_def->block_size;
+ const unsigned int macSize = crSpec->mac_size;
- if (crSpec->version <= SSL_LIBRARY_VERSION_3_0) {
- good &= SECStatusToMask(ssl_RemoveSSLv3CBCPadding(
- plaintext, blockSize, macSize));
- } else {
- good &= SECStatusToMask(ssl_RemoveTLSCBCPadding(
- plaintext, macSize));
+ if (crSpec->version <= SSL_LIBRARY_VERSION_3_0) {
+ good &= SECStatusToMask(ssl_RemoveSSLv3CBCPadding(
+ plaintext, blockSize, macSize));
+ } else {
+ good &= SECStatusToMask(ssl_RemoveTLSCBCPadding(
+ plaintext, macSize));
+ }
}
- }
- /* compute the MAC */
- rType = cText->type;
- 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,
- plaintext->buf, plaintext->len, originalLen,
- hash, &hashBytes);
-
- ssl_CBCExtractMAC(plaintext, originalLen, givenHashBuf,
- crSpec->mac_size);
- givenHash = givenHashBuf;
-
- /* plaintext->len will always have enough space to remove the MAC
- * because in ssl_Remove{SSLv3|TLS}CBCPadding we only adjust
- * plaintext->len if the result has enough space for the MAC and we
- * tested the unadjusted size against minLength, above. */
- plaintext->len -= crSpec->mac_size;
- } else {
- /* This is safe because we checked the minLength above. */
- plaintext->len -= crSpec->mac_size;
+ /* compute the MAC */
+ 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,
+ plaintext->buf, plaintext->len, originalLen,
+ hash, &hashBytes);
+
+ ssl_CBCExtractMAC(plaintext, originalLen, givenHashBuf,
+ crSpec->mac_size);
+ givenHash = givenHashBuf;
+
+ /* plaintext->len will always have enough space to remove the MAC
+ * because in ssl_Remove{SSLv3|TLS}CBCPadding we only adjust
+ * plaintext->len if the result has enough space for the MAC and we
+ * tested the unadjusted size against minLength, above. */
+ plaintext->len -= crSpec->mac_size;
+ } else {
+ /* This is safe because we checked the minLength above. */
+ 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);
+ 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);
- /* We can read the MAC directly from the record because its location is
- * public when a stream cipher is used. */
- givenHash = plaintext->buf + plaintext->len;
- }
+ /* We can read the MAC directly from the record because its location
+ * is public when a stream cipher is used. */
+ givenHash = plaintext->buf + plaintext->len;
+ }
- good &= SECStatusToMask(rv);
+ good &= SECStatusToMask(rv);
- if (hashBytes != (unsigned)crSpec->mac_size ||
- NSS_SecureMemcmp(givenHash, hash, crSpec->mac_size) != 0) {
- /* We're allowed to leak whether or not the MAC check was correct */
- good = 0;
+ if (hashBytes != (unsigned)crSpec->mac_size ||
+ NSS_SecureMemcmp(givenHash, hash, crSpec->mac_size) != 0) {
+ /* We're allowed to leak whether or not the MAC check was correct */
+ good = 0;
+ }
}
if (good == 0) {
diff --git a/net/third_party/nss/ssl/ssl3ecc.c b/net/third_party/nss/ssl/ssl3ecc.c
index 74995f1..a3638e7 100644
--- a/net/third_party/nss/ssl/ssl3ecc.c
+++ b/net/third_party/nss/ssl/ssl3ecc.c
@@ -911,6 +911,7 @@ static const ssl3CipherSuite ecdhe_ecdsa_suites[] = {
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_NULL_SHA,
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
@@ -921,6 +922,7 @@ static const ssl3CipherSuite ecdhe_rsa_suites[] = {
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_RSA_WITH_NULL_SHA,
TLS_ECDHE_RSA_WITH_RC4_128_SHA,
@@ -932,12 +934,14 @@ static const ssl3CipherSuite ecSuites[] = {
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_NULL_SHA,
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_RSA_WITH_NULL_SHA,
TLS_ECDHE_RSA_WITH_RC4_128_SHA,
diff --git a/net/third_party/nss/ssl/sslenum.c b/net/third_party/nss/ssl/sslenum.c
index b460f26..597ec07 100644
--- a/net/third_party/nss/ssl/sslenum.c
+++ b/net/third_party/nss/ssl/sslenum.c
@@ -29,6 +29,14 @@
* Finally, update the ssl_V3_SUITES_IMPLEMENTED macro in sslimpl.h.
*/
const PRUint16 SSL_ImplementedCiphers[] = {
+ /* AES-GCM */
+#ifdef NSS_ENABLE_ECC
+ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+#endif /* NSS_ENABLE_ECC */
+ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
+ TLS_RSA_WITH_AES_128_GCM_SHA256,
+
/* 256-bit */
#ifdef NSS_ENABLE_ECC
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
diff --git a/net/third_party/nss/ssl/sslimpl.h b/net/third_party/nss/ssl/sslimpl.h
index e6792b3..da302abe 100644
--- a/net/third_party/nss/ssl/sslimpl.h
+++ b/net/third_party/nss/ssl/sslimpl.h
@@ -64,6 +64,7 @@ typedef SSLSignType SSL3SignType;
#define calg_aes ssl_calg_aes
#define calg_camellia ssl_calg_camellia
#define calg_seed ssl_calg_seed
+#define calg_aes_gcm ssl_calg_aes_gcm
#define mac_null ssl_mac_null
#define mac_md5 ssl_mac_md5
@@ -290,9 +291,9 @@ typedef struct {
} ssl3CipherSuiteCfg;
#ifdef NSS_ENABLE_ECC
-#define ssl_V3_SUITES_IMPLEMENTED 57
+#define ssl_V3_SUITES_IMPLEMENTED 61
#else
-#define ssl_V3_SUITES_IMPLEMENTED 35
+#define ssl_V3_SUITES_IMPLEMENTED 37
#endif /* NSS_ENABLE_ECC */
#define MAX_DTLS_SRTP_CIPHER_SUITES 4
@@ -440,20 +441,6 @@ struct sslGatherStr {
#define GS_DATA 3
#define GS_PAD 4
-typedef SECStatus (*SSLCipher)(void * context,
- unsigned char * out,
- int * outlen,
- int maxout,
- const unsigned char *in,
- int inlen);
-typedef SECStatus (*SSLCompressor)(void * context,
- unsigned char * out,
- int * outlen,
- int maxout,
- const unsigned char *in,
- int inlen);
-typedef SECStatus (*SSLDestroy)(void *context, PRBool freeit);
-
#if defined(NSS_PLATFORM_CLIENT_AUTH) && defined(XP_WIN32)
typedef PCERT_KEY_CONTEXT PlatformKey;
#elif defined(NSS_PLATFORM_CLIENT_AUTH) && defined(XP_MACOSX)
@@ -485,11 +472,12 @@ typedef enum {
cipher_camellia_128,
cipher_camellia_256,
cipher_seed,
+ cipher_aes_128_gcm,
cipher_missing /* reserved for no such supported cipher */
/* This enum must match ssl3_cipherName[] in ssl3con.c. */
} SSL3BulkCipher;
-typedef enum { type_stream, type_block } CipherType;
+typedef enum { type_stream, type_block, type_aead } CipherType;
#define MAX_IV_LENGTH 24
@@ -531,6 +519,31 @@ typedef struct {
PRUint64 cipher_context[MAX_CIPHER_CONTEXT_LLONGS];
} ssl3KeyMaterial;
+typedef SECStatus (*SSLCipher)(void * context,
+ unsigned char * out,
+ int * outlen,
+ int maxout,
+ const unsigned char *in,
+ int inlen);
+typedef SECStatus (*SSLAEADCipher)(
+ ssl3KeyMaterial * keys,
+ PRBool doDecrypt,
+ unsigned char * out,
+ int * outlen,
+ int maxout,
+ const unsigned char *in,
+ int inlen,
+ SSL3ContentType type,
+ SSL3ProtocolVersion version,
+ SSL3SequenceNumber seqnum);
+typedef SECStatus (*SSLCompressor)(void * context,
+ unsigned char * out,
+ int * outlen,
+ int maxout,
+ const unsigned char *in,
+ int inlen);
+typedef SECStatus (*SSLDestroy)(void *context, PRBool freeit);
+
/* The DTLS anti-replay window. Defined here because we need it in
* the cipher spec. Note that this is a ring buffer but left and
* right represent the true window, with modular arithmetic used to
@@ -557,6 +570,7 @@ typedef struct {
int mac_size;
SSLCipher encode;
SSLCipher decode;
+ SSLAEADCipher aead;
SSLDestroy destroy;
void * encodeContext;
void * decodeContext;
@@ -706,8 +720,6 @@ typedef struct {
PRBool tls_keygen;
} ssl3KEADef;
-typedef enum { kg_null, kg_strong, kg_export } SSL3KeyGenMode;
-
/*
** There are tables of these, all const.
*/
@@ -719,7 +731,8 @@ struct ssl3BulkCipherDefStr {
CipherType type;
int iv_size;
int block_size;
- SSL3KeyGenMode keygen_mode;
+ int tag_size; /* authentication tag size for AEAD ciphers. */
+ int explicit_nonce_size; /* for AEAD ciphers. */
};
/*
diff --git a/net/third_party/nss/ssl/sslinfo.c b/net/third_party/nss/ssl/sslinfo.c
index d29fb0d..215731e 100644
--- a/net/third_party/nss/ssl/sslinfo.c
+++ b/net/third_party/nss/ssl/sslinfo.c
@@ -109,7 +109,7 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len)
#define K_ECDHE "ECDHE", kt_ecdh
#define C_SEED "SEED", calg_seed
-#define C_CAMELLIA "CAMELLIA", calg_camellia
+#define C_CAMELLIA "CAMELLIA", calg_camellia
#define C_AES "AES", calg_aes
#define C_RC4 "RC4", calg_rc4
#define C_RC2 "RC2", calg_rc2
@@ -117,6 +117,7 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len)
#define C_3DES "3DES", calg_3des
#define C_NULL "NULL", calg_null
#define C_SJ "SKIPJACK", calg_sj
+#define C_AESGCM "AES-GCM", calg_aes_gcm
#define B_256 256, 256, 256
#define B_128 128, 128, 128
@@ -130,9 +131,12 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len)
#define M_SHA256 "SHA256", ssl_hmac_sha256, 256
#define M_SHA "SHA1", ssl_mac_sha, 160
#define M_MD5 "MD5", ssl_mac_md5, 128
+#define M_NULL "NULL", ssl_mac_null, 0
static const SSLCipherSuiteInfo suiteInfo[] = {
/* <------ Cipher suite --------------------> <auth> <KEA> <bulk cipher> <MAC> <FIPS> */
+{0,CS(TLS_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_RSA, C_AESGCM, B_128, M_NULL, 1, 0, 0, },
+
{0,CS(TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_256, M_SHA, 0, 0, 0, },
{0,CS(TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_256, M_SHA, 0, 0, 0, },
{0,CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_DHE, C_AES, B_256, M_SHA256, 1, 0, 0, },
@@ -146,6 +150,7 @@ static const SSLCipherSuiteInfo suiteInfo[] = {
{0,CS(TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_128, M_SHA, 0, 0, 0, },
{0,CS(TLS_DHE_DSS_WITH_RC4_128_SHA), S_DSA, K_DHE, C_RC4, B_128, M_SHA, 0, 0, 0, },
{0,CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_DHE, C_AES, B_128, M_SHA256, 1, 0, 0, },
+{0,CS(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_DHE, C_AESGCM, B_128, M_NULL, 1, 0, 0, },
{0,CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_DHE, C_AES, B_128, M_SHA, 1, 0, 0, },
{0,CS(TLS_DHE_DSS_WITH_AES_128_CBC_SHA), S_DSA, K_DHE, C_AES, B_128, M_SHA, 1, 0, 0, },
{0,CS(TLS_RSA_WITH_SEED_CBC_SHA), S_RSA, K_RSA, C_SEED,B_128, M_SHA, 1, 0, 0, },
@@ -175,6 +180,9 @@ static const SSLCipherSuiteInfo suiteInfo[] = {
#ifdef NSS_ENABLE_ECC
/* ECC cipher suites */
+{0,CS(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_ECDHE, C_AESGCM, B_128, M_NULL, 1, 0, 0, },
+{0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), S_ECDSA, K_ECDHE, C_AESGCM, B_128, M_NULL, 1, 0, 0, },
+
{0,CS(TLS_ECDH_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDH, C_NULL, B_0, M_SHA, 0, 0, 0, },
{0,CS(TLS_ECDH_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDH, C_RC4, B_128, M_SHA, 0, 0, 0, },
{0,CS(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDH, C_3DES, B_3DES, M_SHA, 1, 0, 0, },
diff --git a/net/third_party/nss/ssl/sslproto.h b/net/third_party/nss/ssl/sslproto.h
index b037887..53bba01 100644
--- a/net/third_party/nss/ssl/sslproto.h
+++ b/net/third_party/nss/ssl/sslproto.h
@@ -162,6 +162,10 @@
#define TLS_RSA_WITH_SEED_CBC_SHA 0x0096
+#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C
+#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x009E
+#define TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 0x00A2
+
/* TLS "Signaling Cipher Suite Value" (SCSV). May be requested by client.
* Must NEVER be chosen by server. SSL 3.0 server acknowledges by sending
* back an empty Renegotiation Info (RI) server hello extension.
@@ -204,6 +208,11 @@
#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023
#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027
+#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B
+#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D
+#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F
+#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031
+
/* Netscape "experimental" cipher suites. */
#define SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA 0xffe0
#define SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA 0xffe1
diff --git a/net/third_party/nss/ssl/sslsock.c b/net/third_party/nss/ssl/sslsock.c
index db0da5f..c17c7a3 100644
--- a/net/third_party/nss/ssl/sslsock.c
+++ b/net/third_party/nss/ssl/sslsock.c
@@ -67,8 +67,10 @@ static cipherPolicy ssl_ciphers[] = { /* Export France */
{ TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
{ TLS_DHE_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
{ TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
+ { TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
{ TLS_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
{ TLS_RSA_WITH_AES_128_CBC_SHA256, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
+ { TLS_RSA_WITH_AES_128_GCM_SHA256, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
{ TLS_DHE_DSS_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
{ TLS_DHE_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
{ TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
@@ -94,6 +96,7 @@ static cipherPolicy ssl_ciphers[] = { /* Export France */
{ TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
{ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
{ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
+ { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
{ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
{ TLS_ECDH_RSA_WITH_NULL_SHA, SSL_ALLOWED, SSL_ALLOWED },
{ TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
@@ -105,6 +108,7 @@ static cipherPolicy ssl_ciphers[] = { /* Export France */
{ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
{ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
{ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
+ { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
{ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
#endif /* NSS_ENABLE_ECC */
{ 0, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }
diff --git a/net/third_party/nss/ssl/sslt.h b/net/third_party/nss/ssl/sslt.h
index 41d0113..f4be174 100644
--- a/net/third_party/nss/ssl/sslt.h
+++ b/net/third_party/nss/ssl/sslt.h
@@ -91,9 +91,10 @@ typedef enum {
ssl_calg_3des = 4,
ssl_calg_idea = 5,
ssl_calg_fortezza = 6, /* deprecated, now unused */
- ssl_calg_aes = 7, /* coming soon */
+ ssl_calg_aes = 7,
ssl_calg_camellia = 8,
- ssl_calg_seed = 9
+ ssl_calg_seed = 9,
+ ssl_calg_aes_gcm = 10
} SSLCipherAlgorithm;
typedef enum {