OpenDNSSEC-libhsm  1.4.8.2
libhsm.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009 .SE (The Internet Infrastructure Foundation).
3  * Copyright (c) 2009 NLNet Labs.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "config.h"
29 
30 #include <stdio.h>
31 #include <string.h>
32 #include <strings.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <dlfcn.h>
36 
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  if (handle) {
256 #if defined(HAVE_LOADLIBRARY)
257  /* no idea */
258 #elif defined(HAVE_DLOPEN)
259  (void) dlclose(handle);
260 #endif
261  }
262 }
263 
265 static CK_RV
266 hsm_pkcs11_load_functions(hsm_module_t *module)
267 {
268  CK_C_GetFunctionList pGetFunctionList = NULL;
269 
270  if (module && module->path) {
271  /* library provided by application or user */
272 
273 #if defined(HAVE_LOADLIBRARY)
274  /* Load PKCS #11 library */
275  HINSTANCE hDLL = LoadLibrary(_T(module->path));
276 
277  if (hDLL == NULL) {
278  /* Failed to load the PKCS #11 library */
279  return CKR_FUNCTION_FAILED;
280  }
281 
282  /* Retrieve the entry point for C_GetFunctionList */
283  pGetFunctionList = (CK_C_GetFunctionList)
284  GetProcAddress(hDLL, _T("C_GetFunctionList"));
285 
286 #elif defined(HAVE_DLOPEN)
287  /* Load PKCS #11 library */
288  void* pDynLib = dlopen(module->path, RTLD_NOW | RTLD_LOCAL);
289 
290  if (pDynLib == NULL) {
291  /* Failed to load the PKCS #11 library */
292  return CKR_FUNCTION_FAILED;
293  }
294 
295  /* Retrieve the entry point for C_GetFunctionList */
296  pGetFunctionList = (CK_C_GetFunctionList) dlsym(pDynLib, "C_GetFunctionList");
297  /* Store the handle so we can dlclose it later */
298  module->handle = pDynLib;
299 
300 #else
301  return CKR_FUNCTION_FAILED;
302 #endif
303  } else {
304  /* No library provided, use the statically compiled softHSM */
305 #ifdef HAVE_PKCS11_MODULE
306  return C_GetFunctionList(pkcs11_functions);
307 #else
308  return CKR_FUNCTION_FAILED;
309 #endif
310  }
311 
312  if (pGetFunctionList == NULL) {
313  /* Failed to load the PKCS #11 library */
314  return CKR_FUNCTION_FAILED;
315  }
316 
317  /* Retrieve the function list */
318  (pGetFunctionList)((CK_FUNCTION_LIST_PTR_PTR)(&module->sym));
319  return CKR_OK;
320 }
321 
322 static void
323 hsm_remove_leading_zeroes(CK_BYTE_PTR data, CK_ULONG *len)
324 {
325  CK_BYTE_PTR p = data;
326  CK_ULONG l;
327 
328  if (data == NULL || len == NULL) return;
329 
330  l = *len;
331 
332  while ((unsigned short int)(*p) == 0 && l > 1) {
333  p++;
334  l--;
335  }
336 
337  if (p != data) {
338  memmove(data, p, l);
339  *len = l;
340  }
341 }
342 
343 static int
344 hsm_pkcs11_check_token_name(hsm_ctx_t *ctx,
345  CK_FUNCTION_LIST_PTR pkcs11_functions,
346  CK_SLOT_ID slotId,
347  const char *token_name)
348 {
349  /* token label is always 32 bytes */
350  char token_name_bytes[HSM_TOKEN_LABEL_LENGTH];
351  int result = 0;
352  CK_RV rv;
353  CK_TOKEN_INFO token_info;
354 
355  rv = pkcs11_functions->C_GetTokenInfo(slotId, &token_info);
356  if (hsm_pkcs11_check_error(ctx, rv, "C_GetTokenInfo")) {
357  return 0;
358  }
359 
360  memset(token_name_bytes, ' ', HSM_TOKEN_LABEL_LENGTH);
361  if (strlen(token_name) < HSM_TOKEN_LABEL_LENGTH) {
362  memcpy(token_name_bytes, token_name, strlen(token_name));
363  } else {
364  memcpy(token_name_bytes, token_name, HSM_TOKEN_LABEL_LENGTH);
365  }
366 
367  result = memcmp(token_info.label,
368  token_name_bytes,
370 
371  return result;
372 }
373 
374 
375 int
377  CK_FUNCTION_LIST_PTR pkcs11_functions,
378  const char *token_name, CK_SLOT_ID *slotId)
379 {
380  CK_RV rv;
381  CK_ULONG slotCount;
382  CK_SLOT_ID cur_slot;
383  CK_SLOT_ID *slotIds;
384  int found = 0;
385 
386  if (token_name == NULL || slotId == NULL) return HSM_ERROR;
387 
388  rv = pkcs11_functions->C_GetSlotList(CK_TRUE, NULL_PTR, &slotCount);
389  if (hsm_pkcs11_check_error(ctx, rv, "get slot list")) {
390  return HSM_ERROR;
391  }
392 
393  if (slotCount < 1) {
394  hsm_ctx_set_error(ctx, HSM_ERROR, "hsm_get_slot_id()",
395  "No slots found in HSM");
396  return HSM_ERROR;
397  } else if (slotCount > (SIZE_MAX / sizeof(CK_SLOT_ID))) {
398  hsm_ctx_set_error(ctx, HSM_ERROR, "hsm_get_slot_id()",
399  "Too many slots found in HSM");
400  return HSM_ERROR;
401  }
402 
403  slotIds = malloc(sizeof(CK_SLOT_ID) * slotCount);
404  if(slotIds == NULL) {
405  hsm_ctx_set_error(ctx, HSM_ERROR, "hsm_get_slot_id()",
406  "Could not allocate slot ID table");
407  return HSM_ERROR;
408  }
409 
410  rv = pkcs11_functions->C_GetSlotList(CK_TRUE, slotIds, &slotCount);
411  if (hsm_pkcs11_check_error(ctx, rv, "get slot list")) {
412  return HSM_ERROR;
413  }
414 
415  for (cur_slot = 0; cur_slot < slotCount; cur_slot++) {
416  if (hsm_pkcs11_check_token_name(ctx,
417  pkcs11_functions,
418  slotIds[cur_slot],
419  token_name)) {
420  *slotId = slotIds[cur_slot];
421  found = 1;
422  break;
423  }
424  }
425  free(slotIds);
426  if (!found) {
427  hsm_ctx_set_error(ctx, -1, "hsm_get_slot_id()",
428  "could not find token with the name %s", token_name);
429  return HSM_ERROR;
430  }
431 
432  return HSM_OK;
433 }
434 
435 /* internal functions */
436 static hsm_module_t *
437 hsm_module_new(const char *repository,
438  const char *token_label,
439  const char *path,
440  const hsm_config_t *config)
441 {
442  hsm_module_t *module;
443 
444  if (!repository || !path) return NULL;
445 
446 
447  module = malloc(sizeof(hsm_module_t));
448  if (!module) return NULL;
449 
450  if (config) {
451  module->config = malloc(sizeof(hsm_config_t));
452  if (!module->config) {
453  free(module);
454  return NULL;
455  }
456  memcpy(module->config, config, sizeof(hsm_config_t));
457  } else {
458  module->config = NULL;
459  }
460 
461  module->id = 0; /*TODO i think we can remove this*/
462  module->name = strdup(repository);
463  module->token_label = strdup(token_label);
464  module->path = strdup(path);
465  module->handle = NULL;
466  module->sym = NULL;
467 
468  return module;
469 }
470 
471 static void
472 hsm_module_free(hsm_module_t *module)
473 {
474  if (module) {
475  if (module->name) free(module->name);
476  if (module->token_label) free(module->token_label);
477  if (module->path) free(module->path);
478  if (module->config) free(module->config);
479 
480  free(module);
481  }
482 }
483 
484 static hsm_session_t *
485 hsm_session_new(hsm_module_t *module, CK_SESSION_HANDLE session_handle)
486 {
487  hsm_session_t *session;
488  session = malloc(sizeof(hsm_session_t));
489  session->module = module;
490  session->session = session_handle;
491  return session;
492 }
493 
494 static void
495 hsm_session_free(hsm_session_t *session) {
496  if (session) {
497  free(session);
498  }
499 }
500 
502 static void
503 hsm_config_default(hsm_config_t *config)
504 {
505  config->use_pubkey = 1;
506  config->allow_extract = 0;
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  (void)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, **keys_prev;
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, *key_handles_prev;
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  (void)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_prev = key_handles;
1192  if (!(key_handles = realloc(key_handles_prev, total_count * sizeof(CK_OBJECT_HANDLE)))) {
1193  free(key_handles_prev);
1194  *count = 0;
1195  return NULL;
1196  }
1197  for (i = 0; i < objectCount; i++) {
1198  key_handles[j] = object[i];
1199  j++;
1200  }
1201  }
1202  }
1203 
1204  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjectsFinal(session->session);
1205  if (hsm_pkcs11_check_error(ctx, rv, "Find objects final")) {
1206  free(key_handles);
1207  *count = 0;
1208  return NULL;
1209  }
1210 
1211  if (store) {
1212  keys_prev = keys;
1213  if (!(keys = realloc(keys_prev, total_count * sizeof(hsm_key_t *)))) {
1214  free(key_handles);
1215  free(keys_prev);
1216  *count = 0;
1217  return NULL;
1218  }
1219  for (i = 0; i < total_count; i++) {
1220  key = hsm_key_new_privkey_object_handle(ctx, session,
1221  key_handles[i]);
1222  /* todo, if we get NULL, free all and return error? */
1223  keys[i] = key;
1224  }
1225  }
1226  free(key_handles);
1227 
1228  *count = total_count;
1229  return keys;
1230 }
1231 
1232 
1233 /* returns an array of all keys available to the given session
1234  *
1235  * \param session the session to find the keys in
1236  * \param count this value will contain the number of keys found
1237  *
1238  * \return the list of keys
1239  */
1240 hsm_key_t **
1242  size_t *count)
1243 {
1244  return hsm_list_keys_session_internal(ctx, session, count, 1);
1245 }
1246 
1247 /* returns a count all keys available to the given session
1248  *
1249  * \param session the session to find the keys in
1250  *
1251  * \return the number of keys
1252  */
1253 size_t
1255 {
1256  size_t count = 0;
1257  (void) hsm_list_keys_session_internal(ctx, session, &count, 0);
1258  return count;
1259 }
1260 
1261 /* returns a newly allocated key structure containing the key data
1262  * for the given CKA_ID available in the session. Returns NULL if not
1263  * found
1264  */
1265 static hsm_key_t *
1266 hsm_find_key_by_id_session(hsm_ctx_t *ctx, const hsm_session_t *session,
1267  const unsigned char *id, size_t len)
1268 {
1269  hsm_key_t *key;
1270  CK_OBJECT_HANDLE private_key_handle;
1271 
1272  private_key_handle = hsm_find_object_handle_for_id(
1273  ctx,
1274  session,
1276  (CK_BYTE *) id,
1277  (CK_ULONG) len);
1278  if (private_key_handle != 0) {
1279  key = hsm_key_new_privkey_object_handle(ctx, session,
1280  private_key_handle);
1281  return key;
1282  } else {
1283  return NULL;
1284  }
1285 }
1286 
1287 /* Find a key pair by CKA_ID (as byte array)
1288 
1289 The returned key structure can be freed with hsm_key_free()
1290 
1291 \param context HSM context
1292 \param id CKA_ID of key to find (array of bytes)
1293 \param len number of bytes in the id
1294 \return key identifier or NULL if not found
1295 */
1296 static hsm_key_t *
1297 hsm_find_key_by_id_bin(hsm_ctx_t *ctx,
1298  const unsigned char *id,
1299  size_t len)
1300 {
1301  hsm_key_t *key;
1302  unsigned int i;
1303 
1304  if (!ctx) ctx = _hsm_ctx;
1305  if (!id) return NULL;
1306 
1307  for (i = 0; i < ctx->session_count; i++) {
1308  key = hsm_find_key_by_id_session(ctx, ctx->session[i], id, len);
1309  if (key) return key;
1310  }
1311  return NULL;
1312 }
1313 
1314 
1320 static hsm_session_t *
1321 hsm_find_repository_session(hsm_ctx_t *ctx, const char *repository)
1322 {
1323  unsigned int i;
1324  if (!repository) {
1325  for (i = 0; i < ctx->session_count; i++) {
1326  if (ctx->session[i]) {
1327  return ctx->session[i];
1328  }
1329  }
1330  } else {
1331  for (i = 0; i < ctx->session_count; i++) {
1332  if (ctx->session[i] &&
1333  strcmp(repository, ctx->session[i]->module->name) == 0)
1334  {
1335  return ctx->session[i];
1336  }
1337  }
1338  }
1339 
1341  "hsm_find_repository_session()",
1342  "Can't find repository: %s", repository);
1343 
1344  return NULL;
1345 }
1346 
1347 static ldns_rdf *
1348 hsm_get_key_rdata_rsa(hsm_ctx_t *ctx, hsm_session_t *session,
1349  const hsm_key_t *key)
1350 {
1351  CK_RV rv;
1352  CK_BYTE_PTR public_exponent = NULL;
1353  CK_ULONG public_exponent_len = 0;
1354  CK_BYTE_PTR modulus = NULL;
1355  CK_ULONG modulus_len = 0;
1356  unsigned long hKey = 0;
1357  unsigned char *data = NULL;
1358  size_t data_size = 0;
1359 
1360  CK_ATTRIBUTE template[] = {
1361  {CKA_PUBLIC_EXPONENT, NULL, 0},
1362  {CKA_MODULUS, NULL, 0},
1363  };
1364  ldns_rdf *rdf;
1365 
1366  if (!session || !session->module) {
1367  return NULL;
1368  }
1369 
1370  if (session->module->config->use_pubkey) {
1371  hKey = key->public_key;
1372  } else {
1373  hKey = key->private_key;
1374  }
1375 
1376  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1377  session->session,
1378  hKey,
1379  template,
1380  2);
1381  if (hsm_pkcs11_check_error(ctx, rv, "C_GetAttributeValue")) {
1382  return NULL;
1383  }
1384  public_exponent_len = template[0].ulValueLen;
1385  modulus_len = template[1].ulValueLen;
1386 
1387  public_exponent = template[0].pValue = malloc(public_exponent_len);
1388  if (!public_exponent) {
1389  hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata_rsa()",
1390  "Error allocating memory for public exponent");
1391  return NULL;
1392  }
1393 
1394  modulus = template[1].pValue = malloc(modulus_len);
1395  if (!modulus) {
1396  hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata_rsa()",
1397  "Error allocating memory for modulus");
1398  free(public_exponent);
1399  return NULL;
1400  }
1401 
1402  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1403  session->session,
1404  hKey,
1405  template,
1406  2);
1407  if (hsm_pkcs11_check_error(ctx, rv, "get attribute value")) {
1408  free(template[0].pValue);
1409  free(template[1].pValue);
1410  return NULL;
1411  }
1412 
1413  // Remove leading zeroes
1414  hsm_remove_leading_zeroes(public_exponent, &public_exponent_len);
1415  hsm_remove_leading_zeroes(modulus, &modulus_len);
1416 
1417  data_size = public_exponent_len + modulus_len + 1;
1418  if (public_exponent_len <= 255) {
1419  data = malloc(data_size);
1420  if (!data) {
1421  hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata_rsa()",
1422  "Error allocating memory for pub key rr data");
1423  free(public_exponent);
1424  free(modulus);
1425  return NULL;
1426  }
1427  data[0] = public_exponent_len;
1428  memcpy(&data[1], public_exponent, public_exponent_len);
1429  memcpy(&data[1 + public_exponent_len], modulus, modulus_len);
1430  } else if (public_exponent_len <= 65535) {
1431  data_size += 2;
1432  data = malloc(data_size);
1433  if (!data) {
1434  hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata_rsa()",
1435  "Error allocating memory for pub key rr data");
1436  free(public_exponent);
1437  free(modulus);
1438  return NULL;
1439  }
1440  data[0] = 0;
1441  ldns_write_uint16(&data[1], (uint16_t) public_exponent_len);
1442  memcpy(&data[3], public_exponent, public_exponent_len);
1443  memcpy(&data[3 + public_exponent_len], modulus, modulus_len);
1444  } else {
1445  hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata_rsa()",
1446  "Public exponent too big");
1447  free(public_exponent);
1448  free(modulus);
1449  return NULL;
1450  }
1451  rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, data_size, data);
1452  free(public_exponent);
1453  free(modulus);
1454 
1455  return rdf;
1456 }
1457 
1458 static ldns_rdf *
1459 hsm_get_key_rdata_dsa(hsm_ctx_t *ctx, hsm_session_t *session,
1460  const hsm_key_t *key)
1461 {
1462  CK_RV rv;
1463  CK_BYTE_PTR prime = NULL;
1464  CK_ULONG prime_len = 0;
1465  CK_BYTE_PTR subprime = NULL;
1466  CK_ULONG subprime_len = 0;
1467  CK_BYTE_PTR base = NULL;
1468  CK_ULONG base_len = 0;
1469  CK_BYTE_PTR value = NULL;
1470  CK_ULONG value_len = 0;
1471  unsigned char *data = NULL;
1472  size_t data_size = 0;
1473 
1474  CK_ATTRIBUTE template[] = {
1475  {CKA_PRIME, NULL, 0},
1476  {CKA_SUBPRIME, NULL, 0},
1477  {CKA_BASE, NULL, 0},
1478  {CKA_VALUE, NULL, 0},
1479  };
1480  ldns_rdf *rdf;
1481 
1482  if (!session || !session->module) {
1483  return NULL;
1484  }
1485 
1486  /* DSA needs the public key compared with RSA */
1487  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1488  session->session,
1489  key->public_key,
1490  template,
1491  4);
1492  if (hsm_pkcs11_check_error(ctx, rv, "C_GetAttributeValue")) {
1493  return NULL;
1494  }
1495  prime_len = template[0].ulValueLen;
1496  subprime_len = template[1].ulValueLen;
1497  base_len = template[2].ulValueLen;
1498  value_len = template[3].ulValueLen;
1499 
1500  prime = template[0].pValue = malloc(prime_len);
1501  if (!prime) {
1502  hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata_dsa()",
1503  "Error allocating memory for prime");
1504  return NULL;
1505  }
1506 
1507  subprime = template[1].pValue = malloc(subprime_len);
1508  if (!subprime) {
1509  hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata_dsa()",
1510  "Error allocating memory for subprime");
1511  free(prime);
1512  return NULL;
1513  }
1514 
1515  base = template[2].pValue = malloc(base_len);
1516  if (!base) {
1517  hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata_dsa()",
1518  "Error allocating memory for base");
1519  free(prime);
1520  free(subprime);
1521  return NULL;
1522  }
1523 
1524  value = template[3].pValue = malloc(value_len);
1525  if (!value) {
1526  hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata_dsa()",
1527  "Error allocating memory for value");
1528  free(prime);
1529  free(subprime);
1530  free(base);
1531  return NULL;
1532  }
1533 
1534  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1535  session->session,
1536  key->public_key,
1537  template,
1538  4);
1539  if (hsm_pkcs11_check_error(ctx, rv, "get attribute value")) {
1540  free(prime);
1541  free(subprime);
1542  free(base);
1543  free(value);
1544  return NULL;
1545  }
1546 
1547  data_size = prime_len + subprime_len + base_len + value_len + 1;
1548  data = malloc(data_size);
1549  if (!data) {
1550  hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata_dsa()",
1551  "Error allocating memory for pub key rr data");
1552  free(prime);
1553  free(subprime);
1554  free(base);
1555  free(value);
1556  return NULL;
1557  }
1558  data[0] = (prime_len - 64) / 8;
1559  memcpy(&data[1], subprime, subprime_len);
1560  memcpy(&data[1 + subprime_len], prime, prime_len);
1561  memcpy(&data[1 + subprime_len + prime_len], base, base_len);
1562  memcpy(&data[1 + subprime_len + prime_len + base_len], value, value_len);
1563 
1564  rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, data_size, data);
1565  free(prime);
1566  free(subprime);
1567  free(base);
1568  free(value);
1569 
1570  return rdf;
1571 }
1572 
1573 static ldns_rdf *
1574 hsm_get_key_rdata_gost(hsm_ctx_t *ctx, hsm_session_t *session,
1575  const hsm_key_t *key)
1576 {
1577  CK_RV rv;
1578  CK_BYTE_PTR value = NULL;
1579  CK_ULONG value_len = 0;
1580 
1581  CK_ATTRIBUTE template[] = {
1582  {CKA_VALUE, NULL, 0},
1583  };
1584  ldns_rdf *rdf;
1585 
1586  if (!session || !session->module) {
1587  return NULL;
1588  }
1589 
1590  /* GOST needs the public key compared with RSA */
1591  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1592  session->session,
1593  key->public_key,
1594  template,
1595  1);
1596  if (hsm_pkcs11_check_error(ctx, rv, "C_GetAttributeValue")) {
1597  return NULL;
1598  }
1599  value_len = template[0].ulValueLen;
1600 
1601  value = template[0].pValue = malloc(value_len);
1602  if (!value) {
1603  hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata_dsa()",
1604  "Error allocating memory for value");
1605  return NULL;
1606  }
1607 
1608  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
1609  session->session,
1610  key->public_key,
1611  template,
1612  1);
1613  if (hsm_pkcs11_check_error(ctx, rv, "get attribute value")) {
1614  free(value);
1615  return NULL;
1616  }
1617 
1618  rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, value_len, value);
1619  return rdf;
1620 }
1621 
1622 static ldns_rdf *
1623 hsm_get_key_rdata(hsm_ctx_t *ctx, hsm_session_t *session,
1624  const hsm_key_t *key)
1625 {
1626  /* TODO: Add ECDSA */
1627  switch (hsm_get_key_algorithm(ctx, session, key)) {
1628  case CKK_RSA:
1629  return hsm_get_key_rdata_rsa(ctx, session, key);
1630  break;
1631  case CKK_DSA:
1632  return hsm_get_key_rdata_dsa(ctx, session, key);
1633  break;
1634  case CKK_GOSTR3410:
1635  return hsm_get_key_rdata_gost(ctx, session, key);
1636  break;
1637  default:
1638  return 0;
1639  }
1640 }
1641 
1642 /* this function allocates memory for the mechanism ID and enough room
1643  * to leave the upcoming digest data. It fills in the mechanism id
1644  * use with care. The returned data must be free'd by the caller.
1645  * Only used by RSA PKCS. */
1646 static CK_BYTE *
1647 hsm_create_prefix(CK_ULONG digest_len,
1648  ldns_algorithm algorithm,
1649  CK_ULONG *data_size)
1650 {
1651  CK_BYTE *data;
1652  const CK_BYTE RSA_MD5_ID[] = { 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 };
1653  const CK_BYTE RSA_SHA1_ID[] = { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14 };
1654  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 };
1655  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 };
1656 
1657  switch(algorithm) {
1658  case LDNS_SIGN_RSAMD5:
1659  *data_size = sizeof(RSA_MD5_ID) + digest_len;
1660  data = malloc(*data_size);
1661  memcpy(data, RSA_MD5_ID, sizeof(RSA_MD5_ID));
1662  break;
1663  case LDNS_SIGN_RSASHA1:
1664  case LDNS_SIGN_RSASHA1_NSEC3:
1665  *data_size = sizeof(RSA_SHA1_ID) + digest_len;
1666  data = malloc(*data_size);
1667  memcpy(data, RSA_SHA1_ID, sizeof(RSA_SHA1_ID));
1668  break;
1669  case LDNS_SIGN_RSASHA256:
1670  *data_size = sizeof(RSA_SHA256_ID) + digest_len;
1671  data = malloc(*data_size);
1672  memcpy(data, RSA_SHA256_ID, sizeof(RSA_SHA256_ID));
1673  break;
1674  case LDNS_SIGN_RSASHA512:
1675  *data_size = sizeof(RSA_SHA512_ID) + digest_len;
1676  data = malloc(*data_size);
1677  memcpy(data, RSA_SHA512_ID, sizeof(RSA_SHA512_ID));
1678  break;
1679  case LDNS_SIGN_DSA:
1680  case LDNS_SIGN_DSA_NSEC3:
1681  case LDNS_SIGN_ECC_GOST:
1682 #if LDNS_BUILD_CONFIG_USE_ECDSA
1683  case LDNS_SIGN_ECDSAP256SHA256:
1684  case LDNS_SIGN_ECDSAP384SHA384:
1685 #endif
1686  *data_size = digest_len;
1687  data = malloc(*data_size);
1688  break;
1689  default:
1690  return NULL;
1691  }
1692  return data;
1693 }
1694 
1695 static CK_BYTE *
1696 hsm_digest_through_hsm(hsm_ctx_t *ctx,
1697  hsm_session_t *session,
1698  CK_MECHANISM_TYPE mechanism_type,
1699  CK_ULONG digest_len,
1700  ldns_buffer *sign_buf)
1701 {
1702  CK_MECHANISM digest_mechanism;
1703  CK_BYTE *digest;
1704  CK_RV rv;
1705 
1706  digest_mechanism.pParameter = NULL;
1707  digest_mechanism.ulParameterLen = 0;
1708  digest_mechanism.mechanism = mechanism_type;
1709  digest = malloc(digest_len);
1710  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DigestInit(session->session,
1711  &digest_mechanism);
1712  if (hsm_pkcs11_check_error(ctx, rv, "HSM digest init")) {
1713  free(digest);
1714  return NULL;
1715  }
1716 
1717  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Digest(session->session,
1718  ldns_buffer_begin(sign_buf),
1719  ldns_buffer_position(sign_buf),
1720  digest,
1721  &digest_len);
1722  if (hsm_pkcs11_check_error(ctx, rv, "HSM digest")) {
1723  free(digest);
1724  return NULL;
1725  }
1726  return digest;
1727 }
1728 
1729 static ldns_rdf *
1730 hsm_sign_buffer(hsm_ctx_t *ctx,
1731  ldns_buffer *sign_buf,
1732  const hsm_key_t *key,
1733  ldns_algorithm algorithm)
1734 {
1735  CK_RV rv;
1736  CK_ULONG signatureLen = HSM_MAX_SIGNATURE_LENGTH;
1737  CK_BYTE signature[HSM_MAX_SIGNATURE_LENGTH];
1738  CK_MECHANISM sign_mechanism;
1739 
1740  ldns_rdf *sig_rdf;
1741  CK_BYTE *digest = NULL;
1742  CK_ULONG digest_len;
1743 
1744  CK_BYTE *data = NULL;
1745  CK_ULONG data_len = 0;
1746 
1747  hsm_session_t *session;
1748 
1749  session = hsm_find_key_session(ctx, key);
1750  if (!session) return NULL;
1751 
1752  /* some HSMs don't really handle CKM_SHA1_RSA_PKCS well, so
1753  * we'll do the hashing manually */
1754  /* When adding algorithms, remember there is another switch below */
1755  switch (algorithm) {
1756  case LDNS_SIGN_RSAMD5:
1757  digest_len = 16;
1758  digest = hsm_digest_through_hsm(ctx, session,
1759  CKM_MD5, digest_len,
1760  sign_buf);
1761  break;
1762  case LDNS_SIGN_RSASHA1:
1763  case LDNS_SIGN_RSASHA1_NSEC3:
1764  case LDNS_SIGN_DSA:
1765  case LDNS_SIGN_DSA_NSEC3:
1766  digest_len = LDNS_SHA1_DIGEST_LENGTH;
1767  digest = malloc(digest_len);
1768  digest = ldns_sha1(ldns_buffer_begin(sign_buf),
1769  ldns_buffer_position(sign_buf),
1770  digest);
1771  break;
1772 
1773  case LDNS_SIGN_RSASHA256:
1774 #if LDNS_BUILD_CONFIG_USE_ECDSA
1775  case LDNS_SIGN_ECDSAP256SHA256:
1776 #endif
1777  digest_len = LDNS_SHA256_DIGEST_LENGTH;
1778  digest = malloc(digest_len);
1779  digest = ldns_sha256(ldns_buffer_begin(sign_buf),
1780  ldns_buffer_position(sign_buf),
1781  digest);
1782  break;
1783 #if LDNS_BUILD_CONFIG_USE_ECDSA
1784  case LDNS_SIGN_ECDSAP384SHA384:
1785  digest_len = LDNS_SHA384_DIGEST_LENGTH;
1786  digest = malloc(digest_len);
1787  digest = ldns_sha384(ldns_buffer_begin(sign_buf),
1788  ldns_buffer_position(sign_buf),
1789  digest);
1790  break;
1791 #endif
1792  case LDNS_SIGN_RSASHA512:
1793  digest_len = LDNS_SHA512_DIGEST_LENGTH;
1794  digest = malloc(digest_len);
1795  digest = ldns_sha512(ldns_buffer_begin(sign_buf),
1796  ldns_buffer_position(sign_buf),
1797  digest);
1798  break;
1799  case LDNS_SIGN_ECC_GOST:
1800  digest_len = 32;
1801  digest = hsm_digest_through_hsm(ctx, session,
1802  CKM_GOSTR3411, digest_len,
1803  sign_buf);
1804  break;
1805  default:
1806  /* log error? or should we not even get here for
1807  * unsupported algorithms? */
1808  return NULL;
1809  }
1810 
1811  if (!digest) {
1812  return NULL;
1813  }
1814 
1815  /* CKM_RSA_PKCS does the padding, but cannot know the identifier
1816  * prefix, so we need to add that ourselves.
1817  * The other algorithms will just get the digest buffer returned. */
1818  data = hsm_create_prefix(digest_len, algorithm, &data_len);
1819  memcpy(data + data_len - digest_len, digest, digest_len);
1820 
1821  sign_mechanism.pParameter = NULL;
1822  sign_mechanism.ulParameterLen = 0;
1823  switch(algorithm) {
1824  case LDNS_SIGN_RSAMD5:
1825  case LDNS_SIGN_RSASHA1:
1826  case LDNS_SIGN_RSASHA1_NSEC3:
1827  case LDNS_SIGN_RSASHA256:
1828  case LDNS_SIGN_RSASHA512:
1829  sign_mechanism.mechanism = CKM_RSA_PKCS;
1830  break;
1831  case LDNS_SIGN_DSA:
1832  case LDNS_SIGN_DSA_NSEC3:
1833  sign_mechanism.mechanism = CKM_DSA;
1834  break;
1835  case LDNS_SIGN_ECC_GOST:
1836  sign_mechanism.mechanism = CKM_GOSTR3410;
1837  break;
1838 #if LDNS_BUILD_CONFIG_USE_ECDSA
1839  /* TODO: Add ECDSA */
1840  case LDNS_SIGN_ECDSAP256SHA256:
1841  case LDNS_SIGN_ECDSAP384SHA384:
1842 #endif
1843  default:
1844  /* log error? or should we not even get here for
1845  * unsupported algorithms? */
1846  free(data);
1847  free(digest);
1848  return NULL;
1849  }
1850 
1851  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_SignInit(
1852  session->session,
1853  &sign_mechanism,
1854  key->private_key);
1855  if (hsm_pkcs11_check_error(ctx, rv, "sign init")) {
1856  free(data);
1857  free(digest);
1858  return NULL;
1859  }
1860 
1861  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Sign(session->session, data, data_len,
1862  signature,
1863  &signatureLen);
1864  if (hsm_pkcs11_check_error(ctx, rv, "sign final")) {
1865  free(data);
1866  free(digest);
1867  return NULL;
1868  }
1869 
1870  sig_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
1871  signatureLen,
1872  signature);
1873 
1874  free(data);
1875  free(digest);
1876 
1877  return sig_rdf;
1878 
1879 }
1880 
1881 static int
1882 hsm_dname_is_wildcard(const ldns_rdf* dname)
1883 {
1884  return ( ldns_dname_label_count(dname) > 0 &&
1885  ldns_rdf_data(dname)[0] == 1 &&
1886  ldns_rdf_data(dname)[1] == '*');
1887 }
1888 
1889 static ldns_rr *
1890 hsm_create_empty_rrsig(const ldns_rr_list *rrset,
1891  const hsm_sign_params_t *sign_params)
1892 {
1893  ldns_rr *rrsig;
1894  uint32_t orig_ttl;
1895  uint32_t orig_class;
1896  time_t now;
1897  uint8_t label_count;
1898 
1899  label_count = ldns_dname_label_count(
1900  ldns_rr_owner(ldns_rr_list_rr(rrset, 0)));
1901  /* RFC 4035 section 2.2: dnssec label length and wildcards */
1902  if (hsm_dname_is_wildcard(ldns_rr_owner(ldns_rr_list_rr(rrset, 0)))) {
1903  label_count--;
1904  }
1905 
1906  rrsig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG);
1907 
1908  /* set the type on the new signature */
1909  orig_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrset, 0));
1910  orig_class = ldns_rr_get_class(ldns_rr_list_rr(rrset, 0));
1911 
1912  ldns_rr_set_class(rrsig, orig_class);
1913  ldns_rr_set_ttl(rrsig, orig_ttl);
1914  ldns_rr_set_owner(rrsig,
1915  ldns_rdf_clone(
1916  ldns_rr_owner(
1917  ldns_rr_list_rr(rrset,
1918  0))));
1919 
1920  /* fill in what we know of the signature */
1921 
1922  /* set the orig_ttl */
1923  (void)ldns_rr_rrsig_set_origttl(
1924  rrsig,
1925  ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
1926  orig_ttl));
1927  /* the signers name */
1928  (void)ldns_rr_rrsig_set_signame(
1929  rrsig,
1930  ldns_rdf_clone(sign_params->owner));
1931  /* label count - get it from the first rr in the rr_list */
1932  (void)ldns_rr_rrsig_set_labels(
1933  rrsig,
1934  ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
1935  label_count));
1936  /* inception, expiration */
1937  now = time(NULL);
1938  if (sign_params->inception != 0) {
1939  (void)ldns_rr_rrsig_set_inception(
1940  rrsig,
1941  ldns_native2rdf_int32(
1942  LDNS_RDF_TYPE_TIME,
1943  sign_params->inception));
1944  } else {
1945  (void)ldns_rr_rrsig_set_inception(
1946  rrsig,
1947  ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, now));
1948  }
1949  if (sign_params->expiration != 0) {
1950  (void)ldns_rr_rrsig_set_expiration(
1951  rrsig,
1952  ldns_native2rdf_int32(
1953  LDNS_RDF_TYPE_TIME,
1954  sign_params->expiration));
1955  } else {
1956  (void)ldns_rr_rrsig_set_expiration(
1957  rrsig,
1958  ldns_native2rdf_int32(
1959  LDNS_RDF_TYPE_TIME,
1960  now + LDNS_DEFAULT_EXP_TIME));
1961  }
1962 
1963  (void)ldns_rr_rrsig_set_keytag(
1964  rrsig,
1965  ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
1966  sign_params->keytag));
1967 
1968  (void)ldns_rr_rrsig_set_algorithm(
1969  rrsig,
1970  ldns_native2rdf_int8(
1971  LDNS_RDF_TYPE_ALG,
1972  sign_params->algorithm));
1973 
1974  (void)ldns_rr_rrsig_set_typecovered(
1975  rrsig,
1976  ldns_native2rdf_int16(
1977  LDNS_RDF_TYPE_TYPE,
1978  ldns_rr_get_type(ldns_rr_list_rr(rrset,
1979  0))));
1980 
1981  return rrsig;
1982 }
1983 
1984 
1985 /*
1986  * API functions
1987  */
1988 
1989 int
1990 hsm_open(const char *config,
1991  char *(pin_callback)(unsigned int, const char *, unsigned int))
1992 {
1993  xmlDocPtr doc;
1994  xmlXPathContextPtr xpath_ctx;
1995  xmlXPathObjectPtr xpath_obj;
1996  xmlNode *curNode;
1997  xmlChar *xexpr;
1998 
1999  int i;
2000  char *config_file;
2001  char *repository;
2002  char *token_label;
2003  char *module_path;
2004  char *module_pin;
2005  hsm_config_t module_config;
2006  int result = HSM_OK;
2007  int tries;
2008  int repositories = 0;
2009 
2010  /* create an internal context with an attached session for each
2011  * configured HSM. */
2012  _hsm_ctx = hsm_ctx_new();
2013 
2014  if (config) {
2015  config_file = strdup(config);
2016  } else{
2017  config_file = strdup(HSM_DEFAULT_CONFIG);
2018  }
2019 
2020  /* Load XML document */
2021  doc = xmlParseFile(config_file);
2022  free(config_file);
2023  if (doc == NULL) {
2024  return HSM_CONFIG_FILE_ERROR;
2025  }
2026 
2027  /* Create xpath evaluation context */
2028  xpath_ctx = xmlXPathNewContext(doc);
2029  if(xpath_ctx == NULL) {
2030  xmlFreeDoc(doc);
2031  hsm_ctx_free(_hsm_ctx);
2032  _hsm_ctx = NULL;
2033  return -1;
2034  }
2035 
2036  /* Evaluate xpath expression */
2037  xexpr = (xmlChar *)"//Configuration/RepositoryList/Repository";
2038  xpath_obj = xmlXPathEvalExpression(xexpr, xpath_ctx);
2039  if(xpath_obj == NULL) {
2040  xmlXPathFreeContext(xpath_ctx);
2041  xmlFreeDoc(doc);
2042  hsm_ctx_free(_hsm_ctx);
2043  _hsm_ctx = NULL;
2044  return -1;
2045  }
2046 
2047  if (xpath_obj->nodesetval) {
2048  for (i = 0; i < xpath_obj->nodesetval->nodeNr; i++) {
2049  /*module = hsm_module_new();*/
2050  token_label = NULL;
2051  module_path = NULL;
2052  module_pin = NULL;
2053  hsm_config_default(&module_config);
2054 
2055  curNode = xpath_obj->nodesetval->nodeTab[i]->xmlChildrenNode;
2056  repository = (char *) xmlGetProp(xpath_obj->nodesetval->nodeTab[i],
2057  (const xmlChar *)"name");
2058 
2059  while (curNode) {
2060  if (xmlStrEqual(curNode->name, (const xmlChar *)"TokenLabel"))
2061  token_label = (char *) xmlNodeGetContent(curNode);
2062  if (xmlStrEqual(curNode->name, (const xmlChar *)"Module"))
2063  module_path = (char *) xmlNodeGetContent(curNode);
2064  if (xmlStrEqual(curNode->name, (const xmlChar *)"PIN"))
2065  module_pin = (char *) xmlNodeGetContent(curNode);
2066  if (xmlStrEqual(curNode->name, (const xmlChar *)"SkipPublicKey"))
2067  module_config.use_pubkey = 0;
2068  if (xmlStrEqual(curNode->name, (const xmlChar *)"AllowExtraction"))
2069  module_config.allow_extract = 1;
2070  curNode = curNode->next;
2071  }
2072 
2073  if (repository && token_label && module_path) {
2074  if (module_pin) {
2075  result = hsm_attach(repository,
2076  token_label,
2077  module_path,
2078  module_pin,
2079  &module_config);
2080  free(module_pin);
2081  } else {
2082  if (pin_callback) {
2083  result = HSM_PIN_INCORRECT;
2084  tries = 0;
2085  while (result == HSM_PIN_INCORRECT &&
2086  tries < 3) {
2087  if (tries == 0) {
2088  module_pin = pin_callback(_hsm_ctx->session_count,
2089  repository,
2090  HSM_PIN_FIRST);
2091  } else {
2092  module_pin = pin_callback(_hsm_ctx->session_count,
2093  repository,
2094  HSM_PIN_RETRY);
2095  }
2096 
2097  if (module_pin == NULL) break;
2098 
2099  result = hsm_attach(repository,
2100  token_label,
2101  module_path,
2102  module_pin,
2103  &module_config);
2104  if (result == HSM_OK) {
2105  pin_callback(_hsm_ctx->session_count - 1,
2106  repository,
2107  HSM_PIN_SAVE);
2108  }
2109  memset(module_pin, 0, strlen(module_pin));
2110  tries++;
2111  }
2112  } else {
2113  /* no pin, no callback */
2114  hsm_ctx_set_error(_hsm_ctx, HSM_ERROR, "hsm_open()",
2115  "No pin or callback function");
2116  result = HSM_ERROR;
2117  }
2118  }
2119  free(repository);
2120  free(token_label);
2121  free(module_path);
2122 
2123  if (result != HSM_OK) {
2124  break;
2125  }
2126 
2127  repositories++;
2128  }
2129  }
2130  }
2131 
2132  xmlXPathFreeObject(xpath_obj);
2133  xmlXPathFreeContext(xpath_ctx);
2134  xmlFreeDoc(doc);
2135 
2136  if (result == HSM_OK && repositories == 0) {
2137  hsm_ctx_set_error(_hsm_ctx, HSM_NO_REPOSITORIES, "hsm_open()",
2138  "No repositories found");
2139  return HSM_NO_REPOSITORIES;
2140  }
2141 
2142  return result;
2143 }
2144 
2145 int
2147 {
2148  hsm_ctx_close(_hsm_ctx, 1);
2149  return 0;
2150 }
2151 
2152 hsm_ctx_t *
2154 {
2155  return hsm_ctx_clone(_hsm_ctx);
2156 }
2157 
2158 int
2160 {
2161  unsigned int i;
2162  hsm_session_t *session;
2163  CK_SESSION_INFO info;
2164  CK_RV rv;
2165  CK_SESSION_HANDLE session_handle;
2166 
2167  if (ctx == NULL) {
2168  ctx = _hsm_ctx;
2169  }
2170 
2171  for (i = 0; i < ctx->session_count; i++) {
2172  session = ctx->session[i];
2173  if (session == NULL) continue;
2174 
2175  /* Get session info */
2176  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetSessionInfo(
2177  session->session,
2178  &info);
2179  if (hsm_pkcs11_check_error(ctx, rv, "get session info")) {
2180  return HSM_ERROR;
2181  }
2182 
2183  /* Check session info */
2184  if (info.state != CKS_RW_USER_FUNCTIONS) {
2185  hsm_ctx_set_error(ctx, HSM_ERROR, "hsm_check_context()",
2186  "Session not logged in");
2187  return HSM_ERROR;
2188  }
2189 
2190  /* Try open and close a session with the token */
2191  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_OpenSession(info.slotID,
2193  NULL,
2194  NULL,
2195  &session_handle);
2196  if (hsm_pkcs11_check_error(ctx, rv, "test open session")) {
2197  return HSM_ERROR;
2198  }
2199  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_CloseSession(session_handle);
2200  if (hsm_pkcs11_check_error(ctx, rv, "test close session")) {
2201  return HSM_ERROR;
2202  }
2203  }
2204 
2205  return HSM_OK;
2206 }
2207 
2208 void
2210 {
2211  hsm_ctx_close(ctx, 0);
2212 }
2213 
2219 {
2220  hsm_sign_params_t *params;
2221  params = malloc(sizeof(hsm_sign_params_t));
2222  if (!params) {
2223  return NULL;
2224  }
2225  params->algorithm = LDNS_SIGN_RSASHA256;
2226  params->flags = LDNS_KEY_ZONE_KEY;
2227  params->inception = 0;
2228  params->expiration = 0;
2229  params->keytag = 0;
2230  params->owner = NULL;
2231  return params;
2232 }
2233 
2234 void
2236 {
2237  if (params) {
2238  if (params->owner) ldns_rdf_deep_free(params->owner);
2239  free(params);
2240  }
2241 }
2242 
2243 hsm_key_t **
2244 hsm_list_keys(hsm_ctx_t *ctx, size_t *count)
2245 {
2246  hsm_key_t **keys = NULL, **keys_prev;
2247  size_t key_count = 0;
2248  size_t cur_key_count;
2249  hsm_key_t **session_keys;
2250  unsigned int i, j;
2251 
2252  if (!ctx) {
2253  ctx = _hsm_ctx;
2254  }
2255 
2256  for (i = 0; i < ctx->session_count; i++) {
2257  session_keys = hsm_list_keys_session(ctx, ctx->session[i],
2258  &cur_key_count);
2259  keys_prev = keys;
2260  keys = realloc(keys_prev,
2261  (key_count + cur_key_count) * sizeof(hsm_key_t *));
2262  if (!keys) {
2263  free(keys_prev);
2264  return NULL;
2265  }
2266 
2267  for (j = 0; j < cur_key_count; j++) {
2268  keys[key_count + j] = session_keys[j];
2269  }
2270  key_count += cur_key_count;
2271  free(session_keys);
2272  }
2273  if (count) {
2274  *count = key_count;
2275  }
2276  return keys;
2277 }
2278 
2279 hsm_key_t **
2281  size_t *count,
2282  const char *repository)
2283 {
2284  hsm_session_t *session;
2285 
2286  if (!repository) return NULL;
2287  if (!ctx) ctx = _hsm_ctx;
2288 
2289  session = hsm_find_repository_session(ctx, repository);
2290  if (!session) {
2291  *count = 0;
2292  return NULL;
2293  }
2294  return hsm_list_keys_session(ctx, session, count);
2295 }
2296 
2297 size_t
2299 {
2300  size_t count = 0;
2301  unsigned int i;
2302 
2303  if (!ctx) ctx = _hsm_ctx;
2304  for (i = 0; i < ctx->session_count; i++) {
2305  count += hsm_count_keys_session(ctx, ctx->session[i]);
2306  }
2307  return count;
2308 }
2309 
2310 size_t
2312  const char *repository)
2313 {
2314  hsm_session_t *session;
2315 
2316  if (!repository) return 0;
2317  if (!ctx) ctx = _hsm_ctx;
2318 
2319  session = hsm_find_repository_session(ctx, repository);
2320  if (!session) {
2321  return 0;
2322  }
2323  return hsm_count_keys_session(ctx, session);
2324 }
2325 
2326 hsm_key_t *
2327 hsm_find_key_by_id(hsm_ctx_t *ctx, const char *id)
2328 {
2329  unsigned char *id_bytes;
2330  size_t len;
2331  hsm_key_t *key;
2332 
2333  id_bytes = hsm_hex_parse(id, &len);
2334 
2335  if (!id_bytes) return NULL;
2336 
2337  key = hsm_find_key_by_id_bin(ctx, id_bytes, len);
2338  free(id_bytes);
2339  return key;
2340 }
2341 
2342 hsm_key_t *
2344  const char *repository,
2345  unsigned long keysize)
2346 {
2347  hsm_key_t *new_key, *key;
2348  hsm_session_t *session;
2349  /* ids we create are 16 bytes of data */
2350  unsigned char id[16];
2351  /* that's 33 bytes in string (16*2 + 1 for \0) */
2352  char id_str[33];
2353  CK_RV rv;
2354  CK_OBJECT_HANDLE publicKey, privateKey;
2355  CK_KEY_TYPE keyType = CKK_RSA;
2356  CK_MECHANISM mechanism = {
2358  };
2359  CK_BYTE publicExponent[] = { 1, 0, 1 };
2360  CK_BBOOL ctrue = CK_TRUE;
2361  CK_BBOOL cfalse = CK_FALSE;
2362  CK_BBOOL ctoken = CK_TRUE;
2363  CK_BBOOL cextractable = CK_FALSE;
2364 
2365  if (!ctx) ctx = _hsm_ctx;
2366  session = hsm_find_repository_session(ctx, repository);
2367  if (!session) return NULL;
2368  cextractable = session->module->config->allow_extract ? CK_TRUE : CK_FALSE;
2369 
2370  /* check whether this key doesn't happen to exist already */
2371  key = NULL;
2372  do {
2373  free(key);
2374  hsm_random_buffer(ctx, id, 16);
2375  } while ((key = hsm_find_key_by_id_bin(ctx, id, 16)));
2376  /* the CKA_LABEL will contain a hexadecimal string representation
2377  * of the id */
2378  hsm_hex_unparse(id_str, id, 16);
2379 
2380  if (! session->module->config->use_pubkey) {
2381  ctoken = CK_FALSE;
2382  }
2383 
2384  CK_ATTRIBUTE publicKeyTemplate[] = {
2385  { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen(id_str) },
2386  { CKA_ID, id, 16 },
2387  { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2388  { CKA_VERIFY, &ctrue, sizeof(ctrue) },
2389  { CKA_ENCRYPT, &cfalse, sizeof(cfalse) },
2390  { CKA_WRAP, &cfalse, sizeof(cfalse) },
2391  { CKA_TOKEN, &ctoken, sizeof(ctoken) },
2392  { CKA_MODULUS_BITS, &keysize, sizeof(keysize) },
2393  { CKA_PUBLIC_EXPONENT, &publicExponent, sizeof(publicExponent)}
2394  };
2395 
2396  CK_ATTRIBUTE privateKeyTemplate[] = {
2397  { CKA_LABEL,(CK_UTF8CHAR *) id_str, strlen (id_str) },
2398  { CKA_ID, id, 16 },
2399  { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2400  { CKA_SIGN, &ctrue, sizeof (ctrue) },
2401  { CKA_DECRYPT, &cfalse, sizeof (cfalse) },
2402  { CKA_UNWRAP, &cfalse, sizeof (cfalse) },
2403  { CKA_SENSITIVE, &ctrue, sizeof (ctrue) },
2404  { CKA_TOKEN, &ctrue, sizeof (ctrue) },
2405  { CKA_PRIVATE, &ctrue, sizeof (ctrue) },
2406  { CKA_EXTRACTABLE, &cextractable, sizeof (cextractable) }
2407  };
2408 
2409  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateKeyPair(session->session,
2410  &mechanism,
2411  publicKeyTemplate, 9,
2412  privateKeyTemplate, 10,
2413  &publicKey,
2414  &privateKey);
2415  if (hsm_pkcs11_check_error(ctx, rv, "generate key pair")) {
2416  return NULL;
2417  }
2418 
2419  new_key = hsm_key_new();
2420  new_key->module = session->module;
2421 
2422  if (session->module->config->use_pubkey) {
2423  new_key->public_key = publicKey;
2424  } else {
2425  /* Destroy the object directly in order to optimize storage in HSM */
2426  /* Ignore return value, it is just a session object and will be destroyed later */
2427  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DestroyObject(session->session, publicKey);
2428  new_key->public_key = 0;
2429  }
2430 
2431  new_key->private_key = privateKey;
2432  return new_key;
2433 }
2434 
2435 hsm_key_t *
2437  const char *repository,
2438  unsigned long keysize)
2439 {
2440  CK_RV rv;
2441  hsm_key_t *new_key, *key;
2442  hsm_session_t *session;
2443  CK_OBJECT_HANDLE domainPar, publicKey, privateKey;
2444  CK_BBOOL ctrue = CK_TRUE;
2445  CK_BBOOL cfalse = CK_FALSE;
2446  CK_BBOOL cextractable = CK_FALSE;
2447 
2448  /* ids we create are 16 bytes of data */
2449  unsigned char id[16];
2450  /* that's 33 bytes in string (16*2 + 1 for \0) */
2451  char id_str[33];
2452 
2453  CK_KEY_TYPE keyType = CKK_DSA;
2454  CK_MECHANISM mechanism1 = {
2456  };
2457  CK_MECHANISM mechanism2 = {
2459  };
2460 
2461  /* The maximum size for DSA in DNSSEC */
2462  CK_BYTE dsa_p[128];
2463  CK_BYTE dsa_q[20];
2464  CK_BYTE dsa_g[128];
2465 
2466  CK_ATTRIBUTE domainTemplate[] = {
2467  { CKA_PRIME_BITS, &keysize, sizeof(keysize) }
2468  };
2469 
2470  CK_ATTRIBUTE publicKeyTemplate[] = {
2471  { CKA_PRIME, dsa_p, sizeof(dsa_p) },
2472  { CKA_SUBPRIME, dsa_q, sizeof(dsa_q) },
2473  { CKA_BASE, dsa_g, sizeof(dsa_g) },
2474  { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen(id_str) },
2475  { CKA_ID, id, 16 },
2476  { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2477  { CKA_VERIFY, &ctrue, sizeof(ctrue) },
2478  { CKA_ENCRYPT, &cfalse, sizeof(cfalse) },
2479  { CKA_WRAP, &cfalse, sizeof(cfalse) },
2480  { CKA_TOKEN, &ctrue, sizeof(ctrue) }
2481  };
2482 
2483  CK_ATTRIBUTE privateKeyTemplate[] = {
2484  { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen (id_str) },
2485  { CKA_ID, id, 16 },
2486  { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2487  { CKA_SIGN, &ctrue, sizeof(ctrue) },
2488  { CKA_DECRYPT, &cfalse, sizeof(cfalse) },
2489  { CKA_UNWRAP, &cfalse, sizeof(cfalse) },
2490  { CKA_SENSITIVE, &ctrue, sizeof(ctrue) },
2491  { CKA_TOKEN, &ctrue, sizeof(ctrue) },
2492  { CKA_PRIVATE, &ctrue, sizeof(ctrue) },
2493  { CKA_EXTRACTABLE, &cextractable, sizeof (cextractable) }
2494  };
2495 
2496  if (!ctx) ctx = _hsm_ctx;
2497  session = hsm_find_repository_session(ctx, repository);
2498  if (!session) return NULL;
2499  cextractable = session->module->config->allow_extract ? CK_TRUE : CK_FALSE;
2500 
2501  /* check whether this key doesn't happen to exist already */
2502 
2503  key = NULL;
2504  do {
2505  hsm_key_free(key);
2506  hsm_random_buffer(ctx, id, 16);
2507  } while ((key = hsm_find_key_by_id_bin(ctx, id, 16)));
2508  /* the CKA_LABEL will contain a hexadecimal string representation
2509  * of the id */
2510  hsm_hex_unparse(id_str, id, 16);
2511 
2512  /* Generate the domain parameters */
2513 
2514  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateKey(session->session,
2515  &mechanism1,
2516  domainTemplate, 1,
2517  &domainPar);
2518  if (hsm_pkcs11_check_error(ctx, rv, "generate domain parameters")) {
2519  return NULL;
2520  }
2521 
2522  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(session->session,
2523  domainPar, publicKeyTemplate, 3);
2524  if (hsm_pkcs11_check_error(ctx, rv, "get domain parameters")) {
2525  return NULL;
2526  }
2527 
2528  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DestroyObject(session->session, domainPar);
2529  if (hsm_pkcs11_check_error(ctx, rv, "destroy domain parameters")) {
2530  return NULL;
2531  }
2532 
2533  /* Generate key pair */
2534 
2535  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateKeyPair(session->session,
2536  &mechanism2,
2537  publicKeyTemplate, 10,
2538  privateKeyTemplate, 10,
2539  &publicKey,
2540  &privateKey);
2541  if (hsm_pkcs11_check_error(ctx, rv, "generate key pair")) {
2542  return NULL;
2543  }
2544 
2545  new_key = hsm_key_new();
2546  new_key->module = session->module;
2547  new_key->public_key = publicKey;
2548  new_key->private_key = privateKey;
2549 
2550  return new_key;
2551 }
2552 
2553 hsm_key_t *
2555  const char *repository)
2556 {
2557  CK_RV rv;
2558  hsm_key_t *new_key, *key;
2559  hsm_session_t *session;
2560  CK_OBJECT_HANDLE publicKey, privateKey;
2561  CK_BBOOL ctrue = CK_TRUE;
2562  CK_BBOOL cfalse = CK_FALSE;
2563  CK_BBOOL cextractable = CK_FALSE;
2564 
2565  /* ids we create are 16 bytes of data */
2566  unsigned char id[16];
2567  /* that's 33 bytes in string (16*2 + 1 for \0) */
2568  char id_str[33];
2569 
2570  CK_KEY_TYPE keyType = CKK_GOSTR3410;
2571  CK_MECHANISM mechanism = {
2573  };
2574 
2575  CK_BYTE oid1[] = { 0x06, 0x07, 0x2A, 0x85, 0x03, 0x02, 0x02, 0x23, 0x01 };
2576  CK_BYTE oid2[] = { 0x06, 0x07, 0x2A, 0x85, 0x03, 0x02, 0x02, 0x1E, 0x01 };
2577 
2578  CK_ATTRIBUTE publicKeyTemplate[] = {
2579  { CKA_GOSTR3410PARAMS, oid1, sizeof(oid1) },
2580  { CKA_GOSTR3411PARAMS, oid2, sizeof(oid2) },
2581  { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen(id_str) },
2582  { CKA_ID, id, 16 },
2583  { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2584  { CKA_VERIFY, &ctrue, sizeof(ctrue) },
2585  { CKA_ENCRYPT, &cfalse, sizeof(cfalse) },
2586  { CKA_WRAP, &cfalse, sizeof(cfalse) },
2587  { CKA_TOKEN, &ctrue, sizeof(ctrue) }
2588  };
2589 
2590  CK_ATTRIBUTE privateKeyTemplate[] = {
2591  { CKA_LABEL,(CK_UTF8CHAR*) id_str, strlen (id_str) },
2592  { CKA_ID, id, 16 },
2593  { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
2594  { CKA_SIGN, &ctrue, sizeof(ctrue) },
2595  { CKA_DECRYPT, &cfalse, sizeof(cfalse) },
2596  { CKA_UNWRAP, &cfalse, sizeof(cfalse) },
2597  { CKA_SENSITIVE, &ctrue, sizeof(ctrue) },
2598  { CKA_TOKEN, &ctrue, sizeof(ctrue) },
2599  { CKA_PRIVATE, &ctrue, sizeof(ctrue) },
2600  { CKA_EXTRACTABLE, &cextractable, sizeof (cextractable) }
2601  };
2602 
2603  if (!ctx) ctx = _hsm_ctx;
2604  session = hsm_find_repository_session(ctx, repository);
2605  if (!session) return NULL;
2606  cextractable = session->module->config->allow_extract ? CK_TRUE : CK_FALSE;
2607 
2608  /* check whether this key doesn't happen to exist already */
2609 
2610  key = NULL;
2611  do {
2612  hsm_key_free(key);
2613  hsm_random_buffer(ctx, id, 16);
2614  } while ((key = hsm_find_key_by_id_bin(ctx, id, 16)));
2615  /* the CKA_LABEL will contain a hexadecimal string representation
2616  * of the id */
2617  hsm_hex_unparse(id_str, id, 16);
2618 
2619  /* Generate key pair */
2620 
2621  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateKeyPair(session->session,
2622  &mechanism,
2623  publicKeyTemplate, 9,
2624  privateKeyTemplate, 10,
2625  &publicKey,
2626  &privateKey);
2627  if (hsm_pkcs11_check_error(ctx, rv, "generate key pair")) {
2628  return NULL;
2629  }
2630 
2631  new_key = hsm_key_new();
2632  new_key->module = session->module;
2633  new_key->public_key = publicKey;
2634  new_key->private_key = privateKey;
2635 
2636  return new_key;
2637 }
2638 
2639 int
2641 {
2642  CK_RV rv;
2643  hsm_session_t *session;
2644  if (!ctx) ctx = _hsm_ctx;
2645  if (!key) return -1;
2646 
2647  session = hsm_find_key_session(ctx, key);
2648  if (!session) return -2;
2649 
2650  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DestroyObject(session->session,
2651  key->private_key);
2652  if (hsm_pkcs11_check_error(ctx, rv, "Destroy private key")) {
2653  return -3;
2654  }
2655  key->private_key = 0;
2656 
2657  if (session->module->config->use_pubkey) {
2658  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DestroyObject(session->session,
2659  key->public_key);
2660  if (hsm_pkcs11_check_error(ctx, rv, "Destroy public key")) {
2661  return -4;
2662  }
2663  }
2664  key->public_key = 0;
2665 
2666  return 0;
2667 }
2668 
2669 void
2671 {
2672  if (key) {
2673  free(key);
2674  }
2675 }
2676 
2677 void
2678 hsm_key_list_free(hsm_key_t **key_list, size_t count)
2679 {
2680  size_t i;
2681  for (i = 0; i < count; i++) {
2682  hsm_key_free(key_list[i]);
2683  }
2684  free(key_list);
2685 }
2686 
2687 char *
2689 {
2690  unsigned char *id;
2691  char *id_str;
2692  size_t len;
2693  hsm_session_t *session;
2694 
2695  if (!ctx) ctx = _hsm_ctx;
2696  if (!key) return NULL;
2697 
2698  session = hsm_find_key_session(ctx, key);
2699  if (!session) return NULL;
2700 
2701  id = hsm_get_id_for_object(ctx, session, key->private_key, &len);
2702  if (!id) return NULL;
2703 
2704  /* this is plain binary data, we need to convert it to hex */
2705  id_str = malloc(len * 2 + 1);
2706  if (!id_str) {
2707  free(id);
2708  return NULL;
2709  }
2710 
2711  hsm_hex_unparse(id_str, id, len);
2712 
2713  free(id);
2714 
2715  return id_str;
2716 }
2717 
2720  const hsm_key_t *key)
2721 {
2722  hsm_key_info_t *key_info;
2723  hsm_session_t *session;
2724 
2725  if (!ctx) ctx = _hsm_ctx;
2726  session = hsm_find_key_session(ctx, key);
2727  if (!session) return NULL;
2728 
2729  key_info = malloc(sizeof(hsm_key_info_t));
2730 
2731  key_info->id = hsm_get_key_id(ctx, key);
2732  if (key_info->id == NULL) {
2733  key_info->id = strdup("");
2734  }
2735 
2736  key_info->algorithm = (unsigned long) hsm_get_key_algorithm(ctx,
2737  session,
2738  key);
2739  key_info->keysize = (unsigned long) hsm_get_key_size(ctx,
2740  session,
2741  key,
2742  key_info->algorithm);
2743 
2744  /* TODO: Add ECDSA */
2745  switch(key_info->algorithm) {
2746  case CKK_RSA:
2747  key_info->algorithm_name = strdup("RSA");
2748  break;
2749  case CKK_DSA:
2750  key_info->algorithm_name = strdup("DSA");
2751  break;
2752  case CKK_GOSTR3410:
2753  key_info->algorithm_name = strdup("GOST");
2754  break;
2755  default:
2756  key_info->algorithm_name = malloc(HSM_MAX_ALGONAME);
2757  snprintf(key_info->algorithm_name, HSM_MAX_ALGONAME,
2758  "%lu", key_info->algorithm);
2759  break;
2760  }
2761 
2762  return key_info;
2763 }
2764 
2765 void
2767 {
2768  if (key_info) {
2769  if (key_info->id) {
2770  free(key_info->id);
2771  }
2772  if (key_info->algorithm_name) {
2773  free(key_info->algorithm_name);
2774  }
2775  free(key_info);
2776  }
2777 }
2778 
2779 ldns_rr*
2781  const ldns_rr_list* rrset,
2782  const hsm_key_t *key,
2783  const hsm_sign_params_t *sign_params)
2784 {
2785  ldns_rr *signature;
2786  ldns_buffer *sign_buf;
2787  ldns_rdf *b64_rdf;
2788  size_t i;
2789 
2790  if (!key) return NULL;
2791  if (!sign_params) return NULL;
2792  if (!ctx) ctx = _hsm_ctx;
2793 
2794  signature = hsm_create_empty_rrsig((ldns_rr_list *)rrset,
2795  sign_params);
2796 
2797  /* right now, we have: a key, a semi-sig and an rrset. For
2798  * which we can create the sig and base64 encode that and
2799  * add that to the signature */
2800  sign_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
2801 
2802  if (ldns_rrsig2buffer_wire(sign_buf, signature)
2803  != LDNS_STATUS_OK) {
2804  ldns_buffer_free(sign_buf);
2805  /* ERROR */
2806  ldns_rr_free(signature);
2807  return NULL;
2808  }
2809 
2810  /* make it canonical */
2811  for(i = 0; i < ldns_rr_list_rr_count(rrset); i++) {
2812  ldns_rr2canonical(ldns_rr_list_rr(rrset, i));
2813  }
2814 
2815  /* add the rrset in sign_buf */
2816  if (ldns_rr_list2buffer_wire(sign_buf, rrset)
2817  != LDNS_STATUS_OK) {
2818  ldns_buffer_free(sign_buf);
2819  ldns_rr_free(signature);
2820  return NULL;
2821  }
2822 
2823  b64_rdf = hsm_sign_buffer(ctx, sign_buf, key, sign_params->algorithm);
2824 
2825  ldns_buffer_free(sign_buf);
2826  if (!b64_rdf) {
2827  /* signing went wrong */
2828  ldns_rr_free(signature);
2829  return NULL;
2830  }
2831 
2832  ldns_rr_rrsig_set_sig(signature, b64_rdf);
2833 
2834  return signature;
2835 }
2836 
2837 /* returns a newly allocated (not null-terminated!) string containing
2838  * the message digest of the given source string
2839  * digest length contains the length of the result
2840  * caller must free returned data with free()
2841  * returns NULL (and zero digest length) on error
2842  */
2843 static CK_BYTE *
2844 hsm_digest(hsm_ctx_t *ctx,
2845  hsm_session_t *session,
2846  CK_MECHANISM digest_mechanism,
2847  char *source,
2848  size_t length,
2849  size_t *digest_length)
2850 {
2851  CK_RV rv;
2852  CK_BYTE *digest;
2853  CK_ULONG d = 0;
2854 
2855  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DigestInit(session->session,
2856  &digest_mechanism);
2857  if (hsm_pkcs11_check_error(ctx, rv, "digest init")) {
2858  *digest_length = 0;
2859  return NULL;
2860  }
2861 
2862  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Digest(session->session,
2863  (CK_BYTE *)source,
2864  length,
2865  NULL,
2866  &d);
2867 
2868  if (hsm_pkcs11_check_error(ctx, rv, "digest to determine result size")) {
2869  *digest_length = 0;
2870  return NULL;
2871  }
2872  digest = malloc(d);
2873  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Digest(session->session,
2874  (CK_BYTE *)source,
2875  length,
2876  digest,
2877  &d);
2878  if (hsm_pkcs11_check_error(ctx, rv, "digest")) {
2879  *digest_length = 0;
2880  free(digest);
2881  return NULL;
2882  }
2883 
2884  *digest_length = d;
2885  return digest;
2886 }
2887 
2888 ldns_rdf *
2890  ldns_rdf *name,
2891  uint8_t algorithm,
2892  uint16_t iterations,
2893  uint8_t salt_length,
2894  uint8_t *salt)
2895 {
2896  char *orig_owner_str;
2897  size_t hashed_owner_str_len;
2898  ldns_rdf *hashed_owner;
2899  char *hashed_owner_str;
2900  char *hashed_owner_b32;
2901  int hashed_owner_b32_len;
2902  uint32_t cur_it;
2903  char *hash = NULL;
2904  size_t hash_length = 0;
2905  ldns_status status;
2906  CK_MECHANISM mechanism;
2907  unsigned int i;
2908  hsm_session_t *session = NULL;
2909  char *error_name;
2910 
2911  switch(algorithm) {
2912  case 1:
2913  mechanism.mechanism = CKM_SHA_1;
2914  mechanism.pParameter = NULL;
2915  mechanism.ulParameterLen = 0;
2916  break;
2917  default:
2918  printf("unknown algo: %u\n", (unsigned int)algorithm);
2919  return NULL;
2920  break;
2921  }
2922 
2923  /* just use the first available session */
2924  if (!ctx) ctx = _hsm_ctx;
2925  for (i = 0; i < ctx->session_count; i++) {
2926  if (ctx->session[i]) session = ctx->session[i];
2927  }
2928  if (!session) {
2929  return NULL;
2930  }
2931 
2932  /* prepare the owner name according to the draft section bla */
2933  orig_owner_str = ldns_rdf2str(name);
2934 
2935  hashed_owner_str_len = salt_length + ldns_rdf_size(name);
2936  hashed_owner_str = LDNS_XMALLOC(char, hashed_owner_str_len);
2937  memcpy(hashed_owner_str, ldns_rdf_data(name), ldns_rdf_size(name));
2938  memcpy(hashed_owner_str + ldns_rdf_size(name), salt, salt_length);
2939 
2940  for (cur_it = iterations + 1; cur_it > 0; cur_it--) {
2941  if (hash != NULL) free(hash);
2942  hash = (char *) hsm_digest(ctx,
2943  session,
2944  mechanism,
2945  hashed_owner_str,
2946  hashed_owner_str_len,
2947  &hash_length);
2948 
2949  LDNS_FREE(hashed_owner_str);
2950  hashed_owner_str_len = salt_length + hash_length;
2951  hashed_owner_str = LDNS_XMALLOC(char, hashed_owner_str_len);
2952  if (!hashed_owner_str) {
2953  hsm_ctx_set_error(ctx, -1, "hsm_nsec3_hash_name()",
2954  "Memory error");
2955  return NULL;
2956  }
2957  memcpy(hashed_owner_str, hash, hash_length);
2958  memcpy(hashed_owner_str + hash_length, salt, salt_length);
2959  }
2960 
2961  LDNS_FREE(hashed_owner_str);
2962  hashed_owner_str = hash;
2963  hashed_owner_str_len = hash_length;
2964  hashed_owner_b32 = LDNS_XMALLOC(char,
2965  ldns_b32_ntop_calculate_size(
2966  hashed_owner_str_len) + 1);
2967  LDNS_FREE(orig_owner_str);
2968  hashed_owner_b32_len =
2969  (size_t) ldns_b32_ntop_extended_hex((uint8_t *) hashed_owner_str,
2970  hashed_owner_str_len,
2971  hashed_owner_b32,
2972  ldns_b32_ntop_calculate_size(
2973  hashed_owner_str_len));
2974  if (hashed_owner_b32_len < 1) {
2975  error_name = ldns_rdf2str(name);
2976  hsm_ctx_set_error(ctx, -1, "hsm_nsec3_hash_name()",
2977  "Error in base32 extended hex encoding "
2978  "of hashed owner name (name: %s, return code: %d)",
2979  error_name, hashed_owner_b32_len);
2980  LDNS_FREE(error_name);
2981  LDNS_FREE(hashed_owner_b32);
2982  return NULL;
2983  }
2984  hashed_owner_str_len = hashed_owner_b32_len;
2985  hashed_owner_b32[hashed_owner_b32_len] = '\0';
2986 
2987  status = ldns_str2rdf_dname(&hashed_owner, hashed_owner_b32);
2988  if (status != LDNS_STATUS_OK) {
2989  hsm_ctx_set_error(ctx, -1, "hsm_nsec3_hash_name()",
2990  "Error creating rdf from %s", hashed_owner_b32);
2991  LDNS_FREE(hashed_owner_b32);
2992  return NULL;
2993  }
2994 
2995  free(hash);
2996  LDNS_FREE(hashed_owner_b32);
2997  return hashed_owner;
2998 }
2999 
3000 ldns_rr *
3002  const hsm_key_t *key,
3003  const hsm_sign_params_t *sign_params)
3004 {
3005  /* CK_RV rv; */
3006  ldns_rr *dnskey;
3007  hsm_session_t *session;
3008  ldns_rdf *rdata;
3009 
3010  if (!ctx) ctx = _hsm_ctx;
3011  if (!key) {
3012  hsm_ctx_set_error(ctx, -1, "hsm_get_dnskey()", "Got NULL key");
3013  return NULL;
3014  }
3015  if (!sign_params) {
3016  hsm_ctx_set_error(ctx, -1, "hsm_get_dnskey()", "Got NULL sign_params");
3017  return NULL;
3018  }
3019  session = hsm_find_key_session(ctx, key);
3020  if (!session) return NULL;
3021 
3022  dnskey = ldns_rr_new();
3023  ldns_rr_set_type(dnskey, LDNS_RR_TYPE_DNSKEY);
3024 
3025  ldns_rr_set_owner(dnskey, ldns_rdf_clone(sign_params->owner));
3026 
3027  ldns_rr_push_rdf(dnskey,
3028  ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
3029  sign_params->flags));
3030  ldns_rr_push_rdf(dnskey,
3031  ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
3032  LDNS_DNSSEC_KEYPROTO));
3033  ldns_rr_push_rdf(dnskey,
3034  ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG,
3035  sign_params->algorithm));
3036 
3037  rdata = hsm_get_key_rdata(ctx, session, key);
3038  if (rdata == NULL) {
3039  ldns_rr_free(dnskey);
3040  return NULL;
3041  }
3042  ldns_rr_push_rdf(dnskey, rdata);
3043 
3044  return dnskey;
3045 }
3046 
3047 int
3049  unsigned char *buffer,
3050  unsigned long length)
3051 {
3052  CK_RV rv;
3053  unsigned int i;
3054  hsm_session_t *session;
3055  if (!buffer) return -1;
3056  if (!ctx) ctx = _hsm_ctx;
3057 
3058  /* just try every attached token. If one errors (be it NO_RNG, or
3059  * any other error, simply try the next */
3060  for (i = 0; i < ctx->session_count; i++) {
3061  session = ctx->session[i];
3062  if (session) {
3063  rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateRandom(
3064  session->session,
3065  buffer,
3066  length);
3067  if (rv == CKR_OK) {
3068  return 0;
3069  }
3070  }
3071  }
3072  return 1;
3073 }
3074 
3075 uint32_t
3077 {
3078  uint32_t rnd;
3079  int result;
3080  unsigned char rnd_buf[4];
3081  result = hsm_random_buffer(ctx, rnd_buf, 4);
3082  if (result == 0) {
3083  memcpy(&rnd, rnd_buf, 4);
3084  return rnd;
3085  } else {
3086  return 0;
3087  }
3088 }
3089 
3090 uint64_t
3092 {
3093  uint64_t rnd;
3094  int result;
3095  unsigned char rnd_buf[8];
3096  result = hsm_random_buffer(ctx, rnd_buf, 8);
3097  if (result == 0) {
3098  memcpy(&rnd, rnd_buf, 8);
3099  return rnd;
3100  } else {
3101  return 0;
3102  }
3103 }
3104 
3105 
3106 /*
3107  * Additional functions
3108  */
3109 
3110 int hsm_attach(const char *repository,
3111  const char *token_label,
3112  const char *path,
3113  const char *pin,
3114  const hsm_config_t *config)
3115 {
3116  hsm_session_t *session;
3117  int result;
3118 
3119  result = hsm_session_init(_hsm_ctx,
3120  &session,
3121  repository,
3122  token_label,
3123  path,
3124  pin,
3125  config);
3126  if (result == HSM_OK) {
3127  return hsm_ctx_add_session(_hsm_ctx, session);
3128  } else {
3129  return result;
3130  }
3131 }
3132 
3134 int hsm_detach(const char *repository)
3135 {
3136  unsigned int i;
3137  for (i = 0; i < _hsm_ctx->session_count; i++) {
3138  if (_hsm_ctx->session[i] &&
3139  strcmp(_hsm_ctx->session[i]->module->name,
3140  repository) == 0) {
3141  hsm_session_close(_hsm_ctx, _hsm_ctx->session[i], 1);
3142  _hsm_ctx->session[i] = NULL;
3143  /* if this was the last session in the list, decrease the
3144  * session count */
3145  if (i == _hsm_ctx->session_count) {
3146  while(_hsm_ctx->session_count > 0 &&
3147  !_hsm_ctx->session[i]) {
3148  _hsm_ctx->session_count--;
3149  }
3150  }
3151  return 0;
3152  }
3153  }
3154  return -1;
3155 }
3156 
3157 int
3158 hsm_token_attached(hsm_ctx_t *ctx, const char *repository)
3159 {
3160  unsigned int i;
3161  if (!ctx) ctx = _hsm_ctx;
3162  for (i = 0; i < ctx->session_count; i++) {
3163  if (ctx->session[i] &&
3164  strcmp(ctx->session[i]->module->name, repository) == 0) {
3165  return 1;
3166  }
3167  }
3168 
3170  "hsm_token_attached()",
3171  "Can't find repository: %s", repository);
3172  return 0;
3173 }
3174 
3175 int
3177 {
3178  switch(algorithm) {
3179  case LDNS_SIGN_RSAMD5:
3180  case LDNS_SIGN_RSASHA1:
3181  case LDNS_SIGN_RSASHA1_NSEC3:
3182  case LDNS_SIGN_RSASHA256:
3183  case LDNS_SIGN_RSASHA512:
3184  case LDNS_SIGN_DSA:
3185  case LDNS_SIGN_DSA_NSEC3:
3186  case LDNS_SIGN_ECC_GOST:
3187  return 0;
3188  break;
3189 #if LDNS_BUILD_CONFIG_USE_ECDSA
3190  case LDNS_SIGN_ECDSAP256SHA256:
3191  case LDNS_SIGN_ECDSAP384SHA384:
3192 #endif
3193  default:
3194  return -1;
3195  }
3196 }
3197 
3198 char *
3200 {
3201  hsm_ctx_t *ctx;
3202 
3203  char *message;
3204 
3205  if (!gctx) {
3206  ctx = _hsm_ctx;
3207  } else {
3208  ctx = gctx;
3209  }
3210 
3211  if (ctx->error) {
3212  ctx->error = 0;
3213  message = malloc(HSM_ERROR_MSGSIZE);
3214 
3215  if (message == NULL) {
3216  return strdup("libhsm memory allocation failed");
3217  }
3218 
3219  snprintf(message, HSM_ERROR_MSGSIZE,
3220  "%s: %s",
3221  ctx->error_action ? ctx->error_action : "unknown()",
3222  ctx->error_message[0] ? ctx->error_message : "unknown error");
3223  return message;
3224  };
3225 
3226  return NULL;
3227 }
3228 
3229 void
3231 {
3232  printf("\t\tmodule at %p (sym %p)\n", (void *) session->module, (void *) session->module->sym);
3233  printf("\t\tmodule path: %s\n", session->module->path);
3234  printf("\t\trepository name: %s\n", session->module->name);
3235  printf("\t\ttoken label: %s\n", session->module->token_label);
3236  printf("\t\tsess handle: %u\n", (unsigned int) session->session);
3237 }
3238 
3239 void
3241  hsm_ctx_t *ctx;
3242  unsigned int i;
3243  if (!gctx) {
3244  ctx = _hsm_ctx;
3245  } else {
3246  ctx = gctx;
3247  }
3248  printf("CTX Sessions: %lu\n",
3249  (long unsigned int) ctx->session_count);
3250  for (i = 0; i < ctx->session_count; i++) {
3251  printf("\tSession at %p\n", (void *) ctx->session[i]);
3252  hsm_print_session(ctx->session[i]);
3253  }
3254 }
3255 
3256 void
3258  hsm_key_info_t *key_info;
3259  if (key) {
3260  key_info = hsm_get_key_info(NULL, key);
3261  if (key_info) {
3262  printf("key:\n");
3263  printf("\tmodule: %p\n", (void *) key->module);
3264  printf("\tprivkey handle: %u\n", (unsigned int) key->private_key);
3265  if (key->module->config->use_pubkey) {
3266  printf("\tpubkey handle: %u\n", (unsigned int) key->public_key);
3267  } else {
3268  printf("\tpubkey handle: %s\n", "NULL");
3269  }
3270  printf("\trepository: %s\n", key->module->name);
3271  printf("\talgorithm: %s\n", key_info->algorithm_name);
3272  printf("\tsize: %lu\n", key_info->keysize);
3273  printf("\tid: %s\n", key_info->id);
3274  hsm_key_info_free(key_info);
3275  } else {
3276  printf("key: hsm_get_key_info() returned NULL\n");
3277  }
3278  } else {
3279  printf("key: <void>\n");
3280  }
3281 }
3282 
3283 void
3285 {
3286  char *message;
3287 
3288  message = hsm_get_error(gctx);
3289 
3290  if (message) {
3291  fprintf(stderr, "%s\n", message);
3292  free(message);
3293  } else {
3294  fprintf(stderr, "Unknown error\n");
3295  }
3296 }
3297 
3298 void
3300 {
3301  CK_RV rv;
3302  CK_SLOT_ID slot_id;
3303  CK_TOKEN_INFO token_info;
3304  hsm_ctx_t *ctx;
3305  unsigned int i;
3306  hsm_session_t *session;
3307  int result;
3308 
3309  if (!gctx) {
3310  ctx = _hsm_ctx;
3311  } else {
3312  ctx = gctx;
3313  }
3314 
3315  for (i = 0; i < ctx->session_count; i++) {
3316  session = ctx->session[i];
3317 
3318  result = hsm_get_slot_id(ctx,
3319  session->module->sym,
3320  session->module->token_label,
3321  &slot_id);
3322  if (result != HSM_OK) return;
3323 
3324  rv = ((CK_FUNCTION_LIST_PTR) session->module->sym)->C_GetTokenInfo(slot_id, &token_info);
3325  if (hsm_pkcs11_check_error(ctx, rv, "C_GetTokenInfo")) {
3326  return;
3327  }
3328 
3329  printf("Repository: %s\n",session->module->name);
3330 
3331  printf("\tModule: %s\n", session->module->path);
3332  printf("\tSlot: %lu\n", slot_id);
3333  printf("\tToken Label: %.*s\n",
3334  (int) sizeof(token_info.label), token_info.label);
3335  printf("\tManufacturer: %.*s\n",
3336  (int) sizeof(token_info.manufacturerID), token_info.manufacturerID);
3337  printf("\tModel: %.*s\n",
3338  (int) sizeof(token_info.model), token_info.model);
3339  printf("\tSerial: %.*s\n",
3340  (int) sizeof(token_info.serialNumber), token_info.serialNumber);
3341 
3342  if (i + 1 != ctx->session_count)
3343  printf("\n");
3344  }
3345 }
#define value_len
Definition: pkcs11.h:151
char * hsm_get_key_id(hsm_ctx_t *ctx, const hsm_key_t *key)
Definition: libhsm.c:2688
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:2889
#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:3110
#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:2670
void hsm_print_session(hsm_session_t *session)
Definition: libhsm.c:3230
#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:3199
unsigned char label[32]
Definition: pkcs11.h:231
const char * error_action
Definition: libhsm.h:123
hsm_key_t * hsm_find_key_by_id(hsm_ctx_t *ctx, const char *id)
Definition: libhsm.c:2327
#define CKM_MD5
Definition: pkcs11.h:540
void * handle
Definition: libhsm.h:87
int hsm_detach(const char *repository)
Definition: libhsm.c:3134
#define CKF_RW_SESSION
Definition: pkcs11.h:304
#define HSM_MAX_SIGNATURE_LENGTH
Definition: libhsm.h:49
hsm_module_t * module
Definition: libhsm.h:94
#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:2719
void hsm_sign_params_free(hsm_sign_params_t *params)
Definition: libhsm.c:2235
#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:86
#define CKR_DEVICE_ERROR
Definition: pkcs11.h:1120
char * name
Definition: libhsm.h:84
#define CKR_USER_NOT_LOGGED_IN
Definition: pkcs11.h:1167
unsigned long private_key
Definition: libhsm.h:101
uint32_t hsm_random32(hsm_ctx_t *ctx)
Definition: libhsm.c:3076
#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:3240
#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:2146
#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:2678
unsigned long algorithm
Definition: libhsm.h:108
#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:2436
void * sym
Definition: libhsm.h:88
ldns_rr * hsm_get_dnskey(hsm_ctx_t *ctx, const hsm_key_t *key, const hsm_sign_params_t *sign_params)
Definition: libhsm.c:3001
#define HSM_TOKEN_LABEL_LENGTH
Definition: libhsm.c:50
#define CK_FALSE
Definition: pkcs11.h:1215
unsigned int allow_extract
Definition: libhsm.h:78
void hsm_destroy_context(hsm_ctx_t *ctx)
Definition: libhsm.c:2209
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:1990
#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:1254
#define CKA_PRIVATE
Definition: pkcs11.h:375
hsm_key_t ** hsm_list_keys(hsm_ctx_t *ctx, size_t *count)
Definition: libhsm.c:2244
#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:2766
void hsm_print_key(hsm_key_t *key)
Definition: libhsm.c:3257
#define CKR_FUNCTION_CANCELED
Definition: pkcs11.h:1125
int hsm_token_attached(hsm_ctx_t *ctx, const char *repository)
Definition: libhsm.c:3158
#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:102
#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:2218
size_t session_count
Definition: libhsm.h:116
#define CKA_SUBPRIME
Definition: pkcs11.h:418
unsigned long session
Definition: libhsm.h:95
#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:83
#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:2554
#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:89
#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:109
char error_message[HSM_ERROR_MSGSIZE]
Definition: libhsm.h:126
#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:115
#define CKA_ENCRYPT
Definition: pkcs11.h:397
unsigned char CK_UTF8CHAR
Definition: pkcs11.h:1205
const hsm_module_t * module
Definition: libhsm.h:100
int hsm_supported_algorithm(ldns_algorithm algorithm)
Definition: libhsm.c:3176
#define CKR_OK
Definition: pkcs11.h:1104
uint64_t hsm_random64(hsm_ctx_t *ctx)
Definition: libhsm.c:3091
#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:2640
hsm_ctx_t * hsm_create_context()
Definition: libhsm.c:2153
#define CKA_CLASS
Definition: pkcs11.h:373
int hsm_random_buffer(hsm_ctx_t *ctx, unsigned char *buffer, unsigned long length)
Definition: libhsm.c:3048
ldns_algorithm algorithm
Definition: hsmspeed.c:41
#define CKR_SESSION_CLOSED
Definition: pkcs11.h:1148
int error
Definition: libhsm.h:119
#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:2280
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:110
hsm_key_t ** hsm_list_keys_session(hsm_ctx_t *ctx, const hsm_session_t *session, size_t *count)
Definition: libhsm.c:1241
char * id
Definition: libhsm.h:107
#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:2343
#define HSM_MAX_ALGONAME
Definition: libhsm.h:43
#define CKR_TOKEN_NOT_PRESENT
Definition: pkcs11.h:1160
char * token_label
Definition: libhsm.h:85
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:2159
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:376
#define CKK_GOSTR3410
Definition: pkcs11.h:359
void hsm_print_error(hsm_ctx_t *gctx)
Definition: libhsm.c:3284
#define CKR_MECHANISM_PARAM_INVALID
Definition: pkcs11.h:1139
void hsm_print_tokeninfo(hsm_ctx_t *gctx)
Definition: libhsm.c:3299
size_t hsm_count_keys(hsm_ctx_t *ctx)
Definition: libhsm.c:2298
#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:2311
#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:2780