OLD | NEW |
| (Empty) |
1 diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h | |
2 index 870a8cc..3550580 100644 | |
3 --- a/lib/ssl/ssl.h | |
4 +++ b/lib/ssl/ssl.h | |
5 @@ -387,6 +387,27 @@ SSL_IMPORT SECStatus SSL_DHEGroupPrefSet(PRFileDesc *fd, | |
6 */ | |
7 SSL_IMPORT SECStatus SSL_EnableWeakDHEPrimeGroup(PRFileDesc *fd, PRBool enabled
); | |
8 | |
9 +/* SSLChannelBindingType enumerates the types of supported channel binding | |
10 + * values. See RFC 5929. */ | |
11 +typedef enum SSLChannelBindingType { | |
12 + SSL_CHANNEL_BINDING_TLS_UNIQUE = 1, | |
13 +} SSLChannelBindingType; | |
14 + | |
15 +/* SSL_GetChannelBinding copies the requested channel binding value, as defined | |
16 + * in RFC 5929, into |out|. The full length of the binding value is written | |
17 + * into |*outLen|. | |
18 + * | |
19 + * At most |outLenMax| bytes of data are copied. If |outLenMax| is | |
20 + * insufficient then the function returns SECFailure and sets the error to | |
21 + * SEC_ERROR_OUTPUT_LEN, but |*outLen| is still set. | |
22 + * | |
23 + * This call will fail if made during a renegotiation. */ | |
24 +SSL_IMPORT SECStatus SSL_GetChannelBinding(PRFileDesc *fd, | |
25 + SSLChannelBindingType binding_type, | |
26 + unsigned char *out, | |
27 + unsigned int *outLen, | |
28 + unsigned int outLenMax); | |
29 + | |
30 /* SSL Version Range API | |
31 ** | |
32 ** This API should be used to control SSL 3.0 & TLS support instead of the | |
33 diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c | |
34 index a2beec2..1394542 100644 | |
35 --- a/lib/ssl/ssl3con.c | |
36 +++ b/lib/ssl/ssl3con.c | |
37 @@ -13808,6 +13808,69 @@ ssl3_InitSocketPolicy(sslSocket *ss) | |
38 ss->ssl3.signatureAlgorithmCount = PR_ARRAY_SIZE(defaultSignatureAlgorithms
); | |
39 } | |
40 | |
41 +SECStatus | |
42 +ssl3_GetTLSUniqueChannelBinding(sslSocket *ss, | |
43 + unsigned char *out, | |
44 + unsigned int *outLen, | |
45 + unsigned int outLenMax) | |
46 +{ | |
47 + PRBool isTLS; | |
48 + int index = 0; | |
49 + unsigned int len; | |
50 + SECStatus rv = SECFailure; | |
51 + | |
52 + *outLen = 0; | |
53 + | |
54 + ssl_GetSSL3HandshakeLock(ss); | |
55 + | |
56 + ssl_GetSpecReadLock(ss); | |
57 + isTLS = (PRBool)(ss->ssl3.cwSpec->version > SSL_LIBRARY_VERSION_3_0); | |
58 + ssl_ReleaseSpecReadLock(ss); | |
59 + | |
60 + /* The tls-unique channel binding is the first Finished structure in the | |
61 + * handshake. In the case of a resumption, that's the server's Finished. | |
62 + * Otherwise, it's the client's Finished. */ | |
63 + len = ss->ssl3.hs.finishedBytes; | |
64 + | |
65 + /* Sending or receiving a Finished message will set finishedBytes to a | |
66 + * non-zero value. */ | |
67 + if (len == 0) { | |
68 + PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED); | |
69 + goto loser; | |
70 + } | |
71 + | |
72 + /* If we are in the middle of a renegotiation then the channel binding | |
73 + * value is poorly defined and depends on the direction that it will be | |
74 + * used on. Therefore we simply return an error in this case. */ | |
75 + if (ss->firstHsDone && ss->ssl3.hs.ws != idle_handshake) { | |
76 + PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED); | |
77 + goto loser; | |
78 + } | |
79 + | |
80 + /* If resuming, then we want the second Finished value in the array, which | |
81 + * is the server's */ | |
82 + if (ss->ssl3.hs.isResuming) | |
83 + index = 1; | |
84 + | |
85 + *outLen = len; | |
86 + if (outLenMax < len) { | |
87 + PORT_SetError(SEC_ERROR_OUTPUT_LEN); | |
88 + goto loser; | |
89 + } | |
90 + | |
91 + if (isTLS) { | |
92 + memcpy(out, &ss->ssl3.hs.finishedMsgs.tFinished[index], len); | |
93 + } else { | |
94 + memcpy(out, &ss->ssl3.hs.finishedMsgs.sFinished[index], len); | |
95 + } | |
96 + | |
97 + rv = SECSuccess; | |
98 + | |
99 +loser: | |
100 + ssl_ReleaseSSL3HandshakeLock(ss); | |
101 + return rv; | |
102 +} | |
103 + | |
104 /* ssl3_config_match_init must have already been called by | |
105 * the caller of this function. | |
106 */ | |
107 diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h | |
108 index 4607655..d47eb28 100644 | |
109 --- a/lib/ssl/sslimpl.h | |
110 +++ b/lib/ssl/sslimpl.h | |
111 @@ -1981,6 +1981,11 @@ extern PRBool ssl_GetSessionTicketKeysPKCS11(SECKEYPrivat
eKey *svrPrivKey, | |
112 extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char *data, | |
113 unsigned int length); | |
114 | |
115 +extern SECStatus ssl3_GetTLSUniqueChannelBinding(sslSocket *ss, | |
116 + unsigned char *out, | |
117 + unsigned int *outLen, | |
118 + unsigned int outLenMax); | |
119 + | |
120 /* Construct a new NSPR socket for the app to use */ | |
121 extern PRFileDesc *ssl_NewPRSocket(sslSocket *ss, PRFileDesc *fd); | |
122 extern void ssl_FreePRSocket(PRFileDesc *fd); | |
123 diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c | |
124 index 84c78b3..e312d82 100644 | |
125 --- a/lib/ssl/sslsock.c | |
126 +++ b/lib/ssl/sslsock.c | |
127 @@ -1700,6 +1700,29 @@ SSL_EnableWeakDHEPrimeGroup(PRFileDesc *fd, PRBool enable
d) | |
128 return SECSuccess; | |
129 } | |
130 | |
131 +SECStatus | |
132 +SSL_GetChannelBinding(PRFileDesc *fd, | |
133 + SSLChannelBindingType binding_type, | |
134 + unsigned char *out, | |
135 + unsigned int *outLen, | |
136 + unsigned int outLenMax) | |
137 +{ | |
138 + sslSocket *ss = ssl_FindSocket(fd); | |
139 + | |
140 + if (!ss) { | |
141 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelBinding", | |
142 + SSL_GETPID(), fd)); | |
143 + return SECFailure; | |
144 + } | |
145 + | |
146 + if (binding_type != SSL_CHANNEL_BINDING_TLS_UNIQUE) { | |
147 + PORT_SetError(PR_INVALID_ARGUMENT_ERROR); | |
148 + return SECFailure; | |
149 + } | |
150 + | |
151 + return ssl3_GetTLSUniqueChannelBinding(ss, out, outLen, outLenMax); | |
152 +} | |
153 + | |
154 #include "dhe-param.c" | |
155 | |
156 static const SSLDHEGroupType ssl_default_dhe_groups[] = { | |
OLD | NEW |