OLD | NEW |
| (Empty) |
1 diff -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 */ | |
73 diff -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 | |
104 diff -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); | |
119 diff -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 */ | |
OLD | NEW |