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