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