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,
591 CKF_SERIAL_SESSION | CKF_RW_SESSION,
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;
764 ctx->session_count++;
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 i;
1361
1362 for (i = 0; i < len; i++) {
1363 snprintf(dst + (2*i), 3, "%02x", src[i]);
1364 }
1365 dst[len*2] = '\0';
1366}
1367
1368/* returns an allocated byte array with the CKA_ID for the given object
1369 * len will contain the result size
1370 * returns NULL and size zero if not found in this session
1371 */
1372static CK_BYTE *
1373hsm_get_id_for_object(hsm_ctx_t *ctx,
1374 const hsm_session_t *session,
1375 CK_OBJECT_HANDLE object,
1376 size_t *len)
1377{
1378 CK_RV rv;
1379 CK_BYTE *id = NULL;
1380
1381 CK_ATTRIBUTE template[] = {
1382 {CKA_ID, id, 0}
1383 };
1384
1385 /* find out the size of the id first */
1386 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1387 session->session,
1388 object,
1389 template,
1390 1);
1391 if (hsm_pkcs11_check_error(ctx, rv, "Get attr value")) {
1392 *len = 0;
1393 return NULL;
1394 }
1395
1396 if ((CK_LONG)template[0].ulValueLen < 1) {
1397 /* No CKA_ID found, return NULL */
1398 *len = 0;
1399 return NULL;
1400 }
1401
1402 CHECKALLOC(template[0].pValue = malloc(template[0].ulValueLen));
1403 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1404 session->session,
1405 object,
1406 template,
1407 1);
1408 if (hsm_pkcs11_check_error(ctx, rv, "Get attr value 2")) {
1409 *len = 0;
1410 free(template[0].pValue);
1411 return NULL;
1412 }
1413
1414 *len = template[0].ulValueLen;
1415 return template[0].pValue;
1416}
1417
1418/* returns an libhsm_key_t object for the given *private key* object handle
1419 * the module, private key, and public key handle are set
1420 * The session needs to be free to perform a search for the public key
1421 */
1422static libhsm_key_t *
1423libhsm_key_new_privkey_object_handle(hsm_ctx_t *ctx,
1424 const hsm_session_t *session,
1425 CK_OBJECT_HANDLE object)
1426{
1427 libhsm_key_t *key;
1428 CK_BYTE *id;
1429 size_t len;
1430
1431 id = hsm_get_id_for_object(ctx, session, object, &len);
1432
1433 if (!id) return NULL;
1434
1435 key = libhsm_key_new();
1436 key->modulename = strdup(session->module->name);
1437 key->private_key = object;
1438
1439 key->public_key = hsm_find_object_handle_for_id(
1440 ctx,
1441 session,
1443 id,
1444 len);
1445
1446 free(id);
1447 return key;
1448}
1449
1450/* helper function to find both key counts or the keys themselves
1451 * if the argument store is 0, results are not returned; the
1452 * function will only set the count and return NULL
1453 * Otherwise, a newly allocated key array will be returned
1454 * (on error, the count will also be zero and NULL returned)
1455 */
1456static libhsm_key_t **
1457hsm_list_keys_session_internal(hsm_ctx_t *ctx,
1458 const hsm_session_t *session,
1459 size_t *count,
1460 int store)
1461{
1462 libhsm_key_t **keys = NULL;
1463 libhsm_key_t *key;
1464 CK_RV rv;
1465 CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY;
1466 CK_ATTRIBUTE template[] = {
1467 { CKA_CLASS, &key_class, sizeof(key_class) },
1468 };
1469 CK_ULONG total_count = 0;
1470 CK_ULONG objectCount = 1;
1471 /* find 100 keys at a time (and loop until there are none left) */
1472 CK_ULONG max_object_count = 100;
1473 CK_ULONG i, j;
1474 CK_OBJECT_HANDLE object[max_object_count];
1475 CK_OBJECT_HANDLE *key_handles = NULL, *new_key_handles = NULL;
1476
1477
1478 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjectsInit(session->session,
1479 template, 1);
1480 if (hsm_pkcs11_check_error(ctx, rv, "Find objects init")) {
1481 goto err;
1482 }
1483
1484 j = 0;
1485 while (objectCount > 0) {
1486 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjects(session->session,
1487 object,
1488 max_object_count,
1489 &objectCount);
1490 if (hsm_pkcs11_check_error(ctx, rv, "Find first object")) {
1491 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjectsFinal(session->session);
1492 hsm_pkcs11_check_error(ctx, rv, "Find objects cleanup");
1493 goto err;
1494 }
1495
1496 total_count += objectCount;
1497 if (objectCount > 0 && store) {
1498 if (SIZE_MAX / sizeof(CK_OBJECT_HANDLE) < total_count) {
1499 hsm_ctx_set_error(ctx, -1, "hsm_list_keys_session_internal",
1500 "Too much object handle returned by HSM to allocate key_handles");
1501 goto err;
1502 }
1503
1504 new_key_handles = realloc(key_handles, total_count * sizeof(CK_OBJECT_HANDLE));
1505 if (new_key_handles != NULL) {
1506 key_handles = new_key_handles;
1507 } else {
1508 hsm_ctx_set_error(ctx, -1, "hsm_list_keys_session_internal",
1509 "Error allocating memory for object handle (OOM)");
1510 goto err;
1511 }
1512
1513 for (i = 0; i < objectCount; i++) {
1514 key_handles[j] = object[i];
1515 j++;
1516 }
1517 }
1518 }
1519
1520 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjectsFinal(session->session);
1521 if (hsm_pkcs11_check_error(ctx, rv, "Find objects final")) {
1522 goto err;
1523 }
1524
1525 if (store) {
1526 if(SIZE_MAX / sizeof(libhsm_key_t *) < total_count) {
1527 hsm_ctx_set_error(ctx, -1, "hsm_list_keys_session_internal",
1528 "Too much object handle returned by HSM to allocate keys");
1529 goto err;
1530 }
1531
1532 CHECKALLOC(keys = malloc(total_count * sizeof(libhsm_key_t *)));
1533
1534 for (i = 0; i < total_count; i++) {
1535 key = libhsm_key_new_privkey_object_handle(ctx, session,
1536 key_handles[i]);
1537 if(!key) {
1538 libhsm_key_list_free(keys, i);
1539 goto err;
1540 }
1541 keys[i] = key;
1542 }
1543 }
1544 free(key_handles);
1545
1546 *count = total_count;
1547 return keys;
1548
1549err:
1550 free(key_handles);
1551 *count = 0;
1552 return NULL;
1553}
1554
1555
1556/* returns an array of all keys available to the given session
1557 *
1558 * \param session the session to find the keys in
1559 * \param count this value will contain the number of keys found
1560 *
1561 * \return the list of keys
1562 */
1563static libhsm_key_t **
1564hsm_list_keys_session(hsm_ctx_t *ctx, const hsm_session_t *session,
1565 size_t *count)
1566{
1567 return hsm_list_keys_session_internal(ctx, session, count, 1);
1568}
1569
1570/* returns a newly allocated key structure containing the key data
1571 * for the given CKA_ID available in the session. Returns NULL if not
1572 * found
1573 */
1574static libhsm_key_t *
1575hsm_find_key_by_id_session(hsm_ctx_t *ctx, const hsm_session_t *session,
1576 const unsigned char *id, size_t len)
1577{
1578 libhsm_key_t *key;
1579 CK_OBJECT_HANDLE private_key_handle;
1580
1581 private_key_handle = hsm_find_object_handle_for_id(
1582 ctx,
1583 session,
1585 (CK_BYTE *) id,
1586 (CK_ULONG) len);
1587 if (private_key_handle != 0) {
1588 key = libhsm_key_new_privkey_object_handle(ctx, session,
1589 private_key_handle);
1590 return key;
1591 } else {
1592 return NULL;
1593 }
1594}
1595
1596/* Find a key pair by CKA_ID (as byte array)
1597
1598The returned key structure can be freed with free()
1599
1600\param context HSM context
1601\param id CKA_ID of key to find (array of bytes)
1602\param len number of bytes in the id
1603\return key identifier or NULL if not found
1604*/
1605static libhsm_key_t *
1606hsm_find_key_by_id_bin(hsm_ctx_t *ctx,
1607 const unsigned char *id,
1608 size_t len)
1609{
1610 libhsm_key_t *key;
1611 unsigned int i;
1612
1613 if (!id) return NULL;
1614
1615 /* OPENDNSSEC-955: This procedure is mutexed to prevent a C_Login or
1616 * C_OpenSession happening at the same * time as looking up a key with
1617 * C_FindObject. Some HSMs like SoftHSM in database backend mode don't
1618 * like this.
1619 */
1620 pthread_mutex_lock(&_hsm_ctx_mutex);
1621 for (i = 0; i < ctx->session_count; i++) {
1622 key = hsm_find_key_by_id_session(ctx, ctx->session[i], id, len);
1623 if (key) {
1624 pthread_mutex_unlock(&_hsm_ctx_mutex);
1625 return key;
1626 }
1627 }
1628 pthread_mutex_unlock(&_hsm_ctx_mutex);
1629 return NULL;
1630}
1631
1632
1638static hsm_session_t *
1639hsm_find_repository_session(hsm_ctx_t *ctx, const char *repository)
1640{
1641 unsigned int i;
1642 if (!repository) {
1643 for (i = 0; i < ctx->session_count; i++) {
1644 if (ctx->session[i]) {
1645 return ctx->session[i];
1646 }
1647 }
1648 } else {
1649 for (i = 0; i < ctx->session_count; i++) {
1650 if (ctx->session[i] &&
1651 strcmp(repository, ctx->session[i]->module->name) == 0)
1652 {
1653 return ctx->session[i];
1654 }
1655 }
1656 }
1657
1659 "hsm_find_repository_session()",
1660 "Can't find repository: %s", repository);
1661
1662 return NULL;
1663}
1664
1665static ldns_rdf *
1666hsm_get_key_rdata_rsa(hsm_ctx_t *ctx, hsm_session_t *session,
1667 const libhsm_key_t *key)
1668{
1669 CK_RV rv;
1670 CK_BYTE_PTR public_exponent = NULL;
1671 CK_ULONG public_exponent_len = 0;
1672 CK_BYTE_PTR modulus = NULL;
1673 CK_ULONG modulus_len = 0;
1674 unsigned long hKey = 0;
1675 unsigned char *data = NULL;
1676 size_t data_size = 0;
1677
1678 CK_ATTRIBUTE template[] = {
1679 {CKA_PUBLIC_EXPONENT, NULL, 0},
1680 {CKA_MODULUS, NULL, 0},
1681 };
1682 ldns_rdf *rdf;
1683
1684 if (!session || !session->module) {
1685 return NULL;
1686 }
1687
1688 if (key->public_key) {
1689 hKey = key->public_key;
1690 } else {
1691 hKey = key->private_key;
1692 }
1693
1694 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1695 session->session,
1696 hKey,
1697 template,
1698 2);
1699 if (hsm_pkcs11_check_error(ctx, rv, "C_GetAttributeValue")) {
1700 return NULL;
1701 }
1702 public_exponent_len = template[0].ulValueLen;
1703 modulus_len = template[1].ulValueLen;
1704
1705 CHECKALLOC(public_exponent = template[0].pValue = malloc(public_exponent_len));
1706
1707 CHECKALLOC(modulus = template[1].pValue = malloc(modulus_len));
1708
1709 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1710 session->session,
1711 hKey,
1712 template,
1713 2);
1714 if (hsm_pkcs11_check_error(ctx, rv, "get attribute value")) {
1715 free(template[0].pValue);
1716 free(template[1].pValue);
1717 return NULL;
1718 }
1719
1720 // Remove leading zeroes
1721 hsm_remove_leading_zeroes(public_exponent, &public_exponent_len);
1722 hsm_remove_leading_zeroes(modulus, &modulus_len);
1723
1724 data_size = public_exponent_len + modulus_len + 1;
1725 if (public_exponent_len <= 255) {
1726 CHECKALLOC(data = malloc(data_size));
1727 data[0] = public_exponent_len;
1728 memcpy(&data[1], public_exponent, public_exponent_len);
1729 memcpy(&data[1 + public_exponent_len], modulus, modulus_len);
1730 } else if (public_exponent_len <= 65535) {
1731 data_size += 2;
1732 CHECKALLOC(data = malloc(data_size));
1733 data[0] = 0;
1734 ldns_write_uint16(&data[1], (uint16_t) public_exponent_len);
1735 memcpy(&data[3], public_exponent, public_exponent_len);
1736 memcpy(&data[3 + public_exponent_len], modulus, modulus_len);
1737 } else {
1738 hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata_rsa()",
1739 "Public exponent too big");
1740 free(public_exponent);
1741 free(modulus);
1742 return NULL;
1743 }
1744 rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, data_size, data);
1745 free(public_exponent);
1746 free(modulus);
1747
1748 return rdf;
1749}
1750
1751static ldns_rdf *
1752hsm_get_key_rdata_dsa(hsm_ctx_t *ctx, hsm_session_t *session,
1753 const libhsm_key_t *key)
1754{
1755 CK_RV rv;
1756 CK_BYTE_PTR prime = NULL;
1757 CK_ULONG prime_len = 0;
1758 CK_BYTE_PTR subprime = NULL;
1759 CK_ULONG subprime_len = 0;
1760 CK_BYTE_PTR base = NULL;
1761 CK_ULONG base_len = 0;
1762 CK_BYTE_PTR value = NULL;
1763 CK_ULONG value_len = 0;
1764 unsigned char *data = NULL;
1765 size_t data_size = 0;
1766
1767 CK_ATTRIBUTE template[] = {
1768 {CKA_PRIME, NULL, 0},
1769 {CKA_SUBPRIME, NULL, 0},
1770 {CKA_BASE, NULL, 0},
1771 {CKA_VALUE, NULL, 0},
1772 };
1773 ldns_rdf *rdf;
1774
1775 if (!session || !session->module) {
1776 return NULL;
1777 }
1778
1779 /* DSA needs the public key compared with RSA */
1780 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1781 session->session,
1782 key->public_key,
1783 template,
1784 4);
1785 if (hsm_pkcs11_check_error(ctx, rv, "C_GetAttributeValue")) {
1786 return NULL;
1787 }
1788 prime_len = template[0].ulValueLen;
1789 subprime_len = template[1].ulValueLen;
1790 base_len = template[2].ulValueLen;
1791 value_len = template[3].ulValueLen;
1792
1793 CHECKALLOC(prime = template[0].pValue = malloc(prime_len));
1794
1795 CHECKALLOC(subprime = template[1].pValue = malloc(subprime_len));
1796
1797 CHECKALLOC(base = template[2].pValue = malloc(base_len));
1798
1799 CHECKALLOC(value = template[3].pValue = malloc(value_len));
1800
1801 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1802 session->session,
1803 key->public_key,
1804 template,
1805 4);
1806 if (hsm_pkcs11_check_error(ctx, rv, "get attribute value")) {
1807 free(prime);
1808 free(subprime);
1809 free(base);
1810 free(value);
1811 return NULL;
1812 }
1813
1814 data_size = prime_len + subprime_len + base_len + value_len + 1;
1815 CHECKALLOC(data = malloc(data_size));
1816 data[0] = (prime_len - 64) / 8;
1817 memcpy(&data[1], subprime, subprime_len);
1818 memcpy(&data[1 + subprime_len], prime, prime_len);
1819 memcpy(&data[1 + subprime_len + prime_len], base, base_len);
1820 memcpy(&data[1 + subprime_len + prime_len + base_len], value, value_len);
1821
1822 rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, data_size, data);
1823 free(prime);
1824 free(subprime);
1825 free(base);
1826 free(value);
1827
1828 return rdf;
1829}
1830
1831static ldns_rdf *
1832hsm_get_key_rdata_gost(hsm_ctx_t *ctx, hsm_session_t *session,
1833 const libhsm_key_t *key)
1834{
1835 CK_RV rv;
1836 CK_BYTE_PTR value = NULL;
1837 CK_ULONG value_len = 0;
1838
1839 CK_ATTRIBUTE template[] = {
1840 {CKA_VALUE, NULL, 0},
1841 };
1842 ldns_rdf *rdf;
1843
1844 if (!session || !session->module) {
1845 return NULL;
1846 }
1847
1848 /* GOST needs the public key compared with RSA */
1849 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1850 session->session,
1851 key->public_key,
1852 template,
1853 1);
1854 if (hsm_pkcs11_check_error(ctx, rv, "C_GetAttributeValue")) {
1855 return NULL;
1856 }
1857 value_len = template[0].ulValueLen;
1858
1859 CHECKALLOC(value = template[0].pValue = malloc(value_len));
1860
1861 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1862 session->session,
1863 key->public_key,
1864 template,
1865 1);
1866 if (hsm_pkcs11_check_error(ctx, rv, "get attribute value")) {
1867 free(value);
1868 return NULL;
1869 }
1870
1871 rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, value_len, value);
1872 return rdf;
1873}
1874
1875static ldns_rdf *
1876hsm_get_key_rdata_ecdsa(hsm_ctx_t *ctx, hsm_session_t *session,
1877 const libhsm_key_t *key)
1878{
1880 unsigned char* value = hsm_get_key_ecdsa_value(ctx, session, key, &value_len);
1881
1882 if (value == NULL) return NULL;
1883
1884 ldns_rdf *rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, value_len, value);
1885
1886 return rdf;
1887}
1888
1889static ldns_rdf *
1890hsm_get_key_rdata_eddsa(hsm_ctx_t *ctx, hsm_session_t *session,
1891 const libhsm_key_t *key)
1892{
1894 unsigned char* value = hsm_get_key_eddsa_value(ctx, session, key, &value_len);
1895
1896 if (value == NULL) return NULL;
1897
1898 ldns_rdf *rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, value_len, value);
1899
1900 return rdf;
1901}
1902
1903static ldns_rdf *
1904hsm_get_key_rdata(hsm_ctx_t *ctx, hsm_session_t *session,
1905 const libhsm_key_t *key)
1906{
1907 switch (hsm_get_key_algorithm(ctx, session, key)) {
1908 case CKK_RSA:
1909 return hsm_get_key_rdata_rsa(ctx, session, key);
1910 break;
1911 case CKK_DSA:
1912 return hsm_get_key_rdata_dsa(ctx, session, key);
1913 break;
1914 case CKK_GOSTR3410:
1915 return hsm_get_key_rdata_gost(ctx, session, key);
1916 break;
1917 case CKK_EC:
1918 return hsm_get_key_rdata_ecdsa(ctx, session, key);
1919 case CKK_EC_EDWARDS:
1920 return hsm_get_key_rdata_eddsa(ctx, session, key);
1921 default:
1922 return 0;
1923 }
1924}
1925
1926/* this function allocates memory for the mechanism ID and enough room
1927 * to leave the upcoming digest data. It fills in the mechanism id
1928 * use with care. The returned data must be free'd by the caller.
1929 * Only used by RSA PKCS. */
1930static CK_BYTE *
1931hsm_create_prefix(CK_ULONG digest_len,
1932 ldns_algorithm algorithm,
1933 CK_ULONG *data_size)
1934{
1935 CK_BYTE *data;
1936 const CK_BYTE RSA_MD5_ID[] = { 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 };
1937 const CK_BYTE RSA_SHA1_ID[] = { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14 };
1938 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 };
1939 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 };
1940
1941 switch((ldns_signing_algorithm)algorithm) {
1942 case LDNS_SIGN_RSAMD5:
1943 *data_size = sizeof(RSA_MD5_ID) + digest_len;
1944 CHECKALLOC(data = malloc(*data_size));
1945 memcpy(data, RSA_MD5_ID, sizeof(RSA_MD5_ID));
1946 break;
1947 case LDNS_SIGN_RSASHA1:
1948 case LDNS_SIGN_RSASHA1_NSEC3:
1949 *data_size = sizeof(RSA_SHA1_ID) + digest_len;
1950 CHECKALLOC(data = malloc(*data_size));
1951 memcpy(data, RSA_SHA1_ID, sizeof(RSA_SHA1_ID));
1952 break;
1953 case LDNS_SIGN_RSASHA256:
1954 *data_size = sizeof(RSA_SHA256_ID) + digest_len;
1955 CHECKALLOC(data = malloc(*data_size));
1956 memcpy(data, RSA_SHA256_ID, sizeof(RSA_SHA256_ID));
1957 break;
1958 case LDNS_SIGN_RSASHA512:
1959 *data_size = sizeof(RSA_SHA512_ID) + digest_len;
1960 CHECKALLOC(data = malloc(*data_size));
1961 memcpy(data, RSA_SHA512_ID, sizeof(RSA_SHA512_ID));
1962 break;
1963 case LDNS_SIGN_DSA:
1964 case LDNS_SIGN_DSA_NSEC3:
1965 case LDNS_SIGN_ECC_GOST:
1966 case LDNS_SIGN_ECDSAP256SHA256:
1967 case LDNS_SIGN_ECDSAP384SHA384:
1968 *data_size = digest_len;
1969 CHECKALLOC(data = malloc(*data_size));
1970 break;
1971 default:
1972 return NULL;
1973 }
1974 return data;
1975}
1976
1977static CK_BYTE *
1978hsm_digest_through_hsm(hsm_ctx_t *ctx,
1979 hsm_session_t *session,
1980 CK_MECHANISM_TYPE mechanism_type,
1981 CK_ULONG digest_len,
1982 ldns_buffer *sign_buf)
1983{
1984 CK_MECHANISM digest_mechanism;
1985 CK_BYTE *digest;
1986 CK_RV rv;
1987
1988 digest_mechanism.pParameter = NULL;
1989 digest_mechanism.ulParameterLen = 0;
1990 digest_mechanism.mechanism = mechanism_type;
1991 CHECKALLOC(digest = malloc(digest_len));
1992 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DigestInit(session->session,
1993 &digest_mechanism);
1994 if (hsm_pkcs11_check_error(ctx, rv, "HSM digest init")) {
1995 free(digest);
1996 return NULL;
1997 }
1998
1999 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Digest(session->session,
2000 ldns_buffer_begin(sign_buf),
2001 ldns_buffer_position(sign_buf),
2002 digest,
2003 &digest_len);
2004 if (hsm_pkcs11_check_error(ctx, rv, "HSM digest")) {
2005 free(digest);
2006 return NULL;
2007 }
2008 return digest;
2009}
2010
2011static ldns_rdf *
2012hsm_sign_buffer(hsm_ctx_t *ctx,
2013 ldns_buffer *sign_buf,
2014 const libhsm_key_t *key,
2015 ldns_algorithm algorithm)
2016{
2017 CK_RV rv;
2018 CK_ULONG signatureLen = HSM_MAX_SIGNATURE_LENGTH;
2020 CK_MECHANISM sign_mechanism;
2021
2022 int data_direct = 0; // don't pre-create digest, use data directly
2023
2024 ldns_rdf *sig_rdf;
2025 CK_BYTE *digest = NULL;
2026 CK_ULONG digest_len = 0;
2027
2028 CK_BYTE *data = NULL;
2029 CK_ULONG data_len = 0;
2030
2031 hsm_session_t *session;
2032
2033 session = hsm_find_key_session(ctx, key);
2034 if (!session) return NULL;
2035
2036 /* some HSMs don't really handle CKM_SHA1_RSA_PKCS well, so
2037 * we'll do the hashing manually */
2038 /* When adding algorithms, remember there is another switch below */
2039 switch ((ldns_signing_algorithm)algorithm) {
2040 case LDNS_SIGN_RSAMD5:
2041 digest_len = 16;
2042 digest = hsm_digest_through_hsm(ctx, session,
2043 CKM_MD5, digest_len,
2044 sign_buf);
2045 break;
2046 case LDNS_SIGN_RSASHA1:
2047 case LDNS_SIGN_RSASHA1_NSEC3:
2048 case LDNS_SIGN_DSA:
2049 case LDNS_SIGN_DSA_NSEC3:
2050 digest_len = LDNS_SHA1_DIGEST_LENGTH;
2051 CHECKALLOC(digest = malloc(digest_len));
2052 digest = ldns_sha1(ldns_buffer_begin(sign_buf),
2053 ldns_buffer_position(sign_buf),
2054 digest);
2055 break;
2056
2057 case LDNS_SIGN_RSASHA256:
2058 case LDNS_SIGN_ECDSAP256SHA256:
2059 digest_len = LDNS_SHA256_DIGEST_LENGTH;
2060 CHECKALLOC(digest = malloc(digest_len));
2061 digest = ldns_sha256(ldns_buffer_begin(sign_buf),
2062 ldns_buffer_position(sign_buf),
2063 digest);
2064 break;
2065 case LDNS_SIGN_ECDSAP384SHA384:
2066 digest_len = LDNS_SHA384_DIGEST_LENGTH;
2067 CHECKALLOC(digest = malloc(digest_len));
2068 digest = ldns_sha384(ldns_buffer_begin(sign_buf),
2069 ldns_buffer_position(sign_buf),
2070 digest);
2071 break;
2072 case LDNS_SIGN_RSASHA512:
2073 digest_len = LDNS_SHA512_DIGEST_LENGTH;
2074 CHECKALLOC(digest = malloc(digest_len));
2075 digest = ldns_sha512(ldns_buffer_begin(sign_buf),
2076 ldns_buffer_position(sign_buf),
2077 digest);
2078 break;
2079 case LDNS_SIGN_ECC_GOST:
2080 digest_len = 32;
2081 digest = hsm_digest_through_hsm(ctx, session,
2082 CKM_GOSTR3411, digest_len,
2083 sign_buf);
2084 break;
2085#if (LDNS_REVISION >= ((1<<16)|(7<<8)|(0)))
2086 case LDNS_SIGN_ED25519:
2087 data_direct = 1;
2088 break;
2089 case LDNS_SIGN_ED448:
2090 data_direct = 1;
2091 break;
2092#endif
2093 default:
2094 /* log error? or should we not even get here for
2095 * unsupported algorithms? */
2096 return NULL;
2097 }
2098
2099 if (!data_direct && !digest) {
2100 return NULL;
2101 }
2102
2103 if (data_direct) {
2104 data = ldns_buffer_begin(sign_buf);
2105 data_len = ldns_buffer_position(sign_buf);
2106 } else {
2107 /* CKM_RSA_PKCS does the padding, but cannot know the identifier
2108 * prefix, so we need to add that ourselves.
2109 * The other algorithms will just get the digest buffer returned. */
2110 data = hsm_create_prefix(digest_len, algorithm, &data_len);
2111 memcpy(data + data_len - digest_len, digest, digest_len);
2112 }
2113
2114 sign_mechanism.pParameter = NULL;
2115 sign_mechanism.ulParameterLen = 0;
2116 switch((ldns_signing_algorithm)algorithm) {
2117 case LDNS_SIGN_RSAMD5:
2118 case LDNS_SIGN_RSASHA1:
2119 case LDNS_SIGN_RSASHA1_NSEC3:
2120 case LDNS_SIGN_RSASHA256:
2121 case LDNS_SIGN_RSASHA512:
2122 sign_mechanism.mechanism = CKM_RSA_PKCS;
2123 break;
2124 case LDNS_SIGN_DSA:
2125 case LDNS_SIGN_DSA_NSEC3:
2126 sign_mechanism.mechanism = CKM_DSA;
2127 break;
2128 case LDNS_SIGN_ECC_GOST:
2129 sign_mechanism.mechanism = CKM_GOSTR3410;
2130 break;
2131 case LDNS_SIGN_ECDSAP256SHA256:
2132 case LDNS_SIGN_ECDSAP384SHA384:
2133 sign_mechanism.mechanism = CKM_ECDSA;
2134 break;
2135#if (LDNS_REVISION >= ((1<<16)|(7<<8)|(0)))
2136 case LDNS_SIGN_ED25519:
2137 sign_mechanism.mechanism = CKM_EDDSA;
2138 break;
2139 case LDNS_SIGN_ED448:
2140 sign_mechanism.mechanism = CKM_EDDSA;
2141 break;
2142#endif
2143 default:
2144 /* log error? or should we not even get here for
2145 * unsupported algorithms? */
2146 free(data);
2147 free(digest);
2148 return NULL;
2149 }
2150
2151 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_SignInit(
2152 session->session,
2153 &sign_mechanism,
2154 key->private_key);
2155 if (hsm_pkcs11_check_error(ctx, rv, "sign init")) {
2156 if (!data_direct) {
2157 free(data);
2158 free(digest);
2159 }
2160 return NULL;
2161 }
2162
2163 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Sign(session->session, data, data_len,
2164 signature,
2165 &signatureLen);
2166 if (hsm_pkcs11_check_error(ctx, rv, "sign final")) {
2167 if (!data_direct) {
2168 free(data);
2169 free(digest);
2170 }
2171 return NULL;
2172 }
2173
2174 sig_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
2175 signatureLen,
2176 signature);
2177
2178 if (!data_direct) {
2179 free(data);
2180 free(digest);
2181 }
2182
2183 return sig_rdf;
2184
2185}
2186
2187static int
2188hsm_dname_is_wildcard(const ldns_rdf* dname)
2189{
2190 return ( ldns_dname_label_count(dname) > 0 &&
2191 ldns_rdf_data(dname)[0] == 1 &&
2192 ldns_rdf_data(dname)[1] == '*');
2193}
2194
2195static ldns_rr *
2196hsm_create_empty_rrsig(const ldns_rr_list *rrset,
2197 const hsm_sign_params_t *sign_params)
2198{
2199 ldns_rr *rrsig;
2200 uint32_t orig_ttl;
2201 uint32_t orig_class;
2202 time_t now;
2203 uint8_t label_count;
2204
2205 label_count = ldns_dname_label_count(
2206 ldns_rr_owner(ldns_rr_list_rr(rrset, 0)));
2207 /* RFC 4035 section 2.2: dnssec label length and wildcards */
2208 if (hsm_dname_is_wildcard(ldns_rr_owner(ldns_rr_list_rr(rrset, 0)))) {
2209 label_count--;
2210 }
2211
2212 rrsig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG);
2213
2214 /* set the type on the new signature */
2215 orig_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrset, 0));
2216 orig_class = ldns_rr_get_class(ldns_rr_list_rr(rrset, 0));
2217
2218 ldns_rr_set_class(rrsig, orig_class);
2219 ldns_rr_set_ttl(rrsig, orig_ttl);
2220 ldns_rr_set_owner(rrsig,
2221 ldns_rdf_clone(
2222 ldns_rr_owner(
2223 ldns_rr_list_rr(rrset,
2224 0))));
2225
2226 /* fill in what we know of the signature */
2227
2228 /* set the orig_ttl */
2229 (void)ldns_rr_rrsig_set_origttl(
2230 rrsig,
2231 ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
2232 orig_ttl));
2233 /* the signers name */
2234 (void)ldns_rr_rrsig_set_signame(
2235 rrsig,
2236 ldns_rdf_clone(sign_params->owner));
2237 /* label count - get it from the first rr in the rr_list */
2238 (void)ldns_rr_rrsig_set_labels(
2239 rrsig,
2240 ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
2241 label_count));
2242 /* inception, expiration */
2243 now = time_now();
2244 if (sign_params->inception != 0) {
2245 (void)ldns_rr_rrsig_set_inception(
2246 rrsig,
2247 ldns_native2rdf_int32(
2248 LDNS_RDF_TYPE_TIME,
2249 sign_params->inception));
2250 } else {
2251 (void)ldns_rr_rrsig_set_inception(
2252 rrsig,
2253 ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, now));
2254 }
2255 if (sign_params->expiration != 0) {
2256 (void)ldns_rr_rrsig_set_expiration(
2257 rrsig,
2258 ldns_native2rdf_int32(
2259 LDNS_RDF_TYPE_TIME,
2260 sign_params->expiration));
2261 } else {
2262 (void)ldns_rr_rrsig_set_expiration(
2263 rrsig,
2264 ldns_native2rdf_int32(
2265 LDNS_RDF_TYPE_TIME,
2266 now + LDNS_DEFAULT_EXP_TIME));
2267 }
2268
2269 (void)ldns_rr_rrsig_set_keytag(
2270 rrsig,
2271 ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
2272 sign_params->keytag));
2273
2274 (void)ldns_rr_rrsig_set_algorithm(
2275 rrsig,
2276 ldns_native2rdf_int8(
2277 LDNS_RDF_TYPE_ALG,
2278 sign_params->algorithm));
2279
2280 (void)ldns_rr_rrsig_set_typecovered(
2281 rrsig,
2282 ldns_native2rdf_int16(
2283 LDNS_RDF_TYPE_TYPE,
2284 ldns_rr_get_type(ldns_rr_list_rr(rrset,
2285 0))));
2286
2287 return rrsig;
2288}
2289
2290
2291/*
2292 * API functions
2293 */
2294
2295int
2297 char *(pin_callback)(unsigned int, const char *, unsigned int))
2298{
2299 hsm_config_t module_config;
2300 hsm_repository_t* repo = NULL;
2301 char* module_pin = NULL;
2302 int result = HSM_OK;
2303 int tries;
2304 int repositories = 0;
2305
2306 pthread_mutex_lock(&_hsm_ctx_mutex);
2307 /* create an internal context with an attached session for each
2308 * configured HSM. */
2309 if ((_hsm_ctx = hsm_ctx_new())) {
2311 }
2312
2313 repo = rlist;
2314 while (repo) {
2315 hsm_config_default(&module_config);
2316 module_config.use_pubkey = repo->use_pubkey;
2317 module_config.allow_extract = repo->allow_extract;
2318 if (repo->name && repo->module && repo->tokenlabel) {
2319 if (repo->pin) {
2320 result = hsm_attach(repo->name, repo->tokenlabel,
2321 repo->module, repo->pin, &module_config);
2322 } else {
2323 if (pin_callback) {
2324 result = HSM_PIN_INCORRECT;
2325 tries = 0;
2326 while (result == HSM_PIN_INCORRECT && tries < 3) {
2327 module_pin = pin_callback(_hsm_ctx->session_count,
2328 repo->name, tries?HSM_PIN_RETRY:HSM_PIN_FIRST);
2329 if (module_pin == NULL) break;
2330 result = hsm_attach(repo->name, repo->tokenlabel,
2331 repo->module, module_pin, &module_config);
2332 if (result == HSM_OK) {
2333 pin_callback(_hsm_ctx->session_count - 1,
2334 repo->name, HSM_PIN_SAVE);
2335 }
2336 memset(module_pin, 0, strlen(module_pin));
2337 tries++;
2338 }
2339 } else {
2340 /* no pin, no callback */
2341 hsm_ctx_set_error(_hsm_ctx, HSM_ERROR, "hsm_open2()",
2342 "No pin or callback function");
2343 result = HSM_ERROR;
2344 }
2345 }
2346 if (result != HSM_OK) {
2347 break;
2348 }
2349 repositories++;
2350 }
2351 repo = repo->next;
2352 }
2353 if (result == HSM_OK && repositories == 0) {
2355 "No repositories found");
2356 result = HSM_NO_REPOSITORIES;
2357 }
2358 pthread_mutex_unlock(&_hsm_ctx_mutex);
2359 return result;
2360}
2361
2362void
2364{
2365 pthread_mutex_lock(&_hsm_ctx_mutex);
2367 hsm_ctx_close(_hsm_ctx, 1);
2368 _hsm_ctx = NULL;
2369 pthread_mutex_unlock(&_hsm_ctx_mutex);
2370}
2371
2372hsm_ctx_t *
2374{
2375 hsm_ctx_t* newctx;
2376 pthread_mutex_lock(&_hsm_ctx_mutex);
2377 newctx = hsm_ctx_clone(_hsm_ctx);
2378 pthread_mutex_unlock(&_hsm_ctx_mutex);
2379 return newctx;
2380}
2381
2382int
2384{
2385 unsigned int i;
2386 hsm_session_t *session;
2387 CK_SESSION_INFO info;
2388 CK_RV rv;
2389 CK_SESSION_HANDLE session_handle;
2390 hsm_ctx_t *ctx;
2391
2392 pthread_mutex_lock(&_hsm_ctx_mutex);
2393 ctx = _hsm_ctx;
2394
2395 for (i = 0; i < ctx->session_count; i++) {
2396 session = ctx->session[i];
2397 if (session == NULL) continue;
2398
2399 /* Get session info */
2400 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetSessionInfo(
2401 session->session,
2402 &info);
2403 if (hsm_pkcs11_check_error(ctx, rv, "get session info")) {
2404 pthread_mutex_unlock(&_hsm_ctx_mutex);
2405 return HSM_ERROR;
2406 }
2407
2408 /* Check session info */
2409 if (info.state != CKS_RW_USER_FUNCTIONS) {
2410 hsm_ctx_set_error(ctx, HSM_ERROR, "hsm_check_context()",
2411 "Session not logged in");
2412 pthread_mutex_unlock(&_hsm_ctx_mutex);
2413 return HSM_ERROR;
2414 }
2415
2416 /* Try open and close a session with the token */
2417 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_OpenSession(info.slotID,
2419 NULL,
2420 NULL,
2421 &session_handle);
2422 if (hsm_pkcs11_check_error(ctx, rv, "test open session")) {
2423 pthread_mutex_unlock(&_hsm_ctx_mutex);
2424 return HSM_ERROR;
2425 }
2426 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_CloseSession(session_handle);
2427 if (hsm_pkcs11_check_error(ctx, rv, "test close session")) {
2428 pthread_mutex_unlock(&_hsm_ctx_mutex);
2429 return HSM_ERROR;
2430 }
2431 }
2432
2433 pthread_mutex_unlock(&_hsm_ctx_mutex);
2434 return HSM_OK;
2435}
2436
2437void
2439{
2440 hsm_ctx_close(ctx, 0);
2441}
2442
2448{
2449 hsm_sign_params_t *params;
2450 CHECKALLOC(params = malloc(sizeof(hsm_sign_params_t)));
2451 params->algorithm = LDNS_RSASHA256;
2452 params->flags = LDNS_KEY_ZONE_KEY;
2453 params->inception = 0;
2454 params->expiration = 0;
2455 params->keytag = 0;
2456 params->owner = NULL;
2457 return params;
2458}
2459
2460void
2462{
2463 if (params) {
2464 if (params->owner) ldns_rdf_deep_free(params->owner);
2465 free(params);
2466 }
2467}
2468
2469void
2471{
2472 free(key->modulename);
2473 free(key);
2474}
2475
2476libhsm_key_t **
2478{
2479 libhsm_key_t **keys = NULL;
2480 size_t key_count = 0;
2481 size_t cur_key_count;
2482 libhsm_key_t **session_keys;
2483 unsigned int i, j;
2484
2485 for (i = 0; i < ctx->session_count; i++) {
2486 session_keys = hsm_list_keys_session(ctx, ctx->session[i],
2487 &cur_key_count);
2488 CHECKALLOC(keys = realloc(keys,
2489 (key_count + cur_key_count) * sizeof(libhsm_key_t *)));
2490 for (j = 0; j < cur_key_count; j++) {
2491 keys[key_count + j] = session_keys[j];
2492 }
2493 key_count += cur_key_count;
2494 free(session_keys);
2495 }
2496 if (count) {
2497 *count = key_count;
2498 }
2499 return keys;
2500}
2501
2502libhsm_key_t **
2504 size_t *count,
2505 const char *repository)
2506{
2507 hsm_session_t *session;
2508
2509 if (!repository) return NULL;
2510
2511 session = hsm_find_repository_session(ctx, repository);
2512 if (!session) {
2513 *count = 0;
2514 return NULL;
2515 }
2516 return hsm_list_keys_session(ctx, session, count);
2517}
2518
2521{
2522 unsigned char *id_bytes;
2523 size_t len;
2524 libhsm_key_t *key;
2525
2526 id_bytes = hsm_hex_parse(id, &len);
2527
2528 if (!id_bytes) return NULL;
2529
2530 key = hsm_find_key_by_id_bin(ctx, id_bytes, len);
2531 free(id_bytes);
2532 return key;
2533}
2534
2535static void
2536generate_unique_id(hsm_ctx_t *ctx, unsigned char *buf, size_t bufsize)
2537{
2538 libhsm_key_t *key;
2539 /* check whether this key doesn't happen to exist already */
2540 hsm_random_buffer(ctx, buf, bufsize);
2541 while ((key = hsm_find_key_by_id_bin(ctx, buf, bufsize))) {
2542 libhsm_key_free(key);
2543 hsm_random_buffer(ctx, buf, bufsize);
2544 }
2545
2546}
2547
2550 const char *repository,
2551 unsigned long keysize)
2552{
2553 libhsm_key_t *new_key;
2554 hsm_session_t *session;
2555 /* ids we create are 16 bytes of data */
2556 unsigned char id[16];
2557 /* that's 33 bytes in string (16*2 + 1 for \0) */
2558 char id_str[33];
2559 CK_RV rv;
2560 CK_OBJECT_HANDLE publicKey, privateKey;
2561 CK_KEY_TYPE keyType = CKK_RSA;
2562 CK_MECHANISM mechanism = {
2564 };
2565 CK_BYTE publicExponent[] = { 1, 0, 1 };
2566 CK_BBOOL ctrue = CK_TRUE;
2567 CK_BBOOL cfalse = CK_FALSE;
2568 CK_BBOOL ctoken = CK_TRUE;
2569 CK_BBOOL cextractable = CK_FALSE;
2570
2571 session = hsm_find_repository_session(ctx, repository);
2572 if (!session) return NULL;
2573 cextractable = session->module->config->allow_extract ? CK_TRUE : CK_FALSE;
2574
2575 generate_unique_id(ctx, id, 16);
2576
2577 /* the CKA_LABEL will contain a hexadecimal string representation
2578 * of the id */
2579 hsm_hex_unparse(id_str, id, 16);
2580
2581 if (! session->module->config->use_pubkey) {
2582 ctoken = CK_FALSE;
2583 }
2584
2585 CK_ATTRIBUTE publicKeyTemplate[] = {
2586 { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen(id_str) },
2587 { CKA_ID, id, 16 },
2588 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2589 { CKA_VERIFY, &ctrue, sizeof(ctrue) },
2590 { CKA_ENCRYPT, &cfalse, sizeof(cfalse) },
2591 { CKA_WRAP, &cfalse, sizeof(cfalse) },
2592 { CKA_TOKEN, &ctoken, sizeof(ctoken) },
2593 { CKA_MODULUS_BITS, &keysize, sizeof(keysize) },
2594 { CKA_PUBLIC_EXPONENT, &publicExponent, sizeof(publicExponent)}
2595 };
2596
2597 CK_ATTRIBUTE privateKeyTemplate[] = {
2598 { CKA_LABEL,(CK_UTF8CHAR *) id_str, strlen (id_str) },
2599 { CKA_ID, id, 16 },
2600 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2601 { CKA_SIGN, &ctrue, sizeof (ctrue) },
2602 { CKA_DECRYPT, &cfalse, sizeof (cfalse) },
2603 { CKA_UNWRAP, &cfalse, sizeof (cfalse) },
2604 { CKA_SENSITIVE, &ctrue, sizeof (ctrue) },
2605 { CKA_TOKEN, &ctrue, sizeof (ctrue) },
2606 { CKA_PRIVATE, &ctrue, sizeof (ctrue) },
2607 { CKA_EXTRACTABLE, &cextractable, sizeof (cextractable) }
2608 };
2609
2610 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateKeyPair(session->session,
2611 &mechanism,
2612 publicKeyTemplate, 9,
2613 privateKeyTemplate, 10,
2614 &publicKey,
2615 &privateKey);
2616 if (hsm_pkcs11_check_error(ctx, rv, "generate key pair")) {
2617 return NULL;
2618 }
2619
2620 new_key = libhsm_key_new();
2621 new_key->modulename = strdup(session->module->name);
2622
2623 if (session->module->config->use_pubkey) {
2624 new_key->public_key = publicKey;
2625 } else {
2626 /* Destroy the object directly in order to optimize storage in HSM */
2627 /* Ignore return value, it is just a session object and will be destroyed later */
2628 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DestroyObject(session->session, publicKey);
2629 new_key->public_key = 0;
2630 }
2631
2632 new_key->private_key = privateKey;
2633 return new_key;
2634}
2635
2638 const char *repository,
2639 unsigned long keysize)
2640{
2641 CK_RV rv;
2642 libhsm_key_t *new_key;
2643 hsm_session_t *session;
2644 CK_OBJECT_HANDLE domainPar, publicKey, privateKey;
2645 CK_BBOOL ctrue = CK_TRUE;
2646 CK_BBOOL cfalse = CK_FALSE;
2647 CK_BBOOL cextractable = CK_FALSE;
2648
2649 /* ids we create are 16 bytes of data */
2650 unsigned char id[16];
2651 /* that's 33 bytes in string (16*2 + 1 for \0) */
2652 char id_str[33];
2653
2654 session = hsm_find_repository_session(ctx, repository);
2655 if (!session) return NULL;
2656 cextractable = session->module->config->allow_extract ? CK_TRUE : CK_FALSE;
2657
2658 generate_unique_id(ctx, id, 16);
2659
2660 /* the CKA_LABEL will contain a hexadecimal string representation
2661 * of the id */
2662 hsm_hex_unparse(id_str, id, 16);
2663
2664 CK_KEY_TYPE keyType = CKK_DSA;
2665 CK_MECHANISM mechanism1 = {
2667 };
2668 CK_MECHANISM mechanism2 = {
2670 };
2671
2672 /* The maximum size for DSA in DNSSEC */
2673 CK_BYTE dsa_p[128];
2674 CK_BYTE dsa_q[20];
2675 CK_BYTE dsa_g[128];
2676
2677 CK_ATTRIBUTE domainTemplate[] = {
2678 { CKA_PRIME_BITS, &keysize, sizeof(keysize) }
2679 };
2680
2681 CK_ATTRIBUTE publicKeyTemplate[] = {
2682 { CKA_PRIME, dsa_p, sizeof(dsa_p) },
2683 { CKA_SUBPRIME, dsa_q, sizeof(dsa_q) },
2684 { CKA_BASE, dsa_g, sizeof(dsa_g) },
2685 { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen(id_str) },
2686 { CKA_ID, id, 16 },
2687 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2688 { CKA_VERIFY, &ctrue, sizeof(ctrue) },
2689 { CKA_ENCRYPT, &cfalse, sizeof(cfalse) },
2690 { CKA_WRAP, &cfalse, sizeof(cfalse) },
2691 { CKA_TOKEN, &ctrue, sizeof(ctrue) }
2692 };
2693
2694 CK_ATTRIBUTE privateKeyTemplate[] = {
2695 { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen (id_str) },
2696 { CKA_ID, id, 16 },
2697 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2698 { CKA_SIGN, &ctrue, sizeof(ctrue) },
2699 { CKA_DECRYPT, &cfalse, sizeof(cfalse) },
2700 { CKA_UNWRAP, &cfalse, sizeof(cfalse) },
2701 { CKA_SENSITIVE, &ctrue, sizeof(ctrue) },
2702 { CKA_TOKEN, &ctrue, sizeof(ctrue) },
2703 { CKA_PRIVATE, &ctrue, sizeof(ctrue) },
2704 { CKA_EXTRACTABLE, &cextractable, sizeof (cextractable) }
2705 };
2706
2707 cextractable = session->module->config->allow_extract ? CK_TRUE : CK_FALSE;
2708
2709 /* Generate the domain parameters */
2710
2711 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateKey(session->session,
2712 &mechanism1,
2713 domainTemplate, 1,
2714 &domainPar);
2715 if (hsm_pkcs11_check_error(ctx, rv, "generate domain parameters")) {
2716 return NULL;
2717 }
2718
2719 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(session->session,
2720 domainPar, publicKeyTemplate, 3);
2721 if (hsm_pkcs11_check_error(ctx, rv, "get domain parameters")) {
2722 return NULL;
2723 }
2724
2725 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DestroyObject(session->session, domainPar);
2726 if (hsm_pkcs11_check_error(ctx, rv, "destroy domain parameters")) {
2727 return NULL;
2728 }
2729
2730 /* Generate key pair */
2731
2732 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateKeyPair(session->session,
2733 &mechanism2,
2734 publicKeyTemplate, 10,
2735 privateKeyTemplate, 10,
2736 &publicKey,
2737 &privateKey);
2738 if (hsm_pkcs11_check_error(ctx, rv, "generate key pair")) {
2739 return NULL;
2740 }
2741
2742 new_key = libhsm_key_new();
2743 new_key->modulename = strdup(session->module->name);
2744 new_key->public_key = publicKey;
2745 new_key->private_key = privateKey;
2746
2747 return new_key;
2748}
2749
2752 const char *repository)
2753{
2754 CK_RV rv;
2755 libhsm_key_t *new_key;
2756 hsm_session_t *session;
2757 CK_OBJECT_HANDLE publicKey, privateKey;
2758 CK_BBOOL ctrue = CK_TRUE;
2759 CK_BBOOL cfalse = CK_FALSE;
2760 CK_BBOOL cextractable = CK_FALSE;
2761
2762 /* ids we create are 16 bytes of data */
2763 unsigned char id[16];
2764 /* that's 33 bytes in string (16*2 + 1 for \0) */
2765 char id_str[33];
2766
2767 session = hsm_find_repository_session(ctx, repository);
2768 if (!session) return NULL;
2769 cextractable = session->module->config->allow_extract ? CK_TRUE : CK_FALSE;
2770
2771 generate_unique_id(ctx, id, 16);
2772
2773 /* the CKA_LABEL will contain a hexadecimal string representation
2774 * of the id */
2775 hsm_hex_unparse(id_str, id, 16);
2776
2777 CK_KEY_TYPE keyType = CKK_GOSTR3410;
2778 CK_MECHANISM mechanism = {
2780 };
2781
2782 CK_BYTE oid1[] = { 0x06, 0x07, 0x2A, 0x85, 0x03, 0x02, 0x02, 0x23, 0x01 };
2783 CK_BYTE oid2[] = { 0x06, 0x07, 0x2A, 0x85, 0x03, 0x02, 0x02, 0x1E, 0x01 };
2784
2785 CK_ATTRIBUTE publicKeyTemplate[] = {
2786 { CKA_GOSTR3410PARAMS, oid1, sizeof(oid1) },
2787 { CKA_GOSTR3411PARAMS, oid2, sizeof(oid2) },
2788 { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen(id_str) },
2789 { CKA_ID, id, 16 },
2790 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2791 { CKA_VERIFY, &ctrue, sizeof(ctrue) },
2792 { CKA_ENCRYPT, &cfalse, sizeof(cfalse) },
2793 { CKA_WRAP, &cfalse, sizeof(cfalse) },
2794 { CKA_TOKEN, &ctrue, sizeof(ctrue) }
2795 };
2796
2797 CK_ATTRIBUTE privateKeyTemplate[] = {
2798 { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen (id_str) },
2799 { CKA_ID, id, 16 },
2800 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2801 { CKA_SIGN, &ctrue, sizeof(ctrue) },
2802 { CKA_DECRYPT, &cfalse, sizeof(cfalse) },
2803 { CKA_UNWRAP, &cfalse, sizeof(cfalse) },
2804 { CKA_SENSITIVE, &ctrue, sizeof(ctrue) },
2805 { CKA_TOKEN, &ctrue, sizeof(ctrue) },
2806 { CKA_PRIVATE, &ctrue, sizeof(ctrue) },
2807 { CKA_EXTRACTABLE, &cextractable, sizeof (cextractable) }
2808 };
2809
2810 /* Generate key pair */
2811
2812 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateKeyPair(session->session,
2813 &mechanism,
2814 publicKeyTemplate, 9,
2815 privateKeyTemplate, 10,
2816 &publicKey,
2817 &privateKey);
2818 if (hsm_pkcs11_check_error(ctx, rv, "generate key pair")) {
2819 return NULL;
2820 }
2821
2822 new_key = libhsm_key_new();
2823 new_key->modulename = strdup(session->module->name);
2824 new_key->public_key = publicKey;
2825 new_key->private_key = privateKey;
2826
2827 return new_key;
2828}
2829
2832 const char *repository,
2833 const char *curve)
2834{
2835 CK_RV rv;
2836 libhsm_key_t *new_key;
2837 hsm_session_t *session;
2838 CK_OBJECT_HANDLE publicKey, privateKey;
2839 CK_BBOOL ctrue = CK_TRUE;
2840 CK_BBOOL cfalse = CK_FALSE;
2841 CK_BBOOL cextractable = CK_FALSE;
2842
2843 /* ids we create are 16 bytes of data */
2844 unsigned char id[16];
2845 /* that's 33 bytes in string (16*2 + 1 for \0) */
2846 char id_str[33];
2847
2848 session = hsm_find_repository_session(ctx, repository);
2849 if (!session) return NULL;
2850 cextractable = session->module->config->allow_extract ? CK_TRUE : CK_FALSE;
2851
2852 generate_unique_id(ctx, id, 16);
2853
2854 /* the CKA_LABEL will contain a hexadecimal string representation
2855 * of the id */
2856 hsm_hex_unparse(id_str, id, 16);
2857
2858 CK_KEY_TYPE keyType = CKK_EC;
2859 CK_MECHANISM mechanism = {
2861 };
2862
2863 CK_BYTE oidP256[] = { 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07 };
2864 CK_BYTE oidP384[] = { 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22 };
2865
2866 CK_ATTRIBUTE publicKeyTemplate[] = {
2867 { CKA_EC_PARAMS, NULL, 0 },
2868 { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen(id_str) },
2869 { CKA_ID, id, 16 },
2870 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2871 { CKA_VERIFY, &ctrue, sizeof(ctrue) },
2872 { CKA_ENCRYPT, &cfalse, sizeof(cfalse) },
2873 { CKA_WRAP, &cfalse, sizeof(cfalse) },
2874 { CKA_TOKEN, &ctrue, sizeof(ctrue) }
2875 };
2876
2877 CK_ATTRIBUTE privateKeyTemplate[] = {
2878 { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen (id_str) },
2879 { CKA_ID, id, 16 },
2880 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2881 { CKA_SIGN, &ctrue, sizeof(ctrue) },
2882 { CKA_DECRYPT, &cfalse, sizeof(cfalse) },
2883 { CKA_UNWRAP, &cfalse, sizeof(cfalse) },
2884 { CKA_SENSITIVE, &ctrue, sizeof(ctrue) },
2885 { CKA_TOKEN, &ctrue, sizeof(ctrue) },
2886 { CKA_PRIVATE, &ctrue, sizeof(ctrue) },
2887 { CKA_EXTRACTABLE, &cextractable, sizeof (cextractable) }
2888 };
2889
2890 /* Select the curve */
2891 if (strcmp(curve, "P-256") == 0)
2892 {
2893 publicKeyTemplate[0].pValue = oidP256;
2894 publicKeyTemplate[0].ulValueLen = sizeof(oidP256);
2895 }
2896 else if (strcmp(curve, "P-384") == 0)
2897 {
2898 publicKeyTemplate[0].pValue = oidP384;
2899 publicKeyTemplate[0].ulValueLen = sizeof(oidP384);
2900 }
2901 else
2902 {
2903 return NULL;
2904 }
2905
2906 /* Generate key pair */
2907
2908 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateKeyPair(session->session,
2909 &mechanism,
2910 publicKeyTemplate, 8,
2911 privateKeyTemplate, 10,
2912 &publicKey,
2913 &privateKey);
2914 if (hsm_pkcs11_check_error(ctx, rv, "generate key pair")) {
2915 return NULL;
2916 }
2917
2918 new_key = libhsm_key_new();
2919 new_key->modulename = strdup(session->module->name);
2920 new_key->public_key = publicKey;
2921 new_key->private_key = privateKey;
2922
2923 return new_key;
2924}
2925
2928 const char *repository,
2929 const char *curve)
2930{
2931 CK_RV rv;
2932 libhsm_key_t *new_key;
2933 hsm_session_t *session;
2934 CK_OBJECT_HANDLE publicKey, privateKey;
2935 CK_BBOOL ctrue = CK_TRUE;
2936 CK_BBOOL cfalse = CK_FALSE;
2937 CK_BBOOL cextractable = CK_FALSE;
2938
2939 /* ids we create are 16 bytes of data */
2940 unsigned char id[16];
2941 /* that's 33 bytes in string (16*2 + 1 for \0) */
2942 char id_str[33];
2943
2944 session = hsm_find_repository_session(ctx, repository);
2945 if (!session) return NULL;
2946 cextractable = session->module->config->allow_extract ? CK_TRUE : CK_FALSE;
2947
2948 generate_unique_id(ctx, id, 16);
2949
2950 /* the CKA_LABEL will contain a hexadecimal string representation
2951 * of the id */
2952 hsm_hex_unparse(id_str, id, 16);
2953
2954 CK_KEY_TYPE keyType = CKK_EC_EDWARDS;
2955 CK_MECHANISM mechanism = {
2957 };
2958
2959 CK_BYTE oid25519[] = { 0x06, 0x03, 0x2B, 0x65, 0x70 };
2960 CK_BYTE oid448[] = { 0x06, 0x03, 0x2B, 0x65, 0x71 };
2961
2962 CK_ATTRIBUTE publicKeyTemplate[] = {
2963 { CKA_EC_PARAMS, NULL, 0 },
2964 { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen(id_str) },
2965 { CKA_ID, id, 16 },
2966 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2967 { CKA_VERIFY, &ctrue, sizeof(ctrue) },
2968 { CKA_ENCRYPT, &cfalse, sizeof(cfalse) },
2969 { CKA_WRAP, &cfalse, sizeof(cfalse) },
2970 { CKA_TOKEN, &ctrue, sizeof(ctrue) }
2971 };
2972
2973 CK_ATTRIBUTE privateKeyTemplate[] = {
2974 { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen (id_str) },
2975 { CKA_ID, id, 16 },
2976 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2977 { CKA_SIGN, &ctrue, sizeof(ctrue) },
2978 { CKA_DECRYPT, &cfalse, sizeof(cfalse) },
2979 { CKA_UNWRAP, &cfalse, sizeof(cfalse) },
2980 { CKA_SENSITIVE, &ctrue, sizeof(ctrue) },
2981 { CKA_TOKEN, &ctrue, sizeof(ctrue) },
2982 { CKA_PRIVATE, &ctrue, sizeof(ctrue) },
2983 { CKA_EXTRACTABLE, &cextractable, sizeof (cextractable) }
2984 };
2985
2986 /* Select the curve */
2987 if (strcmp(curve, "edwards25519") == 0)
2988 {
2989 publicKeyTemplate[0].pValue = oid25519;
2990 publicKeyTemplate[0].ulValueLen = sizeof(oid25519);
2991 }
2992 else if (strcmp(curve, "edwards448") == 0)
2993 {
2994 publicKeyTemplate[0].pValue = oid448;
2995 publicKeyTemplate[0].ulValueLen = sizeof(oid448);
2996 }
2997 else
2998 {
2999 return NULL;
3000 }
3001
3002 /* Generate key pair */
3003
3004 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateKeyPair(session->session,
3005 &mechanism,
3006 publicKeyTemplate, 8,
3007 privateKeyTemplate, 10,
3008 &publicKey,
3009 &privateKey);
3010 if (hsm_pkcs11_check_error(ctx, rv, "generate key pair")) {
3011 return NULL;
3012 }
3013
3014 new_key = libhsm_key_new();
3015 new_key->modulename = strdup(session->module->name);
3016 new_key->public_key = publicKey;
3017 new_key->private_key = privateKey;
3018
3019 return new_key;
3020}
3021
3022int
3024{
3025 CK_RV rv;
3026 hsm_session_t *session;
3027 if (!key) return -1;
3028
3029 session = hsm_find_key_session(ctx, key);
3030 if (!session) return -2;
3031
3032 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DestroyObject(session->session,
3033 key->private_key);
3034 if (hsm_pkcs11_check_error(ctx, rv, "Destroy private key")) {
3035 return -3;
3036 }
3037 key->private_key = 0;
3038
3039 if (key->public_key) {
3040 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DestroyObject(session->session,
3041 key->public_key);
3042 if (hsm_pkcs11_check_error(ctx, rv, "Destroy public key")) {
3043 return -4;
3044 }
3045 }
3046 key->public_key = 0;
3047
3048 return 0;
3049}
3050
3051void
3052libhsm_key_list_free(libhsm_key_t **key_list, size_t count)
3053{
3054 size_t i;
3055 for (i = 0; i < count; i++) {
3056 libhsm_key_free(key_list[i]);
3057 }
3058 free(key_list);
3059}
3060
3061char *
3063{
3064 unsigned char *id;
3065 char *id_str;
3066 size_t len;
3067 hsm_session_t *session;
3068
3069 if (!key) return NULL;
3070
3071 session = hsm_find_key_session(ctx, key);
3072 if (!session) return NULL;
3073
3074 id = hsm_get_id_for_object(ctx, session, key->private_key, &len);
3075 if (!id) return NULL;
3076
3077 /* this is plain binary data, we need to convert it to hex */
3078 CHECKALLOC(id_str = malloc(len * 2 + 1));
3079
3080 hsm_hex_unparse(id_str, id, len);
3081
3082 free(id);
3083
3084 return id_str;
3085}
3086
3089 const libhsm_key_t *key)
3090{
3091 libhsm_key_info_t *key_info;
3092 hsm_session_t *session;
3093
3094 session = hsm_find_key_session(ctx, key);
3095 if (!session) return NULL;
3096
3097 CHECKALLOC(key_info = malloc(sizeof(libhsm_key_info_t)));
3098
3099 key_info->id = hsm_get_key_id(ctx, key);
3100 if (key_info->id == NULL) {
3101 key_info->id = strdup("");
3102 }
3103
3104 key_info->algorithm = (unsigned long) hsm_get_key_algorithm(ctx,
3105 session,
3106 key);
3107 key_info->keysize = (unsigned long) hsm_get_key_size(ctx,
3108 session,
3109 key,
3110 key_info->algorithm);
3111
3112 switch(key_info->algorithm) {
3113 case CKK_RSA:
3114 key_info->algorithm_name = strdup("RSA");
3115 break;
3116 case CKK_DSA:
3117 key_info->algorithm_name = strdup("DSA");
3118 break;
3119 case CKK_GOSTR3410:
3120 key_info->algorithm_name = strdup("GOST");
3121 break;
3122 case CKK_EC:
3123 key_info->algorithm_name = strdup("ECDSA");
3124 break;
3125 case CKK_EC_EDWARDS:
3126 key_info->algorithm_name = strdup("EDDSA");
3127 break;
3128 default:
3129 CHECKALLOC(key_info->algorithm_name = malloc(HSM_MAX_ALGONAME));
3130 snprintf(key_info->algorithm_name, HSM_MAX_ALGONAME,
3131 "%lu", key_info->algorithm);
3132 break;
3133 }
3134
3135 return key_info;
3136}
3137
3138void
3140{
3141 if (key_info) {
3142 if (key_info->id) {
3143 free(key_info->id);
3144 }
3145 if (key_info->algorithm_name) {
3146 free(key_info->algorithm_name);
3147 }
3148 free(key_info);
3149 }
3150}
3151
3152ldns_rr*
3154 const ldns_rr_list* rrset,
3155 const libhsm_key_t *key,
3156 const hsm_sign_params_t *sign_params)
3157{
3158 ldns_rr *signature;
3159 ldns_buffer *sign_buf;
3160 ldns_rdf *b64_rdf;
3161 size_t i;
3162
3163 if (!key) return NULL;
3164 if (!sign_params) return NULL;
3165
3166 signature = hsm_create_empty_rrsig((ldns_rr_list *)rrset,
3167 sign_params);
3168
3169 /* right now, we have: a key, a semi-sig and an rrset. For
3170 * which we can create the sig and base64 encode that and
3171 * add that to the signature */
3172 sign_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
3173
3174 if (ldns_rrsig2buffer_wire(sign_buf, signature)
3175 != LDNS_STATUS_OK) {
3176 ldns_buffer_free(sign_buf);
3177 /* ERROR */
3178 ldns_rr_free(signature);
3179 return NULL;
3180 }
3181
3182 /* make it canonical */
3183 for(i = 0; i < ldns_rr_list_rr_count(rrset); i++) {
3184 ldns_rr2canonical(ldns_rr_list_rr(rrset, i));
3185 }
3186
3187 /* add the rrset in sign_buf */
3188 if (ldns_rr_list2buffer_wire(sign_buf, rrset)
3189 != LDNS_STATUS_OK) {
3190 ldns_buffer_free(sign_buf);
3191 ldns_rr_free(signature);
3192 return NULL;
3193 }
3194
3195 b64_rdf = hsm_sign_buffer(ctx, sign_buf, key, sign_params->algorithm);
3196
3197 ldns_buffer_free(sign_buf);
3198 if (!b64_rdf) {
3199 /* signing went wrong */
3200 ldns_rr_free(signature);
3201 return NULL;
3202 }
3203
3204 ldns_rr_rrsig_set_sig(signature, b64_rdf);
3205
3206 return signature;
3207}
3208
3209int
3210hsm_keytag(const char* loc, int alg, int sep, uint16_t* keytag)
3211{
3212 uint16_t tag;
3213 hsm_ctx_t *hsm_ctx;
3214 hsm_sign_params_t *sign_params;
3215 libhsm_key_t *hsmkey;
3216 ldns_rr *dnskey_rr;
3217
3218 if (!loc) {
3219 return 1;
3220 }
3221
3222 if (!(hsm_ctx = hsm_create_context())) {
3223 return 1;
3224 }
3225 if (!(sign_params = hsm_sign_params_new())) {
3226 hsm_destroy_context(hsm_ctx);
3227 return 1;
3228 }
3229
3230 /* The owner name is not relevant for the keytag calculation.
3231 * However, a ldns_rdf_clone down the path will trip over it. */
3232 sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "dummy");
3233 sign_params->algorithm = (ldns_algorithm) alg;
3234 sign_params->flags = LDNS_KEY_ZONE_KEY;
3235 if (sep)
3236 sign_params->flags |= LDNS_KEY_SEP_KEY;
3237
3238 hsmkey = hsm_find_key_by_id(hsm_ctx, loc);
3239 if (!hsmkey) {
3240 hsm_sign_params_free(sign_params);
3241 hsm_destroy_context(hsm_ctx);
3242 return 1;
3243 }
3244
3245 dnskey_rr = hsm_get_dnskey(hsm_ctx, hsmkey, sign_params);
3246 if (!dnskey_rr) {
3247 libhsm_key_free(hsmkey);
3248 hsm_sign_params_free(sign_params);
3249 hsm_destroy_context(hsm_ctx);
3250 return 1;
3251 }
3252
3253 tag = ldns_calc_keytag(dnskey_rr);
3254
3255 ldns_rr_free(dnskey_rr);
3256 libhsm_key_free(hsmkey);
3257 hsm_sign_params_free(sign_params);
3258 hsm_destroy_context(hsm_ctx);
3259
3260 if (keytag)
3261 *keytag = tag;
3262 return 0;
3263}
3264
3265ldns_rr *
3267 const libhsm_key_t *key,
3268 const hsm_sign_params_t *sign_params)
3269{
3270 /* CK_RV rv; */
3271 ldns_rr *dnskey;
3272 hsm_session_t *session;
3273 ldns_rdf *rdata;
3274
3275 if (!key) {
3276 hsm_ctx_set_error(ctx, -1, "hsm_get_dnskey()", "Got NULL key");
3277 return NULL;
3278 }
3279 if (!sign_params) {
3280 hsm_ctx_set_error(ctx, -1, "hsm_get_dnskey()", "Got NULL sign_params");
3281 return NULL;
3282 }
3283 session = hsm_find_key_session(ctx, key);
3284 if (!session) return NULL;
3285
3286 dnskey = ldns_rr_new();
3287 ldns_rr_set_type(dnskey, LDNS_RR_TYPE_DNSKEY);
3288
3289 ldns_rr_set_owner(dnskey, ldns_rdf_clone(sign_params->owner));
3290
3291 ldns_rr_push_rdf(dnskey,
3292 ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
3293 sign_params->flags));
3294 ldns_rr_push_rdf(dnskey,
3295 ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
3296 LDNS_DNSSEC_KEYPROTO));
3297 ldns_rr_push_rdf(dnskey,
3298 ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG,
3299 sign_params->algorithm));
3300
3301 rdata = hsm_get_key_rdata(ctx, session, key);
3302 if (rdata == NULL) {
3303 ldns_rr_free(dnskey);
3304 return NULL;
3305 }
3306 ldns_rr_push_rdf(dnskey, rdata);
3307
3308 return dnskey;
3309}
3310
3311int
3313 unsigned char *buffer,
3314 unsigned long length)
3315{
3316 CK_RV rv;
3317 unsigned int i;
3318 hsm_session_t *session;
3319 if (!buffer) return -1;
3320
3321 /* just try every attached token. If one errors (be it NO_RNG, or
3322 * any other error, simply try the next */
3323 for (i = 0; i < ctx->session_count; i++) {
3324 session = ctx->session[i];
3325 if (session) {
3326 rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateRandom(
3327 session->session,
3328 buffer,
3329 length);
3330 if (rv == CKR_OK) {
3331 return 0;
3332 }
3333 }
3334 }
3335 return 1;
3336}
3337
3338uint32_t
3340{
3341 uint32_t rnd;
3342 int result;
3343 unsigned char rnd_buf[4];
3344 result = hsm_random_buffer(ctx, rnd_buf, 4);
3345 if (result == 0) {
3346 memcpy(&rnd, rnd_buf, 4);
3347 return rnd;
3348 } else {
3349 return 0;
3350 }
3351}
3352
3353uint64_t
3355{
3356 uint64_t rnd;
3357 int result;
3358 unsigned char rnd_buf[8];
3359 result = hsm_random_buffer(ctx, rnd_buf, 8);
3360 if (result == 0) {
3361 memcpy(&rnd, rnd_buf, 8);
3362 return rnd;
3363 } else {
3364 return 0;
3365 }
3366}
3367
3368
3369/*
3370 * Additional functions
3371 */
3372
3373int hsm_attach(const char *repository,
3374 const char *token_label,
3375 const char *path,
3376 const char *pin,
3377 const hsm_config_t *config)
3378{
3379 hsm_session_t *session;
3380 int result;
3381
3382 result = hsm_session_init(_hsm_ctx,
3383 &session,
3384 repository,
3385 token_label,
3386 path,
3387 pin,
3388 config);
3389 if (result == HSM_OK) {
3390 result = hsm_ctx_add_session(_hsm_ctx, session);
3391 }
3392 return result;
3393}
3394
3395int
3396hsm_token_attached(hsm_ctx_t *ctx, const char *repository)
3397{
3398 unsigned int i;
3399 for (i = 0; i < ctx->session_count; i++) {
3400 if (ctx->session[i] &&
3401 strcmp(ctx->session[i]->module->name, repository) == 0) {
3402 return 1;
3403 }
3404 }
3405
3407 "hsm_token_attached()",
3408 "Can't find repository: %s", repository);
3409 return 0;
3410}
3411
3412char *
3414{
3415 hsm_ctx_t *ctx;
3416
3417 char *message;
3418
3419 if (!gctx) {
3420 ctx = _hsm_ctx;
3421 } else {
3422 ctx = gctx;
3423 }
3424
3425 if (ctx->error) {
3426 ctx->error = 0;
3427 CHECKALLOC(message = malloc(HSM_ERROR_MSGSIZE+3));
3428
3429 snprintf(message, HSM_ERROR_MSGSIZE,
3430 "%s: %s",
3431 ctx->error_action ? ctx->error_action : "unknown()",
3432 ctx->error_message[0] ? ctx->error_message : "unknown error");
3433
3434 /* Since both message and ctx->error_message have the same length, the
3435 * snprintf statement above may be truncated. In this case the string
3436 * won't be null-terminated. */
3437 message[HSM_ERROR_MSGSIZE - 1U] = '\0';
3438 return message;
3439 };
3440
3441 return NULL;
3442}
3443
3444void
3446{
3447 printf("\t\tmodule at %p (sym %p)\n", (void *) session->module, (void *) session->module->sym);
3448 printf("\t\tmodule path: %s\n", session->module->path);
3449 printf("\t\trepository name: %s\n", session->module->name);
3450 printf("\t\ttoken label: %s\n", session->module->token_label);
3451 printf("\t\tsess handle: %u\n", (unsigned int) session->session);
3452}
3453
3454void
3456 unsigned int i;
3457 printf("CTX Sessions: %lu\n",
3458 (long unsigned int) ctx->session_count);
3459 for (i = 0; i < ctx->session_count; i++) {
3460 printf("\tSession at %p\n", (void *) ctx->session[i]);
3461 hsm_print_session(ctx->session[i]);
3462 }
3463}
3464
3465void
3467 libhsm_key_info_t *key_info;
3468 if (key) {
3469 key_info = hsm_get_key_info(ctx, key);
3470 if (key_info) {
3471 printf("key:\n");
3472 printf("\tprivkey handle: %u\n", (unsigned int) key->private_key);
3473 if (key->public_key) {
3474 printf("\tpubkey handle: %u\n", (unsigned int) key->public_key);
3475 } else {
3476 printf("\tpubkey handle: %s\n", "NULL");
3477 }
3478 printf("\trepository: %s\n", key->modulename);
3479 printf("\talgorithm: %s\n", key_info->algorithm_name);
3480 printf("\tsize: %lu\n", key_info->keysize);
3481 printf("\tid: %s\n", key_info->id);
3482 libhsm_key_info_free(key_info);
3483 } else {
3484 printf("key: hsm_get_key_info() returned NULL\n");
3485 }
3486 } else {
3487 printf("key: <void>\n");
3488 }
3489}
3490
3491void
3493{
3494 char *message;
3495
3496 message = hsm_get_error(gctx);
3497
3498 if (message) {
3499 fprintf(stderr, "%s\n", message);
3500 free(message);
3501 } else {
3502 fprintf(stderr, "Unknown error\n");
3503 }
3504}
3505
3506void
3508{
3509 CK_RV rv;
3510 CK_SLOT_ID slot_id;
3511 CK_TOKEN_INFO token_info;
3512 unsigned int i;
3513 hsm_session_t *session;
3514 int result;
3515
3516 for (i = 0; i < ctx->session_count; i++) {
3517 session = ctx->session[i];
3518
3519 result = hsm_get_slot_id(ctx,
3520 session->module->sym,
3521 session->module->token_label,
3522 &slot_id);
3523 if (result != HSM_OK) return;
3524
3525 rv = ((CK_FUNCTION_LIST_PTR) session->module->sym)->C_GetTokenInfo(slot_id, &token_info);
3526 if (hsm_pkcs11_check_error(ctx, rv, "C_GetTokenInfo")) {
3527 return;
3528 }
3529
3530 printf("Repository: %s\n",session->module->name);
3531
3532 printf("\tModule: %s\n", session->module->path);
3533 printf("\tSlot: %lu\n", slot_id);
3534 printf("\tToken Label: %.*s\n",
3535 (int) sizeof(token_info.label), token_info.label);
3536 printf("\tManufacturer: %.*s\n",
3537 (int) sizeof(token_info.manufacturerID), token_info.manufacturerID);
3538 printf("\tModel: %.*s\n",
3539 (int) sizeof(token_info.model), token_info.model);
3540 printf("\tSerial: %.*s\n",
3541 (int) sizeof(token_info.serialNumber), token_info.serialNumber);
3542
3543 if (i + 1 != ctx->session_count)
3544 printf("\n");
3545 }
3546}
3547
3548static int
3549keycache_cmpfunc(const void* a, const void* b)
3550{
3551 const char* x = (const char*)a;
3552 const char* y = (const char*)b;
3553 return strcmp(x, y);
3554}
3555
3556static void
3557keycache_delfunc(ldns_rbnode_t* node, void* cargo)
3558{
3559 (void)cargo;
3560 free((void*)node->key);
3561 free(((libhsm_key_t*)node->data)->modulename);
3562 free((void*)node->data);
3563 free((void*)node);
3564}
3565
3566void
3568{
3569 ctx->keycache = ldns_rbtree_create(keycache_cmpfunc);
3570 CHECKALLOC(_hsm_ctx->keycache_lock = malloc(sizeof (pthread_mutex_t)));
3571 pthread_mutex_init(_hsm_ctx->keycache_lock, NULL);
3572}
3573
3574void
3576{
3577 ldns_traverse_postorder(ctx->keycache, keycache_delfunc, NULL);
3578 ldns_rbtree_free(ctx->keycache);
3579 pthread_mutex_destroy(ctx->keycache_lock);
3580 free(ctx->keycache_lock);
3581 ctx->keycache_lock = NULL;
3582}
3583
3584const libhsm_key_t*
3585keycache_lookup(hsm_ctx_t* ctx, const char* locator)
3586{
3587 ldns_rbnode_t* node;
3588
3589 pthread_mutex_lock(ctx->keycache_lock);
3590 node = ldns_rbtree_search(ctx->keycache, locator);
3591 pthread_mutex_unlock(ctx->keycache_lock);
3592 if (node == LDNS_RBTREE_NULL || node == NULL) {
3593 libhsm_key_t* key;
3594 if ((key = hsm_find_key_by_id(ctx, locator)) == NULL) {
3595 node = NULL;
3596 } else {
3597 CHECKALLOC(node = malloc(sizeof(ldns_rbnode_t)));
3598 node->key = strdup(locator);
3599 node->data = key;
3600 pthread_mutex_lock(ctx->keycache_lock);
3601 node = ldns_rbtree_insert(ctx->keycache, node);
3602 pthread_mutex_unlock(ctx->keycache_lock);
3603 }
3604 }
3605
3606 if (node == LDNS_RBTREE_NULL || node == NULL)
3607 return NULL;
3608 else
3609 return node->data;
3610}
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:3153
void libhsm_key_list_free(libhsm_key_t **key_list, size_t count)
Definition libhsm.c:3052
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:3585
pthread_mutex_t _hsm_ctx_mutex
Definition libhsm.c:60
uint64_t hsm_random64(hsm_ctx_t *ctx)
Definition libhsm.c:3354
char * hsm_get_error(hsm_ctx_t *gctx)
Definition libhsm.c:3413
uint32_t hsm_random32(hsm_ctx_t *ctx)
Definition libhsm.c:3339
void hsm_print_error(hsm_ctx_t *gctx)
Definition libhsm.c:3492
libhsm_key_t * hsm_find_key_by_id(hsm_ctx_t *ctx, const char *id)
Definition libhsm.c:2520
int hsm_token_attached(hsm_ctx_t *ctx, const char *repository)
Definition libhsm.c:3396
#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:2549
libhsm_key_t * hsm_generate_gost_key(hsm_ctx_t *ctx, const char *repository)
Definition libhsm.c:2751
void hsm_print_key(hsm_ctx_t *ctx, libhsm_key_t *key)
Definition libhsm.c:3466
hsm_sign_params_t * hsm_sign_params_new()
Definition libhsm.c:2447
void hsm_print_ctx(hsm_ctx_t *ctx)
Definition libhsm.c:3455
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:3373
int hsm_check_context()
Definition libhsm.c:2383
char * hsm_get_key_id(hsm_ctx_t *ctx, const libhsm_key_t *key)
Definition libhsm.c:3062
void libhsm_key_info_free(libhsm_key_info_t *key_info)
Definition libhsm.c:3139
libhsm_key_t ** hsm_list_keys_repository(hsm_ctx_t *ctx, size_t *count, const char *repository)
Definition libhsm.c:2503
int hsm_random_buffer(hsm_ctx_t *ctx, unsigned char *buffer, unsigned long length)
Definition libhsm.c:3312
int hsm_open2(hsm_repository_t *rlist, char *(pin_callback)(unsigned int, const char *, unsigned int))
Definition libhsm.c:2296
ldns_rr * hsm_get_dnskey(hsm_ctx_t *ctx, const libhsm_key_t *key, const hsm_sign_params_t *sign_params)
Definition libhsm.c:3266
libhsm_key_t * hsm_generate_dsa_key(hsm_ctx_t *ctx, const char *repository, unsigned long keysize)
Definition libhsm.c:2637
libhsm_key_t * hsm_generate_eddsa_key(hsm_ctx_t *ctx, const char *repository, const char *curve)
Definition libhsm.c:2927
int hsm_keytag(const char *loc, int alg, int sep, uint16_t *keytag)
Definition libhsm.c:3210
libhsm_key_t * hsm_generate_ecdsa_key(hsm_ctx_t *ctx, const char *repository, const char *curve)
Definition libhsm.c:2831
void hsm_close()
Definition libhsm.c:2363
void hsm_print_session(hsm_session_t *session)
Definition libhsm.c:3445
void keycache_create(hsm_ctx_t *ctx)
Definition libhsm.c:3567
int hsm_remove_key(hsm_ctx_t *ctx, libhsm_key_t *key)
Definition libhsm.c:3023
void hsm_print_tokeninfo(hsm_ctx_t *ctx)
Definition libhsm.c:3507
libhsm_key_info_t * hsm_get_key_info(hsm_ctx_t *ctx, const libhsm_key_t *key)
Definition libhsm.c:3088
void hsm_destroy_context(hsm_ctx_t *ctx)
Definition libhsm.c:2438
libhsm_key_t ** hsm_list_keys(hsm_ctx_t *ctx, size_t *count)
Definition libhsm.c:2477
void keycache_destroy(hsm_ctx_t *ctx)
Definition libhsm.c:3575
void libhsm_key_free(libhsm_key_t *key)
Definition libhsm.c:2470
void hsm_sign_params_free(hsm_sign_params_t *params)
Definition libhsm.c:2461
hsm_ctx_t * hsm_create_context()
Definition libhsm.c:2373
#define HSM_NO_REPOSITORIES
Definition libhsm.h:70
struct hsm_repository_struct hsm_repository_t
Definition libhsm.h:117
#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
struct ck_token_info CK_TOKEN_INFO
Definition pkcs11.h:1249
#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
struct ck_session_info CK_SESSION_INFO
Definition pkcs11.h:1254
#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 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
#define CKO_PRIVATE_KEY
Definition pkcs11.h:316
struct ck_mechanism CK_MECHANISM
Definition pkcs11.h:1269
#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
struct ck_function_list ** CK_FUNCTION_LIST_PTR_PTR
Definition pkcs11.h:1277
#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
struct ck_attribute CK_ATTRIBUTE
Definition pkcs11.h:1261
#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
struct ck_c_initialize_args CK_C_INITIALIZE_ARGS
Definition pkcs11.h:1279
#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
ldns_rbtree_t * keycache
Definition libhsm.h:144
pthread_mutex_t * keycache_lock
Definition libhsm.h:145
char * token_label
Definition libhsm.h:88
char * name
Definition libhsm.h:87
void * handle
Definition libhsm.h:90
char * path
Definition libhsm.h:89
void * sym
Definition libhsm.h:91
hsm_config_t * config
Definition libhsm.h:92
hsm_repository_t * next
Definition libhsm.h:119
unsigned int allow_extract
Definition libhsm.h:126
uint8_t require_backup
Definition libhsm.h:124
unsigned long session
Definition libhsm.h:98
hsm_module_t * module
Definition libhsm.h:97
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