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