OpenDNSSEC-libhsm  1.3.16
libhsm.c
Go to the documentation of this file.
1 /* $Id: libhsm.c 7438 2013-11-27 10:45:51Z matthijs $ */
2 
3 /*
4  * Copyright (c) 2009 .SE (The Internet Infrastructure Foundation).
5  * Copyright (c) 2009 NLNet Labs.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "config.h"
31 
32 #include <stdio.h>
33 #include <string.h>
34 #include <strings.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <dlfcn.h>
38 
39 #include <libxml/tree.h>
40 #include <libxml/parser.h>
41 #include <libxml/xpath.h>
42 #include <libxml/xpathInternals.h>
43 #include <libxml/relaxng.h>
44 
45 #include "libhsm.h"
46 #include "libhsmdns.h"
47 #include "compat.h"
48 
49 #include <pkcs11.h>
50 
52 #define HSM_TOKEN_LABEL_LENGTH 32
53 
55 static hsm_ctx_t *_hsm_ctx;
56 
58 static char *
59 ldns_pkcs11_rv_str(CK_RV rv)
60 {
61  switch (rv)
62  {
63  case CKR_OK:
64  return "CKR_OK";
65  case CKR_CANCEL:
66  return "CKR_CANCEL";
67  case CKR_HOST_MEMORY:
68  return "CKR_HOST_MEMORY";
69  case CKR_GENERAL_ERROR:
70  return "CKR_GENERAL_ERROR";
72  return "CKR_FUNCTION_FAILED";
74  return "CKR_SLOT_ID_INVALID";
76  return "CKR_ATTRIBUTE_READ_ONLY";
78  return "CKR_ATTRIBUTE_SENSITIVE";
80  return "CKR_ATTRIBUTE_TYPE_INVALID";
82  return "CKR_ATTRIBUTE_VALUE_INVALID";
83  case CKR_DATA_INVALID:
84  return "CKR_DATA_INVALID";
85  case CKR_DATA_LEN_RANGE:
86  return "CKR_DATA_LEN_RANGE";
87  case CKR_DEVICE_ERROR:
88  return "CKR_DEVICE_ERROR";
89  case CKR_DEVICE_MEMORY:
90  return "CKR_DEVICE_MEMORY";
91  case CKR_DEVICE_REMOVED:
92  return "CKR_DEVICE_REMOVED";
94  return "CKR_ENCRYPTED_DATA_INVALID";
96  return "CKR_ENCRYPTED_DATA_LEN_RANGE";
98  return "CKR_FUNCTION_CANCELED";
100  return "CKR_FUNCTION_NOT_PARALLEL";
102  return "CKR_KEY_HANDLE_INVALID";
103  case CKR_KEY_SIZE_RANGE:
104  return "CKR_KEY_SIZE_RANGE";
106  return "CKR_KEY_TYPE_INCONSISTENT";
108  return "CKR_MECHANISM_INVALID";
110  return "CKR_MECHANISM_PARAM_INVALID";
112  return "CKR_OBJECT_HANDLE_INVALID";
114  return "CKR_OPERATION_ACTIVE";
116  return "CKR_OPERATION_NOT_INITIALIZED";
117  case CKR_PIN_INCORRECT:
118  return "CKR_PIN_INCORRECT";
119  case CKR_PIN_INVALID:
120  return "CKR_PIN_INVALID";
121  case CKR_PIN_LEN_RANGE:
122  return "CKR_PIN_LEN_RANGE";
123  case CKR_SESSION_CLOSED:
124  return "CKR_SESSION_CLOSED";
125  case CKR_SESSION_COUNT:
126  return "CKR_SESSION_COUNT";
128  return "CKR_SESSION_HANDLE_INVALID";
130  return "CKR_SESSION_PARALLEL_NOT_SUPPORTED";
132  return "CKR_SESSION_READ_ONLY";
133  case CKR_SESSION_EXISTS:
134  return "CKR_SESSION_EXISTS";
136  return "CKR_SIGNATURE_INVALID";
138  return "CKR_SIGNATURE_LEN_RANGE";
140  return "CKR_TEMPLATE_INCOMPLETE";
142  return "CKR_TEMPLATE_INCONSISTENT";
144  return "CKR_TOKEN_NOT_PRESENT";
146  return "CKR_TOKEN_NOT_RECOGNIZED";
148  return "CKR_TOKEN_WRITE_PROTECTED";
150  return "CKR_UNWRAPPING_KEY_HANDLE_INVALID";
152  return "CKR_UNWRAPPING_KEY_SIZE_RANGE";
154  return "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT";
156  return "CKR_USER_ALREADY_LOGGED_IN";
158  return "CKR_USER_NOT_LOGGED_IN";
160  return "CKR_USER_PIN_NOT_INITIALIZED";
162  return "CKR_USER_TYPE_INVALID";
164  return "CKR_WRAPPED_KEY_INVALID";
166  return "CKR_WRAPPED_KEY_LEN_RANGE";
168  return "CKR_WRAPPING_KEY_HANDLE_INVALID";
170  return "CKR_WRAPPING_KEY_SIZE_RANGE";
172  return "CKR_WRAPPING_KEY_TYPE_INCONSISTENT";
174  return "CKR_RANDOM_SEED_NOT_SUPPORTED";
175  case CKR_VENDOR_DEFINED:
176  return "CKR_VENDOR_DEFINED";
178  return "CKR_BUFFER_TOO_SMALL";
180  return "CKR_SAVED_STATE_INVALID";
182  return "CKR_INFORMATION_SENSITIVE";
184  return "CKR_STATE_UNSAVEABLE";
186  return "CKR_CRYPTOKI_NOT_INITIALIZED";
188  return "CKR_CRYPTOKI_ALREADY_INITIALIZED";
189  case CKR_MUTEX_BAD:
190  return "CKR_MUTEX_BAD";
192  return "CKR_MUTEX_NOT_LOCKED";
193  default:
194  return "Unknown error";
195  }
196 }
197 
209 static void
210 hsm_ctx_set_error(hsm_ctx_t *ctx, int error, const char *action,
211  const char *message, ...)
212 {
213  va_list args;
214 
215  if (ctx && ctx->error == 0) {
216  ctx->error = error;
217  ctx->error_action = action;
218 
219  va_start(args, message);
220  vsnprintf(ctx->error_message, sizeof(ctx->error_message),
221  message, args);
222  va_end(args);
223  }
224 }
225 
237 static int
238 hsm_pkcs11_check_error(hsm_ctx_t *ctx, CK_RV rv, const char *action)
239 {
240  if (rv != CKR_OK) {
241  if (ctx && ctx->error == 0) {
242  ctx->error = (int) rv;
243  ctx->error_action = action;
244  strlcpy(ctx->error_message, ldns_pkcs11_rv_str(rv), sizeof(ctx->error_message));
245  }
246  return 1;
247  }
248  return 0;
249 }
250 
252 static void
253 hsm_pkcs11_unload_functions(void *handle)
254 {
255  int result;
256  if (handle) {
257 #if defined(HAVE_LOADLIBRARY)
258  /* no idea */
259 #elif defined(HAVE_DLOPEN)
260  result = dlclose(handle);
261 #endif
262  }
263 }
264 
266 static CK_RV
267 hsm_pkcs11_load_functions(hsm_module_t *module)
268 {
269  CK_C_GetFunctionList pGetFunctionList = NULL;
270 
271  if (module && module->path) {
272  /* library provided by application or user */
273 
274 #if defined(HAVE_LOADLIBRARY)
275  /* Load PKCS #11 library */
276  HINSTANCE hDLL = LoadLibrary(_T(module->path));
277 
278  if (hDLL == NULL) {
279  /* Failed to load the PKCS #11 library */
280  return CKR_FUNCTION_FAILED;
281  }
282 
283  /* Retrieve the entry point for C_GetFunctionList */
284  pGetFunctionList = (CK_C_GetFunctionList)
285  GetProcAddress(hDLL, _T("C_GetFunctionList"));
286 
287 #elif defined(HAVE_DLOPEN)
288  /* Load PKCS #11 library */
289  void* pDynLib = dlopen(module->path, RTLD_NOW | RTLD_LOCAL);
290 
291  if (pDynLib == NULL) {
292  /* Failed to load the PKCS #11 library */
293  return CKR_FUNCTION_FAILED;
294  }
295 
296  /* Retrieve the entry point for C_GetFunctionList */
297  pGetFunctionList = (CK_C_GetFunctionList) dlsym(pDynLib, "C_GetFunctionList");
298  /* Store the handle so we can dlclose it later */
299  module->handle = pDynLib;
300 
301 #else
302  return CKR_FUNCTION_FAILED;
303 #endif
304  } else {
305  /* No library provided, use the statically compiled softHSM */
306 #ifdef HAVE_PKCS11_MODULE
307  return C_GetFunctionList(pkcs11_functions);
308 #else
309  return CKR_FUNCTION_FAILED;
310 #endif
311  }
312 
313  if (pGetFunctionList == NULL) {
314  /* Failed to load the PKCS #11 library */
315  return CKR_FUNCTION_FAILED;
316  }
317 
318  /* Retrieve the function list */
319  (pGetFunctionList)((CK_FUNCTION_LIST_PTR)(&module->sym));
320  return CKR_OK;
321 }
322 
323 static void
324 hsm_remove_leading_zeroes(CK_BYTE_PTR data, CK_ULONG *len)
325 {
326  CK_BYTE_PTR p = data;
327  CK_ULONG l;
328 
329  if (data == NULL || len == NULL) return;
330 
331  l = *len;
332 
333  while ((unsigned short int)(*p) == 0 && l > 1) {
334  p++;
335  l--;
336  }
337 
338  if (p != data) {
339  memmove(data, p, l);
340  *len = l;
341  }
342 }
343 
344 static int
345 hsm_pkcs11_check_token_name(hsm_ctx_t *ctx,
346  CK_FUNCTION_LIST_PTR pkcs11_functions,
347  CK_SLOT_ID slotId,
348  const char *token_name)
349 {
350  /* token label is always 32 bytes */
351  char token_name_bytes[HSM_TOKEN_LABEL_LENGTH];
352  int result = 0;
353  CK_RV rv;
354  CK_TOKEN_INFO token_info;
355 
356  rv = pkcs11_functions->C_GetTokenInfo(slotId, &token_info);
357  if (hsm_pkcs11_check_error(ctx, rv, "C_GetTokenInfo")) {
358  return 0;
359  }
360 
361  memset(token_name_bytes, ' ', HSM_TOKEN_LABEL_LENGTH);
362  if (strlen(token_name) < HSM_TOKEN_LABEL_LENGTH) {
363  memcpy(token_name_bytes, token_name, strlen(token_name));
364  } else {
365  memcpy(token_name_bytes, token_name, HSM_TOKEN_LABEL_LENGTH);
366  }
367 
368  result = memcmp(token_info.label,
369  token_name_bytes,
371 
372  return result;
373 }
374 
375 
376 int
378  CK_FUNCTION_LIST_PTR pkcs11_functions,
379  const char *token_name, CK_SLOT_ID *slotId)
380 {
381  CK_RV rv;
382  CK_ULONG slotCount;
383  CK_SLOT_ID cur_slot;
384  CK_SLOT_ID *slotIds;
385  int found = 0;
386 
387  if (token_name == NULL || slotId == NULL) return HSM_ERROR;
388 
389  rv = pkcs11_functions->C_GetSlotList(CK_TRUE, NULL_PTR, &slotCount);
390  if (hsm_pkcs11_check_error(ctx, rv, "get slot list")) {
391  return HSM_ERROR;
392  }
393 
394  if (slotCount < 1) {
395  hsm_ctx_set_error(ctx, HSM_ERROR, "hsm_get_slot_id()",
396  "No slots found in HSM");
397  return HSM_ERROR;
398  }
399 
400  slotIds = malloc(sizeof(CK_SLOT_ID) * slotCount);
401  rv = pkcs11_functions->C_GetSlotList(CK_TRUE, slotIds, &slotCount);
402  if (hsm_pkcs11_check_error(ctx, rv, "get slot list")) {
403  return HSM_ERROR;
404  }
405 
406  for (cur_slot = 0; cur_slot < slotCount; cur_slot++) {
407  if (hsm_pkcs11_check_token_name(ctx,
408  pkcs11_functions,
409  slotIds[cur_slot],
410  token_name)) {
411  *slotId = slotIds[cur_slot];
412  found = 1;
413  break;
414  }
415  }
416  free(slotIds);
417  if (!found) {
418  hsm_ctx_set_error(ctx, -1, "hsm_get_slot_id()",
419  "could not find token with the name %s", token_name);
420  return HSM_ERROR;
421  }
422 
423  return HSM_OK;
424 }
425 
426 /* internal functions */
427 static hsm_module_t *
428 hsm_module_new(const char *repository,
429  const char *token_label,
430  const char *path,
431  const hsm_config_t *config)
432 {
433  hsm_module_t *module;
434 
435  if (!repository || !path) return NULL;
436 
437 
438  module = malloc(sizeof(hsm_module_t));
439  if (!module) return NULL;
440 
441  if (config) {
442  module->config = malloc(sizeof(hsm_config_t));
443  if (!module->config) {
444  free(module);
445  return NULL;
446  }
447  memcpy(module->config, config, sizeof(hsm_config_t));
448  } else {
449  module->config = NULL;
450  }
451 
452  module->id = 0; /*TODO i think we can remove this*/
453  module->name = strdup(repository);
454  module->token_label = strdup(token_label);
455  module->path = strdup(path);
456  module->handle = NULL;
457  module->sym = NULL;
458 
459  return module;
460 }
461 
462 static void
463 hsm_module_free(hsm_module_t *module)
464 {
465  if (module) {
466  if (module->name) free(module->name);
467  if (module->token_label) free(module->token_label);
468  if (module->path) free(module->path);
469  if (module->config) free(module->config);
470 
471  free(module);
472  }
473 }
474 
475 static hsm_session_t *
476 hsm_session_new(hsm_module_t *module, CK_SESSION_HANDLE session_handle)
477 {
478  hsm_session_t *session;
479  session = malloc(sizeof(hsm_session_t));
480  session->module = module;
481  session->session = session_handle;
482  return session;
483 }
484 
485 static void
486 hsm_session_free(hsm_session_t *session) {
487  if (session) {
488  free(session);
489  }
490 }
491 
493 static void
494 hsm_config_default(hsm_config_t *config)
495 {
496  config->use_pubkey = 1;
497 }
498 
499 /* creates a session_t structure, and automatically adds and initializes
500  * a module_t struct for it
501  */
502 static int
503 hsm_session_init(hsm_ctx_t *ctx, hsm_session_t **session,
504  const char *repository, const char *token_label,
505  const char *module_path, const char *pin,
506  const hsm_config_t *config)
507 {
508  CK_RV rv;
509  CK_RV rv_login;
510  hsm_module_t *module;
511  CK_SLOT_ID slot_id;
512  CK_SESSION_HANDLE session_handle;
513  int first = 1, result;
514 
515  CK_C_INITIALIZE_ARGS InitArgs = {NULL, NULL, NULL, NULL,
516  CKF_OS_LOCKING_OK, NULL };
517 
518  module = hsm_module_new(repository, token_label, module_path, config);
519  if (!module) return HSM_ERROR;
520  rv = hsm_pkcs11_load_functions(module);
521  if (rv != CKR_OK) {
522  hsm_ctx_set_error(ctx, HSM_MODULE_NOT_FOUND,
523  "hsm_session_init()",
524  "PKCS#11 module load failed: %s", module_path);
525  hsm_module_free(module);
526  return HSM_MODULE_NOT_FOUND;
527  }
528  rv = ((CK_FUNCTION_LIST_PTR) module->sym)->C_Initialize((CK_VOID_PTR) &InitArgs);
529  /* ALREADY_INITIALIZED is ok, apparently we are using a second
530  * device with the same library */
532  if (hsm_pkcs11_check_error(ctx, rv, "Initialization")) {
533  hsm_module_free(module);
534  return HSM_ERROR;
535  }
536  } else {
537  first = 0;
538  }
539  result = hsm_get_slot_id(ctx, module->sym, token_label, &slot_id);
540  if (result != HSM_OK) {
541  hsm_module_free(module);
542  return HSM_ERROR;
543  }
544  rv = ((CK_FUNCTION_LIST_PTR) module->sym)->C_OpenSession(slot_id,
546  NULL,
547  NULL,
548  &session_handle);
549  if (hsm_pkcs11_check_error(ctx, rv, "Open first session")) {
550  hsm_module_free(module);
551  return HSM_ERROR;
552  }
553  rv_login = ((CK_FUNCTION_LIST_PTR) module->sym)->C_Login(session_handle,
554  CKU_USER,
555  (unsigned char *) pin,
556  strlen((char *)pin));
557 
558  if (rv_login == CKR_OK) {
559  *session = hsm_session_new(module, session_handle);
560  return HSM_OK;
561  } else {
562  /* uninitialize the session again */
563  if (session_handle) {
564  rv = ((CK_FUNCTION_LIST_PTR) module->sym)->
565  C_CloseSession(session_handle);
566  if (hsm_pkcs11_check_error(ctx, rv,
567  "finalize after failed login")) {
568  hsm_module_free(module);
569  return HSM_ERROR;
570  }
571  }
572  /* if this was not the first, don't close the library for
573  * the rest of us */
574  if (first) {
575  rv = ((CK_FUNCTION_LIST_PTR) module->sym)->C_Finalize(NULL);
576  if (hsm_pkcs11_check_error(ctx, rv, "finalize after failed login")) {
577  hsm_module_free(module);
578  return HSM_ERROR;
579  }
580  }
581  hsm_module_free(module);
582  *session = NULL;
583  switch(rv_login) {
584  case CKR_PIN_INCORRECT:
585  hsm_ctx_set_error(ctx, HSM_PIN_INCORRECT,
586  "hsm_session_init()",
587  "Incorrect PIN for repository %s", repository);
588  return HSM_PIN_INCORRECT;
589  default:
590  return HSM_ERROR;
591  }
592  }
593 }
594 
595 /* open a second session from the given one */
596 static hsm_session_t *
597 hsm_session_clone(hsm_ctx_t *ctx, hsm_session_t *session)
598 {
599  CK_RV rv;
600  CK_SLOT_ID slot_id;
601  CK_SESSION_HANDLE session_handle;
602  hsm_session_t *new_session;
603  int result;
604 
605  result = hsm_get_slot_id(ctx,
606  session->module->sym,
607  session->module->token_label,
608  &slot_id);
609  if (result != HSM_OK) return NULL;
610  rv = ((CK_FUNCTION_LIST_PTR) session->module->sym)->C_OpenSession(slot_id,
612  NULL,
613  NULL,
614  &session_handle);
615 
616  if (hsm_pkcs11_check_error(ctx, rv, "Clone session")) {
617  return NULL;
618  }
619  new_session = hsm_session_new(session->module, session_handle);
620 
621  return new_session;
622 }
623 
624 static hsm_ctx_t *
625 hsm_ctx_new()
626 {
627  hsm_ctx_t *ctx;
628  ctx = malloc(sizeof(hsm_ctx_t));
629  memset(ctx->session, 0, HSM_MAX_SESSIONS);
630  ctx->session_count = 0;
631  ctx->error = 0;
632  return ctx;
633 }
634 
635 /* ctx_free frees the structure */
636 static void
637 hsm_ctx_free(hsm_ctx_t *ctx)
638 {
639  unsigned int i;
640  if (ctx) {
641  for (i = 0; i < ctx->session_count; i++) {
642  hsm_session_free(ctx->session[i]);
643  }
644  free(ctx);
645  }
646 }
647 
648 /* close the session, and free the allocated data
649  *
650  * if unload is non-zero, C_Logout() is called,
651  * the dlopen()d module is closed and unloaded
652  * (only call this on the last session for each
653  * module, ie. the one in the global ctx)
654  */
655 static void
656 hsm_session_close(hsm_ctx_t *ctx, hsm_session_t *session, int unload)
657 {
658  /* If we loaded this library more than once, we may have
659  * already finalized it before, so we can safely ignore
660  * NOT_INITIALIZED */
661  CK_RV rv;
662  if (unload) {
663  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Logout(session->session);
664  if (rv != CKR_CRYPTOKI_NOT_INITIALIZED) {
665  (void) hsm_pkcs11_check_error(ctx, rv, "Logout");
666  }
667  }
668  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_CloseSession(session->session);
669  if (rv != CKR_CRYPTOKI_NOT_INITIALIZED) {
670  (void) hsm_pkcs11_check_error(ctx, rv, "Close session");
671  }
672  if (unload) {
673  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Finalize(NULL);
674  if (rv != CKR_CRYPTOKI_NOT_INITIALIZED) {
675  (void) hsm_pkcs11_check_error(ctx, rv, "Finalize");
676  hsm_pkcs11_unload_functions(session->module->handle);
677  }
678  hsm_module_free(session->module);
679  session->module = NULL;
680  }
681  hsm_session_free(session);
682 }
683 
684 /* ctx_close closes all session, and free
685  * the structures.
686  *
687  * if unload is non-zero, the associated dynamic libraries are unloaded
688  * (hence only use that on the last, global, ctx)
689  */
690 static void
691 hsm_ctx_close(hsm_ctx_t *ctx, int unload)
692 {
693  unsigned int i;
694 
695  if (ctx) {
696  for (i = 0; i < ctx->session_count; i++) {
697  /* todo syslog? */
698  /*printf("close session %u (unload: %d)\n", i, unload);*/
699  /*hsm_print_ctx(ctx);*/
700  hsm_session_close(ctx, ctx->session[i], unload);
701  ctx->session[i] = NULL;
702  /* if this was the last session in the array, decrease
703  * the session counter of the context */
704  if (i == _hsm_ctx->session_count) {
705  while(ctx->session_count > 0 && !ctx->session[i]) {
706  ctx->session_count--;
707  }
708  }
709  }
710  free(ctx);
711  }
712 }
713 
714 
715 /* adds a session to the context.
716  * returns 0 on success
717  * 1 if the maximum number of sessions (HSM_MAX_SESSIONS) was
718  * reached
719  * -1 if one of the arguments is NULL
720  */
721 static int
722 hsm_ctx_add_session(hsm_ctx_t *ctx, hsm_session_t *session)
723 {
724  if (!ctx || !session) return -1;
725  if (ctx->session_count >= HSM_MAX_SESSIONS) return 1;
726  ctx->session[ctx->session_count] = session;
727  ctx->session_count++;
728  return 0;
729 }
730 
731 static hsm_ctx_t *
732 hsm_ctx_clone(hsm_ctx_t *ctx)
733 {
734  unsigned int i;
735  hsm_ctx_t *new_ctx;
736  hsm_session_t *new_session;
737 
738  new_ctx = NULL;
739  if (ctx) {
740  new_ctx = hsm_ctx_new();
741  for (i = 0; i < ctx->session_count; i++) {
742  new_session = hsm_session_clone(ctx, ctx->session[i]);
743  if (!new_session) {
744  /* one of the sessions failed to clone. Clear the
745  * new ctx and return NULL */
746  hsm_ctx_close(new_ctx, 0);
747  return NULL;
748  }
749  hsm_ctx_add_session(new_ctx, new_session);
750  }
751  }
752  return new_ctx;
753 }
754 
755 static hsm_key_t *
756 hsm_key_new()
757 {
758  hsm_key_t *key;
759  key = malloc(sizeof(hsm_key_t));
760  key->module = NULL;
761  key->private_key = 0;
762  key->public_key = 0;
763  return key;
764 }
765 
766 /* find the session belonging to a key, by iterating over the modules
767  * in the context */
768 static hsm_session_t *
769 hsm_find_key_session(hsm_ctx_t *ctx, const hsm_key_t *key)
770 {
771  unsigned int i;
772  if (!key || !key->module) return NULL;
773  if (!ctx) ctx = _hsm_ctx;
774  for (i = 0; i < ctx->session_count; i++) {
775  if (ctx->session[i] && ctx->session[i]->module == key->module) {
776  return ctx->session[i];
777  }
778  }
779  return NULL;
780 }
781 
782 /* Returns the key type (algorithm) of the given key */
783 static CK_KEY_TYPE
784 hsm_get_key_algorithm(hsm_ctx_t *ctx, const hsm_session_t *session,
785  const hsm_key_t *key)
786 {
787  CK_RV rv;
788  CK_KEY_TYPE key_type;
789 
790  CK_ATTRIBUTE template[] = {
791  {CKA_KEY_TYPE, &key_type, sizeof(CK_KEY_TYPE)}
792  };
793 
794  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
795  session->session,
796  key->private_key,
797  template,
798  1);
799  if (hsm_pkcs11_check_error(ctx, rv,
800  "Get attr value algorithm type")) {
801  /* this is actually not a good return value;
802  * CKK_RSA is also 0. But we can't return a negative
803  * value. Should we #define a specific 'key type' that
804  * indicates an error? (TODO) */
805  return 0;
806  }
807 
808  if ((CK_LONG)template[0].ulValueLen < 1) {
809  /* this is actually not a good return value;
810  * CKK_RSA is also 0. But we can't return a negative
811  * value. Should we #define a specific 'key type' that
812  * indicates an error? (TODO) */
813  return 0;
814  }
815 
816  return key_type;
817 }
818 
819 /* returns a CK_ULONG with the key size of the given RSA key. The
820  * key is not checked for type. For RSA, the number of bits in the
821  * modulus is the key size (CKA_MODULUS_BITS)
822  */
823 static CK_ULONG
824 hsm_get_key_size_rsa(hsm_ctx_t *ctx, const hsm_session_t *session,
825  const hsm_key_t *key)
826 {
827  CK_RV rv;
828  CK_ULONG modulus_bits;
829 
830  /* Template for public keys */
831  CK_ATTRIBUTE template[] = {
832  {CKA_MODULUS_BITS, &modulus_bits, sizeof(CK_KEY_TYPE)}
833  };
834 
835  /* Template for private keys */
836  CK_BYTE_PTR modulus = NULL;
837  int mask;
838  CK_ATTRIBUTE template2[] = {
839  {CKA_MODULUS, NULL, 0}
840  };
841 
842  if (session->module->config->use_pubkey) {
843  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
844  session->session,
845  key->public_key,
846  template,
847  1);
848  if (hsm_pkcs11_check_error(ctx, rv,
849  "Get attr value algorithm type")) {
850  return 0;
851  }
852 
853  if ((CK_ULONG)template[0].ulValueLen < 1) {
854  return 0;
855  }
856  } else {
857  // Get buffer size
858  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
859  session->session,
860  key->private_key,
861  template2,
862  1);
863  if (hsm_pkcs11_check_error(ctx, rv, "Could not get the size of the modulus of the private key")) {
864  return 0;
865  }
866 
867  // Allocate memory
868  modulus = (CK_BYTE_PTR)malloc(template2[0].ulValueLen);
869  template2[0].pValue = modulus;
870  if (modulus == NULL) {
871  hsm_ctx_set_error(ctx, -1, "hsm_get_key_size_rsa()",
872  "Error allocating memory for modulus");
873  return 0;
874  }
875 
876  // Get attribute
877  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
878  session->session,
879  key->private_key,
880  template2,
881  1);
882  if (hsm_pkcs11_check_error(ctx, rv, "Could not get the modulus of the private key")) {
883  free(modulus);
884  return 0;
885  }
886 
887  // Calculate size
888  modulus_bits = template2[0].ulValueLen * 8;
889  mask = 0x80;
890  for (int i = 0; modulus_bits && (modulus[i] & mask) == 0; modulus_bits--) {
891  mask >>= 1;
892  if (mask == 0) {
893  i++;
894  mask = 0x80;
895  }
896  }
897  free(modulus);
898  }
899 
900  return modulus_bits;
901 }
902 
903 /* Wrapper for specific key size functions, currently only supports
904  * CKK_RSA (the value 0) as algorithm identifier */
905 static CK_ULONG
906 hsm_get_key_size(hsm_ctx_t *ctx, const hsm_session_t *session,
907  const hsm_key_t *key, const unsigned long algorithm)
908 {
909  switch (algorithm) {
910  case CKK_RSA:
911  return hsm_get_key_size_rsa(ctx, session, key);
912  break;
913  default:
914  return 0;
915  }
916 }
917 
918 static CK_OBJECT_HANDLE
919 hsm_find_object_handle_for_id(hsm_ctx_t *ctx,
920  const hsm_session_t *session,
921  CK_OBJECT_CLASS key_class,
922  CK_BYTE *id,
923  CK_ULONG id_len)
924 {
925  CK_ULONG objectCount;
926  CK_OBJECT_HANDLE object;
927  CK_RV rv;
928 
929  CK_ATTRIBUTE template[] = {
930  { CKA_CLASS, &key_class, sizeof(key_class) },
931  { CKA_ID, id, id_len },
932  };
933 
934  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjectsInit(session->session,
935  template, 2);
936  if (hsm_pkcs11_check_error(ctx, rv, "Find objects init")) {
937  return 0;
938  }
939 
940  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjects(session->session,
941  &object,
942  1,
943  &objectCount);
944  if (hsm_pkcs11_check_error(ctx, rv, "Find object")) {
945  return 0;
946  }
947 
948  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjectsFinal(session->session);
949  if (hsm_pkcs11_check_error(ctx, rv, "Find object final")) {
950  return 0;
951  }
952 
953  if (objectCount > 0) {
954  return object;
955  } else {
956  return 0;
957  }
958 }
959 
960 /*
961  * Parses the null-terminated string hex as hex values,
962  * Returns allocated data that needs to be freed (or NULL on error)
963  * len will contain the number of bytes allocated, or 0 on error
964  */
965 static unsigned char *
966 hsm_hex_parse(const char *hex, size_t *len)
967 {
968  unsigned char *bytes;
969  /* length of the hex input */
970  size_t hex_len;
971  size_t i;
972 
973  if (!len) return NULL;
974  *len = 0;
975 
976  if (!hex) return NULL;
977  hex_len = strlen(hex);
978  if (hex_len % 2 != 0) {
979  return NULL;
980  }
981 
982  *len = hex_len / 2;
983  bytes = malloc(*len);
984  for (i = 0; i < *len; i++) {
985  bytes[i] = ldns_hexdigit_to_int(hex[2*i]) * 16 +
986  ldns_hexdigit_to_int(hex[2*i+1]);
987  }
988  return bytes;
989 }
990 
991 /* put a hexadecimal representation of the data from src into dst
992  * len is the number of bytes to read from src
993  * dst must have allocated enough space (len*2 + 1)
994  */
995 static void
996 hsm_hex_unparse(char *dst, const unsigned char *src, size_t len)
997 {
998  size_t dst_len = len*2 + 1;
999  size_t i;
1000 
1001  for (i = 0; i < len; i++) {
1002  snprintf(dst + (2*i), dst_len, "%02x", src[i]);
1003  }
1004  dst[len*2] = '\0';
1005 }
1006 
1007 /* returns an allocated byte array with the CKA_ID for the given object
1008  * len will contain the result size
1009  * returns NULL and size zero if not found in this session
1010  */
1011 static CK_BYTE *
1012 hsm_get_id_for_object(hsm_ctx_t *ctx,
1013  const hsm_session_t *session,
1014  CK_OBJECT_HANDLE object,
1015  size_t *len)
1016 {
1017  CK_RV rv;
1018  CK_BYTE *id = NULL;
1019 
1020  CK_ATTRIBUTE template[] = {
1021  {CKA_ID, id, 0}
1022  };
1023 
1024  /* find out the size of the id first */
1025  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1026  session->session,
1027  object,
1028  template,
1029  1);
1030  if (hsm_pkcs11_check_error(ctx, rv, "Get attr value")) {
1031  *len = 0;
1032  return NULL;
1033  }
1034 
1035  if ((CK_LONG)template[0].ulValueLen < 1) {
1036  /* No CKA_ID found, return NULL */
1037  *len = 0;
1038  return NULL;
1039  }
1040 
1041  template[0].pValue = malloc(template[0].ulValueLen);
1042  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1043  session->session,
1044  object,
1045  template,
1046  1);
1047  if (hsm_pkcs11_check_error(ctx, rv, "Get attr value 2")) {
1048  *len = 0;
1049  free(template[0].pValue);
1050  return NULL;
1051  }
1052 
1053  *len = template[0].ulValueLen;
1054  return template[0].pValue;
1055 }
1056 
1057 /* returns an hsm_key_t object for the given *private key* object handle
1058  * the module, private key, and public key handle are set
1059  * The session needs to be free to perform a search for the public key
1060  */
1061 static hsm_key_t *
1062 hsm_key_new_privkey_object_handle(hsm_ctx_t *ctx,
1063  const hsm_session_t *session,
1064  CK_OBJECT_HANDLE object)
1065 {
1066  hsm_key_t *key;
1067  CK_BYTE *id;
1068  size_t len;
1069 
1070  id = hsm_get_id_for_object(ctx, session, object, &len);
1071 
1072  if (!id) return NULL;
1073 
1074  key = hsm_key_new();
1075  key->module = session->module;
1076  key->private_key = object;
1077 
1078  if (session->module->config->use_pubkey) {
1079  key->public_key = hsm_find_object_handle_for_id(
1080  ctx,
1081  session,
1083  id,
1084  len);
1085  } else {
1086  key->public_key = 0;
1087  }
1088 
1089  free(id);
1090  return key;
1091 }
1092 
1093 /* helper function to find both key counts or the keys themselves
1094  * if the argument store is 0, results are not returned; the
1095  * function will only set the count and return NULL
1096  * Otherwise, a newly allocated key array will be returned
1097  * (on error, the count will also be zero and NULL returned)
1098  */
1099 static hsm_key_t **
1100 hsm_list_keys_session_internal(hsm_ctx_t *ctx,
1101  const hsm_session_t *session,
1102  size_t *count,
1103  int store)
1104 {
1105  hsm_key_t **keys = NULL;
1106  hsm_key_t *key;
1107  CK_RV rv;
1108  CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY;
1109  CK_ATTRIBUTE template[] = {
1110  { CKA_CLASS, &key_class, sizeof(key_class) },
1111  };
1112  CK_ULONG total_count = 0;
1113  CK_ULONG objectCount = 1;
1114  /* find 100 keys at a time (and loop until there are none left) */
1115  CK_ULONG max_object_count = 100;
1116  CK_ULONG i, j;
1117  CK_OBJECT_HANDLE object[max_object_count];
1118  CK_OBJECT_HANDLE *key_handles = NULL;
1119 
1120  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjectsInit(session->session,
1121  template, 1);
1122  if (hsm_pkcs11_check_error(ctx, rv, "Find objects init")) {
1123  *count = 0;
1124  return NULL;
1125  }
1126  j = 0;
1127  while (objectCount > 0) {
1128  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjects(session->session,
1129  object,
1130  max_object_count,
1131  &objectCount);
1132  if (hsm_pkcs11_check_error(ctx, rv, "Find first object")) {
1133  free(key_handles);
1134  *count = 0;
1135  return NULL;
1136  }
1137 
1138  total_count += objectCount;
1139  if (objectCount > 0 && store) {
1140  key_handles = realloc(key_handles, total_count * sizeof(CK_OBJECT_HANDLE));
1141  for (i = 0; i < objectCount; i++) {
1142  key_handles[j] = object[i];
1143  j++;
1144  }
1145  }
1146  }
1147 
1148  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjectsFinal(session->session);
1149  if (hsm_pkcs11_check_error(ctx, rv, "Find objects final")) {
1150  free(key_handles);
1151  *count = 0;
1152  return NULL;
1153  }
1154 
1155  if (store) {
1156  keys = realloc(keys, total_count * sizeof(hsm_key_t *));
1157  for (i = 0; i < total_count; i++) {
1158  key = hsm_key_new_privkey_object_handle(ctx, session,
1159  key_handles[i]);
1160  /* todo, if we get NULL, free all and return error? */
1161  keys[i] = key;
1162  }
1163  }
1164  free(key_handles);
1165 
1166  *count = total_count;
1167  return keys;
1168 }
1169 
1170 
1171 /* returns an array of all keys available to the given session
1172  *
1173  * \param session the session to find the keys in
1174  * \param count this value will contain the number of keys found
1175  *
1176  * \return the list of keys
1177  */
1178 hsm_key_t **
1180  size_t *count)
1181 {
1182  return hsm_list_keys_session_internal(ctx, session, count, 1);
1183 }
1184 
1185 /* returns a count all keys available to the given session
1186  *
1187  * \param session the session to find the keys in
1188  *
1189  * \return the number of keys
1190  */
1191 size_t
1193 {
1194  size_t count = 0;
1195  (void) hsm_list_keys_session_internal(ctx, session, &count, 0);
1196  return count;
1197 }
1198 
1199 /* returns a newly allocated key structure containing the key data
1200  * for the given CKA_ID available in the session. Returns NULL if not
1201  * found
1202  */
1203 static hsm_key_t *
1204 hsm_find_key_by_id_session(hsm_ctx_t *ctx, const hsm_session_t *session,
1205  const unsigned char *id, size_t len)
1206 {
1207  hsm_key_t *key;
1208  CK_OBJECT_HANDLE private_key_handle;
1209 
1210  private_key_handle = hsm_find_object_handle_for_id(
1211  ctx,
1212  session,
1214  (CK_BYTE *) id,
1215  (CK_ULONG) len);
1216  if (private_key_handle != 0) {
1217  key = hsm_key_new_privkey_object_handle(ctx, session,
1218  private_key_handle);
1219  return key;
1220  } else {
1221  return NULL;
1222  }
1223 }
1224 
1225 /* Find a key pair by CKA_ID (as byte array)
1226 
1227 The returned key structure can be freed with hsm_key_free()
1228 
1229 \param context HSM context
1230 \param id CKA_ID of key to find (array of bytes)
1231 \param len number of bytes in the id
1232 \return key identifier or NULL if not found
1233 */
1234 static hsm_key_t *
1235 hsm_find_key_by_id_bin(hsm_ctx_t *ctx,
1236  const unsigned char *id,
1237  size_t len)
1238 {
1239  hsm_key_t *key;
1240  unsigned int i;
1241 
1242  if (!ctx) ctx = _hsm_ctx;
1243  if (!id) return NULL;
1244 
1245  for (i = 0; i < ctx->session_count; i++) {
1246  key = hsm_find_key_by_id_session(ctx, ctx->session[i], id, len);
1247  if (key) return key;
1248  }
1249  return NULL;
1250 }
1251 
1252 
1258 static hsm_session_t *
1259 hsm_find_repository_session(hsm_ctx_t *ctx, const char *repository)
1260 {
1261  unsigned int i;
1262  if (!repository) {
1263  for (i = 0; i < ctx->session_count; i++) {
1264  if (ctx->session[i]) {
1265  return ctx->session[i];
1266  }
1267  }
1268  } else {
1269  for (i = 0; i < ctx->session_count; i++) {
1270  if (ctx->session[i] &&
1271  strcmp(repository, ctx->session[i]->module->name) == 0)
1272  {
1273  return ctx->session[i];
1274  }
1275  }
1276  }
1277 
1278  hsm_ctx_set_error(ctx, HSM_REPOSITORY_NOT_FOUND,
1279  "hsm_find_repository_session()",
1280  "Can't find repository: %s", repository);
1281 
1282  return NULL;
1283 }
1284 
1285 static ldns_rdf *
1286 hsm_get_key_rdata(hsm_ctx_t *ctx, hsm_session_t *session,
1287  const hsm_key_t *key)
1288 {
1289  CK_RV rv;
1290  CK_BYTE_PTR public_exponent = NULL;
1291  CK_ULONG public_exponent_len = 0;
1292  CK_BYTE_PTR modulus = NULL;
1293  CK_ULONG modulus_len = 0;
1294  unsigned long hKey = 0;
1295  unsigned char *data = NULL;
1296  size_t data_size = 0;
1297 
1298  CK_ATTRIBUTE template[] = {
1299  {CKA_PUBLIC_EXPONENT, NULL, 0},
1300  {CKA_MODULUS, NULL, 0},
1301  };
1302  ldns_rdf *rdf;
1303 
1304  if (!session || !session->module) {
1305  return NULL;
1306  }
1307 
1308  if (session->module->config->use_pubkey) {
1309  hKey = key->public_key;
1310  } else {
1311  hKey = key->private_key;
1312  }
1313 
1314  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1315  session->session,
1316  hKey,
1317  template,
1318  2);
1319  if (hsm_pkcs11_check_error(ctx, rv, "C_GetAttributeValue")) {
1320  return NULL;
1321  }
1322  public_exponent_len = template[0].ulValueLen;
1323  modulus_len = template[1].ulValueLen;
1324 
1325  public_exponent = template[0].pValue = malloc(public_exponent_len);
1326  if (!public_exponent) {
1327  hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata()",
1328  "Error allocating memory for public exponent");
1329  return NULL;
1330  }
1331 
1332  modulus = template[1].pValue = malloc(modulus_len);
1333  if (!modulus) {
1334  hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata()",
1335  "Error allocating memory for modulus");
1336  free(public_exponent);
1337  return NULL;
1338  }
1339 
1340  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1341  session->session,
1342  hKey,
1343  template,
1344  2);
1345  if (hsm_pkcs11_check_error(ctx, rv, "get attribute value")) {
1346  free(template[0].pValue);
1347  free(template[1].pValue);
1348  return NULL;
1349  }
1350 
1351  // Remove leading zeroes
1352  hsm_remove_leading_zeroes(public_exponent, &public_exponent_len);
1353  hsm_remove_leading_zeroes(modulus, &modulus_len);
1354 
1355  data_size = public_exponent_len + modulus_len + 1;
1356  if (public_exponent_len <= 256) {
1357  data = malloc(data_size);
1358  if (!data) {
1359  hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata()",
1360  "Error allocating memory for pub key rr data");
1361  free(public_exponent);
1362  free(modulus);
1363  return NULL;
1364  }
1365  data[0] = public_exponent_len;
1366  memcpy(&data[1], public_exponent, public_exponent_len);
1367  memcpy(&data[1 + public_exponent_len], modulus, modulus_len);
1368  } else if (public_exponent_len <= 65535) {
1369  data_size += 2;
1370  data = malloc(data_size);
1371  if (!data) {
1372  hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata()",
1373  "Error allocating memory for pub key rr data");
1374  free(public_exponent);
1375  free(modulus);
1376  return NULL;
1377  }
1378  data[0] = 0;
1379  ldns_write_uint16(&data[1], (uint16_t) public_exponent_len);
1380  memcpy(&data[3], public_exponent, public_exponent_len);
1381  memcpy(&data[3 + public_exponent_len], modulus, modulus_len);
1382  } else {
1383  hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata()",
1384  "Public exponent too big");
1385  free(public_exponent);
1386  free(modulus);
1387  return NULL;
1388  }
1389  rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, data_size, data);
1390  free(public_exponent);
1391  free(modulus);
1392 
1393  return rdf;
1394 }
1395 
1396 /* this function allocates memory for the mechanism ID and enough room
1397  * to leave the upcoming digest data. It fills in the mechanism id
1398  * use with care. The returned data must be free'd by the caller */
1399 static CK_BYTE *
1400 hsm_create_prefix(CK_ULONG digest_len,
1401  ldns_algorithm algorithm,
1402  CK_ULONG *data_size)
1403 {
1404  CK_BYTE *data;
1405  const CK_BYTE RSA_MD5_ID[] = { 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 };
1406  const CK_BYTE RSA_SHA1_ID[] = { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14 };
1407  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 };
1408  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 };
1409 
1410  switch(algorithm) {
1411  case LDNS_SIGN_RSAMD5:
1412  *data_size = sizeof(RSA_MD5_ID) + digest_len;
1413  data = malloc(*data_size);
1414  memcpy(data, RSA_MD5_ID, sizeof(RSA_MD5_ID));
1415  break;
1416  case LDNS_SIGN_RSASHA1:
1417  case LDNS_SIGN_RSASHA1_NSEC3:
1418  *data_size = sizeof(RSA_SHA1_ID) + digest_len;
1419  data = malloc(*data_size);
1420  memcpy(data, RSA_SHA1_ID, sizeof(RSA_SHA1_ID));
1421  break;
1422  case LDNS_SIGN_RSASHA256:
1423  *data_size = sizeof(RSA_SHA256_ID) + digest_len;
1424  data = malloc(*data_size);
1425  memcpy(data, RSA_SHA256_ID, sizeof(RSA_SHA256_ID));
1426  break;
1427  case LDNS_SIGN_RSASHA512:
1428  *data_size = sizeof(RSA_SHA512_ID) + digest_len;
1429  data = malloc(*data_size);
1430  memcpy(data, RSA_SHA512_ID, sizeof(RSA_SHA512_ID));
1431  break;
1432  default:
1433  return NULL;
1434  }
1435  return data;
1436 }
1437 
1438 static CK_BYTE *
1439 hsm_digest_through_hsm(hsm_ctx_t *ctx,
1440  hsm_session_t *session,
1441  CK_MECHANISM_TYPE mechanism_type,
1442  CK_ULONG digest_len,
1443  ldns_buffer *sign_buf)
1444 {
1445  CK_MECHANISM digest_mechanism;
1446  CK_BYTE *digest;
1447  CK_RV rv;
1448 
1449  digest_mechanism.pParameter = NULL;
1450  digest_mechanism.ulParameterLen = 0;
1451  digest_mechanism.mechanism = mechanism_type;
1452  digest = malloc(digest_len);
1453  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DigestInit(session->session,
1454  &digest_mechanism);
1455  if (hsm_pkcs11_check_error(ctx, rv, "HSM digest init")) {
1456  free(digest);
1457  return NULL;
1458  }
1459 
1460  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Digest(session->session,
1461  ldns_buffer_begin(sign_buf),
1462  ldns_buffer_position(sign_buf),
1463  digest,
1464  &digest_len);
1465  if (hsm_pkcs11_check_error(ctx, rv, "HSM digest")) {
1466  free(digest);
1467  return NULL;
1468  }
1469  return digest;
1470 }
1471 
1472 static ldns_rdf *
1473 hsm_sign_buffer(hsm_ctx_t *ctx,
1474  ldns_buffer *sign_buf,
1475  const hsm_key_t *key,
1476  ldns_algorithm algorithm)
1477 {
1478  CK_RV rv;
1479  /* TODO: depends on type and key, or just leave it at current
1480  * maximum? */
1481  CK_ULONG signatureLen = 512;
1482  CK_BYTE *signature = NULL;
1483  CK_MECHANISM sign_mechanism;
1484 
1485  ldns_rdf *sig_rdf;
1486  CK_BYTE *digest = NULL;
1487  CK_ULONG digest_len;
1488 
1489  CK_BYTE *data = NULL;
1490  CK_ULONG data_len = 0;
1491 
1492  hsm_session_t *session;
1493 
1494  session = hsm_find_key_session(ctx, key);
1495  if (!session) return NULL;
1496 
1497  signature = malloc(signatureLen);
1498  if (signature == NULL) {
1499  return NULL;
1500  }
1501 
1502  /* some HSMs don't really handle CKM_SHA1_RSA_PKCS well, so
1503  * we'll do the hashing manually */
1504  /* When adding algorithms, remember there is another switch below */
1505  switch (algorithm) {
1506  case LDNS_SIGN_RSAMD5:
1507  digest_len = 16;
1508  digest = hsm_digest_through_hsm(ctx, session,
1509  CKM_MD5, digest_len,
1510  sign_buf);
1511  break;
1512 
1513  case LDNS_SIGN_RSASHA1:
1514  case LDNS_SIGN_RSASHA1_NSEC3:
1515  digest_len = LDNS_SHA1_DIGEST_LENGTH;
1516  digest = malloc(digest_len);
1517  digest = ldns_sha1(ldns_buffer_begin(sign_buf),
1518  ldns_buffer_position(sign_buf),
1519  digest);
1520  break;
1521 
1522  case LDNS_SIGN_RSASHA256:
1523  digest_len = LDNS_SHA256_DIGEST_LENGTH;
1524  digest = malloc(digest_len);
1525  digest = ldns_sha256(ldns_buffer_begin(sign_buf),
1526  ldns_buffer_position(sign_buf),
1527  digest);
1528  break;
1529 
1530  case LDNS_SIGN_RSASHA512:
1531  digest_len = LDNS_SHA512_DIGEST_LENGTH;
1532  digest = malloc(digest_len);
1533  digest = ldns_sha512(ldns_buffer_begin(sign_buf),
1534  ldns_buffer_position(sign_buf),
1535  digest);
1536  break;
1537 
1538  default:
1539  /* log error? or should we not even get here for
1540  * unsupported algorithms? */
1541  free(signature);
1542  return NULL;
1543  }
1544 
1545  if (!digest) {
1546  free(signature);
1547  return NULL;
1548  }
1549 
1550  /* CKM_RSA_PKCS does the padding, but cannot know the identifier
1551  * prefix, so we need to add that ourselves */
1552  data = hsm_create_prefix(digest_len, algorithm, &data_len);
1553  memcpy(data + data_len - digest_len, digest, digest_len);
1554 
1555  sign_mechanism.pParameter = NULL;
1556  sign_mechanism.ulParameterLen = 0;
1557  switch(algorithm) {
1558  case LDNS_SIGN_RSAMD5:
1559  case LDNS_SIGN_RSASHA1:
1560  case LDNS_SIGN_RSASHA1_NSEC3:
1561  case LDNS_SIGN_RSASHA256:
1562  case LDNS_SIGN_RSASHA512:
1563  sign_mechanism.mechanism = CKM_RSA_PKCS;
1564  break;
1565  default:
1566  /* log error? or should we not even get here for
1567  * unsupported algorithms? */
1568  free(data);
1569  free(digest);
1570  free(signature);
1571  return NULL;
1572  }
1573 
1574  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_SignInit(
1575  session->session,
1576  &sign_mechanism,
1577  key->private_key);
1578  if (hsm_pkcs11_check_error(ctx, rv, "sign init")) {
1579  free(data);
1580  free(digest);
1581  free(signature);
1582  return NULL;
1583  }
1584 
1585  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Sign(session->session, data, data_len,
1586  signature,
1587  &signatureLen);
1588  if (hsm_pkcs11_check_error(ctx, rv, "sign final")) {
1589  free(data);
1590  free(digest);
1591  free(signature);
1592  return NULL;
1593  }
1594 
1595  sig_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
1596  signatureLen,
1597  signature);
1598 
1599  free(data);
1600  free(digest);
1601  free(signature);
1602 
1603  return sig_rdf;
1604 
1605 }
1606 
1607 static int
1608 hsm_dname_is_wildcard(const ldns_rdf* dname)
1609 {
1610  return ( ldns_dname_label_count(dname) > 0 &&
1611  ldns_rdf_data(dname)[0] == 1 &&
1612  ldns_rdf_data(dname)[1] == '*');
1613 }
1614 
1615 static ldns_rr *
1616 hsm_create_empty_rrsig(const ldns_rr_list *rrset,
1617  const hsm_sign_params_t *sign_params)
1618 {
1619  ldns_rr *rrsig;
1620  uint32_t orig_ttl;
1621  uint32_t orig_class;
1622  time_t now;
1623  uint8_t label_count;
1624 
1625  label_count = ldns_dname_label_count(
1626  ldns_rr_owner(ldns_rr_list_rr(rrset, 0)));
1627  /* RFC 4035 section 2.2: dnssec label length and wildcards */
1628  if (hsm_dname_is_wildcard(ldns_rr_owner(ldns_rr_list_rr(rrset, 0)))) {
1629  label_count--;
1630  }
1631 
1632  rrsig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG);
1633 
1634  /* set the type on the new signature */
1635  orig_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrset, 0));
1636  orig_class = ldns_rr_get_class(ldns_rr_list_rr(rrset, 0));
1637 
1638  ldns_rr_set_class(rrsig, orig_class);
1639  ldns_rr_set_ttl(rrsig, orig_ttl);
1640  ldns_rr_set_owner(rrsig,
1641  ldns_rdf_clone(
1642  ldns_rr_owner(
1643  ldns_rr_list_rr(rrset,
1644  0))));
1645 
1646  /* fill in what we know of the signature */
1647 
1648  /* set the orig_ttl */
1649  (void)ldns_rr_rrsig_set_origttl(
1650  rrsig,
1651  ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
1652  orig_ttl));
1653  /* the signers name */
1654  (void)ldns_rr_rrsig_set_signame(
1655  rrsig,
1656  ldns_rdf_clone(sign_params->owner));
1657  /* label count - get it from the first rr in the rr_list */
1658  (void)ldns_rr_rrsig_set_labels(
1659  rrsig,
1660  ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
1661  label_count));
1662  /* inception, expiration */
1663  now = time(NULL);
1664  if (sign_params->inception != 0) {
1665  (void)ldns_rr_rrsig_set_inception(
1666  rrsig,
1667  ldns_native2rdf_int32(
1668  LDNS_RDF_TYPE_TIME,
1669  sign_params->inception));
1670  } else {
1671  (void)ldns_rr_rrsig_set_inception(
1672  rrsig,
1673  ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, now));
1674  }
1675  if (sign_params->expiration != 0) {
1676  (void)ldns_rr_rrsig_set_expiration(
1677  rrsig,
1678  ldns_native2rdf_int32(
1679  LDNS_RDF_TYPE_TIME,
1680  sign_params->expiration));
1681  } else {
1682  (void)ldns_rr_rrsig_set_expiration(
1683  rrsig,
1684  ldns_native2rdf_int32(
1685  LDNS_RDF_TYPE_TIME,
1686  now + LDNS_DEFAULT_EXP_TIME));
1687  }
1688 
1689  (void)ldns_rr_rrsig_set_keytag(
1690  rrsig,
1691  ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
1692  sign_params->keytag));
1693 
1694  (void)ldns_rr_rrsig_set_algorithm(
1695  rrsig,
1696  ldns_native2rdf_int8(
1697  LDNS_RDF_TYPE_ALG,
1698  sign_params->algorithm));
1699 
1700  (void)ldns_rr_rrsig_set_typecovered(
1701  rrsig,
1702  ldns_native2rdf_int16(
1703  LDNS_RDF_TYPE_TYPE,
1704  ldns_rr_get_type(ldns_rr_list_rr(rrset,
1705  0))));
1706 
1707  return rrsig;
1708 }
1709 
1710 
1711 /*
1712  * API functions
1713  */
1714 
1715 int
1716 hsm_open(const char *config,
1717  char *(pin_callback)(const char *repository, void *),
1718  void *data)
1719 {
1720  xmlDocPtr doc;
1721  xmlXPathContextPtr xpath_ctx;
1722  xmlXPathObjectPtr xpath_obj;
1723  xmlNode *curNode;
1724  xmlChar *xexpr;
1725 
1726  int i;
1727  char *config_file;
1728  char *repository;
1729  char *token_label;
1730  char *module_path;
1731  char *module_pin;
1732  hsm_config_t module_config;
1733  int result = HSM_OK;
1734  int tries;
1735  int repositories = 0;
1736 
1737  /* create an internal context with an attached session for each
1738  * configured HSM. */
1739  _hsm_ctx = hsm_ctx_new();
1740 
1741  if (config) {
1742  config_file = strdup(config);
1743  } else{
1744  config_file = strdup(HSM_DEFAULT_CONFIG);
1745  }
1746 
1747  /* Load XML document */
1748  doc = xmlParseFile(config_file);
1749  free(config_file);
1750  if (doc == NULL) {
1751  return HSM_CONFIG_FILE_ERROR;
1752  }
1753 
1754  /* Create xpath evaluation context */
1755  xpath_ctx = xmlXPathNewContext(doc);
1756  if(xpath_ctx == NULL) {
1757  xmlFreeDoc(doc);
1758  hsm_ctx_free(_hsm_ctx);
1759  _hsm_ctx = NULL;
1760  return -1;
1761  }
1762 
1763  /* Evaluate xpath expression */
1764  xexpr = (xmlChar *)"//Configuration/RepositoryList/Repository";
1765  xpath_obj = xmlXPathEvalExpression(xexpr, xpath_ctx);
1766  if(xpath_obj == NULL) {
1767  xmlXPathFreeContext(xpath_ctx);
1768  xmlFreeDoc(doc);
1769  hsm_ctx_free(_hsm_ctx);
1770  _hsm_ctx = NULL;
1771  return -1;
1772  }
1773 
1774  if (xpath_obj->nodesetval) {
1775  for (i = 0; i < xpath_obj->nodesetval->nodeNr; i++) {
1776  /*module = hsm_module_new();*/
1777  token_label = NULL;
1778  module_path = NULL;
1779  module_pin = NULL;
1780  hsm_config_default(&module_config);
1781 
1782  curNode = xpath_obj->nodesetval->nodeTab[i]->xmlChildrenNode;
1783  repository = (char *) xmlGetProp(xpath_obj->nodesetval->nodeTab[i],
1784  (const xmlChar *)"name");
1785 
1786  while (curNode) {
1787  if (xmlStrEqual(curNode->name, (const xmlChar *)"TokenLabel"))
1788  token_label = (char *) xmlNodeGetContent(curNode);
1789  if (xmlStrEqual(curNode->name, (const xmlChar *)"Module"))
1790  module_path = (char *) xmlNodeGetContent(curNode);
1791  if (xmlStrEqual(curNode->name, (const xmlChar *)"PIN"))
1792  module_pin = (char *) xmlNodeGetContent(curNode);
1793  if (xmlStrEqual(curNode->name, (const xmlChar *)"SkipPublicKey"))
1794  module_config.use_pubkey = 0;
1795  curNode = curNode->next;
1796  }
1797 
1798  if (repository && token_label && module_path) {
1799  if (module_pin) {
1800  result = hsm_attach(repository,
1801  token_label,
1802  module_path,
1803  module_pin,
1804  &module_config);
1805  free(module_pin);
1806  } else {
1807  if (pin_callback) {
1808  result = HSM_PIN_INCORRECT;
1809  tries = 0;
1810  while (result == HSM_PIN_INCORRECT &&
1811  tries < 3) {
1812  module_pin = pin_callback(repository,
1813  data);
1814  result = hsm_attach(repository,
1815  token_label,
1816  module_path,
1817  module_pin,
1818  &module_config);
1819  memset(module_pin, 0, strlen(module_pin));
1820  tries++;
1821  }
1822  } else {
1823  /* no pin, no callback, ignore
1824  * module and token */
1825  result = HSM_OK;
1826  }
1827  }
1828  free(repository);
1829  free(token_label);
1830  free(module_path);
1831 
1832  if (result != HSM_OK) {
1833  break;
1834  }
1835 
1836  repositories++;
1837  }
1838  }
1839  }
1840 
1841  xmlXPathFreeObject(xpath_obj);
1842  xmlXPathFreeContext(xpath_ctx);
1843  xmlFreeDoc(doc);
1844 
1845  if (result == HSM_OK && repositories == 0) {
1846  hsm_ctx_set_error(_hsm_ctx, HSM_NO_REPOSITORIES, "hsm_open()",
1847  "No repositories found");
1848  return HSM_NO_REPOSITORIES;
1849  }
1850 
1851  return result;
1852 }
1853 
1854 char *
1855 hsm_prompt_pin(const char *repository, void *data)
1856 {
1857  char *prompt;
1858  char *r;
1859  (void) data;
1860  prompt = malloc(64);
1861  snprintf(prompt, 64, "Enter PIN for token %s:", repository);
1862 #ifdef HAVE_GETPASSPHRASE
1863  r = getpassphrase("Enter PIN:");
1864 #else
1865  r = getpass("Enter PIN:");
1866 #endif
1867  free(prompt);
1868  return r;
1869 }
1870 
1871 int
1873 {
1874  hsm_ctx_close(_hsm_ctx, 1);
1875  return 0;
1876 }
1877 
1878 hsm_ctx_t *
1880 {
1881  return hsm_ctx_clone(_hsm_ctx);
1882 }
1883 
1884 int
1886 {
1887  unsigned int i;
1888  hsm_session_t *session;
1889  CK_SESSION_INFO info;
1890  CK_RV rv;
1891  CK_SESSION_HANDLE session_handle;
1892 
1893  if (ctx == NULL) {
1894  ctx = _hsm_ctx;
1895  }
1896 
1897  for (i = 0; i < ctx->session_count; i++) {
1898  session = ctx->session[i];
1899  if (session == NULL) continue;
1900 
1901  /* Get session info */
1902  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetSessionInfo(
1903  session->session,
1904  &info);
1905  if (hsm_pkcs11_check_error(ctx, rv, "get session info")) {
1906  return HSM_ERROR;
1907  }
1908 
1909  /* Check session info */
1910  if (info.state != CKS_RW_USER_FUNCTIONS) {
1911  hsm_ctx_set_error(ctx, HSM_ERROR, "hsm_check_context()",
1912  "Session not logged in");
1913  return HSM_ERROR;
1914  }
1915 
1916  /* Try open and close a session with the token */
1917  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_OpenSession(info.slotID,
1919  NULL,
1920  NULL,
1921  &session_handle);
1922  if (hsm_pkcs11_check_error(ctx, rv, "test open session")) {
1923  return HSM_ERROR;
1924  }
1925  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_CloseSession(session_handle);
1926  if (hsm_pkcs11_check_error(ctx, rv, "test close session")) {
1927  return HSM_ERROR;
1928  }
1929  }
1930 
1931  return HSM_OK;
1932 }
1933 
1934 void
1936 {
1937  hsm_ctx_close(ctx, 0);
1938 }
1939 
1945 {
1946  hsm_sign_params_t *params;
1947  params = malloc(sizeof(hsm_sign_params_t));
1948  if (!params) {
1949  return NULL;
1950  }
1951  params->algorithm = LDNS_SIGN_RSASHA1;
1952  params->flags = LDNS_KEY_ZONE_KEY;
1953  params->inception = 0;
1954  params->expiration = 0;
1955  params->keytag = 0;
1956  params->owner = NULL;
1957  return params;
1958 }
1959 
1960 void
1962 {
1963  if (params) {
1964  if (params->owner) ldns_rdf_deep_free(params->owner);
1965  free(params);
1966  }
1967 }
1968 
1969 hsm_key_t **
1970 hsm_list_keys(hsm_ctx_t *ctx, size_t *count)
1971 {
1972  hsm_key_t **keys = NULL;
1973  size_t key_count = 0;
1974  size_t cur_key_count;
1975  hsm_key_t **session_keys;
1976  unsigned int i, j;
1977 
1978  if (!ctx) {
1979  ctx = _hsm_ctx;
1980  }
1981 
1982  for (i = 0; i < ctx->session_count; i++) {
1983  session_keys = hsm_list_keys_session(ctx, ctx->session[i],
1984  &cur_key_count);
1985  keys = realloc(keys,
1986  (key_count + cur_key_count) * sizeof(hsm_key_t *));
1987  for (j = 0; j < cur_key_count; j++) {
1988  keys[key_count + j] = session_keys[j];
1989  }
1990  key_count += cur_key_count;
1991  free(session_keys);
1992  }
1993  if (count) {
1994  *count = key_count;
1995  }
1996  return keys;
1997 }
1998 
1999 hsm_key_t **
2001  size_t *count,
2002  const char *repository)
2003 {
2004  hsm_session_t *session;
2005 
2006  if (!repository) return NULL;
2007  if (!ctx) ctx = _hsm_ctx;
2008 
2009  session = hsm_find_repository_session(ctx, repository);
2010  if (!session) {
2011  *count = 0;
2012  return NULL;
2013  }
2014  return hsm_list_keys_session(ctx, session, count);
2015 }
2016 
2017 size_t
2019 {
2020  size_t count = 0;
2021  unsigned int i;
2022 
2023  if (!ctx) ctx = _hsm_ctx;
2024  for (i = 0; i < ctx->session_count; i++) {
2025  count += hsm_count_keys_session(ctx, ctx->session[i]);
2026  }
2027  return count;
2028 }
2029 
2030 size_t
2032  const char *repository)
2033 {
2034  hsm_session_t *session;
2035 
2036  if (!repository) return 0;
2037  if (!ctx) ctx = _hsm_ctx;
2038 
2039  session = hsm_find_repository_session(ctx, repository);
2040  if (!session) {
2041  return 0;
2042  }
2043  return hsm_count_keys_session(ctx, session);
2044 }
2045 
2046 hsm_key_t *
2047 hsm_find_key_by_id(hsm_ctx_t *ctx, const char *id)
2048 {
2049  unsigned char *id_bytes;
2050  size_t len;
2051  hsm_key_t *key;
2052 
2053  id_bytes = hsm_hex_parse(id, &len);
2054 
2055  if (!id_bytes) return NULL;
2056 
2057  key = hsm_find_key_by_id_bin(ctx, id_bytes, len);
2058  free(id_bytes);
2059  return key;
2060 }
2061 
2062 hsm_key_t *
2064  const char *repository,
2065  unsigned long keysize)
2066 {
2067  hsm_key_t *new_key;
2068  hsm_session_t *session;
2069  /* ids we create are 16 bytes of data */
2070  unsigned char id[16];
2071  /* that's 33 bytes in string (16*2 + 1 for \0) */
2072  char id_str[33];
2073  CK_RV rv;
2074  CK_OBJECT_HANDLE publicKey, privateKey;
2075  CK_KEY_TYPE keyType = CKK_RSA;
2076  CK_MECHANISM mechanism = {
2078  };
2079  CK_BYTE publicExponent[] = { 1, 0, 1 };
2080  CK_BBOOL ctrue = CK_TRUE;
2081  CK_BBOOL cfalse = CK_FALSE;
2082  CK_BBOOL ctoken = CK_TRUE;
2083 
2084  if (!ctx) ctx = _hsm_ctx;
2085  session = hsm_find_repository_session(ctx, repository);
2086  if (!session) return NULL;
2087 
2088  /* check whether this key doesn't happen to exist already */
2089  do {
2090  hsm_random_buffer(ctx, id, 16);
2091  } while (hsm_find_key_by_id_bin(ctx, id, 16));
2092  /* the CKA_LABEL will contain a hexadecimal string representation
2093  * of the id */
2094  hsm_hex_unparse(id_str, id, 16);
2095 
2096  if (! session->module->config->use_pubkey) {
2097  ctoken = CK_FALSE;
2098  }
2099 
2100  CK_ATTRIBUTE publicKeyTemplate[] = {
2101  { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen(id_str) },
2102  { CKA_ID, id, 16 },
2103  { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2104  { CKA_VERIFY, &ctrue, sizeof(ctrue) },
2105  { CKA_ENCRYPT, &cfalse, sizeof(cfalse) },
2106  { CKA_WRAP, &cfalse, sizeof(cfalse) },
2107  { CKA_TOKEN, &ctoken, sizeof(ctoken) },
2108  { CKA_MODULUS_BITS, &keysize, sizeof(keysize) },
2109  { CKA_PUBLIC_EXPONENT, &publicExponent, sizeof(publicExponent)}
2110  };
2111 
2112  CK_ATTRIBUTE privateKeyTemplate[] = {
2113  { CKA_LABEL,(CK_UTF8CHAR *) id_str, strlen (id_str) },
2114  { CKA_ID, id, 16 },
2115  { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2116  { CKA_SIGN, &ctrue, sizeof (ctrue) },
2117  { CKA_DECRYPT, &cfalse, sizeof (cfalse) },
2118  { CKA_UNWRAP, &cfalse, sizeof (cfalse) },
2119  { CKA_SENSITIVE, &ctrue, sizeof (ctrue) },
2120  { CKA_TOKEN, &ctrue, sizeof (ctrue) },
2121  { CKA_PRIVATE, &ctrue, sizeof (ctrue) },
2122  { CKA_EXTRACTABLE, &cfalse, sizeof (cfalse) }
2123  };
2124 
2125  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateKeyPair(session->session,
2126  &mechanism,
2127  publicKeyTemplate, 9,
2128  privateKeyTemplate, 10,
2129  &publicKey,
2130  &privateKey);
2131  if (hsm_pkcs11_check_error(ctx, rv, "generate key pair")) {
2132  return NULL;
2133  }
2134 
2135  new_key = hsm_key_new();
2136  new_key->module = session->module;
2137 
2138  if (session->module->config->use_pubkey) {
2139  new_key->public_key = publicKey;
2140  } else {
2141  new_key->public_key = 0;
2142  }
2143 
2144  new_key->private_key = privateKey;
2145  return new_key;
2146 }
2147 
2148 int
2150 {
2151  CK_RV rv;
2152  hsm_session_t *session;
2153  if (!ctx) ctx = _hsm_ctx;
2154  if (!key) return -1;
2155 
2156  session = hsm_find_key_session(ctx, key);
2157  if (!session) return -2;
2158 
2159  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DestroyObject(session->session,
2160  key->private_key);
2161  if (hsm_pkcs11_check_error(ctx, rv, "Destroy private key")) {
2162  return -3;
2163  }
2164  key->private_key = 0;
2165 
2166  if (session->module->config->use_pubkey) {
2167  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DestroyObject(session->session,
2168  key->public_key);
2169  if (hsm_pkcs11_check_error(ctx, rv, "Destroy public key")) {
2170  return -4;
2171  }
2172  }
2173  key->public_key = 0;
2174 
2175  return 0;
2176 }
2177 
2178 void
2180 {
2181  if (key) {
2182  free(key);
2183  }
2184 }
2185 
2186 void
2187 hsm_key_list_free(hsm_key_t **key_list, size_t count)
2188 {
2189  size_t i;
2190  for (i = 0; i < count; i++) {
2191  hsm_key_free(key_list[i]);
2192  }
2193  free(key_list);
2194 }
2195 
2196 char *
2198 {
2199  unsigned char *id;
2200  char *id_str;
2201  size_t len;
2202  hsm_session_t *session;
2203 
2204  if (!ctx) ctx = _hsm_ctx;
2205  if (!key) return NULL;
2206 
2207  session = hsm_find_key_session(ctx, key);
2208  if (!session) return NULL;
2209 
2210  id = hsm_get_id_for_object(ctx, session, key->private_key, &len);
2211  if (!id) return NULL;
2212 
2213  /* this is plain binary data, we need to convert it to hex */
2214  id_str = malloc(len * 2 + 1);
2215  if (!id_str) return NULL;
2216 
2217  hsm_hex_unparse(id_str, id, len);
2218 
2219  free(id);
2220 
2221  return id_str;
2222 }
2223 
2226  const hsm_key_t *key)
2227 {
2228  hsm_key_info_t *key_info;
2229  hsm_session_t *session;
2230 
2231  if (!ctx) ctx = _hsm_ctx;
2232  session = hsm_find_key_session(ctx, key);
2233  if (!session) return NULL;
2234 
2235  key_info = malloc(sizeof(hsm_key_info_t));
2236 
2237  key_info->id = hsm_get_key_id(ctx, key);
2238  if (key_info->id == NULL) {
2239  key_info->id = strdup("");
2240  }
2241 
2242  key_info->algorithm = (unsigned long) hsm_get_key_algorithm(ctx,
2243  session,
2244  key);
2245  key_info->keysize = (unsigned long) hsm_get_key_size(ctx,
2246  session,
2247  key,
2248  key_info->algorithm);
2249 
2250  switch(key_info->algorithm) {
2251  case CKK_RSA:
2252  key_info->algorithm_name = strdup("RSA");
2253  break;
2254  default:
2255  key_info->algorithm_name = malloc(HSM_MAX_ALGONAME);
2256  snprintf(key_info->algorithm_name, HSM_MAX_ALGONAME,
2257  "%lu", key_info->algorithm);
2258  break;
2259  }
2260 
2261  return key_info;
2262 }
2263 
2264 void
2266 {
2267  if (key_info) {
2268  if (key_info->id) {
2269  free(key_info->id);
2270  }
2271  if (key_info->algorithm_name) {
2272  free(key_info->algorithm_name);
2273  }
2274  free(key_info);
2275  }
2276 }
2277 
2278 ldns_rr*
2280  const ldns_rr_list* rrset,
2281  const hsm_key_t *key,
2282  const hsm_sign_params_t *sign_params)
2283 {
2284  ldns_rr *signature;
2285  ldns_buffer *sign_buf;
2286  ldns_rdf *b64_rdf;
2287  size_t i;
2288  (void) ctx;
2289 
2290  if (!key) return NULL;
2291  if (!sign_params) return NULL;
2292 
2293  signature = hsm_create_empty_rrsig((ldns_rr_list *)rrset,
2294  sign_params);
2295 
2296  /* right now, we have: a key, a semi-sig and an rrset. For
2297  * which we can create the sig and base64 encode that and
2298  * add that to the signature */
2299  sign_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
2300 
2301  if (ldns_rrsig2buffer_wire(sign_buf, signature)
2302  != LDNS_STATUS_OK) {
2303  ldns_buffer_free(sign_buf);
2304  /* ERROR */
2305  return NULL;
2306  }
2307 
2308  /* make it canonical */
2309  for(i = 0; i < ldns_rr_list_rr_count(rrset); i++) {
2310  ldns_rr2canonical(ldns_rr_list_rr(rrset, i));
2311  }
2312 
2313  /* add the rrset in sign_buf */
2314  if (ldns_rr_list2buffer_wire(sign_buf, rrset)
2315  != LDNS_STATUS_OK) {
2316  ldns_buffer_free(sign_buf);
2317  return NULL;
2318  }
2319 
2320  b64_rdf = hsm_sign_buffer(ctx, sign_buf, key, sign_params->algorithm);
2321 
2322  ldns_buffer_free(sign_buf);
2323  if (!b64_rdf) {
2324  /* signing went wrong */
2325  return NULL;
2326  }
2327 
2328  ldns_rr_rrsig_set_sig(signature, b64_rdf);
2329 
2330  return signature;
2331 }
2332 
2333 /* returns a newly allocated (not null-terminated!) string containing
2334  * the message digest of the given source string
2335  * digest length contains the length of the result
2336  * caller must free returned data with free()
2337  * returns NULL (and zero digest length) on error
2338  */
2339 static CK_BYTE *
2340 hsm_digest(hsm_ctx_t *ctx,
2341  hsm_session_t *session,
2342  CK_MECHANISM digest_mechanism,
2343  char *source,
2344  size_t length,
2345  size_t *digest_length)
2346 {
2347  CK_RV rv;
2348  CK_BYTE *digest;
2349  CK_ULONG d = 0;
2350 
2351  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DigestInit(session->session,
2352  &digest_mechanism);
2353  if (hsm_pkcs11_check_error(ctx, rv, "digest init")) {
2354  *digest_length = 0;
2355  return NULL;
2356  }
2357 
2358  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Digest(session->session,
2359  (CK_BYTE *)source,
2360  length,
2361  NULL,
2362  &d);
2363 
2364  if (hsm_pkcs11_check_error(ctx, rv, "digest to determine result size")) {
2365  *digest_length = 0;
2366  return NULL;
2367  }
2368  digest = malloc(d);
2369  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Digest(session->session,
2370  (CK_BYTE *)source,
2371  length,
2372  digest,
2373  &d);
2374  if (hsm_pkcs11_check_error(ctx, rv, "digest")) {
2375  *digest_length = 0;
2376  free(digest);
2377  return NULL;
2378  }
2379 
2380  *digest_length = d;
2381  return digest;
2382 }
2383 
2384 ldns_rdf *
2386  ldns_rdf *name,
2387  uint8_t algorithm,
2388  uint16_t iterations,
2389  uint8_t salt_length,
2390  uint8_t *salt)
2391 {
2392  char *orig_owner_str;
2393  size_t hashed_owner_str_len;
2394  ldns_rdf *hashed_owner;
2395  char *hashed_owner_str;
2396  char *hashed_owner_b32;
2397  int hashed_owner_b32_len;
2398  uint32_t cur_it;
2399  char *hash = NULL;
2400  size_t hash_length = 0;
2401  ldns_status status;
2402  CK_MECHANISM mechanism;
2403  unsigned int i;
2404  hsm_session_t *session = NULL;
2405  char *error_name;
2406 
2407  switch(algorithm) {
2408  case 1:
2409  mechanism.mechanism = CKM_SHA_1;
2410  mechanism.pParameter = NULL;
2411  mechanism.ulParameterLen = 0;
2412  break;
2413  default:
2414  printf("unknown algo: %u\n", (unsigned int)algorithm);
2415  return NULL;
2416  break;
2417  }
2418 
2419  /* just use the first available session */
2420  if (!ctx) ctx = _hsm_ctx;
2421  for (i = 0; i < ctx->session_count; i++) {
2422  if (ctx->session[i]) session = ctx->session[i];
2423  }
2424  if (!session) {
2425  return NULL;
2426  }
2427 
2428  /* prepare the owner name according to the draft section bla */
2429  orig_owner_str = ldns_rdf2str(name);
2430 
2431  hashed_owner_str_len = salt_length + ldns_rdf_size(name);
2432  hashed_owner_str = LDNS_XMALLOC(char, hashed_owner_str_len);
2433  memcpy(hashed_owner_str, ldns_rdf_data(name), ldns_rdf_size(name));
2434  memcpy(hashed_owner_str + ldns_rdf_size(name), salt, salt_length);
2435 
2436  for (cur_it = iterations + 1; cur_it > 0; cur_it--) {
2437  if (hash != NULL) free(hash);
2438  hash = (char *) hsm_digest(ctx,
2439  session,
2440  mechanism,
2441  hashed_owner_str,
2442  hashed_owner_str_len,
2443  &hash_length);
2444 
2445  LDNS_FREE(hashed_owner_str);
2446  hashed_owner_str_len = salt_length + hash_length;
2447  hashed_owner_str = LDNS_XMALLOC(char, hashed_owner_str_len);
2448  if (!hashed_owner_str) {
2449  hsm_ctx_set_error(ctx, -1, "hsm_nsec3_hash_name()",
2450  "Memory error");
2451  return NULL;
2452  }
2453  memcpy(hashed_owner_str, hash, hash_length);
2454  memcpy(hashed_owner_str + hash_length, salt, salt_length);
2455  }
2456 
2457  LDNS_FREE(hashed_owner_str);
2458  hashed_owner_str = hash;
2459  hashed_owner_str_len = hash_length;
2460  hashed_owner_b32 = LDNS_XMALLOC(char,
2461  ldns_b32_ntop_calculate_size(
2462  hashed_owner_str_len) + 1);
2463  LDNS_FREE(orig_owner_str);
2464  hashed_owner_b32_len =
2465  (size_t) ldns_b32_ntop_extended_hex((uint8_t *) hashed_owner_str,
2466  hashed_owner_str_len,
2467  hashed_owner_b32,
2468  ldns_b32_ntop_calculate_size(
2469  hashed_owner_str_len));
2470  if (hashed_owner_b32_len < 1) {
2471  error_name = ldns_rdf2str(name);
2472  hsm_ctx_set_error(ctx, -1, "hsm_nsec3_hash_name()",
2473  "Error in base32 extended hex encoding "
2474  "of hashed owner name (name: %s, return code: %d)",
2475  error_name, hashed_owner_b32_len);
2476  LDNS_FREE(error_name);
2477  LDNS_FREE(hashed_owner_b32);
2478  return NULL;
2479  }
2480  hashed_owner_str_len = hashed_owner_b32_len;
2481  hashed_owner_b32[hashed_owner_b32_len] = '\0';
2482 
2483  status = ldns_str2rdf_dname(&hashed_owner, hashed_owner_b32);
2484  if (status != LDNS_STATUS_OK) {
2485  hsm_ctx_set_error(ctx, -1, "hsm_nsec3_hash_name()",
2486  "Error creating rdf from %s", hashed_owner_b32);
2487  LDNS_FREE(hashed_owner_b32);
2488  return NULL;
2489  }
2490 
2491  free(hash);
2492  LDNS_FREE(hashed_owner_b32);
2493  return hashed_owner;
2494 }
2495 
2496 ldns_rr *
2498  const hsm_key_t *key,
2499  const hsm_sign_params_t *sign_params)
2500 {
2501  /* CK_RV rv; */
2502  ldns_rr *dnskey;
2503  hsm_session_t *session;
2504  ldns_rdf *rdata;
2505 
2506  if (!ctx) ctx = _hsm_ctx;
2507  if (!key) {
2508  hsm_ctx_set_error(ctx, -1, "hsm_get_dnskey()", "Got NULL key");
2509  return NULL;
2510  }
2511  if (!sign_params) {
2512  hsm_ctx_set_error(ctx, -1, "hsm_get_dnskey()", "Got NULL sign_params");
2513  return NULL;
2514  }
2515  session = hsm_find_key_session(ctx, key);
2516  if (!session) return NULL;
2517 
2518  dnskey = ldns_rr_new();
2519  ldns_rr_set_type(dnskey, LDNS_RR_TYPE_DNSKEY);
2520 
2521  ldns_rr_set_owner(dnskey, ldns_rdf_clone(sign_params->owner));
2522 
2523  ldns_rr_push_rdf(dnskey,
2524  ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
2525  sign_params->flags));
2526  ldns_rr_push_rdf(dnskey,
2527  ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
2528  LDNS_DNSSEC_KEYPROTO));
2529  ldns_rr_push_rdf(dnskey,
2530  ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG,
2531  sign_params->algorithm));
2532 
2533  rdata = hsm_get_key_rdata(ctx, session, key);
2534  if (rdata == NULL) {
2535  ldns_rr_free(dnskey);
2536  return NULL;
2537  }
2538  ldns_rr_push_rdf(dnskey, rdata);
2539 
2540  return dnskey;
2541 }
2542 
2543 int
2545  unsigned char *buffer,
2546  unsigned long length)
2547 {
2548  CK_RV rv;
2549  unsigned int i;
2550  hsm_session_t *session;
2551  if (!buffer) return -1;
2552  if (!ctx) ctx = _hsm_ctx;
2553 
2554  /* just try every attached token. If one errors (be it NO_RNG, or
2555  * any other error, simply try the next */
2556  for (i = 0; i < ctx->session_count; i++) {
2557  session = ctx->session[i];
2558  if (session) {
2559  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateRandom(
2560  session->session,
2561  buffer,
2562  length);
2563  if (rv == CKR_OK) {
2564  return 0;
2565  }
2566  }
2567  }
2568  return 1;
2569 }
2570 
2571 uint32_t
2573 {
2574  uint32_t rnd;
2575  int result;
2576  unsigned char rnd_buf[4];
2577  result = hsm_random_buffer(ctx, rnd_buf, 4);
2578  if (result == 0) {
2579  memcpy(&rnd, rnd_buf, 4);
2580  return rnd;
2581  } else {
2582  return 0;
2583  }
2584 }
2585 
2586 uint64_t
2588 {
2589  uint64_t rnd;
2590  int result;
2591  unsigned char rnd_buf[8];
2592  result = hsm_random_buffer(ctx, rnd_buf, 8);
2593  if (result == 0) {
2594  memcpy(&rnd, rnd_buf, 8);
2595  return rnd;
2596  } else {
2597  return 0;
2598  }
2599 }
2600 
2601 
2602 /*
2603  * Additional functions
2604  */
2605 
2606 int hsm_attach(const char *repository,
2607  const char *token_label,
2608  const char *path,
2609  const char *pin,
2610  const hsm_config_t *config)
2611 {
2612  hsm_session_t *session;
2613  int result;
2614 
2615  result = hsm_session_init(_hsm_ctx,
2616  &session,
2617  repository,
2618  token_label,
2619  path,
2620  pin,
2621  config);
2622  if (result == HSM_OK) {
2623  return hsm_ctx_add_session(_hsm_ctx, session);
2624  } else {
2625  return result;
2626  }
2627 }
2628 
2630 int hsm_detach(const char *repository)
2631 {
2632  unsigned int i;
2633  for (i = 0; i < _hsm_ctx->session_count; i++) {
2634  if (_hsm_ctx->session[i] &&
2635  strcmp(_hsm_ctx->session[i]->module->name,
2636  repository) == 0) {
2637  hsm_session_close(_hsm_ctx, _hsm_ctx->session[i], 1);
2638  _hsm_ctx->session[i] = NULL;
2639  /* if this was the last session in the list, decrease the
2640  * session count */
2641  if (i == _hsm_ctx->session_count) {
2642  while(_hsm_ctx->session_count > 0 &&
2643  !_hsm_ctx->session[i]) {
2644  _hsm_ctx->session_count--;
2645  }
2646  }
2647  return 0;
2648  }
2649  }
2650  return -1;
2651 }
2652 
2653 int
2654 hsm_token_attached(hsm_ctx_t *ctx, const char *repository)
2655 {
2656  unsigned int i;
2657  if (!ctx) ctx = _hsm_ctx;
2658  for (i = 0; i < ctx->session_count; i++) {
2659  if (ctx->session[i] &&
2660  strcmp(ctx->session[i]->module->name, repository) == 0) {
2661  return 1;
2662  }
2663  }
2664 
2665  hsm_ctx_set_error(ctx, HSM_REPOSITORY_NOT_FOUND,
2666  "hsm_token_attached()",
2667  "Can't find repository: %s", repository);
2668  return 0;
2669 }
2670 
2671 int
2672 hsm_supported_algorithm(ldns_algorithm algorithm)
2673 {
2674  switch(algorithm) {
2675  case LDNS_SIGN_RSAMD5:
2676  case LDNS_SIGN_RSASHA1:
2677  case LDNS_SIGN_RSASHA1_NSEC3:
2678  case LDNS_SIGN_RSASHA256:
2679  case LDNS_SIGN_RSASHA512:
2680  return 0;
2681  break;
2682  default:
2683  return -1;
2684  }
2685 }
2686 
2687 char *
2689 {
2690  hsm_ctx_t *ctx;
2691 
2692  char *message;
2693 
2694  if (!gctx) {
2695  ctx = _hsm_ctx;
2696  } else {
2697  ctx = gctx;
2698  }
2699 
2700  if (ctx->error) {
2701  ctx->error = 0;
2702  message = malloc(HSM_ERROR_MSGSIZE);
2703 
2704  if (message == NULL) {
2705  return strdup("libhsm memory allocation failed");
2706  }
2707 
2708  snprintf(message, HSM_ERROR_MSGSIZE,
2709  "%s: %s",
2710  ctx->error_action ? ctx->error_action : "unknown()",
2711  ctx->error_message ? ctx->error_message : "unknown error");
2712  return message;
2713  };
2714 
2715  return NULL;
2716 }
2717 
2718 void
2720 {
2721  printf("\t\tmodule at %p (sym %p)\n", (void *) session->module, (void *) session->module->sym);
2722  printf("\t\tmodule path: %s\n", session->module->path);
2723  printf("\t\trepository name: %s\n", session->module->name);
2724  printf("\t\ttoken label: %s\n", session->module->token_label);
2725  printf("\t\tsess handle: %u\n", (unsigned int) session->session);
2726 }
2727 
2728 void
2730  hsm_ctx_t *ctx;
2731  unsigned int i;
2732  if (!gctx) {
2733  ctx = _hsm_ctx;
2734  } else {
2735  ctx = gctx;
2736  }
2737  printf("CTX Sessions: %lu\n",
2738  (long unsigned int) ctx->session_count);
2739  for (i = 0; i < ctx->session_count; i++) {
2740  printf("\tSession at %p\n", (void *) ctx->session[i]);
2741  hsm_print_session(ctx->session[i]);
2742  }
2743 }
2744 
2745 void
2747  hsm_key_info_t *key_info;
2748  if (key) {
2749  key_info = hsm_get_key_info(NULL, key);
2750  if (key_info) {
2751  printf("key:\n");
2752  printf("\tmodule: %p\n", (void *) key->module);
2753  printf("\tprivkey handle: %u\n", (unsigned int) key->private_key);
2754  if (key->module->config->use_pubkey) {
2755  printf("\tpubkey handle: %u\n", (unsigned int) key->public_key);
2756  } else {
2757  printf("\tpubkey handle: %s\n", "NULL");
2758  }
2759  printf("\trepository: %s\n", key->module->name);
2760  printf("\talgorithm: %s\n", key_info->algorithm_name);
2761  printf("\tsize: %lu\n", key_info->keysize);
2762  printf("\tid: %s\n", key_info->id);
2763  hsm_key_info_free(key_info);
2764  } else {
2765  printf("key: hsm_get_key_info() returned NULL\n");
2766  }
2767  } else {
2768  printf("key: <void>\n");
2769  }
2770 }
2771 
2772 void
2774 {
2775  char *message;
2776 
2777  message = hsm_get_error(gctx);
2778 
2779  if (message) {
2780  fprintf(stderr, "%s\n", message);
2781  free(message);
2782  } else {
2783  fprintf(stderr, "Unknown error\n");
2784  }
2785 }
2786 
2787 void
2789 {
2790  CK_RV rv;
2791  CK_SLOT_ID slot_id;
2792  CK_TOKEN_INFO token_info;
2793  hsm_ctx_t *ctx;
2794  unsigned int i;
2795  hsm_session_t *session;
2796  int result;
2797 
2798  if (!gctx) {
2799  ctx = _hsm_ctx;
2800  } else {
2801  ctx = gctx;
2802  }
2803 
2804  for (i = 0; i < ctx->session_count; i++) {
2805  session = ctx->session[i];
2806 
2807  result = hsm_get_slot_id(ctx,
2808  session->module->sym,
2809  session->module->token_label,
2810  &slot_id);
2811  if (result != HSM_OK) return;
2812 
2813  rv = ((CK_FUNCTION_LIST_PTR) session->module->sym)->C_GetTokenInfo(slot_id, &token_info);
2814  if (hsm_pkcs11_check_error(ctx, rv, "C_GetTokenInfo")) {
2815  return;
2816  }
2817 
2818  printf("Repository: %s\n",session->module->name);
2819 
2820  printf("\tModule: %s\n", session->module->path);
2821  printf("\tSlot: %lu\n", slot_id);
2822  printf("\tToken Label: %.*s\n",
2823  (int) sizeof(token_info.label), token_info.label);
2824  printf("\tManufacturer: %.*s\n",
2825  (int) sizeof(token_info.manufacturerID), token_info.manufacturerID);
2826  printf("\tModel: %.*s\n",
2827  (int) sizeof(token_info.model), token_info.model);
2828  printf("\tSerial: %.*s\n",
2829  (int) sizeof(token_info.serialNumber), token_info.serialNumber);
2830 
2831  if (i + 1 != ctx->session_count)
2832  printf("\n");
2833  }
2834 }
char * hsm_get_key_id(hsm_ctx_t *ctx, const hsm_key_t *key)
Definition: libhsm.c:2197
CK_BYTE * CK_BYTE_PTR
Definition: pkcs11.h:1202
#define CKR_SIGNATURE_INVALID
Definition: pkcs11.h:1149
ldns_rdf * hsm_nsec3_hash_name(hsm_ctx_t *ctx, ldns_rdf *name, uint8_t algorithm, uint16_t iterations, uint8_t salt_length, uint8_t *salt)
Definition: libhsm.c:2385
#define CKA_KEY_TYPE
Definition: pkcs11.h:392
#define CKR_SAVED_STATE_INVALID
Definition: pkcs11.h:1174
#define CKR_SESSION_EXISTS
Definition: pkcs11.h:1146
#define CKR_RANDOM_SEED_NOT_SUPPORTED
Definition: pkcs11.h:1170
#define CKR_SESSION_COUNT
Definition: pkcs11.h:1142
int hsm_attach(const char *repository, const char *token_label, const char *path, const char *pin, const hsm_config_t *config)
Definition: libhsm.c:2606
char * hsm_prompt_pin(const char *repository, void *data)
Definition: libhsm.c:1855
#define CKR_KEY_SIZE_RANGE
Definition: pkcs11.h:1122
#define CKF_OS_LOCKING_OK
Definition: pkcs11.h:1095
#define CKR_KEY_TYPE_INCONSISTENT
Definition: pkcs11.h:1123
void hsm_key_free(hsm_key_t *key)
Definition: libhsm.c:2179
void hsm_print_session(hsm_session_t *session)
Definition: libhsm.c:2719
#define CKF_SERIAL_SESSION
Definition: pkcs11.h:305
CK_C_GetSlotList C_GetSlotList
Definition: pkcs11.h:1010
#define CKR_SESSION_PARALLEL_NOT_SUPPORTED
Definition: pkcs11.h:1144
#define CKR_STATE_UNSAVEABLE
Definition: pkcs11.h:1176
#define CKR_MUTEX_NOT_LOCKED
Definition: pkcs11.h:1180
#define CKK_RSA
Definition: pkcs11.h:334
void * CK_VOID_PTR
Definition: pkcs11.h:1206
char * hsm_get_error(hsm_ctx_t *gctx)
Definition: libhsm.c:2688
unsigned char label[32]
Definition: pkcs11.h:231
const char * error_action
Definition: libhsm.h:105
hsm_key_t * hsm_find_key_by_id(hsm_ctx_t *ctx, const char *id)
Definition: libhsm.c:2047
#define CKM_MD5
Definition: pkcs11.h:537
void * handle
Definition: libhsm.h:69
int hsm_detach(const char *repository)
Definition: libhsm.c:2630
#define CKF_RW_SESSION
Definition: pkcs11.h:304
hsm_module_t * module
Definition: libhsm.h:76
#define NULL_PTR
Definition: pkcs11.h:1263
hsm_key_info_t * hsm_get_key_info(hsm_ctx_t *ctx, const hsm_key_t *key)
Definition: libhsm.c:2225
void hsm_sign_params_free(hsm_sign_params_t *params)
Definition: libhsm.c:1961
#define CKR_SESSION_READ_ONLY
Definition: pkcs11.h:1145
#define CKR_WRAPPING_KEY_HANDLE_INVALID
Definition: pkcs11.h:1167
#define CKO_PUBLIC_KEY
Definition: pkcs11.h:315
char * path
Definition: libhsm.h:68
#define CKR_DEVICE_ERROR
Definition: pkcs11.h:1113
char * name
Definition: libhsm.h:66
#define CKR_USER_NOT_LOGGED_IN
Definition: pkcs11.h:1160
unsigned long private_key
Definition: libhsm.h:83
uint32_t hsm_random32(hsm_ctx_t *ctx)
Definition: libhsm.c:2572
#define CKR_ATTRIBUTE_SENSITIVE
Definition: pkcs11.h:1108
#define CKA_DECRYPT
Definition: pkcs11.h:397
void hsm_print_ctx(hsm_ctx_t *gctx)
Definition: libhsm.c:2729
#define CKR_TEMPLATE_INCOMPLETE
Definition: pkcs11.h:1151
ldns_rdf * owner
Definition: libhsmdns.h:49
#define CKR_PIN_LEN_RANGE
Definition: pkcs11.h:1138
#define slot_id
Definition: pkcs11.h:139
int hsm_close()
Definition: libhsm.c:1872
#define CKA_MODULUS_BITS
Definition: pkcs11.h:408
#define CKR_INFORMATION_SENSITIVE
Definition: pkcs11.h:1175
#define CKR_GENERAL_ERROR
Definition: pkcs11.h:1101
unsigned long int CK_ULONG
Definition: pkcs11.h:1200
void hsm_key_list_free(hsm_key_t **key_list, size_t count)
Definition: libhsm.c:2187
unsigned long algorithm
Definition: libhsm.h:90
#define CKA_PUBLIC_EXPONENT
Definition: pkcs11.h:409
long int CK_LONG
Definition: pkcs11.h:1201
void * sym
Definition: libhsm.h:70
ldns_rr * hsm_get_dnskey(hsm_ctx_t *ctx, const hsm_key_t *key, const hsm_sign_params_t *sign_params)
Definition: libhsm.c:2497
#define HSM_TOKEN_LABEL_LENGTH
Definition: libhsm.c:52
#define CK_FALSE
Definition: pkcs11.h:1208
void hsm_destroy_context(hsm_ctx_t *ctx)
Definition: libhsm.c:1935
ck_mechanism_type_t mechanism
Definition: pkcs11.h:680
#define CKR_PIN_INCORRECT
Definition: pkcs11.h:1136
#define CKR_FUNCTION_FAILED
Definition: pkcs11.h:1102
unsigned char CK_BBOOL
Definition: pkcs11.h:1199
int hsm_open(const char *config, char *(pin_callback)(const char *repository, void *), void *data)
Definition: libhsm.c:1716
#define CKR_VENDOR_DEFINED
Definition: pkcs11.h:1182
#define CKR_OPERATION_ACTIVE
Definition: pkcs11.h:1134
#define CKR_SLOT_ID_INVALID
Definition: pkcs11.h:1100
ck_state_t state
Definition: pkcs11.h:299
#define CKU_USER
Definition: pkcs11.h:283
#define CKR_UNWRAPPING_KEY_HANDLE_INVALID
Definition: pkcs11.h:1156
#define CKR_PIN_INVALID
Definition: pkcs11.h:1137
#define CKR_ENCRYPTED_DATA_LEN_RANGE
Definition: pkcs11.h:1117
size_t hsm_count_keys_session(hsm_ctx_t *ctx, const hsm_session_t *session)
Definition: libhsm.c:1192
#define CKA_PRIVATE
Definition: pkcs11.h:374
hsm_key_t ** hsm_list_keys(hsm_ctx_t *ctx, size_t *count)
Definition: libhsm.c:1970
#define CKR_HOST_MEMORY
Definition: pkcs11.h:1099
#define HSM_MODULE_NOT_FOUND
Definition: libhsm.h:55
#define CKR_MECHANISM_INVALID
Definition: pkcs11.h:1131
uint32_t inception
Definition: libhsmdns.h:43
void hsm_key_info_free(hsm_key_info_t *key_info)
Definition: libhsm.c:2265
void hsm_print_key(hsm_key_t *key)
Definition: libhsm.c:2746
#define CKR_FUNCTION_CANCELED
Definition: pkcs11.h:1118
int hsm_token_attached(hsm_ctx_t *ctx, const char *repository)
Definition: libhsm.c:2654
uint16_t flags
Definition: libhsmdns.h:41
#define CKA_SIGN
Definition: pkcs11.h:400
#define CKA_VERIFY
Definition: pkcs11.h:402
#define CKR_WRAPPED_KEY_LEN_RANGE
Definition: pkcs11.h:1166
unsigned long public_key
Definition: libhsm.h:84
#define CKR_KEY_HANDLE_INVALID
Definition: pkcs11.h:1121
uint16_t keytag
Definition: libhsmdns.h:47
#define CKR_MUTEX_BAD
Definition: pkcs11.h:1179
#define HSM_ERROR_MSGSIZE
Definition: libhsm.h:43
CK_C_GetTokenInfo C_GetTokenInfo
Definition: pkcs11.h:1012
unsigned int use_pubkey
Definition: libhsm.h:60
#define CKR_CRYPTOKI_ALREADY_INITIALIZED
Definition: pkcs11.h:1178
#define HSM_REPOSITORY_NOT_FOUND
Definition: libhsm.h:53
#define HSM_NO_REPOSITORIES
Definition: libhsm.h:54
hsm_sign_params_t * hsm_sign_params_new()
Definition: libhsm.c:1944
size_t session_count
Definition: libhsm.h:98
unsigned long session
Definition: libhsm.h:77
#define CKM_RSA_PKCS_KEY_PAIR_GEN
Definition: pkcs11.h:477
unsigned char model[16]
Definition: pkcs11.h:233
#define CKR_ATTRIBUTE_VALUE_INVALID
Definition: pkcs11.h:1110
#define CKA_ID
Definition: pkcs11.h:394
#define CKR_FUNCTION_NOT_PARALLEL
Definition: pkcs11.h:1119
unsigned int id
Definition: libhsm.h:65
ldns_algorithm algorithm
Definition: libhsmdns.h:39
#define CKR_SIGNATURE_LEN_RANGE
Definition: pkcs11.h:1150
#define HSM_CONFIG_FILE_ERROR
Definition: libhsm.h:52
#define CKR_DATA_INVALID
Definition: pkcs11.h:1111
uint32_t expiration
Definition: libhsmdns.h:45
#define CKR_CRYPTOKI_NOT_INITIALIZED
Definition: pkcs11.h:1177
#define CKR_ENCRYPTED_DATA_INVALID
Definition: pkcs11.h:1116
#define HSM_PIN_INCORRECT
Definition: libhsm.h:51
#define CKA_EXTRACTABLE
Definition: pkcs11.h:423
#define HSM_ERROR
Definition: libhsm.h:50
#define CKR_ATTRIBUTE_TYPE_INVALID
Definition: pkcs11.h:1109
hsm_config_t * config
Definition: libhsm.h:71
#define CKR_UNWRAPPING_KEY_SIZE_RANGE
Definition: pkcs11.h:1157
#define CKR_USER_PIN_NOT_INITIALIZED
Definition: pkcs11.h:1161
char * algorithm_name
Definition: libhsm.h:91
char error_message[HSM_ERROR_MSGSIZE]
Definition: libhsm.h:108
#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT
Definition: pkcs11.h:1169
#define CKR_TEMPLATE_INCONSISTENT
Definition: pkcs11.h:1152
#define CKR_ATTRIBUTE_READ_ONLY
Definition: pkcs11.h:1107
#define CKA_TOKEN
Definition: pkcs11.h:373
#define CKR_TOKEN_NOT_RECOGNIZED
Definition: pkcs11.h:1154
#define CKR_WRAPPING_KEY_SIZE_RANGE
Definition: pkcs11.h:1168
#define CKA_WRAP
Definition: pkcs11.h:398
#define CKR_TOKEN_WRITE_PROTECTED
Definition: pkcs11.h:1155
#define CKR_OBJECT_HANDLE_INVALID
Definition: pkcs11.h:1133
#define HSM_MAX_SESSIONS
Definition: libhsm.h:35
hsm_session_t * session[HSM_MAX_SESSIONS]
Definition: libhsm.h:97
#define CKA_ENCRYPT
Definition: pkcs11.h:396
unsigned char CK_UTF8CHAR
Definition: pkcs11.h:1198
const hsm_module_t * module
Definition: libhsm.h:82
int hsm_supported_algorithm(ldns_algorithm algorithm)
Definition: libhsm.c:2672
#define CKR_OK
Definition: pkcs11.h:1097
uint64_t hsm_random64(hsm_ctx_t *ctx)
Definition: libhsm.c:2587
#define CKO_PRIVATE_KEY
Definition: pkcs11.h:316
#define CKM_SHA_1
Definition: pkcs11.h:540
#define CKA_MODULUS
Definition: pkcs11.h:407
#define CKS_RW_USER_FUNCTIONS
Definition: pkcs11.h:292
#define CKR_OPERATION_NOT_INITIALIZED
Definition: pkcs11.h:1135
#define CKR_BUFFER_TOO_SMALL
Definition: pkcs11.h:1173
int hsm_remove_key(hsm_ctx_t *ctx, hsm_key_t *key)
Definition: libhsm.c:2149
hsm_ctx_t * hsm_create_context()
Definition: libhsm.c:1879
#define CKA_CLASS
Definition: pkcs11.h:372
int hsm_random_buffer(hsm_ctx_t *ctx, unsigned char *buffer, unsigned long length)
Definition: libhsm.c:2544
ldns_algorithm algorithm
Definition: hsmspeed.c:43
#define CKR_SESSION_CLOSED
Definition: pkcs11.h:1141
int error
Definition: libhsm.h:101
#define CKR_DEVICE_MEMORY
Definition: pkcs11.h:1114
hsm_key_t ** hsm_list_keys_repository(hsm_ctx_t *ctx, size_t *count, const char *repository)
Definition: libhsm.c:2000
struct ck_function_list * CK_FUNCTION_LIST_PTR
Definition: pkcs11.h:1257
#define HSM_OK
Definition: libhsm.h:49
#define CKR_CANCEL
Definition: pkcs11.h:1098
#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT
Definition: pkcs11.h:1158
unsigned long keysize
Definition: libhsm.h:92
hsm_key_t ** hsm_list_keys_session(hsm_ctx_t *ctx, const hsm_session_t *session, size_t *count)
Definition: libhsm.c:1179
char * id
Definition: libhsm.h:89
#define CKA_LABEL
Definition: pkcs11.h:375
#define CKR_USER_TYPE_INVALID
Definition: pkcs11.h:1162
#define CKR_DEVICE_REMOVED
Definition: pkcs11.h:1115
hsm_key_t * hsm_generate_rsa_key(hsm_ctx_t *ctx, const char *repository, unsigned long keysize)
Definition: libhsm.c:2063
#define HSM_MAX_ALGONAME
Definition: libhsm.h:41
#define CKR_TOKEN_NOT_PRESENT
Definition: pkcs11.h:1153
char * token_label
Definition: libhsm.h:67
unsigned char CK_BYTE
Definition: pkcs11.h:1196
#define CKR_WRAPPED_KEY_INVALID
Definition: pkcs11.h:1165
#define CKA_SENSITIVE
Definition: pkcs11.h:395
#define CKR_USER_ALREADY_LOGGED_IN
Definition: pkcs11.h:1159
int hsm_check_context(hsm_ctx_t *ctx)
Definition: libhsm.c:1885
int hsm_get_slot_id(hsm_ctx_t *ctx, CK_FUNCTION_LIST_PTR pkcs11_functions, const char *token_name, CK_SLOT_ID *slotId)
Definition: libhsm.c:377
void hsm_print_error(hsm_ctx_t *gctx)
Definition: libhsm.c:2773
#define CKR_MECHANISM_PARAM_INVALID
Definition: pkcs11.h:1132
void hsm_print_tokeninfo(hsm_ctx_t *gctx)
Definition: libhsm.c:2788
size_t hsm_count_keys(hsm_ctx_t *ctx)
Definition: libhsm.c:2018
#define CK_TRUE
Definition: pkcs11.h:1209
size_t hsm_count_keys_repository(hsm_ctx_t *ctx, const char *repository)
Definition: libhsm.c:2031
#define CKA_UNWRAP
Definition: pkcs11.h:399
#define CKM_RSA_PKCS
Definition: pkcs11.h:478
#define CKR_DATA_LEN_RANGE
Definition: pkcs11.h:1112
#define CKR_SESSION_HANDLE_INVALID
Definition: pkcs11.h:1143
ldns_rr * hsm_sign_rrset(hsm_ctx_t *ctx, const ldns_rr_list *rrset, const hsm_key_t *key, const hsm_sign_params_t *sign_params)
Definition: libhsm.c:2279