/src/wolfssl/src/ssl_api_ext.c
Line | Count | Source |
1 | | /* ssl_api_ext.c |
2 | | * |
3 | | * Copyright (C) 2006-2026 wolfSSL Inc. |
4 | | * |
5 | | * This file is part of wolfSSL. |
6 | | * |
7 | | * wolfSSL is free software; you can redistribute it and/or modify |
8 | | * it under the terms of the GNU General Public License as published by |
9 | | * the Free Software Foundation; either version 3 of the License, or |
10 | | * (at your option) any later version. |
11 | | * |
12 | | * wolfSSL is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | * GNU General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU General Public License |
18 | | * along with this program; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA |
20 | | */ |
21 | | |
22 | | #include <wolfssl/wolfcrypt/libwolfssl_sources.h> |
23 | | |
24 | | #if !defined(WOLFSSL_SSL_API_EXT_INCLUDED) |
25 | | #ifndef WOLFSSL_IGNORE_FILE_WARN |
26 | | #warning ssl_api_ext.c does not need to be compiled separately from ssl.c |
27 | | #endif |
28 | | #else |
29 | | |
30 | | #ifndef WOLFCRYPT_ONLY |
31 | | #ifndef NO_TLS |
32 | | |
33 | | #ifdef HAVE_SNI |
34 | | |
35 | | /* Set the Server Name Indication extension data on the object. |
36 | | * |
37 | | * @param [in] ssl SSL/TLS object. |
38 | | * @param [in] type SNI type, e.g. WOLFSSL_SNI_HOST_NAME. |
39 | | * @param [in] data SNI data. |
40 | | * @param [in] size Length of SNI data in bytes. |
41 | | * @return WOLFSSL_SUCCESS on success. |
42 | | * @return BAD_FUNC_ARG when ssl is NULL. |
43 | | * @return Negative value on error. |
44 | | */ |
45 | | WOLFSSL_ABI |
46 | | int wolfSSL_UseSNI(WOLFSSL* ssl, byte type, const void* data, word16 size) |
47 | 0 | { |
48 | 0 | if (ssl == NULL) |
49 | 0 | return BAD_FUNC_ARG; |
50 | | |
51 | 0 | return TLSX_UseSNI(&ssl->extensions, type, data, size, ssl->heap); |
52 | 0 | } |
53 | | |
54 | | |
55 | | /* Set the Server Name Indication extension data on the context. |
56 | | * |
57 | | * @param [in] ctx SSL/TLS context object. |
58 | | * @param [in] type SNI type, e.g. WOLFSSL_SNI_HOST_NAME. |
59 | | * @param [in] data SNI data. |
60 | | * @param [in] size Length of SNI data in bytes. |
61 | | * @return WOLFSSL_SUCCESS on success. |
62 | | * @return BAD_FUNC_ARG when ctx is NULL. |
63 | | * @return Negative value on error. |
64 | | */ |
65 | | WOLFSSL_ABI |
66 | | int wolfSSL_CTX_UseSNI(WOLFSSL_CTX* ctx, byte type, const void* data, |
67 | | word16 size) |
68 | 0 | { |
69 | 0 | if (ctx == NULL) |
70 | 0 | return BAD_FUNC_ARG; |
71 | | |
72 | 0 | return TLSX_UseSNI(&ctx->extensions, type, data, size, ctx->heap); |
73 | 0 | } |
74 | | |
75 | | #ifndef NO_WOLFSSL_SERVER |
76 | | |
77 | | /* Set options for the Server Name Indication extension on the object. |
78 | | * |
79 | | * @param [in] ssl SSL/TLS object. |
80 | | * @param [in] type SNI type. |
81 | | * @param [in] options Bitmask of SNI options. |
82 | | */ |
83 | | void wolfSSL_SNI_SetOptions(WOLFSSL* ssl, byte type, byte options) |
84 | 0 | { |
85 | 0 | if ((ssl != NULL) && (ssl->extensions != NULL)) { |
86 | 0 | TLSX_SNI_SetOptions(ssl->extensions, type, options); |
87 | 0 | } |
88 | 0 | } |
89 | | |
90 | | |
91 | | /* Set options for the Server Name Indication extension on the context. |
92 | | * |
93 | | * @param [in] ctx SSL/TLS context object. |
94 | | * @param [in] type SNI type. |
95 | | * @param [in] options Bitmask of SNI options. |
96 | | */ |
97 | | void wolfSSL_CTX_SNI_SetOptions(WOLFSSL_CTX* ctx, byte type, byte options) |
98 | 0 | { |
99 | 0 | if ((ctx != NULL) && (ctx->extensions != NULL)) { |
100 | 0 | TLSX_SNI_SetOptions(ctx->extensions, type, options); |
101 | 0 | } |
102 | 0 | } |
103 | | |
104 | | |
105 | | /* Get the status of the Server Name Indication extension on the object. |
106 | | * |
107 | | * @param [in] ssl SSL/TLS object. |
108 | | * @param [in] type SNI type. |
109 | | * @return SNI status for the type. |
110 | | */ |
111 | | byte wolfSSL_SNI_Status(WOLFSSL* ssl, byte type) |
112 | 0 | { |
113 | 0 | return TLSX_SNI_Status((ssl != NULL) ? ssl->extensions : NULL, type); |
114 | 0 | } |
115 | | |
116 | | |
117 | | /* Get the Server Name Indication request data received from the peer. |
118 | | * |
119 | | * @param [in] ssl SSL/TLS object. |
120 | | * @param [in] type SNI type. |
121 | | * @param [out] data Pointer to the SNI request data. May be NULL. |
122 | | * @return Length of the SNI request data in bytes, or 0 when none. |
123 | | */ |
124 | | word16 wolfSSL_SNI_GetRequest(WOLFSSL* ssl, byte type, void** data) |
125 | 0 | { |
126 | 0 | if (data) |
127 | 0 | *data = NULL; |
128 | |
|
129 | 0 | if (ssl && ssl->extensions) |
130 | 0 | return TLSX_SNI_GetRequest(ssl->extensions, type, data, 0); |
131 | | |
132 | 0 | return 0; |
133 | 0 | } |
134 | | |
135 | | |
136 | | /* Get the Server Name Indication data from a raw ClientHello buffer. |
137 | | * |
138 | | * @param [in] clientHello ClientHello message buffer. |
139 | | * @param [in] helloSz Length of the ClientHello in bytes. |
140 | | * @param [in] type SNI type. |
141 | | * @param [out] sni Buffer to hold the SNI data. |
142 | | * @param [in, out] inOutSz In: size of buffer. Out: length of SNI data. |
143 | | * @return WOLFSSL_SUCCESS on success. |
144 | | * @return BAD_FUNC_ARG when an argument is NULL or a size is zero. |
145 | | */ |
146 | | int wolfSSL_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz, |
147 | | byte type, byte* sni, word32* inOutSz) |
148 | 0 | { |
149 | 0 | if (clientHello && helloSz > 0 && sni && inOutSz && *inOutSz > 0) |
150 | 0 | return TLSX_SNI_GetFromBuffer(clientHello, helloSz, type, sni, inOutSz); |
151 | | |
152 | 0 | return BAD_FUNC_ARG; |
153 | 0 | } |
154 | | |
155 | | #endif /* !NO_WOLFSSL_SERVER */ |
156 | | |
157 | | #endif /* HAVE_SNI */ |
158 | | |
159 | | |
160 | | #ifdef HAVE_TRUSTED_CA |
161 | | |
162 | | /* Set the Trusted CA Indication extension on the object. |
163 | | * |
164 | | * @param [in] ssl SSL/TLS object. |
165 | | * @param [in] type Trusted CA identifier type. |
166 | | * @param [in] certId Certificate identifier data. |
167 | | * @param [in] certIdSz Length of certificate identifier in bytes. |
168 | | * @return WOLFSSL_SUCCESS on success. |
169 | | * @return BAD_FUNC_ARG when ssl is NULL or arguments are inconsistent with |
170 | | * the type. |
171 | | */ |
172 | | int wolfSSL_UseTrustedCA(WOLFSSL* ssl, byte type, |
173 | | const byte* certId, word32 certIdSz) |
174 | | { |
175 | | if (ssl == NULL) |
176 | | return BAD_FUNC_ARG; |
177 | | |
178 | | if (type == WOLFSSL_TRUSTED_CA_PRE_AGREED) { |
179 | | if (certId != NULL || certIdSz != 0) |
180 | | return BAD_FUNC_ARG; |
181 | | } |
182 | | else if (type == WOLFSSL_TRUSTED_CA_X509_NAME) { |
183 | | if (certId == NULL || certIdSz == 0) |
184 | | return BAD_FUNC_ARG; |
185 | | } |
186 | | #ifndef NO_SHA |
187 | | else if (type == WOLFSSL_TRUSTED_CA_KEY_SHA1 || |
188 | | type == WOLFSSL_TRUSTED_CA_CERT_SHA1) { |
189 | | if (certId == NULL || certIdSz != WC_SHA_DIGEST_SIZE) |
190 | | return BAD_FUNC_ARG; |
191 | | } |
192 | | #endif |
193 | | else |
194 | | return BAD_FUNC_ARG; |
195 | | |
196 | | return TLSX_UseTrustedCA(&ssl->extensions, |
197 | | type, certId, certIdSz, ssl->heap); |
198 | | } |
199 | | |
200 | | #endif /* HAVE_TRUSTED_CA */ |
201 | | |
202 | | |
203 | | #ifdef HAVE_MAX_FRAGMENT |
204 | | #ifndef NO_WOLFSSL_CLIENT |
205 | | |
206 | | /* Set the Maximum Fragment Length extension on the object. |
207 | | * |
208 | | * @param [in] ssl SSL/TLS object. |
209 | | * @param [in] mfl Maximum fragment length code, e.g. WOLFSSL_MFL_2_9. |
210 | | * @return WOLFSSL_SUCCESS on success. |
211 | | * @return BAD_FUNC_ARG when ssl is NULL. |
212 | | * @return Negative value on error. |
213 | | */ |
214 | | int wolfSSL_UseMaxFragment(WOLFSSL* ssl, byte mfl) |
215 | | { |
216 | | if (ssl == NULL) |
217 | | return BAD_FUNC_ARG; |
218 | | |
219 | | #ifdef WOLFSSL_ALLOW_MAX_FRAGMENT_ADJUST |
220 | | /* The following is a non-standard way to reconfigure the max packet size |
221 | | post-handshake for wolfSSL_write/wolfSSL_read */ |
222 | | if (ssl->options.handShakeState == HANDSHAKE_DONE) { |
223 | | switch (mfl) { |
224 | | case WOLFSSL_MFL_2_8 : ssl->max_fragment = 256; break; |
225 | | case WOLFSSL_MFL_2_9 : ssl->max_fragment = 512; break; |
226 | | case WOLFSSL_MFL_2_10: ssl->max_fragment = 1024; break; |
227 | | case WOLFSSL_MFL_2_11: ssl->max_fragment = 2048; break; |
228 | | case WOLFSSL_MFL_2_12: ssl->max_fragment = 4096; break; |
229 | | case WOLFSSL_MFL_2_13: ssl->max_fragment = 8192; break; |
230 | | default: ssl->max_fragment = MAX_RECORD_SIZE; break; |
231 | | } |
232 | | return WOLFSSL_SUCCESS; |
233 | | } |
234 | | #endif /* WOLFSSL_MAX_FRAGMENT_ADJUST */ |
235 | | |
236 | | /* This call sets the max fragment TLS extension, which gets sent to server. |
237 | | The server_hello response is what sets the `ssl->max_fragment` in |
238 | | TLSX_MFL_Parse */ |
239 | | return TLSX_UseMaxFragment(&ssl->extensions, mfl, ssl->heap); |
240 | | } |
241 | | |
242 | | |
243 | | /* Set the Maximum Fragment Length extension on the context. |
244 | | * |
245 | | * @param [in] ctx SSL/TLS context object. |
246 | | * @param [in] mfl Maximum fragment length code, e.g. WOLFSSL_MFL_2_9. |
247 | | * @return WOLFSSL_SUCCESS on success. |
248 | | * @return BAD_FUNC_ARG when ctx is NULL. |
249 | | * @return Negative value on error. |
250 | | */ |
251 | | int wolfSSL_CTX_UseMaxFragment(WOLFSSL_CTX* ctx, byte mfl) |
252 | | { |
253 | | if (ctx == NULL) |
254 | | return BAD_FUNC_ARG; |
255 | | |
256 | | return TLSX_UseMaxFragment(&ctx->extensions, mfl, ctx->heap); |
257 | | } |
258 | | |
259 | | #endif /* NO_WOLFSSL_CLIENT */ |
260 | | #endif /* HAVE_MAX_FRAGMENT */ |
261 | | |
262 | | #ifdef HAVE_TRUNCATED_HMAC |
263 | | #ifndef NO_WOLFSSL_CLIENT |
264 | | |
265 | | /* Set the Truncated HMAC extension on the object. |
266 | | * |
267 | | * @param [in] ssl SSL/TLS object. |
268 | | * @return WOLFSSL_SUCCESS on success. |
269 | | * @return BAD_FUNC_ARG when ssl is NULL. |
270 | | * @return Negative value on error. |
271 | | */ |
272 | | int wolfSSL_UseTruncatedHMAC(WOLFSSL* ssl) |
273 | | { |
274 | | if (ssl == NULL) |
275 | | return BAD_FUNC_ARG; |
276 | | |
277 | | return TLSX_UseTruncatedHMAC(&ssl->extensions, ssl->heap); |
278 | | } |
279 | | |
280 | | |
281 | | /* Set the Truncated HMAC extension on the context. |
282 | | * |
283 | | * @param [in] ctx SSL/TLS context object. |
284 | | * @return WOLFSSL_SUCCESS on success. |
285 | | * @return BAD_FUNC_ARG when ctx is NULL. |
286 | | * @return Negative value on error. |
287 | | */ |
288 | | int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx) |
289 | | { |
290 | | if (ctx == NULL) |
291 | | return BAD_FUNC_ARG; |
292 | | |
293 | | return TLSX_UseTruncatedHMAC(&ctx->extensions, ctx->heap); |
294 | | } |
295 | | |
296 | | #endif /* NO_WOLFSSL_CLIENT */ |
297 | | #endif /* HAVE_TRUNCATED_HMAC */ |
298 | | |
299 | | /* Elliptic Curves */ |
300 | | #if defined(HAVE_SUPPORTED_CURVES) |
301 | | |
302 | | /* Determine whether a named group is a supported curve or FFDHE group. |
303 | | * |
304 | | * @param [in] name Named group identifier. |
305 | | * @return 1 when the named group is valid. |
306 | | * @return 0 otherwise. |
307 | | */ |
308 | | static int isValidCurveGroup(word16 name) |
309 | 0 | { |
310 | 0 | switch (name) { |
311 | 0 | case WOLFSSL_ECC_SECP160K1: |
312 | 0 | case WOLFSSL_ECC_SECP160R1: |
313 | 0 | case WOLFSSL_ECC_SECP160R2: |
314 | 0 | case WOLFSSL_ECC_SECP192K1: |
315 | 0 | case WOLFSSL_ECC_SECP192R1: |
316 | 0 | case WOLFSSL_ECC_SECP224K1: |
317 | 0 | case WOLFSSL_ECC_SECP224R1: |
318 | 0 | case WOLFSSL_ECC_SECP256K1: |
319 | 0 | case WOLFSSL_ECC_SECP256R1: |
320 | 0 | case WOLFSSL_ECC_SECP384R1: |
321 | 0 | case WOLFSSL_ECC_SECP521R1: |
322 | 0 | case WOLFSSL_ECC_BRAINPOOLP256R1: |
323 | 0 | case WOLFSSL_ECC_BRAINPOOLP384R1: |
324 | 0 | case WOLFSSL_ECC_BRAINPOOLP512R1: |
325 | 0 | case WOLFSSL_ECC_SM2P256V1: |
326 | 0 | case WOLFSSL_ECC_X25519: |
327 | 0 | case WOLFSSL_ECC_X448: |
328 | 0 | case WOLFSSL_ECC_BRAINPOOLP256R1TLS13: |
329 | 0 | case WOLFSSL_ECC_BRAINPOOLP384R1TLS13: |
330 | 0 | case WOLFSSL_ECC_BRAINPOOLP512R1TLS13: |
331 | |
|
332 | 0 | case WOLFSSL_FFDHE_2048: |
333 | 0 | case WOLFSSL_FFDHE_3072: |
334 | 0 | case WOLFSSL_FFDHE_4096: |
335 | 0 | case WOLFSSL_FFDHE_6144: |
336 | 0 | case WOLFSSL_FFDHE_8192: |
337 | |
|
338 | 0 | #ifdef WOLFSSL_HAVE_MLKEM |
339 | 0 | #ifndef WOLFSSL_NO_ML_KEM |
340 | | #ifndef WOLFSSL_TLS_NO_MLKEM_STANDALONE |
341 | | case WOLFSSL_ML_KEM_512: |
342 | | case WOLFSSL_ML_KEM_768: |
343 | | case WOLFSSL_ML_KEM_1024: |
344 | | #endif /* !WOLFSSL_TLS_NO_MLKEM_STANDALONE */ |
345 | 0 | #ifdef WOLFSSL_PQC_HYBRIDS |
346 | 0 | case WOLFSSL_SECP384R1MLKEM1024: |
347 | 0 | case WOLFSSL_X25519MLKEM768: |
348 | 0 | case WOLFSSL_SECP256R1MLKEM768: |
349 | 0 | #endif /* WOLFSSL_PQC_HYBRIDS */ |
350 | | #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS |
351 | | case WOLFSSL_SECP256R1MLKEM512: |
352 | | case WOLFSSL_SECP384R1MLKEM768: |
353 | | case WOLFSSL_SECP521R1MLKEM1024: |
354 | | case WOLFSSL_X25519MLKEM512: |
355 | | case WOLFSSL_X448MLKEM768: |
356 | | #endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ |
357 | 0 | #endif /* !WOLFSSL_NO_ML_KEM */ |
358 | | #ifdef WOLFSSL_MLKEM_KYBER |
359 | | case WOLFSSL_KYBER_LEVEL1: |
360 | | case WOLFSSL_KYBER_LEVEL3: |
361 | | case WOLFSSL_KYBER_LEVEL5: |
362 | | case WOLFSSL_P256_KYBER_LEVEL1: |
363 | | case WOLFSSL_P384_KYBER_LEVEL3: |
364 | | case WOLFSSL_P521_KYBER_LEVEL5: |
365 | | case WOLFSSL_X25519_KYBER_LEVEL1: |
366 | | case WOLFSSL_X448_KYBER_LEVEL3: |
367 | | case WOLFSSL_X25519_KYBER_LEVEL3: |
368 | | case WOLFSSL_P256_KYBER_LEVEL3: |
369 | | #endif /* WOLFSSL_MLKEM_KYBER */ |
370 | 0 | #endif |
371 | 0 | return 1; |
372 | | |
373 | 0 | default: |
374 | 0 | return 0; |
375 | 0 | } |
376 | 0 | } |
377 | | |
378 | | /* Set a named group in the Supported Groups extension on the object. |
379 | | * |
380 | | * @param [in] ssl SSL/TLS object. |
381 | | * @param [in] name Named group identifier. |
382 | | * @return WOLFSSL_SUCCESS on success. |
383 | | * @return BAD_FUNC_ARG when ssl is NULL or the group is invalid. |
384 | | * @return WOLFSSL_FAILURE when TLS is not compiled in. |
385 | | */ |
386 | | int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, word16 name) |
387 | 0 | { |
388 | 0 | if (ssl == NULL || !isValidCurveGroup(name)) |
389 | 0 | return BAD_FUNC_ARG; |
390 | | |
391 | 0 | ssl->options.userCurves = 1; |
392 | | #if defined(NO_TLS) |
393 | | return WOLFSSL_FAILURE; |
394 | | #else |
395 | 0 | return TLSX_UseSupportedCurve(&ssl->extensions, name, ssl->heap, |
396 | 0 | ssl->options.side); |
397 | 0 | #endif /* NO_TLS */ |
398 | 0 | } |
399 | | |
400 | | |
401 | | /* Set a named group in the Supported Groups extension on the context. |
402 | | * |
403 | | * @param [in] ctx SSL/TLS context object. |
404 | | * @param [in] name Named group identifier. |
405 | | * @return WOLFSSL_SUCCESS on success. |
406 | | * @return BAD_FUNC_ARG when ctx is NULL or the group is invalid. |
407 | | * @return WOLFSSL_FAILURE when TLS is not compiled in. |
408 | | */ |
409 | | int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx, word16 name) |
410 | 0 | { |
411 | 0 | if (ctx == NULL || !isValidCurveGroup(name)) |
412 | 0 | return BAD_FUNC_ARG; |
413 | | |
414 | 0 | ctx->userCurves = 1; |
415 | | #if defined(NO_TLS) |
416 | | return WOLFSSL_FAILURE; |
417 | | #else |
418 | 0 | return TLSX_UseSupportedCurve(&ctx->extensions, name, ctx->heap, |
419 | 0 | ctx->method->side); |
420 | 0 | #endif /* NO_TLS */ |
421 | 0 | } |
422 | | |
423 | | #if defined(OPENSSL_EXTRA) |
424 | | /* Validate a list of group identifiers and translate them into named groups. |
425 | | * |
426 | | * Group values may be wolfSSL named groups or curve NIDs (when ECC is |
427 | | * available). |
428 | | * |
429 | | * @param [in] groups Array of group identifiers. |
430 | | * @param [in] count Number of groups in the array. |
431 | | * @param [out] outGroups Array to hold the named groups. Must have at least |
432 | | * count entries. |
433 | | * @return WOLFSSL_SUCCESS on success. |
434 | | * @return WOLFSSL_FAILURE when a group is not recognized. |
435 | | */ |
436 | | static int wolfssl_validate_groups(const int* groups, int count, int* outGroups) |
437 | | { |
438 | | int i; |
439 | | int ret = WOLFSSL_SUCCESS; |
440 | | |
441 | | for (i = 0; i < count; i++) { |
442 | | if (isValidCurveGroup((word16)groups[i])) { |
443 | | outGroups[i] = groups[i]; |
444 | | } |
445 | | #ifdef HAVE_ECC |
446 | | else { |
447 | | /* Groups may be populated with curve NIDs. */ |
448 | | int oid = (int)nid2oid(groups[i], oidCurveType); |
449 | | int name = (int)GetCurveByOID(oid); |
450 | | if (name == 0) { |
451 | | WOLFSSL_MSG("Invalid group name"); |
452 | | ret = WOLFSSL_FAILURE; |
453 | | break; |
454 | | } |
455 | | outGroups[i] = name; |
456 | | } |
457 | | #else |
458 | | else { |
459 | | WOLFSSL_MSG("Invalid group name"); |
460 | | ret = WOLFSSL_FAILURE; |
461 | | break; |
462 | | } |
463 | | #endif |
464 | | } |
465 | | |
466 | | return ret; |
467 | | } |
468 | | |
469 | | /* Set the list of supported groups on the context. |
470 | | * |
471 | | * Group values may be wolfSSL named groups or curve NIDs. |
472 | | * |
473 | | * @param [in] ctx SSL/TLS context object. |
474 | | * @param [in] groups Array of group identifiers. |
475 | | * @param [in] count Number of groups in the array. |
476 | | * @return WOLFSSL_SUCCESS on success. |
477 | | * @return WOLFSSL_FAILURE when count is invalid or a group is not recognized. |
478 | | */ |
479 | | int wolfSSL_CTX_set1_groups(WOLFSSL_CTX* ctx, int* groups, int count) |
480 | | { |
481 | | int _groups[WOLFSSL_MAX_GROUP_COUNT]; |
482 | | int ret = WOLFSSL_SUCCESS; |
483 | | |
484 | | WOLFSSL_ENTER("wolfSSL_CTX_set1_groups"); |
485 | | if (groups == NULL || count <= 0) { |
486 | | WOLFSSL_MSG("Groups NULL or count not positive"); |
487 | | ret = WOLFSSL_FAILURE; |
488 | | } |
489 | | else if (count > WOLFSSL_MAX_GROUP_COUNT) { |
490 | | WOLFSSL_MSG("Group count exceeds maximum"); |
491 | | ret = WOLFSSL_FAILURE; |
492 | | } |
493 | | else { |
494 | | /* Translate the input list into named groups, then apply it. */ |
495 | | ret = wolfssl_validate_groups(groups, count, _groups); |
496 | | if (ret == WOLFSSL_SUCCESS) { |
497 | | ret = wolfSSL_CTX_set_groups(ctx, _groups, count); |
498 | | /* Normalize any non-success result to WOLFSSL_FAILURE. */ |
499 | | if (ret != WOLFSSL_SUCCESS) { |
500 | | ret = WOLFSSL_FAILURE; |
501 | | } |
502 | | } |
503 | | } |
504 | | |
505 | | return ret; |
506 | | } |
507 | | |
508 | | /* Set the list of supported groups on the object. |
509 | | * |
510 | | * Group values may be wolfSSL named groups or curve NIDs. |
511 | | * |
512 | | * @param [in] ssl SSL/TLS object. |
513 | | * @param [in] groups Array of group identifiers. |
514 | | * @param [in] count Number of groups in the array. |
515 | | * @return WOLFSSL_SUCCESS on success. |
516 | | * @return WOLFSSL_FAILURE when count is invalid or a group is not recognized. |
517 | | */ |
518 | | int wolfSSL_set1_groups(WOLFSSL* ssl, int* groups, int count) |
519 | | { |
520 | | int _groups[WOLFSSL_MAX_GROUP_COUNT]; |
521 | | int ret = WOLFSSL_SUCCESS; |
522 | | |
523 | | WOLFSSL_ENTER("wolfSSL_set1_groups"); |
524 | | if (groups == NULL || count <= 0) { |
525 | | WOLFSSL_MSG("Groups NULL or count not positive"); |
526 | | ret = WOLFSSL_FAILURE; |
527 | | } |
528 | | else if (count > WOLFSSL_MAX_GROUP_COUNT) { |
529 | | WOLFSSL_MSG("Group count exceeds maximum"); |
530 | | ret = WOLFSSL_FAILURE; |
531 | | } |
532 | | else { |
533 | | /* Translate the input list into named groups, then apply it. */ |
534 | | ret = wolfssl_validate_groups(groups, count, _groups); |
535 | | if (ret == WOLFSSL_SUCCESS) { |
536 | | ret = wolfSSL_set_groups(ssl, _groups, count); |
537 | | /* Normalize any non-success result to WOLFSSL_FAILURE. */ |
538 | | if (ret != WOLFSSL_SUCCESS) { |
539 | | ret = WOLFSSL_FAILURE; |
540 | | } |
541 | | } |
542 | | } |
543 | | |
544 | | return ret; |
545 | | } |
546 | | #endif /* OPENSSL_EXTRA */ |
547 | | #endif /* HAVE_SUPPORTED_CURVES */ |
548 | | |
549 | | /* Application-Layer Protocol Negotiation */ |
550 | | #ifdef HAVE_ALPN |
551 | | |
552 | | /* Set the Application-Layer Protocol Negotiation extension on the object. |
553 | | * |
554 | | * @param [in] ssl SSL/TLS object. |
555 | | * @param [in] protocol_name_list Comma-separated list of protocol names. |
556 | | * @param [in] protocol_name_listSz Length of the list in bytes. |
557 | | * @param [in] options Bitmask of ALPN options. |
558 | | * @return WOLFSSL_SUCCESS on success. |
559 | | * @return BAD_FUNC_ARG when an argument is NULL, the list is too long or |
560 | | * options are unsupported. |
561 | | * @return MEMORY_ERROR on allocation failure. |
562 | | */ |
563 | | WOLFSSL_ABI |
564 | | int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list, |
565 | | word32 protocol_name_listSz, byte options) |
566 | | { |
567 | | char* list = NULL; |
568 | | char* ptr = NULL; |
569 | | char** token = NULL; |
570 | | word16 len; |
571 | | int idx = 0; |
572 | | int ret = WOLFSSL_SUCCESS; |
573 | | |
574 | | WOLFSSL_ENTER("wolfSSL_UseALPN"); |
575 | | |
576 | | if ((ssl == NULL) || (protocol_name_list == NULL)) { |
577 | | return BAD_FUNC_ARG; |
578 | | } |
579 | | else if (protocol_name_listSz > (WOLFSSL_MAX_ALPN_NUMBER * |
580 | | WOLFSSL_MAX_ALPN_PROTO_NAME_LEN + WOLFSSL_MAX_ALPN_NUMBER)) { |
581 | | WOLFSSL_MSG("Invalid arguments, protocol name list too long"); |
582 | | return BAD_FUNC_ARG; |
583 | | } |
584 | | else if ((!(options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH)) && |
585 | | (!(options & WOLFSSL_ALPN_FAILED_ON_MISMATCH))) { |
586 | | WOLFSSL_MSG("Invalid arguments, options not supported"); |
587 | | return BAD_FUNC_ARG; |
588 | | } |
589 | | |
590 | | list = (char *)XMALLOC(protocol_name_listSz + 1, ssl->heap, |
591 | | DYNAMIC_TYPE_ALPN); |
592 | | token = (char **)XMALLOC(sizeof(char*) * (WOLFSSL_MAX_ALPN_NUMBER + 1), |
593 | | ssl->heap, DYNAMIC_TYPE_ALPN); |
594 | | if ((list == NULL) || (token == NULL)) { |
595 | | WOLFSSL_MSG("Memory failure"); |
596 | | ret = MEMORY_ERROR; |
597 | | } |
598 | | |
599 | | if (ret == WOLFSSL_SUCCESS) { |
600 | | XMEMSET(token, 0, sizeof(char *) * (WOLFSSL_MAX_ALPN_NUMBER+1)); |
601 | | |
602 | | XSTRNCPY(list, protocol_name_list, protocol_name_listSz); |
603 | | list[protocol_name_listSz] = '\0'; |
604 | | |
605 | | /* Read all protocol names from the list. */ |
606 | | token[idx] = XSTRTOK(list, ",", &ptr); |
607 | | while ((idx < WOLFSSL_MAX_ALPN_NUMBER) && (token[idx] != NULL)) { |
608 | | token[++idx] = XSTRTOK(NULL, ",", &ptr); |
609 | | } |
610 | | |
611 | | /* Add the protocol name list to the TLS extension in reverse order. */ |
612 | | while ((idx--) > 0) { |
613 | | len = (word16)XSTRLEN(token[idx]); |
614 | | |
615 | | ret = TLSX_UseALPN(&ssl->extensions, token[idx], len, options, |
616 | | ssl->heap); |
617 | | if (ret != WOLFSSL_SUCCESS) { |
618 | | WOLFSSL_MSG("TLSX_UseALPN failure"); |
619 | | break; |
620 | | } |
621 | | } |
622 | | } |
623 | | |
624 | | XFREE(token, ssl->heap, DYNAMIC_TYPE_ALPN); |
625 | | XFREE(list, ssl->heap, DYNAMIC_TYPE_ALPN); |
626 | | |
627 | | return ret; |
628 | | } |
629 | | |
630 | | /* Get the ALPN protocol negotiated for the object. |
631 | | * |
632 | | * @param [in] ssl SSL/TLS object. |
633 | | * @param [out] protocol_name Negotiated protocol name. |
634 | | * @param [out] size Length of the protocol name in bytes. |
635 | | * @return WOLFSSL_SUCCESS on success. |
636 | | * @return Negative value on error. |
637 | | */ |
638 | | int wolfSSL_ALPN_GetProtocol(WOLFSSL* ssl, char **protocol_name, word16 *size) |
639 | | { |
640 | | return TLSX_ALPN_GetRequest((ssl != NULL) ? ssl->extensions : NULL, |
641 | | (void **)protocol_name, size); |
642 | | } |
643 | | |
644 | | /* Get the ALPN protocol list offered by the peer as a comma-separated string. |
645 | | * |
646 | | * The returned list must be freed with wolfSSL_ALPN_FreePeerProtocol(). |
647 | | * |
648 | | * @param [in] ssl SSL/TLS object. |
649 | | * @param [out] list Newly allocated comma-separated protocol list. |
650 | | * @param [out] listSz Length of the list string. |
651 | | * @return WOLFSSL_SUCCESS on success. |
652 | | * @return BAD_FUNC_ARG when an argument is NULL. |
653 | | * @return BUFFER_ERROR when the peer offered no protocols. |
654 | | * @return MEMORY_ERROR on allocation failure. |
655 | | */ |
656 | | int wolfSSL_ALPN_GetPeerProtocol(WOLFSSL* ssl, char **list, word16 *listSz) |
657 | | { |
658 | | int i, len; |
659 | | char *p; |
660 | | byte *s; |
661 | | |
662 | | if (ssl == NULL || list == NULL || listSz == NULL) |
663 | | return BAD_FUNC_ARG; |
664 | | |
665 | | if (ssl->alpn_peer_requested == NULL |
666 | | || ssl->alpn_peer_requested_length == 0) |
667 | | return BUFFER_ERROR; |
668 | | |
669 | | /* ssl->alpn_peer_requested are the original bytes sent in a ClientHello, |
670 | | * formatted as (len-byte chars+)+. To turn n protocols into a |
671 | | * comma-separated C string, one needs (n-1) commas and a final 0 byte |
672 | | * which has the same length as the original. |
673 | | * The returned length is the strlen() of the C string, so -1 of that. */ |
674 | | *listSz = ssl->alpn_peer_requested_length-1; |
675 | | *list = p = (char *)XMALLOC(ssl->alpn_peer_requested_length, ssl->heap, |
676 | | DYNAMIC_TYPE_TLSX); |
677 | | if (p == NULL) |
678 | | return MEMORY_ERROR; |
679 | | |
680 | | for (i = 0, s = ssl->alpn_peer_requested; |
681 | | i < ssl->alpn_peer_requested_length; |
682 | | p += len, i += len) |
683 | | { |
684 | | if (i) |
685 | | *p++ = ','; |
686 | | len = s[i++]; |
687 | | /* guard against bad length bytes. */ |
688 | | if (i + len > ssl->alpn_peer_requested_length) { |
689 | | XFREE(*list, ssl->heap, DYNAMIC_TYPE_TLSX); |
690 | | *list = NULL; |
691 | | return WOLFSSL_FAILURE; |
692 | | } |
693 | | XMEMCPY(p, s + i, (size_t)len); |
694 | | } |
695 | | *p = 0; |
696 | | |
697 | | return WOLFSSL_SUCCESS; |
698 | | } |
699 | | |
700 | | |
701 | | /* Free a peer protocol list returned by wolfSSL_ALPN_GetPeerProtocol(). |
702 | | * |
703 | | * @param [in] ssl SSL/TLS object. |
704 | | * @param [in, out] list Protocol list to free; set to NULL on return. |
705 | | * @return WOLFSSL_SUCCESS on success. |
706 | | * @return BAD_FUNC_ARG when ssl is NULL. |
707 | | */ |
708 | | int wolfSSL_ALPN_FreePeerProtocol(WOLFSSL* ssl, char **list) |
709 | | { |
710 | | if (ssl == NULL) { |
711 | | return BAD_FUNC_ARG; |
712 | | } |
713 | | |
714 | | XFREE(*list, ssl->heap, DYNAMIC_TYPE_TLSX); |
715 | | *list = NULL; |
716 | | |
717 | | return WOLFSSL_SUCCESS; |
718 | | } |
719 | | |
720 | | #endif /* HAVE_ALPN */ |
721 | | |
722 | | /* Secure Renegotiation */ |
723 | | #ifdef HAVE_SERVER_RENEGOTIATION_INFO |
724 | | |
725 | | /* Enable the Secure Renegotiation extension on the object. |
726 | | * |
727 | | * Use of secure renegotiation is discouraged. |
728 | | * |
729 | | * @param [in] ssl SSL/TLS object. |
730 | | * @return WOLFSSL_SUCCESS on success. |
731 | | * @return BAD_FUNC_ARG when ssl is NULL. |
732 | | * @return Negative value on error. |
733 | | */ |
734 | | int wolfSSL_UseSecureRenegotiation(WOLFSSL* ssl) |
735 | 0 | { |
736 | 0 | int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); |
737 | | #if defined(NO_TLS) |
738 | | (void)ssl; |
739 | | #else |
740 | 0 | if (ssl != NULL) { |
741 | 0 | ret = TLSX_UseSecureRenegotiation(&ssl->extensions, ssl->heap); |
742 | 0 | } |
743 | 0 | else { |
744 | 0 | ret = BAD_FUNC_ARG; |
745 | 0 | } |
746 | |
|
747 | 0 | if (ret == WOLFSSL_SUCCESS) { |
748 | 0 | TLSX* extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO); |
749 | 0 | if (extension != NULL) { |
750 | 0 | ssl->secure_renegotiation = (SecureRenegotiation*)extension->data; |
751 | 0 | } |
752 | 0 | } |
753 | 0 | #endif /* !NO_TLS */ |
754 | 0 | return ret; |
755 | 0 | } |
756 | | |
757 | | /* Enable the Secure Renegotiation extension on the context. |
758 | | * |
759 | | * Use of secure renegotiation is discouraged. |
760 | | * |
761 | | * @param [in] ctx SSL/TLS context object. |
762 | | * @return WOLFSSL_SUCCESS on success. |
763 | | * @return BAD_FUNC_ARG when ctx is NULL. |
764 | | */ |
765 | | int wolfSSL_CTX_UseSecureRenegotiation(WOLFSSL_CTX* ctx) |
766 | 0 | { |
767 | 0 | if (ctx == NULL) |
768 | 0 | return BAD_FUNC_ARG; |
769 | | |
770 | 0 | ctx->useSecureReneg = 1; |
771 | 0 | return WOLFSSL_SUCCESS; |
772 | 0 | } |
773 | | |
774 | | #ifdef HAVE_SECURE_RENEGOTIATION |
775 | | /* Perform a secure renegotiation handshake on the object. |
776 | | * |
777 | | * User forced; use of secure renegotiation is discouraged. |
778 | | * |
779 | | * @param [in] ssl SSL/TLS object. |
780 | | * @return WOLFSSL_SUCCESS on success. |
781 | | * @return BAD_FUNC_ARG when ssl is NULL. |
782 | | * @return SECURE_RENEGOTIATION_E when renegotiation is not allowed. |
783 | | * @return WOLFSSL_FATAL_ERROR on error. |
784 | | */ |
785 | | static int _Rehandshake(WOLFSSL* ssl) |
786 | | { |
787 | | int ret; |
788 | | |
789 | | if (ssl == NULL) |
790 | | return BAD_FUNC_ARG; |
791 | | |
792 | | if (IsAtLeastTLSv1_3(ssl->version)) { |
793 | | WOLFSSL_MSG("Secure Renegotiation not supported in TLS 1.3"); |
794 | | return SECURE_RENEGOTIATION_E; |
795 | | } |
796 | | |
797 | | if (ssl->secure_renegotiation == NULL) { |
798 | | WOLFSSL_MSG("Secure Renegotiation not forced on by user"); |
799 | | return SECURE_RENEGOTIATION_E; |
800 | | } |
801 | | |
802 | | if (ssl->secure_renegotiation->enabled == 0) { |
803 | | WOLFSSL_MSG("Secure Renegotiation not enabled at extension level"); |
804 | | return SECURE_RENEGOTIATION_E; |
805 | | } |
806 | | |
807 | | #ifdef WOLFSSL_DTLS |
808 | | if (ssl->options.dtls && ssl->keys.dtls_epoch == 0xFFFF) { |
809 | | WOLFSSL_MSG("Secure Renegotiation not allowed. Epoch would wrap"); |
810 | | return SECURE_RENEGOTIATION_E; |
811 | | } |
812 | | #endif |
813 | | |
814 | | /* If the client started the renegotiation, the server will already |
815 | | * have processed the client's hello. */ |
816 | | if (ssl->options.side != WOLFSSL_SERVER_END || |
817 | | ssl->options.acceptState != ACCEPT_FIRST_REPLY_DONE) { |
818 | | |
819 | | if (ssl->options.handShakeState != HANDSHAKE_DONE) { |
820 | | if (!ssl->options.handShakeDone) { |
821 | | WOLFSSL_MSG("Can't renegotiate until initial " |
822 | | "handshake complete"); |
823 | | return SECURE_RENEGOTIATION_E; |
824 | | } |
825 | | else { |
826 | | WOLFSSL_MSG("Renegotiation already started. " |
827 | | "Moving it forward."); |
828 | | ret = wolfSSL_negotiate(ssl); |
829 | | if (ret == WOLFSSL_SUCCESS) |
830 | | ssl->secure_rene_count++; |
831 | | return ret; |
832 | | } |
833 | | } |
834 | | |
835 | | /* reset handshake states */ |
836 | | ssl->options.sendVerify = 0; |
837 | | ssl->options.serverState = NULL_STATE; |
838 | | ssl->options.clientState = NULL_STATE; |
839 | | ssl->options.connectState = CONNECT_BEGIN; |
840 | | ssl->options.acceptState = ACCEPT_BEGIN_RENEG; |
841 | | ssl->options.handShakeState = NULL_STATE; |
842 | | ssl->options.processReply = 0; /* TODO, move states in internal.h */ |
843 | | |
844 | | XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived)); |
845 | | |
846 | | ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED; |
847 | | |
848 | | #if !defined(NO_WOLFSSL_SERVER) && !defined(WOLFSSL_NO_TLS12) |
849 | | if (ssl->options.side == WOLFSSL_SERVER_END) { |
850 | | ret = SendHelloRequest(ssl); |
851 | | if (ret != 0) { |
852 | | ssl->error = ret; |
853 | | return WOLFSSL_FATAL_ERROR; |
854 | | } |
855 | | } |
856 | | #endif /* !NO_WOLFSSL_SERVER && !WOLFSSL_NO_TLS12 */ |
857 | | |
858 | | ret = InitHandshakeHashes(ssl); |
859 | | if (ret != 0) { |
860 | | ssl->error = ret; |
861 | | return WOLFSSL_FATAL_ERROR; |
862 | | } |
863 | | } |
864 | | ret = wolfSSL_negotiate(ssl); |
865 | | if (ret == WOLFSSL_SUCCESS) |
866 | | ssl->secure_rene_count++; |
867 | | return ret; |
868 | | } |
869 | | |
870 | | |
871 | | /* Perform a secure renegotiation handshake on the object. |
872 | | * |
873 | | * User forced; use of secure renegotiation is discouraged. |
874 | | * |
875 | | * @param [in] ssl SSL/TLS object. |
876 | | * @return WOLFSSL_SUCCESS on success. |
877 | | * @return WOLFSSL_FAILURE when ssl is NULL. |
878 | | * @return Negative value on error. |
879 | | */ |
880 | | int wolfSSL_Rehandshake(WOLFSSL* ssl) |
881 | | { |
882 | | int ret; |
883 | | WOLFSSL_ENTER("wolfSSL_Rehandshake"); |
884 | | |
885 | | if (ssl == NULL) |
886 | | return WOLFSSL_FAILURE; |
887 | | |
888 | | #ifdef HAVE_SESSION_TICKET |
889 | | ret = WOLFSSL_SUCCESS; |
890 | | #endif |
891 | | |
892 | | if (ssl->options.side == WOLFSSL_SERVER_END) { |
893 | | /* Reset option to send certificate verify. */ |
894 | | ssl->options.sendVerify = 0; |
895 | | /* Reset resuming flag to do full secure handshake. */ |
896 | | ssl->options.resuming = 0; |
897 | | } |
898 | | else { |
899 | | /* Reset resuming flag to do full secure handshake. */ |
900 | | ssl->options.resuming = 0; |
901 | | #if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_CLIENT) |
902 | | /* Clearing the ticket. */ |
903 | | ret = wolfSSL_UseSessionTicket(ssl); |
904 | | #endif |
905 | | } |
906 | | /* CLIENT/SERVER: Reset peer authentication for full secure handshake. */ |
907 | | ssl->options.peerAuthGood = 0; |
908 | | |
909 | | #ifdef HAVE_SESSION_TICKET |
910 | | if (ret == WOLFSSL_SUCCESS) |
911 | | #endif |
912 | | ret = _Rehandshake(ssl); |
913 | | |
914 | | return ret; |
915 | | } |
916 | | |
917 | | |
918 | | #ifndef NO_WOLFSSL_CLIENT |
919 | | |
920 | | /* Perform a secure resumption handshake on the object. |
921 | | * |
922 | | * Client side only. User forced; use of secure renegotiation is discouraged. |
923 | | * |
924 | | * @param [in] ssl SSL/TLS object. |
925 | | * @return WOLFSSL_SUCCESS on success. |
926 | | * @return BAD_FUNC_ARG when ssl is NULL. |
927 | | * @return WOLFSSL_FATAL_ERROR when called on a server. |
928 | | */ |
929 | | int wolfSSL_SecureResume(WOLFSSL* ssl) |
930 | | { |
931 | | WOLFSSL_ENTER("wolfSSL_SecureResume"); |
932 | | |
933 | | if (ssl == NULL) |
934 | | return BAD_FUNC_ARG; |
935 | | |
936 | | if (ssl->options.side == WOLFSSL_SERVER_END) { |
937 | | ssl->error = SIDE_ERROR; |
938 | | return WOLFSSL_FATAL_ERROR; |
939 | | } |
940 | | |
941 | | return _Rehandshake(ssl); |
942 | | } |
943 | | |
944 | | #endif /* NO_WOLFSSL_CLIENT */ |
945 | | |
946 | | #endif /* HAVE_SECURE_RENEGOTIATION */ |
947 | | |
948 | | /* Get whether secure renegotiation is enabled for the object. |
949 | | * |
950 | | * @param [in] ssl SSL/TLS object. |
951 | | * @return 1 when secure renegotiation is enabled. |
952 | | * @return 0 when ssl is NULL or it is not enabled. |
953 | | */ |
954 | | long wolfSSL_SSL_get_secure_renegotiation_support(WOLFSSL* ssl) |
955 | 0 | { |
956 | 0 | WOLFSSL_ENTER("wolfSSL_SSL_get_secure_renegotiation_support"); |
957 | |
|
958 | 0 | return (ssl != NULL) && (ssl->secure_renegotiation != NULL) && |
959 | 0 | ssl->secure_renegotiation->enabled; |
960 | 0 | } |
961 | | |
962 | | #endif /* HAVE_SECURE_RENEGOTIATION_INFO */ |
963 | | |
964 | | #if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \ |
965 | | defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK) |
966 | | /* Get whether the secure renegotiation check is enabled for the object. |
967 | | * |
968 | | * @param [in] ssl SSL/TLS object. |
969 | | * @return Non-zero when the check is enabled, 0 otherwise. |
970 | | * @return BAD_FUNC_ARG when ssl is NULL. |
971 | | */ |
972 | | WOLFSSL_API int wolfSSL_get_scr_check_enabled(const WOLFSSL* ssl) |
973 | | { |
974 | | WOLFSSL_ENTER("wolfSSL_get_scr_check_enabled"); |
975 | | |
976 | | if (ssl == NULL) |
977 | | return BAD_FUNC_ARG; |
978 | | |
979 | | return ssl->scr_check_enabled; |
980 | | } |
981 | | |
982 | | /* Set whether the secure renegotiation check is enabled for the object. |
983 | | * |
984 | | * @param [in] ssl SSL/TLS object. |
985 | | * @param [in] enabled Non-zero to enable the check, 0 to disable it. |
986 | | * @return WOLFSSL_SUCCESS on success. |
987 | | * @return BAD_FUNC_ARG when ssl is NULL. |
988 | | */ |
989 | | WOLFSSL_API int wolfSSL_set_scr_check_enabled(WOLFSSL* ssl, byte enabled) |
990 | | { |
991 | | WOLFSSL_ENTER("wolfSSL_set_scr_check_enabled"); |
992 | | |
993 | | if (ssl == NULL) |
994 | | return BAD_FUNC_ARG; |
995 | | |
996 | | ssl->scr_check_enabled = !!enabled; |
997 | | return WOLFSSL_SUCCESS; |
998 | | } |
999 | | #endif |
1000 | | |
1001 | | #if defined(HAVE_SESSION_TICKET) |
1002 | | /* Session Ticket */ |
1003 | | |
1004 | | #if !defined(NO_WOLFSSL_SERVER) |
1005 | | /* Disable use of session tickets with TLS 1.2 on the context. |
1006 | | * |
1007 | | * @param [in] ctx SSL/TLS context object. |
1008 | | * @return WOLFSSL_SUCCESS on success. |
1009 | | * @return BAD_FUNC_ARG when ctx is NULL. |
1010 | | */ |
1011 | | int wolfSSL_CTX_NoTicketTLSv12(WOLFSSL_CTX* ctx) |
1012 | | { |
1013 | | if (ctx == NULL) |
1014 | | return BAD_FUNC_ARG; |
1015 | | |
1016 | | ctx->noTicketTls12 = 1; |
1017 | | |
1018 | | return WOLFSSL_SUCCESS; |
1019 | | } |
1020 | | |
1021 | | /* Disable use of session tickets with TLS 1.2 on the object. |
1022 | | * |
1023 | | * @param [in] ssl SSL/TLS object. |
1024 | | * @return WOLFSSL_SUCCESS on success. |
1025 | | * @return BAD_FUNC_ARG when ssl is NULL. |
1026 | | */ |
1027 | | int wolfSSL_NoTicketTLSv12(WOLFSSL* ssl) |
1028 | | { |
1029 | | if (ssl == NULL) |
1030 | | return BAD_FUNC_ARG; |
1031 | | |
1032 | | ssl->options.noTicketTls12 = 1; |
1033 | | |
1034 | | return WOLFSSL_SUCCESS; |
1035 | | } |
1036 | | |
1037 | | /* Set the session ticket encryption callback on the context. |
1038 | | * |
1039 | | * @param [in] ctx SSL/TLS context object. |
1040 | | * @param [in] cb Session ticket encryption callback. |
1041 | | * @return WOLFSSL_SUCCESS on success. |
1042 | | * @return BAD_FUNC_ARG when ctx is NULL. |
1043 | | */ |
1044 | | int wolfSSL_CTX_set_TicketEncCb(WOLFSSL_CTX* ctx, SessionTicketEncCb cb) |
1045 | | { |
1046 | | if (ctx == NULL) |
1047 | | return BAD_FUNC_ARG; |
1048 | | |
1049 | | ctx->ticketEncCb = cb; |
1050 | | |
1051 | | return WOLFSSL_SUCCESS; |
1052 | | } |
1053 | | |
1054 | | /* Set the session ticket lifetime hint, in seconds, on the context. |
1055 | | * |
1056 | | * @param [in] ctx SSL/TLS context object. |
1057 | | * @param [in] hint Lifetime hint in seconds. No more than 604800 (7 days). |
1058 | | * @return WOLFSSL_SUCCESS on success. |
1059 | | * @return BAD_FUNC_ARG when ctx is NULL or hint is out of range. |
1060 | | */ |
1061 | | int wolfSSL_CTX_set_TicketHint(WOLFSSL_CTX* ctx, int hint) |
1062 | | { |
1063 | | if (ctx == NULL) |
1064 | | return BAD_FUNC_ARG; |
1065 | | |
1066 | | /* RFC8446 Section 4.6.1: Servers MUST NOT use any value greater than |
1067 | | * 604800 seconds (7 days). */ |
1068 | | if (hint < 0 || hint > 604800) |
1069 | | return BAD_FUNC_ARG; |
1070 | | |
1071 | | ctx->ticketHint = hint; |
1072 | | |
1073 | | return WOLFSSL_SUCCESS; |
1074 | | } |
1075 | | |
1076 | | /* Set the user context passed to the session ticket encryption callback. |
1077 | | * |
1078 | | * @param [in] ctx SSL/TLS context object. |
1079 | | * @param [in] userCtx User context for the ticket encryption callback. |
1080 | | * @return WOLFSSL_SUCCESS on success. |
1081 | | * @return BAD_FUNC_ARG when ctx is NULL. |
1082 | | */ |
1083 | | int wolfSSL_CTX_set_TicketEncCtx(WOLFSSL_CTX* ctx, void* userCtx) |
1084 | | { |
1085 | | if (ctx == NULL) |
1086 | | return BAD_FUNC_ARG; |
1087 | | |
1088 | | ctx->ticketEncCtx = userCtx; |
1089 | | |
1090 | | return WOLFSSL_SUCCESS; |
1091 | | } |
1092 | | |
1093 | | /* Get the user context passed to the session ticket encryption callback. |
1094 | | * |
1095 | | * @param [in] ctx SSL/TLS context object. |
1096 | | * @return User context on success. |
1097 | | * @return NULL when ctx is NULL. |
1098 | | */ |
1099 | | void* wolfSSL_CTX_get_TicketEncCtx(WOLFSSL_CTX* ctx) |
1100 | | { |
1101 | | if (ctx == NULL) |
1102 | | return NULL; |
1103 | | |
1104 | | return ctx->ticketEncCtx; |
1105 | | } |
1106 | | |
1107 | | #ifdef WOLFSSL_TLS13 |
1108 | | /* Set the maximum number of TLS 1.3 session tickets to send. |
1109 | | * |
1110 | | * @param [in] ctx SSL/TLS context object. |
1111 | | * @param [in] mxTickets Maximum number of tickets to send. |
1112 | | * @return WOLFSSL_SUCCESS on success. |
1113 | | * @return WOLFSSL_FAILURE when ctx is NULL. |
1114 | | */ |
1115 | | int wolfSSL_CTX_set_num_tickets(WOLFSSL_CTX* ctx, size_t mxTickets) |
1116 | | { |
1117 | | if (ctx == NULL) |
1118 | | return WOLFSSL_FAILURE; |
1119 | | |
1120 | | ctx->maxTicketTls13 = (unsigned int)mxTickets; |
1121 | | return WOLFSSL_SUCCESS; |
1122 | | } |
1123 | | |
1124 | | /* Get the maximum number of TLS 1.3 session tickets to send. |
1125 | | * |
1126 | | * @param [in] ctx SSL/TLS context object. |
1127 | | * @return Maximum number of tickets to send, or 0 when ctx is NULL. |
1128 | | */ |
1129 | | size_t wolfSSL_CTX_get_num_tickets(WOLFSSL_CTX* ctx) |
1130 | | { |
1131 | | if (ctx == NULL) |
1132 | | return 0; |
1133 | | |
1134 | | return (size_t)ctx->maxTicketTls13; |
1135 | | } |
1136 | | #endif /* WOLFSSL_TLS13 */ |
1137 | | #endif /* !NO_WOLFSSL_SERVER */ |
1138 | | |
1139 | | #if !defined(NO_WOLFSSL_CLIENT) |
1140 | | /* Enable use of the session ticket extension on the object. |
1141 | | * |
1142 | | * @param [in] ssl SSL/TLS object. |
1143 | | * @return WOLFSSL_SUCCESS on success. |
1144 | | * @return BAD_FUNC_ARG when ssl is NULL. |
1145 | | * @return Negative value on error. |
1146 | | */ |
1147 | | int wolfSSL_UseSessionTicket(WOLFSSL* ssl) |
1148 | | { |
1149 | | if (ssl == NULL) |
1150 | | return BAD_FUNC_ARG; |
1151 | | |
1152 | | return TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap); |
1153 | | } |
1154 | | |
1155 | | /* Enable use of the session ticket extension on the context. |
1156 | | * |
1157 | | * @param [in] ctx SSL/TLS context object. |
1158 | | * @return WOLFSSL_SUCCESS on success. |
1159 | | * @return BAD_FUNC_ARG when ctx is NULL. |
1160 | | * @return Negative value on error. |
1161 | | */ |
1162 | | int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx) |
1163 | | { |
1164 | | if (ctx == NULL) |
1165 | | return BAD_FUNC_ARG; |
1166 | | |
1167 | | return TLSX_UseSessionTicket(&ctx->extensions, NULL, ctx->heap); |
1168 | | } |
1169 | | |
1170 | | /* Get the session ticket stored on the object. |
1171 | | * |
1172 | | * When buf is NULL and *bufSz is 0, the length required is returned in bufSz. |
1173 | | * |
1174 | | * @param [in] ssl SSL/TLS object. |
1175 | | * @param [out] buf Buffer to hold the ticket. May be NULL for length. |
1176 | | * @param [in, out] bufSz In: size of buffer. Out: length of ticket. |
1177 | | * @return WOLFSSL_SUCCESS on success. |
1178 | | * @return LENGTH_ONLY_E when buf is NULL and bufSz has been set. |
1179 | | * @return BAD_FUNC_ARG when ssl or bufSz is NULL. |
1180 | | */ |
1181 | | int wolfSSL_get_SessionTicket(WOLFSSL* ssl, byte* buf, word32* bufSz) |
1182 | | { |
1183 | | if (ssl == NULL || bufSz == NULL) |
1184 | | return BAD_FUNC_ARG; |
1185 | | |
1186 | | if (*bufSz == 0 && buf == NULL) { |
1187 | | *bufSz = ssl->session->ticketLen; |
1188 | | return LENGTH_ONLY_E; |
1189 | | } |
1190 | | |
1191 | | if (buf == NULL) |
1192 | | return BAD_FUNC_ARG; |
1193 | | |
1194 | | if (ssl->session->ticketLen <= *bufSz) { |
1195 | | XMEMCPY(buf, ssl->session->ticket, ssl->session->ticketLen); |
1196 | | *bufSz = ssl->session->ticketLen; |
1197 | | } |
1198 | | else |
1199 | | *bufSz = 0; |
1200 | | |
1201 | | return WOLFSSL_SUCCESS; |
1202 | | } |
1203 | | |
1204 | | /* Set the session ticket to use on the object. |
1205 | | * |
1206 | | * @param [in] ssl SSL/TLS object. |
1207 | | * @param [in] buf Ticket data, may be NULL when bufSz is 0. |
1208 | | * @param [in] bufSz Length of ticket data in bytes. |
1209 | | * @return WOLFSSL_SUCCESS on success. |
1210 | | * @return BAD_FUNC_ARG when ssl is NULL or buf is NULL with bufSz > 0. |
1211 | | * @return MEMORY_ERROR on allocation failure. |
1212 | | */ |
1213 | | int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const byte* buf, |
1214 | | word32 bufSz) |
1215 | | { |
1216 | | if (ssl == NULL || (buf == NULL && bufSz > 0)) |
1217 | | return BAD_FUNC_ARG; |
1218 | | |
1219 | | if (bufSz > 0) { |
1220 | | /* Ticket will fit into static ticket */ |
1221 | | if (bufSz <= SESSION_TICKET_LEN) { |
1222 | | if (ssl->session->ticketLenAlloc > 0) { |
1223 | | XFREE(ssl->session->ticket, ssl->session->heap, |
1224 | | DYNAMIC_TYPE_SESSION_TICK); |
1225 | | ssl->session->ticketLenAlloc = 0; |
1226 | | ssl->session->ticket = ssl->session->staticTicket; |
1227 | | } |
1228 | | } |
1229 | | else { /* Ticket requires dynamic ticket storage */ |
1230 | | /* is dyn buffer big enough */ |
1231 | | if (ssl->session->ticketLen < bufSz) { |
1232 | | if (ssl->session->ticketLenAlloc > 0) { |
1233 | | XFREE(ssl->session->ticket, ssl->session->heap, |
1234 | | DYNAMIC_TYPE_SESSION_TICK); |
1235 | | } |
1236 | | ssl->session->ticket = (byte*)XMALLOC(bufSz, ssl->session->heap, |
1237 | | DYNAMIC_TYPE_SESSION_TICK); |
1238 | | if(ssl->session->ticket == NULL) { |
1239 | | ssl->session->ticket = ssl->session->staticTicket; |
1240 | | ssl->session->ticketLenAlloc = 0; |
1241 | | return MEMORY_ERROR; |
1242 | | } |
1243 | | ssl->session->ticketLenAlloc = (word16)bufSz; |
1244 | | } |
1245 | | } |
1246 | | XMEMCPY(ssl->session->ticket, buf, bufSz); |
1247 | | } |
1248 | | ssl->session->ticketLen = (word16)bufSz; |
1249 | | |
1250 | | return WOLFSSL_SUCCESS; |
1251 | | } |
1252 | | |
1253 | | |
1254 | | /* Set the session ticket callback and user context on the object. |
1255 | | * |
1256 | | * @param [in] ssl SSL/TLS object. |
1257 | | * @param [in] cb Session ticket callback. |
1258 | | * @param [in] ctx User context passed to the callback. |
1259 | | * @return WOLFSSL_SUCCESS on success. |
1260 | | * @return BAD_FUNC_ARG when ssl is NULL. |
1261 | | */ |
1262 | | int wolfSSL_set_SessionTicket_cb(WOLFSSL* ssl, |
1263 | | CallbackSessionTicket cb, void* ctx) |
1264 | | { |
1265 | | if (ssl == NULL) |
1266 | | return BAD_FUNC_ARG; |
1267 | | |
1268 | | ssl->session_ticket_cb = cb; |
1269 | | ssl->session_ticket_ctx = ctx; |
1270 | | |
1271 | | return WOLFSSL_SUCCESS; |
1272 | | } |
1273 | | #endif /* !NO_WOLFSSL_CLIENT */ |
1274 | | |
1275 | | #endif /* HAVE_SESSION_TICKET */ |
1276 | | |
1277 | | |
1278 | | #ifdef HAVE_EXTENDED_MASTER |
1279 | | #ifndef NO_WOLFSSL_CLIENT |
1280 | | |
1281 | | /* Disable the Extended Master Secret extension on the context. |
1282 | | * |
1283 | | * @param [in] ctx SSL/TLS context object. |
1284 | | * @return WOLFSSL_SUCCESS on success. |
1285 | | * @return BAD_FUNC_ARG when ctx is NULL. |
1286 | | */ |
1287 | | int wolfSSL_CTX_DisableExtendedMasterSecret(WOLFSSL_CTX* ctx) |
1288 | 0 | { |
1289 | 0 | if (ctx == NULL) |
1290 | 0 | return BAD_FUNC_ARG; |
1291 | | |
1292 | 0 | ctx->haveEMS = 0; |
1293 | |
|
1294 | 0 | return WOLFSSL_SUCCESS; |
1295 | 0 | } |
1296 | | |
1297 | | |
1298 | | /* Disable the Extended Master Secret extension on the object. |
1299 | | * |
1300 | | * @param [in] ssl SSL/TLS object. |
1301 | | * @return WOLFSSL_SUCCESS on success. |
1302 | | * @return BAD_FUNC_ARG when ssl is NULL. |
1303 | | */ |
1304 | | int wolfSSL_DisableExtendedMasterSecret(WOLFSSL* ssl) |
1305 | 0 | { |
1306 | 0 | if (ssl == NULL) |
1307 | 0 | return BAD_FUNC_ARG; |
1308 | | |
1309 | 0 | ssl->options.haveEMS = 0; |
1310 | |
|
1311 | 0 | return WOLFSSL_SUCCESS; |
1312 | 0 | } |
1313 | | |
1314 | | #endif |
1315 | | #endif |
1316 | | |
1317 | | #endif /* !NO_TLS */ |
1318 | | /* ---- OpenSSL-compatibility TLS extension APIs (moved from ssl.c) ---- */ |
1319 | | |
1320 | | #ifdef OPENSSL_EXTRA |
1321 | | |
1322 | | #ifdef HAVE_PK_CALLBACKS |
1323 | | /* Set the debug argument passed to the logging callback on the object. |
1324 | | * |
1325 | | * @param [in] ssl SSL/TLS object. |
1326 | | * @param [in] arg Debug argument. |
1327 | | * @return WOLFSSL_SUCCESS on success. |
1328 | | * @return WOLFSSL_FAILURE when ssl is NULL. |
1329 | | */ |
1330 | | long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg) |
1331 | | { |
1332 | | if (ssl == NULL) { |
1333 | | return WOLFSSL_FAILURE; |
1334 | | } |
1335 | | |
1336 | | ssl->loggingCtx = arg; |
1337 | | return WOLFSSL_SUCCESS; |
1338 | | } |
1339 | | #endif /* HAVE_PK_CALLBACKS */ |
1340 | | |
1341 | | #ifndef NO_WOLFSSL_STUB |
1342 | | /* Get the certificate status request extensions on the object. |
1343 | | * |
1344 | | * Not implemented - stub for OpenSSL compatibility. |
1345 | | * |
1346 | | * @param [in] s SSL/TLS object. |
1347 | | * @param [in] arg Ignored. |
1348 | | * @return WOLFSSL_FAILURE always. |
1349 | | */ |
1350 | | long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg) |
1351 | | { |
1352 | | (void)s; |
1353 | | (void)arg; |
1354 | | WOLFSSL_STUB("wolfSSL_get_tlsext_status_exts"); |
1355 | | return WOLFSSL_FAILURE; |
1356 | | } |
1357 | | #endif |
1358 | | |
1359 | | /* Set the certificate status request extensions on the object. |
1360 | | * |
1361 | | * Not implemented - stub for OpenSSL compatibility. |
1362 | | * |
1363 | | * @param [in] s SSL/TLS object. |
1364 | | * @param [in] arg Ignored. |
1365 | | * @return WOLFSSL_FAILURE always. |
1366 | | */ |
1367 | | #ifndef NO_WOLFSSL_STUB |
1368 | | long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg) |
1369 | | { |
1370 | | (void)s; |
1371 | | (void)arg; |
1372 | | WOLFSSL_STUB("wolfSSL_set_tlsext_status_exts"); |
1373 | | return WOLFSSL_FAILURE; |
1374 | | } |
1375 | | #endif |
1376 | | |
1377 | | /* Get the certificate status request responder ids on the object. |
1378 | | * |
1379 | | * Not implemented - stub for OpenSSL compatibility. |
1380 | | * |
1381 | | * @param [in] s SSL/TLS object. |
1382 | | * @param [in] arg Ignored. |
1383 | | * @return WOLFSSL_FAILURE always. |
1384 | | */ |
1385 | | #ifndef NO_WOLFSSL_STUB |
1386 | | long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg) |
1387 | | { |
1388 | | (void)s; |
1389 | | (void)arg; |
1390 | | WOLFSSL_STUB("wolfSSL_get_tlsext_status_ids"); |
1391 | | return WOLFSSL_FAILURE; |
1392 | | } |
1393 | | #endif |
1394 | | |
1395 | | /* Set the certificate status request responder ids on the object. |
1396 | | * |
1397 | | * Not implemented - stub for OpenSSL compatibility. |
1398 | | * |
1399 | | * @param [in] s SSL/TLS object. |
1400 | | * @param [in] arg Ignored. |
1401 | | * @return WOLFSSL_FAILURE always. |
1402 | | */ |
1403 | | #ifndef NO_WOLFSSL_STUB |
1404 | | long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg) |
1405 | | { |
1406 | | (void)s; |
1407 | | (void)arg; |
1408 | | WOLFSSL_STUB("wolfSSL_set_tlsext_status_ids"); |
1409 | | return WOLFSSL_FAILURE; |
1410 | | } |
1411 | | #endif |
1412 | | |
1413 | | #ifdef HAVE_MAX_FRAGMENT |
1414 | | #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_TLS) |
1415 | | /* Set the Maximum Fragment Length extension on the context. |
1416 | | * |
1417 | | * @param [in] c SSL/TLS context object. |
1418 | | * @param [in] mode Maximum fragment length mode, e.g. WOLFSSL_MFL_2_9. |
1419 | | * @return WOLFSSL_SUCCESS on success. |
1420 | | * @return BAD_FUNC_ARG when c is NULL or mode is out of range. |
1421 | | */ |
1422 | | int wolfSSL_CTX_set_tlsext_max_fragment_length(WOLFSSL_CTX *c, |
1423 | | unsigned char mode) |
1424 | | { |
1425 | | if (c == NULL || (mode < WOLFSSL_MFL_2_9 || mode > WOLFSSL_MFL_2_12 )) |
1426 | | return BAD_FUNC_ARG; |
1427 | | |
1428 | | return wolfSSL_CTX_UseMaxFragment(c, mode); |
1429 | | } |
1430 | | /* Set the Maximum Fragment Length extension on the object. |
1431 | | * |
1432 | | * @param [in] s SSL/TLS object. |
1433 | | * @param [in] mode Maximum fragment length mode, e.g. WOLFSSL_MFL_2_9. |
1434 | | * @return WOLFSSL_SUCCESS on success. |
1435 | | * @return BAD_FUNC_ARG when s is NULL or mode is out of range. |
1436 | | */ |
1437 | | int wolfSSL_set_tlsext_max_fragment_length(WOLFSSL *s, unsigned char mode) |
1438 | | { |
1439 | | if (s == NULL || (mode < WOLFSSL_MFL_2_9 || mode > WOLFSSL_MFL_2_12 )) |
1440 | | return BAD_FUNC_ARG; |
1441 | | |
1442 | | return wolfSSL_UseMaxFragment(s, mode); |
1443 | | } |
1444 | | #endif /* !NO_WOLFSSL_CLIENT && !NO_TLS */ |
1445 | | #endif /* HAVE_MAX_FRAGMENT */ |
1446 | | |
1447 | | /* Set the signature algorithms list on the context. |
1448 | | * |
1449 | | * @param [in] ctx SSL/TLS context object. |
1450 | | * @param [in] list Colon-separated list of <public key>+<digest> algorithms. |
1451 | | * @return WOLFSSL_SUCCESS on success. |
1452 | | * @return WOLFSSL_FAILURE when ctx or list is NULL or on error. |
1453 | | */ |
1454 | | int wolfSSL_CTX_set1_sigalgs_list(WOLFSSL_CTX* ctx, const char* list) |
1455 | | { |
1456 | | WOLFSSL_MSG("wolfSSL_CTX_set1_sigalg_list"); |
1457 | | |
1458 | | if (ctx == NULL || list == NULL) { |
1459 | | WOLFSSL_MSG("Bad function arguments"); |
1460 | | return WOLFSSL_FAILURE; |
1461 | | } |
1462 | | |
1463 | | if (AllocateCtxSuites(ctx) != 0) |
1464 | | return WOLFSSL_FAILURE; |
1465 | | |
1466 | | return SetSuitesHashSigAlgo(ctx->suites, list); |
1467 | | } |
1468 | | |
1469 | | /* Set the signature algorithms list on the object. |
1470 | | * |
1471 | | * @param [in] ssl SSL/TLS object. |
1472 | | * @param [in] list Colon-separated list of <public key>+<digest> algorithms. |
1473 | | * @return WOLFSSL_SUCCESS on success. |
1474 | | * @return WOLFSSL_FAILURE when ssl or list is NULL or on error. |
1475 | | */ |
1476 | | int wolfSSL_set1_sigalgs_list(WOLFSSL* ssl, const char* list) |
1477 | | { |
1478 | | WOLFSSL_MSG("wolfSSL_set1_sigalg_list"); |
1479 | | |
1480 | | if (ssl == NULL || list == NULL) { |
1481 | | WOLFSSL_MSG("Bad function arguments"); |
1482 | | return WOLFSSL_FAILURE; |
1483 | | } |
1484 | | |
1485 | | if (AllocateSuites(ssl) != 0) |
1486 | | return WOLFSSL_FAILURE; |
1487 | | |
1488 | | return SetSuitesHashSigAlgo(ssl->suites, list); |
1489 | | } |
1490 | | |
1491 | | #ifdef HAVE_ECC |
1492 | | |
1493 | | #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) |
1494 | | /* Set the supported groups list, by name, on the context. |
1495 | | * |
1496 | | * @param [in] ctx SSL/TLS context object. |
1497 | | * @param [in] list Colon-separated list of group names. |
1498 | | * @return WOLFSSL_SUCCESS on success. |
1499 | | * @return WOLFSSL_FAILURE when ctx or list is NULL or on error. |
1500 | | */ |
1501 | | int wolfSSL_CTX_set1_groups_list(WOLFSSL_CTX *ctx, const char *list) |
1502 | | { |
1503 | | if (!ctx || !list) { |
1504 | | return WOLFSSL_FAILURE; |
1505 | | } |
1506 | | |
1507 | | return set_curves_list(NULL, ctx, list, 0); |
1508 | | } |
1509 | | |
1510 | | /* Set the supported groups list, by name, on the object. |
1511 | | * |
1512 | | * @param [in] ssl SSL/TLS object. |
1513 | | * @param [in] list Colon-separated list of group names. |
1514 | | * @return WOLFSSL_SUCCESS on success. |
1515 | | * @return WOLFSSL_FAILURE when ssl or list is NULL or on error. |
1516 | | */ |
1517 | | int wolfSSL_set1_groups_list(WOLFSSL *ssl, const char *list) |
1518 | | { |
1519 | | if (!ssl || !list) { |
1520 | | return WOLFSSL_FAILURE; |
1521 | | } |
1522 | | |
1523 | | return set_curves_list(ssl, NULL, list, 0); |
1524 | | } |
1525 | | #endif /* WOLFSSL_TLS13 */ |
1526 | | |
1527 | | #endif /* HAVE_ECC */ |
1528 | | |
1529 | | #endif /* OPENSSL_EXTRA */ |
1530 | | |
1531 | | #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) |
1532 | | |
1533 | | #ifdef HAVE_SNI |
1534 | | /* Set the SNI host name extension on the object. |
1535 | | * |
1536 | | * @param [in] ssl SSL/TLS object. |
1537 | | * @param [in] host_name Host name string. |
1538 | | * @return WOLFSSL_SUCCESS on success. |
1539 | | * @return BAD_FUNC_ARG when ssl is NULL. |
1540 | | * @return Negative value on error. |
1541 | | */ |
1542 | | int wolfSSL_set_tlsext_host_name(WOLFSSL* ssl, const char* host_name) |
1543 | | { |
1544 | | int ret; |
1545 | | WOLFSSL_ENTER("wolfSSL_set_tlsext_host_name"); |
1546 | | ret = wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, host_name, |
1547 | | (word16)XSTRLEN(host_name)); |
1548 | | WOLFSSL_LEAVE("wolfSSL_set_tlsext_host_name", ret); |
1549 | | return ret; |
1550 | | } |
1551 | | |
1552 | | #ifndef NO_WOLFSSL_SERVER |
1553 | | /* Get the SNI host name requested for the object. |
1554 | | * |
1555 | | * May be called by a server to get the accepted name or by a client to get |
1556 | | * the requested name. |
1557 | | * |
1558 | | * @param [in] ssl SSL/TLS object. |
1559 | | * @param [in] type SNI type. |
1560 | | * @return Requested server name on success. |
1561 | | * @return NULL when ssl is NULL or no name is set. |
1562 | | */ |
1563 | | const char * wolfSSL_get_servername(WOLFSSL* ssl, byte type) |
1564 | | { |
1565 | | void * serverName = NULL; |
1566 | | if (ssl == NULL) |
1567 | | return NULL; |
1568 | | TLSX_SNI_GetRequest(ssl->extensions, type, &serverName, |
1569 | | !wolfSSL_is_server(ssl)); |
1570 | | return (const char *)serverName; |
1571 | | } |
1572 | | #endif |
1573 | | |
1574 | | #endif /* HAVE_SNI */ |
1575 | | |
1576 | | #ifdef HAVE_SNI |
1577 | | /* Set the SNI receive callback on the context. |
1578 | | * |
1579 | | * Compatibility function; consider using wolfSSL_CTX_set_servername_callback(). |
1580 | | * |
1581 | | * @param [in] ctx SSL/TLS context object. |
1582 | | * @param [in] cb SNI receive callback. |
1583 | | * @return WOLFSSL_SUCCESS on success. |
1584 | | * @return WOLFSSL_FAILURE when ctx is NULL. |
1585 | | */ |
1586 | | int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX* ctx, |
1587 | | CallbackSniRecv cb) |
1588 | | { |
1589 | | WOLFSSL_ENTER("wolfSSL_CTX_set_tlsext_servername_callback"); |
1590 | | if (ctx) { |
1591 | | ctx->sniRecvCb = cb; |
1592 | | return WOLFSSL_SUCCESS; |
1593 | | } |
1594 | | return WOLFSSL_FAILURE; |
1595 | | } |
1596 | | |
1597 | | #endif /* HAVE_SNI */ |
1598 | | |
1599 | | #endif /* OPENSSL_ALL || OPENSSL_EXTRA */ |
1600 | | |
1601 | | #ifdef HAVE_SNI |
1602 | | |
1603 | | /* Set the SNI receive callback on the context. |
1604 | | * |
1605 | | * @param [in] ctx SSL/TLS context object. |
1606 | | * @param [in] cb SNI receive callback. |
1607 | | */ |
1608 | | void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX* ctx, CallbackSniRecv cb) |
1609 | 0 | { |
1610 | 0 | WOLFSSL_ENTER("wolfSSL_CTX_set_servername_callback"); |
1611 | |
|
1612 | 0 | if (ctx != NULL) { |
1613 | 0 | ctx->sniRecvCb = cb; |
1614 | 0 | } |
1615 | 0 | } |
1616 | | |
1617 | | |
1618 | | /* Set the user argument passed to the SNI receive callback on the context. |
1619 | | * |
1620 | | * @param [in] ctx SSL/TLS context object. |
1621 | | * @param [in] arg User argument for the SNI receive callback. |
1622 | | * @return WOLFSSL_SUCCESS on success. |
1623 | | * @return WOLFSSL_FAILURE when ctx is NULL. |
1624 | | */ |
1625 | | int wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX* ctx, void* arg) |
1626 | 0 | { |
1627 | 0 | WOLFSSL_ENTER("wolfSSL_CTX_set_servername_arg"); |
1628 | 0 | if (ctx) { |
1629 | 0 | ctx->sniRecvCbArg = arg; |
1630 | 0 | return WOLFSSL_SUCCESS; |
1631 | 0 | } |
1632 | 0 | return WOLFSSL_FAILURE; |
1633 | 0 | } |
1634 | | |
1635 | | #endif /* HAVE_SNI */ |
1636 | | |
1637 | | #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \ |
1638 | | || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) |
1639 | | |
1640 | | #if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER) |
1641 | | /* Expected return values from implementations of OpenSSL ticket key callback. |
1642 | | */ |
1643 | | #define TICKET_KEY_CB_RET_FAILURE (-1) |
1644 | | #define TICKET_KEY_CB_RET_NOT_FOUND 0 |
1645 | | #define TICKET_KEY_CB_RET_OK 1 |
1646 | | #define TICKET_KEY_CB_RET_RENEW 2 |
1647 | | |
1648 | | /* Encrypt the ticket data in place and compute the HMAC over it. |
1649 | | * |
1650 | | * @param [in] evpCtx Cipher context initialized by the callback. |
1651 | | * @param [in] hmacCtx HMAC context initialized by the callback. |
1652 | | * @param [in, out] encTicket Ticket data, encrypted in place. |
1653 | | * @param [in] encTicketLen Length of the plaintext ticket data in bytes. |
1654 | | * @param [in] encSz Capacity of the ticket buffer in bytes. |
1655 | | * @param [out] mac HMAC of the encrypted data. |
1656 | | * @param [out] outSz Length of the encrypted data in bytes. |
1657 | | * @return 1 on success. |
1658 | | * @return 0 on error. |
1659 | | */ |
1660 | | static int wolfssl_ticket_key_enc(WOLFSSL_EVP_CIPHER_CTX* evpCtx, |
1661 | | WOLFSSL_HMAC_CTX* hmacCtx, unsigned char* encTicket, int encTicketLen, |
1662 | | int encSz, unsigned char* mac, int* outSz) |
1663 | | { |
1664 | | int ret = 1; |
1665 | | int len = 0; |
1666 | | int totalSz = 0; |
1667 | | unsigned int mdSz = 0; |
1668 | | |
1669 | | /* Encrypt in place. */ |
1670 | | if (!wolfSSL_EVP_CipherUpdate(evpCtx, encTicket, &len, encTicket, |
1671 | | encTicketLen)) { |
1672 | | ret = 0; |
1673 | | } |
1674 | | if (ret == 1) { |
1675 | | totalSz = len; |
1676 | | /* Encrypted data must fit in the output buffer. */ |
1677 | | if (totalSz > encSz) { |
1678 | | ret = 0; |
1679 | | } |
1680 | | } |
1681 | | if ((ret == 1) && |
1682 | | (!wolfSSL_EVP_EncryptFinal(evpCtx, &encTicket[len], &len))) { |
1683 | | ret = 0; |
1684 | | } |
1685 | | if (ret == 1) { |
1686 | | /* Total length of encrypted data. */ |
1687 | | totalSz += len; |
1688 | | if (totalSz > encSz) { |
1689 | | ret = 0; |
1690 | | } |
1691 | | } |
1692 | | /* HMAC the encrypted data into the parameter 'mac'. */ |
1693 | | if ((ret == 1) && (!wolfSSL_HMAC_Update(hmacCtx, encTicket, totalSz))) { |
1694 | | ret = 0; |
1695 | | } |
1696 | | if ((ret == 1) && (!wolfSSL_HMAC_Final(hmacCtx, mac, &mdSz))) { |
1697 | | ret = 0; |
1698 | | } |
1699 | | if (ret == 1) { |
1700 | | *outSz = totalSz; |
1701 | | } |
1702 | | |
1703 | | return ret; |
1704 | | } |
1705 | | |
1706 | | /* Verify the ticket HMAC then decrypt the ticket data in place. |
1707 | | * |
1708 | | * @param [in] evpCtx Cipher context initialized by the callback. |
1709 | | * @param [in] hmacCtx HMAC context initialized by the callback. |
1710 | | * @param [in, out] encTicket Ticket data, decrypted in place. |
1711 | | * @param [in] encTicketLen Length of the encrypted ticket data in bytes. |
1712 | | * @param [in] mac Expected HMAC of the encrypted data. |
1713 | | * @param [out] outSz Length of the decrypted data in bytes. |
1714 | | * @return 1 on success. |
1715 | | * @return 0 on error or when the HMAC does not match. |
1716 | | */ |
1717 | | static int wolfssl_ticket_key_dec(WOLFSSL_EVP_CIPHER_CTX* evpCtx, |
1718 | | WOLFSSL_HMAC_CTX* hmacCtx, unsigned char* encTicket, int encTicketLen, |
1719 | | const unsigned char* mac, int* outSz) |
1720 | | { |
1721 | | int ret = 1; |
1722 | | int len = 0; |
1723 | | int totalSz = 0; |
1724 | | unsigned int mdSz = 0; |
1725 | | byte digest[WC_MAX_DIGEST_SIZE]; |
1726 | | |
1727 | | /* HMAC the encrypted data and compare it to the passed in data. */ |
1728 | | if (!wolfSSL_HMAC_Update(hmacCtx, encTicket, encTicketLen)) { |
1729 | | ret = 0; |
1730 | | } |
1731 | | if ((ret == 1) && (!wolfSSL_HMAC_Final(hmacCtx, digest, &mdSz))) { |
1732 | | ret = 0; |
1733 | | } |
1734 | | if ((ret == 1) && (ConstantCompare(mac, digest, (int)mdSz) != 0)) { |
1735 | | ret = 0; |
1736 | | } |
1737 | | /* Decrypt the ticket data in place. */ |
1738 | | if ((ret == 1) && |
1739 | | (!wolfSSL_EVP_CipherUpdate(evpCtx, encTicket, &len, encTicket, |
1740 | | encTicketLen))) { |
1741 | | ret = 0; |
1742 | | } |
1743 | | if (ret == 1) { |
1744 | | totalSz = len; |
1745 | | /* Decrypted data must fit in the buffer. */ |
1746 | | if (totalSz > encTicketLen) { |
1747 | | ret = 0; |
1748 | | } |
1749 | | } |
1750 | | if ((ret == 1) && |
1751 | | (!wolfSSL_EVP_DecryptFinal(evpCtx, &encTicket[len], &len))) { |
1752 | | ret = 0; |
1753 | | } |
1754 | | if (ret == 1) { |
1755 | | /* Total length of decrypted data. */ |
1756 | | totalSz += len; |
1757 | | if (totalSz > encTicketLen) { |
1758 | | ret = 0; |
1759 | | } |
1760 | | } |
1761 | | if (ret == 1) { |
1762 | | *outSz = totalSz; |
1763 | | } |
1764 | | |
1765 | | return ret; |
1766 | | } |
1767 | | |
1768 | | /* Encrypt or decrypt a session ticket using the OpenSSL ticket key callback. |
1769 | | * |
1770 | | * Wraps the application's OpenSSL-style callback that initializes the cipher |
1771 | | * and HMAC. |
1772 | | * |
1773 | | * @param [in] ssl SSL/TLS object. |
1774 | | * @param [in] keyName Key name identifying the key to use. |
1775 | | * @param [in] iv IV to use. |
1776 | | * @param [in, out] mac MAC of the encrypted data. |
1777 | | * @param [in] enc 1 to encrypt the ticket, 0 to decrypt. |
1778 | | * @param [in, out] encTicket Ticket data, encrypted/decrypted in place. |
1779 | | * @param [in] encTicketLen Length of the ticket data in bytes. |
1780 | | * @param [out] encLen Output length of the ticket data. |
1781 | | * @param [in] ctx Ignored. Application specific data. |
1782 | | * @return WOLFSSL_TICKET_RET_OK on success. |
1783 | | * @return WOLFSSL_TICKET_RET_CREATE when a new ticket is required. |
1784 | | * @return WOLFSSL_TICKET_RET_FATAL on error. |
1785 | | */ |
1786 | | static int wolfSSL_TicketKeyCb(WOLFSSL* ssl, |
1787 | | unsigned char keyName[WOLFSSL_TICKET_NAME_SZ], |
1788 | | unsigned char iv[WOLFSSL_TICKET_IV_SZ], |
1789 | | unsigned char mac[WOLFSSL_TICKET_MAC_SZ], |
1790 | | int enc, unsigned char* encTicket, |
1791 | | int encTicketLen, int* encLen, void* ctx) |
1792 | | { |
1793 | | WC_DECLARE_VAR(evpCtx, WOLFSSL_EVP_CIPHER_CTX, 1, 0); |
1794 | | int ret = WOLFSSL_TICKET_RET_OK; |
1795 | | |
1796 | | (void)ctx; |
1797 | | |
1798 | | WOLFSSL_ENTER("wolfSSL_TicketKeyCb"); |
1799 | | |
1800 | | if ((ssl == NULL) || (ssl->ctx == NULL) || |
1801 | | (ssl->ctx->ticketEncWrapCb == NULL)) { |
1802 | | WOLFSSL_MSG("Bad parameter"); |
1803 | | ret = WOLFSSL_TICKET_RET_FATAL; |
1804 | | } |
1805 | | |
1806 | | #ifdef WOLFSSL_SMALL_STACK |
1807 | | if (ret == WOLFSSL_TICKET_RET_OK) { |
1808 | | evpCtx = (WOLFSSL_EVP_CIPHER_CTX *)XMALLOC(sizeof(*evpCtx), ssl->heap, |
1809 | | DYNAMIC_TYPE_TMP_BUFFER); |
1810 | | if (evpCtx == NULL) { |
1811 | | WOLFSSL_MSG("out of memory"); |
1812 | | ret = WOLFSSL_TICKET_RET_FATAL; |
1813 | | } |
1814 | | } |
1815 | | #endif |
1816 | | |
1817 | | if (ret == WOLFSSL_TICKET_RET_OK) { |
1818 | | WOLFSSL_HMAC_CTX hmacCtx; |
1819 | | |
1820 | | /* Initialize the cipher and HMAC. */ |
1821 | | wolfSSL_EVP_CIPHER_CTX_init(evpCtx); |
1822 | | |
1823 | | if (wolfSSL_HMAC_CTX_Init(&hmacCtx) != WOLFSSL_SUCCESS) { |
1824 | | WOLFSSL_MSG("wolfSSL_HMAC_CTX_Init error"); |
1825 | | ret = WOLFSSL_TICKET_RET_FATAL; |
1826 | | } |
1827 | | |
1828 | | if (ret == WOLFSSL_TICKET_RET_OK) { |
1829 | | int res; |
1830 | | int totalSz = 0; |
1831 | | |
1832 | | res = ssl->ctx->ticketEncWrapCb(ssl, keyName, iv, evpCtx, &hmacCtx, |
1833 | | enc); |
1834 | | if ((res != TICKET_KEY_CB_RET_OK) && |
1835 | | (res != TICKET_KEY_CB_RET_RENEW)) { |
1836 | | WOLFSSL_MSG("Ticket callback error"); |
1837 | | ret = WOLFSSL_TICKET_RET_FATAL; |
1838 | | } |
1839 | | |
1840 | | if (ret == WOLFSSL_TICKET_RET_OK) { |
1841 | | if (wolfSSL_HMAC_size(&hmacCtx) > WOLFSSL_TICKET_MAC_SZ) { |
1842 | | WOLFSSL_MSG("Ticket cipher MAC size error"); |
1843 | | ret = WOLFSSL_TICKET_RET_FATAL; |
1844 | | } |
1845 | | } |
1846 | | |
1847 | | if (ret == WOLFSSL_TICKET_RET_OK) { |
1848 | | if (enc) { |
1849 | | if (!wolfssl_ticket_key_enc(evpCtx, &hmacCtx, encTicket, |
1850 | | encTicketLen, *encLen, mac, &totalSz)) { |
1851 | | ret = WOLFSSL_TICKET_RET_FATAL; |
1852 | | } |
1853 | | } |
1854 | | else { |
1855 | | if (!wolfssl_ticket_key_dec(evpCtx, &hmacCtx, encTicket, |
1856 | | encTicketLen, mac, &totalSz)) { |
1857 | | ret = WOLFSSL_TICKET_RET_FATAL; |
1858 | | } |
1859 | | } |
1860 | | } |
1861 | | |
1862 | | if (ret == WOLFSSL_TICKET_RET_OK) { |
1863 | | *encLen = totalSz; |
1864 | | |
1865 | | if ((res == TICKET_KEY_CB_RET_RENEW) && |
1866 | | (!IsAtLeastTLSv1_3(ssl->version)) && (!enc)) { |
1867 | | ret = WOLFSSL_TICKET_RET_CREATE; |
1868 | | } |
1869 | | else { |
1870 | | ret = WOLFSSL_TICKET_RET_OK; |
1871 | | } |
1872 | | } |
1873 | | |
1874 | | (void)wc_HmacFree(&hmacCtx.hmac); |
1875 | | } |
1876 | | (void)wolfSSL_EVP_CIPHER_CTX_cleanup(evpCtx); |
1877 | | WC_FREE_VAR_EX(evpCtx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); |
1878 | | } |
1879 | | |
1880 | | return ret; |
1881 | | } |
1882 | | |
1883 | | /* Set the OpenSSL-style session ticket key callback on the context. |
1884 | | * |
1885 | | * Installs a wrapper as the ticket encryption callback. |
1886 | | * |
1887 | | * @param [in] ctx SSL/TLS context object. |
1888 | | * @param [in] cb OpenSSL session ticket key callback. |
1889 | | * @return WOLFSSL_SUCCESS on success. |
1890 | | */ |
1891 | | int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *ctx, ticketCompatCb cb) |
1892 | | { |
1893 | | |
1894 | | /* Set the ticket encryption callback to be a wrapper around OpenSSL |
1895 | | * callback. |
1896 | | */ |
1897 | | ctx->ticketEncCb = wolfSSL_TicketKeyCb; |
1898 | | ctx->ticketEncWrapCb = cb; |
1899 | | |
1900 | | return WOLFSSL_SUCCESS; |
1901 | | } |
1902 | | |
1903 | | #endif /* HAVE_SESSION_TICKET */ |
1904 | | |
1905 | | #endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || |
1906 | | OPENSSL_EXTRA || HAVE_LIGHTY */ |
1907 | | |
1908 | | #if defined(HAVE_SESSION_TICKET) && !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \ |
1909 | | !defined(NO_WOLFSSL_SERVER) |
1910 | | /* Serialize the session ticket encryption keys. |
1911 | | * |
1912 | | * @param [in] ctx SSL/TLS context object. |
1913 | | * @param [in] keys Buffer to hold session ticket keys. |
1914 | | * @param [in] keylen Length of buffer. |
1915 | | * @return WOLFSSL_SUCCESS on success. |
1916 | | * @return WOLFSSL_FAILURE when ctx is NULL, keys is NULL or keylen is not the |
1917 | | * correct length. |
1918 | | */ |
1919 | | long wolfSSL_CTX_get_tlsext_ticket_keys(WOLFSSL_CTX *ctx, |
1920 | | unsigned char *keys, int keylen) |
1921 | | { |
1922 | | if (ctx == NULL || keys == NULL) { |
1923 | | return WOLFSSL_FAILURE; |
1924 | | } |
1925 | | if (keylen != WOLFSSL_TICKET_KEYS_SZ) { |
1926 | | return WOLFSSL_FAILURE; |
1927 | | } |
1928 | | |
1929 | | XMEMCPY(keys, ctx->ticketKeyCtx.name, WOLFSSL_TICKET_NAME_SZ); |
1930 | | keys += WOLFSSL_TICKET_NAME_SZ; |
1931 | | XMEMCPY(keys, ctx->ticketKeyCtx.key[0], WOLFSSL_TICKET_KEY_SZ); |
1932 | | keys += WOLFSSL_TICKET_KEY_SZ; |
1933 | | XMEMCPY(keys, ctx->ticketKeyCtx.key[1], WOLFSSL_TICKET_KEY_SZ); |
1934 | | keys += WOLFSSL_TICKET_KEY_SZ; |
1935 | | c32toa(ctx->ticketKeyCtx.expirary[0], keys); |
1936 | | keys += OPAQUE32_LEN; |
1937 | | c32toa(ctx->ticketKeyCtx.expirary[1], keys); |
1938 | | |
1939 | | return WOLFSSL_SUCCESS; |
1940 | | } |
1941 | | |
1942 | | /* Deserialize the session ticket encryption keys. |
1943 | | * |
1944 | | * @param [in] ctx SSL/TLS context object. |
1945 | | * @param [in] keys Session ticket keys. |
1946 | | * @param [in] keylen Length of data. |
1947 | | * @return WOLFSSL_SUCCESS on success. |
1948 | | * @return WOLFSSL_FAILURE when ctx is NULL, keys is NULL or keylen is not the |
1949 | | * correct length. |
1950 | | */ |
1951 | | long wolfSSL_CTX_set_tlsext_ticket_keys(WOLFSSL_CTX *ctx, |
1952 | | const void *keys_vp, int keylen) |
1953 | | { |
1954 | | const byte* keys = (const byte*)keys_vp; |
1955 | | if (ctx == NULL || keys == NULL) { |
1956 | | return WOLFSSL_FAILURE; |
1957 | | } |
1958 | | if (keylen != WOLFSSL_TICKET_KEYS_SZ) { |
1959 | | return WOLFSSL_FAILURE; |
1960 | | } |
1961 | | |
1962 | | XMEMCPY(ctx->ticketKeyCtx.name, keys, WOLFSSL_TICKET_NAME_SZ); |
1963 | | keys += WOLFSSL_TICKET_NAME_SZ; |
1964 | | XMEMCPY(ctx->ticketKeyCtx.key[0], keys, WOLFSSL_TICKET_KEY_SZ); |
1965 | | keys += WOLFSSL_TICKET_KEY_SZ; |
1966 | | XMEMCPY(ctx->ticketKeyCtx.key[1], keys, WOLFSSL_TICKET_KEY_SZ); |
1967 | | keys += WOLFSSL_TICKET_KEY_SZ; |
1968 | | ato32(keys, &ctx->ticketKeyCtx.expirary[0]); |
1969 | | keys += OPAQUE32_LEN; |
1970 | | ato32(keys, &ctx->ticketKeyCtx.expirary[1]); |
1971 | | |
1972 | | return WOLFSSL_SUCCESS; |
1973 | | } |
1974 | | #endif |
1975 | | |
1976 | | #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \ |
1977 | | defined(WOLFSSL_HAPROXY) || defined(HAVE_LIGHTY) || \ |
1978 | | defined(WOLFSSL_QUIC) |
1979 | | #ifdef HAVE_ALPN |
1980 | | /* Get the ALPN protocol selected for the object. |
1981 | | * |
1982 | | * @param [in] ssl SSL/TLS object. |
1983 | | * @param [out] data Selected protocol data. |
1984 | | * @param [out] len Length of the protocol data in bytes. |
1985 | | */ |
1986 | | void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl, const unsigned char **data, |
1987 | | unsigned int *len) |
1988 | | { |
1989 | | word16 nameLen = 0; |
1990 | | |
1991 | | if ((ssl != NULL) && (data != NULL) && (len != NULL)) { |
1992 | | TLSX_ALPN_GetRequest(ssl->extensions, (void **)data, &nameLen); |
1993 | | *len = nameLen; |
1994 | | } |
1995 | | } |
1996 | | |
1997 | | /* Determine whether a protocol appears in the client's protocol list. |
1998 | | * |
1999 | | * The client's list is in wire format: each entry is a length byte followed |
2000 | | * by that many protocol-name bytes. |
2001 | | * |
2002 | | * @param [in] proto Protocol name to look for. |
2003 | | * @param [in] protoLen Length of the protocol name in bytes. |
2004 | | * @param [in] clientNames Client's protocol list. |
2005 | | * @param [in] clientLen Length of the client's list in bytes. |
2006 | | * @return 1 when the protocol is in the list. |
2007 | | * @return 0 when the protocol is not in the list. |
2008 | | */ |
2009 | | static int wolfssl_protocol_in_list(const unsigned char* proto, byte protoLen, |
2010 | | const unsigned char* clientNames, unsigned int clientLen) |
2011 | | { |
2012 | | unsigned int j; |
2013 | | byte lenClient; |
2014 | | int found = 0; |
2015 | | |
2016 | | /* Compare against each of the client's length-prefixed names. */ |
2017 | | for (j = 0; j < clientLen; j += lenClient) { |
2018 | | lenClient = clientNames[j++]; |
2019 | | if ((lenClient == 0) || (j + lenClient > clientLen)) { |
2020 | | break; |
2021 | | } |
2022 | | |
2023 | | if ((protoLen == lenClient) && |
2024 | | (XMEMCMP(proto, clientNames + j, protoLen) == 0)) { |
2025 | | found = 1; |
2026 | | break; |
2027 | | } |
2028 | | } |
2029 | | |
2030 | | return found; |
2031 | | } |
2032 | | |
2033 | | /* Select the next protocol from the peer's list that matches the client's. |
2034 | | * |
2035 | | * On no overlap, the first client protocol is selected. |
2036 | | * |
2037 | | * @param [out] out Selected protocol data. |
2038 | | * @param [out] outLen Length of the selected protocol in bytes. |
2039 | | * @param [in] in Peer's protocol list. |
2040 | | * @param [in] inLen Length of the peer's list in bytes. |
2041 | | * @param [in] clientNames Client's protocol list. |
2042 | | * @param [in] clientLen Length of the client's list in bytes. |
2043 | | * @return WOLFSSL_NPN_NEGOTIATED when a match was found. |
2044 | | * @return WOLFSSL_NPN_NO_OVERLAP when no match was found. |
2045 | | * @return WOLFSSL_NPN_UNSUPPORTED when an argument is NULL. |
2046 | | */ |
2047 | | int wolfSSL_select_next_proto(unsigned char **out, unsigned char *outLen, |
2048 | | const unsigned char *in, unsigned int inLen, |
2049 | | const unsigned char *clientNames, unsigned int clientLen) |
2050 | | { |
2051 | | unsigned int i; |
2052 | | byte lenIn; |
2053 | | int ret = WOLFSSL_NPN_NO_OVERLAP; |
2054 | | |
2055 | | if ((out == NULL) || (outLen == NULL) || (in == NULL) || |
2056 | | (clientNames == NULL)) { |
2057 | | ret = WOLFSSL_NPN_UNSUPPORTED; |
2058 | | } |
2059 | | else { |
2060 | | /* Walk the peer's list; each entry is a length byte then that many |
2061 | | * protocol-name bytes. */ |
2062 | | for (i = 0; i < inLen; i += lenIn) { |
2063 | | lenIn = in[i++]; |
2064 | | /* Stop on an empty entry or one that runs past the buffer. */ |
2065 | | if ((lenIn == 0) || (i + lenIn > inLen)) { |
2066 | | break; |
2067 | | } |
2068 | | /* Select this peer protocol if the client also offered it. */ |
2069 | | if (wolfssl_protocol_in_list(in + i, lenIn, clientNames, |
2070 | | clientLen)) { |
2071 | | *out = (unsigned char *)(in + i); |
2072 | | *outLen = lenIn; |
2073 | | ret = WOLFSSL_NPN_NEGOTIATED; |
2074 | | break; |
2075 | | } |
2076 | | } |
2077 | | |
2078 | | if (ret != WOLFSSL_NPN_NEGOTIATED) { |
2079 | | /* No overlap: fall back to the client's first protocol. */ |
2080 | | if ((clientLen > 0) && |
2081 | | ((unsigned int)clientNames[0] + 1 <= clientLen)) { |
2082 | | *out = (unsigned char *)clientNames + 1; |
2083 | | *outLen = clientNames[0]; |
2084 | | } |
2085 | | else { |
2086 | | *out = (unsigned char *)clientNames; |
2087 | | *outLen = 0; |
2088 | | } |
2089 | | ret = WOLFSSL_NPN_NO_OVERLAP; |
2090 | | } |
2091 | | } |
2092 | | |
2093 | | return ret; |
2094 | | } |
2095 | | |
2096 | | /* Set the ALPN selection callback on the object. |
2097 | | * |
2098 | | * @param [in] ssl SSL/TLS object. |
2099 | | * @param [in] cb ALPN selection callback. |
2100 | | * @param [in] arg User argument passed to the callback. |
2101 | | */ |
2102 | | void wolfSSL_set_alpn_select_cb(WOLFSSL *ssl, |
2103 | | int (*cb)(WOLFSSL *ssl, const unsigned char **out, unsigned char *outlen, |
2104 | | const unsigned char *in, unsigned int inlen, void *arg), |
2105 | | void *arg) |
2106 | | { |
2107 | | if (ssl != NULL) { |
2108 | | ssl->alpnSelect = cb; |
2109 | | ssl->alpnSelectArg = arg; |
2110 | | } |
2111 | | } |
2112 | | |
2113 | | /* Set the ALPN selection callback on the context. |
2114 | | * |
2115 | | * @param [in] ctx SSL/TLS context object. |
2116 | | * @param [in] cb ALPN selection callback. |
2117 | | * @param [in] arg User argument passed to the callback. |
2118 | | */ |
2119 | | void wolfSSL_CTX_set_alpn_select_cb(WOLFSSL_CTX *ctx, |
2120 | | int (*cb)(WOLFSSL *ssl, const unsigned char **out, unsigned char *outlen, |
2121 | | const unsigned char *in, unsigned int inlen, void *arg), |
2122 | | void *arg) |
2123 | | { |
2124 | | if (ctx != NULL) { |
2125 | | ctx->alpnSelect = cb; |
2126 | | ctx->alpnSelectArg = arg; |
2127 | | } |
2128 | | } |
2129 | | |
2130 | | /* Set the NPN advertised-protocols callback on the context. |
2131 | | * |
2132 | | * Not implemented - stub for OpenSSL compatibility. |
2133 | | * |
2134 | | * @param [in] s SSL/TLS context object. |
2135 | | * @param [in] cb NPN advertised-protocols callback. |
2136 | | * @param [in] arg User argument passed to the callback. |
2137 | | */ |
2138 | | void wolfSSL_CTX_set_next_protos_advertised_cb(WOLFSSL_CTX *s, |
2139 | | int (*cb)(WOLFSSL *ssl, const unsigned char **out, unsigned int *outlen, |
2140 | | void *arg), void *arg) |
2141 | | { |
2142 | | (void)s; |
2143 | | (void)cb; |
2144 | | (void)arg; |
2145 | | WOLFSSL_STUB("wolfSSL_CTX_set_next_protos_advertised_cb"); |
2146 | | } |
2147 | | |
2148 | | /* Set the NPN protocol-selection callback on the context. |
2149 | | * |
2150 | | * Not implemented - stub for OpenSSL compatibility. |
2151 | | * |
2152 | | * @param [in] s SSL/TLS context object. |
2153 | | * @param [in] cb NPN protocol-selection callback. |
2154 | | * @param [in] arg User argument passed to the callback. |
2155 | | */ |
2156 | | void wolfSSL_CTX_set_next_proto_select_cb(WOLFSSL_CTX *s, |
2157 | | int (*cb)(WOLFSSL *ssl, unsigned char **out, unsigned char *outlen, |
2158 | | const unsigned char *in, unsigned int inlen, void *arg), |
2159 | | void *arg) |
2160 | | { |
2161 | | (void)s; |
2162 | | (void)cb; |
2163 | | (void)arg; |
2164 | | WOLFSSL_STUB("wolfSSL_CTX_set_next_proto_select_cb"); |
2165 | | } |
2166 | | |
2167 | | /* Get the NPN protocol negotiated for the object. |
2168 | | * |
2169 | | * Not implemented - stub for OpenSSL compatibility. |
2170 | | * |
2171 | | * @param [in] s SSL/TLS object. |
2172 | | * @param [out] data Negotiated protocol data. |
2173 | | * @param [out] len Length of the protocol data in bytes. |
2174 | | */ |
2175 | | void wolfSSL_get0_next_proto_negotiated(const WOLFSSL *s, |
2176 | | const unsigned char **data, unsigned *len) |
2177 | | { |
2178 | | (void)s; |
2179 | | (void)data; |
2180 | | (void)len; |
2181 | | WOLFSSL_STUB("wolfSSL_get0_next_proto_negotiated"); |
2182 | | } |
2183 | | #endif /* HAVE_ALPN */ |
2184 | | |
2185 | | #endif /* WOLFSSL_NGINX / WOLFSSL_HAPROXY */ |
2186 | | |
2187 | | #if defined(OPENSSL_EXTRA) || defined(HAVE_CURL) |
2188 | | |
2189 | | /* Determine whether an elliptic curve is disabled for the object. |
2190 | | * |
2191 | | * @param [in] ssl SSL/TLS object. |
2192 | | * @param [in] curve_id Curve identifier. |
2193 | | * @return 1 when the curve is disabled or out of range. |
2194 | | * @return 0 when the curve is enabled or is an FFDHE group. |
2195 | | */ |
2196 | | int wolfSSL_curve_is_disabled(const WOLFSSL* ssl, word16 curve_id) |
2197 | | { |
2198 | | int ret = 0; |
2199 | | |
2200 | | WOLFSSL_ENTER("wolfSSL_curve_is_disabled"); |
2201 | | WOLFSSL_MSG_EX("wolfSSL_curve_is_disabled checking for %d", curve_id); |
2202 | | |
2203 | | /* (curve_id >= WOLFSSL_FFDHE_START) - DH parameters are never disabled. */ |
2204 | | if (curve_id < WOLFSSL_FFDHE_START) { |
2205 | | if (curve_id > WOLFSSL_ECC_MAX_AVAIL) { |
2206 | | WOLFSSL_MSG("Curve id out of supported range"); |
2207 | | /* Disabled if not in valid range. */ |
2208 | | ret = 1; |
2209 | | } |
2210 | | else if (curve_id >= 32) { |
2211 | | /* 0 is for invalid and 1-14 aren't used otherwise. */ |
2212 | | ret = (ssl->disabledCurves & (1U << (curve_id - 32))) != 0; |
2213 | | } |
2214 | | else { |
2215 | | ret = (ssl->disabledCurves & (1U << curve_id)) != 0; |
2216 | | } |
2217 | | } |
2218 | | |
2219 | | WOLFSSL_LEAVE("wolfSSL_curve_is_disabled", ret); |
2220 | | return ret; |
2221 | | } |
2222 | | |
2223 | | #if (defined(HAVE_ECC) || \ |
2224 | | defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)) |
2225 | | |
2226 | | /* Set the supported curves list, by name, on the context. |
2227 | | * |
2228 | | * @param [in] ctx SSL/TLS context object. |
2229 | | * @param [in] names Colon-separated list of curve names. |
2230 | | * @return WOLFSSL_SUCCESS on success. |
2231 | | * @return WOLFSSL_FAILURE when ctx or names is NULL or on error. |
2232 | | */ |
2233 | | int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, const char* names) |
2234 | | { |
2235 | | WOLFSSL_ENTER("wolfSSL_CTX_set1_curves_list"); |
2236 | | if (ctx == NULL || names == NULL) { |
2237 | | WOLFSSL_MSG("ctx or names was NULL"); |
2238 | | return WOLFSSL_FAILURE; |
2239 | | } |
2240 | | return set_curves_list(NULL, ctx, names, 1); |
2241 | | } |
2242 | | |
2243 | | /* Set the supported curves list, by name, on the object. |
2244 | | * |
2245 | | * @param [in] ssl SSL/TLS object. |
2246 | | * @param [in] names Colon-separated list of curve names. |
2247 | | * @return WOLFSSL_SUCCESS on success. |
2248 | | * @return WOLFSSL_FAILURE when ssl or names is NULL or on error. |
2249 | | */ |
2250 | | int wolfSSL_set1_curves_list(WOLFSSL* ssl, const char* names) |
2251 | | { |
2252 | | WOLFSSL_ENTER("wolfSSL_set1_curves_list"); |
2253 | | if (ssl == NULL || names == NULL) { |
2254 | | WOLFSSL_MSG("ssl or names was NULL"); |
2255 | | return WOLFSSL_FAILURE; |
2256 | | } |
2257 | | return set_curves_list(ssl, NULL, names, 1); |
2258 | | } |
2259 | | |
2260 | | #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ |
2261 | | #endif /* OPENSSL_EXTRA || HAVE_CURL */ |
2262 | | |
2263 | | #ifdef OPENSSL_EXTRA |
2264 | | |
2265 | | /* Set the ALPN protocol list, in wire format, on the context. |
2266 | | * |
2267 | | * @param [in] ctx SSL/TLS context object. |
2268 | | * @param [in] p ALPN protocol list in wire format (length-prefixed). |
2269 | | * @param [in] p_len Length of the protocol list in bytes. |
2270 | | * @return WOLFSSL_SUCCESS (or 0 with WOLFSSL_ERROR_CODE_OPENSSL) on success. |
2271 | | * @return BAD_FUNC_ARG when ctx or p is NULL. |
2272 | | * @return WOLFSSL_FAILURE (or 1 with WOLFSSL_ERROR_CODE_OPENSSL) on error. |
2273 | | */ |
2274 | | int wolfSSL_CTX_set_alpn_protos(WOLFSSL_CTX *ctx, const unsigned char *p, |
2275 | | unsigned int p_len) |
2276 | | { |
2277 | | WOLFSSL_ENTER("wolfSSL_CTX_set_alpn_protos"); |
2278 | | if (ctx == NULL || p == NULL) |
2279 | | return BAD_FUNC_ARG; |
2280 | | if (ctx->alpn_cli_protos != NULL) { |
2281 | | XFREE((void*)ctx->alpn_cli_protos, ctx->heap, DYNAMIC_TYPE_OPENSSL); |
2282 | | } |
2283 | | |
2284 | | ctx->alpn_cli_protos = (const unsigned char*)XMALLOC(p_len, |
2285 | | ctx->heap, DYNAMIC_TYPE_OPENSSL); |
2286 | | if (ctx->alpn_cli_protos == NULL) { |
2287 | | #if defined(WOLFSSL_ERROR_CODE_OPENSSL) |
2288 | | /* 0 on success in OpenSSL, non-0 on failure in OpenSSL |
2289 | | * the function reverses the return value convention. |
2290 | | */ |
2291 | | return 1; |
2292 | | #else |
2293 | | return WOLFSSL_FAILURE; |
2294 | | #endif |
2295 | | } |
2296 | | XMEMCPY((void*)ctx->alpn_cli_protos, p, p_len); |
2297 | | ctx->alpn_cli_protos_len = p_len; |
2298 | | |
2299 | | #if defined(WOLFSSL_ERROR_CODE_OPENSSL) |
2300 | | /* 0 on success in OpenSSL, non-0 on failure in OpenSSL |
2301 | | * the function reverses the return value convention. |
2302 | | */ |
2303 | | return 0; |
2304 | | #else |
2305 | | return WOLFSSL_SUCCESS; |
2306 | | #endif |
2307 | | } |
2308 | | |
2309 | | |
2310 | | #ifdef HAVE_ALPN |
2311 | | #ifndef NO_BIO |
2312 | | /* Convert a wire-format ALPN protocol list into a comma-separated string. |
2313 | | * |
2314 | | * The wire format is a sequence of entries, each a length byte followed by |
2315 | | * that many protocol-name bytes. |
2316 | | * |
2317 | | * @param [in] p ALPN protocol list in wire format. |
2318 | | * @param [in] p_len Length of the protocol list in bytes. |
2319 | | * @param [out] pt Buffer to hold the comma-separated list. Must hold at |
2320 | | * least p_len bytes. |
2321 | | * @param [out] ptLen Length of the comma-separated list written. |
2322 | | * @return 1 on success. |
2323 | | * @return 0 when the wire format is invalid. |
2324 | | */ |
2325 | | static int wolfssl_alpn_protos_to_list(const unsigned char* p, |
2326 | | unsigned int p_len, char* pt, unsigned int* ptLen) |
2327 | | { |
2328 | | unsigned int idx = 0; |
2329 | | unsigned int ptIdx = 0; |
2330 | | unsigned int sz; |
2331 | | int ret = 1; |
2332 | | |
2333 | | /* Convert into a comma separated list. */ |
2334 | | while (idx < p_len - 1) { |
2335 | | unsigned int i; |
2336 | | |
2337 | | sz = p[idx++]; |
2338 | | if (idx + sz > p_len) { |
2339 | | WOLFSSL_MSG("Bad list format"); |
2340 | | ret = 0; |
2341 | | break; |
2342 | | } |
2343 | | if (sz > 0) { |
2344 | | for (i = 0; i < sz; i++) { |
2345 | | pt[ptIdx++] = p[idx++]; |
2346 | | } |
2347 | | if (idx < p_len - 1) { |
2348 | | pt[ptIdx++] = ','; |
2349 | | } |
2350 | | } |
2351 | | } |
2352 | | |
2353 | | if (ret == 1) { |
2354 | | *ptLen = ptIdx; |
2355 | | } |
2356 | | |
2357 | | return ret; |
2358 | | } |
2359 | | |
2360 | | /* Set the ALPN protocol list, in wire format, on the object. |
2361 | | * |
2362 | | * The list is length-prefixed, e.g. |
2363 | | * unsigned char p[] = { 8, 'h','t','t','p','/','1','.','1' }; |
2364 | | * |
2365 | | * @param [in] ssl SSL/TLS object. |
2366 | | * @param [in] p ALPN protocol list in wire format (length-prefixed). |
2367 | | * @param [in] p_len Length of the protocol list in bytes. |
2368 | | * @return WOLFSSL_SUCCESS (or 0 with WOLFSSL_ERROR_CODE_OPENSSL) on success. |
2369 | | * @return WOLFSSL_FAILURE (or 1 with WOLFSSL_ERROR_CODE_OPENSSL) on error. |
2370 | | */ |
2371 | | int wolfSSL_set_alpn_protos(WOLFSSL* ssl, |
2372 | | const unsigned char* p, unsigned int p_len) |
2373 | | { |
2374 | | char* pt = NULL; |
2375 | | unsigned int ptIdx = 0; |
2376 | | /* RFC 7301: a server that does not select any of the client's offered |
2377 | | * protocols MUST send no_application_protocol. Match that contract on |
2378 | | * the OpenSSL-compat surface rather than silently continuing. */ |
2379 | | int alpn_opt = WOLFSSL_ALPN_FAILED_ON_MISMATCH; |
2380 | | #if defined(WOLFSSL_ERROR_CODE_OPENSSL) |
2381 | | int ret = 1; |
2382 | | #else |
2383 | | int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE); |
2384 | | #endif |
2385 | | |
2386 | | WOLFSSL_ENTER("wolfSSL_set_alpn_protos"); |
2387 | | |
2388 | | if ((ssl != NULL) && (p_len > 1) && (p != NULL)) { |
2389 | | /* Replacing leading number with trailing ',' and adding '\0'. */ |
2390 | | pt = (char*)XMALLOC(p_len + 1, ssl->heap, DYNAMIC_TYPE_OPENSSL); |
2391 | | if (pt != NULL) { |
2392 | | if (wolfssl_alpn_protos_to_list(p, p_len, pt, &ptIdx)) { |
2393 | | pt[ptIdx++] = '\0'; |
2394 | | |
2395 | | /* Clear out all currently set ALPN extensions. */ |
2396 | | TLSX_Remove(&ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL, |
2397 | | ssl->heap); |
2398 | | |
2399 | | if (wolfSSL_UseALPN(ssl, pt, ptIdx, (byte)alpn_opt) == |
2400 | | WOLFSSL_SUCCESS) { |
2401 | | #if defined(WOLFSSL_ERROR_CODE_OPENSSL) |
2402 | | ret = 0; |
2403 | | #else |
2404 | | ret = WOLFSSL_SUCCESS; |
2405 | | #endif |
2406 | | } |
2407 | | } |
2408 | | |
2409 | | XFREE(pt, ssl->heap, DYNAMIC_TYPE_OPENSSL); |
2410 | | } |
2411 | | } |
2412 | | |
2413 | | return ret; |
2414 | | } |
2415 | | #endif /* !NO_BIO */ |
2416 | | #endif /* HAVE_ALPN */ |
2417 | | |
2418 | | #endif /* OPENSSL_EXTRA */ |
2419 | | |
2420 | | #endif /* !WOLFCRYPT_ONLY */ |
2421 | | |
2422 | | #endif /* !WOLFSSL_SSL_API_EXT_INCLUDED */ |