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