summaryrefslogtreecommitdiffstats
path: root/net/third_party
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-22 15:41:45 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-22 15:41:45 +0000
commitf95f89147dbc66f2b3c54f6e8179c9400607338c (patch)
tree4442cd54775f9eefc37844994b7f4306a2d17d23 /net/third_party
parenta0d5eada2a9f69c41b0345dd670aaceb74c04cb9 (diff)
downloadchromium_src-f95f89147dbc66f2b3c54f6e8179c9400607338c.zip
chromium_src-f95f89147dbc66f2b3c54f6e8179c9400607338c.tar.gz
chromium_src-f95f89147dbc66f2b3c54f6e8179c9400607338c.tar.bz2
net: add NSS support for RFC 5705
(Keying Material Exporters for TLS). This is a reworked version of the patch from https://bugzilla.mozilla.org/show_bug.cgi?id=507359. BUG=none TEST=none yet Review URL: http://codereview.chromium.org/7464031 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93635 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/third_party')
-rw-r--r--net/third_party/nss/README.chromium5
-rwxr-xr-xnet/third_party/nss/patches/applypatches.sh2
-rw-r--r--net/third_party/nss/patches/secret_exporter.patch236
-rw-r--r--net/third_party/nss/ssl/ssl.h11
-rw-r--r--net/third_party/nss/ssl/ssl3con.c60
-rw-r--r--net/third_party/nss/ssl/sslimpl.h6
-rw-r--r--net/third_party/nss/ssl/sslinfo.c63
7 files changed, 361 insertions, 22 deletions
diff --git a/net/third_party/nss/README.chromium b/net/third_party/nss/README.chromium
index 7e241a1..0d2c4b4 100644
--- a/net/third_party/nss/README.chromium
+++ b/net/third_party/nss/README.chromium
@@ -59,6 +59,11 @@ Patches:
* Support origin bound certificates (http://balfanz.github.com/tls-obc-spec/draft-balfanz-tls-obc-00.txt)
patches/origin_bound_certs.patch
+ * Add a function to implement RFC 5705: Keying Material Exporters for TLS
+ This is a reworked version of the patch from
+ https://bugzilla.mozilla.org/show_bug.cgi?id=507359
+ patches/secret_exporter.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/applypatches.sh b/net/third_party/nss/patches/applypatches.sh
index c32b9a7..7124ca2 100755
--- a/net/third_party/nss/patches/applypatches.sh
+++ b/net/third_party/nss/patches/applypatches.sh
@@ -26,3 +26,5 @@ patch -p6 < $patches_dir/didhandshakeresume.patch
patch -p6 < $patches_dir/cbcrandomiv.patch
patch -p6 < $patches_dir/origin_bound_certs.patch
+
+patch -p6 < $patches_dir/secret_exporter.patch
diff --git a/net/third_party/nss/patches/secret_exporter.patch b/net/third_party/nss/patches/secret_exporter.patch
new file mode 100644
index 0000000..8e04252
--- /dev/null
+++ b/net/third_party/nss/patches/secret_exporter.patch
@@ -0,0 +1,236 @@
+commit 58913147a052b19246ac946077484d033d309287
+Author: Adam Langley <agl@chromium.org>
+Date: Thu Jul 21 11:34:32 2011 -0400
+
+ secret_extractor.patch
+
+diff --git a/mozilla/security/nss/lib/ssl/ssl.def b/mozilla/security/nss/lib/ssl/ssl.def
+index 7ef15db..1993d3e 100644
+--- a/mozilla/security/nss/lib/ssl/ssl.def
++++ b/mozilla/security/nss/lib/ssl/ssl.def
+@@ -154,6 +154,7 @@ SSL_SNISocketConfigHook;
+ ;+};
+ ;+NSS_CHROMIUM {
+ ;+ global:
++SSL_ExportKeyingMaterial;
+ SSL_GetNextProto;
+ SSL_GetStapledOCSPResponse;
+ SSL_HandshakeResumedSession;
+diff --git a/mozilla/security/nss/lib/ssl/ssl.h b/mozilla/security/nss/lib/ssl/ssl.h
+index 53ca301..1537aae 100644
+--- a/mozilla/security/nss/lib/ssl/ssl.h
++++ b/mozilla/security/nss/lib/ssl/ssl.h
+@@ -686,6 +686,17 @@ SSL_IMPORT SECStatus SSL_GetCipherSuiteInfo(PRUint16 cipherSuite,
+ /* Returnes negotiated through SNI host info. */
+ SSL_IMPORT SECItem *SSL_GetNegotiatedHostInfo(PRFileDesc *fd);
+
++/* Export keying material according to RFC 5705.
++** fd must correspond to a TLS 1.0 or higher socket and out must
++** already be allocated.
++*/
++SSL_IMPORT SECStatus SSL_ExportKeyingMaterial(PRFileDesc *fd,
++ const char *label,
++ const unsigned char *context,
++ unsigned int contextlen,
++ unsigned char *out,
++ unsigned int outlen);
++
+ /*
+ ** Return a new reference to the certificate that was most recently sent
+ ** to the peer on this SSL/TLS connection, or NULL if none has been sent.
+diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/ssl/ssl3con.c
+index c39b8f8..dee5555 100644
+--- a/mozilla/security/nss/lib/ssl/ssl3con.c
++++ b/mozilla/security/nss/lib/ssl/ssl3con.c
+@@ -8442,18 +8442,17 @@ ssl3_RestartHandshakeAfterServerCert(sslSocket *ss)
+ return rv;
+ }
+
+-static SECStatus
+-ssl3_ComputeTLSFinished(ssl3CipherSpec *spec,
+- PRBool isServer,
+- const SSL3Finished * hashes,
+- TLSFinished * tlsFinished)
++/* The calling function must acquire and release the appropriate lock (i.e.,
++ * ssl_GetSpecReadLock / ssl_ReleaseSpecReadLock for ss->ssl3.crSpec). Any
++ * label must already be concatenated onto the beginning of val.
++ */
++SECStatus
++ssl3_TLSPRFWithMasterSecret(ssl3CipherSpec *spec, const char *label,
++ unsigned int labelLen, const unsigned char *val, unsigned int valLen,
++ unsigned char *out, unsigned int outLen)
+ {
+- const char * label;
+- unsigned int len;
+- SECStatus rv;
+-
+- label = isServer ? "server finished" : "client finished";
+- len = 15;
++ SECStatus rv = SECSuccess;
++ unsigned int retLen;
+
+ if (spec->master_secret && !spec->bypassCiphers) {
+ SECItem param = {siBuffer, NULL, 0};
+@@ -8464,11 +8463,11 @@ ssl3_ComputeTLSFinished(ssl3CipherSpec *spec,
+ return SECFailure;
+
+ rv = PK11_DigestBegin(prf_context);
+- rv |= PK11_DigestOp(prf_context, (const unsigned char *) label, len);
+- rv |= PK11_DigestOp(prf_context, hashes->md5, sizeof *hashes);
+- rv |= PK11_DigestFinal(prf_context, tlsFinished->verify_data,
+- &len, sizeof tlsFinished->verify_data);
+- PORT_Assert(rv != SECSuccess || len == sizeof *tlsFinished);
++ rv |= PK11_DigestOp(prf_context, (unsigned char *) label, labelLen);
++ rv |= PK11_DigestOp(prf_context, val, valLen);
++ rv |= PK11_DigestFinal(prf_context, out,
++ &retLen, outLen);
++ PORT_Assert(rv != SECSuccess || retLen == outLen);
+
+ PK11_DestroyContext(prf_context, PR_TRUE);
+ } else {
+@@ -8477,17 +8476,34 @@ ssl3_ComputeTLSFinished(ssl3CipherSpec *spec,
+ SECItem outData = { siBuffer, };
+ PRBool isFIPS = PR_FALSE;
+
+- inData.data = (unsigned char *)hashes->md5;
+- inData.len = sizeof hashes[0];
+- outData.data = tlsFinished->verify_data;
+- outData.len = sizeof tlsFinished->verify_data;
++ inData.data = (unsigned char *) val;
++ inData.len = valLen;
++ outData.data = out;
++ outData.len = outLen;
+ rv = TLS_PRF(&spec->msItem, label, &inData, &outData, isFIPS);
+- PORT_Assert(rv != SECSuccess || \
+- outData.len == sizeof tlsFinished->verify_data);
++ PORT_Assert(rv != SECSuccess || outData.len == outLen);
+ }
+ return rv;
+ }
+
++static SECStatus
++ssl3_ComputeTLSFinished(ssl3CipherSpec *spec,
++ PRBool isServer,
++ const SSL3Finished * hashes,
++ TLSFinished * tlsFinished)
++{
++ const char * label;
++ SECStatus rv;
++
++ label = isServer ? "server finished" : "client finished";
++
++ rv = ssl3_TLSPRFWithMasterSecret(spec, label, 15, hashes->md5,
++ sizeof *hashes, tlsFinished->verify_data,
++ sizeof tlsFinished->verify_data);
++
++ return rv;
++}
++
+ /* called from ssl3_HandleServerHelloDone
+ */
+ static SECStatus
+diff --git a/mozilla/security/nss/lib/ssl/sslimpl.h b/mozilla/security/nss/lib/ssl/sslimpl.h
+index df30029..073616f 100644
+--- a/mozilla/security/nss/lib/ssl/sslimpl.h
++++ b/mozilla/security/nss/lib/ssl/sslimpl.h
+@@ -1726,6 +1726,12 @@ SECStatus SSL_DisableDefaultExportCipherSuites(void);
+ SECStatus SSL_DisableExportCipherSuites(PRFileDesc * fd);
+ PRBool SSL_IsExportCipherSuite(PRUint16 cipherSuite);
+
++SECStatus ssl3_TLSPRFWithMasterSecret(
++ ssl3CipherSpec *spec, const char *label,
++ unsigned int labelLen, const unsigned char *val,
++ unsigned int valLen, unsigned char *out,
++ unsigned int outLen);
++
+ /********************** FNV hash *********************/
+
+ void FNV1A64_Init(PRUint64 *digest);
+diff --git a/mozilla/security/nss/lib/ssl/sslinfo.c b/mozilla/security/nss/lib/ssl/sslinfo.c
+index 96377b0..9a58b4d 100644
+--- a/mozilla/security/nss/lib/ssl/sslinfo.c
++++ b/mozilla/security/nss/lib/ssl/sslinfo.c
+@@ -20,6 +20,7 @@
+ *
+ * Contributor(s):
+ * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
++ * Douglas Stebila <douglas@stebila.ca>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+@@ -38,6 +39,7 @@
+ #include "ssl.h"
+ #include "sslimpl.h"
+ #include "sslproto.h"
++#include "pk11func.h"
+
+ static const char *
+ ssl_GetCompressionMethodName(SSLCompressionMethod compression)
+@@ -316,6 +318,67 @@ SSL_IsExportCipherSuite(PRUint16 cipherSuite)
+ return PR_FALSE;
+ }
+
++/* Export keying material according to draft-ietf-tls-extractor-06.
++** fd must correspond to a TLS 1.0 or higher socket, out must
++** be already allocated.
++*/
++SECStatus
++SSL_ExportKeyingMaterial(PRFileDesc *fd, const char *label,
++ const unsigned char *context,
++ unsigned int contextLen,
++ unsigned char *out,
++ unsigned int outLen)
++{
++ sslSocket *ss;
++ unsigned char *val = NULL;
++ unsigned int valLen, i;
++ SECStatus rv = SECFailure;
++
++ ss = ssl_FindSocket(fd);
++ if (!ss) {
++ SSL_DBG(("%d: SSL[%d]: bad socket in ExportKeyingMaterial",
++ SSL_GETPID(), fd));
++ return SECFailure;
++ }
++
++ if (ss->version < SSL_LIBRARY_VERSION_3_1_TLS) {
++ PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
++ return SECFailure;
++ }
++
++ if (ss->ssl3.hs.ws != idle_handshake) {
++ PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED);
++ return SECFailure;
++ }
++
++ valLen = SSL3_RANDOM_LENGTH * 2;
++ if (contextLen > 0)
++ valLen += 2 /* uint16 length */ + contextLen;
++ val = PORT_Alloc(valLen);
++ if (val == NULL)
++ return SECFailure;
++ i = 0;
++ PORT_Memcpy(val + i, &ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH);
++ i += SSL3_RANDOM_LENGTH;
++ PORT_Memcpy(val + i, &ss->ssl3.hs.server_random.rand, SSL3_RANDOM_LENGTH);
++ i += SSL3_RANDOM_LENGTH;
++ if (contextLen > 0) {
++ val[i++] = contextLen >> 8;
++ val[i++] = contextLen;
++ PORT_Memcpy(val + i, context, contextLen);
++ i += contextLen;
++ }
++ PORT_Assert(i == valLen);
++
++ ssl_GetSpecReadLock(ss);
++ rv = ssl3_TLSPRFWithMasterSecret(ss->ssl3.crSpec, label, strlen(label), val, valLen, out, outLen);
++ ssl_ReleaseSpecReadLock(ss);
++
++ if (val != NULL)
++ PORT_ZFree(val, valLen);
++ return rv;
++}
++
+ SECItem*
+ SSL_GetNegotiatedHostInfo(PRFileDesc *fd)
+ {
diff --git a/net/third_party/nss/ssl/ssl.h b/net/third_party/nss/ssl/ssl.h
index 53ca301..1537aae 100644
--- a/net/third_party/nss/ssl/ssl.h
+++ b/net/third_party/nss/ssl/ssl.h
@@ -686,6 +686,17 @@ SSL_IMPORT SECStatus SSL_GetCipherSuiteInfo(PRUint16 cipherSuite,
/* Returnes negotiated through SNI host info. */
SSL_IMPORT SECItem *SSL_GetNegotiatedHostInfo(PRFileDesc *fd);
+/* Export keying material according to RFC 5705.
+** fd must correspond to a TLS 1.0 or higher socket and out must
+** already be allocated.
+*/
+SSL_IMPORT SECStatus SSL_ExportKeyingMaterial(PRFileDesc *fd,
+ const char *label,
+ const unsigned char *context,
+ unsigned int contextlen,
+ unsigned char *out,
+ unsigned int outlen);
+
/*
** Return a new reference to the certificate that was most recently sent
** to the peer on this SSL/TLS connection, or NULL if none has been sent.
diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c
index c39b8f8..dee5555 100644
--- a/net/third_party/nss/ssl/ssl3con.c
+++ b/net/third_party/nss/ssl/ssl3con.c
@@ -8442,18 +8442,17 @@ ssl3_RestartHandshakeAfterServerCert(sslSocket *ss)
return rv;
}
-static SECStatus
-ssl3_ComputeTLSFinished(ssl3CipherSpec *spec,
- PRBool isServer,
- const SSL3Finished * hashes,
- TLSFinished * tlsFinished)
+/* The calling function must acquire and release the appropriate lock (i.e.,
+ * ssl_GetSpecReadLock / ssl_ReleaseSpecReadLock for ss->ssl3.crSpec). Any
+ * label must already be concatenated onto the beginning of val.
+ */
+SECStatus
+ssl3_TLSPRFWithMasterSecret(ssl3CipherSpec *spec, const char *label,
+ unsigned int labelLen, const unsigned char *val, unsigned int valLen,
+ unsigned char *out, unsigned int outLen)
{
- const char * label;
- unsigned int len;
- SECStatus rv;
-
- label = isServer ? "server finished" : "client finished";
- len = 15;
+ SECStatus rv = SECSuccess;
+ unsigned int retLen;
if (spec->master_secret && !spec->bypassCiphers) {
SECItem param = {siBuffer, NULL, 0};
@@ -8464,11 +8463,11 @@ ssl3_ComputeTLSFinished(ssl3CipherSpec *spec,
return SECFailure;
rv = PK11_DigestBegin(prf_context);
- rv |= PK11_DigestOp(prf_context, (const unsigned char *) label, len);
- rv |= PK11_DigestOp(prf_context, hashes->md5, sizeof *hashes);
- rv |= PK11_DigestFinal(prf_context, tlsFinished->verify_data,
- &len, sizeof tlsFinished->verify_data);
- PORT_Assert(rv != SECSuccess || len == sizeof *tlsFinished);
+ rv |= PK11_DigestOp(prf_context, (unsigned char *) label, labelLen);
+ rv |= PK11_DigestOp(prf_context, val, valLen);
+ rv |= PK11_DigestFinal(prf_context, out,
+ &retLen, outLen);
+ PORT_Assert(rv != SECSuccess || retLen == outLen);
PK11_DestroyContext(prf_context, PR_TRUE);
} else {
@@ -8477,17 +8476,34 @@ ssl3_ComputeTLSFinished(ssl3CipherSpec *spec,
SECItem outData = { siBuffer, };
PRBool isFIPS = PR_FALSE;
- inData.data = (unsigned char *)hashes->md5;
- inData.len = sizeof hashes[0];
- outData.data = tlsFinished->verify_data;
- outData.len = sizeof tlsFinished->verify_data;
+ inData.data = (unsigned char *) val;
+ inData.len = valLen;
+ outData.data = out;
+ outData.len = outLen;
rv = TLS_PRF(&spec->msItem, label, &inData, &outData, isFIPS);
- PORT_Assert(rv != SECSuccess || \
- outData.len == sizeof tlsFinished->verify_data);
+ PORT_Assert(rv != SECSuccess || outData.len == outLen);
}
return rv;
}
+static SECStatus
+ssl3_ComputeTLSFinished(ssl3CipherSpec *spec,
+ PRBool isServer,
+ const SSL3Finished * hashes,
+ TLSFinished * tlsFinished)
+{
+ const char * label;
+ SECStatus rv;
+
+ label = isServer ? "server finished" : "client finished";
+
+ rv = ssl3_TLSPRFWithMasterSecret(spec, label, 15, hashes->md5,
+ sizeof *hashes, tlsFinished->verify_data,
+ sizeof tlsFinished->verify_data);
+
+ return rv;
+}
+
/* called from ssl3_HandleServerHelloDone
*/
static SECStatus
diff --git a/net/third_party/nss/ssl/sslimpl.h b/net/third_party/nss/ssl/sslimpl.h
index df30029..073616f 100644
--- a/net/third_party/nss/ssl/sslimpl.h
+++ b/net/third_party/nss/ssl/sslimpl.h
@@ -1726,6 +1726,12 @@ SECStatus SSL_DisableDefaultExportCipherSuites(void);
SECStatus SSL_DisableExportCipherSuites(PRFileDesc * fd);
PRBool SSL_IsExportCipherSuite(PRUint16 cipherSuite);
+SECStatus ssl3_TLSPRFWithMasterSecret(
+ ssl3CipherSpec *spec, const char *label,
+ unsigned int labelLen, const unsigned char *val,
+ unsigned int valLen, unsigned char *out,
+ unsigned int outLen);
+
/********************** FNV hash *********************/
void FNV1A64_Init(PRUint64 *digest);
diff --git a/net/third_party/nss/ssl/sslinfo.c b/net/third_party/nss/ssl/sslinfo.c
index 96377b0..9a58b4d 100644
--- a/net/third_party/nss/ssl/sslinfo.c
+++ b/net/third_party/nss/ssl/sslinfo.c
@@ -20,6 +20,7 @@
*
* Contributor(s):
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
+ * Douglas Stebila <douglas@stebila.ca>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -38,6 +39,7 @@
#include "ssl.h"
#include "sslimpl.h"
#include "sslproto.h"
+#include "pk11func.h"
static const char *
ssl_GetCompressionMethodName(SSLCompressionMethod compression)
@@ -316,6 +318,67 @@ SSL_IsExportCipherSuite(PRUint16 cipherSuite)
return PR_FALSE;
}
+/* Export keying material according to draft-ietf-tls-extractor-06.
+** fd must correspond to a TLS 1.0 or higher socket, out must
+** be already allocated.
+*/
+SECStatus
+SSL_ExportKeyingMaterial(PRFileDesc *fd, const char *label,
+ const unsigned char *context,
+ unsigned int contextLen,
+ unsigned char *out,
+ unsigned int outLen)
+{
+ sslSocket *ss;
+ unsigned char *val = NULL;
+ unsigned int valLen, i;
+ SECStatus rv = SECFailure;
+
+ ss = ssl_FindSocket(fd);
+ if (!ss) {
+ SSL_DBG(("%d: SSL[%d]: bad socket in ExportKeyingMaterial",
+ SSL_GETPID(), fd));
+ return SECFailure;
+ }
+
+ if (ss->version < SSL_LIBRARY_VERSION_3_1_TLS) {
+ PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
+ return SECFailure;
+ }
+
+ if (ss->ssl3.hs.ws != idle_handshake) {
+ PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED);
+ return SECFailure;
+ }
+
+ valLen = SSL3_RANDOM_LENGTH * 2;
+ if (contextLen > 0)
+ valLen += 2 /* uint16 length */ + contextLen;
+ val = PORT_Alloc(valLen);
+ if (val == NULL)
+ return SECFailure;
+ i = 0;
+ PORT_Memcpy(val + i, &ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH);
+ i += SSL3_RANDOM_LENGTH;
+ PORT_Memcpy(val + i, &ss->ssl3.hs.server_random.rand, SSL3_RANDOM_LENGTH);
+ i += SSL3_RANDOM_LENGTH;
+ if (contextLen > 0) {
+ val[i++] = contextLen >> 8;
+ val[i++] = contextLen;
+ PORT_Memcpy(val + i, context, contextLen);
+ i += contextLen;
+ }
+ PORT_Assert(i == valLen);
+
+ ssl_GetSpecReadLock(ss);
+ rv = ssl3_TLSPRFWithMasterSecret(ss->ssl3.crSpec, label, strlen(label), val, valLen, out, outLen);
+ ssl_ReleaseSpecReadLock(ss);
+
+ if (val != NULL)
+ PORT_ZFree(val, valLen);
+ return rv;
+}
+
SECItem*
SSL_GetNegotiatedHostInfo(PRFileDesc *fd)
{