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