diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-25 22:43:08 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-25 22:43:08 +0000 |
commit | a644b1135cb8a735d487cf210034abc6dd195bd3 (patch) | |
tree | 6aad1b77aa51a245d329ce0555f75b51c5a09926 /net | |
parent | 8072c7b6f31a761804abc8a3b98fbae346e4431a (diff) | |
download | chromium_src-a644b1135cb8a735d487cf210034abc6dd195bd3.zip chromium_src-a644b1135cb8a735d487cf210034abc6dd195bd3.tar.gz chromium_src-a644b1135cb8a735d487cf210034abc6dd195bd3.tar.bz2 |
NSS: add ability to get the tls-unique channel binding value.
BUG=129174
TEST=none
Review URL: https://chromiumcodereview.appspot.com/10649007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@144037 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/third_party/nss/README.chromium | 3 | ||||
-rwxr-xr-x | net/third_party/nss/patches/applypatches.sh | 2 | ||||
-rw-r--r-- | net/third_party/nss/patches/tlsunique.patch | 153 | ||||
-rw-r--r-- | net/third_party/nss/ssl/ssl.h | 21 | ||||
-rw-r--r-- | net/third_party/nss/ssl/ssl3con.c | 62 | ||||
-rw-r--r-- | net/third_party/nss/ssl/sslimpl.h | 5 | ||||
-rw-r--r-- | net/third_party/nss/ssl/sslsock.c | 21 |
7 files changed, 267 insertions, 0 deletions
diff --git a/net/third_party/nss/README.chromium b/net/third_party/nss/README.chromium index b92d6bc..b16bb66 100644 --- a/net/third_party/nss/README.chromium +++ b/net/third_party/nss/README.chromium @@ -78,6 +78,9 @@ Patches: https://bugzilla.mozilla.org/show_bug.cgi?id=766137 patches/getchannelinfo.patch + * Add support for extracting the tls-unique channel binding value + patches/tlsunique.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 2cf6f18..d0500c5 100755 --- a/net/third_party/nss/patches/applypatches.sh +++ b/net/third_party/nss/patches/applypatches.sh @@ -43,3 +43,5 @@ patch -p4 < $patches_dir/dtlssrtp.patch patch -p4 < $patches_dir/keylog.patch patch -p4 < $patches_dir/getchannelinfo.patch + +patch -p4 < $patches_dir/tlsunique.patch diff --git a/net/third_party/nss/patches/tlsunique.patch b/net/third_party/nss/patches/tlsunique.patch new file mode 100644 index 0000000..ed7fe49 --- /dev/null +++ b/net/third_party/nss/patches/tlsunique.patch @@ -0,0 +1,153 @@ +diff --git a/net/third_party/nss/ssl/ssl.h b/net/third_party/nss/ssl/ssl.h +index bb8c0b7..518cb21 100644 +--- a/net/third_party/nss/ssl/ssl.h ++++ b/net/third_party/nss/ssl/ssl.h +@@ -282,6 +282,27 @@ SSL_IMPORT SECStatus SSL_CipherPrefGetDefault(PRInt32 cipher, PRBool *enabled); + SSL_IMPORT SECStatus SSL_CipherPolicySet(PRInt32 cipher, PRInt32 policy); + SSL_IMPORT SECStatus SSL_CipherPolicyGet(PRInt32 cipher, PRInt32 *policy); + ++/* SSLChannelBindingType enumerates the types of supported channel binding ++ * values. See RFC 5929. */ ++typedef enum SSLChannelBindingType { ++ SSL_CHANNEL_BINDING_TLS_UNIQUE = 1, ++} SSLChannelBindingType; ++ ++/* SSL_GetChannelBinding copies the requested channel binding value, as defined ++ * in RFC 5929, into |out|. The full length of the binding value is written ++ * into |*outLen|. ++ * ++ * At most |outLenMax| bytes of data are copied. If |outLenMax| is ++ * insufficient then the function returns SECFailure and sets the error to ++ * SEC_ERROR_OUTPUT_LEN, but |*outLen| is still set. ++ * ++ * This call will fail if made during a renegotiation. */ ++SSL_IMPORT SECStatus SSL_GetChannelBinding(PRFileDesc *fd, ++ SSLChannelBindingType binding_type, ++ unsigned char *out, ++ unsigned int *outLen, ++ unsigned int outLenMax); ++ + /* SSL Version Range API + ** + ** This API should be used to control SSL 3.0 & TLS support instead of the +diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c +index 0f1cdc6..1f6def2 100644 +--- a/net/third_party/nss/ssl/ssl3con.c ++++ b/net/third_party/nss/ssl/ssl3con.c +@@ -10539,6 +10539,68 @@ ssl3_InitSocketPolicy(sslSocket *ss) + PORT_Memcpy(ss->cipherSuites, cipherSuites, sizeof cipherSuites); + } + ++SECStatus ++ssl3_GetTLSUniqueChannelBinding(sslSocket *ss, ++ unsigned char *out, ++ unsigned int *outLen, ++ unsigned int outLenMax) { ++ PRBool isTLS; ++ int index = 0; ++ unsigned int len; ++ SECStatus rv = SECFailure; ++ ++ *outLen = 0; ++ ++ ssl_GetSSL3HandshakeLock(ss); ++ ++ ssl_GetSpecReadLock(ss); ++ isTLS = (PRBool)(ss->ssl3.cwSpec->version > SSL_LIBRARY_VERSION_3_0); ++ ssl_ReleaseSpecReadLock(ss); ++ ++ /* The tls-unique channel binding is the first Finished structure in the ++ * handshake. In the case of a resumption, that's the server's Finished. ++ * Otherwise, it's the client's Finished. */ ++ len = ss->ssl3.hs.finishedBytes; ++ ++ /* Sending or receiving a Finished message will set finishedBytes to a ++ * non-zero value. */ ++ if (len == 0) { ++ PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED); ++ goto loser; ++ } ++ ++ /* If we are in the middle of a renegotiation then the channel binding ++ * value is poorly defined and depends on the direction that it will be ++ * used on. Therefore we simply return an error in this case. */ ++ if (ss->firstHsDone && ss->ssl3.hs.ws != idle_handshake) { ++ PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED); ++ goto loser; ++ } ++ ++ /* If resuming, then we want the second Finished value in the array, which ++ * is the server's */ ++ if (ss->ssl3.hs.isResuming) ++ index = 1; ++ ++ *outLen = len; ++ if (outLenMax < len) { ++ PORT_SetError(SEC_ERROR_OUTPUT_LEN); ++ goto loser; ++ } ++ ++ if (isTLS) { ++ memcpy(out, &ss->ssl3.hs.finishedMsgs.tFinished[index], len); ++ } else { ++ memcpy(out, &ss->ssl3.hs.finishedMsgs.sFinished[index], len); ++ } ++ ++ rv = SECSuccess; ++ ++loser: ++ ssl_ReleaseSSL3HandshakeLock(ss); ++ return rv; ++} ++ + /* ssl3_config_match_init must have already been called by + * the caller of this function. + */ +diff --git a/net/third_party/nss/ssl/sslimpl.h b/net/third_party/nss/ssl/sslimpl.h +index adad5d0..eda1885 100644 +--- a/net/third_party/nss/ssl/sslimpl.h ++++ b/net/third_party/nss/ssl/sslimpl.h +@@ -1775,6 +1775,11 @@ extern PRBool ssl_GetSessionTicketKeysPKCS11(SECKEYPrivateKey *svrPrivKey, + extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char* data, + unsigned int length); + ++extern SECStatus ssl3_GetTLSUniqueChannelBinding(sslSocket *ss, ++ unsigned char *out, ++ unsigned int *outLen, ++ unsigned int outLenMax); ++ + /* Construct a new NSPR socket for the app to use */ + extern PRFileDesc *ssl_NewPRSocket(sslSocket *ss, PRFileDesc *fd); + extern void ssl_FreePRSocket(PRFileDesc *fd); +diff --git a/net/third_party/nss/ssl/sslsock.c b/net/third_party/nss/ssl/sslsock.c +index 9387a21..1823a1c 100644 +--- a/net/third_party/nss/ssl/sslsock.c ++++ b/net/third_party/nss/ssl/sslsock.c +@@ -1382,6 +1382,27 @@ NSS_SetFrancePolicy(void) + return NSS_SetDomesticPolicy(); + } + ++SECStatus ++SSL_GetChannelBinding(PRFileDesc *fd, ++ SSLChannelBindingType binding_type, ++ unsigned char *out, ++ unsigned int *outLen, ++ unsigned int outLenMax) { ++ sslSocket *ss = ssl_FindSocket(fd); ++ ++ if (!ss) { ++ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelBinding", ++ SSL_GETPID(), fd)); ++ return SECFailure; ++ } ++ ++ if (binding_type != SSL_CHANNEL_BINDING_TLS_UNIQUE) { ++ PORT_SetError(PR_INVALID_ARGUMENT_ERROR); ++ return SECFailure; ++ } ++ ++ return ssl3_GetTLSUniqueChannelBinding(ss, out, outLen, outLenMax); ++} + + + /* LOCKS ??? XXX */ diff --git a/net/third_party/nss/ssl/ssl.h b/net/third_party/nss/ssl/ssl.h index bb8c0b7..518cb21 100644 --- a/net/third_party/nss/ssl/ssl.h +++ b/net/third_party/nss/ssl/ssl.h @@ -282,6 +282,27 @@ SSL_IMPORT SECStatus SSL_CipherPrefGetDefault(PRInt32 cipher, PRBool *enabled); SSL_IMPORT SECStatus SSL_CipherPolicySet(PRInt32 cipher, PRInt32 policy); SSL_IMPORT SECStatus SSL_CipherPolicyGet(PRInt32 cipher, PRInt32 *policy); +/* SSLChannelBindingType enumerates the types of supported channel binding + * values. See RFC 5929. */ +typedef enum SSLChannelBindingType { + SSL_CHANNEL_BINDING_TLS_UNIQUE = 1, +} SSLChannelBindingType; + +/* SSL_GetChannelBinding copies the requested channel binding value, as defined + * in RFC 5929, into |out|. The full length of the binding value is written + * into |*outLen|. + * + * At most |outLenMax| bytes of data are copied. If |outLenMax| is + * insufficient then the function returns SECFailure and sets the error to + * SEC_ERROR_OUTPUT_LEN, but |*outLen| is still set. + * + * This call will fail if made during a renegotiation. */ +SSL_IMPORT SECStatus SSL_GetChannelBinding(PRFileDesc *fd, + SSLChannelBindingType binding_type, + unsigned char *out, + unsigned int *outLen, + unsigned int outLenMax); + /* SSL Version Range API ** ** This API should be used to control SSL 3.0 & TLS support instead of the diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c index 0f1cdc6..1f6def2 100644 --- a/net/third_party/nss/ssl/ssl3con.c +++ b/net/third_party/nss/ssl/ssl3con.c @@ -10539,6 +10539,68 @@ ssl3_InitSocketPolicy(sslSocket *ss) PORT_Memcpy(ss->cipherSuites, cipherSuites, sizeof cipherSuites); } +SECStatus +ssl3_GetTLSUniqueChannelBinding(sslSocket *ss, + unsigned char *out, + unsigned int *outLen, + unsigned int outLenMax) { + PRBool isTLS; + int index = 0; + unsigned int len; + SECStatus rv = SECFailure; + + *outLen = 0; + + ssl_GetSSL3HandshakeLock(ss); + + ssl_GetSpecReadLock(ss); + isTLS = (PRBool)(ss->ssl3.cwSpec->version > SSL_LIBRARY_VERSION_3_0); + ssl_ReleaseSpecReadLock(ss); + + /* The tls-unique channel binding is the first Finished structure in the + * handshake. In the case of a resumption, that's the server's Finished. + * Otherwise, it's the client's Finished. */ + len = ss->ssl3.hs.finishedBytes; + + /* Sending or receiving a Finished message will set finishedBytes to a + * non-zero value. */ + if (len == 0) { + PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED); + goto loser; + } + + /* If we are in the middle of a renegotiation then the channel binding + * value is poorly defined and depends on the direction that it will be + * used on. Therefore we simply return an error in this case. */ + if (ss->firstHsDone && ss->ssl3.hs.ws != idle_handshake) { + PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED); + goto loser; + } + + /* If resuming, then we want the second Finished value in the array, which + * is the server's */ + if (ss->ssl3.hs.isResuming) + index = 1; + + *outLen = len; + if (outLenMax < len) { + PORT_SetError(SEC_ERROR_OUTPUT_LEN); + goto loser; + } + + if (isTLS) { + memcpy(out, &ss->ssl3.hs.finishedMsgs.tFinished[index], len); + } else { + memcpy(out, &ss->ssl3.hs.finishedMsgs.sFinished[index], len); + } + + rv = SECSuccess; + +loser: + ssl_ReleaseSSL3HandshakeLock(ss); + return rv; +} + /* ssl3_config_match_init must have already been called by * the caller of this function. */ diff --git a/net/third_party/nss/ssl/sslimpl.h b/net/third_party/nss/ssl/sslimpl.h index adad5d0..eda1885 100644 --- a/net/third_party/nss/ssl/sslimpl.h +++ b/net/third_party/nss/ssl/sslimpl.h @@ -1775,6 +1775,11 @@ extern PRBool ssl_GetSessionTicketKeysPKCS11(SECKEYPrivateKey *svrPrivKey, extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char* data, unsigned int length); +extern SECStatus ssl3_GetTLSUniqueChannelBinding(sslSocket *ss, + unsigned char *out, + unsigned int *outLen, + unsigned int outLenMax); + /* Construct a new NSPR socket for the app to use */ extern PRFileDesc *ssl_NewPRSocket(sslSocket *ss, PRFileDesc *fd); extern void ssl_FreePRSocket(PRFileDesc *fd); diff --git a/net/third_party/nss/ssl/sslsock.c b/net/third_party/nss/ssl/sslsock.c index 9387a21..1823a1c 100644 --- a/net/third_party/nss/ssl/sslsock.c +++ b/net/third_party/nss/ssl/sslsock.c @@ -1382,6 +1382,27 @@ NSS_SetFrancePolicy(void) return NSS_SetDomesticPolicy(); } +SECStatus +SSL_GetChannelBinding(PRFileDesc *fd, + SSLChannelBindingType binding_type, + unsigned char *out, + unsigned int *outLen, + unsigned int outLenMax) { + sslSocket *ss = ssl_FindSocket(fd); + + if (!ss) { + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelBinding", + SSL_GETPID(), fd)); + return SECFailure; + } + + if (binding_type != SSL_CHANNEL_BINDING_TLS_UNIQUE) { + PORT_SetError(PR_INVALID_ARGUMENT_ERROR); + return SECFailure; + } + + return ssl3_GetTLSUniqueChannelBinding(ss, out, outLen, outLenMax); +} /* LOCKS ??? XXX */ |