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