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