/src/mozilla-central/security/nss/lib/ssl/ssl3ext.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * SSL3 Protocol |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
8 | | |
9 | | /* TLS extension code moved here from ssl3ecc.c */ |
10 | | |
11 | | #include "nssrenam.h" |
12 | | #include "nss.h" |
13 | | #include "ssl.h" |
14 | | #include "sslimpl.h" |
15 | | #include "sslproto.h" |
16 | | #include "ssl3exthandle.h" |
17 | | #include "tls13err.h" |
18 | | #include "tls13exthandle.h" |
19 | | |
20 | | /* Callback function that handles a received extension. */ |
21 | | typedef SECStatus (*ssl3ExtensionHandlerFunc)(const sslSocket *ss, |
22 | | TLSExtensionData *xtnData, |
23 | | SECItem *data); |
24 | | |
25 | | /* Row in a table of hello extension handlers. */ |
26 | | typedef struct { |
27 | | SSLExtensionType ex_type; |
28 | | ssl3ExtensionHandlerFunc ex_handler; |
29 | | } ssl3ExtensionHandler; |
30 | | |
31 | | /* Table of handlers for received TLS hello extensions, one per extension. |
32 | | * In the second generation, this table will be dynamic, and functions |
33 | | * will be registered here. |
34 | | */ |
35 | | /* This table is used by the server, to handle client hello extensions. */ |
36 | | static const ssl3ExtensionHandler clientHelloHandlers[] = { |
37 | | { ssl_server_name_xtn, &ssl3_HandleServerNameXtn }, |
38 | | { ssl_supported_groups_xtn, &ssl_HandleSupportedGroupsXtn }, |
39 | | { ssl_ec_point_formats_xtn, &ssl3_HandleSupportedPointFormatsXtn }, |
40 | | { ssl_session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn }, |
41 | | { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, |
42 | | { ssl_app_layer_protocol_xtn, &ssl3_ServerHandleAppProtoXtn }, |
43 | | { ssl_use_srtp_xtn, &ssl3_ServerHandleUseSRTPXtn }, |
44 | | { ssl_cert_status_xtn, &ssl3_ServerHandleStatusRequestXtn }, |
45 | | { ssl_signature_algorithms_xtn, &ssl3_HandleSigAlgsXtn }, |
46 | | { ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn }, |
47 | | { ssl_signed_cert_timestamp_xtn, &ssl3_ServerHandleSignedCertTimestampXtn }, |
48 | | { ssl_tls13_key_share_xtn, &tls13_ServerHandleKeyShareXtn }, |
49 | | { ssl_tls13_pre_shared_key_xtn, &tls13_ServerHandlePreSharedKeyXtn }, |
50 | | { ssl_tls13_early_data_xtn, &tls13_ServerHandleEarlyDataXtn }, |
51 | | { ssl_tls13_psk_key_exchange_modes_xtn, &tls13_ServerHandlePskModesXtn }, |
52 | | { ssl_tls13_cookie_xtn, &tls13_ServerHandleCookieXtn }, |
53 | | { ssl_record_size_limit_xtn, &ssl_HandleRecordSizeLimitXtn }, |
54 | | { 0, NULL } |
55 | | }; |
56 | | |
57 | | /* These two tables are used by the client, to handle server hello |
58 | | * extensions. */ |
59 | | static const ssl3ExtensionHandler serverHelloHandlersTLS[] = { |
60 | | { ssl_server_name_xtn, &ssl3_HandleServerNameXtn }, |
61 | | /* TODO: add a handler for ssl_ec_point_formats_xtn */ |
62 | | { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn }, |
63 | | { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, |
64 | | { ssl_app_layer_protocol_xtn, &ssl3_ClientHandleAppProtoXtn }, |
65 | | { ssl_use_srtp_xtn, &ssl3_ClientHandleUseSRTPXtn }, |
66 | | { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn }, |
67 | | { ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn }, |
68 | | { ssl_signed_cert_timestamp_xtn, &ssl3_ClientHandleSignedCertTimestampXtn }, |
69 | | { ssl_tls13_key_share_xtn, &tls13_ClientHandleKeyShareXtn }, |
70 | | { ssl_tls13_pre_shared_key_xtn, &tls13_ClientHandlePreSharedKeyXtn }, |
71 | | { ssl_tls13_early_data_xtn, &tls13_ClientHandleEarlyDataXtn }, |
72 | | { ssl_record_size_limit_xtn, &ssl_HandleRecordSizeLimitXtn }, |
73 | | { 0, NULL } |
74 | | }; |
75 | | |
76 | | static const ssl3ExtensionHandler helloRetryRequestHandlers[] = { |
77 | | { ssl_tls13_key_share_xtn, tls13_ClientHandleKeyShareXtnHrr }, |
78 | | { ssl_tls13_cookie_xtn, tls13_ClientHandleHrrCookie }, |
79 | | { 0, NULL } |
80 | | }; |
81 | | |
82 | | static const ssl3ExtensionHandler serverHelloHandlersSSL3[] = { |
83 | | { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, |
84 | | { 0, NULL } |
85 | | }; |
86 | | |
87 | | static const ssl3ExtensionHandler newSessionTicketHandlers[] = { |
88 | | { ssl_tls13_early_data_xtn, |
89 | | &tls13_ClientHandleTicketEarlyDataXtn }, |
90 | | { 0, NULL } |
91 | | }; |
92 | | |
93 | | /* This table is used by the client to handle server certificates in TLS 1.3 */ |
94 | | static const ssl3ExtensionHandler serverCertificateHandlers[] = { |
95 | | { ssl_signed_cert_timestamp_xtn, &ssl3_ClientHandleSignedCertTimestampXtn }, |
96 | | { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn }, |
97 | | { 0, NULL } |
98 | | }; |
99 | | |
100 | | static const ssl3ExtensionHandler certificateRequestHandlers[] = { |
101 | | { ssl_signature_algorithms_xtn, &ssl3_HandleSigAlgsXtn }, |
102 | | { ssl_tls13_certificate_authorities_xtn, |
103 | | &tls13_ClientHandleCertAuthoritiesXtn }, |
104 | | { 0, NULL } |
105 | | }; |
106 | | |
107 | | /* Tables of functions to format TLS hello extensions, one function per |
108 | | * extension. |
109 | | * These static tables are for the formatting of client hello extensions. |
110 | | * The server's table of hello senders is dynamic, in the socket struct, |
111 | | * and sender functions are registered there. |
112 | | * NB: the order of these extensions can have an impact on compatibility. Some |
113 | | * servers (e.g. Tomcat) will terminate the connection if the last extension in |
114 | | * the client hello is empty (for example, the extended master secret |
115 | | * extension, if it were listed last). See bug 1243641. |
116 | | */ |
117 | | static const sslExtensionBuilder clientHelloSendersTLS[] = |
118 | | { |
119 | | { ssl_server_name_xtn, &ssl3_ClientSendServerNameXtn }, |
120 | | { ssl_extended_master_secret_xtn, &ssl3_SendExtendedMasterSecretXtn }, |
121 | | { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn }, |
122 | | { ssl_supported_groups_xtn, &ssl_SendSupportedGroupsXtn }, |
123 | | { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn }, |
124 | | { ssl_session_ticket_xtn, &ssl3_ClientSendSessionTicketXtn }, |
125 | | { ssl_app_layer_protocol_xtn, &ssl3_ClientSendAppProtoXtn }, |
126 | | { ssl_use_srtp_xtn, &ssl3_ClientSendUseSRTPXtn }, |
127 | | { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn }, |
128 | | { ssl_signed_cert_timestamp_xtn, &ssl3_ClientSendSignedCertTimestampXtn }, |
129 | | { ssl_tls13_key_share_xtn, &tls13_ClientSendKeyShareXtn }, |
130 | | { ssl_tls13_early_data_xtn, &tls13_ClientSendEarlyDataXtn }, |
131 | | /* Some servers (e.g. WebSphere Application Server 7.0 and Tomcat) will |
132 | | * time out or terminate the connection if the last extension in the |
133 | | * client hello is empty. They are not intolerant of TLS 1.2, so list |
134 | | * signature_algorithms at the end. See bug 1243641. */ |
135 | | { ssl_tls13_supported_versions_xtn, &tls13_ClientSendSupportedVersionsXtn }, |
136 | | { ssl_signature_algorithms_xtn, &ssl3_SendSigAlgsXtn }, |
137 | | { ssl_tls13_cookie_xtn, &tls13_ClientSendHrrCookieXtn }, |
138 | | { ssl_tls13_psk_key_exchange_modes_xtn, &tls13_ClientSendPskModesXtn }, |
139 | | { ssl_record_size_limit_xtn, &ssl_SendRecordSizeLimitXtn }, |
140 | | /* The pre_shared_key extension MUST be last. */ |
141 | | { ssl_tls13_pre_shared_key_xtn, &tls13_ClientSendPreSharedKeyXtn }, |
142 | | { 0, NULL } |
143 | | }; |
144 | | |
145 | | static const sslExtensionBuilder clientHelloSendersSSL3[] = { |
146 | | { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn }, |
147 | | { 0, NULL } |
148 | | }; |
149 | | |
150 | | static const sslExtensionBuilder tls13_cert_req_senders[] = { |
151 | | { ssl_signature_algorithms_xtn, &ssl3_SendSigAlgsXtn }, |
152 | | { ssl_tls13_certificate_authorities_xtn, &tls13_SendCertAuthoritiesXtn }, |
153 | | { 0, NULL } |
154 | | }; |
155 | | |
156 | | static const sslExtensionBuilder tls13_hrr_senders[] = { |
157 | | { ssl_tls13_key_share_xtn, &tls13_ServerSendHrrKeyShareXtn }, |
158 | | { ssl_tls13_cookie_xtn, &tls13_ServerSendHrrCookieXtn }, |
159 | | { ssl_tls13_supported_versions_xtn, &tls13_ServerSendSupportedVersionsXtn }, |
160 | | { 0, NULL } |
161 | | }; |
162 | | |
163 | | static const struct { |
164 | | SSLExtensionType type; |
165 | | SSLExtensionSupport support; |
166 | | } ssl_supported_extensions[] = { |
167 | | { ssl_server_name_xtn, ssl_ext_native_only }, |
168 | | { ssl_cert_status_xtn, ssl_ext_native }, |
169 | | { ssl_supported_groups_xtn, ssl_ext_native_only }, |
170 | | { ssl_ec_point_formats_xtn, ssl_ext_native }, |
171 | | { ssl_signature_algorithms_xtn, ssl_ext_native_only }, |
172 | | { ssl_use_srtp_xtn, ssl_ext_native }, |
173 | | { ssl_app_layer_protocol_xtn, ssl_ext_native_only }, |
174 | | { ssl_signed_cert_timestamp_xtn, ssl_ext_native }, |
175 | | { ssl_padding_xtn, ssl_ext_native }, |
176 | | { ssl_extended_master_secret_xtn, ssl_ext_native_only }, |
177 | | { ssl_session_ticket_xtn, ssl_ext_native_only }, |
178 | | { ssl_tls13_key_share_xtn, ssl_ext_native_only }, |
179 | | { ssl_tls13_pre_shared_key_xtn, ssl_ext_native_only }, |
180 | | { ssl_tls13_early_data_xtn, ssl_ext_native_only }, |
181 | | { ssl_tls13_supported_versions_xtn, ssl_ext_native_only }, |
182 | | { ssl_tls13_cookie_xtn, ssl_ext_native_only }, |
183 | | { ssl_tls13_psk_key_exchange_modes_xtn, ssl_ext_native_only }, |
184 | | { ssl_tls13_ticket_early_data_info_xtn, ssl_ext_native_only }, |
185 | | { ssl_tls13_certificate_authorities_xtn, ssl_ext_native }, |
186 | | { ssl_renegotiation_info_xtn, ssl_ext_native } |
187 | | }; |
188 | | |
189 | | static SSLExtensionSupport |
190 | | ssl_GetExtensionSupport(PRUint16 type) |
191 | 0 | { |
192 | 0 | unsigned int i; |
193 | 0 | for (i = 0; i < PR_ARRAY_SIZE(ssl_supported_extensions); ++i) { |
194 | 0 | if (type == ssl_supported_extensions[i].type) { |
195 | 0 | return ssl_supported_extensions[i].support; |
196 | 0 | } |
197 | 0 | } |
198 | 0 | return ssl_ext_none; |
199 | 0 | } |
200 | | |
201 | | SECStatus |
202 | | SSLExp_GetExtensionSupport(PRUint16 type, SSLExtensionSupport *support) |
203 | 0 | { |
204 | 0 | *support = ssl_GetExtensionSupport(type); |
205 | 0 | return SECSuccess; |
206 | 0 | } |
207 | | |
208 | | SECStatus |
209 | | SSLExp_InstallExtensionHooks(PRFileDesc *fd, PRUint16 extension, |
210 | | SSLExtensionWriter writer, void *writerArg, |
211 | | SSLExtensionHandler handler, void *handlerArg) |
212 | 0 | { |
213 | 0 | sslSocket *ss = ssl_FindSocket(fd); |
214 | 0 | PRCList *cursor; |
215 | 0 | sslCustomExtensionHooks *hook; |
216 | 0 |
|
217 | 0 | if (!ss) { |
218 | 0 | return SECFailure; /* Code already set. */ |
219 | 0 | } |
220 | 0 | |
221 | 0 | /* Need to specify both or neither, but not just one. */ |
222 | 0 | if ((writer && !handler) || (!writer && handler)) { |
223 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
224 | 0 | return SECFailure; |
225 | 0 | } |
226 | 0 |
|
227 | 0 | if (ssl_GetExtensionSupport(extension) == ssl_ext_native_only) { |
228 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
229 | 0 | return SECFailure; |
230 | 0 | } |
231 | 0 |
|
232 | 0 | if (ss->firstHsDone || ((ss->ssl3.hs.ws != idle_handshake) && |
233 | 0 | (ss->ssl3.hs.ws != wait_client_hello))) { |
234 | 0 | PORT_SetError(PR_INVALID_STATE_ERROR); |
235 | 0 | return SECFailure; |
236 | 0 | } |
237 | 0 |
|
238 | 0 | /* Remove any old handler. */ |
239 | 0 | for (cursor = PR_NEXT_LINK(&ss->extensionHooks); |
240 | 0 | cursor != &ss->extensionHooks; |
241 | 0 | cursor = PR_NEXT_LINK(cursor)) { |
242 | 0 | hook = (sslCustomExtensionHooks *)cursor; |
243 | 0 | if (hook->type == extension) { |
244 | 0 | PR_REMOVE_LINK(&hook->link); |
245 | 0 | PORT_Free(hook); |
246 | 0 | break; |
247 | 0 | } |
248 | 0 | } |
249 | 0 |
|
250 | 0 | if (!writer && !handler) { |
251 | 0 | return SECSuccess; |
252 | 0 | } |
253 | 0 | |
254 | 0 | hook = PORT_ZNew(sslCustomExtensionHooks); |
255 | 0 | if (!hook) { |
256 | 0 | return SECFailure; /* This removed the old one, oh well. */ |
257 | 0 | } |
258 | 0 | |
259 | 0 | hook->type = extension; |
260 | 0 | hook->writer = writer; |
261 | 0 | hook->writerArg = writerArg; |
262 | 0 | hook->handler = handler; |
263 | 0 | hook->handlerArg = handlerArg; |
264 | 0 | PR_APPEND_LINK(&hook->link, &ss->extensionHooks); |
265 | 0 | return SECSuccess; |
266 | 0 | } |
267 | | |
268 | | static sslCustomExtensionHooks * |
269 | | ssl_FindCustomExtensionHooks(sslSocket *ss, PRUint16 extension) |
270 | 0 | { |
271 | 0 | PRCList *cursor; |
272 | 0 |
|
273 | 0 | for (cursor = PR_NEXT_LINK(&ss->extensionHooks); |
274 | 0 | cursor != &ss->extensionHooks; |
275 | 0 | cursor = PR_NEXT_LINK(cursor)) { |
276 | 0 | sslCustomExtensionHooks *hook = (sslCustomExtensionHooks *)cursor; |
277 | 0 | if (hook->type == extension) { |
278 | 0 | return hook; |
279 | 0 | } |
280 | 0 | } |
281 | 0 |
|
282 | 0 | return NULL; |
283 | 0 | } |
284 | | |
285 | | static PRBool |
286 | | arrayContainsExtension(const PRUint16 *array, PRUint32 len, PRUint16 ex_type) |
287 | 0 | { |
288 | 0 | unsigned int i; |
289 | 0 | for (i = 0; i < len; i++) { |
290 | 0 | if (ex_type == array[i]) |
291 | 0 | return PR_TRUE; |
292 | 0 | } |
293 | 0 | return PR_FALSE; |
294 | 0 | } |
295 | | |
296 | | PRBool |
297 | | ssl3_ExtensionNegotiated(const sslSocket *ss, PRUint16 ex_type) |
298 | 0 | { |
299 | 0 | const TLSExtensionData *xtnData = &ss->xtnData; |
300 | 0 | return arrayContainsExtension(xtnData->negotiated, |
301 | 0 | xtnData->numNegotiated, ex_type); |
302 | 0 | } |
303 | | |
304 | | /* This checks for whether an extension was advertised. On the client, this |
305 | | * covers extensions that are sent in ClientHello; on the server, extensions |
306 | | * sent in CertificateRequest (TLS 1.3 only). */ |
307 | | PRBool |
308 | | ssl3_ExtensionAdvertised(const sslSocket *ss, PRUint16 ex_type) |
309 | 0 | { |
310 | 0 | const TLSExtensionData *xtnData = &ss->xtnData; |
311 | 0 | return arrayContainsExtension(xtnData->advertised, |
312 | 0 | xtnData->numAdvertised, ex_type); |
313 | 0 | } |
314 | | |
315 | | /* Go through hello extensions in |b| and deserialize |
316 | | * them into the list in |ss->ssl3.hs.remoteExtensions|. |
317 | | * The only checking we do in this point is for duplicates. |
318 | | * |
319 | | * IMPORTANT: This list just contains pointers to the incoming |
320 | | * buffer so they can only be used during ClientHello processing. |
321 | | */ |
322 | | SECStatus |
323 | | ssl3_ParseExtensions(sslSocket *ss, PRUint8 **b, PRUint32 *length) |
324 | 0 | { |
325 | 0 | /* Clean out the extensions list. */ |
326 | 0 | ssl3_DestroyRemoteExtensions(&ss->ssl3.hs.remoteExtensions); |
327 | 0 |
|
328 | 0 | while (*length) { |
329 | 0 | SECStatus rv; |
330 | 0 | PRUint32 extension_type; |
331 | 0 | SECItem extension_data = { siBuffer, NULL, 0 }; |
332 | 0 | TLSExtension *extension; |
333 | 0 | PRCList *cursor; |
334 | 0 |
|
335 | 0 | /* Get the extension's type field */ |
336 | 0 | rv = ssl3_ConsumeHandshakeNumber(ss, &extension_type, 2, b, length); |
337 | 0 | if (rv != SECSuccess) { |
338 | 0 | return SECFailure; /* alert already sent */ |
339 | 0 | } |
340 | 0 | |
341 | 0 | SSL_TRC(10, ("%d: SSL3[%d]: parsing extension %d", |
342 | 0 | SSL_GETPID(), ss->fd, extension_type)); |
343 | 0 | /* Check whether an extension has been sent multiple times. */ |
344 | 0 | for (cursor = PR_NEXT_LINK(&ss->ssl3.hs.remoteExtensions); |
345 | 0 | cursor != &ss->ssl3.hs.remoteExtensions; |
346 | 0 | cursor = PR_NEXT_LINK(cursor)) { |
347 | 0 | if (((TLSExtension *)cursor)->type == extension_type) { |
348 | 0 | (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter); |
349 | 0 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_EXTENSION); |
350 | 0 | return SECFailure; |
351 | 0 | } |
352 | 0 | } |
353 | 0 |
|
354 | 0 | /* Get the data for this extension, so we can pass it or skip it. */ |
355 | 0 | rv = ssl3_ConsumeHandshakeVariable(ss, &extension_data, 2, b, length); |
356 | 0 | if (rv != SECSuccess) { |
357 | 0 | return rv; /* alert already sent */ |
358 | 0 | } |
359 | 0 | |
360 | 0 | extension = PORT_ZNew(TLSExtension); |
361 | 0 | if (!extension) { |
362 | 0 | return SECFailure; |
363 | 0 | } |
364 | 0 | |
365 | 0 | extension->type = (PRUint16)extension_type; |
366 | 0 | extension->data = extension_data; |
367 | 0 | PR_APPEND_LINK(&extension->link, &ss->ssl3.hs.remoteExtensions); |
368 | 0 | } |
369 | 0 |
|
370 | 0 | return SECSuccess; |
371 | 0 | } |
372 | | |
373 | | TLSExtension * |
374 | | ssl3_FindExtension(sslSocket *ss, SSLExtensionType extension_type) |
375 | 0 | { |
376 | 0 | PRCList *cursor; |
377 | 0 |
|
378 | 0 | for (cursor = PR_NEXT_LINK(&ss->ssl3.hs.remoteExtensions); |
379 | 0 | cursor != &ss->ssl3.hs.remoteExtensions; |
380 | 0 | cursor = PR_NEXT_LINK(cursor)) { |
381 | 0 | TLSExtension *extension = (TLSExtension *)cursor; |
382 | 0 |
|
383 | 0 | if (extension->type == extension_type) { |
384 | 0 | return extension; |
385 | 0 | } |
386 | 0 | } |
387 | 0 |
|
388 | 0 | return NULL; |
389 | 0 | } |
390 | | |
391 | | static SECStatus |
392 | | ssl_CallExtensionHandler(sslSocket *ss, SSLHandshakeType handshakeMessage, |
393 | | TLSExtension *extension, |
394 | | const ssl3ExtensionHandler *handler) |
395 | 0 | { |
396 | 0 | SECStatus rv = SECSuccess; |
397 | 0 | SSLAlertDescription alert = handshake_failure; |
398 | 0 | sslCustomExtensionHooks *customHooks; |
399 | 0 |
|
400 | 0 | customHooks = ssl_FindCustomExtensionHooks(ss, extension->type); |
401 | 0 | if (customHooks) { |
402 | 0 | if (customHooks->handler) { |
403 | 0 | rv = customHooks->handler(ss->fd, handshakeMessage, |
404 | 0 | extension->data.data, |
405 | 0 | extension->data.len, |
406 | 0 | &alert, customHooks->handlerArg); |
407 | 0 | } |
408 | 0 | } else { |
409 | 0 | /* Find extension_type in table of Hello Extension Handlers. */ |
410 | 0 | for (; handler->ex_handler != NULL; ++handler) { |
411 | 0 | if (handler->ex_type == extension->type) { |
412 | 0 | rv = (*handler->ex_handler)(ss, &ss->xtnData, &extension->data); |
413 | 0 | break; |
414 | 0 | } |
415 | 0 | } |
416 | 0 | } |
417 | 0 |
|
418 | 0 | if (rv != SECSuccess) { |
419 | 0 | if (!ss->ssl3.fatalAlertSent) { |
420 | 0 | /* Send an alert if the handler didn't already. */ |
421 | 0 | (void)SSL3_SendAlert(ss, alert_fatal, alert); |
422 | 0 | } |
423 | 0 | return SECFailure; |
424 | 0 | } |
425 | 0 |
|
426 | 0 | return SECSuccess; |
427 | 0 | } |
428 | | |
429 | | /* Go through the hello extensions in |ss->ssl3.hs.remoteExtensions|. |
430 | | * For each one, find the extension handler in the table, and |
431 | | * if present, invoke that handler. |
432 | | * Servers ignore any extensions with unknown extension types. |
433 | | * Clients reject any extensions with unadvertised extension types |
434 | | * |
435 | | * In TLS >= 1.3, the client checks that extensions appear in the |
436 | | * right phase. |
437 | | */ |
438 | | SECStatus |
439 | | ssl3_HandleParsedExtensions(sslSocket *ss, SSLHandshakeType message) |
440 | 0 | { |
441 | 0 | const ssl3ExtensionHandler *handlers; |
442 | 0 | /* HelloRetryRequest doesn't set ss->version. It might be safe to |
443 | 0 | * do so, but we weren't entirely sure. TODO(ekr@rtfm.com). */ |
444 | 0 | PRBool isTLS13 = (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) || |
445 | 0 | (message == ssl_hs_hello_retry_request); |
446 | 0 | /* The following messages can include extensions that were not included in |
447 | 0 | * the original ClientHello. */ |
448 | 0 | PRBool allowNotOffered = (message == ssl_hs_client_hello) || |
449 | 0 | (message == ssl_hs_certificate_request) || |
450 | 0 | (message == ssl_hs_new_session_ticket); |
451 | 0 | PRCList *cursor; |
452 | 0 |
|
453 | 0 | switch (message) { |
454 | 0 | case ssl_hs_client_hello: |
455 | 0 | handlers = clientHelloHandlers; |
456 | 0 | break; |
457 | 0 | case ssl_hs_new_session_ticket: |
458 | 0 | PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3); |
459 | 0 | handlers = newSessionTicketHandlers; |
460 | 0 | break; |
461 | 0 | case ssl_hs_hello_retry_request: |
462 | 0 | handlers = helloRetryRequestHandlers; |
463 | 0 | break; |
464 | 0 | case ssl_hs_encrypted_extensions: |
465 | 0 | PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3); |
466 | 0 | /* fall through */ |
467 | 0 | case ssl_hs_server_hello: |
468 | 0 | if (ss->version > SSL_LIBRARY_VERSION_3_0) { |
469 | 0 | handlers = serverHelloHandlersTLS; |
470 | 0 | } else { |
471 | 0 | handlers = serverHelloHandlersSSL3; |
472 | 0 | } |
473 | 0 | break; |
474 | 0 | case ssl_hs_certificate: |
475 | 0 | PORT_Assert(!ss->sec.isServer); |
476 | 0 | handlers = serverCertificateHandlers; |
477 | 0 | break; |
478 | 0 | case ssl_hs_certificate_request: |
479 | 0 | PORT_Assert(!ss->sec.isServer); |
480 | 0 | handlers = certificateRequestHandlers; |
481 | 0 | break; |
482 | 0 | default: |
483 | 0 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
484 | 0 | PORT_Assert(0); |
485 | 0 | return SECFailure; |
486 | 0 | } |
487 | 0 |
|
488 | 0 | for (cursor = PR_NEXT_LINK(&ss->ssl3.hs.remoteExtensions); |
489 | 0 | cursor != &ss->ssl3.hs.remoteExtensions; |
490 | 0 | cursor = PR_NEXT_LINK(cursor)) { |
491 | 0 | TLSExtension *extension = (TLSExtension *)cursor; |
492 | 0 | SECStatus rv; |
493 | 0 |
|
494 | 0 | /* Check whether the server sent an extension which was not advertised |
495 | 0 | * in the ClientHello. |
496 | 0 | * |
497 | 0 | * Note that a TLS 1.3 server should check if CertificateRequest |
498 | 0 | * extensions were sent. But the extensions used for CertificateRequest |
499 | 0 | * do not have any response, so we rely on |
500 | 0 | * ssl3_ExtensionAdvertised to return false on the server. That |
501 | 0 | * results in the server only rejecting any extension. */ |
502 | 0 | if (!allowNotOffered && (extension->type != ssl_tls13_cookie_xtn) && |
503 | 0 | !ssl3_ExtensionAdvertised(ss, extension->type)) { |
504 | 0 | (void)SSL3_SendAlert(ss, alert_fatal, unsupported_extension); |
505 | 0 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_EXTENSION); |
506 | 0 | return SECFailure; |
507 | 0 | } |
508 | 0 |
|
509 | 0 | /* Check that this is a legal extension in TLS 1.3 */ |
510 | 0 | if (isTLS13 && |
511 | 0 | !ssl_FindCustomExtensionHooks(ss, extension->type)) { |
512 | 0 | switch (tls13_ExtensionStatus(extension->type, message)) { |
513 | 0 | case tls13_extension_allowed: |
514 | 0 | break; |
515 | 0 | case tls13_extension_unknown: |
516 | 0 | if (allowNotOffered) { |
517 | 0 | continue; /* Skip over unknown extensions. */ |
518 | 0 | } |
519 | 0 | /* Fall through. */ |
520 | 0 | case tls13_extension_disallowed: |
521 | 0 | SSL_TRC(3, ("%d: TLS13: unexpected extension %d in message %d", |
522 | 0 | SSL_GETPID(), extension, message)); |
523 | 0 | tls13_FatalError(ss, SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION, |
524 | 0 | unsupported_extension); |
525 | 0 | return SECFailure; |
526 | 0 | } |
527 | 0 | } |
528 | 0 | |
529 | 0 | /* Special check for this being the last extension if it's |
530 | 0 | * PreSharedKey */ |
531 | 0 | if (ss->sec.isServer && isTLS13 && |
532 | 0 | (extension->type == ssl_tls13_pre_shared_key_xtn) && |
533 | 0 | (PR_NEXT_LINK(cursor) != &ss->ssl3.hs.remoteExtensions)) { |
534 | 0 | tls13_FatalError(ss, |
535 | 0 | SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, |
536 | 0 | illegal_parameter); |
537 | 0 | return SECFailure; |
538 | 0 | } |
539 | 0 | |
540 | 0 | rv = ssl_CallExtensionHandler(ss, message, extension, handlers); |
541 | 0 | if (rv != SECSuccess) { |
542 | 0 | return SECFailure; |
543 | 0 | } |
544 | 0 | } |
545 | 0 | return SECSuccess; |
546 | 0 | } |
547 | | |
548 | | /* Syntactic sugar around ssl3_ParseExtensions and |
549 | | * ssl3_HandleParsedExtensions. */ |
550 | | SECStatus |
551 | | ssl3_HandleExtensions(sslSocket *ss, |
552 | | PRUint8 **b, PRUint32 *length, |
553 | | SSLHandshakeType handshakeMessage) |
554 | 0 | { |
555 | 0 | SECStatus rv; |
556 | 0 |
|
557 | 0 | rv = ssl3_ParseExtensions(ss, b, length); |
558 | 0 | if (rv != SECSuccess) |
559 | 0 | return rv; |
560 | 0 | |
561 | 0 | rv = ssl3_HandleParsedExtensions(ss, handshakeMessage); |
562 | 0 | if (rv != SECSuccess) |
563 | 0 | return rv; |
564 | 0 | |
565 | 0 | ssl3_DestroyRemoteExtensions(&ss->ssl3.hs.remoteExtensions); |
566 | 0 | return SECSuccess; |
567 | 0 | } |
568 | | |
569 | | /* Add a callback function to the table of senders of server hello extensions. |
570 | | */ |
571 | | SECStatus |
572 | | ssl3_RegisterExtensionSender(const sslSocket *ss, |
573 | | TLSExtensionData *xtnData, |
574 | | PRUint16 ex_type, |
575 | | sslExtensionBuilderFunc cb) |
576 | 0 | { |
577 | 0 | int i; |
578 | 0 | sslExtensionBuilder *sender; |
579 | 0 | if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { |
580 | 0 | sender = &xtnData->serverHelloSenders[0]; |
581 | 0 | } else { |
582 | 0 | if (tls13_ExtensionStatus(ex_type, ssl_hs_server_hello) == |
583 | 0 | tls13_extension_allowed) { |
584 | 0 | PORT_Assert(tls13_ExtensionStatus(ex_type, |
585 | 0 | ssl_hs_encrypted_extensions) == |
586 | 0 | tls13_extension_disallowed); |
587 | 0 | sender = &xtnData->serverHelloSenders[0]; |
588 | 0 | } else if (tls13_ExtensionStatus(ex_type, |
589 | 0 | ssl_hs_encrypted_extensions) == |
590 | 0 | tls13_extension_allowed) { |
591 | 0 | sender = &xtnData->encryptedExtensionsSenders[0]; |
592 | 0 | } else if (tls13_ExtensionStatus(ex_type, ssl_hs_certificate) == |
593 | 0 | tls13_extension_allowed) { |
594 | 0 | sender = &xtnData->certificateSenders[0]; |
595 | 0 | } else { |
596 | 0 | PORT_Assert(0); |
597 | 0 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
598 | 0 | return SECFailure; |
599 | 0 | } |
600 | 0 | } |
601 | 0 | for (i = 0; i < SSL_MAX_EXTENSIONS; ++i, ++sender) { |
602 | 0 | if (!sender->ex_sender) { |
603 | 0 | sender->ex_type = ex_type; |
604 | 0 | sender->ex_sender = cb; |
605 | 0 | return SECSuccess; |
606 | 0 | } |
607 | 0 | /* detect duplicate senders */ |
608 | 0 | PORT_Assert(sender->ex_type != ex_type); |
609 | 0 | if (sender->ex_type == ex_type) { |
610 | 0 | /* duplicate */ |
611 | 0 | break; |
612 | 0 | } |
613 | 0 | } |
614 | 0 | PORT_Assert(i < SSL_MAX_EXTENSIONS); /* table needs to grow */ |
615 | 0 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
616 | 0 | return SECFailure; |
617 | 0 | } |
618 | | |
619 | | static SECStatus |
620 | | ssl_CallCustomExtensionSenders(sslSocket *ss, sslBuffer *buf, |
621 | | SSLHandshakeType message) |
622 | 0 | { |
623 | 0 | sslBuffer tail = SSL_BUFFER_EMPTY; |
624 | 0 | SECStatus rv; |
625 | 0 | PRCList *cursor; |
626 | 0 |
|
627 | 0 | /* Save any extensions that want to be last. */ |
628 | 0 | if (ss->xtnData.lastXtnOffset) { |
629 | 0 | rv = sslBuffer_Append(&tail, buf->buf + ss->xtnData.lastXtnOffset, |
630 | 0 | buf->len - ss->xtnData.lastXtnOffset); |
631 | 0 | if (rv != SECSuccess) { |
632 | 0 | return SECFailure; |
633 | 0 | } |
634 | 0 | buf->len = ss->xtnData.lastXtnOffset; |
635 | 0 | } |
636 | 0 |
|
637 | 0 | /* Reserve the maximum amount of space possible. */ |
638 | 0 | rv = sslBuffer_Grow(buf, 65535); |
639 | 0 | if (rv != SECSuccess) { |
640 | 0 | return SECFailure; |
641 | 0 | } |
642 | 0 | |
643 | 0 | for (cursor = PR_NEXT_LINK(&ss->extensionHooks); |
644 | 0 | cursor != &ss->extensionHooks; |
645 | 0 | cursor = PR_NEXT_LINK(cursor)) { |
646 | 0 | sslCustomExtensionHooks *hook = |
647 | 0 | (sslCustomExtensionHooks *)cursor; |
648 | 0 | PRBool append = PR_FALSE; |
649 | 0 | unsigned int len = 0; |
650 | 0 |
|
651 | 0 | if (hook->writer) { |
652 | 0 | /* The writer writes directly into |buf|. Provide space that allows |
653 | 0 | * for the existing extensions, any tail, plus type and length. */ |
654 | 0 | unsigned int space = buf->space - (buf->len + tail.len + 4); |
655 | 0 | append = (*hook->writer)(ss->fd, message, |
656 | 0 | buf->buf + buf->len + 4, &len, space, |
657 | 0 | hook->writerArg); |
658 | 0 | if (len > space) { |
659 | 0 | PORT_SetError(SEC_ERROR_APPLICATION_CALLBACK_ERROR); |
660 | 0 | goto loser; |
661 | 0 | } |
662 | 0 | } |
663 | 0 | if (!append) { |
664 | 0 | continue; |
665 | 0 | } |
666 | 0 | |
667 | 0 | rv = sslBuffer_AppendNumber(buf, hook->type, 2); |
668 | 0 | if (rv != SECSuccess) { |
669 | 0 | goto loser; /* Code already set. */ |
670 | 0 | } |
671 | 0 | rv = sslBuffer_AppendNumber(buf, len, 2); |
672 | 0 | if (rv != SECSuccess) { |
673 | 0 | goto loser; /* Code already set. */ |
674 | 0 | } |
675 | 0 | buf->len += len; |
676 | 0 |
|
677 | 0 | if (message == ssl_hs_client_hello || |
678 | 0 | message == ssl_hs_certificate_request) { |
679 | 0 | ss->xtnData.advertised[ss->xtnData.numAdvertised++] = hook->type; |
680 | 0 | } |
681 | 0 | } |
682 | 0 |
|
683 | 0 | rv = sslBuffer_Append(buf, tail.buf, tail.len); |
684 | 0 | if (rv != SECSuccess) { |
685 | 0 | goto loser; /* Code already set. */ |
686 | 0 | } |
687 | 0 | |
688 | 0 | sslBuffer_Clear(&tail); |
689 | 0 | return SECSuccess; |
690 | 0 | |
691 | 0 | loser: |
692 | 0 | sslBuffer_Clear(&tail); |
693 | 0 | return SECFailure; |
694 | 0 | } |
695 | | |
696 | | /* Call extension handlers for the given message. */ |
697 | | SECStatus |
698 | | ssl_ConstructExtensions(sslSocket *ss, sslBuffer *buf, SSLHandshakeType message) |
699 | 0 | { |
700 | 0 | const sslExtensionBuilder *sender; |
701 | 0 | SECStatus rv; |
702 | 0 |
|
703 | 0 | PORT_Assert(buf->len == 0); |
704 | 0 |
|
705 | 0 | switch (message) { |
706 | 0 | case ssl_hs_client_hello: |
707 | 0 | if (ss->vrange.max > SSL_LIBRARY_VERSION_3_0) { |
708 | 0 | sender = clientHelloSendersTLS; |
709 | 0 | } else { |
710 | 0 | sender = clientHelloSendersSSL3; |
711 | 0 | } |
712 | 0 | break; |
713 | 0 |
|
714 | 0 | case ssl_hs_server_hello: |
715 | 0 | sender = ss->xtnData.serverHelloSenders; |
716 | 0 | break; |
717 | 0 |
|
718 | 0 | case ssl_hs_certificate_request: |
719 | 0 | PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3); |
720 | 0 | sender = tls13_cert_req_senders; |
721 | 0 | break; |
722 | 0 |
|
723 | 0 | case ssl_hs_certificate: |
724 | 0 | PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3); |
725 | 0 | sender = ss->xtnData.certificateSenders; |
726 | 0 | break; |
727 | 0 |
|
728 | 0 | case ssl_hs_encrypted_extensions: |
729 | 0 | PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3); |
730 | 0 | sender = ss->xtnData.encryptedExtensionsSenders; |
731 | 0 | break; |
732 | 0 |
|
733 | 0 | case ssl_hs_hello_retry_request: |
734 | 0 | PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3); |
735 | 0 | sender = tls13_hrr_senders; |
736 | 0 | break; |
737 | 0 |
|
738 | 0 | default: |
739 | 0 | PORT_Assert(0); |
740 | 0 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
741 | 0 | return SECFailure; |
742 | 0 | } |
743 | 0 |
|
744 | 0 | for (; sender->ex_sender != NULL; ++sender) { |
745 | 0 | PRBool append = PR_FALSE; |
746 | 0 | unsigned int start = buf->len; |
747 | 0 | unsigned int length; |
748 | 0 |
|
749 | 0 | if (ssl_FindCustomExtensionHooks(ss, sender->ex_type)) { |
750 | 0 | continue; |
751 | 0 | } |
752 | 0 | |
753 | 0 | /* Save space for the extension type and length. Note that we don't grow |
754 | 0 | * the buffer now; rely on sslBuffer_Append* to do that. */ |
755 | 0 | buf->len += 4; |
756 | 0 | rv = (*sender->ex_sender)(ss, &ss->xtnData, buf, &append); |
757 | 0 | if (rv != SECSuccess) { |
758 | 0 | goto loser; |
759 | 0 | } |
760 | 0 | |
761 | 0 | /* Save the length and go back to the start. */ |
762 | 0 | length = buf->len - start - 4; |
763 | 0 | buf->len = start; |
764 | 0 | if (!append) { |
765 | 0 | continue; |
766 | 0 | } |
767 | 0 | |
768 | 0 | buf->len = start; |
769 | 0 | rv = sslBuffer_AppendNumber(buf, sender->ex_type, 2); |
770 | 0 | if (rv != SECSuccess) { |
771 | 0 | goto loser; /* Code already set. */ |
772 | 0 | } |
773 | 0 | rv = sslBuffer_AppendNumber(buf, length, 2); |
774 | 0 | if (rv != SECSuccess) { |
775 | 0 | goto loser; /* Code already set. */ |
776 | 0 | } |
777 | 0 | /* Skip over the extension body. */ |
778 | 0 | buf->len += length; |
779 | 0 |
|
780 | 0 | if (message == ssl_hs_client_hello || |
781 | 0 | message == ssl_hs_certificate_request) { |
782 | 0 | ss->xtnData.advertised[ss->xtnData.numAdvertised++] = |
783 | 0 | sender->ex_type; |
784 | 0 | } |
785 | 0 | } |
786 | 0 |
|
787 | 0 | if (!PR_CLIST_IS_EMPTY(&ss->extensionHooks)) { |
788 | 0 | rv = ssl_CallCustomExtensionSenders(ss, buf, message); |
789 | 0 | if (rv != SECSuccess) { |
790 | 0 | goto loser; |
791 | 0 | } |
792 | 0 | } |
793 | 0 | |
794 | 0 | if (buf->len > 0xffff) { |
795 | 0 | PORT_SetError(SSL_ERROR_TX_RECORD_TOO_LONG); |
796 | 0 | goto loser; |
797 | 0 | } |
798 | 0 |
|
799 | 0 | return SECSuccess; |
800 | 0 | |
801 | 0 | loser: |
802 | 0 | sslBuffer_Clear(buf); |
803 | 0 | return SECFailure; |
804 | 0 | } |
805 | | |
806 | | /* This extension sender can be used anywhere that an always empty extension is |
807 | | * needed. Mostly that is for ServerHello where sender registration is dynamic; |
808 | | * ClientHello senders are usually conditional in some way. */ |
809 | | SECStatus |
810 | | ssl_SendEmptyExtension(const sslSocket *ss, TLSExtensionData *xtnData, |
811 | | sslBuffer *buf, PRBool *append) |
812 | 0 | { |
813 | 0 | *append = PR_TRUE; |
814 | 0 | return SECSuccess; |
815 | 0 | } |
816 | | |
817 | | /* Takes the size of the ClientHello, less the record header, and determines how |
818 | | * much padding is required. */ |
819 | | static unsigned int |
820 | | ssl_CalculatePaddingExtLen(const sslSocket *ss, unsigned int clientHelloLength) |
821 | 0 | { |
822 | 0 | unsigned int recordLength = 1 /* handshake message type */ + |
823 | 0 | 3 /* handshake message length */ + |
824 | 0 | clientHelloLength; |
825 | 0 | unsigned int extensionLen; |
826 | 0 |
|
827 | 0 | /* Don't pad for DTLS, for SSLv3, or for renegotiation. */ |
828 | 0 | if (IS_DTLS(ss) || |
829 | 0 | ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_0 || |
830 | 0 | ss->firstHsDone) { |
831 | 0 | return 0; |
832 | 0 | } |
833 | 0 | |
834 | 0 | /* A padding extension may be included to ensure that the record containing |
835 | 0 | * the ClientHello doesn't have a length between 256 and 511 bytes |
836 | 0 | * (inclusive). Initial ClientHello records with such lengths trigger bugs |
837 | 0 | * in F5 devices. */ |
838 | 0 | if (recordLength < 256 || recordLength >= 512) { |
839 | 0 | return 0; |
840 | 0 | } |
841 | 0 | |
842 | 0 | extensionLen = 512 - recordLength; |
843 | 0 | /* Extensions take at least four bytes to encode. Always include at least |
844 | 0 | * one byte of data if we are padding. Some servers will time out or |
845 | 0 | * terminate the connection if the last ClientHello extension is empty. */ |
846 | 0 | if (extensionLen < 5) { |
847 | 0 | extensionLen = 5; |
848 | 0 | } |
849 | 0 |
|
850 | 0 | return extensionLen - 4; |
851 | 0 | } |
852 | | |
853 | | /* ssl3_SendPaddingExtension possibly adds an extension which ensures that a |
854 | | * ClientHello record is either < 256 bytes or is >= 512 bytes. This ensures |
855 | | * that we don't trigger bugs in F5 products. |
856 | | * |
857 | | * This takes an existing extension buffer, |buf|, and the length of the |
858 | | * remainder of the ClientHello, |prefixLen|. It modifies the extension buffer |
859 | | * to insert padding at the right place. |
860 | | */ |
861 | | SECStatus |
862 | | ssl_InsertPaddingExtension(const sslSocket *ss, unsigned int prefixLen, |
863 | | sslBuffer *buf) |
864 | 0 | { |
865 | 0 | static unsigned char padding[252] = { 0 }; |
866 | 0 | unsigned int paddingLen; |
867 | 0 | unsigned int tailLen; |
868 | 0 | SECStatus rv; |
869 | 0 |
|
870 | 0 | /* Account for the size of the header, the length field of the extensions |
871 | 0 | * block and the size of the existing extensions. */ |
872 | 0 | paddingLen = ssl_CalculatePaddingExtLen(ss, prefixLen + 2 + buf->len); |
873 | 0 | if (!paddingLen) { |
874 | 0 | return SECSuccess; |
875 | 0 | } |
876 | 0 | |
877 | 0 | /* Move the tail if there is one. This only happens if we are sending the |
878 | 0 | * TLS 1.3 PSK extension, which needs to be at the end. */ |
879 | 0 | if (ss->xtnData.lastXtnOffset) { |
880 | 0 | PORT_Assert(buf->len > ss->xtnData.lastXtnOffset); |
881 | 0 | tailLen = buf->len - ss->xtnData.lastXtnOffset; |
882 | 0 | rv = sslBuffer_Grow(buf, buf->len + 4 + paddingLen); |
883 | 0 | if (rv != SECSuccess) { |
884 | 0 | return SECFailure; |
885 | 0 | } |
886 | 0 | PORT_Memmove(buf->buf + ss->xtnData.lastXtnOffset + 4 + paddingLen, |
887 | 0 | buf->buf + ss->xtnData.lastXtnOffset, |
888 | 0 | tailLen); |
889 | 0 | buf->len = ss->xtnData.lastXtnOffset; |
890 | 0 | } else { |
891 | 0 | tailLen = 0; |
892 | 0 | } |
893 | 0 |
|
894 | 0 | rv = sslBuffer_AppendNumber(buf, ssl_padding_xtn, 2); |
895 | 0 | if (rv != SECSuccess) { |
896 | 0 | return SECFailure; /* Code already set. */ |
897 | 0 | } |
898 | 0 | rv = sslBuffer_AppendVariable(buf, padding, paddingLen, 2); |
899 | 0 | if (rv != SECSuccess) { |
900 | 0 | return SECFailure; /* Code already set. */ |
901 | 0 | } |
902 | 0 | |
903 | 0 | buf->len += tailLen; |
904 | 0 |
|
905 | 0 | return SECSuccess; |
906 | 0 | } |
907 | | |
908 | | void |
909 | | ssl3_DestroyRemoteExtensions(PRCList *list) |
910 | 0 | { |
911 | 0 | PRCList *cur_p; |
912 | 0 |
|
913 | 0 | while (!PR_CLIST_IS_EMPTY(list)) { |
914 | 0 | cur_p = PR_LIST_TAIL(list); |
915 | 0 | PR_REMOVE_LINK(cur_p); |
916 | 0 | PORT_Free(cur_p); |
917 | 0 | } |
918 | 0 | } |
919 | | |
920 | | /* Initialize the extension data block. */ |
921 | | void |
922 | | ssl3_InitExtensionData(TLSExtensionData *xtnData, const sslSocket *ss) |
923 | 0 | { |
924 | 0 | unsigned int advertisedMax; |
925 | 0 | PRCList *cursor; |
926 | 0 |
|
927 | 0 | /* Set things up to the right starting state. */ |
928 | 0 | PORT_Memset(xtnData, 0, sizeof(*xtnData)); |
929 | 0 | xtnData->peerSupportsFfdheGroups = PR_FALSE; |
930 | 0 | PR_INIT_CLIST(&xtnData->remoteKeyShares); |
931 | 0 |
|
932 | 0 | /* Allocate enough to allow for native extensions, plus any custom ones. */ |
933 | 0 | if (ss->sec.isServer) { |
934 | 0 | advertisedMax = PR_MAX(PR_ARRAY_SIZE(certificateRequestHandlers), |
935 | 0 | PR_ARRAY_SIZE(tls13_cert_req_senders)); |
936 | 0 | } else { |
937 | 0 | advertisedMax = PR_MAX(PR_ARRAY_SIZE(clientHelloHandlers), |
938 | 0 | PR_ARRAY_SIZE(clientHelloSendersTLS)); |
939 | 0 | ++advertisedMax; /* For the RI SCSV, which we also track. */ |
940 | 0 | } |
941 | 0 | for (cursor = PR_NEXT_LINK(&ss->extensionHooks); |
942 | 0 | cursor != &ss->extensionHooks; |
943 | 0 | cursor = PR_NEXT_LINK(cursor)) { |
944 | 0 | ++advertisedMax; |
945 | 0 | } |
946 | 0 | xtnData->advertised = PORT_ZNewArray(PRUint16, advertisedMax); |
947 | 0 | } |
948 | | |
949 | | void |
950 | | ssl3_DestroyExtensionData(TLSExtensionData *xtnData) |
951 | 0 | { |
952 | 0 | ssl3_FreeSniNameArray(xtnData); |
953 | 0 | PORT_Free(xtnData->sigSchemes); |
954 | 0 | SECITEM_FreeItem(&xtnData->nextProto, PR_FALSE); |
955 | 0 | tls13_DestroyKeyShares(&xtnData->remoteKeyShares); |
956 | 0 | SECITEM_FreeItem(&xtnData->certReqContext, PR_FALSE); |
957 | 0 | SECITEM_FreeItem(&xtnData->applicationToken, PR_FALSE); |
958 | 0 | if (xtnData->certReqAuthorities.arena) { |
959 | 0 | PORT_FreeArena(xtnData->certReqAuthorities.arena, PR_FALSE); |
960 | 0 | xtnData->certReqAuthorities.arena = NULL; |
961 | 0 | } |
962 | 0 | PORT_Free(xtnData->advertised); |
963 | 0 | } |
964 | | |
965 | | /* Free everything that has been allocated and then reset back to |
966 | | * the starting state. */ |
967 | | void |
968 | | ssl3_ResetExtensionData(TLSExtensionData *xtnData, const sslSocket *ss) |
969 | 0 | { |
970 | 0 | ssl3_DestroyExtensionData(xtnData); |
971 | 0 | ssl3_InitExtensionData(xtnData, ss); |
972 | 0 | } |
973 | | |
974 | | /* Thunks to let extension handlers operate on const sslSocket* objects. */ |
975 | | void |
976 | | ssl3_ExtSendAlert(const sslSocket *ss, SSL3AlertLevel level, |
977 | | SSL3AlertDescription desc) |
978 | 0 | { |
979 | 0 | (void)SSL3_SendAlert((sslSocket *)ss, level, desc); |
980 | 0 | } |
981 | | |
982 | | void |
983 | | ssl3_ExtDecodeError(const sslSocket *ss) |
984 | 0 | { |
985 | 0 | (void)ssl3_DecodeError((sslSocket *)ss); |
986 | 0 | } |
987 | | |
988 | | SECStatus |
989 | | ssl3_ExtConsumeHandshake(const sslSocket *ss, void *v, PRUint32 bytes, |
990 | | PRUint8 **b, PRUint32 *length) |
991 | 0 | { |
992 | 0 | return ssl3_ConsumeHandshake((sslSocket *)ss, v, bytes, b, length); |
993 | 0 | } |
994 | | |
995 | | SECStatus |
996 | | ssl3_ExtConsumeHandshakeNumber(const sslSocket *ss, PRUint32 *num, |
997 | | PRUint32 bytes, PRUint8 **b, PRUint32 *length) |
998 | 0 | { |
999 | 0 | return ssl3_ConsumeHandshakeNumber((sslSocket *)ss, num, bytes, b, length); |
1000 | 0 | } |
1001 | | |
1002 | | SECStatus |
1003 | | ssl3_ExtConsumeHandshakeVariable(const sslSocket *ss, SECItem *i, |
1004 | | PRUint32 bytes, PRUint8 **b, |
1005 | | PRUint32 *length) |
1006 | 0 | { |
1007 | 0 | return ssl3_ConsumeHandshakeVariable((sslSocket *)ss, i, bytes, b, length); |
1008 | 0 | } |