diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-22 15:41:45 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-22 15:41:45 +0000 |
commit | f95f89147dbc66f2b3c54f6e8179c9400607338c (patch) | |
tree | 4442cd54775f9eefc37844994b7f4306a2d17d23 /net/third_party | |
parent | a0d5eada2a9f69c41b0345dd670aaceb74c04cb9 (diff) | |
download | chromium_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.chromium | 5 | ||||
-rwxr-xr-x | net/third_party/nss/patches/applypatches.sh | 2 | ||||
-rw-r--r-- | net/third_party/nss/patches/secret_exporter.patch | 236 | ||||
-rw-r--r-- | net/third_party/nss/ssl/ssl.h | 11 | ||||
-rw-r--r-- | net/third_party/nss/ssl/ssl3con.c | 60 | ||||
-rw-r--r-- | net/third_party/nss/ssl/sslimpl.h | 6 | ||||
-rw-r--r-- | net/third_party/nss/ssl/sslinfo.c | 63 |
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) { |