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