]>
Commit | Line | Data |
---|---|---|
6b473aca MC |
1 | /* |
2 | * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. | |
3 | * | |
4 | * Licensed under the OpenSSL license (the "License"). You may not use | |
5 | * this file except in compliance with the License. You can obtain a copy | |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
8 | */ | |
9 | ||
10 | #include <stdlib.h> | |
6b473aca MC |
11 | #include "../ssl_locl.h" |
12 | #include "statem_locl.h" | |
13 | ||
6b473aca MC |
14 | typedef struct { |
15 | /* The ID for the extension */ | |
16 | unsigned int type; | |
17 | int (*server_parse)(SSL *s, PACKET *pkt, int *al); | |
18 | int (*client_parse)(SSL *s, PACKET *pkt, int *al); | |
224135e9 MC |
19 | int (*server_construct)(SSL *s, WPACKET *pkt, int *al); |
20 | int (*client_construct)(SSL *s, WPACKET *pkt, int *al); | |
6b473aca MC |
21 | unsigned int context; |
22 | } EXTENSION_DEFINITION; | |
23 | ||
4b299b8e MC |
24 | /* |
25 | * TODO(TLS1.3): Temporarily modified the definitions below to put all TLS1.3 | |
26 | * extensions in the ServerHello for now. That needs to be put back to correct | |
27 | * setting once encrypted extensions is working properly. | |
28 | */ | |
6b473aca MC |
29 | static const EXTENSION_DEFINITION ext_defs[] = { |
30 | { | |
31 | TLSEXT_TYPE_renegotiate, | |
32 | tls_parse_clienthello_renegotiate, | |
33 | NULL, | |
224135e9 MC |
34 | NULL, |
35 | NULL, | |
6b473aca MC |
36 | EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_SSL3_ALLOWED |
37 | | EXT_TLS1_2_AND_BELOW_ONLY | |
38 | }, | |
39 | { | |
40 | TLSEXT_TYPE_server_name, | |
41 | tls_parse_clienthello_server_name, | |
42 | NULL, | |
224135e9 MC |
43 | NULL, |
44 | NULL, | |
6b473aca | 45 | EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO |
4b299b8e | 46 | | /*EXT_TLS1_3_ENCRYPTED_EXTENSIONS*/EXT_TLS1_3_SERVER_HELLO |
6b473aca MC |
47 | }, |
48 | #ifndef OPENSSL_NO_SRP | |
49 | { | |
50 | TLSEXT_TYPE_srp, | |
51 | tls_parse_clienthello_srp, | |
52 | NULL, | |
224135e9 MC |
53 | NULL, |
54 | NULL, | |
6b473aca MC |
55 | EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY |
56 | }, | |
57 | #endif | |
58 | #ifndef OPENSSL_NO_EC | |
59 | { | |
60 | TLSEXT_TYPE_ec_point_formats, | |
61 | tls_parse_clienthello_ec_pt_formats, | |
62 | NULL, | |
224135e9 MC |
63 | NULL, |
64 | NULL, | |
6b473aca MC |
65 | EXT_CLIENT_HELLO | EXT_TLS1_2_AND_BELOW_ONLY |
66 | }, | |
67 | { | |
68 | TLSEXT_TYPE_supported_groups, | |
69 | tls_parse_clienthello_supported_groups, | |
70 | NULL, | |
224135e9 MC |
71 | NULL, |
72 | NULL, | |
4b299b8e MC |
73 | EXT_CLIENT_HELLO |
74 | | /*EXT_TLS1_3_ENCRYPTED_EXTENSIONS*/EXT_TLS1_3_SERVER_HELLO | |
6b473aca MC |
75 | }, |
76 | #endif | |
77 | { | |
78 | TLSEXT_TYPE_session_ticket, | |
79 | tls_parse_clienthello_session_ticket, | |
80 | NULL, | |
224135e9 MC |
81 | NULL, |
82 | NULL, | |
6b473aca MC |
83 | EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY |
84 | }, | |
85 | { | |
86 | TLSEXT_TYPE_signature_algorithms, | |
87 | tls_parse_clienthello_sig_algs, | |
88 | NULL, | |
224135e9 MC |
89 | NULL, |
90 | NULL, | |
6b473aca MC |
91 | EXT_CLIENT_HELLO |
92 | }, | |
93 | { | |
94 | TLSEXT_TYPE_status_request, | |
95 | tls_parse_clienthello_status_request, | |
96 | NULL, | |
224135e9 MC |
97 | NULL, |
98 | NULL, | |
4b299b8e MC |
99 | EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO |
100 | | /*EXT_TLS1_3_CERTIFICATE*/EXT_TLS1_3_SERVER_HELLO | |
6b473aca MC |
101 | }, |
102 | #ifndef OPENSSL_NO_NEXTPROTONEG | |
103 | { | |
104 | TLSEXT_TYPE_next_proto_neg, | |
105 | tls_parse_clienthello_npn, | |
106 | NULL, | |
224135e9 MC |
107 | NULL, |
108 | NULL, | |
6b473aca MC |
109 | EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY |
110 | }, | |
111 | #endif | |
112 | { | |
113 | TLSEXT_TYPE_application_layer_protocol_negotiation, | |
114 | tls_parse_clienthello_alpn, | |
115 | NULL, | |
224135e9 MC |
116 | NULL, |
117 | NULL, | |
6b473aca | 118 | EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO |
4b299b8e | 119 | | /*EXT_TLS1_3_ENCRYPTED_EXTENSIONS*/EXT_TLS1_3_SERVER_HELLO |
6b473aca MC |
120 | }, |
121 | { | |
122 | TLSEXT_TYPE_use_srtp, | |
123 | tls_parse_clienthello_use_srtp, | |
124 | NULL, | |
224135e9 MC |
125 | NULL, |
126 | NULL, | |
6b473aca MC |
127 | EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO |
128 | | EXT_TLS1_3_ENCRYPTED_EXTENSIONS | EXT_DTLS_ONLY | |
129 | }, | |
130 | { | |
131 | TLSEXT_TYPE_encrypt_then_mac, | |
132 | tls_parse_clienthello_etm, | |
133 | NULL, | |
224135e9 MC |
134 | NULL, |
135 | NULL, | |
6b473aca MC |
136 | EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY |
137 | }, | |
138 | { | |
139 | TLSEXT_TYPE_signed_certificate_timestamp, | |
140 | /* | |
141 | * No server side support for this, but can be provided by a custom | |
142 | * extension. This is an exception to the rule that custom extensions | |
143 | * cannot override built in ones. | |
144 | */ | |
145 | NULL, | |
146 | NULL, | |
224135e9 MC |
147 | NULL, |
148 | NULL, | |
4b299b8e MC |
149 | EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO |
150 | | /*EXT_TLS1_3_CERTIFICATE*/EXT_TLS1_3_SERVER_HELLO | |
6b473aca MC |
151 | }, |
152 | { | |
153 | TLSEXT_TYPE_extended_master_secret, | |
154 | tls_parse_clienthello_ems, | |
155 | NULL, | |
4b299b8e MC |
156 | NULL, |
157 | NULL, | |
6b473aca MC |
158 | EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY |
159 | }, | |
160 | { | |
161 | TLSEXT_TYPE_supported_versions, | |
162 | /* Processed inline as part of version selection */ | |
163 | NULL, | |
164 | NULL, | |
224135e9 MC |
165 | NULL, |
166 | NULL, | |
6b473aca MC |
167 | EXT_CLIENT_HELLO | EXT_TLS_IMPLEMENTATION_ONLY |
168 | }, | |
169 | { | |
170 | TLSEXT_TYPE_padding, | |
171 | /* We send this, but don't read it */ | |
172 | NULL, | |
173 | NULL, | |
224135e9 MC |
174 | NULL, |
175 | NULL, | |
6b473aca MC |
176 | EXT_CLIENT_HELLO |
177 | }, | |
178 | { | |
179 | TLSEXT_TYPE_key_share, | |
180 | tls_parse_clienthello_key_share, | |
181 | NULL, | |
224135e9 MC |
182 | NULL, |
183 | NULL, | |
6b473aca MC |
184 | EXT_CLIENT_HELLO | EXT_TLS1_3_SERVER_HELLO |
185 | | EXT_TLS1_3_HELLO_RETRY_REQUEST | EXT_TLS_IMPLEMENTATION_ONLY | |
186 | | EXT_TLS1_3_ONLY | |
187 | } | |
188 | }; | |
189 | ||
190 | /* | |
191 | * Comparison function used in a call to qsort (see tls_collect_extensions() | |
192 | * below.) | |
193 | * The two arguments |p1| and |p2| are expected to be pointers to RAW_EXTENSIONs | |
194 | * | |
195 | * Returns: | |
196 | * 1 if the type for p1 is greater than p2 | |
197 | * 0 if the type for p1 and p2 are the same | |
198 | * -1 if the type for p1 is less than p2 | |
199 | */ | |
200 | static int compare_extensions(const void *p1, const void *p2) | |
201 | { | |
202 | const RAW_EXTENSION *e1 = (const RAW_EXTENSION *)p1; | |
203 | const RAW_EXTENSION *e2 = (const RAW_EXTENSION *)p2; | |
204 | ||
205 | if (e1->type < e2->type) | |
206 | return -1; | |
207 | else if (e1->type > e2->type) | |
208 | return 1; | |
209 | ||
210 | return 0; | |
211 | } | |
212 | ||
213 | /* | |
214 | * Verify whether we are allowed to use the extension |type| in the current | |
215 | * |context|. Returns 1 to indicate the extension is allowed or unknown or 0 to | |
216 | * indicate the extension is not allowed. | |
217 | */ | |
218 | static int verify_extension(SSL *s, unsigned int context, unsigned int type) | |
219 | { | |
220 | size_t i; | |
221 | ||
222 | for (i = 0; i < OSSL_NELEM(ext_defs); i++) { | |
223 | if (type == ext_defs[i].type) { | |
224 | /* Check we're allowed to use this extension in this context */ | |
225 | if ((context & ext_defs[i].context) == 0) | |
226 | return 0; | |
227 | ||
228 | if (SSL_IS_DTLS(s)) { | |
229 | if ((ext_defs[i].context & EXT_TLS_ONLY) != 0) | |
230 | return 0; | |
231 | } else if ((ext_defs[i].context & EXT_DTLS_ONLY) != 0) { | |
232 | return 0; | |
233 | } | |
234 | ||
235 | return 1; | |
236 | } | |
237 | } | |
238 | ||
239 | /* Unknown extension. We allow it */ | |
240 | return 1; | |
241 | } | |
242 | ||
243 | /* | |
244 | * Finds an extension definition for the give extension |type|. | |
245 | * Returns 1 if found and stores the definition in |*def|, or returns 0 | |
246 | * otherwise. | |
247 | */ | |
248 | static int find_extension_definition(SSL *s, unsigned int type, | |
249 | const EXTENSION_DEFINITION **def) | |
250 | { | |
251 | size_t i; | |
252 | ||
253 | for (i = 0; i < OSSL_NELEM(ext_defs); i++) { | |
254 | if (type == ext_defs[i].type) { | |
255 | *def = &ext_defs[i]; | |
256 | return 1; | |
257 | } | |
258 | } | |
259 | ||
260 | /* Unknown extension */ | |
261 | return 0; | |
262 | } | |
263 | ||
264 | /* | |
265 | * Gather a list of all the extensions from the data in |packet]. |context| | |
266 | * tells us which message this extension is for. The raw extension data is | |
267 | * stored in |*res| with the number of found extensions in |*numfound|. In the | |
268 | * event of an error the alert type to use is stored in |*ad|. We don't actually | |
269 | * process the content of the extensions yet, except to check their types. | |
270 | * | |
271 | * Per http://tools.ietf.org/html/rfc5246#section-7.4.1.4, there may not be | |
272 | * more than one extension of the same type in a ClientHello or ServerHello. | |
273 | * This function returns 1 if all extensions are unique and we have parsed their | |
274 | * types, and 0 if the extensions contain duplicates, could not be successfully | |
275 | * parsed, or an internal error occurred. | |
276 | */ | |
277 | /* | |
278 | * TODO(TLS1.3): Refactor ServerHello extension parsing to use this and then | |
279 | * remove tls1_check_duplicate_extensions() | |
280 | */ | |
281 | int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context, | |
282 | RAW_EXTENSION **res, size_t *numfound, int *ad) | |
283 | { | |
284 | PACKET extensions = *packet; | |
285 | size_t num_extensions = 0, i = 0; | |
286 | RAW_EXTENSION *raw_extensions = NULL; | |
287 | ||
288 | /* First pass: count the extensions. */ | |
289 | while (PACKET_remaining(&extensions) > 0) { | |
290 | unsigned int type; | |
291 | PACKET extension; | |
292 | ||
293 | if (!PACKET_get_net_2(&extensions, &type) || | |
294 | !PACKET_get_length_prefixed_2(&extensions, &extension)) { | |
295 | SSLerr(SSL_F_TLS_COLLECT_EXTENSIONS, SSL_R_BAD_EXTENSION); | |
296 | *ad = SSL_AD_DECODE_ERROR; | |
297 | goto err; | |
298 | } | |
299 | /* Verify this extension is allowed */ | |
300 | if (!verify_extension(s, context, type)) { | |
301 | SSLerr(SSL_F_TLS_COLLECT_EXTENSIONS, SSL_R_BAD_EXTENSION); | |
302 | *ad = SSL_AD_ILLEGAL_PARAMETER; | |
303 | goto err; | |
304 | } | |
305 | num_extensions++; | |
306 | } | |
307 | ||
308 | if (num_extensions > 0) { | |
309 | raw_extensions = OPENSSL_zalloc(sizeof(*raw_extensions) | |
310 | * num_extensions); | |
311 | if (raw_extensions == NULL) { | |
312 | *ad = SSL_AD_INTERNAL_ERROR; | |
313 | SSLerr(SSL_F_TLS_COLLECT_EXTENSIONS, ERR_R_MALLOC_FAILURE); | |
314 | goto err; | |
315 | } | |
316 | ||
317 | /* Second pass: collect the extensions. */ | |
318 | for (i = 0; i < num_extensions; i++) { | |
319 | if (!PACKET_get_net_2(packet, &raw_extensions[i].type) || | |
320 | !PACKET_get_length_prefixed_2(packet, | |
321 | &raw_extensions[i].data)) { | |
322 | /* This should not happen. */ | |
323 | *ad = SSL_AD_INTERNAL_ERROR; | |
324 | SSLerr(SSL_F_TLS_COLLECT_EXTENSIONS, ERR_R_INTERNAL_ERROR); | |
325 | goto err; | |
326 | } | |
327 | } | |
328 | ||
329 | if (PACKET_remaining(packet) != 0) { | |
330 | *ad = SSL_AD_DECODE_ERROR; | |
331 | SSLerr(SSL_F_TLS_COLLECT_EXTENSIONS, SSL_R_LENGTH_MISMATCH); | |
332 | goto err; | |
333 | } | |
334 | /* Sort the extensions and make sure there are no duplicates. */ | |
335 | qsort(raw_extensions, num_extensions, sizeof(*raw_extensions), | |
336 | compare_extensions); | |
337 | for (i = 1; i < num_extensions; i++) { | |
338 | if (raw_extensions[i - 1].type == raw_extensions[i].type) { | |
339 | *ad = SSL_AD_DECODE_ERROR; | |
340 | goto err; | |
341 | } | |
342 | } | |
343 | } | |
344 | ||
345 | *res = raw_extensions; | |
346 | *numfound = num_extensions; | |
347 | return 1; | |
348 | ||
349 | err: | |
350 | OPENSSL_free(raw_extensions); | |
351 | return 0; | |
352 | } | |
353 | ||
4b299b8e MC |
354 | int tls_parse_all_extensions(SSL *s, int context, RAW_EXTENSION *exts, |
355 | size_t numexts, int *al) | |
6b473aca MC |
356 | { |
357 | size_t loop; | |
358 | ||
359 | for (loop = 0; loop < numexts; loop++) { | |
360 | RAW_EXTENSION *currext = &exts[loop]; | |
361 | const EXTENSION_DEFINITION *extdef = NULL; | |
362 | int (*parser)(SSL *s, PACKET *pkt, int *al) = NULL; | |
363 | ||
364 | if (s->tlsext_debug_cb) | |
365 | s->tlsext_debug_cb(s, 0, currext->type, | |
366 | PACKET_data(&currext->data), | |
367 | PACKET_remaining(&currext->data), | |
368 | s->tlsext_debug_arg); | |
369 | ||
370 | /* Skip if we've already parsed this extension */ | |
371 | if (currext->parsed) | |
372 | continue; | |
373 | ||
374 | currext->parsed = 1; | |
375 | ||
376 | parser = NULL; | |
224135e9 | 377 | if (find_extension_definition(s, currext->type, &extdef)) { |
6b473aca MC |
378 | parser = s->server ? extdef->server_parse : extdef->client_parse; |
379 | ||
224135e9 MC |
380 | /* Check if extension is defined for our protocol. If not, skip */ |
381 | if ((SSL_IS_DTLS(s) | |
382 | && (extdef->context & EXT_TLS_IMPLEMENTATION_ONLY) != 0) | |
383 | || (s->version == SSL3_VERSION | |
384 | && (extdef->context & EXT_SSL3_ALLOWED) == 0) | |
385 | || (SSL_IS_TLS13(s) | |
386 | && (extdef->context & EXT_TLS1_2_AND_BELOW_ONLY) != 0) | |
387 | || (!SSL_IS_TLS13(s) | |
388 | && (extdef->context & EXT_TLS1_3_ONLY) != 0)) | |
389 | continue; | |
390 | } | |
391 | ||
6b473aca MC |
392 | if (parser == NULL) { |
393 | /* | |
394 | * Could be a custom extension. We only allow this if it is a non | |
224135e9 MC |
395 | * resumed session on the server side. |
396 | * | |
397 | * TODO(TLS1.3): We only allow old style <=TLS1.2 custom extensions. | |
398 | * We're going to need a new mechanism for TLS1.3 to specify which | |
399 | * messages to add the custom extensions to. | |
6b473aca MC |
400 | */ |
401 | if ((!s->hit || !s->server) | |
224135e9 MC |
402 | && (context |
403 | & (EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO)) != 0 | |
6b473aca MC |
404 | && custom_ext_parse(s, s->server, currext->type, |
405 | PACKET_data(&currext->data), | |
406 | PACKET_remaining(&currext->data), | |
407 | al) <= 0) | |
408 | return 0; | |
409 | ||
410 | continue; | |
411 | } | |
412 | ||
6b473aca MC |
413 | if (!parser(s, &currext->data, al)) |
414 | return 0; | |
415 | } | |
416 | ||
417 | return 1; | |
418 | } | |
419 | ||
420 | /* | |
421 | * Find a specific extension by |type| in the list |exts| containing |numexts| | |
422 | * extensions, and the parse it immediately. Returns 1 on success, or 0 on | |
423 | * failure. If a failure has occurred then |*al| will also be set to the alert | |
424 | * to be sent. | |
425 | */ | |
4b299b8e MC |
426 | int tls_parse_extension(SSL *s, int type, int context, RAW_EXTENSION *exts, |
427 | size_t numexts, int *al) | |
6b473aca MC |
428 | { |
429 | RAW_EXTENSION *ext = tls_get_extension_by_type(exts, numexts, type); | |
430 | ||
431 | if (ext == NULL) | |
432 | return 1; | |
433 | ||
4b299b8e | 434 | return tls_parse_all_extensions(s, context, ext, 1, al); |
6b473aca MC |
435 | } |
436 | ||
224135e9 MC |
437 | int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context, |
438 | int *al) | |
439 | { | |
440 | size_t loop; | |
441 | int addcustom = 0; | |
442 | ||
443 | if (!WPACKET_start_sub_packet_u16(pkt) | |
444 | /* | |
445 | * If extensions are of zero length then we don't even add the | |
446 | * extensions length bytes to a ClientHello | |
447 | */ | |
448 | || ((context & EXT_CLIENT_HELLO) != 0 | |
449 | && !WPACKET_set_flags(pkt, | |
450 | WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH))) { | |
451 | *al = SSL_AD_INTERNAL_ERROR; | |
452 | SSLerr(SSL_F_TLS_CONSTRUCT_EXTENSIONS, ERR_R_INTERNAL_ERROR); | |
453 | return 0; | |
454 | } | |
455 | ||
456 | for (loop = 0; loop < OSSL_NELEM(ext_defs); loop++) { | |
4b299b8e MC |
457 | int (*construct)(SSL *s, WPACKET *pkt, int *al); |
458 | ||
224135e9 MC |
459 | /* Skip if not relevant for our context */ |
460 | if ((ext_defs[loop].context & context) == 0) | |
461 | continue; | |
462 | ||
4b299b8e MC |
463 | construct = s->server ? ext_defs[loop].server_construct |
464 | : ext_defs[loop].client_construct; | |
224135e9 MC |
465 | |
466 | /* Check if this extension is defined for our protocol. If not, skip */ | |
467 | if ((SSL_IS_DTLS(s) | |
4b299b8e MC |
468 | && (ext_defs[loop].context & EXT_TLS_IMPLEMENTATION_ONLY) |
469 | != 0) | |
224135e9 | 470 | || (s->version == SSL3_VERSION |
4b299b8e | 471 | && (ext_defs[loop].context & EXT_SSL3_ALLOWED) == 0) |
224135e9 | 472 | || (SSL_IS_TLS13(s) |
4b299b8e MC |
473 | && (ext_defs[loop].context & EXT_TLS1_2_AND_BELOW_ONLY) |
474 | != 0) | |
224135e9 | 475 | || (!SSL_IS_TLS13(s) |
4b299b8e MC |
476 | && (ext_defs[loop].context & EXT_TLS1_3_ONLY) != 0 |
477 | && (context & EXT_CLIENT_HELLO) == 0) | |
224135e9 MC |
478 | || construct == NULL) |
479 | continue; | |
480 | ||
481 | if (!construct(s, pkt, al)) | |
482 | return 0; | |
483 | } | |
484 | ||
224135e9 MC |
485 | /* Add custom extensions */ |
486 | if ((context & EXT_CLIENT_HELLO) != 0) { | |
487 | custom_ext_init(&s->cert->cli_ext); | |
488 | addcustom = 1; | |
4b299b8e | 489 | } else if ((context & EXT_TLS1_2_SERVER_HELLO) != 0) { |
224135e9 MC |
490 | /* |
491 | * We already initialised the custom extensions during ClientHello | |
492 | * parsing. | |
493 | * | |
494 | * TODO(TLS1.3): We're going to need a new custom extension mechanism | |
495 | * for TLS1.3, so that custom extensions can specify which of the | |
496 | * multiple message they wish to add themselves to. | |
497 | */ | |
498 | addcustom = 1; | |
499 | } | |
4b299b8e | 500 | |
224135e9 | 501 | if (addcustom && !custom_ext_add(s, s->server, pkt, al)) { |
4b299b8e | 502 | SSLerr(SSL_F_TLS_CONSTRUCT_EXTENSIONS, ERR_R_INTERNAL_ERROR); |
224135e9 MC |
503 | return 0; |
504 | } | |
505 | ||
506 | if (!WPACKET_close(pkt)) { | |
4b299b8e | 507 | *al = SSL_AD_INTERNAL_ERROR; |
224135e9 MC |
508 | SSLerr(SSL_F_TLS_CONSTRUCT_EXTENSIONS, ERR_R_INTERNAL_ERROR); |
509 | return 0; | |
510 | } | |
511 | ||
512 | return 1; | |
513 | } |