1 diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
2 --- a/nss/lib/ssl/ssl3con.c 2014-01-03 19:39:28.442012014 -0800
3 +++ b/nss/lib/ssl/ssl3con.c 2014-01-03 19:39:45.052283611 -0800
4 @@ -12358,6 +12358,68 @@ ssl3_InitSocketPolicy(sslSocket *ss)
5 PORT_Memcpy(ss->cipherSuites, cipherSuites, sizeof cipherSuites);
9 +ssl3_GetTLSUniqueChannelBinding(sslSocket *ss,
11 + unsigned int *outLen,
12 + unsigned int outLenMax) {
16 + SECStatus rv = SECFailure;
20 + ssl_GetSSL3HandshakeLock(ss);
22 + ssl_GetSpecReadLock(ss);
23 + isTLS = (PRBool)(ss->ssl3.cwSpec->version > SSL_LIBRARY_VERSION_3_0);
24 + ssl_ReleaseSpecReadLock(ss);
26 + /* The tls-unique channel binding is the first Finished structure in the
27 + * handshake. In the case of a resumption, that's the server's Finished.
28 + * Otherwise, it's the client's Finished. */
29 + len = ss->ssl3.hs.finishedBytes;
31 + /* Sending or receiving a Finished message will set finishedBytes to a
32 + * non-zero value. */
34 + PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED);
38 + /* If we are in the middle of a renegotiation then the channel binding
39 + * value is poorly defined and depends on the direction that it will be
40 + * used on. Therefore we simply return an error in this case. */
41 + if (ss->firstHsDone && ss->ssl3.hs.ws != idle_handshake) {
42 + PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
46 + /* If resuming, then we want the second Finished value in the array, which
47 + * is the server's */
48 + if (ss->ssl3.hs.isResuming)
52 + if (outLenMax < len) {
53 + PORT_SetError(SEC_ERROR_OUTPUT_LEN);
58 + memcpy(out, &ss->ssl3.hs.finishedMsgs.tFinished[index], len);
60 + memcpy(out, &ss->ssl3.hs.finishedMsgs.sFinished[index], len);
66 + ssl_ReleaseSSL3HandshakeLock(ss);
70 /* ssl3_config_match_init must have already been called by
71 * the caller of this function.
73 diff -pu a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h
74 --- a/nss/lib/ssl/ssl.h 2014-01-03 19:39:28.442012014 -0800
75 +++ b/nss/lib/ssl/ssl.h 2014-01-03 19:39:45.052283611 -0800
76 @@ -252,6 +252,27 @@ SSL_IMPORT SECStatus SSL_CipherPrefGetDe
77 SSL_IMPORT SECStatus SSL_CipherPolicySet(PRInt32 cipher, PRInt32 policy);
78 SSL_IMPORT SECStatus SSL_CipherPolicyGet(PRInt32 cipher, PRInt32 *policy);
80 +/* SSLChannelBindingType enumerates the types of supported channel binding
81 + * values. See RFC 5929. */
82 +typedef enum SSLChannelBindingType {
83 + SSL_CHANNEL_BINDING_TLS_UNIQUE = 1,
84 +} SSLChannelBindingType;
86 +/* SSL_GetChannelBinding copies the requested channel binding value, as defined
87 + * in RFC 5929, into |out|. The full length of the binding value is written
90 + * At most |outLenMax| bytes of data are copied. If |outLenMax| is
91 + * insufficient then the function returns SECFailure and sets the error to
92 + * SEC_ERROR_OUTPUT_LEN, but |*outLen| is still set.
94 + * This call will fail if made during a renegotiation. */
95 +SSL_IMPORT SECStatus SSL_GetChannelBinding(PRFileDesc *fd,
96 + SSLChannelBindingType binding_type,
98 + unsigned int *outLen,
99 + unsigned int outLenMax);
101 /* SSL Version Range API
103 ** This API should be used to control SSL 3.0 & TLS support instead of the
104 diff -pu a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h
105 --- a/nss/lib/ssl/sslimpl.h 2014-01-03 19:39:28.452012178 -0800
106 +++ b/nss/lib/ssl/sslimpl.h 2014-01-03 19:39:45.072283939 -0800
107 @@ -1844,6 +1844,11 @@ extern PRBool ssl_GetSessionTicketKeysPK
108 extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char* data,
109 unsigned int length);
111 +extern SECStatus ssl3_GetTLSUniqueChannelBinding(sslSocket *ss,
112 + unsigned char *out,
113 + unsigned int *outLen,
114 + unsigned int outLenMax);
116 /* Construct a new NSPR socket for the app to use */
117 extern PRFileDesc *ssl_NewPRSocket(sslSocket *ss, PRFileDesc *fd);
118 extern void ssl_FreePRSocket(PRFileDesc *fd);
119 diff -pu a/nss/lib/ssl/sslsock.c b/nss/lib/ssl/sslsock.c
120 --- a/nss/lib/ssl/sslsock.c 2014-01-03 19:39:28.452012178 -0800
121 +++ b/nss/lib/ssl/sslsock.c 2014-01-03 19:39:45.092284267 -0800
122 @@ -1286,6 +1286,27 @@ NSS_SetFrancePolicy(void)
123 return NSS_SetDomesticPolicy();
127 +SSL_GetChannelBinding(PRFileDesc *fd,
128 + SSLChannelBindingType binding_type,
129 + unsigned char *out,
130 + unsigned int *outLen,
131 + unsigned int outLenMax) {
132 + sslSocket *ss = ssl_FindSocket(fd);
135 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelBinding",
136 + SSL_GETPID(), fd));
140 + if (binding_type != SSL_CHANNEL_BINDING_TLS_UNIQUE) {
141 + PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
145 + return ssl3_GetTLSUniqueChannelBinding(ss, out, outLen, outLenMax);