OpenDNSSEC-libhsm 2.1.13
libhsm.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2009 .SE (The Internet Infrastructure Foundation).
3 * Copyright (c) 2009 NLNet Labs.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "config.h"
29
30#include <stdio.h>
31#include <string.h>
32#include <strings.h>
33#include <stdlib.h>
34#include <unistd.h>
35#include <dlfcn.h>
36#include <ldns/ldns.h>
37#include <ldns/util.h>
38
39#include <libxml/tree.h>
40#include <libxml/parser.h>
41#include <libxml/xpath.h>
42#include <libxml/xpathInternals.h>
43#include <libxml/relaxng.h>
44
45#include "libhsm.h"
46#include "libhsmdns.h"
47#include "compat.h"
48#include "duration.h"
49#include "status.h"
50#include "utilities.h"
51
52#include <pkcs11.h>
53#include <pthread.h>
54
56#define HSM_TOKEN_LABEL_LENGTH 32
57
60pthread_mutex_t _hsm_ctx_mutex = PTHREAD_MUTEX_INITIALIZER;
61
63static char const *
64ldns_pkcs11_rv_str(CK_RV rv)
65{
66 switch (rv)
67 {
68 case CKR_OK:
69 return "CKR_OK";
70 case CKR_CANCEL:
71 return "CKR_CANCEL";
72 case CKR_HOST_MEMORY:
73 return "CKR_HOST_MEMORY";
75 return "CKR_GENERAL_ERROR";
77 return "CKR_FUNCTION_FAILED";
79 return "CKR_SLOT_ID_INVALID";
81 return "CKR_ATTRIBUTE_READ_ONLY";
83 return "CKR_ATTRIBUTE_SENSITIVE";
85 return "CKR_ATTRIBUTE_TYPE_INVALID";
87 return "CKR_ATTRIBUTE_VALUE_INVALID";
89 return "CKR_DATA_INVALID";
91 return "CKR_DATA_LEN_RANGE";
93 return "CKR_DEVICE_ERROR";
95 return "CKR_DEVICE_MEMORY";
97 return "CKR_DEVICE_REMOVED";
99 return "CKR_ENCRYPTED_DATA_INVALID";
101 return "CKR_ENCRYPTED_DATA_LEN_RANGE";
103 return "CKR_FUNCTION_CANCELED";
105 return "CKR_FUNCTION_NOT_PARALLEL";
107 return "CKR_FUNCTION_NOT_SUPPORTED";
109 return "CKR_KEY_HANDLE_INVALID";
111 return "CKR_KEY_SIZE_RANGE";
113 return "CKR_KEY_TYPE_INCONSISTENT";
115 return "CKR_MECHANISM_INVALID";
117 return "CKR_MECHANISM_PARAM_INVALID";
119 return "CKR_OBJECT_HANDLE_INVALID";
121 return "CKR_OPERATION_ACTIVE";
123 return "CKR_OPERATION_NOT_INITIALIZED";
125 return "CKR_PIN_INCORRECT";
126 case CKR_PIN_INVALID:
127 return "CKR_PIN_INVALID";
129 return "CKR_PIN_LEN_RANGE";
131 return "CKR_SESSION_CLOSED";
133 return "CKR_SESSION_COUNT";
135 return "CKR_SESSION_HANDLE_INVALID";
137 return "CKR_SESSION_PARALLEL_NOT_SUPPORTED";
139 return "CKR_SESSION_READ_ONLY";
141 return "CKR_SESSION_EXISTS";
143 return "CKR_SIGNATURE_INVALID";
145 return "CKR_SIGNATURE_LEN_RANGE";
147 return "CKR_TEMPLATE_INCOMPLETE";
149 return "CKR_TEMPLATE_INCONSISTENT";
151 return "CKR_TOKEN_NOT_PRESENT";
153 return "CKR_TOKEN_NOT_RECOGNIZED";
155 return "CKR_TOKEN_WRITE_PROTECTED";
157 return "CKR_UNWRAPPING_KEY_HANDLE_INVALID";
159 return "CKR_UNWRAPPING_KEY_SIZE_RANGE";
161 return "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT";
163 return "CKR_USER_ALREADY_LOGGED_IN";
165 return "CKR_USER_NOT_LOGGED_IN";
167 return "CKR_USER_PIN_NOT_INITIALIZED";
169 return "CKR_USER_TYPE_INVALID";
171 return "CKR_WRAPPED_KEY_INVALID";
173 return "CKR_WRAPPED_KEY_LEN_RANGE";
175 return "CKR_WRAPPING_KEY_HANDLE_INVALID";
177 return "CKR_WRAPPING_KEY_SIZE_RANGE";
179 return "CKR_WRAPPING_KEY_TYPE_INCONSISTENT";
181 return "CKR_RANDOM_SEED_NOT_SUPPORTED";
182 /*CKR_VENDOR_DEFINED is not a constant but a macro which expands in to an */
183 /*expression. Which we are not allowed to use in a switch.*/
184 /*case CKR_VENDOR_DEFINED:*/
185 case 0x80000000:
186 return "CKR_VENDOR_DEFINED";
188 return "CKR_BUFFER_TOO_SMALL";
190 return "CKR_SAVED_STATE_INVALID";
192 return "CKR_INFORMATION_SENSITIVE";
194 return "CKR_STATE_UNSAVEABLE";
196 return "CKR_CRYPTOKI_NOT_INITIALIZED";
198 return "CKR_CRYPTOKI_ALREADY_INITIALIZED";
199 case CKR_MUTEX_BAD:
200 return "CKR_MUTEX_BAD";
202 return "CKR_MUTEX_NOT_LOCKED";
203 default:
204 return "Unknown error";
205 }
206}
207
208void
209hsm_ctx_set_error(hsm_ctx_t *ctx, int error, const char *action,
210 const char *message, ...)
211{
212 va_list args;
213
214 if (ctx && ctx->error == 0) {
215 ctx->error = error;
216 ctx->error_action = action;
217
218 va_start(args, message);
219 vsnprintf(ctx->error_message, sizeof(ctx->error_message),
220 message, args);
221 va_end(args);
222 }
223}
224
236static int
237hsm_pkcs11_check_error(hsm_ctx_t *ctx, CK_RV rv, const char *action)
238{
239 if (rv != CKR_OK) {
240 if (ctx && ctx->error == 0) {
241 ctx->error = (int) rv;
242 ctx->error_action = action;
243 strlcpy(ctx->error_message, ldns_pkcs11_rv_str(rv), sizeof(ctx->error_message));
244 }
245 return 1;
246 }
247 return 0;
248}
249
251static void
252hsm_pkcs11_unload_functions(void *handle)
253{
254 if (handle) {
255#if defined(HAVE_LOADLIBRARY)
256 /* no idea */
257#elif defined(HAVE_DLOPEN)
258 (void) dlclose(handle);
259#endif
260 }
261}
262
264static CK_RV
265hsm_pkcs11_load_functions(hsm_module_t *module)
266{
267 CK_C_GetFunctionList pGetFunctionList = NULL;
268
269 if (module && module->path) {
270 /* library provided by application or user */
271
272#if defined(HAVE_LOADLIBRARY)
273 /* Load PKCS #11 library */
274 HINSTANCE hDLL = LoadLibrary(_T(module->path));
275
276 if (hDLL == NULL) {
277 /* Failed to load the PKCS #11 library */
278 return CKR_FUNCTION_FAILED;
279 }
280
281 /* Retrieve the entry point for C_GetFunctionList */
282 pGetFunctionList = (CK_C_GetFunctionList)
283 GetProcAddress(hDLL, _T("C_GetFunctionList"));
284
285#elif defined(HAVE_DLOPEN)
286 /* Load PKCS #11 library */
287 void* pDynLib = dlopen(module->path, RTLD_NOW | RTLD_LOCAL);
288
289 if (pDynLib == NULL) {
290 /* Failed to load the PKCS #11 library */
291 return CKR_FUNCTION_FAILED;
292 }
293
294 /* Retrieve the entry point for C_GetFunctionList */
295 pGetFunctionList = (CK_C_GetFunctionList) functioncast(dlsym(pDynLib, "C_GetFunctionList"));
296 /* Store the handle so we can dlclose it later */
297 module->handle = pDynLib;
298
299#else
300 return CKR_FUNCTION_FAILED;
301#endif
302 } else {
303 /* No library provided, use the statically compiled softHSM */
304#ifdef HAVE_PKCS11_MODULE
305 return C_GetFunctionList(pkcs11_functions);
306#else
307 return CKR_FUNCTION_FAILED;
308#endif
309 }
310
311 if (pGetFunctionList == NULL) {
312 /* Failed to load the PKCS #11 library */
313 return CKR_FUNCTION_FAILED;
314 }
315
316 /* Retrieve the function list */
317 (pGetFunctionList)((CK_FUNCTION_LIST_PTR_PTR)(&module->sym));
318 return CKR_OK;
319}
320
321static void
322hsm_remove_leading_zeroes(CK_BYTE_PTR data, CK_ULONG *len)
323{
324 CK_BYTE_PTR p = data;
325 CK_ULONG l;
326
327 if (data == NULL || len == NULL) return;
328
329 l = *len;
330
331 while ((unsigned short int)(*p) == 0 && l > 1) {
332 p++;
333 l--;
334 }
335
336 if (p != data) {
337 memmove(data, p, l);
338 *len = l;
339 }
340}
341
342static int
343hsm_pkcs11_check_token_name(hsm_ctx_t *ctx,
344 CK_FUNCTION_LIST_PTR pkcs11_functions,
345 CK_SLOT_ID slotId,
346 const char *token_name)
347{
348 /* token label is always 32 bytes */
349 char token_name_bytes[HSM_TOKEN_LABEL_LENGTH];
350 int result = 0;
351 CK_RV rv;
352 CK_TOKEN_INFO token_info;
353
354 rv = pkcs11_functions->C_GetTokenInfo(slotId, &token_info);
355 if (hsm_pkcs11_check_error(ctx, rv, "C_GetTokenInfo")) {
356 return 0;
357 }
358
359 memset(token_name_bytes, ' ', HSM_TOKEN_LABEL_LENGTH);
360 if (strlen(token_name) < HSM_TOKEN_LABEL_LENGTH) {
361 memcpy(token_name_bytes, token_name, strlen(token_name));
362 } else {
363 memcpy(token_name_bytes, token_name, HSM_TOKEN_LABEL_LENGTH);
364 }
365
366 result = memcmp(token_info.label,
367 token_name_bytes,
369
370 return result;
371}
372
374hsm_repository_new(char* name, char* module, char* tokenlabel, char* pin,
375 uint8_t use_pubkey, uint8_t allowextract, uint8_t require_backup)
376{
378
379 if (!name || !module || !tokenlabel) return NULL;
380
381 r = malloc(sizeof(hsm_repository_t));
382 if (!r) return NULL;
383
384 r->next = NULL;
385 r->pin = NULL;
386 r->name = strdup(name);
387 r->module = strdup(module);
388 r->tokenlabel = strdup(tokenlabel);
389 if (!r->name || !r->module || !r->tokenlabel) {
391 return NULL;
392 }
393 if (pin) {
394 r->pin = strdup(pin);
395 if (!r->pin) {
397 return NULL;
398 }
399 }
400 r->use_pubkey = use_pubkey;
401 r->allow_extract = allowextract;
402 r->require_backup = require_backup;
403 return r;
404}
405
406void
408{
409 if (r) {
410 if (r->next) hsm_repository_free(r->next);
411 if (r->name) free(r->name);
412 if (r->module) free(r->module);
413 if (r->tokenlabel) free(r->tokenlabel);
414 if (r->pin) free(r->pin);
415 }
416 free(r);
417}
418
419static int
420hsm_get_slot_id(hsm_ctx_t *ctx,
421 CK_FUNCTION_LIST_PTR pkcs11_functions,
422 const char *token_name, CK_SLOT_ID *slotId)
423{
424 CK_RV rv;
425 CK_ULONG slotCount;
426 CK_SLOT_ID cur_slot;
427 CK_SLOT_ID *slotIds;
428 int found = 0;
429
430 if (token_name == NULL || slotId == NULL) return HSM_ERROR;
431
432 rv = pkcs11_functions->C_GetSlotList(CK_TRUE, NULL_PTR, &slotCount);
433 if (hsm_pkcs11_check_error(ctx, rv, "get slot list")) {
434 return HSM_ERROR;
435 }
436
437 if (slotCount < 1) {
438 hsm_ctx_set_error(ctx, HSM_ERROR, "hsm_get_slot_id()",
439 "No slots found in HSM");
440 return HSM_ERROR;
441 } else if (slotCount > (SIZE_MAX / sizeof(CK_SLOT_ID))) {
442 hsm_ctx_set_error(ctx, HSM_ERROR, "hsm_get_slot_id()",
443 "Too many slots found in HSM");
444 return HSM_ERROR;
445 }
446
447 CHECKALLOC(slotIds = malloc(sizeof(CK_SLOT_ID) * slotCount));
448
449 rv = pkcs11_functions->C_GetSlotList(CK_TRUE, slotIds, &slotCount);
450 if (hsm_pkcs11_check_error(ctx, rv, "get slot list")) {
451 return HSM_ERROR;
452 }
453
454 for (cur_slot = 0; cur_slot < slotCount; cur_slot++) {
455 if (hsm_pkcs11_check_token_name(ctx,
456 pkcs11_functions,
457 slotIds[cur_slot],
458 token_name)) {
459 *slotId = slotIds[cur_slot];
460 found = 1;
461 break;
462 }
463 }
464 free(slotIds);
465 if (!found) {
466 hsm_ctx_set_error(ctx, -1, "hsm_get_slot_id()",
467 "could not find token with the name %s", token_name);
468 return HSM_ERROR;
469 }
470
471 return HSM_OK;
472}
473
474/* internal functions */
475static hsm_module_t *
476hsm_module_new(const char *repository,
477 const char *token_label,
478 const char *path,
479 const hsm_config_t *config)
480{
481 hsm_module_t *module;
482
483 if (!repository || !path) return NULL;
484
485
486 CHECKALLOC(module = malloc(sizeof(hsm_module_t)));
487
488 if (config) {
489 CHECKALLOC(module->config = malloc(sizeof(hsm_config_t)));
490 memcpy(module->config, config, sizeof(hsm_config_t));
491 } else {
492 module->config = NULL;
493 }
494
495 module->id = 0; /*TODO i think we can remove this*/
496 module->name = strdup(repository);
497 module->token_label = strdup(token_label);
498 module->path = dupstr(path);
499 module->handle = NULL;
500 module->sym = NULL;
501
502 return module;
503}
504
505static void
506hsm_module_free(hsm_module_t *module)
507{
508 if (module) {
509 if (module->name) free(module->name);
510 if (module->token_label) free(module->token_label);
511 if (module->path) free(module->path);
512 if (module->config) free(module->config);
513
514 free(module);
515 }
516}
517
518static hsm_session_t *
519hsm_session_new(hsm_module_t *module, CK_SESSION_HANDLE session_handle)
520{
521 hsm_session_t *session;
522 CHECKALLOC(session = malloc(sizeof(hsm_session_t)));
523 session->module = module;
524 session->session = session_handle;
525 return session;
526}
527
528static void
529hsm_session_free(hsm_session_t *session) {
530 if (session) {
531 free(session);
532 }
533}
534
536static void
537hsm_config_default(hsm_config_t *config)
538{
539 config->use_pubkey = 1;
540 config->allow_extract = 0;
541}
542
543/* creates a session_t structure, and automatically adds and initializes
544 * a module_t struct for it
545 */
546static int
547hsm_session_init(hsm_ctx_t *ctx, hsm_session_t **session,
548 const char *repository, const char *token_label,
549 const char *module_path, const char *pin,
550 const hsm_config_t *config)
551{
552 CK_RV rv;
553 CK_RV rv_login;
554 hsm_module_t *module;
555 CK_SLOT_ID slot_id;
556 CK_SESSION_HANDLE session_handle;
557 int first = 1, result;
558
559 CK_C_INITIALIZE_ARGS InitArgs = {NULL, NULL, NULL, NULL,
560 CKF_OS_LOCKING_OK, NULL };
561
562 if (pin == NULL) return HSM_ERROR;
563
564 module = hsm_module_new(repository, token_label, module_path, config);
565 if (!module) return HSM_ERROR;
566 rv = hsm_pkcs11_load_functions(module);
567 if (rv != CKR_OK) {
569 "hsm_session_init()",
570 "PKCS#11 module load failed: %s", module_path);
571 hsm_module_free(module);
573 }
574 rv = ((CK_FUNCTION_LIST_PTR) module->sym)->C_Initialize((CK_VOID_PTR) &InitArgs);
575 /* ALREADY_INITIALIZED is ok, apparently we are using a second
576 * device with the same library */
578 if (hsm_pkcs11_check_error(ctx, rv, "Initialization")) {
579 hsm_module_free(module);
580 return HSM_ERROR;
581 }
582 } else {
583 first = 0;
584 }
585 result = hsm_get_slot_id(ctx, module->sym, token_label, &slot_id);
586 if (result != HSM_OK) {
587 hsm_module_free(module);
588 return HSM_ERROR;
589 }
590 rv = ((CK_FUNCTION_LIST_PTR) module->sym)->C_OpenSession(slot_id,
592 NULL,
593 NULL,
594 &session_handle);
595 if (hsm_pkcs11_check_error(ctx, rv, "Open first session")) {
596 hsm_module_free(module);
597 return HSM_ERROR;
598 }
599 rv_login = ((CK_FUNCTION_LIST_PTR) module->sym)->C_Login(session_handle,
600 CKU_USER,
601 (unsigned char *) pin,
602 strlen((char *)pin));
603
604 if (rv_login == CKR_OK || rv_login == CKR_USER_ALREADY_LOGGED_IN) {
605 *session = hsm_session_new(module, session_handle);
606 return HSM_OK;
607 } else {
608 /* uninitialize the session again */
609 if (session_handle) {
610 rv = ((CK_FUNCTION_LIST_PTR) module->sym)->
611 C_CloseSession(session_handle);
612 if (hsm_pkcs11_check_error(ctx, rv,
613 "finalize after failed login")) {
614 hsm_module_free(module);
615 return HSM_ERROR;
616 }
617 }
618 /* if this was not the first, don't close the library for
619 * the rest of us */
620 if (first) {
621 rv = ((CK_FUNCTION_LIST_PTR) module->sym)->C_Finalize(NULL);
622 if (hsm_pkcs11_check_error(ctx, rv, "finalize after failed login")) {
623 hsm_module_free(module);
624 return HSM_ERROR;
625 }
626 }
627 hsm_module_free(module);
628 *session = NULL;
629 switch(rv_login) {
632 "hsm_session_init()",
633 "Incorrect PIN for repository %s", repository);
634 return HSM_PIN_INCORRECT;
635 default:
636 return HSM_ERROR;
637 }
638 }
639}
640
641/* open a second session from the given one */
642static hsm_session_t *
643hsm_session_clone(hsm_ctx_t *ctx, hsm_session_t *session)
644{
645 CK_RV rv;
646 CK_SLOT_ID slot_id;
647 CK_SESSION_HANDLE session_handle;
648 hsm_session_t *new_session;
649 int result;
650
651 result = hsm_get_slot_id(ctx,
652 session->module->sym,
653 session->module->token_label,
654 &slot_id);
655 if (result != HSM_OK) return NULL;
656 rv = ((CK_FUNCTION_LIST_PTR) session->module->sym)->C_OpenSession(slot_id,
658 NULL,
659 NULL,
660 &session_handle);
661
662 if (hsm_pkcs11_check_error(ctx, rv, "Clone session")) {
663 return NULL;
664 }
665 new_session = hsm_session_new(session->module, session_handle);
666
667 return new_session;
668}
669
670static hsm_ctx_t *
671hsm_ctx_new()
672{
673 hsm_ctx_t *ctx;
674 CHECKALLOC(ctx = malloc(sizeof(hsm_ctx_t)));
675 memset(ctx->session, 0, HSM_MAX_SESSIONS * sizeof(hsm_ctx_t*));
676 ctx->session_count = 0;
677 ctx->error = 0;
678 return ctx;
679}
680
681/* ctx_free frees the structure */
682static void
683hsm_ctx_free(hsm_ctx_t *ctx)
684{
685 unsigned int i;
686
687 if (ctx) {
688 for (i = 0; i < ctx->session_count; i++) {
689 hsm_session_free(ctx->session[i]);
690 }
691 free(ctx);
692 }
693}
694
695/* close the session, and free the allocated data
696 *
697 * if unload is non-zero, C_Logout() is called,
698 * the dlopen()d module is closed and unloaded
699 * (only call this on the last session for each
700 * module, ie. the one in the global ctx)
701 */
702static void
703hsm_session_close(hsm_ctx_t *ctx, hsm_session_t *session, int unload)
704{
705 /* If we loaded this library more than once, we may have
706 * already finalized it before, so we can safely ignore
707 * NOT_INITIALIZED */
708 CK_RV rv;
709 if (unload) {
710 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Logout(session->session);
712 (void) hsm_pkcs11_check_error(ctx, rv, "Logout");
713 }
714 }
715 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_CloseSession(session->session);
717 (void) hsm_pkcs11_check_error(ctx, rv, "Close session");
718 }
719 if (unload) {
720 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Finalize(NULL);
722 (void) hsm_pkcs11_check_error(ctx, rv, "Finalize");
723 hsm_pkcs11_unload_functions(session->module->handle);
724 }
725 hsm_module_free(session->module);
726 session->module = NULL;
727 }
728 hsm_session_free(session);
729}
730
731/* ctx_close closes all session, and free
732 * the structures.
733 *
734 * if unload is non-zero, the associated dynamic libraries are unloaded
735 * (hence only use that on the last, global, ctx)
736 */
737static void
738hsm_ctx_close(hsm_ctx_t *ctx, int unload)
739{
740 size_t i;
741
742 if (!ctx) return;
743 for (i = 0; i < ctx->session_count; i++) {
744 hsm_session_close(ctx, ctx->session[i], unload);
745 ctx->session[i] = NULL;
746 }
747 hsm_ctx_free(ctx);
748
749}
750
751
752/* adds a session to the context.
753 * returns 0 on success
754 * 1 if the maximum number of sessions (HSM_MAX_SESSIONS) was
755 * reached
756 * -1 if one of the arguments is NULL
757 */
758static int
759hsm_ctx_add_session(hsm_ctx_t *ctx, hsm_session_t *session)
760{
761 if (!ctx || !session) return -1;
762 if (ctx->session_count >= HSM_MAX_SESSIONS) return 1;
763 ctx->session[ctx->session_count] = session;
765 return 0;
766}
767
768static hsm_ctx_t *
769hsm_ctx_clone(hsm_ctx_t *ctx)
770{
771 unsigned int i;
772 hsm_ctx_t *new_ctx;
773 hsm_session_t *new_session;
774
775 new_ctx = NULL;
776 if (ctx) {
777 new_ctx = hsm_ctx_new();
778 for (i = 0; i < ctx->session_count; i++) {
779 new_session = hsm_session_clone(ctx, ctx->session[i]);
780 if (!new_session) {
781 /* one of the sessions failed to clone. Clear the
782 * new ctx and return NULL */
783 hsm_ctx_close(new_ctx, 0);
784 return NULL;
785 }
786 hsm_ctx_add_session(new_ctx, new_session);
787 }
788 new_ctx->keycache = ctx->keycache;
789 new_ctx->keycache_lock = ctx->keycache_lock;
790 }
791 return new_ctx;
792}
793
794static libhsm_key_t *
795libhsm_key_new()
796{
797 libhsm_key_t *key;
798 CHECKALLOC(key = malloc(sizeof(libhsm_key_t)));
799 key->modulename = NULL;
800 key->private_key = 0;
801 key->public_key = 0;
802 return key;
803}
804
805/* find the session belonging to a key, by iterating over the modules
806 * in the context */
807static hsm_session_t *
808hsm_find_key_session(hsm_ctx_t *ctx, const libhsm_key_t *key)
809{
810 unsigned int i;
811 if (!key || !key->modulename) return NULL;
812 for (i = 0; i < ctx->session_count; i++) {
813 if (ctx->session[i] && !strcmp(ctx->session[i]->module->name, key->modulename)) {
814 return ctx->session[i];
815 }
816 }
817 return NULL;
818}
819
820/* Returns the key type (algorithm) of the given key */
821static CK_KEY_TYPE
822hsm_get_key_algorithm(hsm_ctx_t *ctx, const hsm_session_t *session,
823 const libhsm_key_t *key)
824{
825 CK_RV rv;
826 CK_KEY_TYPE key_type;
827
828 CK_ATTRIBUTE template[] = {
829 {CKA_KEY_TYPE, &key_type, sizeof(CK_KEY_TYPE)}
830 };
831
832 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
833 session->session,
834 key->private_key,
835 template,
836 1);
837 if (hsm_pkcs11_check_error(ctx, rv,
838 "Get attr value algorithm type")) {
839 /* this is actually not a good return value;
840 * CKK_RSA is also 0. But we can't return a negative
841 * value. Should we #define a specific 'key type' that
842 * indicates an error? (TODO) */
843 return 0;
844 }
845
846 if ((CK_LONG)template[0].ulValueLen < 1) {
847 /* this is actually not a good return value;
848 * CKK_RSA is also 0. But we can't return a negative
849 * value. Should we #define a specific 'key type' that
850 * indicates an error? (TODO) */
851 return 0;
852 }
853
854 return key_type;
855}
856
857/* returns a CK_ULONG with the key size of the given RSA key. The
858 * key is not checked for type. For RSA, the number of bits in the
859 * modulus is the key size (CKA_MODULUS_BITS)
860 */
861static CK_ULONG
862hsm_get_key_size_rsa(hsm_ctx_t *ctx, const hsm_session_t *session,
863 const libhsm_key_t *key)
864{
865 CK_RV rv;
866 CK_ULONG modulus_bits;
867
868 /* Template for public keys */
869 CK_ATTRIBUTE template[] = {
870 {CKA_MODULUS_BITS, &modulus_bits, sizeof(CK_KEY_TYPE)}
871 };
872
873 /* Template for private keys */
874 CK_BYTE_PTR modulus = NULL;
875 int mask;
876 CK_ATTRIBUTE template2[] = {
877 {CKA_MODULUS, NULL, 0}
878 };
879
880 if (key->public_key) {
881 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
882 session->session,
883 key->public_key,
884 template,
885 1);
886 if (hsm_pkcs11_check_error(ctx, rv,
887 "Get attr value algorithm type")) {
888 return 0;
889 }
890
891 if ((CK_ULONG)template[0].ulValueLen < 1) {
892 return 0;
893 }
894 } else {
895 // Get buffer size
896 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
897 session->session,
898 key->private_key,
899 template2,
900 1);
901 if (hsm_pkcs11_check_error(ctx, rv, "Could not get the size of the modulus of the private key")) {
902 return 0;
903 }
904
905 // Allocate memory
906 modulus = (CK_BYTE_PTR)malloc(template2[0].ulValueLen);
907 template2[0].pValue = modulus;
908 if (modulus == NULL) {
909 hsm_ctx_set_error(ctx, -1, "hsm_get_key_size_rsa()",
910 "Error allocating memory for modulus");
911 return 0;
912 }
913
914 // Get attribute
915 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
916 session->session,
917 key->private_key,
918 template2,
919 1);
920 if (hsm_pkcs11_check_error(ctx, rv, "Could not get the modulus of the private key")) {
921 free(modulus);
922 return 0;
923 }
924
925 // Calculate size
926 modulus_bits = template2[0].ulValueLen * 8;
927 mask = 0x80;
928 for (int i = 0; modulus_bits && (modulus[i] & mask) == 0; modulus_bits--) {
929 mask >>= 1;
930 if (mask == 0) {
931 i++;
932 mask = 0x80;
933 }
934 }
935 free(modulus);
936 }
937
938 return modulus_bits;
939}
940
941/* returns a CK_ULONG with the key size of the given DSA key. The
942 * key is not checked for type. For DSA, the number of bits in the
943 * prime is the key size (CKA_PRIME)
944 */
945static CK_ULONG
946hsm_get_key_size_dsa(hsm_ctx_t *ctx, const hsm_session_t *session,
947 const libhsm_key_t *key)
948{
949 CK_RV rv;
950
951 /* Template */
952 CK_ATTRIBUTE template2[] = {
953 {CKA_PRIME, NULL, 0}
954 };
955
956 // Get buffer size
957 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
958 session->session,
959 key->private_key,
960 template2,
961 1);
962 if (hsm_pkcs11_check_error(ctx, rv, "Could not get the size of the prime of the private key")) {
963 return 0;
964 }
965
966 return template2[0].ulValueLen * 8;
967}
968
969/* Returns the DER decoded value of Q for ECDSA key
970 * Byte string with uncompressed form of a curve point, "x | y"
971 */
972static unsigned char *
973hsm_get_key_ecdsa_value(hsm_ctx_t *ctx, const hsm_session_t *session,
974 const libhsm_key_t *key, CK_ULONG *data_len)
975{
976 CK_RV rv;
977 CK_BYTE_PTR value = NULL;
978 CK_BYTE_PTR data = NULL;
980 CK_ULONG header_len = 0;
981
982 CK_ATTRIBUTE template[] = {
983 {CKA_EC_POINT, NULL, 0},
984 };
985
986 if (!session || !session->module || !key || !data_len) {
987 return NULL;
988 }
989
990 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
991 session->session,
992 key->public_key,
993 template,
994 1);
995 if (hsm_pkcs11_check_error(ctx, rv, "C_GetAttributeValue")) {
996 return NULL;
997 }
998 value_len = template[0].ulValueLen;
999
1000 CHECKALLOC(value = template[0].pValue = malloc(value_len));
1001 memset(value, 0, value_len);
1002
1003 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1004 session->session,
1005 key->public_key,
1006 template,
1007 1);
1008 if (hsm_pkcs11_check_error(ctx, rv, "get attribute value")) {
1009 free(value);
1010 return NULL;
1011 }
1012
1013 if(value_len != template[0].ulValueLen) {
1014 hsm_ctx_set_error(ctx, -1, "hsm_get_key_ecdsa_value()",
1015 "HSM returned two different length for a same CKA_EC_POINT. " \
1016 "Abnormal behaviour detected.");
1017 free(value);
1018 return NULL;
1019 }
1020
1021 /* Check that we have the first two octets */
1022 if (value_len < 2) {
1023 hsm_ctx_set_error(ctx, -1, "hsm_get_key_ecdsa_value()",
1024 "The DER value is too short");
1025 free(value);
1026 return NULL;
1027 }
1028
1029 /* Check the identifier octet, PKCS#11 requires octet string */
1030 if (value[0] != 0x04) {
1031 hsm_ctx_set_error(ctx, -1, "hsm_get_key_ecdsa_value()",
1032 "Invalid identifier octet in the DER value");
1033 free(value);
1034 return NULL;
1035 }
1036 header_len++;
1037
1038 /* Check the length octets, but we do not validate the length */
1039 if (value[1] <= 0x7F) {
1040 header_len++;
1041 } else if (value[1] == 0x80) {
1042 hsm_ctx_set_error(ctx, -1, "hsm_get_key_ecdsa_value()",
1043 "Indefinite length is not supported in DER values");
1044 free(value);
1045 return NULL;
1046 } else {
1047 header_len++;
1048 header_len += value[1] & 0x80;
1049 }
1050
1051 /* Check that we have more data than the header */
1052 if (value_len - header_len < 2) {
1053 hsm_ctx_set_error(ctx, -1, "hsm_get_key_ecdsa_value()",
1054 "The value is too short");
1055 free(value);
1056 return NULL;
1057 }
1058
1059 /* Check that we have uncompressed data */
1060 /* TODO: Not supporting compressed data */
1061 if (value[header_len] != 0x04) {
1062 hsm_ctx_set_error(ctx, -1, "hsm_get_key_ecdsa_value()",
1063 "The value is not uncompressed");
1064 free(value);
1065 return NULL;
1066 }
1067 header_len++;
1068
1069 *data_len = value_len - header_len;
1070 CHECKALLOC(data = malloc(*data_len));
1071
1072 memcpy(data, value + header_len, *data_len);
1073 free(value);
1074
1075 return data;
1076}
1077
1078/* returns a CK_ULONG with the key size of the given ECDSA key. The
1079 * key is not checked for type. For ECDSA, the number of bits in the
1080 * value X is the key size
1081 */
1082static CK_ULONG
1083hsm_get_key_size_ecdsa(hsm_ctx_t *ctx, const hsm_session_t *session,
1084 const libhsm_key_t *key)
1085{
1087 unsigned char* value = hsm_get_key_ecdsa_value(ctx, session, key, &value_len);
1088 CK_ULONG bits = 0;
1089
1090 if (value == NULL) return 0;
1091
1092 if( ((CK_ULONG) - 1) / (8/2) < value_len) {
1093 free(value);
1094 return 0;
1095 }
1096
1097 /* value = x | y */
1098 bits = value_len * 8 / 2;
1099 free(value);
1100
1101 return bits;
1102}
1103
1104/* Returns the DER decoded value of the EDDSA public key
1105 * Byte string with b-bit public key in little endian order
1106 */
1107static unsigned char *
1108hsm_get_key_eddsa_value(hsm_ctx_t *ctx, const hsm_session_t *session,
1109 const libhsm_key_t *key, CK_ULONG *data_len)
1110{
1111 CK_RV rv;
1112 CK_BYTE_PTR value = NULL;
1113 CK_BYTE_PTR data = NULL;
1114 CK_ULONG value_len = 0;
1115 CK_ULONG header_len = 0;
1116
1117 CK_ATTRIBUTE template[] = {
1118 {CKA_EC_POINT, NULL, 0},
1119 };
1120
1121 if (!session || !session->module || !key || !data_len) {
1122 return NULL;
1123 }
1124
1125 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1126 session->session,
1127 key->public_key,
1128 template,
1129 1);
1130 if (hsm_pkcs11_check_error(ctx, rv, "C_GetAttributeValue")) {
1131 return NULL;
1132 }
1133 value_len = template[0].ulValueLen;
1134
1135 value = template[0].pValue = malloc(value_len);
1136 if (!value) {
1137 hsm_ctx_set_error(ctx, -1, "hsm_get_key_eddsa_value()",
1138 "Error allocating memory for value");
1139 return NULL;
1140 }
1141 memset(value, 0, value_len);
1142
1143 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1144 session->session,
1145 key->public_key,
1146 template,
1147 1);
1148 if (hsm_pkcs11_check_error(ctx, rv, "get attribute value")) {
1149 free(value);
1150 return NULL;
1151 }
1152
1153 if(value_len != template[0].ulValueLen) {
1154 hsm_ctx_set_error(ctx, -1, "hsm_get_key_eddsa_value()",
1155 "HSM returned two different length for the same CKA_EC_POINT. " \
1156 "Abnormal behaviour detected.");
1157 free(value);
1158 return NULL;
1159 }
1160
1161 /* Check that we have the first two octets */
1162 if (value_len < 2) {
1163 hsm_ctx_set_error(ctx, -1, "hsm_get_key_eddsa_value()",
1164 "The DER value is too short");
1165 free(value);
1166 return NULL;
1167 }
1168
1169 /* Check the identifier octet, PKCS#11 requires octet string */
1170 if (value[0] != 0x04) {
1171 hsm_ctx_set_error(ctx, -1, "hsm_get_key_eddsa_value()",
1172 "Invalid identifier octet in the DER value");
1173 free(value);
1174 return NULL;
1175 }
1176 header_len++;
1177
1178 /* Check the length octets, but we do not validate the length */
1179 if (value[1] <= 0x7F) {
1180 header_len++;
1181 } else if (value[1] == 0x80) {
1182 hsm_ctx_set_error(ctx, -1, "hsm_get_key_eddsa_value()",
1183 "Indefinite length is not supported in DER values");
1184 free(value);
1185 return NULL;
1186 } else {
1187 header_len++;
1188 header_len += value[1] & 0x80;
1189 }
1190
1191 /* Check that we have more data than the header */
1192 if (value_len - header_len < 2) {
1193 hsm_ctx_set_error(ctx, -1, "hsm_get_key_eddsa_value()",
1194 "The value is too short");
1195 free(value);
1196 return NULL;
1197 }
1198
1199 *data_len = value_len - header_len;
1200 data = malloc(*data_len);
1201 if (data == NULL) {
1202 hsm_ctx_set_error(ctx, -1, "hsm_get_key_eddsa_value()",
1203 "Error allocating memory for data");
1204 free(value);
1205 return NULL;
1206 }
1207
1208 memcpy(data, value + header_len, *data_len);
1209 free(value);
1210
1211 return data;
1212}
1213
1214/* returns a CK_ULONG with the key size of the given EDDSA key. The
1215 * key is not checked for type. For EDDSA, the key size is the number
1216 * of bits in the curve not the size of the public key representation,
1217 * which is larger.
1218 */
1219static CK_ULONG
1220hsm_get_key_size_eddsa(hsm_ctx_t *ctx, const hsm_session_t *session,
1221 const libhsm_key_t *key)
1222{
1224 unsigned char* value = hsm_get_key_eddsa_value(ctx, session, key, &value_len);
1225 CK_ULONG bits = 0;
1226
1227 if (value == NULL) return 0;
1228
1229 if( ((CK_ULONG) - 1) / 8 < value_len) {
1230 free(value);
1231 return 0;
1232 }
1233
1234 bits = value_len * 8;
1235 free(value);
1236
1237 switch (bits) {
1238 // ED25519 keys are 255 bits represented as 256 bits (RFC8080 section 3)
1239 case 256:
1240 bits = 255;
1241 break;
1242 // ED448 keys are 448 bits represented as 456 bits (RFC8080 section 3)
1243 case 456:
1244 bits = 448;
1245 break;
1246 default:
1247 bits = 0;
1248 break;
1249 }
1250
1251 return bits;
1252}
1253
1254/* Wrapper for specific key size functions */
1255static CK_ULONG
1256hsm_get_key_size(hsm_ctx_t *ctx, const hsm_session_t *session,
1257 const libhsm_key_t *key, const unsigned long algorithm)
1258{
1259 switch (algorithm) {
1260 case CKK_RSA:
1261 return hsm_get_key_size_rsa(ctx, session, key);
1262 break;
1263 case CKK_DSA:
1264 return hsm_get_key_size_dsa(ctx, session, key);
1265 break;
1266 case CKK_GOSTR3410:
1267 /* GOST public keys always have a size of 512 bits */
1268 return 512;
1269 case CKK_EC:
1270 return hsm_get_key_size_ecdsa(ctx, session, key);
1271 case CKK_EC_EDWARDS:
1272 return hsm_get_key_size_eddsa(ctx, session, key);
1273 default:
1274 return 0;
1275 }
1276}
1277
1278static CK_OBJECT_HANDLE
1279hsm_find_object_handle_for_id(hsm_ctx_t *ctx,
1280 const hsm_session_t *session,
1281 CK_OBJECT_CLASS key_class,
1282 CK_BYTE *id,
1283 CK_ULONG id_len)
1284{
1285 CK_ULONG objectCount;
1286 CK_OBJECT_HANDLE object;
1287 CK_RV rv;
1288
1289 CK_ATTRIBUTE template[] = {
1290 { CKA_CLASS, &key_class, sizeof(key_class) },
1291 { CKA_ID, id, id_len },
1292 };
1293
1294 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjectsInit(session->session,
1295 template, 2);
1296 if (hsm_pkcs11_check_error(ctx, rv, "Find objects init")) {
1297 return 0;
1298 }
1299
1300 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjects(session->session,
1301 &object,
1302 1,
1303 &objectCount);
1304 if (hsm_pkcs11_check_error(ctx, rv, "Find object")) {
1305 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjectsFinal(session->session);
1306 hsm_pkcs11_check_error(ctx, rv, "Find objects cleanup");
1307 return 0;
1308 }
1309
1310 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjectsFinal(session->session);
1311 if (hsm_pkcs11_check_error(ctx, rv, "Find object final")) {
1312 return 0;
1313 }
1314
1315 if (objectCount > 0) {
1316 return object;
1317 } else {
1318 return 0;
1319 }
1320}
1321
1322/*
1323 * Parses the null-terminated string hex as hex values,
1324 * Returns allocated data that needs to be freed (or NULL on error)
1325 * len will contain the number of bytes allocated, or 0 on error
1326 */
1327static unsigned char *
1328hsm_hex_parse(const char *hex, size_t *len)
1329{
1330 unsigned char *bytes;
1331 /* length of the hex input */
1332 size_t hex_len;
1333 size_t i;
1334
1335 if (!len) return NULL;
1336 *len = 0;
1337
1338 if (!hex) return NULL;
1339 hex_len = strlen(hex);
1340 if (hex_len % 2 != 0) {
1341 return NULL;
1342 }
1343
1344 *len = hex_len / 2;
1345 CHECKALLOC(bytes = malloc(*len));
1346 for (i = 0; i < *len; i++) {
1347 bytes[i] = ldns_hexdigit_to_int(hex[2*i]) * 16 +
1348 ldns_hexdigit_to_int(hex[2*i+1]);
1349 }
1350 return bytes;
1351}
1352
1353/* put a hexadecimal representation of the data from src into dst
1354 * len is the number of bytes to read from src
1355 * dst must have allocated enough space (len*2 + 1)
1356 */
1357static void
1358hsm_hex_unparse(char *dst, const unsigned char *src, size_t len)
1359{
1360 size_t dst_len = len*2 + 1;
1361 size_t i;
1362
1363 for (i = 0; i < len; i++) {
1364 snprintf(dst + (2*i), dst_len, "%02x", src[i]);
1365 }
1366 dst[len*2] = '\0';
1367}
1368
1369/* returns an allocated byte array with the CKA_ID for the given object
1370 * len will contain the result size
1371 * returns NULL and size zero if not found in this session
1372 */
1373static CK_BYTE *
1374hsm_get_id_for_object(hsm_ctx_t *ctx,
1375 const hsm_session_t *session,
1376 CK_OBJECT_HANDLE object,
1377 size_t *len)
1378{
1379 CK_RV rv;
1380 CK_BYTE *id = NULL;
1381
1382 CK_ATTRIBUTE template[] = {
1383 {CKA_ID, id, 0}
1384 };
1385
1386 /* find out the size of the id first */
1387 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1388 session->session,
1389 object,
1390 template,
1391 1);
1392 if (hsm_pkcs11_check_error(ctx, rv, "Get attr value")) {
1393 *len = 0;
1394 return NULL;
1395 }
1396
1397 if ((CK_LONG)template[0].ulValueLen < 1) {
1398 /* No CKA_ID found, return NULL */
1399 *len = 0;
1400 return NULL;
1401 }
1402
1403 CHECKALLOC(template[0].pValue = malloc(template[0].ulValueLen));
1404 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1405 session->session,
1406 object,
1407 template,
1408 1);
1409 if (hsm_pkcs11_check_error(ctx, rv, "Get attr value 2")) {
1410 *len = 0;
1411 free(template[0].pValue);
1412 return NULL;
1413 }
1414
1415 *len = template[0].ulValueLen;
1416 return template[0].pValue;
1417}
1418
1419/* returns an libhsm_key_t object for the given *private key* object handle
1420 * the module, private key, and public key handle are set
1421 * The session needs to be free to perform a search for the public key
1422 */
1423static libhsm_key_t *
1424libhsm_key_new_privkey_object_handle(hsm_ctx_t *ctx,
1425 const hsm_session_t *session,
1426 CK_OBJECT_HANDLE object)
1427{
1428 libhsm_key_t *key;
1429 CK_BYTE *id;
1430 size_t len;
1431
1432 id = hsm_get_id_for_object(ctx, session, object, &len);
1433
1434 if (!id) return NULL;
1435
1436 key = libhsm_key_new();
1437 key->modulename = strdup(session->module->name);
1438 key->private_key = object;
1439
1440 key->public_key = hsm_find_object_handle_for_id(
1441 ctx,
1442 session,
1444 id,
1445 len);
1446
1447 free(id);
1448 return key;
1449}
1450
1451/* helper function to find both key counts or the keys themselves
1452 * if the argument store is 0, results are not returned; the
1453 * function will only set the count and return NULL
1454 * Otherwise, a newly allocated key array will be returned
1455 * (on error, the count will also be zero and NULL returned)
1456 */
1457static libhsm_key_t **
1458hsm_list_keys_session_internal(hsm_ctx_t *ctx,
1459 const hsm_session_t *session,
1460 size_t *count,
1461 int store)
1462{
1463 libhsm_key_t **keys = NULL;
1464 libhsm_key_t *key;
1465 CK_RV rv;
1466 CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY;
1467 CK_ATTRIBUTE template[] = {
1468 { CKA_CLASS, &key_class, sizeof(key_class) },
1469 };
1470 CK_ULONG total_count = 0;
1471 CK_ULONG objectCount = 1;
1472 /* find 100 keys at a time (and loop until there are none left) */
1473 CK_ULONG max_object_count = 100;
1474 CK_ULONG i, j;
1475 CK_OBJECT_HANDLE object[max_object_count];
1476 CK_OBJECT_HANDLE *key_handles = NULL, *new_key_handles = NULL;
1477
1478
1479 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjectsInit(session->session,
1480 template, 1);
1481 if (hsm_pkcs11_check_error(ctx, rv, "Find objects init")) {
1482 goto err;
1483 }
1484
1485 j = 0;
1486 while (objectCount > 0) {
1487 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjects(session->session,
1488 object,
1489 max_object_count,
1490 &objectCount);
1491 if (hsm_pkcs11_check_error(ctx, rv, "Find first object")) {
1492 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjectsFinal(session->session);
1493 hsm_pkcs11_check_error(ctx, rv, "Find objects cleanup");
1494 goto err;
1495 }
1496
1497 total_count += objectCount;
1498 if (objectCount > 0 && store) {
1499 if (SIZE_MAX / sizeof(CK_OBJECT_HANDLE) < total_count) {
1500 hsm_ctx_set_error(ctx, -1, "hsm_list_keys_session_internal",
1501 "Too much object handle returned by HSM to allocate key_handles");
1502 goto err;
1503 }
1504
1505 new_key_handles = realloc(key_handles, total_count * sizeof(CK_OBJECT_HANDLE));
1506 if (new_key_handles != NULL) {
1507 key_handles = new_key_handles;
1508 } else {
1509 hsm_ctx_set_error(ctx, -1, "hsm_list_keys_session_internal",
1510 "Error allocating memory for object handle (OOM)");
1511 goto err;
1512 }
1513
1514 for (i = 0; i < objectCount; i++) {
1515 key_handles[j] = object[i];
1516 j++;
1517 }
1518 }
1519 }
1520
1521 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjectsFinal(session->session);
1522 if (hsm_pkcs11_check_error(ctx, rv, "Find objects final")) {
1523 goto err;
1524 }
1525
1526 if (store) {
1527 if(SIZE_MAX / sizeof(libhsm_key_t *) < total_count) {
1528 hsm_ctx_set_error(ctx, -1, "hsm_list_keys_session_internal",
1529 "Too much object handle returned by HSM to allocate keys");
1530 goto err;
1531 }
1532
1533 CHECKALLOC(keys = malloc(total_count * sizeof(libhsm_key_t *)));
1534
1535 for (i = 0; i < total_count; i++) {
1536 key = libhsm_key_new_privkey_object_handle(ctx, session,
1537 key_handles[i]);
1538 if(!key) {
1539 libhsm_key_list_free(keys, i);
1540 goto err;
1541 }
1542 keys[i] = key;
1543 }
1544 }
1545 free(key_handles);
1546
1547 *count = total_count;
1548 return keys;
1549
1550err:
1551 free(key_handles);
1552 *count = 0;
1553 return NULL;
1554}
1555
1556
1557/* returns an array of all keys available to the given session
1558 *
1559 * \param session the session to find the keys in
1560 * \param count this value will contain the number of keys found
1561 *
1562 * \return the list of keys
1563 */
1564static libhsm_key_t **
1565hsm_list_keys_session(hsm_ctx_t *ctx, const hsm_session_t *session,
1566 size_t *count)
1567{
1568 return hsm_list_keys_session_internal(ctx, session, count, 1);
1569}
1570
1571/* returns a newly allocated key structure containing the key data
1572 * for the given CKA_ID available in the session. Returns NULL if not
1573 * found
1574 */
1575static libhsm_key_t *
1576hsm_find_key_by_id_session(hsm_ctx_t *ctx, const hsm_session_t *session,
1577 const unsigned char *id, size_t len)
1578{
1579 libhsm_key_t *key;
1580 CK_OBJECT_HANDLE private_key_handle;
1581
1582 private_key_handle = hsm_find_object_handle_for_id(
1583 ctx,
1584 session,
1586 (CK_BYTE *) id,
1587 (CK_ULONG) len);
1588 if (private_key_handle != 0) {
1589 key = libhsm_key_new_privkey_object_handle(ctx, session,
1590 private_key_handle);
1591 return key;
1592 } else {
1593 return NULL;
1594 }
1595}
1596
1597/* Find a key pair by CKA_ID (as byte array)
1598
1599The returned key structure can be freed with free()
1600
1601\param context HSM context
1602\param id CKA_ID of key to find (array of bytes)
1603\param len number of bytes in the id
1604\return key identifier or NULL if not found
1605*/
1606static libhsm_key_t *
1607hsm_find_key_by_id_bin(hsm_ctx_t *ctx,
1608 const unsigned char *id,
1609 size_t len)
1610{
1611 libhsm_key_t *key;
1612 unsigned int i;
1613
1614 if (!id) return NULL;
1615
1616 /* OPENDNSSEC-955: This procedure is mutexed to prevent a C_Login or
1617 * C_OpenSession happening at the same * time as looking up a key with
1618 * C_FindObject. Some HSMs like SoftHSM in database backend mode don't
1619 * like this.
1620 */
1621 pthread_mutex_lock(&_hsm_ctx_mutex);
1622 for (i = 0; i < ctx->session_count; i++) {
1623 key = hsm_find_key_by_id_session(ctx, ctx->session[i], id, len);
1624 if (key) {
1625 pthread_mutex_unlock(&_hsm_ctx_mutex);
1626 return key;
1627 }
1628 }
1629 pthread_mutex_unlock(&_hsm_ctx_mutex);
1630 return NULL;
1631}
1632
1633
1639static hsm_session_t *
1640hsm_find_repository_session(hsm_ctx_t *ctx, const char *repository)
1641{
1642 unsigned int i;
1643 if (!repository) {
1644 for (i = 0; i < ctx->session_count; i++) {
1645 if (ctx->session[i]) {
1646 return ctx->session[i];
1647 }
1648 }
1649 } else {
1650 for (i = 0; i < ctx->session_count; i++) {
1651 if (ctx->session[i] &&
1652 strcmp(repository, ctx->session[i]->module->name) == 0)
1653 {
1654 return ctx->session[i];
1655 }
1656 }
1657 }
1658
1660 "hsm_find_repository_session()",
1661 "Can't find repository: %s", repository);
1662
1663 return NULL;
1664}
1665
1666static ldns_rdf *
1667hsm_get_key_rdata_rsa(hsm_ctx_t *ctx, hsm_session_t *session,
1668 const libhsm_key_t *key)
1669{
1670 CK_RV rv;
1671 CK_BYTE_PTR public_exponent = NULL;
1672 CK_ULONG public_exponent_len = 0;
1673 CK_BYTE_PTR modulus = NULL;
1674 CK_ULONG modulus_len = 0;
1675 unsigned long hKey = 0;
1676 unsigned char *data = NULL;
1677 size_t data_size = 0;
1678
1679 CK_ATTRIBUTE template[] = {
1680 {CKA_PUBLIC_EXPONENT, NULL, 0},
1681 {CKA_MODULUS, NULL, 0},
1682 };
1683 ldns_rdf *rdf;
1684
1685 if (!session || !session->module) {
1686 return NULL;
1687 }
1688
1689 if (key->public_key) {
1690 hKey = key->public_key;
1691 } else {
1692 hKey = key->private_key;
1693 }
1694
1695 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1696 session->session,
1697 hKey,
1698 template,
1699 2);
1700 if (hsm_pkcs11_check_error(ctx, rv, "C_GetAttributeValue")) {
1701 return NULL;
1702 }
1703 public_exponent_len = template[0].ulValueLen;
1704 modulus_len = template[1].ulValueLen;
1705
1706 CHECKALLOC(public_exponent = template[0].pValue = malloc(public_exponent_len));
1707
1708 CHECKALLOC(modulus = template[1].pValue = malloc(modulus_len));
1709
1710 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1711 session->session,
1712 hKey,
1713 template,
1714 2);
1715 if (hsm_pkcs11_check_error(ctx, rv, "get attribute value")) {
1716 free(template[0].pValue);
1717 free(template[1].pValue);
1718 return NULL;
1719 }
1720
1721 // Remove leading zeroes
1722 hsm_remove_leading_zeroes(public_exponent, &public_exponent_len);
1723 hsm_remove_leading_zeroes(modulus, &modulus_len);
1724
1725 data_size = public_exponent_len + modulus_len + 1;
1726 if (public_exponent_len <= 255) {
1727 CHECKALLOC(data = malloc(data_size));
1728 data[0] = public_exponent_len;
1729 memcpy(&data[1], public_exponent, public_exponent_len);
1730 memcpy(&data[1 + public_exponent_len], modulus, modulus_len);
1731 } else if (public_exponent_len <= 65535) {
1732 data_size += 2;
1733 CHECKALLOC(data = malloc(data_size));
1734 data[0] = 0;
1735 ldns_write_uint16(&data[1], (uint16_t) public_exponent_len);
1736 memcpy(&data[3], public_exponent, public_exponent_len);
1737 memcpy(&data[3 + public_exponent_len], modulus, modulus_len);
1738 } else {
1739 hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata_rsa()",
1740 "Public exponent too big");
1741 free(public_exponent);
1742 free(modulus);
1743 return NULL;
1744 }
1745 rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, data_size, data);
1746 free(public_exponent);
1747 free(modulus);
1748
1749 return rdf;
1750}
1751
1752static ldns_rdf *
1753hsm_get_key_rdata_dsa(hsm_ctx_t *ctx, hsm_session_t *session,
1754 const libhsm_key_t *key)
1755{
1756 CK_RV rv;
1757 CK_BYTE_PTR prime = NULL;
1758 CK_ULONG prime_len = 0;
1759 CK_BYTE_PTR subprime = NULL;
1760 CK_ULONG subprime_len = 0;
1761 CK_BYTE_PTR base = NULL;
1762 CK_ULONG base_len = 0;
1763 CK_BYTE_PTR value = NULL;
1764 CK_ULONG value_len = 0;
1765 unsigned char *data = NULL;
1766 size_t data_size = 0;
1767
1768 CK_ATTRIBUTE template[] = {
1769 {CKA_PRIME, NULL, 0},
1770 {CKA_SUBPRIME, NULL, 0},
1771 {CKA_BASE, NULL, 0},
1772 {CKA_VALUE, NULL, 0},
1773 };
1774 ldns_rdf *rdf;
1775
1776 if (!session || !session->module) {
1777 return NULL;
1778 }
1779
1780 /* DSA needs the public key compared with RSA */
1781 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1782 session->session,
1783 key->public_key,
1784 template,
1785 4);
1786 if (hsm_pkcs11_check_error(ctx, rv, "C_GetAttributeValue")) {
1787 return NULL;
1788 }
1789 prime_len = template[0].ulValueLen;
1790 subprime_len = template[1].ulValueLen;
1791 base_len = template[2].ulValueLen;
1792 value_len = template[3].ulValueLen;
1793
1794 CHECKALLOC(prime = template[0].pValue = malloc(prime_len));
1795
1796 CHECKALLOC(subprime = template[1].pValue = malloc(subprime_len));
1797
1798 CHECKALLOC(base = template[2].pValue = malloc(base_len));
1799
1800 CHECKALLOC(value = template[3].pValue = malloc(value_len));
1801
1802 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1803 session->session,
1804 key->public_key,
1805 template,
1806 4);
1807 if (hsm_pkcs11_check_error(ctx, rv, "get attribute value")) {
1808 free(prime);
1809 free(subprime);
1810 free(base);
1811 free(value);
1812 return NULL;
1813 }
1814
1815 data_size = prime_len + subprime_len + base_len + value_len + 1;
1816 CHECKALLOC(data = malloc(data_size));
1817 data[0] = (prime_len - 64) / 8;
1818 memcpy(&data[1], subprime, subprime_len);
1819 memcpy(&data[1 + subprime_len], prime, prime_len);
1820 memcpy(&data[1 + subprime_len + prime_len], base, base_len);
1821 memcpy(&data[1 + subprime_len + prime_len + base_len], value, value_len);
1822
1823 rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, data_size, data);
1824 free(prime);
1825 free(subprime);
1826 free(base);
1827 free(value);
1828
1829 return rdf;
1830}
1831
1832static ldns_rdf *
1833hsm_get_key_rdata_gost(hsm_ctx_t *ctx, hsm_session_t *session,
1834 const libhsm_key_t *key)
1835{
1836 CK_RV rv;
1837 CK_BYTE_PTR value = NULL;
1838 CK_ULONG value_len = 0;
1839
1840 CK_ATTRIBUTE template[] = {
1841 {CKA_VALUE, NULL, 0},
1842 };
1843 ldns_rdf *rdf;
1844
1845 if (!session || !session->module) {
1846 return NULL;
1847 }
1848
1849 /* GOST needs the public key compared with RSA */
1850 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1851 session->session,
1852 key->public_key,
1853 template,
1854 1);
1855 if (hsm_pkcs11_check_error(ctx, rv, "C_GetAttributeValue")) {
1856 return NULL;
1857 }
1858 value_len = template[0].ulValueLen;
1859
1860 CHECKALLOC(value = template[0].pValue = malloc(value_len));
1861
1862 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1863 session->session,
1864 key->public_key,
1865 template,
1866 1);
1867 if (hsm_pkcs11_check_error(ctx, rv, "get attribute value")) {
1868 free(value);
1869 return NULL;
1870 }
1871
1872 rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, value_len, value);
1873 return rdf;
1874}
1875
1876static ldns_rdf *
1877hsm_get_key_rdata_ecdsa(hsm_ctx_t *ctx, hsm_session_t *session,
1878 const libhsm_key_t *key)
1879{
1881 unsigned char* value = hsm_get_key_ecdsa_value(ctx, session, key, &value_len);
1882
1883 if (value == NULL) return NULL;
1884
1885 ldns_rdf *rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, value_len, value);
1886
1887 return rdf;
1888}
1889
1890static ldns_rdf *
1891hsm_get_key_rdata_eddsa(hsm_ctx_t *ctx, hsm_session_t *session,
1892 const libhsm_key_t *key)
1893{
1895 unsigned char* value = hsm_get_key_eddsa_value(ctx, session, key, &value_len);
1896
1897 if (value == NULL) return NULL;
1898
1899 ldns_rdf *rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, value_len, value);
1900
1901 return rdf;
1902}
1903
1904static ldns_rdf *
1905hsm_get_key_rdata(hsm_ctx_t *ctx, hsm_session_t *session,
1906 const libhsm_key_t *key)
1907{
1908 switch (hsm_get_key_algorithm(ctx, session, key)) {
1909 case CKK_RSA:
1910 return hsm_get_key_rdata_rsa(ctx, session, key);
1911 break;
1912 case CKK_DSA:
1913 return hsm_get_key_rdata_dsa(ctx, session, key);
1914 break;
1915 case CKK_GOSTR3410:
1916 return hsm_get_key_rdata_gost(ctx, session, key);
1917 break;
1918 case CKK_EC:
1919 return hsm_get_key_rdata_ecdsa(ctx, session, key);
1920 case CKK_EC_EDWARDS:
1921 return hsm_get_key_rdata_eddsa(ctx, session, key);
1922 default:
1923 return 0;
1924 }
1925}
1926
1927/* this function allocates memory for the mechanism ID and enough room
1928 * to leave the upcoming digest data. It fills in the mechanism id
1929 * use with care. The returned data must be free'd by the caller.
1930 * Only used by RSA PKCS. */
1931static CK_BYTE *
1932hsm_create_prefix(CK_ULONG digest_len,
1933 ldns_algorithm algorithm,
1934 CK_ULONG *data_size)
1935{
1936 CK_BYTE *data;
1937 const CK_BYTE RSA_MD5_ID[] = { 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 };
1938 const CK_BYTE RSA_SHA1_ID[] = { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14 };
1939 const CK_BYTE RSA_SHA256_ID[] = { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 };
1940 const CK_BYTE RSA_SHA512_ID[] = { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 };
1941
1942 switch((ldns_signing_algorithm)algorithm) {
1943 case LDNS_SIGN_RSAMD5:
1944 *data_size = sizeof(RSA_MD5_ID) + digest_len;
1945 CHECKALLOC(data = malloc(*data_size));
1946 memcpy(data, RSA_MD5_ID, sizeof(RSA_MD5_ID));
1947 break;
1948 case LDNS_SIGN_RSASHA1:
1949 case LDNS_SIGN_RSASHA1_NSEC3:
1950 *data_size = sizeof(RSA_SHA1_ID) + digest_len;
1951 CHECKALLOC(data = malloc(*data_size));
1952 memcpy(data, RSA_SHA1_ID, sizeof(RSA_SHA1_ID));
1953 break;
1954 case LDNS_SIGN_RSASHA256:
1955 *data_size = sizeof(RSA_SHA256_ID) + digest_len;
1956 CHECKALLOC(data = malloc(*data_size));
1957 memcpy(data, RSA_SHA256_ID, sizeof(RSA_SHA256_ID));
1958 break;
1959 case LDNS_SIGN_RSASHA512:
1960 *data_size = sizeof(RSA_SHA512_ID) + digest_len;
1961 CHECKALLOC(data = malloc(*data_size));
1962 memcpy(data, RSA_SHA512_ID, sizeof(RSA_SHA512_ID));
1963 break;
1964 case LDNS_SIGN_DSA:
1965 case LDNS_SIGN_DSA_NSEC3:
1966 case LDNS_SIGN_ECC_GOST:
1967 case LDNS_SIGN_ECDSAP256SHA256:
1968 case LDNS_SIGN_ECDSAP384SHA384:
1969 *data_size = digest_len;
1970 CHECKALLOC(data = malloc(*data_size));
1971 break;
1972 default:
1973 return NULL;
1974 }
1975 return data;
1976}
1977
1978static CK_BYTE *
1979hsm_digest_through_hsm(hsm_ctx_t *ctx,
1980 hsm_session_t *session,
1981 CK_MECHANISM_TYPE mechanism_type,
1982 CK_ULONG digest_len,
1983 ldns_buffer *sign_buf)
1984{
1985 CK_MECHANISM digest_mechanism;
1986 CK_BYTE *digest;
1987 CK_RV rv;
1988
1989 digest_mechanism.pParameter = NULL;
1990 digest_mechanism.ulParameterLen = 0;
1991 digest_mechanism.mechanism = mechanism_type;
1992 CHECKALLOC(digest = malloc(digest_len));
1993 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DigestInit(session->session,
1994 &digest_mechanism);
1995 if (hsm_pkcs11_check_error(ctx, rv, "HSM digest init")) {
1996 free(digest);
1997 return NULL;
1998 }
1999
2000 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Digest(session->session,
2001 ldns_buffer_begin(sign_buf),
2002 ldns_buffer_position(sign_buf),
2003 digest,
2004 &digest_len);
2005 if (hsm_pkcs11_check_error(ctx, rv, "HSM digest")) {
2006 free(digest);
2007 return NULL;
2008 }
2009 return digest;
2010}
2011
2012static ldns_rdf *
2013hsm_sign_buffer(hsm_ctx_t *ctx,
2014 ldns_buffer *sign_buf,
2015 const libhsm_key_t *key,
2016 ldns_algorithm algorithm)
2017{
2018 CK_RV rv;
2019 CK_ULONG signatureLen = HSM_MAX_SIGNATURE_LENGTH;
2021 CK_MECHANISM sign_mechanism;
2022
2023 int data_direct = 0; // don't pre-create digest, use data directly
2024
2025 ldns_rdf *sig_rdf;
2026 CK_BYTE *digest = NULL;
2027 CK_ULONG digest_len = 0;
2028
2029 CK_BYTE *data = NULL;
2030 CK_ULONG data_len = 0;
2031
2032 hsm_session_t *session;
2033
2034 session = hsm_find_key_session(ctx, key);
2035 if (!session) return NULL;
2036
2037 /* some HSMs don't really handle CKM_SHA1_RSA_PKCS well, so
2038 * we'll do the hashing manually */
2039 /* When adding algorithms, remember there is another switch below */
2040 switch ((ldns_signing_algorithm)algorithm) {
2041 case LDNS_SIGN_RSAMD5:
2042 digest_len = 16;
2043 digest = hsm_digest_through_hsm(ctx, session,
2044 CKM_MD5, digest_len,
2045 sign_buf);
2046 break;
2047 case LDNS_SIGN_RSASHA1:
2048 case LDNS_SIGN_RSASHA1_NSEC3:
2049 case LDNS_SIGN_DSA:
2050 case LDNS_SIGN_DSA_NSEC3:
2051 digest_len = LDNS_SHA1_DIGEST_LENGTH;
2052 CHECKALLOC(digest = malloc(digest_len));
2053 digest = ldns_sha1(ldns_buffer_begin(sign_buf),
2054 ldns_buffer_position(sign_buf),
2055 digest);
2056 break;
2057
2058 case LDNS_SIGN_RSASHA256:
2059 case LDNS_SIGN_ECDSAP256SHA256:
2060 digest_len = LDNS_SHA256_DIGEST_LENGTH;
2061 CHECKALLOC(digest = malloc(digest_len));
2062 digest = ldns_sha256(ldns_buffer_begin(sign_buf),
2063 ldns_buffer_position(sign_buf),
2064 digest);
2065 break;
2066 case LDNS_SIGN_ECDSAP384SHA384:
2067 digest_len = LDNS_SHA384_DIGEST_LENGTH;
2068 CHECKALLOC(digest = malloc(digest_len));
2069 digest = ldns_sha384(ldns_buffer_begin(sign_buf),
2070 ldns_buffer_position(sign_buf),
2071 digest);
2072 break;
2073 case LDNS_SIGN_RSASHA512:
2074 digest_len = LDNS_SHA512_DIGEST_LENGTH;
2075 CHECKALLOC(digest = malloc(digest_len));
2076 digest = ldns_sha512(ldns_buffer_begin(sign_buf),
2077 ldns_buffer_position(sign_buf),
2078 digest);
2079 break;
2080 case LDNS_SIGN_ECC_GOST:
2081 digest_len = 32;
2082 digest = hsm_digest_through_hsm(ctx, session,
2083 CKM_GOSTR3411, digest_len,
2084 sign_buf);
2085 break;
2086#if (LDNS_REVISION >= ((1<<16)|(7<<8)|(0)))
2087 case LDNS_SIGN_ED25519:
2088 data_direct = 1;
2089 break;
2090 case LDNS_SIGN_ED448:
2091 data_direct = 1;
2092 break;
2093#endif
2094 default:
2095 /* log error? or should we not even get here for
2096 * unsupported algorithms? */
2097 return NULL;
2098 }
2099
2100 if (!data_direct && !digest) {
2101 return NULL;
2102 }
2103
2104 if (data_direct) {
2105 data = ldns_buffer_begin(sign_buf);
2106 data_len = ldns_buffer_position(sign_buf);
2107 } else {
2108 /* CKM_RSA_PKCS does the padding, but cannot know the identifier
2109 * prefix, so we need to add that ourselves.
2110 * The other algorithms will just get the digest buffer returned. */
2111 data = hsm_create_prefix(digest_len, algorithm, &data_len);
2112 memcpy(data + data_len - digest_len, digest, digest_len);
2113 }
2114
2115 sign_mechanism.pParameter = NULL;
2116 sign_mechanism.ulParameterLen = 0;
2117 switch((ldns_signing_algorithm)algorithm) {
2118 case LDNS_SIGN_RSAMD5:
2119 case LDNS_SIGN_RSASHA1:
2120 case LDNS_SIGN_RSASHA1_NSEC3:
2121 case LDNS_SIGN_RSASHA256:
2122 case LDNS_SIGN_RSASHA512:
2123 sign_mechanism.mechanism = CKM_RSA_PKCS;
2124 break;
2125 case LDNS_SIGN_DSA:
2126 case LDNS_SIGN_DSA_NSEC3:
2127 sign_mechanism.mechanism = CKM_DSA;
2128 break;
2129 case LDNS_SIGN_ECC_GOST:
2130 sign_mechanism.mechanism = CKM_GOSTR3410;
2131 break;
2132 case LDNS_SIGN_ECDSAP256SHA256:
2133 case LDNS_SIGN_ECDSAP384SHA384:
2134 sign_mechanism.mechanism = CKM_ECDSA;
2135 break;
2136#if (LDNS_REVISION >= ((1<<16)|(7<<8)|(0)))
2137 case LDNS_SIGN_ED25519:
2138 sign_mechanism.mechanism = CKM_EDDSA;
2139 break;
2140 case LDNS_SIGN_ED448:
2141 sign_mechanism.mechanism = CKM_EDDSA;
2142 break;
2143#endif
2144 default:
2145 /* log error? or should we not even get here for
2146 * unsupported algorithms? */
2147 free(data);
2148 free(digest);
2149 return NULL;
2150 }
2151
2152 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_SignInit(
2153 session->session,
2154 &sign_mechanism,
2155 key->private_key);
2156 if (hsm_pkcs11_check_error(ctx, rv, "sign init")) {
2157 if (!data_direct) {
2158 free(data);
2159 free(digest);
2160 }
2161 return NULL;
2162 }
2163
2164 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Sign(session->session, data, data_len,
2165 signature,
2166 &signatureLen);
2167 if (hsm_pkcs11_check_error(ctx, rv, "sign final")) {
2168 if (!data_direct) {
2169 free(data);
2170 free(digest);
2171 }
2172 return NULL;
2173 }
2174
2175 sig_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
2176 signatureLen,
2177 signature);
2178
2179 if (!data_direct) {
2180 free(data);
2181 free(digest);
2182 }
2183
2184 return sig_rdf;
2185
2186}
2187
2188static int
2189hsm_dname_is_wildcard(const ldns_rdf* dname)
2190{
2191 return ( ldns_dname_label_count(dname) > 0 &&
2192 ldns_rdf_data(dname)[0] == 1 &&
2193 ldns_rdf_data(dname)[1] == '*');
2194}
2195
2196static ldns_rr *
2197hsm_create_empty_rrsig(const ldns_rr_list *rrset,
2198 const hsm_sign_params_t *sign_params)
2199{
2200 ldns_rr *rrsig;
2201 uint32_t orig_ttl;
2202 uint32_t orig_class;
2203 time_t now;
2204 uint8_t label_count;
2205
2206 label_count = ldns_dname_label_count(
2207 ldns_rr_owner(ldns_rr_list_rr(rrset, 0)));
2208 /* RFC 4035 section 2.2: dnssec label length and wildcards */
2209 if (hsm_dname_is_wildcard(ldns_rr_owner(ldns_rr_list_rr(rrset, 0)))) {
2210 label_count--;
2211 }
2212
2213 rrsig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG);
2214
2215 /* set the type on the new signature */
2216 orig_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrset, 0));
2217 orig_class = ldns_rr_get_class(ldns_rr_list_rr(rrset, 0));
2218
2219 ldns_rr_set_class(rrsig, orig_class);
2220 ldns_rr_set_ttl(rrsig, orig_ttl);
2221 ldns_rr_set_owner(rrsig,
2222 ldns_rdf_clone(
2223 ldns_rr_owner(
2224 ldns_rr_list_rr(rrset,
2225 0))));
2226
2227 /* fill in what we know of the signature */
2228
2229 /* set the orig_ttl */
2230 (void)ldns_rr_rrsig_set_origttl(
2231 rrsig,
2232 ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
2233 orig_ttl));
2234 /* the signers name */
2235 (void)ldns_rr_rrsig_set_signame(
2236 rrsig,
2237 ldns_rdf_clone(sign_params->owner));
2238 /* label count - get it from the first rr in the rr_list */
2239 (void)ldns_rr_rrsig_set_labels(
2240 rrsig,
2241 ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
2242 label_count));
2243 /* inception, expiration */
2244 now = time_now();
2245 if (sign_params->inception != 0) {
2246 (void)ldns_rr_rrsig_set_inception(
2247 rrsig,
2248 ldns_native2rdf_int32(
2249 LDNS_RDF_TYPE_TIME,
2250 sign_params->inception));
2251 } else {
2252 (void)ldns_rr_rrsig_set_inception(
2253 rrsig,
2254 ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, now));
2255 }
2256 if (sign_params->expiration != 0) {
2257 (void)ldns_rr_rrsig_set_expiration(
2258 rrsig,
2259 ldns_native2rdf_int32(
2260 LDNS_RDF_TYPE_TIME,
2261 sign_params->expiration));
2262 } else {
2263 (void)ldns_rr_rrsig_set_expiration(
2264 rrsig,
2265 ldns_native2rdf_int32(
2266 LDNS_RDF_TYPE_TIME,
2267 now + LDNS_DEFAULT_EXP_TIME));
2268 }
2269
2270 (void)ldns_rr_rrsig_set_keytag(
2271 rrsig,
2272 ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
2273 sign_params->keytag));
2274
2275 (void)ldns_rr_rrsig_set_algorithm(
2276 rrsig,
2277 ldns_native2rdf_int8(
2278 LDNS_RDF_TYPE_ALG,
2279 sign_params->algorithm));
2280
2281 (void)ldns_rr_rrsig_set_typecovered(
2282 rrsig,
2283 ldns_native2rdf_int16(
2284 LDNS_RDF_TYPE_TYPE,
2285 ldns_rr_get_type(ldns_rr_list_rr(rrset,
2286 0))));
2287
2288 return rrsig;
2289}
2290
2291
2292/*
2293 * API functions
2294 */
2295
2296int
2298 char *(pin_callback)(unsigned int, const char *, unsigned int))
2299{
2300 hsm_config_t module_config;
2301 hsm_repository_t* repo = NULL;
2302 char* module_pin = NULL;
2303 int result = HSM_OK;
2304 int tries;
2305 int repositories = 0;
2306
2307 pthread_mutex_lock(&_hsm_ctx_mutex);
2308 /* create an internal context with an attached session for each
2309 * configured HSM. */
2310 if ((_hsm_ctx = hsm_ctx_new())) {
2312 }
2313
2314 repo = rlist;
2315 while (repo) {
2316 hsm_config_default(&module_config);
2317 module_config.use_pubkey = repo->use_pubkey;
2318 module_config.allow_extract = repo->allow_extract;
2319 if (repo->name && repo->module && repo->tokenlabel) {
2320 if (repo->pin) {
2321 result = hsm_attach(repo->name, repo->tokenlabel,
2322 repo->module, repo->pin, &module_config);
2323 } else {
2324 if (pin_callback) {
2325 result = HSM_PIN_INCORRECT;
2326 tries = 0;
2327 while (result == HSM_PIN_INCORRECT && tries < 3) {
2328 module_pin = pin_callback(_hsm_ctx->session_count,
2329 repo->name, tries?HSM_PIN_RETRY:HSM_PIN_FIRST);
2330 if (module_pin == NULL) break;
2331 result = hsm_attach(repo->name, repo->tokenlabel,
2332 repo->module, module_pin, &module_config);
2333 if (result == HSM_OK) {
2334 pin_callback(_hsm_ctx->session_count - 1,
2335 repo->name, HSM_PIN_SAVE);
2336 }
2337 memset(module_pin, 0, strlen(module_pin));
2338 tries++;
2339 }
2340 } else {
2341 /* no pin, no callback */
2342 hsm_ctx_set_error(_hsm_ctx, HSM_ERROR, "hsm_open2()",
2343 "No pin or callback function");
2344 result = HSM_ERROR;
2345 }
2346 }
2347 if (result != HSM_OK) {
2348 break;
2349 }
2350 repositories++;
2351 }
2352 repo = repo->next;
2353 }
2354 if (result == HSM_OK && repositories == 0) {
2356 "No repositories found");
2357 result = HSM_NO_REPOSITORIES;
2358 }
2359 pthread_mutex_unlock(&_hsm_ctx_mutex);
2360 return result;
2361}
2362
2363void
2365{
2366 pthread_mutex_lock(&_hsm_ctx_mutex);
2368 hsm_ctx_close(_hsm_ctx, 1);
2369 _hsm_ctx = NULL;
2370 pthread_mutex_unlock(&_hsm_ctx_mutex);
2371}
2372
2373hsm_ctx_t *
2375{
2376 hsm_ctx_t* newctx;
2377 pthread_mutex_lock(&_hsm_ctx_mutex);
2378 newctx = hsm_ctx_clone(_hsm_ctx);
2379 pthread_mutex_unlock(&_hsm_ctx_mutex);
2380 return newctx;
2381}
2382
2383int
2385{
2386 unsigned int i;
2387 hsm_session_t *session;
2388 CK_SESSION_INFO info;
2389 CK_RV rv;
2390 CK_SESSION_HANDLE session_handle;
2391 hsm_ctx_t *ctx;
2392
2393 pthread_mutex_lock(&_hsm_ctx_mutex);
2394 ctx = _hsm_ctx;
2395
2396 for (i = 0; i < ctx->session_count; i++) {
2397 session = ctx->session[i];
2398 if (session == NULL) continue;
2399
2400 /* Get session info */
2401 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetSessionInfo(
2402 session->session,
2403 &info);
2404 if (hsm_pkcs11_check_error(ctx, rv, "get session info")) {
2405 pthread_mutex_unlock(&_hsm_ctx_mutex);
2406 return HSM_ERROR;
2407 }
2408
2409 /* Check session info */
2410 if (info.state != CKS_RW_USER_FUNCTIONS) {
2411 hsm_ctx_set_error(ctx, HSM_ERROR, "hsm_check_context()",
2412 "Session not logged in");
2413 pthread_mutex_unlock(&_hsm_ctx_mutex);
2414 return HSM_ERROR;
2415 }
2416
2417 /* Try open and close a session with the token */
2418 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_OpenSession(info.slotID,
2420 NULL,
2421 NULL,
2422 &session_handle);
2423 if (hsm_pkcs11_check_error(ctx, rv, "test open session")) {
2424 pthread_mutex_unlock(&_hsm_ctx_mutex);
2425 return HSM_ERROR;
2426 }
2427 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_CloseSession(session_handle);
2428 if (hsm_pkcs11_check_error(ctx, rv, "test close session")) {
2429 pthread_mutex_unlock(&_hsm_ctx_mutex);
2430 return HSM_ERROR;
2431 }
2432 }
2433
2434 pthread_mutex_unlock(&_hsm_ctx_mutex);
2435 return HSM_OK;
2436}
2437
2438void
2440{
2441 hsm_ctx_close(ctx, 0);
2442}
2443
2449{
2450 hsm_sign_params_t *params;
2451 CHECKALLOC(params = malloc(sizeof(hsm_sign_params_t)));
2452 params->algorithm = LDNS_RSASHA256;
2453 params->flags = LDNS_KEY_ZONE_KEY;
2454 params->inception = 0;
2455 params->expiration = 0;
2456 params->keytag = 0;
2457 params->owner = NULL;
2458 return params;
2459}
2460
2461void
2463{
2464 if (params) {
2465 if (params->owner) ldns_rdf_deep_free(params->owner);
2466 free(params);
2467 }
2468}
2469
2470void
2472{
2473 free(key->modulename);
2474 free(key);
2475}
2476
2477libhsm_key_t **
2479{
2480 libhsm_key_t **keys = NULL;
2481 size_t key_count = 0;
2482 size_t cur_key_count;
2483 libhsm_key_t **session_keys;
2484 unsigned int i, j;
2485
2486 for (i = 0; i < ctx->session_count; i++) {
2487 session_keys = hsm_list_keys_session(ctx, ctx->session[i],
2488 &cur_key_count);
2489 CHECKALLOC(keys = realloc(keys,
2490 (key_count + cur_key_count) * sizeof(libhsm_key_t *)));
2491 for (j = 0; j < cur_key_count; j++) {
2492 keys[key_count + j] = session_keys[j];
2493 }
2494 key_count += cur_key_count;
2495 free(session_keys);
2496 }
2497 if (count) {
2498 *count = key_count;
2499 }
2500 return keys;
2501}
2502
2503libhsm_key_t **
2505 size_t *count,
2506 const char *repository)
2507{
2508 hsm_session_t *session;
2509
2510 if (!repository) return NULL;
2511
2512 session = hsm_find_repository_session(ctx, repository);
2513 if (!session) {
2514 *count = 0;
2515 return NULL;
2516 }
2517 return hsm_list_keys_session(ctx, session, count);
2518}
2519
2522{
2523 unsigned char *id_bytes;
2524 size_t len;
2525 libhsm_key_t *key;
2526
2527 id_bytes = hsm_hex_parse(id, &len);
2528
2529 if (!id_bytes) return NULL;
2530
2531 key = hsm_find_key_by_id_bin(ctx, id_bytes, len);
2532 free(id_bytes);
2533 return key;
2534}
2535
2536static void
2537generate_unique_id(hsm_ctx_t *ctx, unsigned char *buf, size_t bufsize)
2538{
2539 libhsm_key_t *key;
2540 /* check whether this key doesn't happen to exist already */
2541 hsm_random_buffer(ctx, buf, bufsize);
2542 while ((key = hsm_find_key_by_id_bin(ctx, buf, bufsize))) {
2543 libhsm_key_free(key);
2544 hsm_random_buffer(ctx, buf, bufsize);
2545 }
2546
2547}
2548
2551 const char *repository,
2552 unsigned long keysize)
2553{
2554 libhsm_key_t *new_key;
2555 hsm_session_t *session;
2556 /* ids we create are 16 bytes of data */
2557 unsigned char id[16];
2558 /* that's 33 bytes in string (16*2 + 1 for \0) */
2559 char id_str[33];
2560 CK_RV rv;
2561 CK_OBJECT_HANDLE publicKey, privateKey;
2562 CK_KEY_TYPE keyType = CKK_RSA;
2563 CK_MECHANISM mechanism = {
2565 };
2566 CK_BYTE publicExponent[] = { 1, 0, 1 };
2567 CK_BBOOL ctrue = CK_TRUE;
2568 CK_BBOOL cfalse = CK_FALSE;
2569 CK_BBOOL ctoken = CK_TRUE;
2570 CK_BBOOL cextractable = CK_FALSE;
2571
2572 session = hsm_find_repository_session(ctx, repository);
2573 if (!session) return NULL;
2574 cextractable = session->module->config->allow_extract ? CK_TRUE : CK_FALSE;
2575
2576 generate_unique_id(ctx, id, 16);
2577
2578 /* the CKA_LABEL will contain a hexadecimal string representation
2579 * of the id */
2580 hsm_hex_unparse(id_str, id, 16);
2581
2582 if (! session->module->config->use_pubkey) {
2583 ctoken = CK_FALSE;
2584 }
2585
2586 CK_ATTRIBUTE publicKeyTemplate[] = {
2587 { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen(id_str) },
2588 { CKA_ID, id, 16 },
2589 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2590 { CKA_VERIFY, &ctrue, sizeof(ctrue) },
2591 { CKA_ENCRYPT, &cfalse, sizeof(cfalse) },
2592 { CKA_WRAP, &cfalse, sizeof(cfalse) },
2593 { CKA_TOKEN, &ctoken, sizeof(ctoken) },
2594 { CKA_MODULUS_BITS, &keysize, sizeof(keysize) },
2595 { CKA_PUBLIC_EXPONENT, &publicExponent, sizeof(publicExponent)}
2596 };
2597
2598 CK_ATTRIBUTE privateKeyTemplate[] = {
2599 { CKA_LABEL,(CK_UTF8CHAR *) id_str, strlen (id_str) },
2600 { CKA_ID, id, 16 },
2601 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2602 { CKA_SIGN, &ctrue, sizeof (ctrue) },
2603 { CKA_DECRYPT, &cfalse, sizeof (cfalse) },
2604 { CKA_UNWRAP, &cfalse, sizeof (cfalse) },
2605 { CKA_SENSITIVE, &ctrue, sizeof (ctrue) },
2606 { CKA_TOKEN, &ctrue, sizeof (ctrue) },
2607 { CKA_PRIVATE, &ctrue, sizeof (ctrue) },
2608 { CKA_EXTRACTABLE, &cextractable, sizeof (cextractable) }
2609 };
2610
2611 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateKeyPair(session->session,
2612 &mechanism,
2613 publicKeyTemplate, 9,
2614 privateKeyTemplate, 10,
2615 &publicKey,
2616 &privateKey);
2617 if (hsm_pkcs11_check_error(ctx, rv, "generate key pair")) {
2618 return NULL;
2619 }
2620
2621 new_key = libhsm_key_new();
2622 new_key->modulename = strdup(session->module->name);
2623
2624 if (session->module->config->use_pubkey) {
2625 new_key->public_key = publicKey;
2626 } else {
2627 /* Destroy the object directly in order to optimize storage in HSM */
2628 /* Ignore return value, it is just a session object and will be destroyed later */
2629 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DestroyObject(session->session, publicKey);
2630 new_key->public_key = 0;
2631 }
2632
2633 new_key->private_key = privateKey;
2634 return new_key;
2635}
2636
2639 const char *repository,
2640 unsigned long keysize)
2641{
2642 CK_RV rv;
2643 libhsm_key_t *new_key;
2644 hsm_session_t *session;
2645 CK_OBJECT_HANDLE domainPar, publicKey, privateKey;
2646 CK_BBOOL ctrue = CK_TRUE;
2647 CK_BBOOL cfalse = CK_FALSE;
2648 CK_BBOOL cextractable = CK_FALSE;
2649
2650 /* ids we create are 16 bytes of data */
2651 unsigned char id[16];
2652 /* that's 33 bytes in string (16*2 + 1 for \0) */
2653 char id_str[33];
2654
2655 session = hsm_find_repository_session(ctx, repository);
2656 if (!session) return NULL;
2657 cextractable = session->module->config->allow_extract ? CK_TRUE : CK_FALSE;
2658
2659 generate_unique_id(ctx, id, 16);
2660
2661 /* the CKA_LABEL will contain a hexadecimal string representation
2662 * of the id */
2663 hsm_hex_unparse(id_str, id, 16);
2664
2665 CK_KEY_TYPE keyType = CKK_DSA;
2666 CK_MECHANISM mechanism1 = {
2668 };
2669 CK_MECHANISM mechanism2 = {
2671 };
2672
2673 /* The maximum size for DSA in DNSSEC */
2674 CK_BYTE dsa_p[128];
2675 CK_BYTE dsa_q[20];
2676 CK_BYTE dsa_g[128];
2677
2678 CK_ATTRIBUTE domainTemplate[] = {
2679 { CKA_PRIME_BITS, &keysize, sizeof(keysize) }
2680 };
2681
2682 CK_ATTRIBUTE publicKeyTemplate[] = {
2683 { CKA_PRIME, dsa_p, sizeof(dsa_p) },
2684 { CKA_SUBPRIME, dsa_q, sizeof(dsa_q) },
2685 { CKA_BASE, dsa_g, sizeof(dsa_g) },
2686 { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen(id_str) },
2687 { CKA_ID, id, 16 },
2688 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2689 { CKA_VERIFY, &ctrue, sizeof(ctrue) },
2690 { CKA_ENCRYPT, &cfalse, sizeof(cfalse) },
2691 { CKA_WRAP, &cfalse, sizeof(cfalse) },
2692 { CKA_TOKEN, &ctrue, sizeof(ctrue) }
2693 };
2694
2695 CK_ATTRIBUTE privateKeyTemplate[] = {
2696 { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen (id_str) },
2697 { CKA_ID, id, 16 },
2698 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2699 { CKA_SIGN, &ctrue, sizeof(ctrue) },
2700 { CKA_DECRYPT, &cfalse, sizeof(cfalse) },
2701 { CKA_UNWRAP, &cfalse, sizeof(cfalse) },
2702 { CKA_SENSITIVE, &ctrue, sizeof(ctrue) },
2703 { CKA_TOKEN, &ctrue, sizeof(ctrue) },
2704 { CKA_PRIVATE, &ctrue, sizeof(ctrue) },
2705 { CKA_EXTRACTABLE, &cextractable, sizeof (cextractable) }
2706 };
2707
2708 cextractable = session->module->config->allow_extract ? CK_TRUE : CK_FALSE;
2709
2710 /* Generate the domain parameters */
2711
2712 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateKey(session->session,
2713 &mechanism1,
2714 domainTemplate, 1,
2715 &domainPar);
2716 if (hsm_pkcs11_check_error(ctx, rv, "generate domain parameters")) {
2717 return NULL;
2718 }
2719
2720 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(session->session,
2721 domainPar, publicKeyTemplate, 3);
2722 if (hsm_pkcs11_check_error(ctx, rv, "get domain parameters")) {
2723 return NULL;
2724 }
2725
2726 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DestroyObject(session->session, domainPar);
2727 if (hsm_pkcs11_check_error(ctx, rv, "destroy domain parameters")) {
2728 return NULL;
2729 }
2730
2731 /* Generate key pair */
2732
2733 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateKeyPair(session->session,
2734 &mechanism2,
2735 publicKeyTemplate, 10,
2736 privateKeyTemplate, 10,
2737 &publicKey,
2738 &privateKey);
2739 if (hsm_pkcs11_check_error(ctx, rv, "generate key pair")) {
2740 return NULL;
2741 }
2742
2743 new_key = libhsm_key_new();
2744 new_key->modulename = strdup(session->module->name);
2745 new_key->public_key = publicKey;
2746 new_key->private_key = privateKey;
2747
2748 return new_key;
2749}
2750
2753 const char *repository)
2754{
2755 CK_RV rv;
2756 libhsm_key_t *new_key;
2757 hsm_session_t *session;
2758 CK_OBJECT_HANDLE publicKey, privateKey;
2759 CK_BBOOL ctrue = CK_TRUE;
2760 CK_BBOOL cfalse = CK_FALSE;
2761 CK_BBOOL cextractable = CK_FALSE;
2762
2763 /* ids we create are 16 bytes of data */
2764 unsigned char id[16];
2765 /* that's 33 bytes in string (16*2 + 1 for \0) */
2766 char id_str[33];
2767
2768 session = hsm_find_repository_session(ctx, repository);
2769 if (!session) return NULL;
2770 cextractable = session->module->config->allow_extract ? CK_TRUE : CK_FALSE;
2771
2772 generate_unique_id(ctx, id, 16);
2773
2774 /* the CKA_LABEL will contain a hexadecimal string representation
2775 * of the id */
2776 hsm_hex_unparse(id_str, id, 16);
2777
2778 CK_KEY_TYPE keyType = CKK_GOSTR3410;
2779 CK_MECHANISM mechanism = {
2781 };
2782
2783 CK_BYTE oid1[] = { 0x06, 0x07, 0x2A, 0x85, 0x03, 0x02, 0x02, 0x23, 0x01 };
2784 CK_BYTE oid2[] = { 0x06, 0x07, 0x2A, 0x85, 0x03, 0x02, 0x02, 0x1E, 0x01 };
2785
2786 CK_ATTRIBUTE publicKeyTemplate[] = {
2787 { CKA_GOSTR3410PARAMS, oid1, sizeof(oid1) },
2788 { CKA_GOSTR3411PARAMS, oid2, sizeof(oid2) },
2789 { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen(id_str) },
2790 { CKA_ID, id, 16 },
2791 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2792 { CKA_VERIFY, &ctrue, sizeof(ctrue) },
2793 { CKA_ENCRYPT, &cfalse, sizeof(cfalse) },
2794 { CKA_WRAP, &cfalse, sizeof(cfalse) },
2795 { CKA_TOKEN, &ctrue, sizeof(ctrue) }
2796 };
2797
2798 CK_ATTRIBUTE privateKeyTemplate[] = {
2799 { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen (id_str) },
2800 { CKA_ID, id, 16 },
2801 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2802 { CKA_SIGN, &ctrue, sizeof(ctrue) },
2803 { CKA_DECRYPT, &cfalse, sizeof(cfalse) },
2804 { CKA_UNWRAP, &cfalse, sizeof(cfalse) },
2805 { CKA_SENSITIVE, &ctrue, sizeof(ctrue) },
2806 { CKA_TOKEN, &ctrue, sizeof(ctrue) },
2807 { CKA_PRIVATE, &ctrue, sizeof(ctrue) },
2808 { CKA_EXTRACTABLE, &cextractable, sizeof (cextractable) }
2809 };
2810
2811 /* Generate key pair */
2812
2813 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateKeyPair(session->session,
2814 &mechanism,
2815 publicKeyTemplate, 9,
2816 privateKeyTemplate, 10,
2817 &publicKey,
2818 &privateKey);
2819 if (hsm_pkcs11_check_error(ctx, rv, "generate key pair")) {
2820 return NULL;
2821 }
2822
2823 new_key = libhsm_key_new();
2824 new_key->modulename = strdup(session->module->name);
2825 new_key->public_key = publicKey;
2826 new_key->private_key = privateKey;
2827
2828 return new_key;
2829}
2830
2833 const char *repository,
2834 const char *curve)
2835{
2836 CK_RV rv;
2837 libhsm_key_t *new_key;
2838 hsm_session_t *session;
2839 CK_OBJECT_HANDLE publicKey, privateKey;
2840 CK_BBOOL ctrue = CK_TRUE;
2841 CK_BBOOL cfalse = CK_FALSE;
2842 CK_BBOOL cextractable = CK_FALSE;
2843
2844 /* ids we create are 16 bytes of data */
2845 unsigned char id[16];
2846 /* that's 33 bytes in string (16*2 + 1 for \0) */
2847 char id_str[33];
2848
2849 session = hsm_find_repository_session(ctx, repository);
2850 if (!session) return NULL;
2851 cextractable = session->module->config->allow_extract ? CK_TRUE : CK_FALSE;
2852
2853 generate_unique_id(ctx, id, 16);
2854
2855 /* the CKA_LABEL will contain a hexadecimal string representation
2856 * of the id */
2857 hsm_hex_unparse(id_str, id, 16);
2858
2859 CK_KEY_TYPE keyType = CKK_EC;
2860 CK_MECHANISM mechanism = {
2862 };
2863
2864 CK_BYTE oidP256[] = { 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07 };
2865 CK_BYTE oidP384[] = { 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22 };
2866
2867 CK_ATTRIBUTE publicKeyTemplate[] = {
2868 { CKA_EC_PARAMS, NULL, 0 },
2869 { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen(id_str) },
2870 { CKA_ID, id, 16 },
2871 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2872 { CKA_VERIFY, &ctrue, sizeof(ctrue) },
2873 { CKA_ENCRYPT, &cfalse, sizeof(cfalse) },
2874 { CKA_WRAP, &cfalse, sizeof(cfalse) },
2875 { CKA_TOKEN, &ctrue, sizeof(ctrue) }
2876 };
2877
2878 CK_ATTRIBUTE privateKeyTemplate[] = {
2879 { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen (id_str) },
2880 { CKA_ID, id, 16 },
2881 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2882 { CKA_SIGN, &ctrue, sizeof(ctrue) },
2883 { CKA_DECRYPT, &cfalse, sizeof(cfalse) },
2884 { CKA_UNWRAP, &cfalse, sizeof(cfalse) },
2885 { CKA_SENSITIVE, &ctrue, sizeof(ctrue) },
2886 { CKA_TOKEN, &ctrue, sizeof(ctrue) },
2887 { CKA_PRIVATE, &ctrue, sizeof(ctrue) },
2888 { CKA_EXTRACTABLE, &cextractable, sizeof (cextractable) }
2889 };
2890
2891 /* Select the curve */
2892 if (strcmp(curve, "P-256") == 0)
2893 {
2894 publicKeyTemplate[0].pValue = oidP256;
2895 publicKeyTemplate[0].ulValueLen = sizeof(oidP256);
2896 }
2897 else if (strcmp(curve, "P-384") == 0)
2898 {
2899 publicKeyTemplate[0].pValue = oidP384;
2900 publicKeyTemplate[0].ulValueLen = sizeof(oidP384);
2901 }
2902 else
2903 {
2904 return NULL;
2905 }
2906
2907 /* Generate key pair */
2908
2909 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateKeyPair(session->session,
2910 &mechanism,
2911 publicKeyTemplate, 8,
2912 privateKeyTemplate, 10,
2913 &publicKey,
2914 &privateKey);
2915 if (hsm_pkcs11_check_error(ctx, rv, "generate key pair")) {
2916 return NULL;
2917 }
2918
2919 new_key = libhsm_key_new();
2920 new_key->modulename = strdup(session->module->name);
2921 new_key->public_key = publicKey;
2922 new_key->private_key = privateKey;
2923
2924 return new_key;
2925}
2926
2929 const char *repository,
2930 const char *curve)
2931{
2932 CK_RV rv;
2933 libhsm_key_t *new_key;
2934 hsm_session_t *session;
2935 CK_OBJECT_HANDLE publicKey, privateKey;
2936 CK_BBOOL ctrue = CK_TRUE;
2937 CK_BBOOL cfalse = CK_FALSE;
2938 CK_BBOOL cextractable = CK_FALSE;
2939
2940 /* ids we create are 16 bytes of data */
2941 unsigned char id[16];
2942 /* that's 33 bytes in string (16*2 + 1 for \0) */
2943 char id_str[33];
2944
2945 session = hsm_find_repository_session(ctx, repository);
2946 if (!session) return NULL;
2947 cextractable = session->module->config->allow_extract ? CK_TRUE : CK_FALSE;
2948
2949 generate_unique_id(ctx, id, 16);
2950
2951 /* the CKA_LABEL will contain a hexadecimal string representation
2952 * of the id */
2953 hsm_hex_unparse(id_str, id, 16);
2954
2955 CK_KEY_TYPE keyType = CKK_EC_EDWARDS;
2956 CK_MECHANISM mechanism = {
2958 };
2959
2960 CK_BYTE oid25519[] = { 0x06, 0x03, 0x2B, 0x65, 0x70 };
2961 CK_BYTE oid448[] = { 0x06, 0x03, 0x2B, 0x65, 0x71 };
2962
2963 CK_ATTRIBUTE publicKeyTemplate[] = {
2964 { CKA_EC_PARAMS, NULL, 0 },
2965 { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen(id_str) },
2966 { CKA_ID, id, 16 },
2967 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2968 { CKA_VERIFY, &ctrue, sizeof(ctrue) },
2969 { CKA_ENCRYPT, &cfalse, sizeof(cfalse) },
2970 { CKA_WRAP, &cfalse, sizeof(cfalse) },
2971 { CKA_TOKEN, &ctrue, sizeof(ctrue) }
2972 };
2973
2974 CK_ATTRIBUTE privateKeyTemplate[] = {
2975 { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen (id_str) },
2976 { CKA_ID, id, 16 },
2977 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2978 { CKA_SIGN, &ctrue, sizeof(ctrue) },
2979 { CKA_DECRYPT, &cfalse, sizeof(cfalse) },
2980 { CKA_UNWRAP, &cfalse, sizeof(cfalse) },
2981 { CKA_SENSITIVE, &ctrue, sizeof(ctrue) },
2982 { CKA_TOKEN, &ctrue, sizeof(ctrue) },
2983 { CKA_PRIVATE, &ctrue, sizeof(ctrue) },
2984 { CKA_EXTRACTABLE, &cextractable, sizeof (cextractable) }
2985 };
2986
2987 /* Select the curve */
2988 if (strcmp(curve, "edwards25519") == 0)
2989 {
2990 publicKeyTemplate[0].pValue = oid25519;
2991 publicKeyTemplate[0].ulValueLen = sizeof(oid25519);
2992 }
2993 else if (strcmp(curve, "edwards448") == 0)
2994 {
2995 publicKeyTemplate[0].pValue = oid448;
2996 publicKeyTemplate[0].ulValueLen = sizeof(oid448);
2997 }
2998 else
2999 {
3000 return NULL;
3001 }
3002
3003 /* Generate key pair */
3004
3005 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateKeyPair(session->session,
3006 &mechanism,
3007 publicKeyTemplate, 8,
3008 privateKeyTemplate, 10,
3009 &publicKey,
3010 &privateKey);
3011 if (hsm_pkcs11_check_error(ctx, rv, "generate key pair")) {
3012 return NULL;
3013 }
3014
3015 new_key = libhsm_key_new();
3016 new_key->modulename = strdup(session->module->name);
3017 new_key->public_key = publicKey;
3018 new_key->private_key = privateKey;
3019
3020 return new_key;
3021}
3022
3023int
3025{
3026 CK_RV rv;
3027 hsm_session_t *session;
3028 if (!key) return -1;
3029
3030 session = hsm_find_key_session(ctx, key);
3031 if (!session) return -2;
3032
3033 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DestroyObject(session->session,
3034 key->private_key);
3035 if (hsm_pkcs11_check_error(ctx, rv, "Destroy private key")) {
3036 return -3;
3037 }
3038 key->private_key = 0;
3039
3040 if (key->public_key) {
3041 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DestroyObject(session->session,
3042 key->public_key);
3043 if (hsm_pkcs11_check_error(ctx, rv, "Destroy public key")) {
3044 return -4;
3045 }
3046 }
3047 key->public_key = 0;
3048
3049 return 0;
3050}
3051
3052void
3053libhsm_key_list_free(libhsm_key_t **key_list, size_t count)
3054{
3055 size_t i;
3056 for (i = 0; i < count; i++) {
3057 libhsm_key_free(key_list[i]);
3058 }
3059 free(key_list);
3060}
3061
3062char *
3064{
3065 unsigned char *id;
3066 char *id_str;
3067 size_t len;
3068 hsm_session_t *session;
3069
3070 if (!key) return NULL;
3071
3072 session = hsm_find_key_session(ctx, key);
3073 if (!session) return NULL;
3074
3075 id = hsm_get_id_for_object(ctx, session, key->private_key, &len);
3076 if (!id) return NULL;
3077
3078 /* this is plain binary data, we need to convert it to hex */
3079 CHECKALLOC(id_str = malloc(len * 2 + 1));
3080
3081 hsm_hex_unparse(id_str, id, len);
3082
3083 free(id);
3084
3085 return id_str;
3086}
3087
3090 const libhsm_key_t *key)
3091{
3092 libhsm_key_info_t *key_info;
3093 hsm_session_t *session;
3094
3095 session = hsm_find_key_session(ctx, key);
3096 if (!session) return NULL;
3097
3098 CHECKALLOC(key_info = malloc(sizeof(libhsm_key_info_t)));
3099
3100 key_info->id = hsm_get_key_id(ctx, key);
3101 if (key_info->id == NULL) {
3102 key_info->id = strdup("");
3103 }
3104
3105 key_info->algorithm = (unsigned long) hsm_get_key_algorithm(ctx,
3106 session,
3107 key);
3108 key_info->keysize = (unsigned long) hsm_get_key_size(ctx,
3109 session,
3110 key,
3111 key_info->algorithm);
3112
3113 switch(key_info->algorithm) {
3114 case CKK_RSA:
3115 key_info->algorithm_name = strdup("RSA");
3116 break;
3117 case CKK_DSA:
3118 key_info->algorithm_name = strdup("DSA");
3119 break;
3120 case CKK_GOSTR3410:
3121 key_info->algorithm_name = strdup("GOST");
3122 break;
3123 case CKK_EC:
3124 key_info->algorithm_name = strdup("ECDSA");
3125 break;
3126 case CKK_EC_EDWARDS:
3127 key_info->algorithm_name = strdup("EDDSA");
3128 break;
3129 default:
3130 CHECKALLOC(key_info->algorithm_name = malloc(HSM_MAX_ALGONAME));
3131 snprintf(key_info->algorithm_name, HSM_MAX_ALGONAME,
3132 "%lu", key_info->algorithm);
3133 break;
3134 }
3135
3136 return key_info;
3137}
3138
3139void
3141{
3142 if (key_info) {
3143 if (key_info->id) {
3144 free(key_info->id);
3145 }
3146 if (key_info->algorithm_name) {
3147 free(key_info->algorithm_name);
3148 }
3149 free(key_info);
3150 }
3151}
3152
3153ldns_rr*
3155 const ldns_rr_list* rrset,
3156 const libhsm_key_t *key,
3157 const hsm_sign_params_t *sign_params)
3158{
3159 ldns_rr *signature;
3160 ldns_buffer *sign_buf;
3161 ldns_rdf *b64_rdf;
3162 size_t i;
3163
3164 if (!key) return NULL;
3165 if (!sign_params) return NULL;
3166
3167 signature = hsm_create_empty_rrsig((ldns_rr_list *)rrset,
3168 sign_params);
3169
3170 /* right now, we have: a key, a semi-sig and an rrset. For
3171 * which we can create the sig and base64 encode that and
3172 * add that to the signature */
3173 sign_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
3174
3175 if (ldns_rrsig2buffer_wire(sign_buf, signature)
3176 != LDNS_STATUS_OK) {
3177 ldns_buffer_free(sign_buf);
3178 /* ERROR */
3179 ldns_rr_free(signature);
3180 return NULL;
3181 }
3182
3183 /* make it canonical */
3184 for(i = 0; i < ldns_rr_list_rr_count(rrset); i++) {
3185 ldns_rr2canonical(ldns_rr_list_rr(rrset, i));
3186 }
3187
3188 /* add the rrset in sign_buf */
3189 if (ldns_rr_list2buffer_wire(sign_buf, rrset)
3190 != LDNS_STATUS_OK) {
3191 ldns_buffer_free(sign_buf);
3192 ldns_rr_free(signature);
3193 return NULL;
3194 }
3195
3196 b64_rdf = hsm_sign_buffer(ctx, sign_buf, key, sign_params->algorithm);
3197
3198 ldns_buffer_free(sign_buf);
3199 if (!b64_rdf) {
3200 /* signing went wrong */
3201 ldns_rr_free(signature);
3202 return NULL;
3203 }
3204
3205 ldns_rr_rrsig_set_sig(signature, b64_rdf);
3206
3207 return signature;
3208}
3209
3210int
3211hsm_keytag(const char* loc, int alg, int sep, uint16_t* keytag)
3212{
3213 uint16_t tag;
3214 hsm_ctx_t *hsm_ctx;
3215 hsm_sign_params_t *sign_params;
3216 libhsm_key_t *hsmkey;
3217 ldns_rr *dnskey_rr;
3218
3219 if (!loc) {
3220 return 1;
3221 }
3222
3223 if (!(hsm_ctx = hsm_create_context())) {
3224 return 1;
3225 }
3226 if (!(sign_params = hsm_sign_params_new())) {
3227 hsm_destroy_context(hsm_ctx);
3228 return 1;
3229 }
3230
3231 /* The owner name is not relevant for the keytag calculation.
3232 * However, a ldns_rdf_clone down the path will trip over it. */
3233 sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "dummy");
3234 sign_params->algorithm = (ldns_algorithm) alg;
3235 sign_params->flags = LDNS_KEY_ZONE_KEY;
3236 if (sep)
3237 sign_params->flags |= LDNS_KEY_SEP_KEY;
3238
3239 hsmkey = hsm_find_key_by_id(hsm_ctx, loc);
3240 if (!hsmkey) {
3241 hsm_sign_params_free(sign_params);
3242 hsm_destroy_context(hsm_ctx);
3243 return 1;
3244 }
3245
3246 dnskey_rr = hsm_get_dnskey(hsm_ctx, hsmkey, sign_params);
3247 if (!dnskey_rr) {
3248 libhsm_key_free(hsmkey);
3249 hsm_sign_params_free(sign_params);
3250 hsm_destroy_context(hsm_ctx);
3251 return 1;
3252 }
3253
3254 tag = ldns_calc_keytag(dnskey_rr);
3255
3256 ldns_rr_free(dnskey_rr);
3257 libhsm_key_free(hsmkey);
3258 hsm_sign_params_free(sign_params);
3259 hsm_destroy_context(hsm_ctx);
3260
3261 if (keytag)
3262 *keytag = tag;
3263 return 0;
3264}
3265
3266ldns_rr *
3268 const libhsm_key_t *key,
3269 const hsm_sign_params_t *sign_params)
3270{
3271 /* CK_RV rv; */
3272 ldns_rr *dnskey;
3273 hsm_session_t *session;
3274 ldns_rdf *rdata;
3275
3276 if (!key) {
3277 hsm_ctx_set_error(ctx, -1, "hsm_get_dnskey()", "Got NULL key");
3278 return NULL;
3279 }
3280 if (!sign_params) {
3281 hsm_ctx_set_error(ctx, -1, "hsm_get_dnskey()", "Got NULL sign_params");
3282 return NULL;
3283 }
3284 session = hsm_find_key_session(ctx, key);
3285 if (!session) return NULL;
3286
3287 dnskey = ldns_rr_new();
3288 ldns_rr_set_type(dnskey, LDNS_RR_TYPE_DNSKEY);
3289
3290 ldns_rr_set_owner(dnskey, ldns_rdf_clone(sign_params->owner));
3291
3292 ldns_rr_push_rdf(dnskey,
3293 ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
3294 sign_params->flags));
3295 ldns_rr_push_rdf(dnskey,
3296 ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
3297 LDNS_DNSSEC_KEYPROTO));
3298 ldns_rr_push_rdf(dnskey,
3299 ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG,
3300 sign_params->algorithm));
3301
3302 rdata = hsm_get_key_rdata(ctx, session, key);
3303 if (rdata == NULL) {
3304 ldns_rr_free(dnskey);
3305 return NULL;
3306 }
3307 ldns_rr_push_rdf(dnskey, rdata);
3308
3309 return dnskey;
3310}
3311
3312int
3314 unsigned char *buffer,
3315 unsigned long length)
3316{
3317 CK_RV rv;
3318 unsigned int i;
3319 hsm_session_t *session;
3320 if (!buffer) return -1;
3321
3322 /* just try every attached token. If one errors (be it NO_RNG, or
3323 * any other error, simply try the next */
3324 for (i = 0; i < ctx->session_count; i++) {
3325 session = ctx->session[i];
3326 if (session) {
3327 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateRandom(
3328 session->session,
3329 buffer,
3330 length);
3331 if (rv == CKR_OK) {
3332 return 0;
3333 }
3334 }
3335 }
3336 return 1;
3337}
3338
3339uint32_t
3341{
3342 uint32_t rnd;
3343 int result;
3344 unsigned char rnd_buf[4];
3345 result = hsm_random_buffer(ctx, rnd_buf, 4);
3346 if (result == 0) {
3347 memcpy(&rnd, rnd_buf, 4);
3348 return rnd;
3349 } else {
3350 return 0;
3351 }
3352}
3353
3354uint64_t
3356{
3357 uint64_t rnd;
3358 int result;
3359 unsigned char rnd_buf[8];
3360 result = hsm_random_buffer(ctx, rnd_buf, 8);
3361 if (result == 0) {
3362 memcpy(&rnd, rnd_buf, 8);
3363 return rnd;
3364 } else {
3365 return 0;
3366 }
3367}
3368
3369
3370/*
3371 * Additional functions
3372 */
3373
3374int hsm_attach(const char *repository,
3375 const char *token_label,
3376 const char *path,
3377 const char *pin,
3378 const hsm_config_t *config)
3379{
3380 hsm_session_t *session;
3381 int result;
3382
3383 result = hsm_session_init(_hsm_ctx,
3384 &session,
3385 repository,
3386 token_label,
3387 path,
3388 pin,
3389 config);
3390 if (result == HSM_OK) {
3391 result = hsm_ctx_add_session(_hsm_ctx, session);
3392 }
3393 return result;
3394}
3395
3396int
3397hsm_token_attached(hsm_ctx_t *ctx, const char *repository)
3398{
3399 unsigned int i;
3400 for (i = 0; i < ctx->session_count; i++) {
3401 if (ctx->session[i] &&
3402 strcmp(ctx->session[i]->module->name, repository) == 0) {
3403 return 1;
3404 }
3405 }
3406
3408 "hsm_token_attached()",
3409 "Can't find repository: %s", repository);
3410 return 0;
3411}
3412
3413char *
3415{
3416 hsm_ctx_t *ctx;
3417
3418 char *message;
3419
3420 if (!gctx) {
3421 ctx = _hsm_ctx;
3422 } else {
3423 ctx = gctx;
3424 }
3425
3426 if (ctx->error) {
3427 ctx->error = 0;
3428 CHECKALLOC(message = malloc(HSM_ERROR_MSGSIZE+3));
3429
3430 snprintf(message, HSM_ERROR_MSGSIZE,
3431 "%s: %s",
3432 ctx->error_action ? ctx->error_action : "unknown()",
3433 ctx->error_message[0] ? ctx->error_message : "unknown error");
3434
3435 /* Since both message and ctx->error_message have the same length, the
3436 * snprintf statement above may be truncated. In this case the string
3437 * won't be null-terminated. */
3438 message[HSM_ERROR_MSGSIZE - 1U] = '\0';
3439 return message;
3440 };
3441
3442 return NULL;
3443}
3444
3445void
3447{
3448 printf("\t\tmodule at %p (sym %p)\n", (void *) session->module, (void *) session->module->sym);
3449 printf("\t\tmodule path: %s\n", session->module->path);
3450 printf("\t\trepository name: %s\n", session->module->name);
3451 printf("\t\ttoken label: %s\n", session->module->token_label);
3452 printf("\t\tsess handle: %u\n", (unsigned int) session->session);
3453}
3454
3455void
3457 unsigned int i;
3458 printf("CTX Sessions: %lu\n",
3459 (long unsigned int) ctx->session_count);
3460 for (i = 0; i < ctx->session_count; i++) {
3461 printf("\tSession at %p\n", (void *) ctx->session[i]);
3463 }
3464}
3465
3466void
3468 libhsm_key_info_t *key_info;
3469 if (key) {
3470 key_info = hsm_get_key_info(ctx, key);
3471 if (key_info) {
3472 printf("key:\n");
3473 printf("\tprivkey handle: %u\n", (unsigned int) key->private_key);
3474 if (key->public_key) {
3475 printf("\tpubkey handle: %u\n", (unsigned int) key->public_key);
3476 } else {
3477 printf("\tpubkey handle: %s\n", "NULL");
3478 }
3479 printf("\trepository: %s\n", key->modulename);
3480 printf("\talgorithm: %s\n", key_info->algorithm_name);
3481 printf("\tsize: %lu\n", key_info->keysize);
3482 printf("\tid: %s\n", key_info->id);
3483 libhsm_key_info_free(key_info);
3484 } else {
3485 printf("key: hsm_get_key_info() returned NULL\n");
3486 }
3487 } else {
3488 printf("key: <void>\n");
3489 }
3490}
3491
3492void
3494{
3495 char *message;
3496
3497 message = hsm_get_error(gctx);
3498
3499 if (message) {
3500 fprintf(stderr, "%s\n", message);
3501 free(message);
3502 } else {
3503 fprintf(stderr, "Unknown error\n");
3504 }
3505}
3506
3507void
3509{
3510 CK_RV rv;
3511 CK_SLOT_ID slot_id;
3512 CK_TOKEN_INFO token_info;
3513 unsigned int i;
3514 hsm_session_t *session;
3515 int result;
3516
3517 for (i = 0; i < ctx->session_count; i++) {
3518 session = ctx->session[i];
3519
3520 result = hsm_get_slot_id(ctx,
3521 session->module->sym,
3522 session->module->token_label,
3523 &slot_id);
3524 if (result != HSM_OK) return;
3525
3526 rv = ((CK_FUNCTION_LIST_PTR) session->module->sym)->C_GetTokenInfo(slot_id, &token_info);
3527 if (hsm_pkcs11_check_error(ctx, rv, "C_GetTokenInfo")) {
3528 return;
3529 }
3530
3531 printf("Repository: %s\n",session->module->name);
3532
3533 printf("\tModule: %s\n", session->module->path);
3534 printf("\tSlot: %lu\n", slot_id);
3535 printf("\tToken Label: %.*s\n",
3536 (int) sizeof(token_info.label), token_info.label);
3537 printf("\tManufacturer: %.*s\n",
3538 (int) sizeof(token_info.manufacturerID), token_info.manufacturerID);
3539 printf("\tModel: %.*s\n",
3540 (int) sizeof(token_info.model), token_info.model);
3541 printf("\tSerial: %.*s\n",
3542 (int) sizeof(token_info.serialNumber), token_info.serialNumber);
3543
3544 if (i + 1 != ctx->session_count)
3545 printf("\n");
3546 }
3547}
3548
3549static int
3550keycache_cmpfunc(const void* a, const void* b)
3551{
3552 const char* x = (const char*)a;
3553 const char* y = (const char*)b;
3554 return strcmp(x, y);
3555}
3556
3557static void
3558keycache_delfunc(ldns_rbnode_t* node, void* cargo)
3559{
3560 (void)cargo;
3561 free((void*)node->key);
3562 free(((libhsm_key_t*)node->data)->modulename);
3563 free((void*)node->data);
3564 free((void*)node);
3565}
3566
3567void
3569{
3570 ctx->keycache = ldns_rbtree_create(keycache_cmpfunc);
3571 CHECKALLOC(_hsm_ctx->keycache_lock = malloc(sizeof (pthread_mutex_t)));
3572 pthread_mutex_init(_hsm_ctx->keycache_lock, NULL);
3573}
3574
3575void
3577{
3578 ldns_traverse_postorder(ctx->keycache, keycache_delfunc, NULL);
3579 ldns_rbtree_free(ctx->keycache);
3580 pthread_mutex_destroy(ctx->keycache_lock);
3581 free(ctx->keycache_lock);
3582 ctx->keycache_lock = NULL;
3583}
3584
3585const libhsm_key_t*
3586keycache_lookup(hsm_ctx_t* ctx, const char* locator)
3587{
3588 ldns_rbnode_t* node;
3589
3590 pthread_mutex_lock(ctx->keycache_lock);
3591 node = ldns_rbtree_search(ctx->keycache, locator);
3592 pthread_mutex_unlock(ctx->keycache_lock);
3593 if (node == LDNS_RBTREE_NULL || node == NULL) {
3594 libhsm_key_t* key;
3595 if ((key = hsm_find_key_by_id(ctx, locator)) == NULL) {
3596 node = NULL;
3597 } else {
3598 CHECKALLOC(node = malloc(sizeof(ldns_rbnode_t)));
3599 node->key = strdup(locator);
3600 node->data = key;
3601 pthread_mutex_lock(ctx->keycache_lock);
3602 node = ldns_rbtree_insert(ctx->keycache, node);
3603 pthread_mutex_unlock(ctx->keycache_lock);
3604 }
3605 }
3606
3607 if (node == LDNS_RBTREE_NULL || node == NULL)
3608 return NULL;
3609 else
3610 return node->data;
3611}
ldns_algorithm algorithm
Definition hsmspeed.c:43
hsm_ctx_t * ctx
Definition hsmutil.c:46
hsm_repository_t * hsm_repository_new(char *name, char *module, char *tokenlabel, char *pin, uint8_t use_pubkey, uint8_t allowextract, uint8_t require_backup)
Definition libhsm.c:374
hsm_ctx_t * _hsm_ctx
Definition libhsm.c:59
ldns_rr * hsm_sign_rrset(hsm_ctx_t *ctx, const ldns_rr_list *rrset, const libhsm_key_t *key, const hsm_sign_params_t *sign_params)
Definition libhsm.c:3154
void libhsm_key_list_free(libhsm_key_t **key_list, size_t count)
Definition libhsm.c:3053
void hsm_ctx_set_error(hsm_ctx_t *ctx, int error, const char *action, const char *message,...)
Definition libhsm.c:209
const libhsm_key_t * keycache_lookup(hsm_ctx_t *ctx, const char *locator)
Definition libhsm.c:3586
pthread_mutex_t _hsm_ctx_mutex
Definition libhsm.c:60
uint64_t hsm_random64(hsm_ctx_t *ctx)
Definition libhsm.c:3355
char * hsm_get_error(hsm_ctx_t *gctx)
Definition libhsm.c:3414
uint32_t hsm_random32(hsm_ctx_t *ctx)
Definition libhsm.c:3340
void hsm_print_error(hsm_ctx_t *gctx)
Definition libhsm.c:3493
libhsm_key_t * hsm_find_key_by_id(hsm_ctx_t *ctx, const char *id)
Definition libhsm.c:2521
int hsm_token_attached(hsm_ctx_t *ctx, const char *repository)
Definition libhsm.c:3397
#define HSM_TOKEN_LABEL_LENGTH
Definition libhsm.c:56
libhsm_key_t * hsm_generate_rsa_key(hsm_ctx_t *ctx, const char *repository, unsigned long keysize)
Definition libhsm.c:2550
libhsm_key_t * hsm_generate_gost_key(hsm_ctx_t *ctx, const char *repository)
Definition libhsm.c:2752
void hsm_print_key(hsm_ctx_t *ctx, libhsm_key_t *key)
Definition libhsm.c:3467
hsm_sign_params_t * hsm_sign_params_new()
Definition libhsm.c:2448
void hsm_print_ctx(hsm_ctx_t *ctx)
Definition libhsm.c:3456
void hsm_repository_free(hsm_repository_t *r)
Definition libhsm.c:407
int hsm_attach(const char *repository, const char *token_label, const char *path, const char *pin, const hsm_config_t *config)
Definition libhsm.c:3374
int hsm_check_context()
Definition libhsm.c:2384
char * hsm_get_key_id(hsm_ctx_t *ctx, const libhsm_key_t *key)
Definition libhsm.c:3063
void libhsm_key_info_free(libhsm_key_info_t *key_info)
Definition libhsm.c:3140
libhsm_key_t ** hsm_list_keys_repository(hsm_ctx_t *ctx, size_t *count, const char *repository)
Definition libhsm.c:2504
int hsm_random_buffer(hsm_ctx_t *ctx, unsigned char *buffer, unsigned long length)
Definition libhsm.c:3313
int hsm_open2(hsm_repository_t *rlist, char *(pin_callback)(unsigned int, const char *, unsigned int))
Definition libhsm.c:2297
ldns_rr * hsm_get_dnskey(hsm_ctx_t *ctx, const libhsm_key_t *key, const hsm_sign_params_t *sign_params)
Definition libhsm.c:3267
libhsm_key_t * hsm_generate_dsa_key(hsm_ctx_t *ctx, const char *repository, unsigned long keysize)
Definition libhsm.c:2638
libhsm_key_t * hsm_generate_eddsa_key(hsm_ctx_t *ctx, const char *repository, const char *curve)
Definition libhsm.c:2928
int hsm_keytag(const char *loc, int alg, int sep, uint16_t *keytag)
Definition libhsm.c:3211
libhsm_key_t * hsm_generate_ecdsa_key(hsm_ctx_t *ctx, const char *repository, const char *curve)
Definition libhsm.c:2832
void hsm_close()
Definition libhsm.c:2364
void hsm_print_session(hsm_session_t *session)
Definition libhsm.c:3446
void keycache_create(hsm_ctx_t *ctx)
Definition libhsm.c:3568
int hsm_remove_key(hsm_ctx_t *ctx, libhsm_key_t *key)
Definition libhsm.c:3024
void hsm_print_tokeninfo(hsm_ctx_t *ctx)
Definition libhsm.c:3508
libhsm_key_info_t * hsm_get_key_info(hsm_ctx_t *ctx, const libhsm_key_t *key)
Definition libhsm.c:3089
void hsm_destroy_context(hsm_ctx_t *ctx)
Definition libhsm.c:2439
libhsm_key_t ** hsm_list_keys(hsm_ctx_t *ctx, size_t *count)
Definition libhsm.c:2478
void keycache_destroy(hsm_ctx_t *ctx)
Definition libhsm.c:3576
void libhsm_key_free(libhsm_key_t *key)
Definition libhsm.c:2471
void hsm_sign_params_free(hsm_sign_params_t *params)
Definition libhsm.c:2462
hsm_ctx_t * hsm_create_context()
Definition libhsm.c:2374
#define HSM_NO_REPOSITORIES
Definition libhsm.h:70
#define HSM_ERROR
Definition libhsm.h:66
#define HSM_PIN_RETRY
Definition libhsm.h:75
#define HSM_ERROR_MSGSIZE
Definition libhsm.h:49
#define HSM_MODULE_NOT_FOUND
Definition libhsm.h:71
#define HSM_PIN_SAVE
Definition libhsm.h:76
#define HSM_MAX_ALGONAME
Definition libhsm.h:47
#define HSM_REPOSITORY_NOT_FOUND
Definition libhsm.h:69
#define HSM_PIN_FIRST
Definition libhsm.h:74
#define HSM_MAX_SIGNATURE_LENGTH
Definition libhsm.h:53
#define HSM_OK
Definition libhsm.h:65
#define HSM_MAX_SESSIONS
Definition libhsm.h:35
#define HSM_PIN_INCORRECT
Definition libhsm.h:67
#define CKM_DSA_PARAMETER_GEN
Definition pkcs11.h:682
#define CKR_SESSION_COUNT
Definition pkcs11.h:1152
#define CKR_DEVICE_MEMORY
Definition pkcs11.h:1124
#define CKA_TOKEN
Definition pkcs11.h:375
#define CKR_GENERAL_ERROR
Definition pkcs11.h:1111
#define CKR_MECHANISM_INVALID
Definition pkcs11.h:1141
#define CKR_SLOT_ID_INVALID
Definition pkcs11.h:1110
#define CKM_RSA_PKCS
Definition pkcs11.h:482
#define CKR_ATTRIBUTE_TYPE_INVALID
Definition pkcs11.h:1119
#define CKO_PUBLIC_KEY
Definition pkcs11.h:315
#define CKR_FUNCTION_CANCELED
Definition pkcs11.h:1128
#define CKR_DATA_INVALID
Definition pkcs11.h:1121
#define CKR_UNWRAPPING_KEY_HANDLE_INVALID
Definition pkcs11.h:1166
#define CKR_WRAPPING_KEY_SIZE_RANGE
Definition pkcs11.h:1178
#define CKR_MECHANISM_PARAM_INVALID
Definition pkcs11.h:1142
#define CKR_TOKEN_NOT_RECOGNIZED
Definition pkcs11.h:1164
#define CKM_MD5
Definition pkcs11.h:541
#define CK_FALSE
Definition pkcs11.h:1227
#define CKR_ATTRIBUTE_SENSITIVE
Definition pkcs11.h:1118
#define CKR_PIN_LEN_RANGE
Definition pkcs11.h:1148
#define CKR_DEVICE_ERROR
Definition pkcs11.h:1123
#define CKR_RANDOM_SEED_NOT_SUPPORTED
Definition pkcs11.h:1180
#define CKR_SESSION_PARALLEL_NOT_SUPPORTED
Definition pkcs11.h:1154
#define CKM_DSA
Definition pkcs11.h:497
#define CKA_ID
Definition pkcs11.h:396
#define CKR_ATTRIBUTE_READ_ONLY
Definition pkcs11.h:1117
#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT
Definition pkcs11.h:1179
#define CKR_SESSION_EXISTS
Definition pkcs11.h:1156
unsigned long int CK_ULONG
Definition pkcs11.h:1219
#define CKK_RSA
Definition pkcs11.h:334
#define CKA_PUBLIC_EXPONENT
Definition pkcs11.h:411
#define CKM_RSA_PKCS_KEY_PAIR_GEN
Definition pkcs11.h:481
#define CKR_SESSION_READ_ONLY
Definition pkcs11.h:1155
#define CKA_GOSTR3410PARAMS
Definition pkcs11.h:438
#define CKR_ENCRYPTED_DATA_LEN_RANGE
Definition pkcs11.h:1127
#define CKR_SIGNATURE_INVALID
Definition pkcs11.h:1159
#define CKR_SESSION_HANDLE_INVALID
Definition pkcs11.h:1153
#define CKF_RW_SESSION
Definition pkcs11.h:304
#define CKA_PRIME
Definition pkcs11.h:418
#define CKR_CANCEL
Definition pkcs11.h:1108
#define CKU_USER
Definition pkcs11.h:283
#define CKA_MODULUS
Definition pkcs11.h:409
unsigned char CK_BYTE
Definition pkcs11.h:1215
#define CKA_PRIVATE
Definition pkcs11.h:376
#define NULL_PTR
Definition pkcs11.h:1282
struct ck_function_list * CK_FUNCTION_LIST_PTR
Definition pkcs11.h:1276
#define CKR_TOKEN_NOT_PRESENT
Definition pkcs11.h:1163
#define CKA_EC_POINT
Definition pkcs11.h:433
#define CKR_CRYPTOKI_NOT_INITIALIZED
Definition pkcs11.h:1187
#define CKA_SENSITIVE
Definition pkcs11.h:397
#define CKR_PIN_INCORRECT
Definition pkcs11.h:1146
#define CKR_WRAPPED_KEY_INVALID
Definition pkcs11.h:1175
#define CKA_SIGN
Definition pkcs11.h:402
#define CKR_WRAPPING_KEY_HANDLE_INVALID
Definition pkcs11.h:1177
#define CKR_MUTEX_NOT_LOCKED
Definition pkcs11.h:1190
#define CKR_SESSION_CLOSED
Definition pkcs11.h:1151
#define CKM_EDDSA
Definition pkcs11.h:664
#define CK_TRUE
Definition pkcs11.h:1228
#define CKM_DSA_KEY_PAIR_GEN
Definition pkcs11.h:496
#define CKA_VALUE
Definition pkcs11.h:379
#define CKM_GOSTR3410
Definition pkcs11.h:679
CK_BYTE * CK_BYTE_PTR
Definition pkcs11.h:1221
#define value
Definition pkcs11.h:150
#define CKF_OS_LOCKING_OK
Definition pkcs11.h:1105
#define CKM_EC_EDWARDS_KEY_PAIR_GEN
Definition pkcs11.h:663
#define CKR_OBJECT_HANDLE_INVALID
Definition pkcs11.h:1143
#define CKA_VERIFY
Definition pkcs11.h:404
#define CKR_PIN_INVALID
Definition pkcs11.h:1147
#define CKR_UNWRAPPING_KEY_SIZE_RANGE
Definition pkcs11.h:1167
void * CK_VOID_PTR
Definition pkcs11.h:1225
#define CKO_PRIVATE_KEY
Definition pkcs11.h:316
#define CKR_ENCRYPTED_DATA_INVALID
Definition pkcs11.h:1126
#define CKR_CRYPTOKI_ALREADY_INITIALIZED
Definition pkcs11.h:1188
#define CKF_SERIAL_SESSION
Definition pkcs11.h:305
#define CKR_FUNCTION_FAILED
Definition pkcs11.h:1112
#define CKR_OPERATION_NOT_INITIALIZED
Definition pkcs11.h:1145
#define CKM_EC_KEY_PAIR_GEN
Definition pkcs11.h:657
#define CKK_DSA
Definition pkcs11.h:335
#define CKR_KEY_SIZE_RANGE
Definition pkcs11.h:1132
#define CKR_TEMPLATE_INCONSISTENT
Definition pkcs11.h:1162
#define CKR_OPERATION_ACTIVE
Definition pkcs11.h:1144
#define CKR_DATA_LEN_RANGE
Definition pkcs11.h:1122
#define CKA_UNWRAP
Definition pkcs11.h:401
#define CKK_GOSTR3410
Definition pkcs11.h:359
unsigned char CK_BBOOL
Definition pkcs11.h:1218
#define CKR_BUFFER_TOO_SMALL
Definition pkcs11.h:1183
#define CKS_RW_USER_FUNCTIONS
Definition pkcs11.h:292
#define CKA_DECRYPT
Definition pkcs11.h:399
#define CKA_KEY_TYPE
Definition pkcs11.h:394
#define CKR_USER_PIN_NOT_INITIALIZED
Definition pkcs11.h:1171
#define CKR_USER_ALREADY_LOGGED_IN
Definition pkcs11.h:1169
#define CKR_STATE_UNSAVEABLE
Definition pkcs11.h:1186
#define CKK_EC_EDWARDS
Definition pkcs11.h:360
#define CKR_INFORMATION_SENSITIVE
Definition pkcs11.h:1185
#define CKR_OK
Definition pkcs11.h:1107
#define CKM_ECDSA
Definition pkcs11.h:658
#define CKA_SUBPRIME
Definition pkcs11.h:419
#define CKR_ATTRIBUTE_VALUE_INVALID
Definition pkcs11.h:1120
#define CKM_GOSTR3411
Definition pkcs11.h:681
#define CKR_FUNCTION_NOT_SUPPORTED
Definition pkcs11.h:1130
#define slot_id
Definition pkcs11.h:139
#define CKR_USER_NOT_LOGGED_IN
Definition pkcs11.h:1170
#define CKR_DEVICE_REMOVED
Definition pkcs11.h:1125
#define CKR_TOKEN_WRITE_PROTECTED
Definition pkcs11.h:1165
#define CKA_MODULUS_BITS
Definition pkcs11.h:410
#define CKA_LABEL
Definition pkcs11.h:377
#define CKA_EXTRACTABLE
Definition pkcs11.h:425
#define CKR_TEMPLATE_INCOMPLETE
Definition pkcs11.h:1161
long int CK_LONG
Definition pkcs11.h:1220
#define CKA_ENCRYPT
Definition pkcs11.h:398
#define CKM_GOSTR3410_KEY_PAIR_GEN
Definition pkcs11.h:678
#define CKR_HOST_MEMORY
Definition pkcs11.h:1109
#define CKR_FUNCTION_NOT_PARALLEL
Definition pkcs11.h:1129
#define CKR_SIGNATURE_LEN_RANGE
Definition pkcs11.h:1160
#define value_len
Definition pkcs11.h:151
#define CKR_USER_TYPE_INVALID
Definition pkcs11.h:1172
#define CKR_KEY_HANDLE_INVALID
Definition pkcs11.h:1131
#define CKR_MUTEX_BAD
Definition pkcs11.h:1189
#define CKA_GOSTR3411PARAMS
Definition pkcs11.h:439
#define CKR_SAVED_STATE_INVALID
Definition pkcs11.h:1184
unsigned char CK_UTF8CHAR
Definition pkcs11.h:1217
#define CKK_EC
Definition pkcs11.h:338
#define CKR_WRAPPED_KEY_LEN_RANGE
Definition pkcs11.h:1176
#define CKA_PRIME_BITS
Definition pkcs11.h:421
#define CKA_BASE
Definition pkcs11.h:420
#define CKR_KEY_TYPE_INCONSISTENT
Definition pkcs11.h:1133
#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT
Definition pkcs11.h:1168
#define CKA_EC_PARAMS
Definition pkcs11.h:432
#define CKA_WRAP
Definition pkcs11.h:400
#define CKA_CLASS
Definition pkcs11.h:374
CK_C_GetSlotList C_GetSlotList
Definition pkcs11.h:1020
CK_C_GetTokenInfo C_GetTokenInfo
Definition pkcs11.h:1022
ck_mechanism_type_t mechanism
Definition pkcs11.h:690
ck_state_t state
Definition pkcs11.h:299
unsigned char model[16]
Definition pkcs11.h:233
unsigned char label[32]
Definition pkcs11.h:231
unsigned int allow_extract
Definition libhsm.h:81
unsigned int use_pubkey
Definition libhsm.h:80
int error
Definition libhsm.h:135
char error_message[HSM_ERROR_MSGSIZE]
Definition libhsm.h:142
const char * error_action
Definition libhsm.h:139
hsm_session_t * session[HSM_MAX_SESSIONS]
Definition libhsm.h:131
ldns_rbtree_t * keycache
Definition libhsm.h:144
size_t session_count
Definition libhsm.h:132
pthread_mutex_t * keycache_lock
Definition libhsm.h:145
char * token_label
Definition libhsm.h:88
char * name
Definition libhsm.h:87
char * path
Definition libhsm.h:89
void * sym
Definition libhsm.h:91
hsm_config_t * config
Definition libhsm.h:92
char *char * tokenlabel
Definition libhsm.h:122
hsm_repository_t * next
Definition libhsm.h:119
unsigned int allow_extract
Definition libhsm.h:126
uint8_t require_backup
Definition libhsm.h:124
hsm_module_t *unsigned long session
Definition libhsm.h:98
uint32_t inception
Definition libhsmdns.h:40
ldns_algorithm algorithm
Definition libhsmdns.h:36
ldns_rdf * owner
Definition libhsmdns.h:46
uint16_t keytag
Definition libhsmdns.h:44
uint32_t expiration
Definition libhsmdns.h:42
unsigned long algorithm
Definition libhsm.h:111
char * algorithm_name
Definition libhsm.h:112
unsigned long keysize
Definition libhsm.h:113
unsigned long public_key
Definition libhsm.h:105
unsigned long private_key
Definition libhsm.h:104
char * modulename
Definition libhsm.h:103