/src/wolfssl-fastmath/src/ssl_api_cert.c
Line | Count | Source |
1 | | /* ssl_api_cert.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_CERT_INCLUDED) |
25 | | #ifndef WOLFSSL_IGNORE_FILE_WARN |
26 | | #warning ssl_api_cert.c is not compiled separately from ssl.c |
27 | | #endif |
28 | | #else |
29 | | |
30 | | #ifndef NO_CERTS |
31 | | |
32 | | /* Set whether mutual authentication is required for connections. |
33 | | * Server side only. |
34 | | * |
35 | | * @param [in] ctx The SSL/TLS CTX object. |
36 | | * @param [in] req 1 to indicate required and 0 when not. |
37 | | * @return 0 on success. |
38 | | * @return BAD_FUNC_ARG when ctx is NULL. |
39 | | * @return SIDE_ERROR when not a server. |
40 | | */ |
41 | | int wolfSSL_CTX_mutual_auth(WOLFSSL_CTX* ctx, int req) |
42 | 0 | { |
43 | 0 | if (ctx == NULL) |
44 | 0 | return BAD_FUNC_ARG; |
45 | | /* Mutual authentication is a server-side only setting. */ |
46 | 0 | if (ctx->method->side != WOLFSSL_SERVER_END) |
47 | 0 | return SIDE_ERROR; |
48 | | |
49 | 0 | ctx->mutualAuth = (byte)req; |
50 | | /* A certificate has to be asked for to be required. */ |
51 | 0 | if (req) { |
52 | 0 | ctx->verifyNone = 0; |
53 | 0 | ctx->verifyPeer = 1; |
54 | 0 | } |
55 | |
|
56 | 0 | return 0; |
57 | 0 | } |
58 | | |
59 | | /* Set whether mutual authentication is required for the connection. |
60 | | * Server side only. |
61 | | * |
62 | | * @param [in, out] ssl SSL/TLS object. |
63 | | * @param [in] req 1 to indicate required and 0 when not. |
64 | | * @return 0 on success. |
65 | | * @return BAD_FUNC_ARG when ssl is NULL. |
66 | | * @return SIDE_ERROR when not a server |
67 | | */ |
68 | | int wolfSSL_mutual_auth(WOLFSSL* ssl, int req) |
69 | 0 | { |
70 | 0 | if (ssl == NULL) |
71 | 0 | return BAD_FUNC_ARG; |
72 | | /* Mutual authentication is a server-side only setting. */ |
73 | 0 | if (ssl->options.side != WOLFSSL_SERVER_END) |
74 | 0 | return SIDE_ERROR; |
75 | | |
76 | 0 | ssl->options.mutualAuth = (word16)req; |
77 | | /* A certificate has to be asked for to be required. */ |
78 | 0 | if (req) { |
79 | 0 | ssl->options.verifyNone = 0; |
80 | 0 | ssl->options.verifyPeer = 1; |
81 | 0 | } |
82 | |
|
83 | 0 | return 0; |
84 | 0 | } |
85 | | |
86 | | /* Get the certificate manager from the WOLFSSL_CTX. |
87 | | * |
88 | | * @param [in] ctx SSL/TLS CTX object. |
89 | | * @return Certificate manager object on success. |
90 | | * @return NULL when ctx is NULL. |
91 | | */ |
92 | | WOLFSSL_CERT_MANAGER* wolfSSL_CTX_GetCertManager(WOLFSSL_CTX* ctx) |
93 | 0 | { |
94 | 0 | WOLFSSL_CERT_MANAGER* cm = NULL; |
95 | | |
96 | | /* The certificate manager is owned by the context. */ |
97 | 0 | if (ctx != NULL) |
98 | 0 | cm = ctx->cm; |
99 | |
|
100 | 0 | return cm; |
101 | 0 | } |
102 | | |
103 | | /* Sets the max chain depth when verifying a certificate chain. |
104 | | * |
105 | | * Default depth is set to MAX_CHAIN_DEPTH. |
106 | | * |
107 | | * @param [in] ctx WOLFSSL_CTX structure to set depth in |
108 | | * @param [in] depth max depth |
109 | | */ |
110 | | void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx, int depth) |
111 | 0 | { |
112 | 0 | WOLFSSL_ENTER("wolfSSL_CTX_set_verify_depth"); |
113 | | |
114 | | /* Reject out-of-range depths; valid range is 0 to MAX_CHAIN_DEPTH. */ |
115 | 0 | if ((ctx == NULL) || (depth < 0) || (depth > MAX_CHAIN_DEPTH)) { |
116 | 0 | WOLFSSL_MSG("Bad depth argument, too large or less than 0"); |
117 | 0 | } |
118 | 0 | else { |
119 | 0 | ctx->verifyDepth = (byte)depth; |
120 | 0 | } |
121 | 0 | } |
122 | | |
123 | | |
124 | | /* Get certificate chaining depth of SSL/TLS context object |
125 | | * |
126 | | * @param [in] ctx SSL/TLS context object. |
127 | | * @return Verification depth on success. |
128 | | * @return BAD_FUNC_ARG when ctx is NULL. |
129 | | */ |
130 | | long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx) |
131 | 0 | { |
132 | 0 | long ret; |
133 | |
|
134 | 0 | if (ctx == NULL) { |
135 | 0 | ret = BAD_FUNC_ARG; |
136 | 0 | } |
137 | 0 | else { |
138 | | /* A configurable depth is only tracked with the OpenSSL extra APIs; |
139 | | * otherwise the fixed maximum chain depth applies. */ |
140 | 0 | #ifndef OPENSSL_EXTRA |
141 | 0 | ret = MAX_CHAIN_DEPTH; |
142 | | #else |
143 | | ret = ctx->verifyDepth; |
144 | | #endif |
145 | 0 | } |
146 | |
|
147 | 0 | return ret; |
148 | 0 | } |
149 | | |
150 | | /* Get certificate chaining depth of SSL/TLS object |
151 | | * |
152 | | * @param [in] ssl SSL/TLS object. |
153 | | * @return Verification depth on success. |
154 | | * @return BAD_FUNC_ARG when ssl is NULL. |
155 | | */ |
156 | | long wolfSSL_get_verify_depth(WOLFSSL* ssl) |
157 | 0 | { |
158 | 0 | long ret; |
159 | |
|
160 | 0 | if (ssl == NULL) { |
161 | 0 | ret = BAD_FUNC_ARG; |
162 | 0 | } |
163 | 0 | else { |
164 | | /* A configurable depth is only tracked with the OpenSSL extra APIs; |
165 | | * otherwise the fixed maximum chain depth applies. */ |
166 | 0 | #ifndef OPENSSL_EXTRA |
167 | 0 | ret = MAX_CHAIN_DEPTH; |
168 | | #else |
169 | | ret = ssl->options.verifyDepth; |
170 | | #endif |
171 | 0 | } |
172 | |
|
173 | 0 | return ret; |
174 | 0 | } |
175 | | |
176 | | #if defined(HAVE_RPK) |
177 | | /* TODO: Change this to use a bitfield. */ |
178 | | |
179 | | /* Confirm that all the byte data in the buffer is unique. |
180 | | * |
181 | | * @param [in] buf Buffer to check. |
182 | | * @param [in] len Length of buffer in bytes. |
183 | | * @return 1 if all the byte data in the buffer is unique. |
184 | | * @return 0 otherwise. |
185 | | */ |
186 | | static int isArrayUnique(const char* buf, size_t len) |
187 | | { |
188 | | size_t i; |
189 | | /* Check the array is unique. */ |
190 | | for (i = 0; i < len - 1; ++i) { |
191 | | size_t j; |
192 | | for (j = i + 1; j < len; ++j) { |
193 | | if (buf[i] == buf[j]) { |
194 | | return 0; |
195 | | } |
196 | | } |
197 | | } |
198 | | return 1; |
199 | | } |
200 | | /* Set user preference for the {client,server}_cert_type extension. |
201 | | * |
202 | | * Takes byte array containing cert types the caller can provide to its peer. |
203 | | * Cert types are in preferred order in the array. |
204 | | * |
205 | | * @param [in] cfg Raw Public Key configuration. |
206 | | * @param [in] client Indicates whether this is the client side. |
207 | | * @param [in] buf List of certificate types. |
208 | | * @param [in] len Length of certificate types. |
209 | | * @return 1 on success. |
210 | | * @return BAD_FUNC_ARG when cfg is NULL. |
211 | | * @return BAD_FUNC_ARG when len is too long. |
212 | | * @return BAD_FUNC_ARG when buffer values are not unique. |
213 | | * @return BAD_FUNC_ARG when buffer contains unrecognized certificate type. |
214 | | */ |
215 | | static int set_cert_type(RpkConfig* cfg, int client, const char* buf, |
216 | | int len) |
217 | | { |
218 | | int i; |
219 | | byte* certTypeCnt; |
220 | | byte* certTypes; |
221 | | |
222 | | /* Validate parameters. */ |
223 | | if ((cfg == NULL) || (len > (client ? MAX_CLIENT_CERT_TYPE_CNT : |
224 | | MAX_SERVER_CERT_TYPE_CNT))) { |
225 | | return BAD_FUNC_ARG; |
226 | | } |
227 | | |
228 | | /* Get preferred certificate types for side. */ |
229 | | if (client) { |
230 | | certTypeCnt = &cfg->preferred_ClientCertTypeCnt; |
231 | | certTypes = cfg->preferred_ClientCertTypes; |
232 | | } |
233 | | else { |
234 | | certTypeCnt = &cfg->preferred_ServerCertTypeCnt; |
235 | | certTypes = cfg->preferred_ServerCertTypes; |
236 | | } |
237 | | /* If no buffer or empty buffer passed in, set the defaults. */ |
238 | | if ((buf == NULL) || (len == 0)) { |
239 | | *certTypeCnt = 1; |
240 | | for (i = 0; i < 2; i++) { |
241 | | certTypes[i] = WOLFSSL_CERT_TYPE_X509; |
242 | | } |
243 | | return 1; |
244 | | } |
245 | | |
246 | | /* Check that the certificate types set are unique. */ |
247 | | if (!isArrayUnique(buf, (size_t)len)) |
248 | | return BAD_FUNC_ARG; |
249 | | |
250 | | /* Check that the certificate types being set are known and then set. */ |
251 | | for (i = 0; i < len; i++) { |
252 | | if ((buf[i] != WOLFSSL_CERT_TYPE_RPK) && |
253 | | (buf[i] != WOLFSSL_CERT_TYPE_X509)) { |
254 | | return BAD_FUNC_ARG; |
255 | | } |
256 | | certTypes[i] = (byte)buf[i]; |
257 | | } |
258 | | *certTypeCnt = len; |
259 | | |
260 | | return 1; |
261 | | } |
262 | | /* Set the client certificate types against the SSL/TLS context. |
263 | | * |
264 | | * @param [in] ctx SSL/TLS context object. |
265 | | * @param [in] buf List of certificate types. |
266 | | * @param [in] len Length of certificate types. |
267 | | * @return 1 on success. |
268 | | * @return BAD_FUNC_ARG when ctx is NULL. |
269 | | * @return BAD_FUNC_ARG when len is too long. |
270 | | * @return BAD_FUNC_ARG when buffer values are not unique. |
271 | | * @return BAD_FUNC_ARG when buffer contains unrecognized certificate type. |
272 | | */ |
273 | | int wolfSSL_CTX_set_client_cert_type(WOLFSSL_CTX* ctx, const char* buf, int len) |
274 | | { |
275 | | int ret; |
276 | | |
277 | | if (ctx == NULL) { |
278 | | ret = BAD_FUNC_ARG; |
279 | | } |
280 | | else { |
281 | | /* A side value of 1 records these as the client certificate types. */ |
282 | | ret = set_cert_type(&ctx->rpkConfig, 1, buf, len); |
283 | | } |
284 | | |
285 | | return ret; |
286 | | } |
287 | | /* Set the server certificate types against the SSL/TLS context. |
288 | | * |
289 | | * @param [in] ctx SSL/TLS context object. |
290 | | * @param [in] buf List of certificate types. |
291 | | * @param [in] len Length of certificate types. |
292 | | * @return 1 on success. |
293 | | * @return BAD_FUNC_ARG when ctx is NULL. |
294 | | * @return BAD_FUNC_ARG when len is too long. |
295 | | * @return BAD_FUNC_ARG when buffer values are not unique. |
296 | | * @return BAD_FUNC_ARG when buffer contains unrecognized certificate type. |
297 | | */ |
298 | | int wolfSSL_CTX_set_server_cert_type(WOLFSSL_CTX* ctx, const char* buf, int len) |
299 | | { |
300 | | int ret; |
301 | | |
302 | | if (ctx == NULL) { |
303 | | ret = BAD_FUNC_ARG; |
304 | | } |
305 | | else { |
306 | | /* A side value of 0 records these as the server certificate types. */ |
307 | | ret = set_cert_type(&ctx->rpkConfig, 0, buf, len); |
308 | | } |
309 | | |
310 | | return ret; |
311 | | } |
312 | | /* Set the client certificate types against the SSL/TLS object. |
313 | | * |
314 | | * @param [in] ssl SSL/TLS object. |
315 | | * @param [in] buf List of certificate types. |
316 | | * @param [in] len Length of certificate types. |
317 | | * @return 1 on success. |
318 | | * @return BAD_FUNC_ARG when ssl is NULL. |
319 | | * @return BAD_FUNC_ARG when len is too long. |
320 | | * @return BAD_FUNC_ARG when buffer values are not unique. |
321 | | * @return BAD_FUNC_ARG when buffer contains unrecognized certificate type. |
322 | | */ |
323 | | int wolfSSL_set_client_cert_type(WOLFSSL* ssl, const char* buf, int len) |
324 | | { |
325 | | int ret; |
326 | | |
327 | | if (ssl == NULL) { |
328 | | ret = BAD_FUNC_ARG; |
329 | | } |
330 | | else { |
331 | | /* A side value of 1 records these as the client certificate types. */ |
332 | | ret = set_cert_type(&ssl->options.rpkConfig, 1, buf, len); |
333 | | } |
334 | | |
335 | | return ret; |
336 | | } |
337 | | /* Set the server certificate types against the SSL/TLS object. |
338 | | * |
339 | | * @param [in] ssl SSL/TLS object. |
340 | | * @param [in] buf List of certificate types. |
341 | | * @param [in] len Length of certificate types. |
342 | | * @return 1 on success. |
343 | | * @return BAD_FUNC_ARG when ssl is NULL. |
344 | | * @return BAD_FUNC_ARG when len is too long. |
345 | | * @return BAD_FUNC_ARG when buffer values are not unique. |
346 | | * @return BAD_FUNC_ARG when buffer contains unrecognized certificate type. |
347 | | */ |
348 | | int wolfSSL_set_server_cert_type(WOLFSSL* ssl, const char* buf, int len) |
349 | | { |
350 | | int ret; |
351 | | |
352 | | if (ssl == NULL) { |
353 | | ret = BAD_FUNC_ARG; |
354 | | } |
355 | | else { |
356 | | /* A side value of 0 records these as the server certificate types. */ |
357 | | ret = set_cert_type(&ssl->options.rpkConfig, 0, buf, len); |
358 | | } |
359 | | |
360 | | return ret; |
361 | | } |
362 | | |
363 | | /* Get negotiated client certificate type value. |
364 | | * |
365 | | * WOLFSSL_CERT_TYPE_UNKNOWN returned when no negotiation has been performed. |
366 | | * |
367 | | * @param [in] ssl SSL/TLS object. |
368 | | * @param [out] tp Certificate type. One of: |
369 | | * -1: WOLFSSL_CERT_TYPE_UNKNOWN |
370 | | * 0: WOLFSSL_CERT_TYPE_X509 |
371 | | * 2: WOLFSSL_CERT_TYPE_RPK |
372 | | * @return 1 on success. |
373 | | * @return BAD_FUNC_ARG when ssl or tp is NULL. |
374 | | */ |
375 | | int wolfSSL_get_negotiated_client_cert_type(WOLFSSL* ssl, int* tp) |
376 | | { |
377 | | int ret = 1; |
378 | | |
379 | | /* Validate parameters. */ |
380 | | if ((ssl == NULL) || (tp == NULL)) { |
381 | | ret = BAD_FUNC_ARG; |
382 | | } |
383 | | /* Check side. */ |
384 | | else if (ssl->options.side == WOLFSSL_CLIENT_END) { |
385 | | /* Check certificate type negotiated. */ |
386 | | if (ssl->options.rpkState.received_ClientCertTypeCnt == 1) { |
387 | | *tp = ssl->options.rpkState.received_ClientCertTypes[0]; |
388 | | } |
389 | | else { |
390 | | *tp = WOLFSSL_CERT_TYPE_UNKNOWN; |
391 | | } |
392 | | } |
393 | | /* Check certificate type negotiated. */ |
394 | | else if (ssl->options.rpkState.sending_ClientCertTypeCnt == 1) { |
395 | | *tp = ssl->options.rpkState.sending_ClientCertTypes[0]; |
396 | | } |
397 | | else { |
398 | | *tp = WOLFSSL_CERT_TYPE_UNKNOWN; |
399 | | } |
400 | | |
401 | | return ret; |
402 | | } |
403 | | |
404 | | /* Get negotiated server certificate type value. |
405 | | * |
406 | | * WOLFSSL_CERT_TYPE_UNKNOWN returned when no negotiation has been performed. |
407 | | * |
408 | | * @param [in] ssl SSL/TLS object. |
409 | | * @param [out] tp Certificate type. One of: |
410 | | * -1: WOLFSSL_CERT_TYPE_UNKNOWN |
411 | | * 0: WOLFSSL_CERT_TYPE_X509 |
412 | | * 2: WOLFSSL_CERT_TYPE_RPK |
413 | | * @return 1 on success. |
414 | | * @return BAD_FUNC_ARG when ssl or tp is NULL. |
415 | | */ |
416 | | int wolfSSL_get_negotiated_server_cert_type(WOLFSSL* ssl, int* tp) |
417 | | { |
418 | | int ret = 1; |
419 | | |
420 | | /* Validate parameters. */ |
421 | | if ((ssl == NULL) || (tp == NULL)) { |
422 | | ret = BAD_FUNC_ARG; |
423 | | } |
424 | | /* Check side. */ |
425 | | else if (ssl->options.side == WOLFSSL_CLIENT_END) { |
426 | | /* Check certificate type negotiated. */ |
427 | | if (ssl->options.rpkState.received_ServerCertTypeCnt == 1) { |
428 | | *tp = ssl->options.rpkState.received_ServerCertTypes[0]; |
429 | | } |
430 | | else { |
431 | | *tp = WOLFSSL_CERT_TYPE_UNKNOWN; |
432 | | } |
433 | | } |
434 | | /* Check certificate type negotiated. */ |
435 | | else if (ssl->options.rpkState.sending_ServerCertTypeCnt == 1) { |
436 | | *tp = ssl->options.rpkState.sending_ServerCertTypes[0]; |
437 | | } |
438 | | else { |
439 | | *tp = WOLFSSL_CERT_TYPE_UNKNOWN; |
440 | | } |
441 | | return ret; |
442 | | } |
443 | | |
444 | | #ifndef NO_SHA256 |
445 | | /* Store the SHA-256 digest of a DER SubjectPublicKeyInfo as an expected Raw |
446 | | * Public Key (RFC 7250) for out-of-band trust. |
447 | | * |
448 | | * @param [in] cfg RPK configuration to add the pin to. |
449 | | * @param [in] spki DER-encoded SubjectPublicKeyInfo. |
450 | | * @param [in] spkiSz Length of spki in bytes. |
451 | | * @return 0 on success. |
452 | | * @return BAD_FUNC_ARG when cfg or spki is NULL, or spkiSz is 0. |
453 | | * @return BUFFER_E when no more pins can be stored. |
454 | | * @return negative hashing error on failure. |
455 | | */ |
456 | | static int rpk_add_expected(RpkConfig* cfg, const unsigned char* spki, |
457 | | unsigned int spkiSz) |
458 | | { |
459 | | int ret; |
460 | | |
461 | | if ((cfg == NULL) || (spki == NULL) || (spkiSz == 0)) { |
462 | | return BAD_FUNC_ARG; |
463 | | } |
464 | | if (cfg->expectedRpkCnt >= WOLFSSL_MAX_RPK_PINS) { |
465 | | return BUFFER_E; |
466 | | } |
467 | | |
468 | | ret = wc_Sha256Hash(spki, spkiSz, cfg->expectedRpk[cfg->expectedRpkCnt]); |
469 | | if (ret == 0) { |
470 | | cfg->expectedRpkCnt++; |
471 | | } |
472 | | return ret; |
473 | | } |
474 | | |
475 | | /* Pin an expected peer Raw Public Key on the SSL/TLS CTX object. |
476 | | * |
477 | | * @param [in] ctx SSL/TLS CTX object. |
478 | | * @param [in] spki DER-encoded SubjectPublicKeyInfo the peer will present. |
479 | | * @param [in] spkiSz Length of spki in bytes. |
480 | | * @return WOLFSSL_SUCCESS on success. |
481 | | * @return BAD_FUNC_ARG when ctx or spki is NULL, or spkiSz is 0. |
482 | | * @return BUFFER_E when the pin table is full (WOLFSSL_MAX_RPK_PINS reached). |
483 | | * @return Other negative error code on hashing failure. |
484 | | */ |
485 | | int wolfSSL_CTX_set_expected_rpk(WOLFSSL_CTX* ctx, const unsigned char* spki, |
486 | | unsigned int spkiSz) |
487 | | { |
488 | | int ret; |
489 | | |
490 | | if (ctx == NULL) { |
491 | | return BAD_FUNC_ARG; |
492 | | } |
493 | | ret = rpk_add_expected(&ctx->rpkConfig, spki, spkiSz); |
494 | | return (ret == 0) ? WOLFSSL_SUCCESS : ret; |
495 | | } |
496 | | |
497 | | /* Pin an expected peer Raw Public Key on the SSL/TLS object. |
498 | | * |
499 | | * @param [in] ssl SSL/TLS object. |
500 | | * @param [in] spki DER-encoded SubjectPublicKeyInfo the peer will present. |
501 | | * @param [in] spkiSz Length of spki in bytes. |
502 | | * @return WOLFSSL_SUCCESS on success. |
503 | | * @return BAD_FUNC_ARG when ssl or spki is NULL, or spkiSz is 0. |
504 | | * @return BUFFER_E when the pin table is full (WOLFSSL_MAX_RPK_PINS reached). |
505 | | * @return Other negative error code on hashing failure. |
506 | | */ |
507 | | int wolfSSL_set_expected_rpk(WOLFSSL* ssl, const unsigned char* spki, |
508 | | unsigned int spkiSz) |
509 | | { |
510 | | int ret; |
511 | | |
512 | | if (ssl == NULL) { |
513 | | return BAD_FUNC_ARG; |
514 | | } |
515 | | ret = rpk_add_expected(&ssl->options.rpkConfig, spki, spkiSz); |
516 | | return (ret == 0) ? WOLFSSL_SUCCESS : ret; |
517 | | } |
518 | | |
519 | | /* Remove all pinned expected peer Raw Public Keys from the SSL/TLS CTX object, |
520 | | * so the table can be repopulated (e.g. across a peer key rotation). |
521 | | * |
522 | | * @param [in] ctx SSL/TLS CTX object. |
523 | | * @return WOLFSSL_SUCCESS on success. |
524 | | * @return BAD_FUNC_ARG when ctx is NULL. |
525 | | */ |
526 | | int wolfSSL_CTX_clear_expected_rpk(WOLFSSL_CTX* ctx) |
527 | | { |
528 | | if (ctx == NULL) { |
529 | | return BAD_FUNC_ARG; |
530 | | } |
531 | | ctx->rpkConfig.expectedRpkCnt = 0; |
532 | | return WOLFSSL_SUCCESS; |
533 | | } |
534 | | |
535 | | /* Remove all pinned expected peer Raw Public Keys from the SSL/TLS object, so |
536 | | * the table can be repopulated (e.g. across a peer key rotation). |
537 | | * |
538 | | * @param [in, out] ssl SSL/TLS object. |
539 | | * @return WOLFSSL_SUCCESS on success. |
540 | | * @return BAD_FUNC_ARG when ssl is NULL. |
541 | | */ |
542 | | int wolfSSL_clear_expected_rpk(WOLFSSL* ssl) |
543 | | { |
544 | | if (ssl == NULL) { |
545 | | return BAD_FUNC_ARG; |
546 | | } |
547 | | ssl->options.rpkConfig.expectedRpkCnt = 0; |
548 | | return WOLFSSL_SUCCESS; |
549 | | } |
550 | | #endif /* !NO_SHA256 */ |
551 | | #endif /* HAVE_RPK */ |
552 | | |
553 | | /* Certificate verification options. */ |
554 | | typedef struct { |
555 | | /* Verify the peer certificate. */ |
556 | | byte verifyPeer:1; |
557 | | /* No peer certificate verification. */ |
558 | | byte verifyNone:1; |
559 | | /* Fail when no peer certificate seen. */ |
560 | | byte failNoCert:1; |
561 | | /* Fail when no peer certificate except when PSK handshake performed. */ |
562 | | byte failNoCertxPSK:1; |
563 | | #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) |
564 | | /* Verify peer certificate post handshake. */ |
565 | | byte verifyPostHandshake:1; |
566 | | #endif |
567 | | } SetVerifyOptions; |
568 | | |
569 | | /* Convert the mode flags into certificate verification options. |
570 | | * |
571 | | * WOLFSSL_VERIFY_CLIENT_ONCE is accepted and deliberately ignored - it has no |
572 | | * corresponding option here, is not stored anywhere, and therefore cannot be |
573 | | * read back by wolfSSL_[CTX_]get_verify_mode(). See the note on the enumerator |
574 | | * in wolfssl/ssl.h. |
575 | | * |
576 | | * Note that WOLFSSL_VERIFY_NONE is matched by equality, not as a bit: a mode |
577 | | * of (WOLFSSL_VERIFY_NONE | WOLFSSL_VERIFY_PEER) verifies the peer. |
578 | | * |
579 | | * @param [in] mode Certificate verification mode flags. |
580 | | * @return Certificate verification options. |
581 | | */ |
582 | | static SetVerifyOptions ModeToVerifyOptions(int mode) |
583 | | { |
584 | | SetVerifyOptions opts; |
585 | | |
586 | | /* Set the options to the default - none set. */ |
587 | | XMEMSET(&opts, 0, sizeof(SetVerifyOptions)); |
588 | | |
589 | | /* When the mode is not default - set the options. */ |
590 | | if (mode != WOLFSSL_VERIFY_DEFAULT) { |
591 | | opts.verifyNone = (mode == WOLFSSL_VERIFY_NONE); |
592 | | /* When not no verification, set the chosen options. */ |
593 | | if (!opts.verifyNone) { |
594 | | opts.verifyPeer = |
595 | | (mode & WOLFSSL_VERIFY_PEER) != 0; |
596 | | opts.failNoCertxPSK = |
597 | | (mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) != 0; |
598 | | opts.failNoCert = |
599 | | (mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT) != 0; |
600 | | /* Both only fail a certificate that was asked for, so they imply |
601 | | * asking. */ |
602 | | if (opts.failNoCert || opts.failNoCertxPSK) { |
603 | | opts.verifyPeer = 1; |
604 | | } |
605 | | #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) |
606 | | opts.verifyPostHandshake = |
607 | | (mode & WOLFSSL_VERIFY_POST_HANDSHAKE) != 0; |
608 | | #endif |
609 | | } |
610 | | } |
611 | | |
612 | | return opts; |
613 | | } |
614 | | |
615 | | /* Set the verification options against the SSL/TLS context. |
616 | | * |
617 | | * @param [in] ctx SSL/TLS context object. |
618 | | * @param [in] mode Verification mode options. |
619 | | * @param [in] verify_callback Verification callback. |
620 | | */ |
621 | | WOLFSSL_ABI |
622 | | void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode, |
623 | | VerifyCallback verify_callback) |
624 | 28 | { |
625 | 28 | WOLFSSL_ENTER("wolfSSL_CTX_set_verify"); |
626 | | |
627 | | /* Ensure we have an SSL/TLS context to work with. */ |
628 | 28 | if (ctx != NULL) { |
629 | 28 | SetVerifyOptions opts = ModeToVerifyOptions(mode); |
630 | | |
631 | | /* Set the bitfield options. */ |
632 | 28 | ctx->verifyNone = opts.verifyNone; |
633 | 28 | ctx->verifyPeer = opts.verifyPeer; |
634 | 28 | ctx->failNoCert = opts.failNoCert; |
635 | 28 | ctx->failNoCertxPSK = opts.failNoCertxPSK; |
636 | | #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) |
637 | | ctx->verifyPostHandshake = opts.verifyPostHandshake; |
638 | | #endif |
639 | | |
640 | | /* Store the user verification callback against the context. */ |
641 | 28 | ctx->verifyCallback = verify_callback; |
642 | 28 | } |
643 | 28 | } |
644 | | |
645 | | #ifdef OPENSSL_ALL |
646 | | /* Set certificate verification callback and context against SSL/TLS context. |
647 | | * |
648 | | * @param [in] ctx SSL/TLS context object. |
649 | | * @param [in] cb Certificate verification callback. |
650 | | * @param [in] arg Context for certification verification callback. |
651 | | */ |
652 | | void wolfSSL_CTX_set_cert_verify_callback(WOLFSSL_CTX* ctx, |
653 | | CertVerifyCallback cb, void* arg) |
654 | | { |
655 | | WOLFSSL_ENTER("wolfSSL_CTX_set_cert_verify_callback"); |
656 | | |
657 | | /* Ensure we have an SSL/TLS context to work with. */ |
658 | | if (ctx != NULL) { |
659 | | ctx->verifyCertCb = cb; |
660 | | ctx->verifyCertCbArg = arg; |
661 | | } |
662 | | } |
663 | | #endif |
664 | | |
665 | | #ifdef WOLFSSL_CHAIN_VERIFY_CB |
666 | | /* Set the callback that replaces peer certificate chain verification for |
667 | | * every SSL/TLS object created from the context. |
668 | | * |
669 | | * Setting a callback turns off all of wolfSSL's own checking of the peer's |
670 | | * certificates. See ChainVerifyCb in ssl.h. |
671 | | * |
672 | | * @param [in, out] ctx SSL/TLS context object. |
673 | | * @param [in] cb Chain verification callback. NULL to clear. |
674 | | * @return WOLFSSL_SUCCESS on success. |
675 | | * @return BAD_FUNC_ARG when ctx is NULL. |
676 | | * @return CHAIN_VERIFY_UNSUPPORTED_E when the context uses DTLS, raw public |
677 | | * keys or OCSP stapling. |
678 | | */ |
679 | | int wolfSSL_CTX_SetChainVerifyCb(WOLFSSL_CTX* ctx, ChainVerifyCb cb) |
680 | | { |
681 | | int ret; |
682 | | |
683 | | WOLFSSL_ENTER("wolfSSL_CTX_SetChainVerifyCb"); |
684 | | |
685 | | if (ctx == NULL) |
686 | | return BAD_FUNC_ARG; |
687 | | |
688 | | if (cb != NULL) { |
689 | | ret = ChainVerifyCbCheckCtx(ctx); |
690 | | if (ret != 0) |
691 | | return ret; |
692 | | } |
693 | | ctx->chainVerifyCb = cb; |
694 | | |
695 | | return WOLFSSL_SUCCESS; |
696 | | } |
697 | | |
698 | | /* Set the callback that replaces peer certificate chain verification for one |
699 | | * SSL/TLS object. Takes precedence over the context's callback. |
700 | | * |
701 | | * @param [in, out] ssl SSL/TLS object. |
702 | | * @param [in] cb Chain verification callback. NULL to fall back to the |
703 | | * context's. |
704 | | * @return WOLFSSL_SUCCESS on success. |
705 | | * @return BAD_FUNC_ARG when ssl is NULL. |
706 | | * @return CHAIN_VERIFY_UNSUPPORTED_E when the object uses DTLS, raw public |
707 | | * keys or OCSP stapling. |
708 | | */ |
709 | | int wolfSSL_SetChainVerifyCb(WOLFSSL* ssl, ChainVerifyCb cb) |
710 | | { |
711 | | int ret; |
712 | | |
713 | | WOLFSSL_ENTER("wolfSSL_SetChainVerifyCb"); |
714 | | |
715 | | if (ssl == NULL) |
716 | | return BAD_FUNC_ARG; |
717 | | |
718 | | if (cb != NULL) { |
719 | | ret = ChainVerifyCbCheckSsl(ssl); |
720 | | if (ret != 0) |
721 | | return ret; |
722 | | } |
723 | | ssl->chainVerifyCb = cb; |
724 | | |
725 | | return WOLFSSL_SUCCESS; |
726 | | } |
727 | | |
728 | | /* Set the user context passed to the chain verification callback for every |
729 | | * SSL/TLS object created from the context. |
730 | | * |
731 | | * @param [in, out] ctx SSL/TLS context object. |
732 | | * @param [in] userCtx User context. |
733 | | */ |
734 | | void wolfSSL_CTX_SetChainVerifyCtx(WOLFSSL_CTX* ctx, void* userCtx) |
735 | | { |
736 | | WOLFSSL_ENTER("wolfSSL_CTX_SetChainVerifyCtx"); |
737 | | |
738 | | if (ctx != NULL) { |
739 | | ctx->chainVerifyCtx = userCtx; |
740 | | } |
741 | | } |
742 | | |
743 | | /* Set the user context passed to the chain verification callback for one |
744 | | * SSL/TLS object. Takes precedence over the context's. |
745 | | * |
746 | | * @param [in, out] ssl SSL/TLS object. |
747 | | * @param [in] ctx User context. NULL to fall back to the context's. |
748 | | */ |
749 | | void wolfSSL_SetChainVerifyCtx(WOLFSSL* ssl, void* ctx) |
750 | | { |
751 | | WOLFSSL_ENTER("wolfSSL_SetChainVerifyCtx"); |
752 | | |
753 | | if (ssl != NULL) { |
754 | | ssl->chainVerifyCtx = ctx; |
755 | | } |
756 | | } |
757 | | |
758 | | /* Get the user context the chain verification callback is called with: the |
759 | | * SSL/TLS object's when set, otherwise the context's. |
760 | | * |
761 | | * @param [in] ssl SSL/TLS object. |
762 | | * @return User context, or NULL when none set or ssl is NULL. |
763 | | */ |
764 | | void* wolfSSL_GetChainVerifyCtx(const WOLFSSL* ssl) |
765 | | { |
766 | | WOLFSSL_ENTER("wolfSSL_GetChainVerifyCtx"); |
767 | | |
768 | | if (ssl != NULL) { |
769 | | if (ssl->chainVerifyCtx != NULL) { |
770 | | return ssl->chainVerifyCtx; |
771 | | } |
772 | | return ssl->ctx->chainVerifyCtx; |
773 | | } |
774 | | |
775 | | return NULL; |
776 | | } |
777 | | #endif /* WOLFSSL_CHAIN_VERIFY_CB */ |
778 | | |
779 | | /* Set the verification options against the SSL/TLS object. |
780 | | * |
781 | | * @param [in, out] ssl SSL/TLS object. |
782 | | * @param [in] mode Verification mode options. |
783 | | * @param [in] verify_callback Verification callback. |
784 | | */ |
785 | | void wolfSSL_set_verify(WOLFSSL* ssl, int mode, VerifyCallback verify_callback) |
786 | 0 | { |
787 | 0 | WOLFSSL_ENTER("wolfSSL_set_verify"); |
788 | | |
789 | | /* Ensure we have an SSL/TLS object to work with. */ |
790 | 0 | if (ssl != NULL) { |
791 | 0 | SetVerifyOptions opts = ModeToVerifyOptions(mode); |
792 | | |
793 | | /* Set the bitfield options. */ |
794 | 0 | ssl->options.verifyNone = opts.verifyNone; |
795 | 0 | ssl->options.verifyPeer = opts.verifyPeer; |
796 | 0 | ssl->options.failNoCert = opts.failNoCert; |
797 | 0 | ssl->options.failNoCertxPSK = opts.failNoCertxPSK; |
798 | | #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) |
799 | | ssl->options.verifyPostHandshake = opts.verifyPostHandshake; |
800 | | #endif |
801 | | |
802 | | /* Store the user verification callback against the object. */ |
803 | 0 | ssl->verifyCallback = verify_callback; |
804 | 0 | } |
805 | 0 | } |
806 | | |
807 | | /* Set the certificate verification result for the SSL/TLS object. |
808 | | * |
809 | | * @param [in, out] ssl SSL/TLS object. |
810 | | * @param [in] v Verification result. |
811 | | */ |
812 | | void wolfSSL_set_verify_result(WOLFSSL *ssl, long v) |
813 | 0 | { |
814 | 0 | WOLFSSL_ENTER("wolfSSL_set_verify_result"); |
815 | | |
816 | | /* Ensure we have an SSL/TLS object to work with. */ |
817 | 0 | if (ssl != NULL) { |
818 | | #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) |
819 | | ssl->peerVerifyRet = (unsigned long)v; |
820 | | #else |
821 | 0 | WOLFSSL_STUB("wolfSSL_set_verify_result"); |
822 | 0 | (void)v; |
823 | 0 | #endif |
824 | 0 | } |
825 | 0 | } |
826 | | |
827 | | /* Store user ctx for verify callback into SSL/TLS context. |
828 | | * |
829 | | * @param [in] ctx SSL/TLS context. |
830 | | * @param [in] userCtx User context for verify callback. |
831 | | */ |
832 | | void wolfSSL_CTX_SetCertCbCtx(WOLFSSL_CTX* ctx, void* userCtx) |
833 | 0 | { |
834 | 0 | WOLFSSL_ENTER("wolfSSL_CTX_SetCertCbCtx"); |
835 | | |
836 | | /* Validate parameters. */ |
837 | 0 | if (ctx != NULL) { |
838 | 0 | ctx->verifyCbCtx = userCtx; |
839 | 0 | } |
840 | 0 | } |
841 | | |
842 | | /* Store user ctx for verify callback into SSL/TLS object. |
843 | | * |
844 | | * @param [in, out] ssl SSL/TLS object. |
845 | | * @param [in] ctx User context for verify callback. |
846 | | */ |
847 | | void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx) |
848 | 0 | { |
849 | 0 | WOLFSSL_ENTER("wolfSSL_SetCertCbCtx"); |
850 | | |
851 | | /* Validate parameters. */ |
852 | 0 | if (ssl != NULL) { |
853 | 0 | ssl->verifyCbCtx = ctx; |
854 | 0 | } |
855 | 0 | } |
856 | | |
857 | | |
858 | | |
859 | | /* Set the callback called when a CA is added to the cache. |
860 | | * |
861 | | * @param [in, out] ctx SSL/TLS context. |
862 | | * @param [in] cb Callback to call. NULL to clear. |
863 | | */ |
864 | | void wolfSSL_CTX_SetCACb(WOLFSSL_CTX* ctx, CallbackCACache cb) |
865 | 0 | { |
866 | | /* Validate parameters. */ |
867 | 0 | if ((ctx != NULL) && (ctx->cm != NULL)) { |
868 | 0 | ctx->cm->caCacheCallback = cb; |
869 | 0 | } |
870 | 0 | } |
871 | | |
872 | | #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_TLS13) && \ |
873 | | defined(WOLFSSL_POST_HANDSHAKE_AUTH) |
874 | | /* For TLS v1.3, send authentication messages after handshake completes. |
875 | | * |
876 | | * @param [in, out] ssl SSL/TLS object. |
877 | | * @return 1 on success. |
878 | | * @return UNSUPPORTED_PROTO_VERSION when not a TLSv1.3 handshake. |
879 | | * @return 0 on other failure. |
880 | | */ |
881 | | int wolfSSL_verify_client_post_handshake(WOLFSSL* ssl) |
882 | | { |
883 | | int ret; |
884 | | |
885 | | /* Do request of certificate. */ |
886 | | ret = wolfSSL_request_certificate(ssl); |
887 | | if (ret != 1) { |
888 | | /* Special logging for wrong protocol version. */ |
889 | | if ((ssl != NULL) && (!IsAtLeastTLSv1_3(ssl->version))) { |
890 | | WOLFSSL_ERROR(UNSUPPORTED_PROTO_VERSION); |
891 | | } |
892 | | else { |
893 | | /* Other errors - return 0. */ |
894 | | WOLFSSL_ERROR(ret); |
895 | | } |
896 | | ret = 0; |
897 | | } |
898 | | |
899 | | return ret; |
900 | | } |
901 | | |
902 | | /* Set whether handshakes from this SSL/TLS context allow auth post handshake. |
903 | | * |
904 | | * @param [in] ctx SSL/TLS context. |
905 | | * @param [in] val Whether to allow post handshake authentication. |
906 | | * @return 1 on success. |
907 | | * @return 0 on failure. |
908 | | */ |
909 | | int wolfSSL_CTX_set_post_handshake_auth(WOLFSSL_CTX* ctx, int val) |
910 | | { |
911 | | int ret; |
912 | | |
913 | | /* Try to allow - really just checking conditions. */ |
914 | | if (wolfSSL_CTX_allow_post_handshake_auth(ctx) == 0) { |
915 | | /* Set value as a bit. */ |
916 | | ctx->postHandshakeAuth = (val != 0); |
917 | | ret = 1; |
918 | | } |
919 | | else { |
920 | | ret = 0; |
921 | | } |
922 | | |
923 | | return ret; |
924 | | } |
925 | | /* Set whether handshakes with this SSL/TLS object allow auth post handshake. |
926 | | * |
927 | | * @param [in, out] ssl SSL/TLS object. |
928 | | * @param [in] val Whether to allow post handshake authentication. |
929 | | * @return 1 on success. |
930 | | * @return 0 on failure. |
931 | | */ |
932 | | int wolfSSL_set_post_handshake_auth(WOLFSSL* ssl, int val) |
933 | | { |
934 | | int ret; |
935 | | |
936 | | /* Try to allow - really just checking conditions. */ |
937 | | if (wolfSSL_allow_post_handshake_auth(ssl) == 0) { |
938 | | /* Set value as a bit. */ |
939 | | ssl->options.postHandshakeAuth = (val != 0); |
940 | | ret = 1; |
941 | | } |
942 | | else { |
943 | | ret = 0; |
944 | | } |
945 | | |
946 | | return ret; |
947 | | } |
948 | | #endif /* OPENSSL_EXTRA && WOLFSSL_TLS13 && WOLFSSL_POST_HANDSHAKE_AUTH */ |
949 | | |
950 | | #if defined(PERSIST_CERT_CACHE) |
951 | | |
952 | | #if !defined(NO_FILESYSTEM) |
953 | | |
954 | | /* Persist certificate cache in SSL/TLS context to file. |
955 | | * |
956 | | * @param [in] ctx SSL/TLS context. |
957 | | * @param [in] fname Filename so store certificate cache to. |
958 | | * @return 1 on success. |
959 | | * @return BAD_FUNC_ARG when ctx or fname is NULL. |
960 | | * @return Other values on failure. |
961 | | */ |
962 | | int wolfSSL_CTX_save_cert_cache(WOLFSSL_CTX* ctx, const char* fname) |
963 | | { |
964 | | int ret; |
965 | | |
966 | | WOLFSSL_ENTER("wolfSSL_CTX_save_cert_cache"); |
967 | | |
968 | | /* Validate parameters. */ |
969 | | if ((ctx == NULL) || (fname == NULL)) { |
970 | | ret = BAD_FUNC_ARG; |
971 | | } |
972 | | else { |
973 | | /* Save certificate cache. */ |
974 | | ret = CM_SaveCertCache(ctx->cm, fname); |
975 | | } |
976 | | |
977 | | return ret; |
978 | | } |
979 | | |
980 | | |
981 | | /* Load certificate cache into SSL/TLS context from file. |
982 | | * |
983 | | * @param [in] ctx SSL/TLS context. |
984 | | * @param [in] fname Filename so store certificate cache to. |
985 | | * @return 1 on success. |
986 | | * @return BAD_FUNC_ARG when ctx or fname is NULL. |
987 | | * @return Other values on failure. |
988 | | */ |
989 | | int wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX* ctx, const char* fname) |
990 | | { |
991 | | int ret; |
992 | | |
993 | | WOLFSSL_ENTER("wolfSSL_CTX_restore_cert_cache"); |
994 | | |
995 | | /* Validate parameters. */ |
996 | | if ((ctx == NULL) || (fname == NULL)) { |
997 | | ret = BAD_FUNC_ARG; |
998 | | } |
999 | | else { |
1000 | | /* Restore certificate cache. */ |
1001 | | ret = CM_RestoreCertCache(ctx->cm, fname); |
1002 | | } |
1003 | | |
1004 | | return ret; |
1005 | | } |
1006 | | |
1007 | | #endif /* NO_FILESYSTEM */ |
1008 | | |
1009 | | /* Persist certificate cache in SSL/TLS context to memory. |
1010 | | * |
1011 | | * @param [in] ctx SSL/TLS context. |
1012 | | * @param [in] mem Memory to fill with certificate cache. |
1013 | | * @param [in] sz Size of memory to fill in bytes. |
1014 | | * @param [out] used The number of bytes of memory used. |
1015 | | * @return 1 on success. |
1016 | | * @return BAD_FUNC_ARG when ctx, mem or used is NULL. |
1017 | | * @return BAD_FUNC_ARG when sz is less than or equal to zero. |
1018 | | * @return Other values on failure. |
1019 | | */ |
1020 | | int wolfSSL_CTX_memsave_cert_cache(WOLFSSL_CTX* ctx, void* mem, |
1021 | | int sz, int* used) |
1022 | | { |
1023 | | int ret; |
1024 | | |
1025 | | WOLFSSL_ENTER("wolfSSL_CTX_memsave_cert_cache"); |
1026 | | |
1027 | | /* Validate parameters. */ |
1028 | | if ((ctx == NULL) || (mem == NULL) || (used == NULL) || (sz <= 0)) { |
1029 | | ret = BAD_FUNC_ARG; |
1030 | | } |
1031 | | else { |
1032 | | /* Persist certificate change to memory. */ |
1033 | | ret = CM_MemSaveCertCache(ctx->cm, mem, sz, used); |
1034 | | } |
1035 | | |
1036 | | return ret; |
1037 | | } |
1038 | | |
1039 | | |
1040 | | /* Load certificate cache into SSL/TLS context from memory. |
1041 | | * |
1042 | | * @param [in] ctx SSL/TLS context. |
1043 | | * @param [in] mem Memory with certificate cache. |
1044 | | * @param [in] sz Size of certificate cache in bytes |
1045 | | * @return 1 on success. |
1046 | | * @return BAD_FUNC_ARG when ctx or mem is NULL. |
1047 | | * @return BAD_FUNC_ARG when sz is less than or equal to zero. |
1048 | | * @return Other values on failure. |
1049 | | */ |
1050 | | int wolfSSL_CTX_memrestore_cert_cache(WOLFSSL_CTX* ctx, const void* mem, int sz) |
1051 | | { |
1052 | | int ret; |
1053 | | |
1054 | | WOLFSSL_ENTER("wolfSSL_CTX_memrestore_cert_cache"); |
1055 | | |
1056 | | /* Validate parameters. */ |
1057 | | if ((ctx == NULL) || (mem == NULL) || (sz <= 0)) { |
1058 | | ret = BAD_FUNC_ARG; |
1059 | | } |
1060 | | else { |
1061 | | /* Restore certificate cache. */ |
1062 | | ret = CM_MemRestoreCertCache(ctx->cm, mem, sz); |
1063 | | } |
1064 | | |
1065 | | return ret; |
1066 | | } |
1067 | | |
1068 | | |
1069 | | /* Get size of certificate cache when persisted. |
1070 | | * |
1071 | | * @param [in] ctx SSL/TLS context. |
1072 | | * @return Size of certificate cache when pesisted in bytes. |
1073 | | * @return BAD_FUNC_ARG when ctx is NULL. |
1074 | | */ |
1075 | | int wolfSSL_CTX_get_cert_cache_memsize(WOLFSSL_CTX* ctx) |
1076 | | { |
1077 | | int ret; |
1078 | | |
1079 | | WOLFSSL_ENTER("wolfSSL_CTX_get_cert_cache_memsize"); |
1080 | | |
1081 | | /* Validate parameter. */ |
1082 | | if (ctx == NULL) { |
1083 | | ret = BAD_FUNC_ARG; |
1084 | | } |
1085 | | else { |
1086 | | /* Get size. */ |
1087 | | ret = CM_GetCertCacheMemSize(ctx->cm); |
1088 | | } |
1089 | | |
1090 | | return ret; |
1091 | | } |
1092 | | |
1093 | | #endif /* PERSIST_CERT_CACHE */ |
1094 | | |
1095 | | /* Unload certificates and keys that the SSL/TLS object owns. |
1096 | | * |
1097 | | * The WOLFSSL_CTX referenced is untouched. |
1098 | | * |
1099 | | * @param [in, out] ssl SSL/TLS object. |
1100 | | * @return 1 on success. |
1101 | | * @return BAD_FUNC_ARG when ssl is NULL. |
1102 | | */ |
1103 | | int wolfSSL_UnloadCertsKeys(WOLFSSL* ssl) |
1104 | 66.2k | { |
1105 | 66.2k | int ret = 1; |
1106 | | |
1107 | | /* Validate parameter. */ |
1108 | 66.2k | if (ssl == NULL) { |
1109 | 0 | WOLFSSL_MSG("Null function arg"); |
1110 | 0 | ret = BAD_FUNC_ARG; |
1111 | 0 | } |
1112 | 66.2k | else { |
1113 | 66.2k | if (ssl->buffers.weOwnCert && (!ssl->keepCert)) { |
1114 | 55.7k | WOLFSSL_MSG("Unloading cert"); |
1115 | 55.7k | FreeDer(&ssl->buffers.certificate); |
1116 | | #ifdef KEEP_OUR_CERT |
1117 | | wolfSSL_X509_free(ssl->ourCert); |
1118 | | ssl->ourCert = NULL; |
1119 | | #endif |
1120 | 55.7k | ssl->buffers.weOwnCert = 0; |
1121 | 55.7k | } |
1122 | | |
1123 | 66.2k | if (ssl->buffers.weOwnCertChain) { |
1124 | 0 | WOLFSSL_MSG("Unloading cert chain"); |
1125 | 0 | FreeDer(&ssl->buffers.certChain); |
1126 | 0 | ssl->buffers.weOwnCertChain = 0; |
1127 | 0 | } |
1128 | | |
1129 | | /* FreeKeyDer() zeroes the key when the last holder lets go of it. It |
1130 | | * can be shared with the CTX (WOLFSSL_DER_REFCOUNT), so it must not |
1131 | | * be zeroed here. */ |
1132 | 66.2k | if (ssl->buffers.weOwnKey) { |
1133 | 55.7k | WOLFSSL_MSG("Unloading key"); |
1134 | 55.7k | FreeKeyDer(&ssl->buffers.key); |
1135 | | #ifdef WOLFSSL_BLIND_PRIVATE_KEY |
1136 | | FreeDer(&ssl->buffers.keyMask); |
1137 | | #endif |
1138 | 55.7k | ssl->buffers.weOwnKey = 0; |
1139 | 55.7k | } |
1140 | | |
1141 | | #ifdef WOLFSSL_DUAL_ALG_CERTS |
1142 | | if (ssl->buffers.weOwnAltKey) { |
1143 | | WOLFSSL_MSG("Unloading alt key"); |
1144 | | FreeKeyDer(&ssl->buffers.altKey); |
1145 | | #ifdef WOLFSSL_BLIND_PRIVATE_KEY |
1146 | | FreeDer(&ssl->buffers.altKeyMask); |
1147 | | #endif |
1148 | | ssl->buffers.weOwnAltKey = 0; |
1149 | | } |
1150 | | #endif /* WOLFSSL_DUAL_ALG_CERTS */ |
1151 | 66.2k | } |
1152 | | |
1153 | 66.2k | return ret; |
1154 | 66.2k | } |
1155 | | |
1156 | | /* Unload CAs from the certificate manager of the SSL/TLS context. |
1157 | | * |
1158 | | * @param [in] ctx SSL/TLS context. |
1159 | | * @return 1 on success. |
1160 | | * @return BAD_FUNC_ARG when ctx or ctx->cm is NULL. |
1161 | | * @return BAD_MUTEX_E when locking fails. |
1162 | | */ |
1163 | | int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX* ctx) |
1164 | 0 | { |
1165 | 0 | int ret; |
1166 | |
|
1167 | 0 | WOLFSSL_ENTER("wolfSSL_CTX_UnloadCAs"); |
1168 | | |
1169 | | /* Validate parameter. */ |
1170 | 0 | if (ctx == NULL) { |
1171 | 0 | ret = BAD_FUNC_ARG; |
1172 | 0 | } |
1173 | 0 | else { |
1174 | 0 | ret = wolfSSL_CertManagerUnloadCAs(ctx->cm); |
1175 | 0 | } |
1176 | |
|
1177 | 0 | return ret; |
1178 | 0 | } |
1179 | | |
1180 | | /* Unload Intermediate CAs from the certificate manager of the SSL/TLS context. |
1181 | | * |
1182 | | * @param [in] ctx SSL/TLS context. |
1183 | | * @return 1 on success. |
1184 | | * @return BAD_FUNC_ARG when ctx or ctx->cm is NULL. |
1185 | | * @return BAD_STATE_E when another reference to the context is held. |
1186 | | * @return BAD_MUTEX_E when locking fails. |
1187 | | */ |
1188 | | int wolfSSL_CTX_UnloadIntermediateCerts(WOLFSSL_CTX* ctx) |
1189 | 0 | { |
1190 | 0 | int ret; |
1191 | |
|
1192 | 0 | WOLFSSL_ENTER("wolfSSL_CTX_UnloadIntermediateCerts"); |
1193 | | |
1194 | | /* Validate parameter. */ |
1195 | 0 | if (ctx == NULL) { |
1196 | 0 | ret = BAD_FUNC_ARG; |
1197 | 0 | } |
1198 | | /* Lock reference count. */ |
1199 | 0 | else if ((ret = wolfSSL_RefWithMutexLock(&ctx->ref)) == 0) { |
1200 | | /* Must not have another reference for this operation to be done. */ |
1201 | 0 | if (ctx->ref.count > 1) { |
1202 | 0 | WOLFSSL_MSG("ctx object must have a ref count of 1 before " |
1203 | 0 | "unloading intermediate certs"); |
1204 | 0 | ret = BAD_STATE_E; |
1205 | 0 | } |
1206 | 0 | else { |
1207 | 0 | ret = wolfSSL_CertManagerUnloadIntermediateCerts(ctx->cm); |
1208 | 0 | } |
1209 | | |
1210 | | /* Unlock reference count. */ |
1211 | 0 | if (wolfSSL_RefWithMutexUnlock(&ctx->ref) != 0) { |
1212 | 0 | WOLFSSL_MSG("Failed to unlock mutex!"); |
1213 | 0 | } |
1214 | 0 | } |
1215 | |
|
1216 | 0 | return ret; |
1217 | 0 | } |
1218 | | |
1219 | | |
1220 | | #ifdef WOLFSSL_TRUST_PEER_CERT |
1221 | | /* Unload trusted peers from the certificate manager of the SSL/TLS context. |
1222 | | * |
1223 | | * @param [in] ctx SSL/TLS context. |
1224 | | * @return 1 on success. |
1225 | | * @return BAD_FUNC_ARG when ctx or ctx->cm is NULL. |
1226 | | * @return BAD_MUTEX_E when locking fails. |
1227 | | */ |
1228 | | int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX* ctx) |
1229 | | { |
1230 | | int ret; |
1231 | | |
1232 | | WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers"); |
1233 | | |
1234 | | /* Validate parameter. */ |
1235 | | if (ctx == NULL) { |
1236 | | ret = BAD_FUNC_ARG; |
1237 | | } |
1238 | | else { |
1239 | | ret = wolfSSL_CertManagerUnload_trust_peers(ctx->cm); |
1240 | | } |
1241 | | |
1242 | | return ret; |
1243 | | } |
1244 | | |
1245 | | #ifdef WOLFSSL_LOCAL_X509_STORE |
1246 | | /* Unload trusted peers from the certificate manager of the SSL/TLS object. |
1247 | | * |
1248 | | * @param [in, out] ssl SSL/TLS object. |
1249 | | * @return 1 on success. |
1250 | | * @return BAD_FUNC_ARG when ssl is NULL. |
1251 | | * @return BAD_MUTEX_E when locking fails. |
1252 | | */ |
1253 | | int wolfSSL_Unload_trust_peers(WOLFSSL* ssl) |
1254 | | { |
1255 | | int ret; |
1256 | | |
1257 | | WOLFSSL_ENTER("wolfSSL_Unload_trust_peers"); |
1258 | | |
1259 | | /* Validate parameter. */ |
1260 | | if (ssl == NULL) { |
1261 | | ret = BAD_FUNC_ARG; |
1262 | | } |
1263 | | else { |
1264 | | /* Output message when certificate manager for object. */ |
1265 | | SSL_CM_WARNING(ssl); |
1266 | | return wolfSSL_CertManagerUnload_trust_peers(SSL_CM(ssl)); |
1267 | | } |
1268 | | |
1269 | | return ret; |
1270 | | } |
1271 | | #endif /* WOLFSSL_LOCAL_X509_STORE */ |
1272 | | #endif /* WOLFSSL_TRUST_PEER_CERT */ |
1273 | | |
1274 | | #if !defined(WOLFSSL_NO_CA_NAMES) && defined(OPENSSL_EXTRA) |
1275 | | /* Add a CA certificate to the list of CA names. |
1276 | | * |
1277 | | * @param [in, out] ca_names List of CA certificate subject names. |
1278 | | * @param [in] x509 X509 certificate. |
1279 | | * @return 1 on success. |
1280 | | * @return 0 on failure. |
1281 | | */ |
1282 | | static int add_to_ca_names_list(WOLFSSL_STACK* ca_names, WOLFSSL_X509* x509) |
1283 | | { |
1284 | | int ret = 1; |
1285 | | WOLFSSL_X509_NAME *nameCopy = NULL; |
1286 | | |
1287 | | /* The list owns its names, so push a copy of the subject name. */ |
1288 | | nameCopy = wolfSSL_X509_NAME_dup(wolfSSL_X509_get_subject_name(x509)); |
1289 | | if (nameCopy == NULL) { |
1290 | | WOLFSSL_MSG("wolfSSL_X509_NAME_dup error"); |
1291 | | ret = 0; |
1292 | | } |
1293 | | /* On push failure the copy is not owned by the list - free it here. */ |
1294 | | else if (wolfSSL_sk_X509_NAME_push(ca_names, nameCopy) <= 0) { |
1295 | | WOLFSSL_MSG("wolfSSL_sk_X509_NAME_push error"); |
1296 | | wolfSSL_X509_NAME_free(nameCopy); |
1297 | | ret = 0; |
1298 | | } |
1299 | | |
1300 | | return ret; |
1301 | | } |
1302 | | |
1303 | | /* Add a client's CA to SSL/TLS context. |
1304 | | * |
1305 | | * @param [in] ctx SSL/TLS context. |
1306 | | * @param [in] x509 X509 certificate. |
1307 | | * @return 1 on success. |
1308 | | * @return 0 on failure. |
1309 | | */ |
1310 | | int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) |
1311 | | { |
1312 | | int ret = 1; |
1313 | | |
1314 | | WOLFSSL_ENTER("wolfSSL_CTX_add_client_CA"); |
1315 | | |
1316 | | /* Validate parameters. */ |
1317 | | if ((ctx == NULL) || (x509 == NULL)) { |
1318 | | WOLFSSL_MSG("Bad argument"); |
1319 | | ret = 0; |
1320 | | } |
1321 | | /* Create a stack of names if not present. */ |
1322 | | else if (ctx->client_ca_names == NULL) { |
1323 | | ctx->client_ca_names = wolfSSL_sk_X509_NAME_new(NULL); |
1324 | | if (ctx->client_ca_names == NULL) { |
1325 | | WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error"); |
1326 | | ret = 0; |
1327 | | } |
1328 | | } |
1329 | | if (ret == 1) { |
1330 | | /* Add certificate's subject name to client CA name list. */ |
1331 | | ret = add_to_ca_names_list(ctx->client_ca_names, x509); |
1332 | | } |
1333 | | |
1334 | | return ret; |
1335 | | } |
1336 | | |
1337 | | /* Add a client's CA to SSL/TLS object. |
1338 | | * |
1339 | | * @param [in, out] ssl SSL/TLS object. |
1340 | | * @param [in] x509 X509 certificate. |
1341 | | * @return 1 on success. |
1342 | | * @return 0 on failure. |
1343 | | */ |
1344 | | int wolfSSL_add_client_CA(WOLFSSL* ssl, WOLFSSL_X509* x509) |
1345 | | { |
1346 | | int ret = 1; |
1347 | | |
1348 | | WOLFSSL_ENTER("wolfSSL_add_client_CA"); |
1349 | | |
1350 | | /* Validate parameters. */ |
1351 | | if ((ssl == NULL) || (x509 == NULL)) { |
1352 | | WOLFSSL_MSG("Bad argument"); |
1353 | | ret = 0; |
1354 | | } |
1355 | | /* Create a stack of names if not present. */ |
1356 | | else if (ssl->client_ca_names == NULL) { |
1357 | | ssl->client_ca_names = wolfSSL_sk_X509_NAME_new(NULL); |
1358 | | if (ssl->client_ca_names == NULL) { |
1359 | | WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error"); |
1360 | | ret = 0; |
1361 | | } |
1362 | | } |
1363 | | if (ret == 1) { |
1364 | | /* Add certificate's subject name to client CA name list. */ |
1365 | | ret = add_to_ca_names_list(ssl->client_ca_names, x509); |
1366 | | } |
1367 | | |
1368 | | return ret; |
1369 | | } |
1370 | | |
1371 | | /* Add a CA to SSL/TLS context. |
1372 | | * |
1373 | | * @param [in] ctx SSL/TLS context. |
1374 | | * @param [in] x509 X509 certificate. |
1375 | | * @return 1 on success. |
1376 | | * @return 0 on failure. |
1377 | | */ |
1378 | | int wolfSSL_CTX_add1_to_CA_list(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) |
1379 | | { |
1380 | | int ret = 1; |
1381 | | |
1382 | | WOLFSSL_ENTER("wolfSSL_CTX_add1_to_CA_list"); |
1383 | | |
1384 | | /* Validate parameters. */ |
1385 | | if ((ctx == NULL) || (x509 == NULL)) { |
1386 | | WOLFSSL_MSG("Bad argument"); |
1387 | | ret = 0; |
1388 | | } |
1389 | | /* Create a stack of names if not present. */ |
1390 | | else if (ctx->ca_names == NULL) { |
1391 | | ctx->ca_names = wolfSSL_sk_X509_NAME_new(NULL); |
1392 | | if (ctx->ca_names == NULL) { |
1393 | | WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error"); |
1394 | | ret = 0; |
1395 | | } |
1396 | | } |
1397 | | if (ret == 1) { |
1398 | | /* Add certificate's subject name to CA name list. */ |
1399 | | ret = add_to_ca_names_list(ctx->ca_names, x509); |
1400 | | } |
1401 | | |
1402 | | return ret; |
1403 | | } |
1404 | | |
1405 | | /* Add a CA to SSL/TLS object. |
1406 | | * |
1407 | | * @param [in, out] ssl SSL/TLS object. |
1408 | | * @param [in] x509 X509 certificate. |
1409 | | * @return 1 on success. |
1410 | | * @return 0 on failure. |
1411 | | */ |
1412 | | int wolfSSL_add1_to_CA_list(WOLFSSL* ssl, WOLFSSL_X509* x509) |
1413 | | { |
1414 | | int ret = 1; |
1415 | | |
1416 | | WOLFSSL_ENTER("wolfSSL_add1_to_CA_list"); |
1417 | | |
1418 | | /* Validate parameters. */ |
1419 | | if ((ssl == NULL) || (x509 == NULL)) { |
1420 | | WOLFSSL_MSG("Bad argument"); |
1421 | | ret = 0; |
1422 | | } |
1423 | | /* Create a stack of names if not present. */ |
1424 | | else if (ssl->ca_names == NULL) { |
1425 | | ssl->ca_names = wolfSSL_sk_X509_NAME_new(NULL); |
1426 | | if (ssl->ca_names == NULL) { |
1427 | | WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error"); |
1428 | | ret = 0; |
1429 | | } |
1430 | | } |
1431 | | if (ret == 1) { |
1432 | | /* Add certificate's subject name to CA name list. */ |
1433 | | ret = add_to_ca_names_list(ssl->ca_names, x509); |
1434 | | } |
1435 | | |
1436 | | return ret; |
1437 | | } |
1438 | | |
1439 | | /* Set the client CA list into SSL/TLS context. |
1440 | | * |
1441 | | * @param [in] ctx SSL/TLS context. |
1442 | | * @param [in] names List of CA subject names. |
1443 | | */ |
1444 | | void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx, |
1445 | | WOLF_STACK_OF(WOLFSSL_X509_NAME)* names) |
1446 | | { |
1447 | | WOLFSSL_ENTER("wolfSSL_CTX_set_client_CA_list"); |
1448 | | |
1449 | | /* Validate parameters. */ |
1450 | | if (ctx != NULL) { |
1451 | | /* Dispose of any existing list. */ |
1452 | | wolfSSL_sk_X509_NAME_pop_free(ctx->client_ca_names, NULL); |
1453 | | /* Take ownership of names list. */ |
1454 | | ctx->client_ca_names = names; |
1455 | | } |
1456 | | } |
1457 | | |
1458 | | /* Set the client CA list into SSL/TLS object. |
1459 | | * |
1460 | | * @param [in] ssl SSL/TLS object. |
1461 | | * @param [in] names List of CA subject names. |
1462 | | */ |
1463 | | void wolfSSL_set_client_CA_list(WOLFSSL* ssl, |
1464 | | WOLF_STACK_OF(WOLFSSL_X509_NAME)* names) |
1465 | | { |
1466 | | WOLFSSL_ENTER("wolfSSL_set_client_CA_list"); |
1467 | | |
1468 | | /* Validate parameters. */ |
1469 | | if (ssl != NULL) { |
1470 | | /* Dispose of any existing list if the object owns it. */ |
1471 | | if (ssl->client_ca_names != ssl->ctx->client_ca_names) { |
1472 | | wolfSSL_sk_X509_NAME_pop_free(ssl->client_ca_names, NULL); |
1473 | | } |
1474 | | /* Take ownership of names list. */ |
1475 | | ssl->client_ca_names = names; |
1476 | | } |
1477 | | } |
1478 | | |
1479 | | /* Set the CA list into SSL/TLS context. |
1480 | | * |
1481 | | * @param [in] ctx SSL/TLS context. |
1482 | | * @param [in] names List of CA subject names. |
1483 | | */ |
1484 | | void wolfSSL_CTX_set0_CA_list(WOLFSSL_CTX* ctx, |
1485 | | WOLF_STACK_OF(WOLFSSL_X509_NAME)* names) |
1486 | | { |
1487 | | WOLFSSL_ENTER("wolfSSL_CTX_set0_CA_list"); |
1488 | | |
1489 | | /* Validate parameters. */ |
1490 | | if (ctx != NULL) { |
1491 | | /* Dispose of any existing list. */ |
1492 | | wolfSSL_sk_X509_NAME_pop_free(ctx->ca_names, NULL); |
1493 | | /* Take ownership of names list. */ |
1494 | | ctx->ca_names = names; |
1495 | | } |
1496 | | } |
1497 | | |
1498 | | /* Set the client CA list into SSL/TLS object. |
1499 | | * |
1500 | | * @param [in] ssl SSL/TLS object. |
1501 | | * @param [in] names List of CA subject names. |
1502 | | */ |
1503 | | void wolfSSL_set0_CA_list(WOLFSSL* ssl, |
1504 | | WOLF_STACK_OF(WOLFSSL_X509_NAME)* names) |
1505 | | { |
1506 | | WOLFSSL_ENTER("wolfSSL_set0_CA_list"); |
1507 | | |
1508 | | /* Validate parameters. */ |
1509 | | if (ssl != NULL) { |
1510 | | /* Dispose of any existing list if the object owns it. */ |
1511 | | if (ssl->ca_names != ssl->ctx->ca_names) { |
1512 | | wolfSSL_sk_X509_NAME_pop_free(ssl->ca_names, NULL); |
1513 | | } |
1514 | | /* Take ownership of names list. */ |
1515 | | ssl->ca_names = names; |
1516 | | } |
1517 | | } |
1518 | | |
1519 | | /* Get the list of client CA subject names from the SSL/TLS context. |
1520 | | * |
1521 | | * @param [in] ctx SSL/TLS context. |
1522 | | * @return List of CA subject names on success. |
1523 | | * @return NULL when ctx is NULL or no names set. |
1524 | | */ |
1525 | | WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_CTX_get_client_CA_list( |
1526 | | const WOLFSSL_CTX *ctx) |
1527 | | { |
1528 | | WOLF_STACK_OF(WOLFSSL_X509_NAME)* ret; |
1529 | | |
1530 | | WOLFSSL_ENTER("wolfSSL_CTX_get_client_CA_list"); |
1531 | | |
1532 | | /* Validate parameter. */ |
1533 | | if (ctx == NULL) { |
1534 | | WOLFSSL_MSG("Bad argument passed to wolfSSL_CTX_get_client_CA_list"); |
1535 | | ret = NULL; |
1536 | | } |
1537 | | else { |
1538 | | ret = ctx->client_ca_names; |
1539 | | } |
1540 | | |
1541 | | return ret; |
1542 | | } |
1543 | | |
1544 | | /* Get the list of client CA subject names from the SSL/TLS object. |
1545 | | * |
1546 | | * On server side: returns the CAs set via *_set_client_CA_list(); |
1547 | | * On client side: returns the CAs received from server -- same as |
1548 | | * wolfSSL_get0_peer_CA_list(). |
1549 | | * |
1550 | | * @param [in] ssl SSL/TLS object. |
1551 | | * @return List of CA subject names on success. |
1552 | | * @return NULL when ssl is NULL or no names set. |
1553 | | */ |
1554 | | WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get_client_CA_list(const WOLFSSL* ssl) |
1555 | | { |
1556 | | WOLF_STACK_OF(WOLFSSL_X509_NAME)* ret; |
1557 | | |
1558 | | WOLFSSL_ENTER("wolfSSL_get_client_CA_list"); |
1559 | | |
1560 | | /* Validate parameter. */ |
1561 | | if (ssl == NULL) { |
1562 | | WOLFSSL_MSG("Bad argument passed to wolfSSL_get_client_CA_list"); |
1563 | | ret = NULL; |
1564 | | } |
1565 | | /* Client side return peer CA names. */ |
1566 | | else if (ssl->options.side == WOLFSSL_CLIENT_END) { |
1567 | | ret = ssl->peer_ca_names; |
1568 | | } |
1569 | | /* Server side return client CA names. */ |
1570 | | else { |
1571 | | ret = SSL_CLIENT_CA_NAMES(ssl); |
1572 | | } |
1573 | | |
1574 | | return ret; |
1575 | | } |
1576 | | |
1577 | | /* Get the list of CA subject names from the SSL/TLS context. |
1578 | | * |
1579 | | * @param [in] ctx SSL/TLS context. |
1580 | | * @return List of CA subject names on success. |
1581 | | * @return NULL when ctx is NULL or no names set. |
1582 | | */ |
1583 | | WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_CTX_get0_CA_list( |
1584 | | const WOLFSSL_CTX *ctx) |
1585 | | { |
1586 | | WOLF_STACK_OF(WOLFSSL_X509_NAME)* ret; |
1587 | | |
1588 | | WOLFSSL_ENTER("wolfSSL_CTX_get0_CA_list"); |
1589 | | |
1590 | | /* Validate parameter. */ |
1591 | | if (ctx == NULL) { |
1592 | | WOLFSSL_MSG("Bad argument passed to wolfSSL_CTX_get0_CA_list"); |
1593 | | ret = NULL; |
1594 | | } |
1595 | | else { |
1596 | | /* Return list directly. */ |
1597 | | ret = ctx->ca_names; |
1598 | | } |
1599 | | |
1600 | | return ret; |
1601 | | } |
1602 | | |
1603 | | /* Get the list of CA subject names from the SSL/TLS object. |
1604 | | * |
1605 | | * Always returns the CA's set via *_set0_CA_list. |
1606 | | * |
1607 | | * @param [in] ssl SSL/TLS object. |
1608 | | * @return List of CA subject names on success. |
1609 | | * @return NULL when ssl is NULL or no names set. |
1610 | | */ |
1611 | | WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get0_CA_list(const WOLFSSL *ssl) |
1612 | | { |
1613 | | WOLF_STACK_OF(WOLFSSL_X509_NAME)* ret; |
1614 | | |
1615 | | WOLFSSL_ENTER("wolfSSL_get0_CA_list"); |
1616 | | |
1617 | | /* Validate parameter. */ |
1618 | | if (ssl == NULL) { |
1619 | | WOLFSSL_MSG("Bad argument passed to wolfSSL_get0_CA_list"); |
1620 | | ret = NULL; |
1621 | | } |
1622 | | else { |
1623 | | /* Return list directly from object, if available, or context. */ |
1624 | | ret = SSL_CA_NAMES(ssl); |
1625 | | } |
1626 | | |
1627 | | return ret; |
1628 | | } |
1629 | | |
1630 | | /* Get the list of peer CA subject names from the SSL/TLS object. |
1631 | | * |
1632 | | * Always returns the CA's received from the peer. |
1633 | | * |
1634 | | * @param [in] ssl SSL/TLS object. |
1635 | | * @return List of CA subject names on success. |
1636 | | * @return NULL when ssl is NULL or no names set. |
1637 | | */ |
1638 | | WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get0_peer_CA_list(const WOLFSSL* ssl) |
1639 | | { |
1640 | | WOLF_STACK_OF(WOLFSSL_X509_NAME)* ret; |
1641 | | |
1642 | | WOLFSSL_ENTER("wolfSSL_get0_peer_CA_list"); |
1643 | | |
1644 | | /* Validate parameter. */ |
1645 | | if (ssl == NULL) { |
1646 | | WOLFSSL_MSG("Bad argument passed to wolfSSL_get0_peer_CA_list"); |
1647 | | ret = NULL; |
1648 | | } |
1649 | | else { |
1650 | | /* Return list directly from object. */ |
1651 | | ret = ssl->peer_ca_names; |
1652 | | } |
1653 | | |
1654 | | return ret; |
1655 | | } |
1656 | | |
1657 | | #ifndef NO_BIO |
1658 | | /* Load the client CA subject names from file. |
1659 | | * |
1660 | | * @param [in] fname Name of file containing client CA certificates. |
1661 | | * @return A list of certificate names on success. |
1662 | | * @return NULL on error. |
1663 | | */ |
1664 | | WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char* fname) |
1665 | | { |
1666 | | /* The webserver build is using this to load a CA into the server |
1667 | | * for client authentication as an option. Have this return NULL in |
1668 | | * that case. If OPENSSL_EXTRA is enabled, go ahead and include |
1669 | | * the function. */ |
1670 | | #ifdef OPENSSL_EXTRA |
1671 | | WOLFSSL_STACK *list = NULL; |
1672 | | WOLFSSL_BIO* bio = NULL; |
1673 | | WOLFSSL_X509 *cert = NULL; |
1674 | | int err = 0; |
1675 | | unsigned long error; |
1676 | | |
1677 | | WOLFSSL_ENTER("wolfSSL_load_client_CA_file"); |
1678 | | |
1679 | | /* Create a file BIO to read. */ |
1680 | | bio = wolfSSL_BIO_new_file(fname, "rb"); |
1681 | | if (bio == NULL) { |
1682 | | WOLFSSL_MSG("wolfSSL_BIO_new_file error"); |
1683 | | err = 1; |
1684 | | } |
1685 | | |
1686 | | if (!err) { |
1687 | | /* Create an empty list of certificate names - default compare cb. */ |
1688 | | list = wolfSSL_sk_X509_NAME_new(NULL); |
1689 | | if (list == NULL) { |
1690 | | WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error"); |
1691 | | err = 1; |
1692 | | } |
1693 | | } |
1694 | | |
1695 | | /* Read each certificate in the chain out of the file. */ |
1696 | | while ((!err) && (wolfSSL_PEM_read_bio_X509(bio, &cert, NULL, NULL) != NULL)) { |
1697 | | WOLFSSL_X509_NAME *nameCopy; |
1698 | | |
1699 | | /* Need a persistent copy of the subject name. */ |
1700 | | nameCopy = wolfSSL_X509_NAME_dup(wolfSSL_X509_get_subject_name(cert)); |
1701 | | if (nameCopy == NULL) { |
1702 | | WOLFSSL_MSG("wolfSSL_X509_NAME_dup error"); |
1703 | | err = 1; |
1704 | | } |
1705 | | else { |
1706 | | /* Original certificate will be freed - clear reference to it. */ |
1707 | | nameCopy->x509 = NULL; |
1708 | | |
1709 | | if (wolfSSL_sk_X509_NAME_push(list, nameCopy) <= 0) { |
1710 | | WOLFSSL_MSG("wolfSSL_sk_X509_NAME_push error"); |
1711 | | /* Name not stored - free now as only place needing to. */ |
1712 | | wolfSSL_X509_NAME_free(nameCopy); |
1713 | | err = 1; |
1714 | | } |
1715 | | } |
1716 | | |
1717 | | /* Dispose of certificate read. */ |
1718 | | wolfSSL_X509_free(cert); |
1719 | | cert = NULL; |
1720 | | } |
1721 | | |
1722 | | /* Clear any error due to no more certificates. */ |
1723 | | CLEAR_ASN_NO_PEM_HEADER_ERROR(error); |
1724 | | |
1725 | | if (err) { |
1726 | | /* Error occurred so return NULL. */ |
1727 | | wolfSSL_sk_X509_NAME_pop_free(list, NULL); |
1728 | | list = NULL; |
1729 | | } |
1730 | | wolfSSL_BIO_free(bio); |
1731 | | return list; |
1732 | | #else |
1733 | | (void)fname; |
1734 | | return NULL; |
1735 | | #endif |
1736 | | } |
1737 | | #endif /* !NO_BIO */ |
1738 | | #endif /* WOLFSSL_NO_CA_NAMES */ |
1739 | | |
1740 | | #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) |
1741 | | /* Get the certificate store of the SSL/TLS context. |
1742 | | * |
1743 | | * @param [in] ctx SSL/TLS context. |
1744 | | * @return X509 certificate store on success. |
1745 | | * @return NULL when ctx is NULL. |
1746 | | */ |
1747 | | WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(const WOLFSSL_CTX* ctx) |
1748 | | { |
1749 | | WOLFSSL_X509_STORE* ret; |
1750 | | |
1751 | | /* Validate parameter. */ |
1752 | | if (ctx == NULL) { |
1753 | | ret = NULL; |
1754 | | } |
1755 | | /* Use pointer to external store if set. */ |
1756 | | else if (ctx->x509_store_pt != NULL) { |
1757 | | ret = ctx->x509_store_pt; |
1758 | | } |
1759 | | else { |
1760 | | /* Return reference to store that is part of the context. */ |
1761 | | ret = (WOLFSSL_X509_STORE*)&ctx->x509_store; |
1762 | | } |
1763 | | |
1764 | | return ret; |
1765 | | } |
1766 | | |
1767 | | /* Set the certificate store of the SSL/TLS context. |
1768 | | * |
1769 | | * The store is not taken when it shares the context's certificate manager. |
1770 | | * |
1771 | | * Ownership: the caller's reference to the store is taken over - no reference |
1772 | | * is added here, and the context releases it on free. A caller that means to |
1773 | | * keep using the store must take its own reference first with |
1774 | | * wolfSSL_X509_STORE_up_ref(). A reference is added to the store's |
1775 | | * certificate manager, which the context then uses as its own. |
1776 | | * |
1777 | | * @param [in, out] ctx SSL/TLS context. |
1778 | | * @param [in] str X509 certificate store to use. |
1779 | | */ |
1780 | | void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str) |
1781 | | { |
1782 | | WOLFSSL_ENTER("wolfSSL_CTX_set_cert_store"); |
1783 | | |
1784 | | /* Validate parameters. */ |
1785 | | if ((ctx == NULL) || (str == NULL) || (ctx->cm == str->cm)) { |
1786 | | WOLFSSL_MSG("Invalid parameters"); |
1787 | | } |
1788 | | else if (wolfSSL_CertManager_up_ref(str->cm) != 1) { |
1789 | | WOLFSSL_MSG("wolfSSL_CertManager_up_ref error"); |
1790 | | } |
1791 | | else { |
1792 | | /* Free any cert manager. */ |
1793 | | wolfSSL_CertManagerFree(ctx->cm); |
1794 | | /* Free any external store. */ |
1795 | | wolfSSL_X509_STORE_free(ctx->x509_store_pt); |
1796 | | /* Set the certificate manager into context. */ |
1797 | | ctx->cm = str->cm; |
1798 | | ctx->x509_store.cm = str->cm; |
1799 | | ctx->x509_store.cache = str->cache; |
1800 | | /* Take ownership of store and free it with context free. */ |
1801 | | ctx->x509_store_pt = str; |
1802 | | /* Context has ownership and free it with context free. */ |
1803 | | ctx->cm->x509_store_p = ctx->x509_store_pt; |
1804 | | |
1805 | | #ifdef OPENSSL_EXTRA |
1806 | | /* Non-self-signed certs (intermediates) added via |
1807 | | * X509_STORE_add_cert only go into store->certs, not the |
1808 | | * CertManager. Push them into the CM now so that all |
1809 | | * verification paths can find them. */ |
1810 | | if (X509StorePushCertsToCM(str) != WOLFSSL_SUCCESS) { |
1811 | | WOLFSSL_MSG("wolfSSL_CTX_set_cert_store: failed to push some " |
1812 | | "certs to CertManager"); |
1813 | | } |
1814 | | #endif |
1815 | | } |
1816 | | } |
1817 | | |
1818 | | #ifdef OPENSSL_ALL |
1819 | | /* Set certificate store into SSL/TLS context but don't take ownership. |
1820 | | * |
1821 | | * A NULL store is refused, which is a deviation from OpenSSL, where |
1822 | | * SSL_CTX_set1_verify_cert_store(ctx, NULL) returns 1 and releases the verify |
1823 | | * store so the context falls back to its own. OpenSSL keeps two stores on a |
1824 | | * context, the one set by SSL_CTX_set_cert_store() and the verify store this |
1825 | | * call sets; both live in ctx->x509_store_pt here, so releasing it on NULL |
1826 | | * would also throw away the store handed to wolfSSL_CTX_set_cert_store() and |
1827 | | * drop the context back to its own, which is not set up for certificate |
1828 | | * lookup by issuer. Until the two are held separately the request cannot be |
1829 | | * honoured, and refusing it is what keeps that visible - returning success |
1830 | | * without clearing would leave the caller verifying against the store it |
1831 | | * asked to be rid of. |
1832 | | * |
1833 | | * Note the asymmetry with the object-level setters: |
1834 | | * wolfSSL_set0_verify_cert_store() and wolfSSL_set1_verify_cert_store() do |
1835 | | * clear on NULL, because an object reverts to the context's store rather than |
1836 | | * having a second store of its own to throw away. |
1837 | | * |
1838 | | * @param [in] ctx SSL/TLS context. |
1839 | | * @param [in] str Certificate store. NULL is refused. |
1840 | | * @return 1 on success. |
1841 | | * @return 0 when ctx or str is NULL, or on other error. |
1842 | | */ |
1843 | | int wolfSSL_CTX_set1_verify_cert_store(WOLFSSL_CTX* ctx, |
1844 | | WOLFSSL_X509_STORE* str) |
1845 | | { |
1846 | | int ret; |
1847 | | |
1848 | | WOLFSSL_ENTER("wolfSSL_CTX_set1_verify_cert_store"); |
1849 | | |
1850 | | /* Validate parameters. A NULL store is refused rather than accepted and |
1851 | | * ignored. OpenSSL keeps two stores on a context - the one set by |
1852 | | * SSL_CTX_set_cert_store() and the verify store this call sets - and |
1853 | | * clearing the verify store leaves the other alone. Both live in |
1854 | | * ctx->x509_store_pt here, so releasing it on NULL would throw away the |
1855 | | * store handed to wolfSSL_CTX_set_cert_store() and drop the context back |
1856 | | * to its own, which is not set up for certificate lookup by issuer. |
1857 | | * Reporting failure keeps that unsupported request visible: returning |
1858 | | * success without clearing would leave the caller verifying against the |
1859 | | * store it asked to be rid of, with no way to tell. */ |
1860 | | if ((ctx == NULL) || (str == NULL)) { |
1861 | | WOLFSSL_MSG("Bad parameter"); |
1862 | | ret = 0; |
1863 | | } |
1864 | | /* Nothing to do when store being set is the same as existing in context. */ |
1865 | | else if (str == CTX_STORE(ctx)) { |
1866 | | ret = 1; |
1867 | | } |
1868 | | /* Take a reference so the pointer can be stored and released with the |
1869 | | * context. A store that is part of another object has none to take - the |
1870 | | * pointer is then kept without anything protecting it. */ |
1871 | | else if (wolfSSL_X509_STORE_up_ref(str) != 1) { |
1872 | | WOLFSSL_MSG("wolfSSL_X509_STORE_up_ref error"); |
1873 | | ret = 0; |
1874 | | } |
1875 | | else { |
1876 | | /* Free any external store. */ |
1877 | | wolfSSL_X509_STORE_free(ctx->x509_store_pt); |
1878 | | /* Ref count increased - store pointer and free with context free. */ |
1879 | | ctx->x509_store_pt = str; |
1880 | | /* As above: the store just released may have been the one this |
1881 | | * manager names, which leaves the manager with no store for the |
1882 | | * lookup by issuer. Unlike wolfSSL_CTX_set_cert_store(), this setter |
1883 | | * does not adopt the new store's manager - str carries its own, and |
1884 | | * that is the one verification resolves through, so pairing this |
1885 | | * manager with str would cross-link two independent managers. The |
1886 | | * context's own store is used instead: what the manager needs is a |
1887 | | * store that stays valid for as long as it does, not the one |
1888 | | * currently in use. */ |
1889 | | if ((ctx->cm != NULL) && (ctx->cm->x509_store_p == NULL)) { |
1890 | | ctx->cm->x509_store_p = &ctx->x509_store; |
1891 | | } |
1892 | | ret = 1; |
1893 | | } |
1894 | | |
1895 | | return ret; |
1896 | | } |
1897 | | #endif |
1898 | | |
1899 | | |
1900 | | /* Set the certificate store used for verification by the SSL/TLS object. |
1901 | | * |
1902 | | * Ownership: with ref set, a reference is taken here (set1 semantics); |
1903 | | * without it the caller's reference is handed over (set0 semantics). With |
1904 | | * ref set the accounting always nets to zero - the reference taken is kept |
1905 | | * with the stored pointer, or released again when no pointer is kept. |
1906 | | * |
1907 | | * A set0 caller's reference is consumed by being kept, except on the two |
1908 | | * paths that keep no pointer and cannot safely release it either: being |
1909 | | * handed the store the object already uses, and being handed the context's |
1910 | | * store while the object holds one of its own. Both leak that reference by |
1911 | | * design - see the comments on those branches; releasing it would free a |
1912 | | * reference a misusing caller never took. |
1913 | | * |
1914 | | * A store that is part of another object has no reference count to take, so |
1915 | | * nothing keeps it alive for as long as the pointer is held here - see |
1916 | | * wolfSSL_X509_STORE_up_ref(). Storing one that belongs to a different |
1917 | | * object outlives its owner only by luck. |
1918 | | * |
1919 | | * A set0 caller must therefore own a reference. Handing over a borrowed |
1920 | | * pointer, such as one straight from wolfSSL_CTX_get_cert_store(), releases |
1921 | | * a reference the caller never took and can destroy a store still in use. |
1922 | | * |
1923 | | * The object uses the context's store by keeping no pointer of its own, so |
1924 | | * that is how both a NULL store, which clears, and being handed the store the |
1925 | | * context already uses are done. Clearing on NULL rather than rejecting it |
1926 | | * matches OpenSSL. |
1927 | | * |
1928 | | * "The store the context already uses" is what CTX_STORE() resolves to, which |
1929 | | * is the context's own store when no other has been set on it. So handing |
1930 | | * over wolfSSL_CTX_get_cert_store() of such a context makes the object follow |
1931 | | * the context rather than pinning that store: a later |
1932 | | * wolfSSL_CTX_set1_verify_cert_store() then changes what the object verifies |
1933 | | * against. OpenSSL's SSL_set1_verify_cert_store() pins instead, and so did |
1934 | | * this before the context's own store was included in the comparison. |
1935 | | * Following is the safer of the two here, because a store that is part of |
1936 | | * another object has no reference count and pinning it stores a pointer with |
1937 | | * nothing keeping it alive. |
1938 | | * |
1939 | | * @param [in, out] ssl SSL/TLS object. |
1940 | | * @param [in] str X509 certificate store to use. NULL to clear. |
1941 | | * @param [in] ref Whether to take a reference to the store. |
1942 | | * @return 1 on success. |
1943 | | * @return 0 when ssl is NULL, or the reference cannot be taken. |
1944 | | */ |
1945 | | static int wolfssl_set_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str, |
1946 | | int ref) |
1947 | | { |
1948 | | int ret; |
1949 | | |
1950 | | WOLFSSL_ENTER("wolfssl_set_verify_cert_store"); |
1951 | | |
1952 | | /* Validate parameters. */ |
1953 | | if (ssl == NULL) { |
1954 | | WOLFSSL_MSG("Bad parameter"); |
1955 | | ret = 0; |
1956 | | } |
1957 | | /* Already the store this object uses - its own, or the context's when it |
1958 | | * has none of its own: leave every reference where it is, as the original |
1959 | | * code did. Consuming one here would release a reference the object or |
1960 | | * the context still relies on when a set0 caller passed a pointer it did |
1961 | | * not own, which is a use-after-free for the object's store and a second |
1962 | | * free at wolfSSL_CTX_free() for the context's. A leaked reference is the |
1963 | | * safer of the two outcomes for an entry point applications reach through |
1964 | | * the OpenSSL compatibility layer. */ |
1965 | | else if (str == SSL_STORE(ssl)) { |
1966 | | ret = 1; |
1967 | | } |
1968 | | /* Take the reference to become responsible for before releasing the one |
1969 | | * the object holds below. The two name different stores - the store the |
1970 | | * object already uses is caught by the early exit above. */ |
1971 | | else if (ref && (str != NULL) && (wolfSSL_X509_STORE_up_ref(str) != 1)) { |
1972 | | WOLFSSL_MSG("wolfSSL_X509_STORE_up_ref error"); |
1973 | | ret = 0; |
1974 | | } |
1975 | | else { |
1976 | | /* The object uses the context's store by keeping no pointer, so that |
1977 | | * is what being handed that store means here. A NULL store, which |
1978 | | * clears, is kept as it is and so keeps no pointer either. */ |
1979 | | WOLFSSL_X509_STORE* keep = (str == CTX_STORE(ssl->ctx)) ? NULL : str; |
1980 | | |
1981 | | /* Release the store held, if any, and take on the new one. The |
1982 | | * reference this call is responsible for - taken above for set1, |
1983 | | * handed over for set0 - is consumed by being kept. */ |
1984 | | wolfSSL_X509_STORE_free(ssl->x509_store_pt); |
1985 | | ssl->x509_store_pt = keep; |
1986 | | if ((keep == NULL) && ref) { |
1987 | | /* Nothing kept the reference taken above, so give it back. Only |
1988 | | * set1 gets here: a set0 caller's reference must be left alone, |
1989 | | * as the store it named is the context's and releasing it would |
1990 | | * leave ctx->x509_store_pt pointing at memory freed a second |
1991 | | * time by wolfSSL_CTX_free(). */ |
1992 | | wolfSSL_X509_STORE_free(str); |
1993 | | } |
1994 | | ret = 1; |
1995 | | } |
1996 | | |
1997 | | return ret; |
1998 | | } |
1999 | | |
2000 | | /* Set certificate store into SSL/TLS object and take ownership. |
2001 | | * |
2002 | | * The caller must own a reference to the store - it is consumed here. A NULL |
2003 | | * store clears any store previously set on the object. * |
2004 | | * Passing the store the context is currently using - what |
2005 | | * wolfSSL_CTX_get_cert_store() returns - makes the object track the context |
2006 | | * instead of pinning that store, so a later |
2007 | | * wolfSSL_CTX_set1_verify_cert_store() changes what this object verifies |
2008 | | * against. OpenSSL's equivalent pins the store. See |
2009 | | * wolfssl_set_verify_cert_store() for why following is preferred here. |
2010 | | * |
2011 | | * @param [in, out] ssl SSL/TLS object. |
2012 | | * @param [in] str Certificate store. NULL to clear. |
2013 | | * @return 1 on success. |
2014 | | * @return 0 when ssl is NULL or on other error. |
2015 | | */ |
2016 | | int wolfSSL_set0_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str) |
2017 | | { |
2018 | | WOLFSSL_ENTER("wolfSSL_set0_verify_cert_store"); |
2019 | | |
2020 | | return wolfssl_set_verify_cert_store(ssl, str, 0); |
2021 | | } |
2022 | | |
2023 | | /* Set certificate store into SSL/TLS object but don't take ownership. |
2024 | | * |
2025 | | * A NULL store clears any store previously set on the object. * |
2026 | | * Passing the store the context is currently using - what |
2027 | | * wolfSSL_CTX_get_cert_store() returns - makes the object track the context |
2028 | | * instead of pinning that store, so a later |
2029 | | * wolfSSL_CTX_set1_verify_cert_store() changes what this object verifies |
2030 | | * against. OpenSSL's equivalent pins the store. See |
2031 | | * wolfssl_set_verify_cert_store() for why following is preferred here. |
2032 | | * |
2033 | | * @param [in, out] ssl SSL/TLS object. |
2034 | | * @param [in] str Certificate store. NULL to clear. |
2035 | | * @return 1 on success. |
2036 | | * @return 0 when ssl is NULL or on other error. |
2037 | | */ |
2038 | | int wolfSSL_set1_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str) |
2039 | | { |
2040 | | WOLFSSL_ENTER("wolfSSL_set1_verify_cert_store"); |
2041 | | |
2042 | | return wolfssl_set_verify_cert_store(ssl, str, 1); |
2043 | | } |
2044 | | #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ |
2045 | | |
2046 | | /* OPENSSL_EXTRA is needed for wolfSSL_X509_d21 function |
2047 | | KEEP_OUR_CERT is to ensure ability to return ssl certificate */ |
2048 | | #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ |
2049 | | defined(KEEP_OUR_CERT) |
2050 | | /* Get the certificate in the SSL/TLS context. |
2051 | | * |
2052 | | * @param [in] ctx SSL/TLS context. |
2053 | | * @return Certificate being sent to peer. |
2054 | | * @return NULL when ctx is NULL, no certificate set or on other error. |
2055 | | */ |
2056 | | WOLFSSL_X509* wolfSSL_CTX_get0_certificate(WOLFSSL_CTX* ctx) |
2057 | | { |
2058 | | WOLFSSL_X509* ret = NULL; |
2059 | | |
2060 | | /* Validate parameters. */ |
2061 | | if (ctx == NULL) { |
2062 | | WOLFSSL_MSG("Invalid parameter"); |
2063 | | } |
2064 | | else { |
2065 | | /* Check if we already have a certificate allocated. */ |
2066 | | if (ctx->ourCert == NULL) { |
2067 | | /* Check if there is a raw certificate. */ |
2068 | | if (ctx->certificate == NULL) { |
2069 | | WOLFSSL_MSG("Ctx Certificate buffer not set!"); |
2070 | | } |
2071 | | #ifndef WOLFSSL_X509_STORE_CERTS |
2072 | | else { |
2073 | | /* Create a certificate object from raw data. */ |
2074 | | ctx->ourCert = wolfSSL_X509_d2i_ex(NULL, |
2075 | | ctx->certificate->buffer, (int)ctx->certificate->length, |
2076 | | ctx->heap); |
2077 | | ctx->ownOurCert = 1; |
2078 | | } |
2079 | | #endif |
2080 | | } |
2081 | | /* Return certificate cached against SSL/TLS context. */ |
2082 | | ret = ctx->ourCert; |
2083 | | } |
2084 | | |
2085 | | return ret; |
2086 | | } |
2087 | | |
2088 | | /* Get the certificate in the SSL/TLS object. |
2089 | | * |
2090 | | * @param [in, out] ssl SSL/TLS object. |
2091 | | * @return Certificate being sent to peer. |
2092 | | * @return NULL when ssl is NULL, no certificate set or on other error. |
2093 | | */ |
2094 | | WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl) |
2095 | | { |
2096 | | WOLFSSL_X509* ret = NULL; |
2097 | | |
2098 | | /* Validate parameters. */ |
2099 | | if (ssl == NULL) { |
2100 | | WOLFSSL_MSG("Invalid parameter"); |
2101 | | } |
2102 | | /* Use certificate in SSL/TLS object if we own it. */ |
2103 | | else if (ssl->buffers.weOwnCert) { |
2104 | | /* Check if we already have a certificate allocated. */ |
2105 | | if (ssl->ourCert == NULL) { |
2106 | | /* Check if ctx has ourCert set - if so, use it instead of creating |
2107 | | * a new X509. This maintains pointer compatibility with |
2108 | | * applications (like nginx OCSP stapling) that use the X509 pointer |
2109 | | * from SSL_CTX_use_certificate as a lookup key. */ |
2110 | | if ((ssl->ctx != NULL) && (ssl->ctx->ourCert != NULL)) { |
2111 | | /* Compare cert buffers to make sure they are the same. The |
2112 | | * SSL may hold the CTX's own buffer (WOLFSSL_DER_REFCOUNT). */ |
2113 | | if ((ssl->buffers.certificate == NULL) || |
2114 | | (ssl->buffers.certificate->buffer == NULL) || |
2115 | | (ssl->buffers.certificate == ssl->ctx->certificate) || |
2116 | | ((ssl->ctx->certificate != NULL) && |
2117 | | (ssl->buffers.certificate->length == |
2118 | | ssl->ctx->certificate->length) && |
2119 | | (XMEMCMP(ssl->buffers.certificate->buffer, |
2120 | | ssl->ctx->certificate->buffer, |
2121 | | ssl->buffers.certificate->length) == 0))) { |
2122 | | return ssl->ctx->ourCert; |
2123 | | } |
2124 | | } |
2125 | | /* We own certificate so this should never happen. */ |
2126 | | if (ssl->buffers.certificate == NULL) { |
2127 | | WOLFSSL_MSG("Certificate buffer not set!"); |
2128 | | } |
2129 | | #ifndef WOLFSSL_X509_STORE_CERTS |
2130 | | else { |
2131 | | /* Create a certificate object from raw data. */ |
2132 | | ssl->ourCert = wolfSSL_X509_d2i_ex(NULL, |
2133 | | ssl->buffers.certificate->buffer, |
2134 | | (int)ssl->buffers.certificate->length, ssl->heap); |
2135 | | } |
2136 | | #endif |
2137 | | } |
2138 | | /* Return certificate cached against SSL/TLS object. */ |
2139 | | ret = ssl->ourCert; |
2140 | | } |
2141 | | else { |
2142 | | /* Use any certificate in SSL/TLS context instead. */ |
2143 | | ret = wolfSSL_CTX_get0_certificate(ssl->ctx); |
2144 | | } |
2145 | | |
2146 | | return ret; |
2147 | | } |
2148 | | #endif /* (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) && KEEP_OUR_CERT */ |
2149 | | |
2150 | | #endif /* !NO_CERTS */ |
2151 | | |
2152 | | #ifndef WOLFCRYPT_ONLY |
2153 | | |
2154 | | #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) |
2155 | | /* Get the index at which the object is stored in an X509 store context's |
2156 | | * external data. |
2157 | | * |
2158 | | * @return Index of the SSL/TLS object (0). |
2159 | | */ |
2160 | | int wolfSSL_get_ex_data_X509_STORE_CTX_idx(void) |
2161 | | { |
2162 | | WOLFSSL_ENTER("wolfSSL_get_ex_data_X509_STORE_CTX_idx"); |
2163 | | |
2164 | | /* store SSL at index 0 */ |
2165 | | return 0; |
2166 | | } |
2167 | | #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ |
2168 | | |
2169 | | |
2170 | | #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ |
2171 | | defined(OPENSSL_ALL) |
2172 | | /* Get the result of peer certificate verification. |
2173 | | * |
2174 | | * @param [in] ssl SSL/TLS object. |
2175 | | * @return Verification result code on success. |
2176 | | * @return WOLFSSL_X509_V_ERR_APPLICATION_VERIFICATION when ssl is NULL. |
2177 | | */ |
2178 | | long wolfSSL_get_verify_result(const WOLFSSL *ssl) |
2179 | | { |
2180 | | long ret; |
2181 | | |
2182 | | if (ssl == NULL) { |
2183 | | /* Return a non-zero error so the OpenSSL-idiomatic |
2184 | | * "!= X509_V_OK" check does not mistake a NULL ssl for a |
2185 | | * successful verification (X509_V_OK is 0). */ |
2186 | | ret = WOLFSSL_X509_V_ERR_APPLICATION_VERIFICATION; |
2187 | | } |
2188 | | else { |
2189 | | /* Result of verifying the peer's certificate chain. */ |
2190 | | ret = (long)ssl->peerVerifyRet; |
2191 | | } |
2192 | | |
2193 | | return ret; |
2194 | | } |
2195 | | #endif |
2196 | | |
2197 | | |
2198 | | #if defined(OPENSSL_EXTRA) && defined(KEEP_PEER_CERT) && \ |
2199 | | defined(HAVE_EX_DATA) && !defined(NO_FILESYSTEM) |
2200 | | /* Compare the peer's certificate against a PEM certificate file. |
2201 | | * |
2202 | | * @param [in] ssl SSL/TLS object. |
2203 | | * @param [in] fname Path to a PEM certificate file. |
2204 | | * @return 0 when the certificates match. |
2205 | | * @return WOLFSSL_FATAL_ERROR when arguments are NULL or they do not match. |
2206 | | * @return WOLFSSL_BAD_FILE when the file cannot be read. |
2207 | | */ |
2208 | | int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname) |
2209 | | { |
2210 | | int ret = 0; |
2211 | | |
2212 | | WOLFSSL_ENTER("wolfSSL_cmp_peer_cert_to_file"); |
2213 | | |
2214 | | if ((ssl == NULL) || (fname == NULL)) { |
2215 | | ret = WOLFSSL_FATAL_ERROR; |
2216 | | } |
2217 | | else { |
2218 | | #ifdef WOLFSSL_SMALL_STACK |
2219 | | byte staticBuffer[1]; /* force heap usage */ |
2220 | | #else |
2221 | | byte staticBuffer[FILE_BUFFER_SIZE]; |
2222 | | #endif |
2223 | | byte* myBuf = staticBuffer; |
2224 | | XFILE file = XBADFILE; |
2225 | | long sz = 0; |
2226 | | void* heap = ssl->ctx->heap; |
2227 | | const DerBuffer* peerDer = GetPeerCertDer(ssl); |
2228 | | DerBuffer* fileDer = NULL; |
2229 | | |
2230 | | /* handle gracefully if called before handshake, or if peer did not |
2231 | | * present a cert. */ |
2232 | | if (peerDer == NULL) { |
2233 | | WOLFSSL_MSG("wolfSSL_cmp_peer_cert_to_file without peer cert"); |
2234 | | ret = WOLFSSL_FATAL_ERROR; |
2235 | | } |
2236 | | |
2237 | | if (ret == 0) { |
2238 | | /* Open the file and determine its size. From here, ret == 0 |
2239 | | * indicates processing is still on track. */ |
2240 | | file = XFOPEN(fname, "rb"); |
2241 | | ret = wolfssl_file_len(file, &sz); |
2242 | | } |
2243 | | /* Use a heap buffer when the file is bigger than the stack buffer. */ |
2244 | | if ((ret == 0) && (sz > (long)sizeof(staticBuffer))) { |
2245 | | WOLFSSL_MSG("Getting dynamic buffer"); |
2246 | | myBuf = (byte*)XMALLOC((size_t)sz, heap, DYNAMIC_TYPE_FILE); |
2247 | | if (myBuf == NULL) { |
2248 | | ret = WOLFSSL_FATAL_ERROR; |
2249 | | } |
2250 | | } |
2251 | | /* Read the whole file into the buffer. */ |
2252 | | if ((ret == 0) && (XFREAD(myBuf, 1, (size_t)sz, file) != (size_t)sz)) { |
2253 | | ret = WOLFSSL_FATAL_ERROR; |
2254 | | } |
2255 | | /* Convert the PEM file contents to DER. */ |
2256 | | if ((ret == 0) && (PemToDer(myBuf, sz, CERT_TYPE, &fileDer, heap, NULL, |
2257 | | NULL) != 0)) { |
2258 | | ret = WOLFSSL_FATAL_ERROR; |
2259 | | } |
2260 | | /* Peer certificate matches when the DER lengths and bytes are equal. */ |
2261 | | if ((ret == 0) && ((fileDer->length == 0) || |
2262 | | (fileDer->length != peerDer->length) || |
2263 | | (XMEMCMP(peerDer->buffer, fileDer->buffer, |
2264 | | fileDer->length) != 0))) { |
2265 | | ret = WOLFSSL_FATAL_ERROR; |
2266 | | } |
2267 | | |
2268 | | /* Dispose of the DER, any heap buffer and close the file. */ |
2269 | | FreeDer(&fileDer); |
2270 | | if (myBuf != staticBuffer) { |
2271 | | XFREE(myBuf, heap, DYNAMIC_TYPE_FILE); |
2272 | | } |
2273 | | if (file != XBADFILE) { |
2274 | | XFCLOSE(file); |
2275 | | } |
2276 | | } |
2277 | | |
2278 | | return ret; |
2279 | | } |
2280 | | #endif |
2281 | | |
2282 | | |
2283 | | #ifdef WOLFSSL_ALT_CERT_CHAINS |
2284 | | /* Determine whether the peer was verified using an alternate cert chain. |
2285 | | * |
2286 | | * @param [in] ssl SSL/TLS object. |
2287 | | * @return 1 when an alternate certificate chain was used. |
2288 | | * @return 0 otherwise, or when ssl is NULL. |
2289 | | */ |
2290 | | int wolfSSL_is_peer_alt_cert_chain(const WOLFSSL* ssl) |
2291 | | { |
2292 | | return (ssl != NULL) && ssl->options.usingAltCertChain; |
2293 | | } |
2294 | | #endif /* WOLFSSL_ALT_CERT_CHAINS */ |
2295 | | |
2296 | | |
2297 | | #ifdef SESSION_CERTS |
2298 | | |
2299 | | #ifdef WOLFSSL_ALT_CERT_CHAINS |
2300 | | /* Get the peer's alternate certificate chain. |
2301 | | * |
2302 | | * @param [in] ssl SSL/TLS object. |
2303 | | * @return Alternate certificate chain on success. |
2304 | | * @return NULL when ssl is NULL. |
2305 | | */ |
2306 | | WOLFSSL_X509_CHAIN* wolfSSL_get_peer_alt_chain(WOLFSSL* ssl) |
2307 | | { |
2308 | | WOLFSSL_X509_CHAIN* chain = NULL; |
2309 | | |
2310 | | WOLFSSL_ENTER("wolfSSL_get_peer_alt_chain"); |
2311 | | |
2312 | | if (ssl != NULL) { |
2313 | | /* The alternate chain is held within the session. */ |
2314 | | chain = &ssl->session->altChain; |
2315 | | } |
2316 | | |
2317 | | return chain; |
2318 | | } |
2319 | | #endif /* WOLFSSL_ALT_CERT_CHAINS */ |
2320 | | |
2321 | | |
2322 | | /* Get the peer's certificate chain. |
2323 | | * |
2324 | | * @param [in] ssl SSL/TLS object. |
2325 | | * @return Certificate chain on success. |
2326 | | * @return NULL when ssl is NULL. |
2327 | | */ |
2328 | | WOLFSSL_X509_CHAIN* wolfSSL_get_peer_chain(WOLFSSL* ssl) |
2329 | | { |
2330 | | WOLFSSL_X509_CHAIN* chain = NULL; |
2331 | | |
2332 | | WOLFSSL_ENTER("wolfSSL_get_peer_chain"); |
2333 | | |
2334 | | if (ssl != NULL) { |
2335 | | /* The peer chain is held within the session. */ |
2336 | | chain = &ssl->session->chain; |
2337 | | } |
2338 | | |
2339 | | return chain; |
2340 | | } |
2341 | | |
2342 | | |
2343 | | /* Get the number of certificates in a certificate chain. |
2344 | | * |
2345 | | * @param [in] chain Certificate chain object. |
2346 | | * @return Number of certificates on success. |
2347 | | * @return 0 when chain is NULL. |
2348 | | */ |
2349 | | int wolfSSL_get_chain_count(WOLFSSL_X509_CHAIN* chain) |
2350 | | { |
2351 | | int count = 0; |
2352 | | |
2353 | | WOLFSSL_ENTER("wolfSSL_get_chain_count"); |
2354 | | |
2355 | | if (chain != NULL) { |
2356 | | /* Number of certificates captured in the chain. */ |
2357 | | count = chain->count; |
2358 | | } |
2359 | | |
2360 | | return count; |
2361 | | } |
2362 | | |
2363 | | |
2364 | | /* Get the length, in bytes, of the DER certificate at an index in a chain. |
2365 | | * |
2366 | | * @param [in] chain Certificate chain object. |
2367 | | * @param [in] idx Index of the certificate in the chain. |
2368 | | * @return Length of the DER certificate in bytes on success. |
2369 | | * @return 0 when chain is NULL or idx is out of range. |
2370 | | */ |
2371 | | int wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN* chain, int idx) |
2372 | | { |
2373 | | int length = 0; |
2374 | | |
2375 | | WOLFSSL_ENTER("wolfSSL_get_chain_length"); |
2376 | | |
2377 | | if ((chain != NULL) && (idx >= 0) && (idx < chain->count)) { |
2378 | | /* DER length of the certificate stored at the given index. */ |
2379 | | length = chain->certs[idx].length; |
2380 | | } |
2381 | | |
2382 | | return length; |
2383 | | } |
2384 | | |
2385 | | |
2386 | | /* Get the DER certificate at an index in a certificate chain. |
2387 | | * |
2388 | | * @param [in] chain Certificate chain object. |
2389 | | * @param [in] idx Index of the certificate in the chain. |
2390 | | * @return Buffer holding the DER certificate on success. |
2391 | | * @return 0 when chain is NULL, idx is out of range or the certificate did |
2392 | | * not fit its slot. |
2393 | | */ |
2394 | | byte* wolfSSL_get_chain_cert(WOLFSSL_X509_CHAIN* chain, int idx) |
2395 | | { |
2396 | | byte* cert = NULL; |
2397 | | |
2398 | | WOLFSSL_ENTER("wolfSSL_get_chain_cert"); |
2399 | | |
2400 | | if ((chain != NULL) && (idx >= 0) && (idx < chain->count) && |
2401 | | (chain->certs[idx].length > 0)) { |
2402 | | /* DER buffer of the certificate stored at the given index. */ |
2403 | | cert = chain->certs[idx].buffer; |
2404 | | } |
2405 | | |
2406 | | return cert; |
2407 | | } |
2408 | | |
2409 | | |
2410 | | /* Decode DER certificate data into a WOLFSSL_X509 object. Defined in |
2411 | | * src/ssl.c. */ |
2412 | | static int DecodeToX509(WOLFSSL_X509* x509, const byte* in, int len); |
2413 | | |
2414 | | /* Get the certificate at an index in a chain as a new X509 object. |
2415 | | * |
2416 | | * The returned object must be freed by the caller with wolfSSL_X509_free(). |
2417 | | * |
2418 | | * @param [in] chain Certificate chain object. |
2419 | | * @param [in] idx Index of the certificate in the chain. |
2420 | | * @return Newly allocated X509 certificate object on success. |
2421 | | * @return NULL when chain is NULL, idx is out of range or on error. |
2422 | | */ |
2423 | | WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx) |
2424 | | { |
2425 | | WOLFSSL_X509* x509 = NULL; |
2426 | | |
2427 | | WOLFSSL_ENTER("wolfSSL_get_chain_X509"); |
2428 | | |
2429 | | if ((chain != NULL) && (idx >= 0) && (idx < chain->count) && |
2430 | | (chain->certs[idx].length > 0)) { |
2431 | | x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL, |
2432 | | DYNAMIC_TYPE_X509); |
2433 | | if (x509 == NULL) { |
2434 | | WOLFSSL_MSG("Failed alloc X509"); |
2435 | | } |
2436 | | else { |
2437 | | /* Pre-init with dynamicMemory=1 so DecodeToX509 skips its own |
2438 | | * InitX509 (and we still own the buffer for X509_free). */ |
2439 | | InitX509(x509, 1, NULL); |
2440 | | if (DecodeToX509(x509, chain->certs[idx].buffer, |
2441 | | chain->certs[idx].length) != 0) { |
2442 | | WOLFSSL_MSG("Failed to decode cert"); |
2443 | | wolfSSL_X509_free(x509); |
2444 | | x509 = NULL; |
2445 | | } |
2446 | | } |
2447 | | } |
2448 | | |
2449 | | return x509; |
2450 | | } |
2451 | | |
2452 | | |
2453 | | /* Get the certificate at an index in a chain as PEM. |
2454 | | * |
2455 | | * When buf is NULL, the length required is returned in outLen. |
2456 | | * |
2457 | | * @param [in] chain Certificate chain object. |
2458 | | * @param [in] idx Index of the certificate in the chain. |
2459 | | * @param [out] buf Buffer to hold PEM. May be NULL to get the length. |
2460 | | * @param [in] inLen Length of buffer in bytes. |
2461 | | * @param [out] outLen Length of PEM data in bytes. |
2462 | | * @return WOLFSSL_SUCCESS on success. |
2463 | | * @return LENGTH_ONLY_E when buf is NULL and outLen has been set. |
2464 | | * @return BAD_FUNC_ARG when a required argument is NULL or idx is invalid. |
2465 | | * @return WOLFSSL_FAILURE on error. |
2466 | | */ |
2467 | | int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx, |
2468 | | unsigned char* buf, int inLen, int* outLen) |
2469 | | { |
2470 | | #ifdef WOLFSSL_DER_TO_PEM |
2471 | | int ret = WOLFSSL_SUCCESS; |
2472 | | |
2473 | | WOLFSSL_ENTER("wolfSSL_get_chain_cert_pem"); |
2474 | | if ((chain == NULL) || (outLen == NULL) || (idx < 0) || |
2475 | | (idx >= wolfSSL_get_chain_count(chain)) || |
2476 | | (chain->certs[idx].length <= 0)) { |
2477 | | ret = BAD_FUNC_ARG; |
2478 | | } |
2479 | | /* Delegate to wc_DerToPem when DER-to-PEM is available. */ |
2480 | | if (ret == WOLFSSL_SUCCESS) { |
2481 | | if (buf == NULL) { |
2482 | | inLen = 0; |
2483 | | } |
2484 | | else if (inLen < 0) { |
2485 | | ret = BAD_FUNC_ARG; |
2486 | | } |
2487 | | } |
2488 | | if (ret == WOLFSSL_SUCCESS) { |
2489 | | int n = wc_DerToPem(chain->certs[idx].buffer, |
2490 | | (word32)chain->certs[idx].length, buf, (word32)inLen, CERT_TYPE); |
2491 | | if (n < 0) { |
2492 | | if (buf == NULL) { |
2493 | | ret = WOLFSSL_FAILURE; |
2494 | | } |
2495 | | else { |
2496 | | ret = n; |
2497 | | } |
2498 | | } |
2499 | | else { |
2500 | | *outLen = n; |
2501 | | if (buf == NULL) { |
2502 | | ret = WC_NO_ERR_TRACE(LENGTH_ONLY_E); |
2503 | | } |
2504 | | } |
2505 | | } |
2506 | | |
2507 | | return ret; |
2508 | | #elif defined(WOLFSSL_PEM_TO_DER) |
2509 | | int ret = WOLFSSL_SUCCESS; |
2510 | | const char* header = NULL; |
2511 | | const char* footer = NULL; |
2512 | | int headerLen; |
2513 | | int footerLen; |
2514 | | int i; |
2515 | | int err; |
2516 | | |
2517 | | WOLFSSL_ENTER("wolfSSL_get_chain_cert_pem"); |
2518 | | if ((chain == NULL) || (outLen == NULL) || (idx < 0) || |
2519 | | (idx >= wolfSSL_get_chain_count(chain)) || |
2520 | | (chain->certs[idx].length <= 0)) { |
2521 | | ret = BAD_FUNC_ARG; |
2522 | | } |
2523 | | if (ret == WOLFSSL_SUCCESS) { |
2524 | | if ((err = wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer)) != 0) { |
2525 | | ret = err; |
2526 | | } |
2527 | | } |
2528 | | if (ret == WOLFSSL_SUCCESS) { |
2529 | | headerLen = (int)XSTRLEN(header); |
2530 | | footerLen = (int)XSTRLEN(footer); |
2531 | | |
2532 | | /* Null output buffer returns size needed in outLen. */ |
2533 | | if (buf == NULL) { |
2534 | | word32 szNeeded = 0; |
2535 | | |
2536 | | if (Base64_Encode(chain->certs[idx].buffer, |
2537 | | (word32)chain->certs[idx].length, NULL, |
2538 | | &szNeeded) != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { |
2539 | | ret = WOLFSSL_FAILURE; |
2540 | | } |
2541 | | else { |
2542 | | *outLen = (int)szNeeded + headerLen + footerLen; |
2543 | | ret = WC_NO_ERR_TRACE(LENGTH_ONLY_E); |
2544 | | } |
2545 | | } |
2546 | | /* buf == NULL, ret will not be WOLFSSL_SUCCESS. */ |
2547 | | } |
2548 | | /* Don't even try when inLen is too short. */ |
2549 | | if ((ret == WOLFSSL_SUCCESS) && |
2550 | | (inLen < headerLen + footerLen + chain->certs[idx].length)) { |
2551 | | ret = BAD_FUNC_ARG; |
2552 | | } |
2553 | | if (ret == WOLFSSL_SUCCESS) { |
2554 | | /* Write the PEM header. */ |
2555 | | XMEMCPY(buf, header, (size_t)headerLen); |
2556 | | i = headerLen; |
2557 | | |
2558 | | /* Space left for Base64 data after header and before footer. */ |
2559 | | *outLen = inLen - headerLen - footerLen; |
2560 | | if ((err = Base64_Encode(chain->certs[idx].buffer, |
2561 | | (word32)chain->certs[idx].length, buf + i, |
2562 | | (word32*)outLen)) < 0) { |
2563 | | ret = err; |
2564 | | } |
2565 | | } |
2566 | | if (ret == WOLFSSL_SUCCESS) { |
2567 | | i += *outLen; |
2568 | | |
2569 | | /* Write the PEM footer. */ |
2570 | | XMEMCPY(buf + i, footer, (size_t)footerLen); |
2571 | | *outLen += headerLen + footerLen; |
2572 | | } |
2573 | | |
2574 | | return ret; |
2575 | | #else |
2576 | | (void)chain; |
2577 | | (void)idx; |
2578 | | (void)buf; |
2579 | | (void)inLen; |
2580 | | (void)outLen; |
2581 | | return WOLFSSL_FAILURE; |
2582 | | #endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */ |
2583 | | } |
2584 | | |
2585 | | #endif /* SESSION_CERTS */ |
2586 | | |
2587 | | |
2588 | | #if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) \ |
2589 | | || defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT) |
2590 | | #ifndef NO_WOLFSSL_STUB |
2591 | | /* Clear the extra certificate chain set on the context. |
2592 | | * |
2593 | | * Not implemented - stub for OpenSSL compatibility. |
2594 | | * |
2595 | | * @param [in] ctx SSL/TLS context object. |
2596 | | * @return Result of the SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS control command. |
2597 | | */ |
2598 | | long wolfSSL_CTX_clear_extra_chain_certs(WOLFSSL_CTX* ctx) |
2599 | | { |
2600 | | return wolfSSL_CTX_ctrl(ctx, SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS, 0L, NULL); |
2601 | | } |
2602 | | #endif |
2603 | | |
2604 | | /* Get the verify callback set on the object. |
2605 | | * |
2606 | | * @param [in] ssl SSL/TLS object. |
2607 | | * @return Verify callback on success. |
2608 | | * @return NULL when ssl is NULL or no callback is set. |
2609 | | */ |
2610 | | VerifyCallback wolfSSL_get_verify_callback(WOLFSSL* ssl) |
2611 | | { |
2612 | | VerifyCallback cb = NULL; |
2613 | | |
2614 | | WOLFSSL_ENTER("wolfSSL_get_verify_callback"); |
2615 | | |
2616 | | if (ssl != NULL) { |
2617 | | /* Verify callback configured on the object. */ |
2618 | | cb = ssl->verifyCallback; |
2619 | | } |
2620 | | |
2621 | | return cb; |
2622 | | } |
2623 | | |
2624 | | #endif |
2625 | | |
2626 | | #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) |
2627 | | /* Get the verify callback set on the context. |
2628 | | * |
2629 | | * @param [in] ctx SSL/TLS context object. |
2630 | | * @return Verify callback on success. |
2631 | | * @return NULL when ctx is NULL or no callback is set. |
2632 | | */ |
2633 | | VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX* ctx) |
2634 | | { |
2635 | | VerifyCallback cb = NULL; |
2636 | | |
2637 | | WOLFSSL_ENTER("wolfSSL_CTX_get_verify_callback"); |
2638 | | |
2639 | | if (ctx != NULL) { |
2640 | | /* Verify callback configured on the context. */ |
2641 | | cb = ctx->verifyCallback; |
2642 | | } |
2643 | | |
2644 | | return cb; |
2645 | | } |
2646 | | |
2647 | | #endif |
2648 | | |
2649 | | #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || defined(HAVE_STUNNEL) || \ |
2650 | | defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) |
2651 | | |
2652 | | /* Get the verification mode set on the object. |
2653 | | * |
2654 | | * WOLFSSL_VERIFY_CLIENT_ONCE is never reported: wolfSSL_set_verify() accepts |
2655 | | * and ignores it rather than storing it. Neither is WOLFSSL_VERIFY_DEFAULT - |
2656 | | * it clears every option, so a mode of 0 is returned for it. |
2657 | | * |
2658 | | * @param [in] ssl SSL/TLS object. |
2659 | | * @return Bitmask of WOLFSSL_VERIFY_* flags on success. |
2660 | | * @return WOLFSSL_FAILURE when ssl is NULL. |
2661 | | */ |
2662 | | int wolfSSL_get_verify_mode(const WOLFSSL* ssl) |
2663 | | { |
2664 | | int mode = 0; |
2665 | | |
2666 | | WOLFSSL_ENTER("wolfSSL_get_verify_mode"); |
2667 | | |
2668 | | if (ssl == NULL) { |
2669 | | mode = WOLFSSL_FAILURE; |
2670 | | } |
2671 | | else if (ssl->options.verifyNone) { |
2672 | | /* VERIFY_NONE is exclusive of the other verify flags. */ |
2673 | | mode = WOLFSSL_VERIFY_NONE; |
2674 | | } |
2675 | | else { |
2676 | | /* Build the mode as a bitmask of the enabled verify flags. */ |
2677 | | if (ssl->options.verifyPeer) { |
2678 | | mode |= WOLFSSL_VERIFY_PEER; |
2679 | | } |
2680 | | if (ssl->options.failNoCert) { |
2681 | | mode |= WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT; |
2682 | | } |
2683 | | if (ssl->options.failNoCertxPSK) { |
2684 | | mode |= WOLFSSL_VERIFY_FAIL_EXCEPT_PSK; |
2685 | | } |
2686 | | #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) |
2687 | | if (ssl->options.verifyPostHandshake) { |
2688 | | mode |= WOLFSSL_VERIFY_POST_HANDSHAKE; |
2689 | | } |
2690 | | #endif |
2691 | | } |
2692 | | |
2693 | | WOLFSSL_LEAVE("wolfSSL_get_verify_mode", mode); |
2694 | | return mode; |
2695 | | } |
2696 | | |
2697 | | /* Get the verification mode set on the context. |
2698 | | * |
2699 | | * WOLFSSL_VERIFY_CLIENT_ONCE is never reported: wolfSSL_CTX_set_verify() |
2700 | | * accepts and ignores it rather than storing it. Neither is |
2701 | | * WOLFSSL_VERIFY_DEFAULT - it clears every option, so a mode of 0 is |
2702 | | * returned for it. |
2703 | | * |
2704 | | * @param [in] ctx SSL/TLS context object. |
2705 | | * @return Bitmask of WOLFSSL_VERIFY_* flags on success. |
2706 | | * @return WOLFSSL_FAILURE when ctx is NULL. |
2707 | | */ |
2708 | | int wolfSSL_CTX_get_verify_mode(const WOLFSSL_CTX* ctx) |
2709 | | { |
2710 | | int mode = 0; |
2711 | | |
2712 | | WOLFSSL_ENTER("wolfSSL_CTX_get_verify_mode"); |
2713 | | |
2714 | | if (ctx == NULL) { |
2715 | | mode = WOLFSSL_FAILURE; |
2716 | | } |
2717 | | else if (ctx->verifyNone) { |
2718 | | /* VERIFY_NONE is exclusive of the other verify flags. */ |
2719 | | mode = WOLFSSL_VERIFY_NONE; |
2720 | | } |
2721 | | else { |
2722 | | /* Build the mode as a bitmask of the enabled verify flags. */ |
2723 | | if (ctx->verifyPeer) { |
2724 | | mode |= WOLFSSL_VERIFY_PEER; |
2725 | | } |
2726 | | if (ctx->failNoCert) { |
2727 | | mode |= WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT; |
2728 | | } |
2729 | | if (ctx->failNoCertxPSK) { |
2730 | | mode |= WOLFSSL_VERIFY_FAIL_EXCEPT_PSK; |
2731 | | } |
2732 | | #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) |
2733 | | if (ctx->verifyPostHandshake) { |
2734 | | mode |= WOLFSSL_VERIFY_POST_HANDSHAKE; |
2735 | | } |
2736 | | #endif |
2737 | | } |
2738 | | |
2739 | | WOLFSSL_LEAVE("wolfSSL_CTX_get_verify_mode", mode); |
2740 | | return mode; |
2741 | | } |
2742 | | |
2743 | | #endif |
2744 | | |
2745 | | |
2746 | | #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ |
2747 | | defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) |
2748 | | /* Create a stack of X509 certificates from a DER encoded certificate chain. |
2749 | | * |
2750 | | * The chain buffer holds each certificate as: 3 byte length | X509 DER data. |
2751 | | * |
2752 | | * @param [in] der DER encoded certificate chain. |
2753 | | * @param [in] derLen Length of certificate chain buffer in bytes. |
2754 | | * @param [in] heap Dynamic memory hint. |
2755 | | * @param [out] chain Stack of X509 certificates. Holds as much of the |
2756 | | * chain as was created on failure. |
2757 | | * @return WOLFSSL_SUCCESS on success. |
2758 | | * @return WOLFSSL_FAILURE on allocation or decode error. |
2759 | | */ |
2760 | | static int wolfssl_certchain_to_x509_stack(byte* der, word32 derLen, |
2761 | | void* heap, WOLF_STACK_OF(X509)** chain) |
2762 | | { |
2763 | | int ret = WOLFSSL_SUCCESS; |
2764 | | word32 idx; |
2765 | | word32 length; |
2766 | | WOLFSSL_STACK* node; |
2767 | | WOLFSSL_STACK* last = NULL; |
2768 | | |
2769 | | /* Create a new stack of WOLFSSL_X509 object from chain buffer. */ |
2770 | | for (idx = 0; idx < derLen; ) { |
2771 | | /* Need 3 bytes for the length of the DER encoded certificate. */ |
2772 | | if ((derLen - idx) < 3) { |
2773 | | ret = WOLFSSL_FAILURE; |
2774 | | break; |
2775 | | } |
2776 | | |
2777 | | /* Format: 3 byte length | X509 DER data. */ |
2778 | | ato24(der + idx, &length); |
2779 | | idx += 3; |
2780 | | |
2781 | | /* Ensure the DER encoded certificate is contained in the buffer. */ |
2782 | | if (length > (derLen - idx)) { |
2783 | | ret = WOLFSSL_FAILURE; |
2784 | | break; |
2785 | | } |
2786 | | |
2787 | | node = wolfSSL_sk_X509_new_null(); |
2788 | | if (node == NULL) { |
2789 | | ret = WOLFSSL_FAILURE; |
2790 | | break; |
2791 | | } |
2792 | | node->next = NULL; |
2793 | | |
2794 | | /* Create a new X509 from DER encoded data. */ |
2795 | | node->data.x509 = wolfSSL_X509_d2i_ex(NULL, der + idx, (int)length, |
2796 | | heap); |
2797 | | if (node->data.x509 == NULL) { |
2798 | | XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL); |
2799 | | /* Return as much of the chain as we created. */ |
2800 | | ret = WOLFSSL_FAILURE; |
2801 | | break; |
2802 | | } |
2803 | | idx += length; |
2804 | | |
2805 | | /* Add object to the end of the stack. */ |
2806 | | if (last == NULL) { |
2807 | | node->num = 1; |
2808 | | *chain = node; |
2809 | | } |
2810 | | else { |
2811 | | (*chain)->num++; |
2812 | | last->next = node; |
2813 | | } |
2814 | | |
2815 | | last = node; |
2816 | | } |
2817 | | |
2818 | | return ret; |
2819 | | } |
2820 | | |
2821 | | /* Get the extra certificate chain set on the context as a stack of X509. |
2822 | | * |
2823 | | * Builds the stack from the context's certificate chain buffer when needed. |
2824 | | * |
2825 | | * @param [in] ctx SSL/TLS context object. |
2826 | | * @param [out] chain Stack of X509 certificates. |
2827 | | * @return WOLFSSL_SUCCESS on success. |
2828 | | * @return WOLFSSL_FAILURE when ctx or chain is NULL, or on allocation error. |
2829 | | */ |
2830 | | int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx, |
2831 | | WOLF_STACK_OF(X509)** chain) |
2832 | | { |
2833 | | int ret = WOLFSSL_SUCCESS; |
2834 | | |
2835 | | if ((ctx == NULL) || (chain == NULL)) { |
2836 | | ret = WOLFSSL_FAILURE; |
2837 | | } |
2838 | | else if (ctx->x509Chain != NULL) { |
2839 | | *chain = ctx->x509Chain; |
2840 | | } |
2841 | | else { |
2842 | | /* If there are no chains then success! */ |
2843 | | *chain = NULL; |
2844 | | if ((ctx->certChain != NULL) && (ctx->certChain->length != 0)) { |
2845 | | /* Build a stack of X509 from the DER certificate chain buffer. */ |
2846 | | ret = wolfssl_certchain_to_x509_stack(ctx->certChain->buffer, |
2847 | | ctx->certChain->length, ctx->heap, chain); |
2848 | | /* Cache the chain - holds as much as was created on failure. */ |
2849 | | ctx->x509Chain = *chain; |
2850 | | } |
2851 | | } |
2852 | | |
2853 | | return ret; |
2854 | | } |
2855 | | |
2856 | | /* Get the certificate chain set on the context. |
2857 | | * |
2858 | | * @param [in] ctx SSL/TLS context object. |
2859 | | * @param [out] sk Stack of X509 certificates. |
2860 | | * @return WOLFSSL_SUCCESS on success. |
2861 | | * @return WOLFSSL_FAILURE when ctx or sk is NULL. |
2862 | | */ |
2863 | | int wolfSSL_CTX_get0_chain_certs(WOLFSSL_CTX *ctx, |
2864 | | WOLF_STACK_OF(WOLFSSL_X509) **sk) |
2865 | | { |
2866 | | int ret; |
2867 | | |
2868 | | WOLFSSL_ENTER("wolfSSL_CTX_get0_chain_certs"); |
2869 | | |
2870 | | if ((ctx == NULL) || (sk == NULL)) { |
2871 | | WOLFSSL_MSG("Bad parameter"); |
2872 | | ret = WOLFSSL_FAILURE; |
2873 | | } |
2874 | | else { |
2875 | | /* This function should return ctx->x509Chain if it is populated, |
2876 | | * otherwise it should be populated from ctx->certChain. This matches |
2877 | | * the behavior of wolfSSL_CTX_get_extra_chain_certs, so it is used |
2878 | | * directly. */ |
2879 | | ret = wolfSSL_CTX_get_extra_chain_certs(ctx, sk); |
2880 | | } |
2881 | | |
2882 | | return ret; |
2883 | | } |
2884 | | |
2885 | | #ifdef KEEP_OUR_CERT |
2886 | | /* Get our certificate chain set on the object. |
2887 | | * |
2888 | | * @param [in] ssl SSL/TLS object. |
2889 | | * @param [out] sk Stack of X509 certificates. |
2890 | | * @return WOLFSSL_SUCCESS on success. |
2891 | | * @return WOLFSSL_FAILURE when ssl or sk is NULL. |
2892 | | */ |
2893 | | int wolfSSL_get0_chain_certs(WOLFSSL *ssl, WOLF_STACK_OF(WOLFSSL_X509) **sk) |
2894 | | { |
2895 | | int ret = WOLFSSL_SUCCESS; |
2896 | | |
2897 | | WOLFSSL_ENTER("wolfSSL_get0_chain_certs"); |
2898 | | |
2899 | | if ((ssl == NULL) || (sk == NULL)) { |
2900 | | WOLFSSL_MSG("Bad parameter"); |
2901 | | ret = WOLFSSL_FAILURE; |
2902 | | } |
2903 | | else { |
2904 | | /* Return our own certificate chain held on the object. */ |
2905 | | *sk = ssl->ourCertChain; |
2906 | | } |
2907 | | |
2908 | | return ret; |
2909 | | } |
2910 | | #endif |
2911 | | |
2912 | | #endif |
2913 | | |
2914 | | #ifdef WOLFSSL_CERT_SETUP_CB |
2915 | | /* ctx->CBClientCert is only in the structure under OPENSSL_EXTRA, so the |
2916 | | * setter cannot be compiled more widely than that. */ |
2917 | | #ifdef OPENSSL_EXTRA |
2918 | | /* Set the callback that supplies a client certificate and key. |
2919 | | * |
2920 | | * Called during the handshake when the server asks for client authentication |
2921 | | * and no certificate and key have been loaded. |
2922 | | * |
2923 | | * @param [in, out] ctx SSL/TLS CTX object. |
2924 | | * @param [in] cb Callback to call. NULL to clear. |
2925 | | */ |
2926 | | void wolfSSL_CTX_set_client_cert_cb(WOLFSSL_CTX *ctx, client_cert_cb cb) |
2927 | | { |
2928 | | WOLFSSL_ENTER("wolfSSL_CTX_set_client_cert_cb"); |
2929 | | |
2930 | | if (ctx != NULL) { |
2931 | | ctx->CBClientCert = cb; |
2932 | | } |
2933 | | } |
2934 | | #endif |
2935 | | |
2936 | | /* Set the certificate setup callback on the SSL/TLS CTX object. |
2937 | | * |
2938 | | * The callback is called during the handshake to allow the certificate and |
2939 | | * key to be chosen or loaded on demand. |
2940 | | * |
2941 | | * @param [in, out] ctx SSL/TLS CTX object. |
2942 | | * @param [in] cb Certificate setup callback. NULL to clear. |
2943 | | * @param [in] arg Context to pass to the callback. |
2944 | | */ |
2945 | | void wolfSSL_CTX_set_cert_cb(WOLFSSL_CTX* ctx, |
2946 | | CertSetupCallback cb, void *arg) |
2947 | | { |
2948 | | WOLFSSL_ENTER("wolfSSL_CTX_set_cert_cb"); |
2949 | | |
2950 | | if (ctx != NULL) { |
2951 | | ctx->certSetupCb = cb; |
2952 | | ctx->certSetupCbArg = arg; |
2953 | | } |
2954 | | } |
2955 | | |
2956 | | /* Call the certificate setup callback and translate its result. |
2957 | | * |
2958 | | * @param [in, out] ssl SSL/TLS object. |
2959 | | * @return 0 when no callback is set or the callback reported success. |
2960 | | * @return CLIENT_CERT_CB_ERROR when the callback failed or returned an |
2961 | | * unrecognized value. A fatal alert is sent when it failed. |
2962 | | * @return WOLFSSL_ERROR_WANT_X509_LOOKUP when the callback returned a |
2963 | | * negative value to ask to be called again. |
2964 | | * @return BAD_STATE_E when the callback replaced a certificate or key on the |
2965 | | * CTX that the SSL uses. A fatal alert is sent. |
2966 | | */ |
2967 | | int CertSetupCbWrapper(WOLFSSL* ssl) |
2968 | | { |
2969 | | int ret = 0; |
2970 | | |
2971 | | if (ssl->ctx->certSetupCb != NULL) { |
2972 | | WOLFSSL_MSG("Calling user cert setup callback"); |
2973 | | ret = ssl->ctx->certSetupCb(ssl, ssl->ctx->certSetupCbArg); |
2974 | | #ifndef NO_CERTS |
2975 | | if (CheckSSL_CTX_CertsAndKeys(ssl) != 0) { |
2976 | | SendAlert(ssl, alert_fatal, internal_error); |
2977 | | return BAD_STATE_E; |
2978 | | } |
2979 | | #endif |
2980 | | if (ret == 1) { |
2981 | | WOLFSSL_MSG("User cert callback returned success"); |
2982 | | ret = 0; |
2983 | | } |
2984 | | else if (ret == 0) { |
2985 | | SendAlert(ssl, alert_fatal, internal_error); |
2986 | | ret = CLIENT_CERT_CB_ERROR; |
2987 | | } |
2988 | | else if (ret < 0) { |
2989 | | ret = WOLFSSL_ERROR_WANT_X509_LOOKUP; |
2990 | | } |
2991 | | else { |
2992 | | WOLFSSL_MSG("Unexpected user callback return"); |
2993 | | ret = CLIENT_CERT_CB_ERROR; |
2994 | | } |
2995 | | } |
2996 | | return ret; |
2997 | | } |
2998 | | #endif /* WOLFSSL_CERT_SETUP_CB */ |
2999 | | |
3000 | | |
3001 | | #ifdef SESSION_CERTS |
3002 | | /* Decode the X509 DER encoded certificate into a WOLFSSL_X509 object. |
3003 | | * |
3004 | | * @param [in, out] x509 WOLFSSL_X509 object to decode into. |
3005 | | * @param [in] in X509 DER data. |
3006 | | * @param [in] len Length of the X509 DER data. |
3007 | | * @return 0 on success. |
3008 | | * @return BAD_FUNC_ARG when x509 or in is NULL, or len is not positive. |
3009 | | * @return MEMORY_E when dynamic memory allocation fails. |
3010 | | * @return Other negative value when the certificate cannot be parsed. |
3011 | | */ |
3012 | | static int DecodeToX509(WOLFSSL_X509* x509, const byte* in, int len) |
3013 | | { |
3014 | | int ret = 0; |
3015 | | WC_DECLARE_VAR(cert, DecodedCert, 1, 0); |
3016 | | |
3017 | | /* Validate parameters. */ |
3018 | | if ((x509 == NULL) || (in == NULL) || (len <= 0)) { |
3019 | | ret = BAD_FUNC_ARG; |
3020 | | } |
3021 | | |
3022 | | if (ret == 0) { |
3023 | | WC_ALLOC_VAR_EX(cert, DecodedCert, 1, NULL, DYNAMIC_TYPE_DCERT, |
3024 | | ret = MEMORY_E); |
3025 | | } |
3026 | | |
3027 | | if (ret == 0) { |
3028 | | /* Create a DecodedCert object and copy fields into WOLFSSL_X509 |
3029 | | * object. */ |
3030 | | InitDecodedCert(cert, (byte*)in, (word32)len, NULL); |
3031 | | ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL, NULL); |
3032 | | if (ret == 0) { |
3033 | | /* Check if x509 was not previously initialized by wolfSSL_X509_new() */ |
3034 | | if (x509->dynamicMemory != TRUE) { |
3035 | | /* A non-dynamic x509 (e.g. ssl->peerCert) may already hold |
3036 | | * decoded contents; free them before re-populating. ReinitX509 |
3037 | | * keeps the object's heap and reference state, as the object |
3038 | | * may be referenced elsewhere. */ |
3039 | | ReinitX509(x509); |
3040 | | } |
3041 | | ret = CopyDecodedToX509(x509, cert); |
3042 | | } |
3043 | | FreeDecodedCert(cert); |
3044 | | WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT); |
3045 | | } |
3046 | | |
3047 | | return ret; |
3048 | | } |
3049 | | #endif /* SESSION_CERTS */ |
3050 | | |
3051 | | |
3052 | | #ifdef KEEP_PEER_CERT |
3053 | | /* Get the kept peer certificate, owned by the SSL/TLS object. |
3054 | | * |
3055 | | * The certificate is built from its kept encoding on first use. Otherwise it |
3056 | | * is decoded from the session chain, and kept, when not already available on |
3057 | | * the object. |
3058 | | * |
3059 | | * @param [in, out] ssl SSL/TLS object. |
3060 | | * @return Kept peer certificate on success. |
3061 | | * @return NULL when no peer certificate is available or it cannot be |
3062 | | * decoded. |
3063 | | */ |
3064 | | static WOLFSSL_X509* LoadPeerCert(WOLFSSL* ssl) |
3065 | | { |
3066 | | WOLFSSL_X509* peer = GetPeerCert(ssl); |
3067 | | |
3068 | | #ifdef SESSION_CERTS |
3069 | | if (((peer == NULL) || (peer->issuer.sz == 0)) && |
3070 | | (ssl->session->chain.count > 0)) { |
3071 | | #ifdef WOLFSSL_DYNAMIC_PEER_CERT |
3072 | | WOLFSSL_X509* x509 = wolfSSL_X509_new_ex(ssl->heap); |
3073 | | if ((x509 != NULL) && (DecodeToX509(x509, |
3074 | | ssl->session->chain.certs[0].buffer, |
3075 | | ssl->session->chain.certs[0].length) == 0)) { |
3076 | | FreePeerCert(ssl); |
3077 | | ssl->peerCert = x509; |
3078 | | peer = x509; |
3079 | | } |
3080 | | else { |
3081 | | wolfSSL_X509_free(x509); |
3082 | | peer = NULL; |
3083 | | } |
3084 | | #else |
3085 | | if (DecodeToX509(peer, ssl->session->chain.certs[0].buffer, |
3086 | | ssl->session->chain.certs[0].length) != 0) { |
3087 | | peer = NULL; |
3088 | | } |
3089 | | #endif |
3090 | | } |
3091 | | #endif |
3092 | | if ((peer != NULL) && (peer->issuer.sz == 0)) { |
3093 | | peer = NULL; |
3094 | | } |
3095 | | |
3096 | | return peer; |
3097 | | } |
3098 | | |
3099 | | /* Get the peer's certificate. |
3100 | | * |
3101 | | * The certificate is decoded from the session chain, and kept, when not |
3102 | | * already available on the object. With WOLFSSL_DYNAMIC_PEER_CERT and X509 |
3103 | | * reference counting (OPENSSL_EXTRA or OPENSSL_EXTRA_X509_SMALL) the kept |
3104 | | * object is returned with a new reference, as OpenSSL does; otherwise a copy |
3105 | | * is returned. Either way the caller must free the returned certificate with |
3106 | | * wolfSSL_X509_free() and it stays valid after the SSL/TLS object is freed. |
3107 | | * |
3108 | | * @param [in, out] ssl SSL/TLS object. |
3109 | | * @return Peer's X509 certificate on success. |
3110 | | * @return NULL when ssl is NULL, no peer certificate was kept or dynamic |
3111 | | * memory allocation fails. |
3112 | | */ |
3113 | | WOLFSSL_ABI |
3114 | | WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl) |
3115 | | { |
3116 | | WOLFSSL_X509* ret = NULL; |
3117 | | WOLFSSL_X509* peer = NULL; |
3118 | | |
3119 | | WOLFSSL_ENTER("wolfSSL_get_peer_certificate"); |
3120 | | |
3121 | | if (ssl != NULL) { |
3122 | | peer = LoadPeerCert(ssl); |
3123 | | } |
3124 | | if (peer != NULL) { |
3125 | | #if defined(WOLFSSL_DYNAMIC_PEER_CERT) && \ |
3126 | | (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) |
3127 | | if (wolfSSL_X509_up_ref(peer) == WOLFSSL_SUCCESS) { |
3128 | | ret = peer; |
3129 | | } |
3130 | | #else |
3131 | | ret = wolfSSL_X509_dup(peer); |
3132 | | #endif |
3133 | | } |
3134 | | WOLFSSL_LEAVE("wolfSSL_get_peer_certificate", ret != NULL); |
3135 | | return ret; |
3136 | | } |
3137 | | |
3138 | | #endif /* KEEP_PEER_CERT */ |
3139 | | |
3140 | | /* NO_CERTS is part of the guard so that the declaration of |
3141 | | * x509GetIssuerFromCM() in src/ssl.c, its definition in src/x509_str.c and |
3142 | | * the call below all agree on when they exist. */ |
3143 | | #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) && !defined(NO_CERTS) |
3144 | | /* Get the stack of the peer's certificates. |
3145 | | * |
3146 | | * The stack is owned by the SSL/TLS object and is disposed of with it, so the |
3147 | | * caller must not free it. |
3148 | | * |
3149 | | * @param [in, out] ssl SSL/TLS object. Declared const, but the chain is |
3150 | | * built into it on the first call. |
3151 | | * @return Stack of the peer's certificates on success. |
3152 | | * @return NULL when ssl is NULL or no chain was received. |
3153 | | */ |
3154 | | WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL* ssl) |
3155 | | { |
3156 | | WOLF_STACK_OF(WOLFSSL_X509)* ret = NULL; |
3157 | | |
3158 | | WOLFSSL_ENTER("wolfSSL_get_peer_cert_chain"); |
3159 | | |
3160 | | if (ssl != NULL) { |
3161 | | /* Try to populate when not present or empty. */ |
3162 | | if ((ssl->peerCertChain == NULL) || |
3163 | | (wolfSSL_sk_X509_num(ssl->peerCertChain) == 0)) { |
3164 | | wolfSSL_set_peer_cert_chain((WOLFSSL*)ssl); |
3165 | | } |
3166 | | ret = ssl->peerCertChain; |
3167 | | } |
3168 | | |
3169 | | return ret; |
3170 | | } |
3171 | | |
3172 | | /* Push the chain of issuing CAs onto the stack. |
3173 | | * |
3174 | | * Each certificate's issuer is looked up in turn, stopping when no further |
3175 | | * issuer is known or the maximum chain depth is reached. |
3176 | | * |
3177 | | * @param [in] cm Certificate manager queried for each issuer. |
3178 | | * @param [in] x Certificate whose issuer is looked up first. |
3179 | | * @param [in, out] sk Stack the issuers are pushed onto. |
3180 | | * @return 0 on success or when no issuer was found. |
3181 | | * @return WOLFSSL_FATAL_ERROR when an issuer could not be pushed. |
3182 | | */ |
3183 | | static int PushCAx509Chain(WOLFSSL_CERT_MANAGER* cm, |
3184 | | WOLFSSL_X509 *x, WOLFSSL_STACK* sk) |
3185 | | { |
3186 | | int ret = 0; |
3187 | | int i; |
3188 | | |
3189 | | for (i = 0; (ret == 0) && (i < MAX_CHAIN_DEPTH); i++) { |
3190 | | WOLFSSL_X509* issuer = NULL; |
3191 | | |
3192 | | /* No more issuers known - chain is as complete as it can be. */ |
3193 | | if (x509GetIssuerFromCM(&issuer, cm, x) != WOLFSSL_SUCCESS) { |
3194 | | break; |
3195 | | } |
3196 | | if (wolfSSL_sk_X509_push(sk, issuer) <= 0) { |
3197 | | /* Not stored on the stack - dispose of it here. */ |
3198 | | wolfSSL_X509_free(issuer); |
3199 | | ret = WOLFSSL_FATAL_ERROR; |
3200 | | } |
3201 | | else { |
3202 | | x = issuer; |
3203 | | } |
3204 | | } |
3205 | | |
3206 | | return ret; |
3207 | | } |
3208 | | |
3209 | | |
3210 | | /* Decode one certificate of the session chain onto the stack. |
3211 | | * |
3212 | | * A certificate that did not fit its slot holds an empty one. The peer's own |
3213 | | * certificate, index 0, is taken from the copy kept on the SSL/TLS object |
3214 | | * instead; any other is left out of the stack, as it was before it had a slot. |
3215 | | * |
3216 | | * @param [in, out] ssl SSL/TLS object. The kept peer certificate may be |
3217 | | * built from its encoding. |
3218 | | * @param [in] idx Index of the certificate in the chain. |
3219 | | * @param [in, out] sk Stack to add the certificate to. |
3220 | | * @param [out] pushed Certificate added to the stack, NULL when the slot |
3221 | | * was empty. Owned by the stack. |
3222 | | * @return 0 on success. |
3223 | | * @return MEMORY_E when the certificate object cannot be created. |
3224 | | * @return Other negative value when the certificate cannot be decoded or |
3225 | | * stored. |
3226 | | */ |
3227 | | static int PushPeerCertToChain(WOLFSSL* ssl, int idx, WOLFSSL_STACK* sk, |
3228 | | WOLFSSL_X509** pushed) |
3229 | | { |
3230 | | int ret = 0; |
3231 | | WOLFSSL_X509* x509 = NULL; |
3232 | | |
3233 | | *pushed = NULL; |
3234 | | |
3235 | | if (ssl->session->chain.certs[idx].length == 0) { |
3236 | | #ifdef KEEP_PEER_CERT |
3237 | | WOLFSSL_X509* peer = (idx == 0) ? GetPeerCert(ssl) : NULL; |
3238 | | |
3239 | | if ((peer != NULL) && (peer->issuer.sz > 0)) { |
3240 | | x509 = wolfSSL_X509_dup(peer); |
3241 | | if (x509 == NULL) { |
3242 | | WOLFSSL_MSG("Error duplicating peer certificate"); |
3243 | | ret = MEMORY_E; |
3244 | | } |
3245 | | } |
3246 | | #endif |
3247 | | if ((ret == 0) && (x509 == NULL)) { |
3248 | | /* An issuer must never slide into the leaf's slot. */ |
3249 | | if (idx == 0) { |
3250 | | return WOLFSSL_FATAL_ERROR; |
3251 | | } |
3252 | | /* Nothing to add for this index. */ |
3253 | | return 0; |
3254 | | } |
3255 | | } |
3256 | | else { |
3257 | | x509 = wolfSSL_X509_new_ex(ssl->heap); |
3258 | | if (x509 == NULL) { |
3259 | | WOLFSSL_MSG("Error Creating X509"); |
3260 | | ret = MEMORY_E; |
3261 | | } |
3262 | | else { |
3263 | | ret = DecodeToX509(x509, ssl->session->chain.certs[idx].buffer, |
3264 | | ssl->session->chain.certs[idx].length); |
3265 | | } |
3266 | | } |
3267 | | |
3268 | | if (ret == 0) { |
3269 | | if (wolfSSL_sk_X509_push(sk, x509) <= 0) { |
3270 | | ret = WOLFSSL_FATAL_ERROR; |
3271 | | } |
3272 | | else { |
3273 | | /* The stack owns the certificate from here on. */ |
3274 | | *pushed = x509; |
3275 | | x509 = NULL; |
3276 | | } |
3277 | | } |
3278 | | if (ret != 0) { |
3279 | | WOLFSSL_MSG("Error decoding cert"); |
3280 | | /* NULL once the stack has taken ownership, and freeing NULL does |
3281 | | * nothing, so this only releases a certificate that never got there. */ |
3282 | | wolfSSL_X509_free(x509); |
3283 | | } |
3284 | | |
3285 | | return ret; |
3286 | | } |
3287 | | |
3288 | | /* Build a stack of the peer's certificates from the session chain. |
3289 | | * |
3290 | | * For a verified chain the CA certificates known for the last certificate are |
3291 | | * placed at the bottom of the stack. |
3292 | | * |
3293 | | * @param [in, out] ssl SSL/TLS object. The kept peer certificate |
3294 | | * may be built from its encoding. |
3295 | | * @param [in] verifiedFlag Whether to append the known CA chain. |
3296 | | * @return Stack of the peer's certificates on success. |
3297 | | * @return NULL when ssl is NULL, the session holds no chain, or a certificate |
3298 | | * cannot be created, decoded or stored. |
3299 | | */ |
3300 | | static WOLF_STACK_OF(WOLFSSL_X509)* CreatePeerCertChain(WOLFSSL* ssl, |
3301 | | int verifiedFlag) |
3302 | | { |
3303 | | WOLFSSL_STACK* sk = NULL; |
3304 | | int err = 0; |
3305 | | |
3306 | | WOLFSSL_ENTER("CreatePeerCertChain"); |
3307 | | |
3308 | | /* There is nothing to build from without a session chain. */ |
3309 | | if ((ssl == NULL) || (ssl->session->chain.count == 0)) { |
3310 | | err = 1; |
3311 | | } |
3312 | | else { |
3313 | | sk = wolfSSL_sk_X509_new_null(); |
3314 | | if (sk == NULL) { |
3315 | | WOLFSSL_MSG("Error creating stack"); |
3316 | | err = 1; |
3317 | | } |
3318 | | } |
3319 | | |
3320 | | if (!err) { |
3321 | | WOLFSSL_X509* last = NULL; |
3322 | | int i; |
3323 | | |
3324 | | for (i = 0; i < ssl->session->chain.count; i++) { |
3325 | | WOLFSSL_X509* pushed = NULL; |
3326 | | |
3327 | | if (PushPeerCertToChain(ssl, i, sk, &pushed) != 0) { |
3328 | | err = 1; |
3329 | | break; |
3330 | | } |
3331 | | if (pushed != NULL) { |
3332 | | last = pushed; |
3333 | | } |
3334 | | } |
3335 | | |
3336 | | /* Append the CA chain known for the last certificate of a verified |
3337 | | * chain. It is owned by the stack, so it is still there to look the |
3338 | | * issuers up with. */ |
3339 | | if ((!err) && verifiedFlag && (last != NULL)) { |
3340 | | SSL_CM_WARNING(ssl); |
3341 | | if (PushCAx509Chain(SSL_CM(ssl), last, sk) != 0) { |
3342 | | err = 1; |
3343 | | } |
3344 | | } |
3345 | | } |
3346 | | |
3347 | | if (err) { |
3348 | | /* Certificates already pushed are freed with the stack. */ |
3349 | | wolfSSL_sk_X509_pop_free(sk, NULL); |
3350 | | sk = NULL; |
3351 | | } |
3352 | | |
3353 | | return sk; |
3354 | | } |
3355 | | |
3356 | | |
3357 | | /* Build and store the stack of the peer's certificates. |
3358 | | * |
3359 | | * On the server the leaf certificate is moved out of the stack and kept as the |
3360 | | * session's peer. The stack is disposed of when the SSL/TLS object is. |
3361 | | * |
3362 | | * @param [in, out] ssl SSL/TLS object. |
3363 | | * @return Stack of the peer's certificates on success. |
3364 | | * @return NULL when ssl is NULL, the session holds no chain, or the stack |
3365 | | * cannot be built. |
3366 | | */ |
3367 | | WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl) |
3368 | | { |
3369 | | WOLFSSL_STACK* sk = NULL; |
3370 | | |
3371 | | WOLFSSL_ENTER("wolfSSL_set_peer_cert_chain"); |
3372 | | |
3373 | | /* Validate parameters. */ |
3374 | | if ((ssl != NULL) && (ssl->session->chain.count > 0)) { |
3375 | | sk = CreatePeerCertChain(ssl, 0); |
3376 | | } |
3377 | | |
3378 | | if (sk != NULL) { |
3379 | | if (ssl->options.side == WOLFSSL_SERVER_END) { |
3380 | | /* Replace any peer kept from a previous call. */ |
3381 | | if (ssl->session->peer != NULL) { |
3382 | | wolfSSL_X509_free(ssl->session->peer); |
3383 | | } |
3384 | | |
3385 | | ssl->session->peer = wolfSSL_sk_X509_shift(sk); |
3386 | | ssl->session->peerVerifyRet = ssl->peerVerifyRet; |
3387 | | } |
3388 | | if (ssl->peerCertChain != NULL) { |
3389 | | wolfSSL_sk_X509_pop_free(ssl->peerCertChain, NULL); |
3390 | | } |
3391 | | /* This is Free'd when ssl is Free'd */ |
3392 | | ssl->peerCertChain = sk; |
3393 | | } |
3394 | | |
3395 | | return sk; |
3396 | | } |
3397 | | |
3398 | | #ifdef KEEP_PEER_CERT |
3399 | | /* Get the peer's certificate chain, verified against the store. |
3400 | | * |
3401 | | * Implemented in a similar way to ngx_ssl_ocsp_validate() when |
3402 | | * SSL_get0_verified_chain is not available. The chain is stored on the SSL/TLS |
3403 | | * object and disposed of with it, so the caller must not free it. |
3404 | | * |
3405 | | * @param [in, out] ssl SSL/TLS object. Declared const, but the verified |
3406 | | * chain is stored into it. |
3407 | | * @return Stack of verified certificates on success. |
3408 | | * @return NULL when ssl or its context is NULL, no peer certificate was kept, |
3409 | | * the chain cannot be built, or verification fails. |
3410 | | */ |
3411 | | WOLF_STACK_OF(WOLFSSL_X509) *wolfSSL_get0_verified_chain(const WOLFSSL *ssl) |
3412 | | { |
3413 | | WOLF_STACK_OF(WOLFSSL_X509)* chain = NULL; |
3414 | | WOLFSSL_X509_STORE_CTX* storeCtx = NULL; |
3415 | | WOLFSSL_X509* peerCert = NULL; |
3416 | | int err = 0; |
3417 | | |
3418 | | WOLFSSL_ENTER("wolfSSL_get0_verified_chain"); |
3419 | | |
3420 | | /* Validate parameters. */ |
3421 | | if ((ssl == NULL) || (ssl->ctx == NULL)) { |
3422 | | WOLFSSL_MSG("Bad parameter"); |
3423 | | err = 1; |
3424 | | } |
3425 | | |
3426 | | if (!err) { |
3427 | | /* Owned by ssl, so not freed here. */ |
3428 | | peerCert = LoadPeerCert((WOLFSSL*)ssl); |
3429 | | if (peerCert == NULL) { |
3430 | | WOLFSSL_MSG("No peer certificate"); |
3431 | | err = 1; |
3432 | | } |
3433 | | } |
3434 | | |
3435 | | if (!err) { |
3436 | | chain = CreatePeerCertChain((WOLFSSL*)ssl, 1); |
3437 | | if (chain == NULL) { |
3438 | | WOLFSSL_MSG("wolfSSL_get_peer_cert_chain error"); |
3439 | | err = 1; |
3440 | | } |
3441 | | else { |
3442 | | /* Replace any chain kept from a previous call. */ |
3443 | | if (ssl->verifiedChain != NULL) { |
3444 | | wolfSSL_sk_X509_pop_free(ssl->verifiedChain, NULL); |
3445 | | } |
3446 | | /* This is Free'd when ssl is Free'd */ |
3447 | | ((WOLFSSL*)ssl)->verifiedChain = chain; |
3448 | | } |
3449 | | } |
3450 | | |
3451 | | if (!err) { |
3452 | | storeCtx = wolfSSL_X509_STORE_CTX_new(); |
3453 | | if (storeCtx == NULL) { |
3454 | | WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_new error"); |
3455 | | err = 1; |
3456 | | } |
3457 | | } |
3458 | | |
3459 | | if (!err) { |
3460 | | if (wolfSSL_X509_STORE_CTX_init(storeCtx, SSL_STORE(ssl), peerCert, |
3461 | | chain) != WOLFSSL_SUCCESS) { |
3462 | | WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_init error"); |
3463 | | err = 1; |
3464 | | } |
3465 | | else if (wolfSSL_X509_verify_cert(storeCtx) <= 0) { |
3466 | | WOLFSSL_MSG("wolfSSL_X509_verify_cert error"); |
3467 | | err = 1; |
3468 | | } |
3469 | | } |
3470 | | |
3471 | | wolfSSL_X509_STORE_CTX_free(storeCtx); |
3472 | | if (err) { |
3473 | | /* The chain stays owned by the object; report failure only. */ |
3474 | | chain = NULL; |
3475 | | } |
3476 | | |
3477 | | return chain; |
3478 | | } |
3479 | | #endif /* KEEP_PEER_CERT */ |
3480 | | #endif /* SESSION_CERTS && OPENSSL_EXTRA && !NO_CERTS */ |
3481 | | |
3482 | | #endif /* !WOLFCRYPT_ONLY */ |
3483 | | |
3484 | | #endif /* !WOLFSSL_SSL_API_CERT_INCLUDED */ |