summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-25 22:43:08 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-25 22:43:08 +0000
commita644b1135cb8a735d487cf210034abc6dd195bd3 (patch)
tree6aad1b77aa51a245d329ce0555f75b51c5a09926 /net
parent8072c7b6f31a761804abc8a3b98fbae346e4431a (diff)
downloadchromium_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.chromium3
-rwxr-xr-xnet/third_party/nss/patches/applypatches.sh2
-rw-r--r--net/third_party/nss/patches/tlsunique.patch153
-rw-r--r--net/third_party/nss/ssl/ssl.h21
-rw-r--r--net/third_party/nss/ssl/ssl3con.c62
-rw-r--r--net/third_party/nss/ssl/sslimpl.h5
-rw-r--r--net/third_party/nss/ssl/sslsock.c21
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 */