• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
2--- a/nss/lib/ssl/ssl3con.c	2014-01-17 18:04:43.127747463 -0800
3+++ b/nss/lib/ssl/ssl3con.c	2014-01-17 18:06:21.919386088 -0800
4@@ -44,6 +44,9 @@
5 #ifdef NSS_ENABLE_ZLIB
6 #include "zlib.h"
7 #endif
8+#ifdef LINUX
9+#include <dlfcn.h>
10+#endif
11
12 #ifndef PK11_SETATTRS
13 #define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \
14@@ -1842,6 +1845,69 @@ ssl3_BuildRecordPseudoHeader(unsigned ch
15     return 13;
16 }
17
18+typedef SECStatus (*PK11CryptFcn)(
19+    PK11SymKey *symKey, CK_MECHANISM_TYPE mechanism, SECItem *param,
20+    unsigned char *out, unsigned int *outLen, unsigned int maxLen,
21+    const unsigned char *in, unsigned int inLen);
22+
23+static PK11CryptFcn pk11_encrypt = NULL;
24+static PK11CryptFcn pk11_decrypt = NULL;
25+
26+static PRCallOnceType resolvePK11CryptOnce;
27+
28+static PRStatus
29+ssl3_ResolvePK11CryptFunctions(void)
30+{
31+#ifdef LINUX
32+    /* On Linux we use the system NSS libraries. Look up the PK11_Encrypt and
33+     * PK11_Decrypt functions at run time. */
34+    void *handle = dlopen(NULL, RTLD_LAZY);
35+    if (!handle) {
36+	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
37+	return PR_FAILURE;
38+    }
39+    pk11_encrypt = (PK11CryptFcn)dlsym(handle, "PK11_Encrypt");
40+    pk11_decrypt = (PK11CryptFcn)dlsym(handle, "PK11_Decrypt");
41+    dlclose(handle);
42+    return PR_SUCCESS;
43+#else
44+    /* On other platforms we use our own copy of NSS. PK11_Encrypt and
45+     * PK11_Decrypt are known to be available. */
46+    pk11_encrypt = PK11_Encrypt;
47+    pk11_decrypt = PK11_Decrypt;
48+    return PR_SUCCESS;
49+#endif
50+}
51+
52+/*
53+ * In NSS 3.15, PK11_Encrypt and PK11_Decrypt were added to provide access
54+ * to the AES GCM implementation in the NSS softoken. So the presence of
55+ * these two functions implies the NSS version supports AES GCM.
56+ */
57+static PRBool
58+ssl3_HasGCMSupport(void)
59+{
60+    (void)PR_CallOnce(&resolvePK11CryptOnce, ssl3_ResolvePK11CryptFunctions);
61+    return pk11_encrypt != NULL;
62+}
63+
64+/* On this socket, disable the GCM cipher suites */
65+SECStatus
66+ssl3_DisableGCMSuites(sslSocket * ss)
67+{
68+    unsigned int i;
69+
70+    for (i = 0; i < PR_ARRAY_SIZE(cipher_suite_defs); i++) {
71+	const ssl3CipherSuiteDef *cipher_def = &cipher_suite_defs[i];
72+	if (cipher_def->bulk_cipher_alg == cipher_aes_128_gcm) {
73+	    SECStatus rv = ssl3_CipherPrefSet(ss, cipher_def->cipher_suite,
74+					      PR_FALSE);
75+	    PORT_Assert(rv == SECSuccess); /* else is coding error */
76+	}
77+    }
78+    return SECSuccess;
79+}
80+
81 static SECStatus
82 ssl3_AESGCM(ssl3KeyMaterial *keys,
83 	    PRBool doDecrypt,
84@@ -1893,10 +1959,10 @@ ssl3_AESGCM(ssl3KeyMaterial *keys,
85     gcmParams.ulTagBits = tagSize * 8;
86
87     if (doDecrypt) {
88-	rv = PK11_Decrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
89+	rv = pk11_decrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
90 			  maxout, in, inlen);
91     } else {
92-	rv = PK11_Encrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
93+	rv = pk11_encrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
94 			  maxout, in, inlen);
95     }
96     *outlen += (int) uOutLen;
97@@ -5103,6 +5169,10 @@ ssl3_SendClientHello(sslSocket *ss, PRBo
98 	ssl3_DisableNonDTLSSuites(ss);
99     }
100
101+    if (!ssl3_HasGCMSupport()) {
102+	ssl3_DisableGCMSuites(ss);
103+    }
104+
105     /* how many suites are permitted by policy and user preference? */
106     num_suites = count_cipher_suites(ss, ss->ssl3.policy, PR_TRUE);
107     if (!num_suites) {
108@@ -8080,6 +8150,10 @@ ssl3_HandleClientHello(sslSocket *ss, SS
109 	ssl3_DisableNonDTLSSuites(ss);
110     }
111
112+    if (!ssl3_HasGCMSupport()) {
113+	ssl3_DisableGCMSuites(ss);
114+    }
115+
116 #ifdef PARANOID
117     /* Look for a matching cipher suite. */
118     j = ssl3_config_match_init(ss);
119