29#if defined(ENABLE_PKCS11)
31#include <pkcs11-helper-1.0/pkcs11h-certificate.h>
51__mygettimeofday(
struct timeval *tv)
53 return gettimeofday(tv, NULL);
58__mysleep(
unsigned long usec)
67 usleep((useconds_t)usec);
72static pkcs11h_engine_system_t s_pkcs11h_sys_engine = { malloc, free, __mytime, __mysleep,
81_pkcs11_msg_pkcs112openvpn(
const unsigned flags)
83#ifdef ENABLE_PKCS11_FORCE_DEBUG
90 case PKCS11H_LOG_DEBUG2:
94 case PKCS11H_LOG_DEBUG1:
98 case PKCS11H_LOG_INFO:
102 case PKCS11H_LOG_WARN:
106 case PKCS11H_LOG_ERROR:
115 return openvpn_flags;
120_pkcs11_msg_openvpn2pkcs11(
const msglvl_t flags)
122#ifdef ENABLE_PKCS11_FORCE_DEBUG
123 return PKCS11H_LOG_DEBUG2;
125 unsigned pkcs11_flags;
129 pkcs11_flags = PKCS11H_LOG_DEBUG2;
133 pkcs11_flags = PKCS11H_LOG_DEBUG1;
135 else if ((flags &
M_INFO) != 0)
137 pkcs11_flags = PKCS11H_LOG_INFO;
139 else if ((flags &
M_WARN) != 0)
141 pkcs11_flags = PKCS11H_LOG_WARN;
143 else if ((flags &
M_FATAL) != 0)
145 pkcs11_flags = PKCS11H_LOG_ERROR;
149 pkcs11_flags = PKCS11H_LOG_ERROR;
157_pkcs11_openvpn_log(
void *
const global_data,
unsigned flags,
const char *
const szFormat,
160 char Buffer[10 * 1024];
164 vsnprintf(Buffer,
sizeof(Buffer), szFormat, args);
165 Buffer[
sizeof(Buffer) - 1] = 0;
167 msg(_pkcs11_msg_pkcs112openvpn(flags),
"%s", Buffer);
171_pkcs11_openvpn_token_prompt(
void *
const global_data,
void *
const user_data,
172 const pkcs11h_token_id_t token,
const unsigned retry)
183 token_resp.defined =
false;
184 token_resp.nocache =
true;
185 snprintf(token_resp.username,
sizeof(token_resp.username),
"Please insert %s token",
188 if (!
get_user_pass(&token_resp, NULL,
"token-insertion-request",
195 return strcmp(token_resp.password,
"ok") == 0;
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)
214 snprintf(prompt,
sizeof(prompt),
"%s token", token->label);
216 token_pass.defined =
false;
217 token_pass.nocache =
true;
227 strncpynt(pin, token_pass.password, pin_max);
230 if (strlen(pin) == 0)
242pkcs11_initialize(
const bool protected_auth,
const int nPINCachePeriod)
244 CK_RV rv = CKR_FUNCTION_FAILED;
248 if ((rv = pkcs11h_engine_setSystem(&s_pkcs11h_sys_engine)) != CKR_OK)
250 msg(
M_FATAL,
"PKCS#11: Cannot initialize system engine %ld-'%s'", rv,
251 pkcs11h_getMessage(rv));
255 if ((rv = pkcs11h_initialize()) != CKR_OK)
257 msg(
M_FATAL,
"PKCS#11: Cannot initialize %ld-'%s'", rv, pkcs11h_getMessage(rv));
261 if ((rv = pkcs11h_setLogHook(_pkcs11_openvpn_log, NULL)) != CKR_OK)
263 msg(
M_FATAL,
"PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage(rv));
269 if ((rv = pkcs11h_setForkMode(FALSE)) != CKR_OK)
271 msg(
M_FATAL,
"PKCS#11: Cannot set fork mode %ld-'%s'", rv, pkcs11h_getMessage(rv));
275 if ((rv = pkcs11h_setTokenPromptHook(_pkcs11_openvpn_token_prompt, NULL)) != CKR_OK)
277 msg(
M_FATAL,
"PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage(rv));
281 if ((rv = pkcs11h_setPINPromptHook(_pkcs11_openvpn_pin_prompt, NULL)) != CKR_OK)
283 msg(
M_FATAL,
"PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage(rv));
287 if ((rv = pkcs11h_setProtectedAuthentication(protected_auth)) != CKR_OK)
289 msg(
M_FATAL,
"PKCS#11: Cannot set protected authentication mode %ld-'%s'", rv,
290 pkcs11h_getMessage(rv));
294 if ((rv = pkcs11h_setPINCachePeriod(nPINCachePeriod)) != CKR_OK)
296 msg(
M_FATAL,
"PKCS#11: Cannot set Pcache period %ld-'%s'", rv, pkcs11h_getMessage(rv));
304 pkcs11h_getMessage(rv));
310pkcs11_terminate(
void)
320pkcs11_addProvider(
const char *
const provider,
const bool protected_auth,
321 const unsigned private_mode,
const bool cert_private)
327 dmsg(
D_PKCS11_DEBUG,
"PKCS#11: pkcs11_addProvider - entered - provider='%s', private_mode=%08x",
328 provider, private_mode);
330 msg(
M_INFO,
"PKCS#11: Adding PKCS#11 provider '%s'", provider);
332#if PKCS11H_VERSION >= ((1 << 16) | (28 << 8) | (0 << 0))
333 if ((rv = pkcs11h_registerProvider(provider)) != CKR_OK)
335 msg(
M_WARN,
"PKCS#11: Cannot register provider '%s' %ld-'%s'", provider, rv,
336 pkcs11h_getMessage(rv));
340 PKCS11H_BOOL allow_protected_auth = protected_auth;
341 PKCS11H_BOOL cert_is_private = cert_private;
343 rv = pkcs11h_setProviderProperty(provider, PKCS11H_PROVIDER_PROPERTY_LOCATION, provider,
344 strlen(provider) + 1);
348 rv = pkcs11h_setProviderProperty(provider,
349 PKCS11H_PROVIDER_PROPERTY_ALLOW_PROTECTED_AUTH,
350 &allow_protected_auth,
sizeof(allow_protected_auth));
354 rv = pkcs11h_setProviderProperty(provider, PKCS11H_PROVIDER_PROPERTY_MASK_PRIVATE_MODE,
355 &private_mode,
sizeof(private_mode));
359 rv = pkcs11h_setProviderProperty(provider, PKCS11H_PROVIDER_PROPERTY_CERT_IS_PRIVATE,
360 &cert_is_private,
sizeof(cert_is_private));
362#if defined(WIN32) && defined(PKCS11H_PROVIDER_PROPERTY_LOADER_FLAGS)
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));
372 if (rv != CKR_OK || (rv = pkcs11h_initializeProvider(provider)) != CKR_OK)
374 msg(
M_WARN,
"PKCS#11: Cannot initialize provider '%s' %ld-'%s'", provider, rv,
375 pkcs11h_getMessage(rv));
376 pkcs11h_removeProvider(provider);
380 if ((rv = pkcs11h_addProvider(provider, provider, protected_auth, private_mode,
381 PKCS11H_SLOTEVENT_METHOD_AUTO, 0, cert_private))
384 msg(
M_WARN,
"PKCS#11: Cannot initialize provider '%s' %ld-'%s'", provider, rv,
385 pkcs11h_getMessage(rv));
390 pkcs11h_getMessage(rv));
398 return pkcs11h_logout() == CKR_OK;
402pkcs11_management_id_count(
void)
404 pkcs11h_certificate_id_list_t id_list = NULL;
405 pkcs11h_certificate_id_list_t t = NULL;
411 if ((rv = pkcs11h_certificate_enumCertificateIds(PKCS11H_ENUM_METHOD_CACHE_EXIST, NULL,
412 PKCS11H_PROMPT_MASK_ALLOW_ALL, NULL, &id_list))
415 msg(
M_WARN,
"PKCS#11: Cannot get certificate list %ld-'%s'", rv, pkcs11h_getMessage(rv));
419 for (count = 0, t = id_list; t != NULL; t = t->next)
426 pkcs11h_certificate_freeCertificateIdList(id_list);
435pkcs11_management_id_get(
const int index,
char **
id,
char **base64)
437 pkcs11h_certificate_id_list_t id_list = NULL;
438 pkcs11h_certificate_id_list_t entry = NULL;
439 pkcs11h_certificate_t certificate = NULL;
441 unsigned char *certificate_blob = NULL;
442 size_t certificate_blob_size = 0;
444 char *internal_id = NULL;
445 char *internal_base64 = NULL;
447 bool success =
false;
457 if ((rv = pkcs11h_certificate_enumCertificateIds(PKCS11H_ENUM_METHOD_CACHE_EXIST, NULL,
458 PKCS11H_PROMPT_MASK_ALLOW_ALL, NULL, &id_list))
461 msg(
M_WARN,
"PKCS#11: Cannot get certificate list %ld-'%s'", rv, pkcs11h_getMessage(rv));
467 while (entry != NULL && count != index)
475 dmsg(
D_PKCS11_DEBUG,
"PKCS#11: pkcs11_management_id_get - no certificate at index=%d",
480 if ((rv = pkcs11h_certificate_serializeCertificateId(NULL, &max, entry->certificate_id))
483 msg(
M_WARN,
"PKCS#11: Cannot serialize certificate id %ld-'%s'", rv,
484 pkcs11h_getMessage(rv));
488 if ((internal_id = (
char *)malloc(max)) == NULL)
490 msg(
M_FATAL,
"PKCS#11: Cannot allocate memory");
494 if ((rv = pkcs11h_certificate_serializeCertificateId(internal_id, &max, entry->certificate_id))
497 msg(
M_WARN,
"PKCS#11: Cannot serialize certificate id %ld-'%s'", rv,
498 pkcs11h_getMessage(rv));
502 if ((rv = pkcs11h_certificate_create(entry->certificate_id, NULL, PKCS11H_PROMPT_MASK_ALLOW_ALL,
503 PKCS11H_PIN_CACHE_INFINITE, &certificate))
506 msg(
M_WARN,
"PKCS#11: Cannot get certificate %ld-'%s'", rv, pkcs11h_getMessage(rv));
510 if ((rv = pkcs11h_certificate_getCertificateBlob(certificate, NULL, &certificate_blob_size))
513 msg(
M_WARN,
"PKCS#11: Cannot get certificate blob %ld-'%s'", rv, pkcs11h_getMessage(rv));
517 if ((certificate_blob = (
unsigned char *)malloc(certificate_blob_size)) == NULL)
519 msg(
M_FATAL,
"PKCS#11: Cannot allocate memory");
523 if ((rv = pkcs11h_certificate_getCertificateBlob(certificate, certificate_blob,
524 &certificate_blob_size))
527 msg(
M_WARN,
"PKCS#11: Cannot get certificate blob %ld-'%s'", rv, pkcs11h_getMessage(rv));
531 if (certificate_blob_size > INT_MAX)
533 msg(
M_WARN,
"PKCS#11: Invalid certificate size %zu", certificate_blob_size);
539 msg(
M_WARN,
"PKCS#11: Cannot encode certificate");
545 *base64 = internal_base64;
546 internal_base64 = NULL;
551 pkcs11h_certificate_freeCertificateIdList(id_list);
554 pkcs11h_certificate_freeCertificate(certificate);
560 free(internal_base64);
561 internal_base64 = NULL;
563 free(certificate_blob);
564 certificate_blob = NULL;
566 dmsg(
D_PKCS11_DEBUG,
"PKCS#11: pkcs11_management_id_get - return success=%d, id='%s'",
567 success ? 1 : 0, *id);
574 const char *
const pkcs11_id)
576 pkcs11h_certificate_id_t certificate_id = NULL;
577 pkcs11h_certificate_t certificate = NULL;
587 "PKCS#11: tls_ctx_use_pkcs11 - entered - ssl_ctx=%p, pkcs11_id_management=%d, pkcs11_id='%s'",
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");
607 if ((rv = pkcs11h_certificate_deserializeCertificateId(&certificate_id, id_resp.password))
610 msg(
M_WARN,
"PKCS#11: Cannot deserialize id %ld-'%s'", rv, pkcs11h_getMessage(rv));
616 if ((rv = pkcs11h_certificate_deserializeCertificateId(&certificate_id, pkcs11_id))
619 msg(
M_WARN,
"PKCS#11: Cannot deserialize id %ld-'%s'", rv, pkcs11h_getMessage(rv));
624 if ((rv = pkcs11h_certificate_create(certificate_id, NULL, PKCS11H_PROMPT_MASK_ALLOW_ALL,
625 PKCS11H_PIN_CACHE_INFINITE, &certificate))
628 msg(
M_WARN,
"PKCS#11: Cannot get certificate %ld-'%s'", rv, pkcs11h_getMessage(rv));
632 if ((pkcs11_init_tls_session(certificate, ssl_ctx)))
644 if (certificate != NULL)
646 pkcs11h_certificate_freeCertificate(certificate);
650 if (certificate_id != NULL)
652 pkcs11h_certificate_freeCertificateId(certificate_id);
653 certificate_id = NULL;
656 dmsg(
D_PKCS11_DEBUG,
"PKCS#11: tls_ctx_use_pkcs11 - return ok=%d, rv=%ld", ok ? 1 : 0, rv);
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)
697 pkcs11h_certificate_id_list_t user_certificates = NULL;
698 pkcs11h_certificate_id_list_t current = NULL;
699 CK_RV rv = CKR_FUNCTION_FAILED;
701 if ((rv = pkcs11h_initialize()) != CKR_OK)
703 msg(
M_FATAL,
"PKCS#11: Cannot initialize %ld-'%s'", rv, pkcs11h_getMessage(rv));
707 if ((rv = pkcs11h_setLogHook(_pkcs11_openvpn_log, NULL)) != CKR_OK)
709 msg(
M_FATAL,
"PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage(rv));
715 if ((rv = pkcs11h_setProtectedAuthentication(TRUE)) != CKR_OK)
717 msg(
M_FATAL,
"PKCS#11: Cannot set protected authentication %ld-'%s'", rv,
718 pkcs11h_getMessage(rv));
722 if ((rv = pkcs11h_setPINPromptHook(_pkcs11_openvpn_show_pkcs11_ids_pin_prompt, NULL)) != CKR_OK)
724 msg(
M_FATAL,
"PKCS#11: Cannot set PIN hook %ld-'%s'", rv, pkcs11h_getMessage(rv));
728 if (!pkcs11_addProvider(provider, TRUE, 0, cert_private ? TRUE : FALSE))
730 msg(
M_FATAL,
"Failed to add PKCS#11 provider '%s", provider);
734 if ((rv = pkcs11h_certificate_enumCertificateIds(PKCS11H_ENUM_METHOD_CACHE_EXIST, NULL,
735 PKCS11H_PROMPT_MASK_ALLOW_ALL, NULL,
739 msg(
M_FATAL,
"PKCS#11: Cannot enumerate certificates %ld-'%s'", rv, pkcs11h_getMessage(rv));
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)
750 pkcs11h_certificate_t certificate = NULL;
752 char serial[1024] = { 0 };
756 if ((rv = pkcs11h_certificate_serializeCertificateId(NULL, &ser_len,
757 current->certificate_id))
760 msg(
M_FATAL,
"PKCS#11: Cannot serialize certificate %ld-'%s'", rv,
761 pkcs11h_getMessage(rv));
765 if (rv == CKR_OK && (ser = (
char *)malloc(ser_len)) == NULL)
767 msg(
M_FATAL,
"PKCS#11: Cannot allocate memory");
772 pkcs11h_certificate_serializeCertificateId(ser, &ser_len, current->certificate_id))
775 msg(
M_FATAL,
"PKCS#11: Cannot serialize certificate %ld-'%s'", rv,
776 pkcs11h_getMessage(rv));
780 if ((rv = pkcs11h_certificate_create(current->certificate_id, NULL,
781 PKCS11H_PROMPT_MASK_ALLOW_ALL,
782 PKCS11H_PIN_CACHE_INFINITE, &certificate)))
784 msg(
M_FATAL,
"PKCS#11: Cannot create certificate %ld-'%s'", rv, pkcs11h_getMessage(rv));
788 if ((dn = pkcs11_certificate_dn(certificate, &
gc)) == NULL)
793 if ((pkcs11_certificate_serial(certificate, serial,
sizeof(serial))))
803 " Serialized id: %s\n"),
808 if (certificate != NULL)
810 pkcs11h_certificate_freeCertificate(certificate);
819 pkcs11h_certificate_freeCertificateIdList(user_certificates);
820 user_certificates = NULL;
bool buf_printf(struct buffer *buf, const char *format,...)
printf-style append to a buffer with overflow check.
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Allocate a buffer of the given size under garbage collection.
#define BSTR(buf)
Return the buffer content pointer cast to char *.
static void strncpynt(char *dest, const char *src, size_t maxlen)
Like strncpy() but always null-terminates the destination.
static void gc_free(struct gc_arena *a)
Free all allocations in a garbage collection arena.
static struct gc_arena gc_new(void)
Allocate and return a new, empty garbage collection arena.
static bool query_user_SINGLE(char *prompt, char *resp, int resp_len, bool echo)
A plain "make Gert happy" wrapper.
void purge_user_pass(struct user_pass *up, const bool force)
#define GET_USER_PASS_MANAGEMENT
#define GET_USER_PASS_PASSWORD_ONLY
#define GET_USER_PASS_NEED_OK
#define GET_USER_PASS_NOFATAL
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.
#define GET_USER_PASS_NEED_STR
msglvl_t get_debug_level(void)
static void update_time(void)
PKCS #11 SSL library-specific backend.
int openvpn_base64_encode(const void *data, int size, char **str)
Wrapper structure for dynamically allocated memory.
int len
Length in bytes of the actual content within the allocated memory.
Garbage collection arena used to keep track of dynamically allocated memory.
Structure that wraps the TLS context.
static int cleanup(void **state)
static bool pkcs11_id_management