• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
2--- a/nss/lib/ssl/ssl3con.c	2014-01-17 17:59:03.242109996 -0800
3+++ b/nss/lib/ssl/ssl3con.c	2014-01-17 17:59:45.862816905 -0800
4@@ -12383,6 +12383,68 @@ ssl3_InitSocketPolicy(sslSocket *ss)
5     PORT_Memcpy(ss->cipherSuites, cipherSuites, sizeof cipherSuites);
6 }
7
8+SECStatus
9+ssl3_GetTLSUniqueChannelBinding(sslSocket *ss,
10+				unsigned char *out,
11+				unsigned int *outLen,
12+				unsigned int outLenMax) {
13+    PRBool       isTLS;
14+    int          index = 0;
15+    unsigned int len;
16+    SECStatus    rv = SECFailure;
17+
18+    *outLen = 0;
19+
20+    ssl_GetSSL3HandshakeLock(ss);
21+
22+    ssl_GetSpecReadLock(ss);
23+    isTLS = (PRBool)(ss->ssl3.cwSpec->version > SSL_LIBRARY_VERSION_3_0);
24+    ssl_ReleaseSpecReadLock(ss);
25+
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;
30+
31+    /* Sending or receiving a Finished message will set finishedBytes to a
32+     * non-zero value. */
33+    if (len == 0) {
34+	PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED);
35+	goto loser;
36+    }
37+
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);
43+	goto loser;
44+    }
45+
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)
49+	index = 1;
50+
51+    *outLen = len;
52+    if (outLenMax < len) {
53+	PORT_SetError(SEC_ERROR_OUTPUT_LEN);
54+	goto loser;
55+    }
56+
57+    if (isTLS) {
58+	memcpy(out, &ss->ssl3.hs.finishedMsgs.tFinished[index], len);
59+    } else {
60+	memcpy(out, &ss->ssl3.hs.finishedMsgs.sFinished[index], len);
61+    }
62+
63+    rv = SECSuccess;
64+
65+loser:
66+    ssl_ReleaseSSL3HandshakeLock(ss);
67+    return rv;
68+}
69+
70 /* ssl3_config_match_init must have already been called by
71  * the caller of this function.
72  */
73diff -pu a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h
74--- a/nss/lib/ssl/ssl.h	2014-01-17 17:59:03.242109996 -0800
75+++ b/nss/lib/ssl/ssl.h	2014-01-17 17:59:45.862816905 -0800
76@@ -282,6 +282,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);
79
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;
85+
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
88+ * into |*outLen|.
89+ *
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.
93+ *
94+ * This call will fail if made during a renegotiation. */
95+SSL_IMPORT SECStatus SSL_GetChannelBinding(PRFileDesc *fd,
96+					   SSLChannelBindingType binding_type,
97+					   unsigned char *out,
98+					   unsigned int *outLen,
99+					   unsigned int outLenMax);
100+
101 /* SSL Version Range API
102 **
103 ** This API should be used to control SSL 3.0 & TLS support instead of the
104diff -pu a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h
105--- a/nss/lib/ssl/sslimpl.h	2014-01-17 17:59:03.242109996 -0800
106+++ b/nss/lib/ssl/sslimpl.h	2014-01-17 17:59:45.862816905 -0800
107@@ -1853,6 +1853,11 @@ extern PRBool ssl_GetSessionTicketKeysPK
108 extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char* data,
109 					    unsigned int length);
110
111+extern SECStatus ssl3_GetTLSUniqueChannelBinding(sslSocket *ss,
112+						 unsigned char *out,
113+						 unsigned int *outLen,
114+						 unsigned int outLenMax);
115+
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);
119diff -pu a/nss/lib/ssl/sslsock.c b/nss/lib/ssl/sslsock.c
120--- a/nss/lib/ssl/sslsock.c	2014-01-17 17:59:03.252110162 -0800
121+++ b/nss/lib/ssl/sslsock.c	2014-01-17 17:59:45.872817074 -0800
122@@ -1308,6 +1308,27 @@ NSS_SetFrancePolicy(void)
123     return NSS_SetDomesticPolicy();
124 }
125
126+SECStatus
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);
133+
134+    if (!ss) {
135+	SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelBinding",
136+		 SSL_GETPID(), fd));
137+	return SECFailure;
138+    }
139+
140+    if (binding_type != SSL_CHANNEL_BINDING_TLS_UNIQUE) {
141+	PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
142+	return SECFailure;
143+    }
144+
145+    return ssl3_GetTLSUniqueChannelBinding(ss, out, outLen, outLenMax);
146+}
147
148
149 /* LOCKS ??? XXX */
150