Index: net/third_party/nss/patches/aesgcm.patch |
=================================================================== |
--- net/third_party/nss/patches/aesgcm.patch (revision 0) |
+++ net/third_party/nss/patches/aesgcm.patch (revision 0) |
@@ -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 */ |