diff options
author | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-15 00:51:34 +0000 |
---|---|---|
committer | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-15 00:51:34 +0000 |
commit | 80096fe8895efbbc7b0fe8ca1580b03e03c57f0e (patch) | |
tree | 663c6d406852517ee07346d1f3d45f93f8091326 | |
parent | 206a5f3ed884fd480fde01abca12c40d7886cf58 (diff) | |
download | chromium_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.cc | 5 | ||||
-rw-r--r-- | net/third_party/nss/README.chromium | 10 | ||||
-rw-r--r-- | net/third_party/nss/patches/aesgcm.patch | 1179 | ||||
-rw-r--r-- | net/third_party/nss/patches/aesgcmchromium.patch | 117 | ||||
-rwxr-xr-x | net/third_party/nss/patches/applypatches.sh | 4 | ||||
-rw-r--r-- | net/third_party/nss/ssl/dtlscon.c | 7 | ||||
-rw-r--r-- | net/third_party/nss/ssl/ssl3con.c | 745 | ||||
-rw-r--r-- | net/third_party/nss/ssl/ssl3ecc.c | 4 | ||||
-rw-r--r-- | net/third_party/nss/ssl/sslenum.c | 8 | ||||
-rw-r--r-- | net/third_party/nss/ssl/sslimpl.h | 53 | ||||
-rw-r--r-- | net/third_party/nss/ssl/sslinfo.c | 10 | ||||
-rw-r--r-- | net/third_party/nss/ssl/sslproto.h | 9 | ||||
-rw-r--r-- | net/third_party/nss/ssl/sslsock.c | 4 | ||||
-rw-r--r-- | net/third_party/nss/ssl/sslt.h | 5 |
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, ¶m, out, &uOutLen, ++ maxout, in, inlen); ++ } else { ++ rv = PK11_Encrypt(keys->write_key, CKM_AES_GCM, ¶m, 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, ¶m, out, &uOutLen, ++ rv = pk11_decrypt(keys->write_key, CKM_AES_GCM, ¶m, out, &uOutLen, + maxout, in, inlen); + } else { +- rv = PK11_Encrypt(keys->write_key, CKM_AES_GCM, ¶m, out, &uOutLen, ++ rv = pk11_encrypt(keys->write_key, CKM_AES_GCM, ¶m, 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, ¶m, out, &uOutLen, + maxout, in, inlen); + } else { + rv = pk11_encrypt(keys->write_key, CKM_AES_GCM, ¶m, 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 { |