| diff -pu -r a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c |
| --- a/net/third_party/nss/ssl/ssl3con.c 2012-11-09 16:13:22.012407752 -0800 |
| +++ b/net/third_party/nss/ssl/ssl3con.c 2012-11-09 16:14:14.123162240 -0800 |
| @@ -10719,6 +10719,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 -pu -r a/net/third_party/nss/ssl/ssl.h b/net/third_party/nss/ssl/ssl.h |
| --- a/net/third_party/nss/ssl/ssl.h 2012-11-09 16:13:22.062408475 -0800 |
| +++ b/net/third_party/nss/ssl/ssl.h 2012-11-09 16:14:14.123162240 -0800 |
| @@ -250,6 +250,27 @@ SSL_IMPORT SECStatus SSL_CipherPrefGetDe |
| 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 -pu -r a/net/third_party/nss/ssl/sslimpl.h b/net/third_party/nss/ssl/sslimpl.h |
| --- a/net/third_party/nss/ssl/sslimpl.h 2012-11-09 16:13:22.062408475 -0800 |
| +++ b/net/third_party/nss/ssl/sslimpl.h 2012-11-09 16:14:14.123162240 -0800 |
| @@ -1732,6 +1732,11 @@ extern PRBool ssl_GetSessionTicketKeysPK |
| 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 -pu -r a/net/third_party/nss/ssl/sslsock.c b/net/third_party/nss/ssl/sslsock.c |
| --- a/net/third_party/nss/ssl/sslsock.c 2012-11-09 16:13:22.062408475 -0800 |
| +++ b/net/third_party/nss/ssl/sslsock.c 2012-11-09 16:14:14.123162240 -0800 |
| @@ -1354,6 +1354,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 */ |