OpenVPN
pkcs11.c
Go to the documentation of this file.
1/*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2002-2025 OpenVPN Inc <sales@openvpn.net>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, see <https://www.gnu.org/licenses/>.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include "syshead.h"
28
29#if defined(ENABLE_PKCS11)
30
31#include <pkcs11-helper-1.0/pkcs11h-certificate.h>
32#include "basic.h"
33#include "error.h"
34#include "manage.h"
35#include "base64.h"
36#include "pkcs11.h"
37#include "misc.h"
38#include "otime.h"
39#include "console.h"
40#include "pkcs11_backend.h"
41
42static time_t
43__mytime(void)
44{
45 return openvpn_time(NULL);
46}
47
48#if !defined(_WIN32)
49static int
50__mygettimeofday(struct timeval *tv)
51{
52 return gettimeofday(tv, NULL);
53}
54#endif
55
56static void
57__mysleep(unsigned long usec)
58{
59#if defined(_WIN32)
60 Sleep(usec / 1000);
61#else
62 if (usec > UINT_MAX)
63 {
64 usec = UINT_MAX;
65 }
66 usleep((useconds_t)usec);
67#endif
68}
69
70
71static pkcs11h_engine_system_t s_pkcs11h_sys_engine = { malloc, free, __mytime, __mysleep,
72#if defined(_WIN32)
73 NULL
74#else
75 __mygettimeofday
76#endif
77};
78
79static msglvl_t
80_pkcs11_msg_pkcs112openvpn(const unsigned flags)
81{
82 msglvl_t openvpn_flags;
83
84 switch (flags)
85 {
86 case PKCS11H_LOG_DEBUG2:
87 openvpn_flags = D_PKCS11_DEBUG;
88 break;
89
90 case PKCS11H_LOG_DEBUG1:
91 openvpn_flags = D_SHOW_PKCS11;
92 break;
93
94 case PKCS11H_LOG_INFO:
95 openvpn_flags = M_INFO;
96 break;
97
98 case PKCS11H_LOG_WARN:
99 openvpn_flags = M_WARN;
100 break;
101
102 case PKCS11H_LOG_ERROR:
103 openvpn_flags = M_FATAL;
104 break;
105
106 default:
107 openvpn_flags = M_FATAL;
108 break;
109 }
110
111#if defined(ENABLE_PKCS11_FORCE_DEBUG)
112 openvpn_flags = M_INFO;
113#endif
114
115 return openvpn_flags;
116}
117
118static unsigned
119_pkcs11_msg_openvpn2pkcs11(const msglvl_t flags)
120{
121 unsigned pkcs11_flags;
122
123 if ((flags & D_PKCS11_DEBUG) != 0)
124 {
125 pkcs11_flags = PKCS11H_LOG_DEBUG2;
126 }
127 else if ((flags & D_SHOW_PKCS11) != 0)
128 {
129 pkcs11_flags = PKCS11H_LOG_DEBUG1;
130 }
131 else if ((flags & M_INFO) != 0)
132 {
133 pkcs11_flags = PKCS11H_LOG_INFO;
134 }
135 else if ((flags & M_WARN) != 0)
136 {
137 pkcs11_flags = PKCS11H_LOG_WARN;
138 }
139 else if ((flags & M_FATAL) != 0)
140 {
141 pkcs11_flags = PKCS11H_LOG_ERROR;
142 }
143 else
144 {
145 pkcs11_flags = PKCS11H_LOG_ERROR;
146 }
147
148#if defined(ENABLE_PKCS11_FORCE_DEBUG)
149 pkcs11_flags = PKCS11H_LOG_DEBUG2;
150#endif
151
152 return pkcs11_flags;
153}
154
155static void
156_pkcs11_openvpn_log(void *const global_data, unsigned flags, const char *const szFormat,
157 va_list args)
158{
159 char Buffer[10 * 1024];
160
161 (void)global_data;
162
163 vsnprintf(Buffer, sizeof(Buffer), szFormat, args);
164 Buffer[sizeof(Buffer) - 1] = 0;
165
166 msg(_pkcs11_msg_pkcs112openvpn(flags), "%s", Buffer);
167}
168
169static PKCS11H_BOOL
170_pkcs11_openvpn_token_prompt(void *const global_data, void *const user_data,
171 const pkcs11h_token_id_t token, const unsigned retry)
172{
173 struct user_pass token_resp;
174
175 (void)global_data;
176 (void)user_data;
177 (void)retry;
178
179 ASSERT(token != NULL);
180
181 CLEAR(token_resp);
182 token_resp.defined = false;
183 token_resp.nocache = true;
184 snprintf(token_resp.username, sizeof(token_resp.username), "Please insert %s token",
185 token->label);
186
187 if (!get_user_pass(&token_resp, NULL, "token-insertion-request",
189 {
190 return false;
191 }
192 else
193 {
194 return strcmp(token_resp.password, "ok") == 0;
195 }
196}
197
198static PKCS11H_BOOL
199_pkcs11_openvpn_pin_prompt(void *const global_data, void *const user_data,
200 const pkcs11h_token_id_t token, const unsigned retry, char *const pin,
201 const size_t pin_max)
202{
203 struct user_pass token_pass;
204 char prompt[1024];
205 CLEAR(token_pass);
206
207 (void)global_data;
208 (void)user_data;
209 (void)retry;
210
211 ASSERT(token != NULL);
212
213 snprintf(prompt, sizeof(prompt), "%s token", token->label);
214
215 token_pass.defined = false;
216 token_pass.nocache = true;
217
218 if (!get_user_pass(&token_pass, NULL, prompt,
221 {
222 return false;
223 }
224 else
225 {
226 strncpynt(pin, token_pass.password, pin_max);
227 purge_user_pass(&token_pass, true);
228
229 if (strlen(pin) == 0)
230 {
231 return false;
232 }
233 else
234 {
235 return true;
236 }
237 }
238}
239
240bool
241pkcs11_initialize(const bool protected_auth, const int nPINCachePeriod)
242{
243 CK_RV rv = CKR_FUNCTION_FAILED;
244
245 dmsg(D_PKCS11_DEBUG, "PKCS#11: pkcs11_initialize - entered");
246
247 if ((rv = pkcs11h_engine_setSystem(&s_pkcs11h_sys_engine)) != CKR_OK)
248 {
249 msg(M_FATAL, "PKCS#11: Cannot initialize system engine %ld-'%s'", rv,
250 pkcs11h_getMessage(rv));
251 goto cleanup;
252 }
253
254 if ((rv = pkcs11h_initialize()) != CKR_OK)
255 {
256 msg(M_FATAL, "PKCS#11: Cannot initialize %ld-'%s'", rv, pkcs11h_getMessage(rv));
257 goto cleanup;
258 }
259
260 if ((rv = pkcs11h_setLogHook(_pkcs11_openvpn_log, NULL)) != CKR_OK)
261 {
262 msg(M_FATAL, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage(rv));
263 goto cleanup;
264 }
265
266 pkcs11h_setLogLevel(_pkcs11_msg_openvpn2pkcs11(get_debug_level()));
267
268 if ((rv = pkcs11h_setForkMode(FALSE)) != CKR_OK)
269 {
270 msg(M_FATAL, "PKCS#11: Cannot set fork mode %ld-'%s'", rv, pkcs11h_getMessage(rv));
271 goto cleanup;
272 }
273
274 if ((rv = pkcs11h_setTokenPromptHook(_pkcs11_openvpn_token_prompt, NULL)) != CKR_OK)
275 {
276 msg(M_FATAL, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage(rv));
277 goto cleanup;
278 }
279
280 if ((rv = pkcs11h_setPINPromptHook(_pkcs11_openvpn_pin_prompt, NULL)) != CKR_OK)
281 {
282 msg(M_FATAL, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage(rv));
283 goto cleanup;
284 }
285
286 if ((rv = pkcs11h_setProtectedAuthentication(protected_auth)) != CKR_OK)
287 {
288 msg(M_FATAL, "PKCS#11: Cannot set protected authentication mode %ld-'%s'", rv,
289 pkcs11h_getMessage(rv));
290 goto cleanup;
291 }
292
293 if ((rv = pkcs11h_setPINCachePeriod(nPINCachePeriod)) != CKR_OK)
294 {
295 msg(M_FATAL, "PKCS#11: Cannot set Pcache period %ld-'%s'", rv, pkcs11h_getMessage(rv));
296 goto cleanup;
297 }
298
299 rv = CKR_OK;
300
301cleanup:
302 dmsg(D_PKCS11_DEBUG, "PKCS#11: pkcs11_initialize - return %ld-'%s'", rv,
303 pkcs11h_getMessage(rv));
304
305 return rv == CKR_OK;
306}
307
308void
309pkcs11_terminate(void)
310{
311 dmsg(D_PKCS11_DEBUG, "PKCS#11: pkcs11_terminate - entered");
312
313 pkcs11h_terminate();
314
315 dmsg(D_PKCS11_DEBUG, "PKCS#11: pkcs11_terminate - return");
316}
317
318bool
319pkcs11_addProvider(const char *const provider, const bool protected_auth,
320 const unsigned private_mode, const bool cert_private)
321{
322 CK_RV rv = CKR_OK;
323
324 ASSERT(provider != NULL);
325
326 dmsg(D_PKCS11_DEBUG, "PKCS#11: pkcs11_addProvider - entered - provider='%s', private_mode=%08x",
327 provider, private_mode);
328
329 msg(M_INFO, "PKCS#11: Adding PKCS#11 provider '%s'", provider);
330
331#if PKCS11H_VERSION >= ((1 << 16) | (28 << 8) | (0 << 0))
332 if ((rv = pkcs11h_registerProvider(provider)) != CKR_OK)
333 {
334 msg(M_WARN, "PKCS#11: Cannot register provider '%s' %ld-'%s'", provider, rv,
335 pkcs11h_getMessage(rv));
336 }
337 else
338 {
339 PKCS11H_BOOL allow_protected_auth = protected_auth;
340 PKCS11H_BOOL cert_is_private = cert_private;
341
342 rv = pkcs11h_setProviderProperty(provider, PKCS11H_PROVIDER_PROPERTY_LOCATION, provider,
343 strlen(provider) + 1);
344
345 if (rv == CKR_OK)
346 {
347 rv = pkcs11h_setProviderProperty(provider,
348 PKCS11H_PROVIDER_PROPERTY_ALLOW_PROTECTED_AUTH,
349 &allow_protected_auth, sizeof(allow_protected_auth));
350 }
351 if (rv == CKR_OK)
352 {
353 rv = pkcs11h_setProviderProperty(provider, PKCS11H_PROVIDER_PROPERTY_MASK_PRIVATE_MODE,
354 &private_mode, sizeof(private_mode));
355 }
356 if (rv == CKR_OK)
357 {
358 rv = pkcs11h_setProviderProperty(provider, PKCS11H_PROVIDER_PROPERTY_CERT_IS_PRIVATE,
359 &cert_is_private, sizeof(cert_is_private));
360 }
361#if defined(WIN32) && defined(PKCS11H_PROVIDER_PROPERTY_LOADER_FLAGS)
362 if (rv == CKR_OK && platform_absolute_pathname(provider))
363 {
364 unsigned loader_flags =
365 LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR;
366 rv = pkcs11h_setProviderProperty(provider, PKCS11H_PROVIDER_PROPERTY_LOADER_FLAGS,
367 &loader_flags, sizeof(loader_flags));
368 }
369#endif
370
371 if (rv != CKR_OK || (rv = pkcs11h_initializeProvider(provider)) != CKR_OK)
372 {
373 msg(M_WARN, "PKCS#11: Cannot initialize provider '%s' %ld-'%s'", provider, rv,
374 pkcs11h_getMessage(rv));
375 pkcs11h_removeProvider(provider);
376 }
377 }
378#else /* if PKCS11H_VERSION >= ((1<<16) | (28<<8) | (0<<0)) */
379 if ((rv = pkcs11h_addProvider(provider, provider, protected_auth, private_mode,
380 PKCS11H_SLOTEVENT_METHOD_AUTO, 0, cert_private))
381 != CKR_OK)
382 {
383 msg(M_WARN, "PKCS#11: Cannot initialize provider '%s' %ld-'%s'", provider, rv,
384 pkcs11h_getMessage(rv));
385 }
386#endif /* if PKCS11H_VERSION >= ((1<<16) | (28<<8) | (0<<0)) */
387
388 dmsg(D_PKCS11_DEBUG, "PKCS#11: pkcs11_addProvider - return rv=%ld-'%s'", rv,
389 pkcs11h_getMessage(rv));
390
391 return rv == CKR_OK;
392}
393
394int
395pkcs11_logout(void)
396{
397 return pkcs11h_logout() == CKR_OK;
398}
399
400int
401pkcs11_management_id_count(void)
402{
403 pkcs11h_certificate_id_list_t id_list = NULL;
404 pkcs11h_certificate_id_list_t t = NULL;
405 CK_RV rv = CKR_OK;
406 int count = 0;
407
408 dmsg(D_PKCS11_DEBUG, "PKCS#11: pkcs11_management_id_count - entered");
409
410 if ((rv = pkcs11h_certificate_enumCertificateIds(PKCS11H_ENUM_METHOD_CACHE_EXIST, NULL,
411 PKCS11H_PROMPT_MASK_ALLOW_ALL, NULL, &id_list))
412 != CKR_OK)
413 {
414 msg(M_WARN, "PKCS#11: Cannot get certificate list %ld-'%s'", rv, pkcs11h_getMessage(rv));
415 goto cleanup;
416 }
417
418 for (count = 0, t = id_list; t != NULL; t = t->next)
419 {
420 count++;
421 }
422
423cleanup:
424
425 pkcs11h_certificate_freeCertificateIdList(id_list);
426 id_list = NULL;
427
428 dmsg(D_PKCS11_DEBUG, "PKCS#11: pkcs11_management_id_count - return count=%d", count);
429
430 return count;
431}
432
433bool
434pkcs11_management_id_get(const int index, char **id, char **base64)
435{
436 pkcs11h_certificate_id_list_t id_list = NULL;
437 pkcs11h_certificate_id_list_t entry = NULL;
438 pkcs11h_certificate_t certificate = NULL;
439 CK_RV rv = CKR_OK;
440 unsigned char *certificate_blob = NULL;
441 size_t certificate_blob_size = 0;
442 size_t max;
443 char *internal_id = NULL;
444 char *internal_base64 = NULL;
445 int count = 0;
446 bool success = false;
447
448 ASSERT(id != NULL);
449 ASSERT(base64 != NULL);
450
451 dmsg(D_PKCS11_DEBUG, "PKCS#11: pkcs11_management_id_get - entered index=%d", index);
452
453 *id = NULL;
454 *base64 = NULL;
455
456 if ((rv = pkcs11h_certificate_enumCertificateIds(PKCS11H_ENUM_METHOD_CACHE_EXIST, NULL,
457 PKCS11H_PROMPT_MASK_ALLOW_ALL, NULL, &id_list))
458 != CKR_OK)
459 {
460 msg(M_WARN, "PKCS#11: Cannot get certificate list %ld-'%s'", rv, pkcs11h_getMessage(rv));
461 goto cleanup;
462 }
463
464 entry = id_list;
465 count = 0;
466 while (entry != NULL && count != index)
467 {
468 count++;
469 entry = entry->next;
470 }
471
472 if (entry == NULL)
473 {
474 dmsg(D_PKCS11_DEBUG, "PKCS#11: pkcs11_management_id_get - no certificate at index=%d",
475 index);
476 goto cleanup;
477 }
478
479 if ((rv = pkcs11h_certificate_serializeCertificateId(NULL, &max, entry->certificate_id))
480 != CKR_OK)
481 {
482 msg(M_WARN, "PKCS#11: Cannot serialize certificate id %ld-'%s'", rv,
483 pkcs11h_getMessage(rv));
484 goto cleanup;
485 }
486
487 if ((internal_id = (char *)malloc(max)) == NULL)
488 {
489 msg(M_FATAL, "PKCS#11: Cannot allocate memory");
490 goto cleanup;
491 }
492
493 if ((rv = pkcs11h_certificate_serializeCertificateId(internal_id, &max, entry->certificate_id))
494 != CKR_OK)
495 {
496 msg(M_WARN, "PKCS#11: Cannot serialize certificate id %ld-'%s'", rv,
497 pkcs11h_getMessage(rv));
498 goto cleanup;
499 }
500
501 if ((rv = pkcs11h_certificate_create(entry->certificate_id, NULL, PKCS11H_PROMPT_MASK_ALLOW_ALL,
502 PKCS11H_PIN_CACHE_INFINITE, &certificate))
503 != CKR_OK)
504 {
505 msg(M_WARN, "PKCS#11: Cannot get certificate %ld-'%s'", rv, pkcs11h_getMessage(rv));
506 goto cleanup;
507 }
508
509 if ((rv = pkcs11h_certificate_getCertificateBlob(certificate, NULL, &certificate_blob_size))
510 != CKR_OK)
511 {
512 msg(M_WARN, "PKCS#11: Cannot get certificate blob %ld-'%s'", rv, pkcs11h_getMessage(rv));
513 goto cleanup;
514 }
515
516 if ((certificate_blob = (unsigned char *)malloc(certificate_blob_size)) == NULL)
517 {
518 msg(M_FATAL, "PKCS#11: Cannot allocate memory");
519 goto cleanup;
520 }
521
522 if ((rv = pkcs11h_certificate_getCertificateBlob(certificate, certificate_blob,
523 &certificate_blob_size))
524 != CKR_OK)
525 {
526 msg(M_WARN, "PKCS#11: Cannot get certificate blob %ld-'%s'", rv, pkcs11h_getMessage(rv));
527 goto cleanup;
528 }
529
530 if (certificate_blob_size > INT_MAX)
531 {
532 msg(M_WARN, "PKCS#11: Invalid certificate size %zu", certificate_blob_size);
533 goto cleanup;
534 }
535
536 if (openvpn_base64_encode(certificate_blob, (int)certificate_blob_size, &internal_base64) == -1)
537 {
538 msg(M_WARN, "PKCS#11: Cannot encode certificate");
539 goto cleanup;
540 }
541
542 *id = internal_id;
543 internal_id = NULL;
544 *base64 = internal_base64;
545 internal_base64 = NULL;
546 success = true;
547
548cleanup:
549
550 pkcs11h_certificate_freeCertificateIdList(id_list);
551 id_list = NULL;
552
553 pkcs11h_certificate_freeCertificate(certificate);
554 certificate = NULL;
555
556 free(internal_id);
557 internal_id = NULL;
558
559 free(internal_base64);
560 internal_base64 = NULL;
561
562 free(certificate_blob);
563 certificate_blob = NULL;
564
565 dmsg(D_PKCS11_DEBUG, "PKCS#11: pkcs11_management_id_get - return success=%d, id='%s'",
566 success ? 1 : 0, *id);
567
568 return success;
569}
570
571int
572tls_ctx_use_pkcs11(struct tls_root_ctx *const ssl_ctx, bool pkcs11_id_management,
573 const char *const pkcs11_id)
574{
575 pkcs11h_certificate_id_t certificate_id = NULL;
576 pkcs11h_certificate_t certificate = NULL;
577 CK_RV rv = CKR_OK;
578
579 bool ok = false;
580
581 ASSERT(ssl_ctx != NULL);
582 ASSERT(pkcs11_id_management || pkcs11_id != NULL);
583
584 dmsg(
586 "PKCS#11: tls_ctx_use_pkcs11 - entered - ssl_ctx=%p, pkcs11_id_management=%d, pkcs11_id='%s'",
587 (void *)ssl_ctx, pkcs11_id_management ? 1 : 0, pkcs11_id);
588
590 {
591 struct user_pass id_resp;
592
593 CLEAR(id_resp);
594
595 id_resp.defined = false;
596 id_resp.nocache = true;
597 snprintf(id_resp.username, sizeof(id_resp.username), "Please specify PKCS#11 id to use");
598
599 if (!get_user_pass(&id_resp, NULL, "pkcs11-id-request",
602 {
603 goto cleanup;
604 }
605
606 if ((rv = pkcs11h_certificate_deserializeCertificateId(&certificate_id, id_resp.password))
607 != CKR_OK)
608 {
609 msg(M_WARN, "PKCS#11: Cannot deserialize id %ld-'%s'", rv, pkcs11h_getMessage(rv));
610 goto cleanup;
611 }
612 }
613 else
614 {
615 if ((rv = pkcs11h_certificate_deserializeCertificateId(&certificate_id, pkcs11_id))
616 != CKR_OK)
617 {
618 msg(M_WARN, "PKCS#11: Cannot deserialize id %ld-'%s'", rv, pkcs11h_getMessage(rv));
619 goto cleanup;
620 }
621 }
622
623 if ((rv = pkcs11h_certificate_create(certificate_id, NULL, PKCS11H_PROMPT_MASK_ALLOW_ALL,
624 PKCS11H_PIN_CACHE_INFINITE, &certificate))
625 != CKR_OK)
626 {
627 msg(M_WARN, "PKCS#11: Cannot get certificate %ld-'%s'", rv, pkcs11h_getMessage(rv));
628 goto cleanup;
629 }
630
631 if ((pkcs11_init_tls_session(certificate, ssl_ctx)))
632 {
633 /* Handled by SSL context free */
634 certificate = NULL;
635 goto cleanup;
636 }
637
638 /* Handled by SSL context free */
639 certificate = NULL;
640 ok = true;
641
642cleanup:
643 if (certificate != NULL)
644 {
645 pkcs11h_certificate_freeCertificate(certificate);
646 certificate = NULL;
647 }
648
649 if (certificate_id != NULL)
650 {
651 pkcs11h_certificate_freeCertificateId(certificate_id);
652 certificate_id = NULL;
653 }
654
655 dmsg(D_PKCS11_DEBUG, "PKCS#11: tls_ctx_use_pkcs11 - return ok=%d, rv=%ld", ok ? 1 : 0, rv);
656
657 return ok ? 1 : 0;
658}
659
660static PKCS11H_BOOL
661_pkcs11_openvpn_show_pkcs11_ids_pin_prompt(void *const global_data, void *const user_data,
662 const pkcs11h_token_id_t token, const unsigned retry,
663 char *const pin, const size_t pin_max)
664{
665 struct gc_arena gc = gc_new();
666 struct buffer pass_prompt = alloc_buf_gc(128, &gc);
667
670 (void)retry;
671
672 ASSERT(token != NULL);
673
674 buf_printf(&pass_prompt, "Please enter '%s' token PIN or 'cancel': ", token->display);
675 if (!query_user_SINGLE(BSTR(&pass_prompt), pin, (int)pin_max, false))
676 {
677 msg(M_FATAL, "Could not retrieve the PIN");
678 }
679
680 gc_free(&gc);
681
682 if (!strcmp(pin, "cancel"))
683 {
684 return FALSE;
685 }
686 else
687 {
688 return TRUE;
689 }
690}
691
692void
693show_pkcs11_ids(const char *const provider, bool cert_private)
694{
695 struct gc_arena gc = gc_new();
696 pkcs11h_certificate_id_list_t user_certificates = NULL;
697 pkcs11h_certificate_id_list_t current = NULL;
698 CK_RV rv = CKR_FUNCTION_FAILED;
699
700 if ((rv = pkcs11h_initialize()) != CKR_OK)
701 {
702 msg(M_FATAL, "PKCS#11: Cannot initialize %ld-'%s'", rv, pkcs11h_getMessage(rv));
703 goto cleanup;
704 }
705
706 if ((rv = pkcs11h_setLogHook(_pkcs11_openvpn_log, NULL)) != CKR_OK)
707 {
708 msg(M_FATAL, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage(rv));
709 goto cleanup;
710 }
711
712 pkcs11h_setLogLevel(_pkcs11_msg_openvpn2pkcs11(get_debug_level()));
713
714 if ((rv = pkcs11h_setProtectedAuthentication(TRUE)) != CKR_OK)
715 {
716 msg(M_FATAL, "PKCS#11: Cannot set protected authentication %ld-'%s'", rv,
717 pkcs11h_getMessage(rv));
718 goto cleanup;
719 }
720
721 if ((rv = pkcs11h_setPINPromptHook(_pkcs11_openvpn_show_pkcs11_ids_pin_prompt, NULL)) != CKR_OK)
722 {
723 msg(M_FATAL, "PKCS#11: Cannot set PIN hook %ld-'%s'", rv, pkcs11h_getMessage(rv));
724 goto cleanup;
725 }
726
727 if (!pkcs11_addProvider(provider, TRUE, 0, cert_private ? TRUE : FALSE))
728 {
729 msg(M_FATAL, "Failed to add PKCS#11 provider '%s", provider);
730 goto cleanup;
731 }
732
733 if ((rv = pkcs11h_certificate_enumCertificateIds(PKCS11H_ENUM_METHOD_CACHE_EXIST, NULL,
734 PKCS11H_PROMPT_MASK_ALLOW_ALL, NULL,
735 &user_certificates))
736 != CKR_OK)
737 {
738 msg(M_FATAL, "PKCS#11: Cannot enumerate certificates %ld-'%s'", rv, pkcs11h_getMessage(rv));
739 goto cleanup;
740 }
741
743 ("\n"
744 "The following objects are available for use.\n"
745 "Each object shown below may be used as parameter to\n"
746 "--pkcs11-id option please remember to use single quote mark.\n"));
747 for (current = user_certificates; current != NULL; current = current->next)
748 {
749 pkcs11h_certificate_t certificate = NULL;
750 char *dn = NULL;
751 char serial[1024] = { 0 };
752 char *ser = NULL;
753 size_t ser_len = 0;
754
755 if ((rv = pkcs11h_certificate_serializeCertificateId(NULL, &ser_len,
756 current->certificate_id))
757 != CKR_OK)
758 {
759 msg(M_FATAL, "PKCS#11: Cannot serialize certificate %ld-'%s'", rv,
760 pkcs11h_getMessage(rv));
761 goto cleanup1;
762 }
763
764 if (rv == CKR_OK && (ser = (char *)malloc(ser_len)) == NULL)
765 {
766 msg(M_FATAL, "PKCS#11: Cannot allocate memory");
767 goto cleanup1;
768 }
769
770 if ((rv =
771 pkcs11h_certificate_serializeCertificateId(ser, &ser_len, current->certificate_id))
772 != CKR_OK)
773 {
774 msg(M_FATAL, "PKCS#11: Cannot serialize certificate %ld-'%s'", rv,
775 pkcs11h_getMessage(rv));
776 goto cleanup1;
777 }
778
779 if ((rv = pkcs11h_certificate_create(current->certificate_id, NULL,
780 PKCS11H_PROMPT_MASK_ALLOW_ALL,
781 PKCS11H_PIN_CACHE_INFINITE, &certificate)))
782 {
783 msg(M_FATAL, "PKCS#11: Cannot create certificate %ld-'%s'", rv, pkcs11h_getMessage(rv));
784 goto cleanup1;
785 }
786
787 if ((dn = pkcs11_certificate_dn(certificate, &gc)) == NULL)
788 {
789 goto cleanup1;
790 }
791
792 if ((pkcs11_certificate_serial(certificate, serial, sizeof(serial))))
793 {
794 goto cleanup1;
795 }
796
798 ("\n"
799 "Certificate\n"
800 " DN: %s\n"
801 " Serial: %s\n"
802 " Serialized id: %s\n"),
803 dn, serial, ser);
804
805cleanup1:
806
807 if (certificate != NULL)
808 {
809 pkcs11h_certificate_freeCertificate(certificate);
810 certificate = NULL;
811 }
812
813 free(ser);
814 ser = NULL;
815 }
816
817cleanup:
818 pkcs11h_certificate_freeCertificateIdList(user_certificates);
819 user_certificates = NULL;
820
821 pkcs11h_terminate();
822 gc_free(&gc);
823}
824#endif /* ENABLE_PKCS11 */
bool buf_printf(struct buffer *buf, const char *format,...)
Definition buffer.c:241
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition buffer.c:89
#define BSTR(buf)
Definition buffer.h:128
static void strncpynt(char *dest, const char *src, size_t maxlen)
Definition buffer.h:361
static void gc_free(struct gc_arena *a)
Definition buffer.h:1025
static struct gc_arena gc_new(void)
Definition buffer.h:1017
static bool query_user_SINGLE(char *prompt, char *resp, int resp_len, bool echo)
A plain "make Gert happy" wrapper.
Definition console.h:118
#define D_PKCS11_DEBUG
Definition errlevel.h:173
#define D_SHOW_PKCS11
Definition errlevel.h:140
#define M_INFO
Definition errlevel.h:54
void purge_user_pass(struct user_pass *up, const bool force)
Definition misc.c:470
#define GET_USER_PASS_MANAGEMENT
Definition misc.h:110
#define GET_USER_PASS_PASSWORD_ONLY
Definition misc.h:112
#define GET_USER_PASS_NEED_OK
Definition misc.h:113
#define GET_USER_PASS_NOFATAL
Definition misc.h:114
static bool get_user_pass(struct user_pass *up, const char *auth_file, const char *prefix, const unsigned int flags)
Retrieves the user credentials from various sources depending on the flags.
Definition misc.h:150
#define GET_USER_PASS_NEED_STR
Definition misc.h:115
#define CLEAR(x)
Definition basic.h:32
msglvl_t get_debug_level(void)
Definition error.c:131
#define M_NOPREFIX
Definition error.h:98
#define M_FATAL
Definition error.h:90
#define M_NOLF
Definition error.h:102
#define dmsg(flags,...)
Definition error.h:172
#define msg(flags,...)
Definition error.h:152
unsigned int msglvl_t
Definition error.h:77
#define ASSERT(x)
Definition error.h:219
#define M_WARN
Definition error.h:92
static time_t openvpn_time(time_t *t)
Definition otime.h:94
PKCS #11 SSL library-specific backend.
bool platform_absolute_pathname(const char *pathname)
Return true if pathname is absolute.
Definition platform.c:637
int openvpn_base64_encode(const void *data, int size, char **str)
Definition base64.c:51
Wrapper structure for dynamically allocated memory.
Definition buffer.h:60
int len
Length in bytes of the actual content within the allocated memory.
Definition buffer.h:65
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:116
Structure that wraps the TLS context.
static int cleanup(void **state)
static bool pkcs11_id_management
struct gc_arena gc
Definition test_ssl.c:131