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