Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
yubihsm_pkcs11.c
Go to the documentation of this file.
1/*
2 * Copyright 2015-2018 Yubico AB
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <sys/types.h>
18#include <sys/stat.h>
19
20#include <stdbool.h>
21#include <stdlib.h>
22#include <string.h>
23#include <unistd.h>
24
25#ifdef __WIN32
26#include <winsock.h>
27#else
28#include <arpa/inet.h>
29#endif
30
31#include <cmdline.h>
32#include <yubihsm.h>
33
34#include <openssl/rsa.h>
35
36#include "debug_p11.h"
37#include "util_pkcs11.h"
38#include "yubihsm_pkcs11.h"
40
41#define YUBIHSM_PKCS11_MANUFACTURER "Yubico (www.yubico.com)"
42#define YUBIHSM_PKCS11_LIBDESC "YubiHSM PKCS#11 Library"
43#define YUBIHSM_PKCS11_MIN_PIN_LEN 12 // key_id (4) + password (8)
44#define YUBIHSM_PKCS11_MAX_PIN_LEN 68 // key_id (4) + password (64)
45
46#define UNUSED(x) (void) (x) // TODO(adma): also in yubihsm-shell.h
47
48#define GLOBAL_LOCK_OR_RETURN \
49 do { \
50 if (g_ctx.mutex != NULL) { \
51 CK_RV lock_rv = g_ctx.lock_mutex(g_ctx.mutex); \
52 if (lock_rv != CKR_OK) { \
53 DBG_ERR("Unable to acquire global lock"); \
54 return lock_rv; \
55 } \
56 } \
57 } while (0)
58
59#define GLOBAL_UNLOCK_OR_RETURN \
60 do { \
61 if (g_ctx.mutex != NULL) { \
62 CK_RV lock_rv = g_ctx.unlock_mutex(g_ctx.mutex); \
63 if (lock_rv != CKR_OK) { \
64 DBG_ERR("Unable to release global lock"); \
65 return lock_rv; \
66 } \
67 } \
68 } while (0)
69
71
72static bool g_yh_initialized = false;
73
74static yubihsm_pkcs11_context g_ctx;
75
76static void destroy_slot_mutex(void *data) {
78 if (slot->mutex != NULL) {
79 g_ctx.destroy_mutex(slot->mutex);
80 }
81
82 slot->mutex = NULL;
83}
84
85static bool compare_ecdh_keys(void *data, void *item) {
86 if (data == NULL || item == NULL) {
87 return false;
88 }
89
90 CK_OBJECT_HANDLE *a = data;
91
92 ListItem *itm = (ListItem *) item;
93 ecdh_session_key *key = (ecdh_session_key *) &itm->data;
94 CK_OBJECT_HANDLE b = key->id;
95
96 return *a == b;
97}
98
99/* General Purpose */
100
101CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(CK_VOID_PTR pInitArgs) {
102
103 DIN;
104
105 if (g_yh_initialized == true) {
107 }
108
109 CK_C_INITIALIZE_ARGS_PTR init_args = pInitArgs;
110
111 yh_dbg_init(false, false, 0, "stderr");
112
113 if (pInitArgs != NULL) {
114 if ((init_args->flags & CKF_OS_LOCKING_OK) == 0 &&
115 init_args->CreateMutex == NULL && init_args->DestroyMutex == NULL &&
116 init_args->LockMutex == NULL && init_args->UnlockMutex == NULL) {
117 // NOTE(adma): no threading required
118 // all is good, do nothing
119 g_ctx.create_mutex = NULL;
120 g_ctx.destroy_mutex = NULL;
121 g_ctx.lock_mutex = NULL;
122 g_ctx.unlock_mutex = NULL;
123 } else if ((init_args->flags & CKF_OS_LOCKING_OK) != 0 &&
124 init_args->CreateMutex == NULL &&
125 init_args->DestroyMutex == NULL &&
126 init_args->LockMutex == NULL && init_args->UnlockMutex == NULL) {
127 // NOTE(adma): threading with native OS locks
128 set_native_locking(&g_ctx);
129 } else if ((init_args->flags & CKF_OS_LOCKING_OK) == 0 &&
130 init_args->CreateMutex != NULL &&
131 init_args->DestroyMutex != NULL &&
132 init_args->LockMutex != NULL && init_args->UnlockMutex != NULL) {
133 // NOTE(adma): threading with supplied functions
134 g_ctx.create_mutex = init_args->CreateMutex;
135 g_ctx.destroy_mutex = init_args->DestroyMutex;
136 g_ctx.lock_mutex = init_args->LockMutex;
137 g_ctx.unlock_mutex = init_args->UnlockMutex;
138 } else if ((init_args->flags & CKF_OS_LOCKING_OK) != 0 &&
139 init_args->CreateMutex != NULL &&
140 init_args->DestroyMutex != NULL &&
141 init_args->LockMutex != NULL && init_args->UnlockMutex != NULL) {
142 // NOTE(adma): threading with native or supplied functions
143 g_ctx.create_mutex = init_args->CreateMutex;
144 g_ctx.destroy_mutex = init_args->DestroyMutex;
145 g_ctx.lock_mutex = init_args->LockMutex;
146 g_ctx.unlock_mutex = init_args->UnlockMutex;
147 } else {
148 return CKR_ARGUMENTS_BAD;
149 }
150 }
151
152 if (g_ctx.create_mutex != NULL) {
153 if (g_ctx.create_mutex(&g_ctx.mutex) != CKR_OK) {
154 DBG_ERR("Unable to create global mutex");
155 return CKR_FUNCTION_FAILED;
156 }
157 } else {
158 g_ctx.mutex = NULL;
159 }
160
161 struct cmdline_parser_params params;
162
163 struct gengetopt_args_info args_info;
164
165 cmdline_parser_params_init(&params);
166
167 params.initialize = 1;
168 params.check_required = 1;
169
170 char *tmp = "";
171
172 if (cmdline_parser(0, &tmp, &args_info) != 0) {
173 DBG_ERR("Unable to initialize ggo structure");
174 return CKR_FUNCTION_FAILED;
175 }
176
177 params.initialize = 0;
178 params.override = 1;
179
180 char *args = NULL;
181 char *args_parsed = NULL;
182
183 yh_connector **connector_list = NULL;
184
185 if (init_args != NULL && init_args->pReserved != NULL) {
186 args = strdup(init_args->pReserved);
187 if (args == NULL) {
188 DBG_ERR("Failed copying reserved string");
189 return CKR_FUNCTION_FAILED;
190 }
191
192 char *str = args;
193 char *save = NULL;
194 char *part;
195 while ((part = strtok_r(str, " \r\n\t", &save))) {
196 char *new_ptr;
197 str = NULL;
198 if (args_parsed == NULL) {
199 new_ptr = calloc(strlen(part) + 4, sizeof(char));
200 } else {
201 new_ptr = realloc(args_parsed, strlen(args_parsed) + strlen(part) + 4);
202 }
203 if (new_ptr) {
204 args_parsed = new_ptr;
205 sprintf(args_parsed + strlen(args_parsed), "--%s ", part);
206 } else {
207 DBG_ERR("Failed allocating memory for args");
208 goto c_i_failure;
209 }
210 }
211
212 DBG_INFO("Now parsing supplied init args as '%s'", args_parsed);
213
214 if (cmdline_parser_string_ext(args_parsed, &args_info,
215 "yubihsm_pkcs11 module", &params) != 0) {
216 DBG_ERR("Parsing of the reserved init args '%s' failed", args);
217 goto c_i_failure;
218 }
219
220 free(args);
221 args = NULL;
222 free(args_parsed);
223 args_parsed = NULL;
224 }
225
226 // NOTE(thorduri): #TOCTOU
227 char *config_file = args_info.config_file_arg;
228 struct stat sb;
229 if (stat(config_file, &sb) == -1) {
230 config_file = getenv("YUBIHSM_PKCS11_CONF");
231 }
232
233 params.override = 0;
234
235 if (config_file != NULL &&
236 cmdline_parser_config_file(config_file, &args_info, &params) != 0) {
237 DBG_ERR("Unable to parse configuration file");
238 return CKR_FUNCTION_FAILED;
239 }
240
241 yh_dbg_init(args_info.debug_flag, args_info.dinout_flag,
242 args_info.libdebug_flag, args_info.debug_file_arg);
243
244 // NOTE(adma): it's better to set the argument optional and check its presence
245 // here
246 if (args_info.connector_given == 0) {
247 DBG_ERR("No connector defined");
248 return CKR_FUNCTION_FAILED;
249 }
250
251 if (yh_init() != YHR_SUCCESS) {
252 DBG_ERR("Unable to initialize libyubihsm");
253 return CKR_FUNCTION_FAILED;
254 }
255
256 DBG_INFO("Found %u configured connector(s)", args_info.connector_given);
257
258 connector_list = calloc(args_info.connector_given, sizeof(yh_connector *));
259 if (connector_list == NULL) {
260 DBG_ERR("Failed allocating memory");
261 goto c_i_failure;
262 }
263 size_t n_connectors = 0;
264 for (unsigned int i = 0; i < args_info.connector_given; i++) {
265 if (yh_init_connector(args_info.connector_arg[i], &connector_list[i]) !=
266 YHR_SUCCESS) {
267 DBG_ERR("Failed to init connector");
268 goto c_i_failure;
269 }
270 if (args_info.cacert_given) {
271 if (yh_set_connector_option(connector_list[i], YH_CONNECTOR_HTTPS_CA,
272 args_info.cacert_arg) != YHR_SUCCESS) {
273 DBG_ERR("Failed to set HTTPS CA option");
274 goto c_i_failure;
275 }
276 }
277 if (args_info.proxy_given) {
279 args_info.proxy_arg) != YHR_SUCCESS) {
280 DBG_ERR("Failed to set proxy server option");
281 goto c_i_failure;
282 }
283 }
284
285 if (yh_connect(connector_list[i], args_info.timeout_arg) != YHR_SUCCESS) {
286 DBG_ERR("Failed to connect '%s'", args_info.connector_arg[i]);
287 continue;
288 } else {
289 n_connectors++;
290 }
291 }
292
293 if (add_connectors(&g_ctx, args_info.connector_given, args_info.connector_arg,
294 connector_list) == false) {
295 DBG_ERR("Failed building connectors list");
296 goto c_i_failure;
297 }
298
299 cmdline_parser_free(&args_info);
300 free(connector_list);
301
302 DBG_INFO("Found %zu usable connector(s)", n_connectors);
303
304 g_yh_initialized = true;
305
306 DOUT;
307 return CKR_OK;
308
309c_i_failure:
310
311 free(args_parsed);
312 free(args);
313
314 list_iterate(&g_ctx.slots, destroy_slot_mutex);
315 list_destroy(&g_ctx.slots);
316
317 if (connector_list) {
318 for (unsigned int i = 0; i < args_info.connector_given; i++) {
319 yh_disconnect(connector_list[i]);
320 }
321 }
322
323 cmdline_parser_free(&args_info);
324 free(connector_list);
325
326 if (g_ctx.mutex != NULL) {
327 g_ctx.destroy_mutex(g_ctx.mutex);
328 g_ctx.mutex = NULL;
329 }
330
331 return CKR_FUNCTION_FAILED;
332}
333
335
336 DIN;
337
338 if (pReserved != NULL) {
339 DBG_ERR("Finalized called with pReserved != NULL");
340 return CKR_ARGUMENTS_BAD;
341 }
342
343 if (g_yh_initialized == false) {
344 DBG_ERR("libyubihsm is not initialized or already finalized");
346 }
347
348 list_iterate(&g_ctx.slots, destroy_slot_mutex);
349 list_destroy(&g_ctx.slots);
350
351 if (g_ctx.mutex != NULL) {
352 g_ctx.destroy_mutex(g_ctx.mutex);
353 g_ctx.mutex = NULL;
354 }
355
356 g_yh_initialized = false;
357
358 yh_exit();
359
360 DOUT;
361
362 if (_YHP11_OUTPUT != stdout && _YHP11_OUTPUT != stderr &&
363 _YHP11_OUTPUT != NULL) {
364 fclose(_YHP11_OUTPUT);
365 _YHP11_OUTPUT = stderr;
366 }
367
368 return CKR_OK;
369}
370
372
373 DIN;
374
375 if (g_yh_initialized == false) {
376 DBG_ERR("libyubihsm is not initialized or already finalized");
378 }
379 if (pInfo == NULL) {
380 return CKR_ARGUMENTS_BAD;
381 }
382
383 CK_VERSION ver = {VERSION_MAJOR, (VERSION_MINOR * 10) + VERSION_PATCH};
384
385 pInfo->cryptokiVersion = function_list.version;
386
387 memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID));
388 memcpy((char *) pInfo->manufacturerID, YUBIHSM_PKCS11_MANUFACTURER,
390
391 pInfo->flags = 0;
392
393 memset(pInfo->libraryDescription, ' ', sizeof(pInfo->libraryDescription));
394 memcpy((char *) pInfo->libraryDescription, YUBIHSM_PKCS11_LIBDESC,
395 strlen(YUBIHSM_PKCS11_LIBDESC));
396
397 pInfo->libraryVersion = ver;
398
399 DOUT;
400 return CKR_OK;
401}
402
403CK_DEFINE_FUNCTION(CK_RV, C_GetFunctionList)
405 yh_dbg_init(false, false, 0, "stderr");
406
408
409 if (ppFunctionList == NULL) {
410 DBG_ERR("GetFunctionList called with ppFunctionList = NULL");
411 return CKR_ARGUMENTS_BAD;
412 }
413
415
417 return CKR_OK;
418}
419
420/* Slot and token management */
421
422CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)
424
425 DIN;
426
427 if (g_yh_initialized == false) {
428 DBG_ERR("libyubihsm is not initialized or already finalized");
430 }
431
432 if (!pulCount) {
433 DBG_ERR("pulCount argument bad");
434 return CKR_ARGUMENTS_BAD;
435 }
436
438
439 if (pSlotList == NULL) {
440 *pulCount = 0;
441 // NOTE(adma) just return the number of slots
442 if (tokenPresent == CK_TRUE) {
443 for (ListItem *item = g_ctx.slots.head; item != NULL; item = item->next) {
445 if (yh_connector_has_device(slot->connector) == true) {
446 *pulCount += 1;
447 }
448 }
449
450 DBG_INFO("Number of slots with a token is %lu", *pulCount);
451 } else {
452 *pulCount = g_ctx.slots.length;
453
454 DBG_INFO("Total number of slots is %lu", *pulCount);
455 }
456 // NOTE(adma): actually return the slot IDs
457 DBG_INFO("Can return %lu slot(s)", *pulCount);
458
460
461 DOUT;
462 return CKR_OK;
463 }
464
466 bool full = false;
467 bool overflow = false;
468 for (ListItem *item = g_ctx.slots.head; item != NULL; item = item->next) {
469 if (j == *pulCount) {
470 full = true;
471 }
472
474 if (tokenPresent == CK_TRUE) {
475 if (yh_connector_has_device(slot->connector) != true) {
476 continue;
477 }
478 }
479 if (full == false) {
480 pSlotList[j] = slot->id;
481
482 DBG_INFO("Returning slot %lu", pSlotList[j]);
483 } else {
484 overflow = true;
485 }
486
487 j += 1;
488 }
489
490 *pulCount = j;
491
492 if (overflow == true) {
495 }
496
498
499 DOUT;
500 return CKR_OK;
501}
502
503CK_DEFINE_FUNCTION(CK_RV, C_GetSlotInfo)
505
506 DIN;
507
508 if (g_yh_initialized == false) {
509 DBG_ERR("libyubihsm is not initialized or already finalized");
511 }
512
513 if (!pInfo) {
514 DBG_ERR("Invalid pInfo");
515 return CKR_ARGUMENTS_BAD;
516 }
517
519 if (slot == NULL) {
520 DBG_ERR("Invalid slot ID %lu", slotID);
521 return CKR_SLOT_ID_INVALID;
522 }
523
524 char *s;
525 int l;
526
527 s = "YubiHSM Connector ";
528 l = strlen(s);
529 memset(pInfo->slotDescription, ' ', 64);
530 memcpy((char *) pInfo->slotDescription, s, l);
531
533 memcpy((char *) pInfo->slotDescription + l, s, strlen(s));
534
535 s = "Yubico";
536 l = strlen(s);
537 memset(pInfo->manufacturerID, ' ', 32);
538 memcpy((char *) pInfo->manufacturerID, s, l);
539
541
545
549
551
552 pInfo->hardwareVersion.major = major;
553 pInfo->hardwareVersion.minor = (minor * 100) + patch;
554
555 pInfo->firmwareVersion.major = major;
556 pInfo->firmwareVersion.minor = (minor * 100) + patch;
557
558 release_slot(&g_ctx, slot);
559
560 DOUT;
561 return CKR_OK;
562}
563
564CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)
565(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo) {
566
567 DIN;
568
569 CK_RV rv = CKR_OK;
570
571 if (g_yh_initialized == false) {
572 DBG_ERR("libyubihsm is not initialized or already finalized");
574 }
575
576 if (!pInfo) {
577 DBG_ERR("Invalid pInfo");
578 return CKR_ARGUMENTS_BAD;
579 }
580
582 if (slot == NULL) {
583 DBG_ERR("Invalid slot ID %lu", slotID);
584 return CKR_SLOT_ID_INVALID;
585 }
586
587 if (yh_connector_has_device(slot->connector) == false) {
588 DBG_ERR("Slot %lu has no token inserted", slotID);
590 goto c_gt_out;
591 }
592
593 char *s;
594 int l;
595
596 s = "YubiHSM";
597 l = strlen(s);
598 memset(pInfo->label, ' ', 32);
599 memcpy((char *) pInfo->label, s, l);
600
602 l = strlen(s);
603 memset(pInfo->manufacturerID, ' ', 32);
604 memcpy((char *) pInfo->manufacturerID, s, l);
605
607
612
614 &serial, NULL, NULL, NULL, NULL);
615 if (yrc != YHR_SUCCESS) {
616 DBG_ERR("Unable to get device version and serial number: %s",
619 goto c_gt_out;
620 }
621
622 s = "YubiHSM";
623 l = strlen(s);
624 memset(pInfo->model, ' ', 16);
625 memcpy((char *) pInfo->model, s, l);
626
627 memset(pInfo->serialNumber, ' ', 16);
628 l = sprintf((char *) pInfo->serialNumber, "%08u", serial);
629 pInfo->serialNumber[l] = ' ';
630
633
634 pInfo->ulMaxSessionCount =
635 CK_EFFECTIVELY_INFINITE; // maximum number of sessions that can be opened
636 // with the token at one time by a single
637 // application
638 pInfo->ulSessionCount =
639 CK_UNAVAILABLE_INFORMATION; // number of sessions that this application
640 // currently has open with the token
641 pInfo->ulMaxRwSessionCount =
642 CK_EFFECTIVELY_INFINITE; // maximum number of read/write sessions that can
643 // be opened with the token at one time by a single
644 // application
645 pInfo->ulRwSessionCount =
646 CK_UNAVAILABLE_INFORMATION; // number of read/write sessions that this
647 // application currently has open with the token
648 pInfo->ulMaxPinLen =
649 YUBIHSM_PKCS11_MAX_PIN_LEN; // maximum length in bytes of the PIN
650 pInfo->ulMinPinLen =
651 YUBIHSM_PKCS11_MIN_PIN_LEN; // minimum length in bytes of the PIN
652 pInfo->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION;
653 pInfo->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION;
654 pInfo->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION;
655 pInfo->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;
656
658
659 pInfo->hardwareVersion = ver;
660
661 pInfo->firmwareVersion = ver;
662
663 DOUT;
664
665c_gt_out:
666
667 release_slot(&g_ctx, slot);
668
669 return rv;
670}
671
672CK_DEFINE_FUNCTION(CK_RV, C_WaitForSlotEvent)
674
675 DIN;
676
680
681 DOUT;
683}
684
685CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)
688
689 DIN;
690
691 CK_RV rv = CKR_OK;
692
693 if (g_yh_initialized == false) {
694 DBG_ERR("libyubihsm is not initialized or already finalized");
696 }
697
698 if (pulCount == NULL) {
699 DBG_ERR("Wrong/missing parameter");
700 return CKR_ARGUMENTS_BAD;
701 }
702
704 if (slot == NULL) {
705 DBG_ERR("Invalid slot ID %lu", slotID);
706 return CKR_SLOT_ID_INVALID;
707 }
708
711 DBG_ERR("Mechanism buffer too small");
712 goto c_gml_out;
713 } else if (rv == CKR_FUNCTION_FAILED) {
714 DBG_ERR("Failed getting device info");
715 goto c_gml_out;
716 }
717
718 DBG_INFO("Found %lu mechanisms", *pulCount);
719
720 DOUT;
721
722c_gml_out:
723
724 release_slot(&g_ctx, slot);
725
726 return rv;
727}
728
729CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismInfo)
730(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo) {
731
732 DIN;
733
734 CK_RV rv = CKR_OK;
735
736 if (g_yh_initialized == false) {
737 DBG_ERR("libyubihsm is not initialized or already finalized");
739 }
740
741 if (pInfo == NULL) {
742 DBG_ERR("Wrong/missing parameter");
743 return CKR_ARGUMENTS_BAD;
744 }
745
747 if (slot == NULL) {
748 DBG_ERR("Invalid slot ID %lu", slotID);
749 return CKR_SLOT_ID_INVALID;
750 }
751
752 if (get_mechanism_info(slot, type, pInfo) == false) {
753 DBG_ERR("Invalid mechanism %lu", type);
755 } else {
756 DOUT;
757 }
758
759 release_slot(&g_ctx, slot);
760
761 return rv;
762}
763
764CK_DEFINE_FUNCTION(CK_RV, C_InitToken)
767
768 DIN;
769
774
775 DOUT;
777}
778
779CK_DEFINE_FUNCTION(CK_RV, C_InitPIN)
781
782 DIN;
783
785 UNUSED(pPin);
787
788 DOUT;
790}
791
792CK_DEFINE_FUNCTION(CK_RV, C_SetPIN)
795
796 DIN;
797
803
804 DOUT;
806}
807
808CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)
809(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY Notify,
811
812 DIN; // TODO(adma): check pApplication and Notify
813
814 CK_RV rv = CKR_OK;
815
818
819 if (g_yh_initialized == false) {
820 DBG_ERR("libyubihsm is not initialized or already finalized");
822 }
823
824 if (phSession == NULL) {
825 DBG_ERR("Wrong/Missing parameter");
826 return CKR_ARGUMENTS_BAD;
827 }
828
829 if ((flags & CKF_SERIAL_SESSION) == 0) {
830 // NOTE(adma): required by specs
831 DBG_ERR("Open session called without CKF_SERIAL_SESSION set");
833 }
834
836 if (slot == NULL) {
837 DBG_ERR("Invalid slot ID %lu", slotID);
838 return CKR_SLOT_ID_INVALID;
839 }
840
841 if (yh_connector_has_device(slot->connector) == false) {
842 DBG_ERR("Slot %lu has no token inserted", slotID);
844 goto c_os_out;
845 }
846
847 // NOTE(adma): we have already checked that the connector is
848 // connectable at this point. This function should only "allocate" a
849 // session pointer
850
852 DBG_ERR("Connector %lu has too many open sessions", slotID);
854 goto c_os_out;
855 }
856
857 DBG_INFO("Allocated session %lu", *phSession);
858
859 DOUT;
860
861c_os_out:
862
863 release_slot(&g_ctx, slot);
864
865 return rv;
866}
867
868CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)(CK_SESSION_HANDLE hSession) {
869
870 DIN;
871
872 if (g_yh_initialized == false) {
873 DBG_ERR("libyubihsm is not initialized or already finalized");
875 }
876
879 if (rv == CKR_OK) {
880 if (session->slot->pkcs11_sessions.length == 1) {
881 // NOTE: if this is the last session and is authenticated we need to
882 // de-auth
884 DBG_ERR("Failed closing device session, continuing");
885 }
886
888 DBG_ERR("Failed destroying session");
889 // TODO: should we handle the error cases here better?
890 }
891 session->slot->device_session = NULL;
892 }
893
894 release_session(&g_ctx, session);
895 } else if (rv == CKR_SESSION_HANDLE_INVALID) {
896 // BUG(thorduri): piggybacking off of the validation in get_session()
897 // above, which might not hold forever.
898 DBG_ERR("Trying to close invalid session");
900 }
901
902 if (session) {
904 }
905 if (delete_session(&g_ctx, &hSession) == false) {
906 DBG_ERR("Trying to close invalid session");
908 }
909
910 DBG_INFO("Closing session %lu", hSession);
911
912 DOUT;
913 return CKR_OK;
914}
915
916CK_DEFINE_FUNCTION(CK_RV, C_CloseAllSessions)(CK_SLOT_ID slotID) {
917
918 DIN;
919
920 CK_RV rv = CKR_OK;
921
922 if (g_yh_initialized == false) {
923 DBG_ERR("libyubihsm is not initialized or already finalized");
925 }
926
928 if (slot == NULL) {
929 DBG_ERR("Invalid slot");
930 return CKR_SLOT_ID_INVALID;
931 }
932
933 DBG_INFO("Closing all sessions for slot %lu", slotID);
934
935 if (slot->device_session) {
937 DBG_ERR("Failed closing device session, continuing");
938 }
940 // TODO: handle or ignore these errrors?
941 DBG_ERR("Failed destroying device session");
942 }
943 slot->device_session = NULL;
944 }
945
948
949 release_slot(&g_ctx, slot);
950
951 DOUT;
952 return rv;
953}
954
955CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)
956(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo) {
957
958 DIN;
959
960 CK_RV rv = CKR_OK;
961
962 if (g_yh_initialized == false) {
963 DBG_ERR("libyubihsm is not initialized or already finalized");
965 }
966
967 if (pInfo == NULL) {
968 DBG_ERR("Wrong/Missing parameter");
969 return CKR_ARGUMENTS_BAD;
970 }
971
973 CK_RV ret = get_session(&g_ctx, hSession, &session, 0);
974 if (ret != CKR_OK) {
975 DBG_ERR("Session handle invalid");
976 return ret;
977 }
978
979 pInfo->slotID = session->slot->id;
980
981 pInfo->flags = 0;
985 break;
986
990 break;
991
994 break;
995
999 break;
1000
1001 default:
1002 DBG_ERR("Unknown session %lu", hSession);
1004 }
1005
1007 pInfo->ulDeviceError = 0;
1008
1009 if (rv == CKR_OK) {
1010 DOUT;
1011 }
1012
1013 release_session(&g_ctx, session);
1014
1015 return rv;
1016}
1017
1018CK_DEFINE_FUNCTION(CK_RV, C_GetOperationState)
1021
1022 DIN;
1023
1027
1028 DOUT;
1030}
1031
1032CK_DEFINE_FUNCTION(CK_RV, C_SetOperationState)
1033(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState,
1035 CK_OBJECT_HANDLE hAuthenticationKey) {
1036
1037 DIN;
1038
1044
1045 DOUT;
1047}
1048
1049static void login_sessions(void *data) {
1051 switch (session->session_state) {
1054 break;
1057 break;
1060 break;
1061 }
1062}
1063
1064static void logout_sessions(void *data) {
1066 switch (session->session_state) {
1069 break;
1072 break;
1075 break;
1076 }
1077}
1078
1079CK_DEFINE_FUNCTION(CK_RV, C_Login)
1080(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin,
1082
1083 DIN;
1084
1085 CK_RV rv = CKR_OK;
1086
1087 if (g_yh_initialized == false) {
1088 DBG_ERR("libyubihsm is not initialized or already finalized");
1090 }
1091
1093 DBG_ERR("Inalid user type, only regular user allowed");
1094 return CKR_USER_TYPE_INVALID;
1095 }
1096
1099 DBG_ERR("Wrong PIN length, must be [%d, %d] got %lu",
1101 return CKR_ARGUMENTS_BAD;
1102 }
1103
1105
1106 if (parse_hex(pPin, 4, (uint8_t *) &key_id) == false) {
1107 DBG_ERR(
1108 "PIN contains invalid characters, first four digits must be [0-9A-Fa-f]");
1109 return CKR_PIN_INCORRECT;
1110 }
1111
1112 key_id = ntohs(key_id);
1113
1114 pPin += 4;
1115 ulPinLen -= 4;
1116
1119 if (rv != CKR_OK) {
1120 DBG_ERR("Invalid session ID: %lu", hSession);
1121 return rv;
1122 }
1123
1124 yh_rc yrc;
1125 yrc =
1127 true, &session->slot->device_session);
1128 if (yrc != YHR_SUCCESS) {
1129 DBG_ERR("Failed to create session: %s", yh_strerror(yrc));
1132 } else {
1134 }
1135 goto c_l_out;
1136 }
1137
1139 if (yrc != YHR_SUCCESS) {
1140 DBG_ERR("Failed to authenticate session: %s", yh_strerror(yrc));
1143 } else {
1145 }
1146 goto c_l_out;
1147 }
1148
1149 list_iterate(&session->slot->pkcs11_sessions, login_sessions);
1150
1151 DOUT;
1152
1153c_l_out:
1154
1155 release_session(&g_ctx, session);
1156
1157 return rv;
1158}
1159
1160CK_DEFINE_FUNCTION(CK_RV, C_Logout)(CK_SESSION_HANDLE hSession) {
1161
1162 DIN;
1163
1164 CK_RV rv = CKR_OK;
1165
1166 if (g_yh_initialized == false) {
1167 DBG_ERR("libyubihsm is not initialized or already finalized");
1169 }
1170
1173 if (rv != CKR_OK) {
1174 DBG_ERR("Invalid session ID: %lu", hSession);
1175 return rv;
1176 }
1177
1179 DBG_ERR("Failed closing session");
1181 goto c_l_out;
1182 }
1183
1185 DBG_ERR("Failed destroying session");
1187 goto c_l_out;
1188 }
1189
1190 session->slot->device_session = NULL;
1191
1192 list_iterate(&session->slot->pkcs11_sessions, logout_sessions);
1193
1194 DOUT;
1195
1196c_l_out:
1197
1198 release_session(&g_ctx, session);
1199
1200 return rv;
1201}
1202
1203CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)
1206
1207 DIN;
1208
1209 CK_RV rv = CKR_OK;
1210
1211 if (g_yh_initialized == false) {
1212 DBG_ERR("libyubihsm is not initialized or already finalized");
1214 }
1215
1216 if (pTemplate == NULL || ulCount == 0 || phObject == NULL) {
1217 DBG_ERR("Called with invalid parameters: pTemplate=%p ulCount=%lu "
1218 "phObject=%p",
1219 (void *) pTemplate, ulCount, (void *) phObject);
1220 return CKR_ARGUMENTS_BAD;
1221 }
1222
1225 if (rv != CKR_OK) {
1226 DBG_ERR("Invalid session ID: %lu", hSession);
1227 return rv;
1228 }
1229
1231 DBG_ERR("A different operation is already active");
1233 goto c_co_out;
1234 }
1235
1236 struct {
1237 bool set;
1239 } class, key_type, id;
1240 class.set = key_type.set = id.set = false;
1241 class.d = key_type.d = id.d = 0;
1243 memset(&template, 0, sizeof(template));
1244
1245 for (CK_ULONG i = 0; i < ulCount; i++) {
1246 switch (pTemplate[i].type) {
1247 case CKA_CLASS:
1248 if (class.set == false) {
1249 class.d = *((CK_ULONG_PTR) pTemplate[i].pValue);
1250 class.set = true;
1251 } else {
1253 goto c_co_out;
1254 }
1255 break;
1256
1257 case CKA_KEY_TYPE:
1258 if (key_type.set == false) {
1259 key_type.d = *((CK_ULONG_PTR) pTemplate[i].pValue);
1260 key_type.set = true;
1261 } else {
1263 goto c_co_out;
1264 }
1265 break;
1266
1267 case CKA_ID:
1268 if (id.set == false) {
1269 id.d = parse_id_value(pTemplate[i].pValue, pTemplate[i].ulValueLen);
1270 if (id.d == (CK_ULONG) -1) {
1272 goto c_co_out;
1273 }
1274 id.set = true;
1275 } else {
1277 goto c_co_out;
1278 }
1279 break;
1280
1281 case CKA_LABEL:
1282 if (pTemplate[i].ulValueLen > YH_OBJ_LABEL_LEN) {
1284 goto c_co_out;
1285 }
1286
1287 memcpy(template.label, pTemplate[i].pValue, pTemplate[i].ulValueLen);
1288
1289 break;
1290
1291 case CKA_EXTRACTABLE:
1292 if ((rv = set_template_attribute(&template.exportable,
1293 pTemplate[i].pValue)) != CKR_OK) {
1294 goto c_co_out;
1295 }
1296 }
1297 }
1298
1299 if (class.set == false) {
1301 goto c_co_out;
1302 }
1303
1304 template.id = id.d;
1307 uint8_t type;
1309
1310 if (template.exportable == ATTRIBUTE_TRUE) {
1311 rc = yh_string_to_capabilities("exportable-under-wrap", &capabilities);
1312 if (rc != YHR_SUCCESS) {
1313 DBG_ERR("Failed setting exportable-under-wrap capability");
1315 goto c_co_out;
1316 }
1317 }
1318
1319 if (class.d == CKO_PRIVATE_KEY) {
1320 if (key_type.set == false) {
1322 goto c_co_out;
1323 }
1324 type = YH_ASYMMETRIC_KEY;
1325 if (key_type.d == CKK_RSA) {
1326 rv = parse_rsa_template(pTemplate, ulCount, &template);
1327 if (rv != CKR_OK) {
1328 goto c_co_out;
1329 }
1330
1331 DBG_INFO("parsed RSA key, algorithm: %d, objlen: %d", template.algorithm,
1332 template.objlen);
1333
1334 if (template.sign == ATTRIBUTE_TRUE) {
1335 rc = yh_string_to_capabilities("sign-pkcs,sign-pss", &capabilities);
1336 if (rc != YHR_SUCCESS) {
1338 goto c_co_out;
1339 }
1340 }
1341
1342 if (template.decrypt == ATTRIBUTE_TRUE) {
1343 rc =
1344 yh_string_to_capabilities("decrypt-pkcs,decrypt-oaep", &capabilities);
1345 if (rc != YHR_SUCCESS) {
1347 goto c_co_out;
1348 }
1349 }
1350
1352 template.label, 0xffff, &capabilities,
1353 template.algorithm, template.obj.rsa.p,
1354 template.obj.rsa.q) != YHR_SUCCESS) {
1355 DBG_ERR("Failed writing RSA key to device");
1357 goto c_co_out;
1358 }
1359 } else if (key_type.d == CKK_EC) {
1360 rv = parse_ec_template(pTemplate, ulCount, &template);
1361 if (rv != CKR_OK) {
1362 goto c_co_out;
1363 }
1364
1365 DBG_INFO("parsed EC key, algorithm: %d, objlen: %d", template.algorithm,
1366 template.objlen);
1367
1368 if (template.sign == ATTRIBUTE_TRUE) {
1369 rc = yh_string_to_capabilities("sign-ecdsa", &capabilities);
1370 if (rc != YHR_SUCCESS) {
1372 goto c_co_out;
1373 }
1374 }
1375
1376 if (template.derive == ATTRIBUTE_TRUE) {
1377 rc = yh_string_to_capabilities("derive-ecdh", &capabilities);
1378 if (rc != YHR_SUCCESS) {
1380 goto c_co_out;
1381 }
1382 }
1383
1385 template.label, 0xffff, &capabilities,
1386 template.algorithm,
1387 template.obj.buf) != YHR_SUCCESS) {
1388 DBG_ERR("Failed writing EC key to device");
1390 goto c_co_out;
1391 }
1392 } else {
1394 goto c_co_out;
1395 }
1396 } else if (class.d == CKO_SECRET_KEY) {
1397 if (key_type.set == false) {
1399 goto c_co_out;
1400 }
1403 type = YH_HMAC_KEY;
1404 rv = parse_hmac_template(pTemplate, ulCount, &template, false);
1405 if (rv != CKR_OK) {
1406 goto c_co_out;
1407 }
1408
1409 DBG_INFO("parsed HMAC key, algorithm: %d, objlen: %d", template.algorithm,
1410 template.objlen);
1411
1412 if (template.sign == ATTRIBUTE_TRUE) {
1413 rc = yh_string_to_capabilities("sign-hmac", &capabilities);
1414 if (rc != YHR_SUCCESS) {
1416 goto c_co_out;
1417 }
1418 }
1419
1420 if (template.verify == ATTRIBUTE_TRUE) {
1421 rc = yh_string_to_capabilities("verify-hmac", &capabilities);
1422 if (rc != YHR_SUCCESS) {
1424 goto c_co_out;
1425 }
1426 }
1427
1429 template.label, 0xffff, &capabilities,
1430 template.algorithm, template.obj.buf,
1431 template.objlen) != YHR_SUCCESS) {
1432 DBG_ERR("Failed writing HMAC key to device");
1434 goto c_co_out;
1435 }
1436 } else if (key_type.d == CKK_YUBICO_AES128_CCM_WRAP ||
1439 yh_algorithm algo = key_type.d & 0xff;
1440 type = YH_WRAP_KEY;
1441 rv = parse_wrap_template(pTemplate, ulCount, &template, false);
1442 if (rv != CKR_OK) {
1443 goto c_co_out;
1444 }
1445
1446 DBG_INFO("parsed WRAP key, objlen: %d", template.objlen);
1447
1448 if (template.wrap == ATTRIBUTE_TRUE) {
1449 rc = yh_string_to_capabilities("export-wrapped", &capabilities);
1450 if (rc != YHR_SUCCESS) {
1452 goto c_co_out;
1453 }
1454 }
1455
1456 if (template.unwrap == ATTRIBUTE_TRUE) {
1457 rc = yh_string_to_capabilities("import-wrapped", &capabilities);
1458 if (rc != YHR_SUCCESS) {
1460 goto c_co_out;
1461 }
1462 }
1463
1464 if (template.encrypt == ATTRIBUTE_TRUE) {
1465 rc = yh_string_to_capabilities("wrap-data", &capabilities);
1466 if (rc != YHR_SUCCESS) {
1468 goto c_co_out;
1469 }
1470 }
1471
1472 if (template.decrypt == ATTRIBUTE_TRUE) {
1473 rc = yh_string_to_capabilities("unwrap-data", &capabilities);
1474 if (rc != YHR_SUCCESS) {
1476 goto c_co_out;
1477 }
1478 }
1479
1481 if (rc != YHR_SUCCESS) {
1483 goto c_co_out;
1484 }
1485
1487 template.label, 0xffff, &capabilities, algo,
1488 &delegated_capabilities, template.obj.buf,
1489 template.objlen) != YHR_SUCCESS) {
1490 DBG_ERR("Failed writing WRAP key to device");
1492 goto c_co_out;
1493 }
1494 } else {
1495 DBG_ERR("Unknown key_type: %lx", key_type.d);
1497 goto c_co_out;
1498 }
1499 } else if (class.d == CKO_CERTIFICATE || class.d == CKO_DATA) {
1500 yh_algorithm algo;
1501 type = YH_OPAQUE;
1502 if (class.d == CKO_CERTIFICATE) {
1504 } else {
1505 algo = YH_ALGO_OPAQUE_DATA;
1506 }
1507 for (CK_ULONG i = 0; i < ulCount; i++) {
1508 switch (pTemplate[i].type) {
1509 case CKA_VALUE:
1510 if (template.obj.buf == NULL) {
1511 template.obj.buf = (CK_BYTE_PTR) pTemplate[i].pValue;
1512 template.objlen = pTemplate[i].ulValueLen;
1513 DBG_INFO("Object will be stored with length %d", template.objlen);
1514 } else {
1515 DBG_ERR("Object buffer already set");
1517 goto c_co_out;
1518 }
1519 break;
1521 if (algo != YH_ALGO_OPAQUE_X509_CERTIFICATE ||
1522 *(CK_CERTIFICATE_TYPE *) pTemplate[i].pValue != CKC_X_509) {
1523 DBG_ERR("Certificate type invalid");
1525 goto c_co_out;
1526 }
1527 break;
1528 }
1529 }
1530
1532 template.label, 0xffff, &capabilities, algo,
1533 template.obj.buf,
1534 template.objlen) != YHR_SUCCESS) {
1535 DBG_ERR("Failed writing Opaque object to device");
1537 goto c_co_out;
1538 }
1539 } else {
1542 }
1543
1546 &object) != YHR_SUCCESS) {
1547 DBG_ERR("Failed executing get object info after creating");
1549 goto c_co_out;
1550 }
1551 *phObject = object.sequence << 24 | object.type << 16 | object.id;
1552
1553 DBG_INFO("Created object %08lx", *phObject);
1554
1555 DOUT;
1556
1558
1559 release_session(&g_ctx, session);
1560
1561 return rv;
1562}
1563
1564CK_DEFINE_FUNCTION(CK_RV, C_CopyObject)
1565(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
1568
1569 DIN;
1570
1576
1577 DOUT;
1579}
1580
1581CK_DEFINE_FUNCTION(CK_RV, C_DestroyObject)
1582(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) {
1583
1584 DIN;
1585
1586 CK_RV rv = CKR_OK;
1587
1588 if (g_yh_initialized == false) {
1589 DBG_ERR("libyubihsm is not initialized or already finalized");
1591 }
1592
1595 if (rv != CKR_OK) {
1596 DBG_ERR("Invalid session ID %lu", hSession);
1597 return rv;
1598 }
1599
1601 DBG_ERR("Other operation in progress");
1603 goto c_do_out;
1604 }
1605
1606 int type = hObject >> 16;
1607
1608 if (type == ECDH_KEY_TYPE) {
1609 ListItem *item =
1610 list_get(&session->ecdh_session_keys, &hObject, compare_ecdh_keys);
1611 if (item) {
1613 DBG_INFO("Deleted ECDH session key %08lx", hObject);
1614 } else {
1615 DBG_INFO("No ECDH session key with ID %08lx was found", hObject);
1616 }
1617 } else {
1618 if (((uint8_t)(hObject >> 16)) == YH_PUBLIC_KEY) {
1619 DBG_INFO("Trying to delete public key, returning success with noop");
1620 goto c_do_out;
1621 }
1622
1625 hObject);
1626 if (object == NULL) {
1627 DBG_ERR("Object not found");
1629 goto c_do_out;
1630 }
1631
1633 object->object.type) != YHR_SUCCESS) {
1634 DBG_ERR("Failed deleting object");
1636 goto c_do_out;
1637 }
1638
1639 DBG_INFO("Deleted object %08lx", hObject);
1641 }
1642
1643 DOUT;
1644
1645c_do_out:
1646
1647 release_session(&g_ctx, session);
1648
1649 return rv;
1650}
1651
1652CK_DEFINE_FUNCTION(CK_RV, C_GetObjectSize)
1653(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize) {
1654
1655 DIN;
1656
1657 CK_RV rv = CKR_OK;
1658
1659 if (g_yh_initialized == false) {
1660 DBG_ERR("libyubihsm is not initialized or already finalized");
1662 }
1663
1664 if (pulSize == NULL) {
1665 return CKR_ARGUMENTS_BAD;
1666 }
1667
1670 if (rv != CKR_OK) {
1671 DBG_ERR("Unknown session %lu", hSession);
1672 return rv;
1673 }
1674
1675 int type = hObject >> 16;
1676
1677 if (type == ECDH_KEY_TYPE) {
1678 ListItem *item =
1679 list_get(&session->ecdh_session_keys, &hObject, compare_ecdh_keys);
1680 if (item) {
1681 ecdh_session_key *key = (ecdh_session_key *) item->data;
1682 *pulSize = key->len;
1683
1684 DOUT;
1685 } else {
1687 }
1688 } else {
1691 hObject);
1692 if (object == NULL) {
1694 } else {
1695 *pulSize = object->object.len;
1696
1697 DOUT;
1698 }
1699 }
1700 release_session(&g_ctx, session);
1701
1702 return rv;
1703}
1704
1705CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)
1706(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
1708
1709 DIN;
1710
1711 CK_RV rv = CKR_OK;
1712
1713 if (g_yh_initialized == false) {
1714 DBG_ERR("libyubihsm is not initialized or already finalized");
1716 }
1717
1718 if (pTemplate == NULL || ulCount == 0) {
1719 return CKR_ARGUMENTS_BAD;
1720 }
1721
1724 if (rv != CKR_OK) {
1725 DBG_ERR("Unknown session %lu", hSession);
1726 return rv;
1727 }
1728
1729 DBG_INFO("For object %08lx", hObject);
1730
1731 int type = hObject >> 16;
1732
1733 if (type == ECDH_KEY_TYPE) {
1734 bool object_found = false;
1735 ListItem *item =
1736 list_get(&session->ecdh_session_keys, &hObject, compare_ecdh_keys);
1737 if (item) {
1738 object_found = true;
1739 DBG_INFO("Object is an ECDH key available only in the current session. "
1740 "Key id: 0x%lx",
1741 hObject);
1742 ecdh_session_key *key = (ecdh_session_key *) item->data;
1743 rv = populate_template(type, key, pTemplate, ulCount,
1745 }
1746
1747 if ((rv == CKR_OK) && !object_found) {
1748 DBG_ERR("Unable to retrieve session ECDH key with ID: %08lx", hObject);
1750 goto c_gav_out;
1751 } else if (rv != CKR_OK) {
1752 goto c_gav_out;
1753 }
1754
1755 } else {
1758 hObject);
1759
1760 if (object == NULL) {
1761 DBG_ERR("Unable to retrieve object");
1763 goto c_gav_out;
1764 }
1765
1766 rv = populate_template(type, object, pTemplate, ulCount,
1768 if (rv != CKR_OK) {
1769 goto c_gav_out;
1770 }
1771 }
1772
1773 DOUT;
1774
1775c_gav_out:
1776
1777 release_session(&g_ctx, session);
1778
1779 return rv;
1780}
1781
1782CK_DEFINE_FUNCTION(CK_RV, C_SetAttributeValue)
1783(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
1785
1786 DIN;
1787
1789
1790 if (g_yh_initialized == false) {
1791 DBG_ERR("libyubihsm is not initialized or already finalized");
1793 }
1794
1795 if (pTemplate == NULL || ulCount == 0) {
1796 DBG_ERR("Called with invalid parameters: pTemplate=%p ulCount=%lu",
1797 (void *) pTemplate, ulCount);
1798 return CKR_ARGUMENTS_BAD;
1799 }
1800
1802 rv = get_session(&g_ctx, hSession, &session, 0);
1803 if (rv != CKR_OK) {
1804 DBG_ERR("Unknown session %lu", hSession);
1805 return rv;
1806 }
1807
1808 int type = hObject >> 16;
1809 if (type == ECDH_KEY_TYPE) {
1810 DBG_INFO("Refusing to change attributes of an ECDH session key");
1812 goto c_sav_out;
1813 }
1814
1817 hObject);
1818 if (object == NULL) {
1819 DBG_ERR("Unable to retrieve object");
1821 goto c_sav_out;
1822 }
1823
1824 for (CK_ULONG i = 0; i < ulCount; i++) {
1825 switch (pTemplate[i].type) {
1826 case CKA_ID: {
1827 int new_id =
1828 parse_id_value(pTemplate[i].pValue, pTemplate[i].ulValueLen);
1829 if (new_id != object->object.id) {
1830 DBG_INFO("Refusing to change id of object (old:%x, new:%x",
1831 object->object.id, new_id);
1833 goto c_sav_out;
1834 }
1835 } break;
1836
1837 case CKA_LABEL:
1838 if (pTemplate[i].ulValueLen != strlen(object->object.label) ||
1839 memcmp(pTemplate[i].pValue, object->object.label,
1840 pTemplate[i].ulValueLen) != 0) {
1841 DBG_INFO("Refusing to change label of object");
1843 goto c_sav_out;
1844 }
1845 break;
1846
1847 default:
1848 DBG_INFO("Refusing to change attribute %lx of object",
1849 pTemplate[i].type);
1851 goto c_sav_out;
1852 }
1853 }
1854
1855 DOUT;
1856c_sav_out:
1857 release_session(&g_ctx, session);
1858
1859 return rv;
1860}
1861
1862static bool should_include_sessionkeys(bool is_secret_key, bool extractable_set,
1863 bool is_extractable, int object_id) {
1864 if (object_id != 0) {
1865 // Searching for a specific keys
1866 return false;
1867 }
1868 if (!is_secret_key) {
1869 return false;
1870 }
1871 if (extractable_set && !is_extractable) {
1872 return false;
1873 }
1874 return true;
1875}
1876
1877CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)
1878(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) {
1879
1880 DIN;
1881
1882 CK_RV rv = CKR_OK;
1883 char *label = NULL;
1884
1885 if (g_yh_initialized == false) {
1886 DBG_ERR("libyubihsm is not initialized or already finalized");
1888 }
1889
1890 if (ulCount != 0 && pTemplate == NULL) {
1891 DBG_ERR("Asking for specific objects but no template given");
1892 return CKR_ARGUMENTS_BAD;
1893 }
1894
1896 rv = get_session(&g_ctx, hSession, &session, 0);
1897 if (rv != CKR_OK) {
1898 DBG_ERR("Unknown session %lu", hSession);
1899 return rv;
1900 }
1901
1903 DBG_ERR("Another operation is already active %d", session->operation.type);
1905 goto c_foi_out;
1906 }
1907
1910
1912 rv = CKR_OK;
1913 // NOTE: we need to take extra care here, we're lying about the operation
1914 // being succesful, so we need to setup the internal state correctly as
1915 // well.
1918 DOUT;
1919 goto c_foi_out;
1920 }
1921
1922 yh_rc rc;
1923
1924 int id = 0;
1925 uint8_t type = 0;
1928 bool pub = false;
1930 bool unknown = false;
1931 bool secret_key = false;
1932 bool extractable_set = false;
1933
1934 DBG_INFO("find with %lu attributes", ulCount);
1935 if (ulCount != 0) {
1936 for (CK_ULONG i = 0; i < ulCount; i++) {
1937 switch (pTemplate[i].type) {
1938 case CKA_ID:
1939 id = parse_id_value(pTemplate[i].pValue, pTemplate[i].ulValueLen);
1940 if (id == -1) {
1941 DBG_ERR("Failed to parse ID from template");
1943 goto c_foi_out;
1944 }
1945 DBG_INFO("id parsed as %x", id);
1946 break;
1947
1948 case CKA_CLASS: {
1949 uint32_t value = *((CK_ULONG_PTR)(pTemplate[i].pValue));
1950 switch (value) {
1951 case CKO_CERTIFICATE:
1952 DBG_INFO("Filtering for certificate");
1953 algorithm =
1954 YH_ALGO_OPAQUE_X509_CERTIFICATE; // TODO: handle other certs?
1955 case CKO_DATA:
1956 type = YH_OPAQUE;
1957 break;
1958
1959 case CKO_PUBLIC_KEY:
1960 pub = true;
1961 type = YH_ASYMMETRIC_KEY;
1962 break;
1963
1964 case CKO_PRIVATE_KEY:
1966 type = YH_ASYMMETRIC_KEY;
1967 break;
1968
1969 case CKO_SECRET_KEY:
1970 secret_key = true;
1971 break;
1972
1973 default:
1974 unknown = true;
1975 DBG_INFO("Asking for unknown class %x, returning empty set",
1976 (uint32_t) pTemplate[i].type);
1977 }
1978 } break;
1979
1980 case CKA_LABEL: {
1981 CK_ULONG len = pTemplate[i].ulValueLen;
1982
1983 if (len > YH_OBJ_LABEL_LEN) {
1984 DBG_ERR("Label value too long, found %lu, maximum is %d", len,
1987 goto c_foi_out;
1988 }
1989
1990 label = calloc(len + 1, sizeof(char));
1991 if (label == NULL) {
1992 DBG_ERR("Unable to allocate label memory");
1994 goto c_foi_out;
1995 }
1996
1997 memcpy(label, pTemplate[i].pValue, len);
1998 } break;
1999
2000 case CKA_SIGN:
2001 if (*((CK_BBOOL *) pTemplate[i].pValue) == CK_TRUE) {
2004 "sign-pkcs,sign-pss,sign-ecdsa,sign-hmac", &capabilities);
2005 if (rc != YHR_SUCCESS) {
2006 DBG_ERR("Failed to parse capabilities: %s", yh_strerror(rc));
2008 goto c_foi_out;
2009 }
2010 }
2011 break;
2012
2013 case CKA_DECRYPT:
2014 if (*((CK_BBOOL *) pTemplate[i].pValue) == CK_TRUE) {
2016 rc =
2017 yh_string_to_capabilities("decrypt-pkcs,decrypt-oaep,derive-ecdh,"
2018 "unwrap-data",
2019 &capabilities);
2020 if (rc != YHR_SUCCESS) {
2021 DBG_ERR("Failed to parse capabilities: %s", yh_strerror(rc));
2023 goto c_foi_out;
2024 }
2025 }
2026 break;
2027
2028 case CKA_ENCRYPT:
2029 if (*((CK_BBOOL *) pTemplate[i].pValue) == CK_TRUE) {
2030 type = YH_WRAP_KEY;
2031 rc = yh_string_to_capabilities("wrap-data", &capabilities);
2032 if (rc != YHR_SUCCESS) {
2033 DBG_ERR("Failed to parse capabilities: %s", yh_strerror(rc));
2035 goto c_foi_out;
2036 }
2037 }
2038 break;
2039
2040 case CKA_WRAP:
2041 if (*((CK_BBOOL *) pTemplate[i].pValue) == CK_TRUE) {
2042 type = YH_WRAP_KEY;
2043 rc = yh_string_to_capabilities("export-wrapped", &capabilities);
2044 if (rc != YHR_SUCCESS) {
2045 DBG_ERR("Failed to parse capabilities: %s", yh_strerror(rc));
2047 goto c_foi_out;
2048 }
2049 }
2050 break;
2051
2052 case CKA_UNWRAP:
2053 if (*((CK_BBOOL *) pTemplate[i].pValue) == CK_TRUE) {
2054 type = YH_WRAP_KEY;
2055 rc = yh_string_to_capabilities("import-wrapped", &capabilities);
2056 if (rc != YHR_SUCCESS) {
2057 DBG_ERR("Failed to parse capabilities: %s", yh_strerror(rc));
2059 goto c_foi_out;
2060 }
2061 }
2062 break;
2063
2064 case CKA_EXTRACTABLE:
2065 extractable_set = true;
2066 if (*((CK_BBOOL *) pTemplate[i].pValue) == CK_TRUE) {
2068 rc =
2069 yh_string_to_capabilities("exportable-under-wrap", &capabilities);
2070 if (rc != YHR_SUCCESS) {
2071 DBG_ERR("Failed to parse capabilities: %s", yh_strerror(rc));
2073 goto c_foi_out;
2074 }
2075 }
2076 break;
2077
2078 case CKA_TOKEN:
2079 case CKA_PRIVATE:
2080 case CKA_SENSITIVE:
2082 case CKA_DESTROYABLE:
2083 case CKA_KEY_TYPE:
2084 case CKA_APPLICATION:
2085 DBG_INFO("Got type %x, ignoring it for results",
2086 (uint32_t) pTemplate[i].type);
2087 break;
2088
2089 default:
2090 unknown = true;
2091 DBG_INFO("Got type %x, returning empty set",
2092 (uint32_t) pTemplate[i].type);
2093 break;
2094 }
2095 }
2096 }
2097
2098 if (unknown == false) {
2099 uint16_t found_objects = 0;
2100 if (secret_key == true) {
2101 // NOTE(adma): looking for a secret key. Get items of all types and filter
2102 // manually
2105 size_t tmp_n_objects = YH_MAX_ITEMS_COUNT + MAX_ECDH_SESSION_KEYS;
2107 &capabilities, algorithm, label, tmp_objects,
2108 &tmp_n_objects);
2109 if (rc != YHR_SUCCESS) {
2110 DBG_ERR("Failed to get object list");
2112 goto c_foi_out;
2113 }
2114
2115 for (uint16_t i = 0; i < tmp_n_objects; i++) {
2116 if (tmp_objects[i].type == YH_WRAP_KEY ||
2117 tmp_objects[i].type == YH_HMAC_KEY) {
2118 memcpy(session->operation.op.find.objects + found_objects,
2119 tmp_objects + i, sizeof(yh_object_descriptor));
2120 found_objects++;
2121 }
2122 }
2123 } else {
2130 if (rc != YHR_SUCCESS) {
2131 DBG_ERR("Failed to get object list");
2133 goto c_foi_out;
2134 }
2135 found_objects = session->operation.op.find.n_objects;
2136
2137 if (pub) {
2138 for (uint16_t i = 0; i < session->operation.op.find.n_objects; i++) {
2140 session->operation.op.find.objects[i].type |= 0x80;
2141 }
2142 }
2143 }
2144 }
2145
2146 if (ulCount == 0 ||
2147 should_include_sessionkeys(secret_key, extractable_set,
2149 id)) {
2150 for (ListItem *item = session->ecdh_session_keys.head; item != NULL;
2151 item = item->next) {
2152 ecdh_session_key *key = (ecdh_session_key *) item->data;
2153
2154 if (label == NULL || strcmp(label, key->label) == 0) {
2155
2157 memset(&desc, 0, sizeof(desc));
2158 desc.id = key->id & 0xffff;
2159 desc.len = key->len;
2160 desc.type = ECDH_KEY_TYPE;
2161 memcpy(desc.label, key->label, strlen(key->label) + 1);
2162
2163 // Add this item/key to the list of found objects
2164 memcpy(session->operation.op.find.objects + found_objects, &desc,
2165 sizeof(yh_object_descriptor));
2166
2167 found_objects++;
2168 }
2169 }
2170 }
2171
2172 session->operation.op.find.n_objects = found_objects;
2173 }
2174
2175 // NOTE: it's important to set the operation type as late as possible so we
2176 // don't leave it set after erroring out.
2179
2180 DOUT;
2181
2182c_foi_out:
2183
2184 if (label != NULL) {
2185 free(label);
2186 label = NULL;
2187 }
2188
2189 release_session(&g_ctx, session);
2190
2191 return rv;
2192}
2193
2194CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)
2195(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject,
2197
2198 DIN;
2199
2200 CK_RV rv = CKR_OK;
2201
2202 if (g_yh_initialized == false) {
2203 DBG_ERR("libyubihsm is not initialized or already finalized");
2205 }
2206
2208 rv = get_session(&g_ctx, hSession, &session, 0);
2209 if (rv != CKR_OK) {
2210 DBG_ERR("Unknown session %lu", hSession);
2211 return rv;
2212 }
2213
2214 if (phObject == NULL || ulMaxObjectCount == 0 || pulObjectCount == NULL) {
2216 goto c_fo_out;
2217 }
2218
2221 goto c_fo_out;
2222 }
2223
2224 DBG_INFO("Can return %lu object(s)", ulMaxObjectCount);
2225
2226 *pulObjectCount = 0;
2227 for (uint16_t i = 0;
2231 yh_object_descriptor *object =
2234 uint32_t id;
2235 switch (object->type) {
2236 case YH_ASYMMETRIC_KEY:
2237 case YH_OPAQUE:
2238 case YH_WRAP_KEY:
2239 case YH_HMAC_KEY:
2240 case YH_PUBLIC_KEY:
2241 id = object->sequence << 24;
2242 id |= object->type << 16;
2243 id |= object->id;
2244 break;
2245 default:
2246 if (object->type == ECDH_KEY_TYPE) {
2247 id = ECDH_KEY_TYPE << 16;
2248 id |= object->id;
2249 } else {
2250 DBG_INFO("Found unknown object type %x, skipping over", object->type);
2251 continue;
2252 }
2253 }
2254
2255 phObject[i++] = id;
2256
2257 *pulObjectCount += 1;
2258
2261 object->type |= 0x80;
2263 DBG_INFO("stepping back");
2264 }
2265
2266 DBG_INFO("Returning object %d as %08x",
2268 }
2269
2270 DBG_INFO("Returning %lu object(s)", *pulObjectCount);
2271
2272 DOUT;
2273
2274c_fo_out:
2275
2276 release_session(&g_ctx, session);
2277
2278 return rv;
2279}
2280
2281CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsFinal)(CK_SESSION_HANDLE hSession) {
2282
2283 DIN;
2284
2285 CK_RV rv = CKR_OK;
2286
2287 if (g_yh_initialized == false) {
2288 DBG_ERR("libyubihsm is not initialized or already finalized");
2290 }
2291
2293 rv = get_session(&g_ctx, hSession, &session, 0);
2294 if (rv != CKR_OK) {
2295 DBG_ERR("Unknown session %lu", hSession);
2296 return rv;
2297 }
2298
2301 goto c_fof_out;
2302 }
2303
2306
2308
2309 DOUT;
2310
2311c_fof_out:
2312
2313 release_session(&g_ctx, session);
2314
2315 return rv;
2316}
2317
2318CK_DEFINE_FUNCTION(CK_RV, C_EncryptInit)
2320 CK_OBJECT_HANDLE hKey) {
2321
2322 DIN;
2323
2324 CK_RV rv = CKR_OK;
2325
2326 if (g_yh_initialized == false) {
2327 DBG_ERR("libyubihsm is not initialized or already finalized");
2329 }
2330
2332 DBG_ERR("Invalid Mechanism");
2333 return CKR_ARGUMENTS_BAD;
2334 }
2335
2338 if (rv != CKR_OK) {
2339 DBG_ERR("Invalid session ID %lu", hSession);
2340 return rv;
2341 }
2342
2344 DBG_ERR("Other operation in progress");
2346 goto c_ei_out;
2347 }
2348
2349 DBG_INFO("Trying to encrypt data with mechanism 0x%04lx and key %08lx",
2351
2352 int type = hKey >> 16;
2353 if (type == ECDH_KEY_TYPE) {
2354 DBG_ERR("Wrong key type");
2356 goto c_ei_out;
2357 }
2358
2361 hKey);
2362
2363 if (object == NULL) {
2364 DBG_ERR("Unable to retrieve object");
2366 goto c_ei_out;
2367 }
2368
2370 DBG_ERR("Encryption mechanism %lu not supported", pMechanism->mechanism);
2372 goto c_ei_out;
2373 }
2375
2376 if (object->object.type != YH_WRAP_KEY) {
2377 DBG_ERR("Wrong key type or algorithm");
2379 goto c_ei_out;
2380 }
2381
2385
2386 DOUT;
2387
2388c_ei_out:
2389 release_session(&g_ctx, session);
2390 return rv;
2391}
2392
2393CK_DEFINE_FUNCTION(CK_RV, C_Encrypt)
2396
2397 DIN;
2398
2399 CK_RV rv = CKR_OK;
2400 bool terminate = true;
2401
2403
2404 if (g_yh_initialized == false) {
2405 DBG_ERR("libyubihsm is not initialized or already finalized");
2407 goto c_e_out;
2408 }
2409
2411 if (rv != CKR_OK) {
2412 DBG_ERR("Invalid session ID %lu", hSession);
2413 goto c_e_out;
2414 }
2415
2417 DBG_ERR("Encryption operation not initialized");
2419 goto c_e_out;
2420 }
2421
2427
2429 DBG_INFO("The size of the data will be %lu", datalen);
2430
2431 if (pEncryptedData == NULL) {
2432 // NOTE: if data is NULL, just return size we'll need
2434 rv = CKR_OK;
2435 terminate = false;
2436
2437 DOUT;
2438 goto c_e_out;
2439 }
2440
2442 DBG_ERR("pulEncryptedDataLen too small, expected = %lu, got %lu)", datalen,
2446 terminate = false;
2447
2449 }
2450
2451 DBG_INFO("Encrypting %lu bytes", ulDataLen);
2453 if (rv != CKR_OK) {
2454 DBG_ERR("Unable to perform encrypt operation step");
2455 goto c_e_out;
2456 }
2457
2460 if (rv != CKR_OK) {
2461 DBG_ERR("Unable to encrypt data");
2462 goto c_e_out;
2463 }
2464
2465 DBG_INFO("Got %lu butes back", *pulEncryptedDataLen);
2466
2467 rv = CKR_OK;
2468
2469 DOUT;
2470
2472 if (session != NULL) {
2473 release_session(&g_ctx, session);
2474 if (terminate == true) {
2476 }
2477 }
2478 return rv;
2479}
2480
2481CK_DEFINE_FUNCTION(CK_RV, C_EncryptUpdate)
2484
2485 DIN;
2486
2487 CK_RV rv = CKR_OK;
2489
2490 if (g_yh_initialized == false) {
2491 DBG_ERR("libyubihsm is not initialized or already finalized");
2493 goto c_eu_out;
2494 }
2495
2497 if (rv != CKR_OK) {
2498 DBG_ERR("Invalid session ID %lu", hSession);
2499 goto c_eu_out;
2500 }
2501
2503 DBG_ERR("Decrypt operation not initialized");
2505 goto c_eu_out;
2506 }
2507
2508 if (pPart == NULL) {
2509 DBG_ERR("No data provided");
2511 goto c_eu_out;
2512 }
2513
2514 DBG_INFO("Encrypt update with %lu bytes", ulPartLen);
2515
2517 if (rv != CKR_OK) {
2518 DBG_ERR("Unable to perform encryption operation step");
2519 goto c_eu_out;
2520 }
2521
2524
2525 DOUT;
2526
2527c_eu_out:
2528 if (session != NULL) {
2529 release_session(&g_ctx, session);
2530 if (rv != CKR_OK) {
2533 }
2534 }
2535
2536 return rv;
2537}
2538
2539CK_DEFINE_FUNCTION(CK_RV, C_EncryptFinal)
2542
2543 DIN;
2544
2545 CK_RV rv = CKR_OK;
2546 bool terminate = true;
2548
2549 if (g_yh_initialized == false) {
2550 DBG_ERR("libyubihsm is not initialized or already finalized");
2552 goto c_ef_out;
2553 }
2554
2556 if (rv != CKR_OK) {
2557 DBG_ERR("Invalid session ID %lu", hSession);
2558 goto c_ef_out;
2559 }
2560
2562 DBG_ERR("Encrypt operation not initialized");
2564 goto c_ef_out;
2565 }
2566
2567 CK_ULONG datalen = 0;
2571 DBG_ERR("Mechanism %lu not supported",
2575 }
2576
2578 DBG_ERR("pulLastEncryptedPartLen too small, data will not fit, expected = "
2579 "%lu, got %lu",
2582
2584 terminate = false;
2585
2586 goto c_ef_out;
2587 }
2588
2589 if (pLastEncryptedPart == NULL) {
2590 // NOTE: should this rather return length and ok?
2591 DBG_ERR("No buffer provided");
2593 goto c_ef_out;
2594 }
2595
2596 rv =
2599
2600 if (rv != CKR_OK) {
2601 DBG_ERR("Unable to encrypt data");
2602 goto c_ef_out;
2603 }
2604
2605 DBG_INFO("Got %lu bytes back", *pulLastEncryptedPartLen);
2606
2607 DOUT;
2608
2610 if (session != NULL) {
2611 release_session(&g_ctx, session);
2612 if (terminate == true) {
2615 }
2616 }
2617
2618 return rv;
2619}
2620
2621CK_DEFINE_FUNCTION(CK_RV, C_DecryptInit)
2622(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
2623 CK_OBJECT_HANDLE hKey) {
2624
2625 DIN;
2626
2627 CK_RV rv = CKR_OK;
2628 EVP_MD_CTX *mdctx = NULL;
2629
2630 if (g_yh_initialized == false) {
2631 DBG_ERR("libyubihsm is not initialized or already finalized");
2633 }
2634
2635 if (pMechanism == NULL) {
2636 DBG_ERR("Invalid Mechanism");
2637 return CKR_ARGUMENTS_BAD;
2638 }
2639
2642 if (rv != CKR_OK) {
2643 DBG_ERR("Invalid session ID %lu", hSession);
2644 return rv;
2645 }
2646
2648 DBG_ERR("Other operation in progress");
2650 goto c_di_out;
2651 }
2652
2653 DBG_INFO("Trying to decrypt data with mechanism 0x%04lx and key %08lx",
2655
2656 int type = hKey >> 16;
2657 if (type == ECDH_KEY_TYPE) {
2658 DBG_ERR("Wrong key type");
2660 goto c_di_out;
2661 }
2662
2665 hKey);
2666
2667 if (object == NULL) {
2668 DBG_ERR("Unable to retrieve object");
2670 goto c_di_out;
2671 }
2672
2674 DBG_ERR("Decryption mechanism %lu not supported", pMechanism->mechanism);
2676 goto c_di_out;
2677 }
2679
2681 yh_is_rsa(object->object.algorithm)) {
2682 DBG_INFO("RSA decryption requested");
2683
2684 size_t key_length;
2686 if (yrc != YHR_SUCCESS) {
2687 DBG_ERR("Unable to get key length: %s", yh_strerror(yrc));
2689 goto c_di_out;
2690 }
2691
2693
2695 if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS)) {
2696 DBG_ERR("Length of mechanism parameters does not match expected value: "
2697 "found %lu, expected %zu",
2698 pMechanism->ulParameterLen, sizeof(CK_RSA_PKCS_OAEP_PARAMS));
2700 goto c_di_out;
2701 }
2702
2704
2705 if (params->source == 0 && params->ulSourceDataLen != 0) {
2706 DBG_ERR("Source parameter empty but sourceDataLen != 0");
2708 goto c_di_out;
2709 } else if (params->source != 0 && params->source != CKZ_DATA_SPECIFIED) {
2710 DBG_ERR("Unknown value in parameter source");
2712 goto c_di_out;
2713 }
2714
2715 switch (params->mgf) {
2716 case CKG_MGF1_SHA1:
2718 break;
2719 case CKG_MGF1_SHA256:
2721 break;
2722 case CKG_MGF1_SHA384:
2724 break;
2725 case CKG_MGF1_SHA512:
2727 break;
2728 default:
2730 goto c_di_out;
2731 };
2732
2733 const EVP_MD *md = NULL;
2734
2735 switch (params->hashAlg) {
2736 case CKM_SHA_1:
2737 md = EVP_sha1();
2738 break;
2739 case CKM_SHA256:
2740 md = EVP_sha256();
2741 break;
2742 case CKM_SHA384:
2743 md = EVP_sha384();
2744 break;
2745 case CKM_SHA512:
2746 md = EVP_sha512();
2747 break;
2748 default:
2750 goto c_di_out;
2751 }
2752 mdctx = EVP_MD_CTX_create();
2753
2754 if (EVP_DigestInit_ex(mdctx, md, NULL) == 0) {
2756 goto c_di_out;
2757 }
2758
2759 if (EVP_DigestUpdate(mdctx, params->pSourceData,
2760 params->ulSourceDataLen) != 1) {
2762 goto c_di_out;
2763 }
2764 if (EVP_DigestFinal_ex(mdctx, session->operation.mechanism.oaep.label,
2765 &session->operation.mechanism.oaep.label_len) !=
2766 1) {
2768 goto c_di_out;
2769 }
2770 } else if (pMechanism->mechanism != CKM_RSA_PKCS) {
2771 DBG_ERR("Mechanism %lu not supported", pMechanism->mechanism);
2773 goto c_di_out;
2774 }
2775 } else if (object->object.type == YH_WRAP_KEY &&
2777 // NOTE: is setup done for the data unwrap?
2778 rv = CKR_OK;
2779 } else {
2782 }
2783
2785
2786 // TODO(adma): check mechanism parameters and key length and key supported
2787 // parameters
2788
2790 if (rv != CKR_OK) {
2791 DBG_ERR("Unable to initialize decryption operation");
2792 goto c_di_out;
2793 }
2794
2796
2797 DOUT;
2798
2800
2801 if (mdctx != NULL) {
2802 EVP_MD_CTX_destroy(mdctx);
2803 }
2804
2805 release_session(&g_ctx, session);
2806
2807 return rv;
2808}
2809
2810CK_DEFINE_FUNCTION(CK_RV, C_Decrypt)
2811(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData,
2813
2814 DIN;
2815
2816 CK_RV rv = CKR_OK;
2817 bool terminate = true;
2818
2820
2821 if (g_yh_initialized == false) {
2822 DBG_ERR("libyubihsm is not initialized or already finalized");
2824 goto c_d_out;
2825 }
2826
2828 if (rv != CKR_OK) {
2829 DBG_ERR("Invalid session ID %lu", hSession);
2830 goto c_d_out;
2831 }
2832
2834 DBG_ERR("Decryption operation not initialized");
2836 goto c_d_out;
2837 }
2838
2839 // NOTE: datalen is just an approximation here since the data is encrypted
2842 datalen = (session->operation.op.decrypt.key_len + 7) / 8 - 11;
2844 datalen = (session->operation.op.decrypt.key_len + 7) / 8 -
2845 session->operation.mechanism.oaep.label_len * 2 - 2;
2846 } else if (session->operation.mechanism.mechanism ==
2849 DBG_ERR("Encrypted data is to short to possibly come from aes-ccm-wrap");
2851 goto c_d_out;
2852 }
2854 } else {
2855 DBG_ERR("Mechanism %lu not supported",
2859 }
2860
2861 DBG_INFO("The size of the data will be %lu", datalen);
2862
2863 if (pData == NULL) {
2864 // NOTE(adma): Just return the size of the data
2866
2867 rv = CKR_OK;
2868 terminate = false;
2869
2870 DOUT;
2871 goto c_d_out;
2872 }
2873
2874 // NOTE: if pData is set we'll go on with decryption no matter what pulDataLen
2875 // is, the user might know more than us about the real data length
2876
2877 // if the operation is already finalized, skip to perform
2879 DBG_INFO("Sending %lu bytes to decrypt", ulEncryptedDataLen);
2880
2883 if (rv != CKR_OK) {
2884 DBG_ERR("Unable to perform decrypt operation step");
2885 goto c_d_out;
2886 }
2887
2889 if (rv != CKR_OK) {
2890 DBG_ERR("Unable to finalize decrypt operation");
2891 goto c_d_out;
2892 }
2893 }
2894
2896
2899 if (rv != CKR_OK) {
2900 DBG_ERR("Unable to decrypt data");
2901 if (rv == CKR_BUFFER_TOO_SMALL) {
2902 terminate = false;
2903 }
2904 goto c_d_out;
2905 }
2906
2907 DBG_INFO("Got %lu bytes back", *pulDataLen);
2908
2909 rv = CKR_OK;
2910
2911 DOUT;
2912
2914 if (session != NULL) {
2915 release_session(&g_ctx, session);
2916 if (terminate == true) {
2919 }
2920 }
2921
2922 return rv;
2923}
2924
2925CK_DEFINE_FUNCTION(CK_RV, C_DecryptUpdate)
2926(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart,
2928
2929 DIN;
2930
2931 CK_RV rv = CKR_OK;
2932
2933 // TODO(adma): somebody should check that this is a proper mult-part
2934 // mechanism/operation
2935
2937
2938 if (g_yh_initialized == false) {
2939 DBG_ERR("libyubihsm is not initialized or already finalized");
2941 goto c_du_out;
2942 }
2943
2945 if (rv != CKR_OK) {
2946 DBG_ERR("Invalid session ID %lu", hSession);
2947 goto c_du_out;
2948 }
2949
2951 DBG_ERR("Decrypt operation not initialized");
2953 goto c_du_out;
2954 }
2955
2956 if (pEncryptedPart == NULL) {
2957 DBG_ERR("No data provided");
2959 goto c_du_out;
2960 }
2961
2962 DBG_INFO("Decrypt update with %lu bytes", ulEncryptedPartLen);
2963
2966 if (rv != CKR_OK) {
2967 DBG_ERR("Unable to perform decryption operation step");
2968 goto c_du_out;
2969 }
2970
2971 // NOTE(adma): we don't really do anything here, just store this current chunk
2972 // of data
2974 *pulPartLen = 0;
2975
2976 DOUT;
2977
2978c_du_out:
2979 if (session != NULL) {
2980 release_session(&g_ctx, session);
2981 if (rv != CKR_OK) {
2984 }
2985 }
2986
2987 return rv;
2988}
2989
2990CK_DEFINE_FUNCTION(CK_RV, C_DecryptFinal)
2991(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart,
2993
2994 DIN;
2995
2996 CK_RV rv = CKR_OK;
2997 bool terminate = true;
2998
3000
3001 if (g_yh_initialized == false) {
3002 DBG_ERR("libyubihsm is not initialized or already finalized");
3004 goto c_df_out;
3005 }
3006
3008 if (rv != CKR_OK) {
3009 DBG_ERR("Invalid session ID %lu", hSession);
3010 goto c_df_out;
3011 }
3012
3014 DBG_ERR("Decrypt operation not initialized");
3016 goto c_df_out;
3017 }
3018
3021 datalen = (session->operation.op.decrypt.key_len + 7) / 8 - 11;
3023 datalen = (session->operation.op.decrypt.key_len + 7) / 8 -
3024 session->operation.mechanism.oaep.label_len * 2 - 2;
3025 } else if (session->operation.mechanism.mechanism ==
3028 DBG_ERR("Encrypted data is to short to possibly come from aes-ccm-wrap");
3030 goto c_df_out;
3031 }
3033 } else {
3034 DBG_ERR("Mechanism %lu not supported",
3038 }
3039
3040 if (pLastPart == NULL) {
3041 DBG_ERR("No buffer provided, length check only");
3043 rv = CKR_OK;
3044 terminate = false;
3045 goto c_df_out;
3046 }
3047
3048 // if it's already finalized, skip to perform
3049 if (session->operation.op.decrypt.finalized == false) {
3051 if (rv != CKR_OK) {
3052 DBG_ERR("Unable to finalize decryption operation");
3053 goto c_df_out;
3054 }
3055 }
3056
3059 if (rv != CKR_OK) {
3060 DBG_ERR("Unable to decrypt data");
3061 if (rv == CKR_BUFFER_TOO_SMALL) {
3062 terminate = false;
3063 }
3064 goto c_df_out;
3065 }
3066
3067 DBG_INFO("Got %lu bytes back", *pulLastPartLen);
3068
3069 DOUT;
3070
3072 if (session != NULL) {
3073 release_session(&g_ctx, session);
3074 if (terminate == true) {
3077 }
3078 }
3079
3080 return rv;
3081}
3082
3083CK_DEFINE_FUNCTION(CK_RV, C_DigestInit)
3084(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism) {
3085
3086 DIN;
3087
3088 CK_RV rv = CKR_OK;
3089
3090 if (g_yh_initialized == false) {
3091 DBG_ERR("libyubihsm is not initialized or already finalized");
3093 }
3094
3095 if (pMechanism == NULL) {
3096 DBG_ERR("Invalid Mechanism");
3097 return CKR_ARGUMENTS_BAD;
3098 }
3099
3101 rv = get_session(&g_ctx, hSession, &session, 0);
3102 if (rv != CKR_OK) {
3103 DBG_ERR("Invalid session ID %lu", hSession);
3104 return rv;
3105 }
3106
3108 DBG_ERR("Other operation in progress");
3110 goto c_di_out;
3111 }
3112
3113 DBG_INFO("Trying to digest data with mechanism 0x%04lx",
3115
3117 DBG_ERR("Digest mechanism %lu not supported", pMechanism->mechanism);
3119 goto c_di_out;
3120 }
3122
3125
3127
3129 if (rv != CKR_OK) {
3130 DBG_ERR("Unable to initialize digest operation");
3131 goto c_di_out;
3132 }
3133
3135
3136 DOUT;
3137
3139
3140 release_session(&g_ctx, session);
3141
3142 return rv;
3143}
3144
3145CK_DEFINE_FUNCTION(CK_RV, C_Digest)
3146(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
3148
3149 DIN;
3150
3151 CK_RV rv = CKR_OK;
3152 bool terminate = true;
3153
3155
3156 if (g_yh_initialized == false) {
3157 DBG_ERR("libyubihsm is not initialized or already finalized");
3159 goto c_d_out;
3160 }
3161
3162 rv = get_session(&g_ctx, hSession, &session, 0);
3163 if (rv != CKR_OK) {
3164 DBG_ERR("Invalid session ID %lu", hSession);
3165 goto c_d_out;
3166 }
3167
3169 DBG_ERR("Digest operation not initialized");
3171 goto c_d_out;
3172 }
3173
3175 DBG_ERR("Another digest operation is already active");
3177 goto c_d_out;
3178 }
3179
3180 if (pulDigestLen == NULL) {
3181 DBG_ERR("Wrong/missing parameter");
3183 goto c_d_out;
3184 }
3185
3186 if (pDigest == NULL) {
3187 // NOTE(adma): Just return the size of the digest
3188 DBG_INFO("The size of the digest will be %lu",
3190
3192
3193 rv = CKR_OK;
3194 terminate = false;
3195
3196 DOUT;
3197 goto c_d_out;
3198 }
3199
3200 if (*pulDigestLen < session->operation.op.digest.digest_len) {
3201 DBG_ERR("pulDigestLen too small, data will not fit, expected = %lu, got "
3202 "%lu",
3204
3206
3208 terminate = false;
3209 goto c_d_out;
3210 }
3211
3212 DBG_INFO("Sending %lu bytes to digest", ulDataLen);
3213
3215 if (rv != CKR_OK) {
3216 DBG_ERR("Unable to perform digest operation step");
3217 goto c_d_out;
3218 }
3219
3221 if (rv != CKR_OK) {
3222 DBG_ERR("Unable to finalize digest operation");
3223 goto c_d_out;
3224 }
3225
3227 (uint16_t *) pulDigestLen); // TODO(adma): too zealous?
3228 // just us a memcpy?
3229 if (rv != CKR_OK) {
3230 DBG_ERR("Unable to digest data");
3231 goto c_d_out;
3232 }
3233
3234 DBG_INFO("Got %lu bytes back", *pulDigestLen);
3235
3236 DOUT;
3237
3239 if (session != NULL) {
3240 release_session(&g_ctx, session);
3241 if (terminate == true) {
3244 }
3245 }
3246
3247 return rv;
3248}
3249
3250CK_DEFINE_FUNCTION(CK_RV, C_DigestUpdate)
3251(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) {
3252
3253 DIN;
3254
3255 CK_RV rv = CKR_OK;
3256
3257 // TODO(adma): somebody should check that this is a proper mult-part
3258 // mechanism/operation
3259
3261
3262 if (g_yh_initialized == false) {
3263 DBG_ERR("libyubihsm is not initialized or already finalized");
3265 goto c_du_out;
3266 }
3267
3268 rv = get_session(&g_ctx, hSession, &session, 0);
3269 if (rv != CKR_OK) {
3270 DBG_ERR("Invalid session ID %lu", hSession);
3271 goto c_du_out;
3272 }
3273
3275 DBG_ERR("Digest operation not initialized");
3277 goto c_du_out;
3278 }
3279
3280 if (pPart == NULL) {
3281 DBG_ERR("No data provided");
3283 goto c_du_out;
3284 }
3285
3286 DBG_INFO("Digest update with %lu bytes", ulPartLen);
3287
3289 if (rv != CKR_OK) {
3290 DBG_ERR("Unable to perform digest operation step");
3291 goto c_du_out;
3292 }
3293
3295
3296 DOUT;
3297
3298c_du_out:
3299 if (session != NULL) {
3300 release_session(&g_ctx, session);
3301 if (rv != CKR_OK) {
3304 }
3305 }
3306
3307 return rv;
3308}
3309
3310CK_DEFINE_FUNCTION(CK_RV, C_DigestKey)
3311(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) {
3312
3313 DIN;
3314
3317
3318 DOUT;
3320}
3321
3322CK_DEFINE_FUNCTION(CK_RV, C_DigestFinal)
3324
3325 DIN;
3326
3327 CK_RV rv = CKR_OK;
3328 bool terminate = true;
3329
3331
3332 if (g_yh_initialized == false) {
3333 DBG_ERR("libyubihsm is not initialized or already finalized");
3335 goto c_df_out;
3336 }
3337
3338 rv = get_session(&g_ctx, hSession, &session, 0);
3339 if (rv != CKR_OK) {
3340 DBG_ERR("Invalid session ID %lu", hSession);
3341 goto c_df_out;
3342 }
3343
3344 if (pulDigestLen == NULL) {
3345 DBG_ERR("Wrong/missing parameter");
3347 goto c_df_out;
3348 }
3349
3351 DBG_ERR("Digest operation not initialized");
3353 goto c_df_out;
3354 }
3355
3356 if (session->operation.op.digest.is_multipart == false) {
3357 DBG_ERR("Another digest operation is already active");
3359 goto c_df_out;
3360 }
3361
3362 if (pDigest == NULL) {
3363 // NOTE(adma): Just return the size of the digest
3364 DBG_INFO("The size of the digest will be %lu",
3366
3368
3369 rv = CKR_OK;
3370 terminate = false;
3371
3372 DOUT;
3373 goto c_df_out;
3374 }
3375
3376 if (*pulDigestLen < session->operation.op.digest.digest_len) {
3377 DBG_ERR("pulDigestLen too small, data will not fit, expected = %lu, got "
3378 "%lu",
3380
3382
3383 terminate = false;
3385 goto c_df_out;
3386 }
3387
3389 if (rv != CKR_OK) {
3390 DBG_ERR("Unable to finalize digest operation");
3391 goto c_df_out;
3392 }
3393
3395 if (rv != CKR_OK) {
3396 DBG_ERR("Unable to digest data");
3397 goto c_df_out;
3398 }
3399
3400 DBG_INFO("Got %lu bytes back", *pulDigestLen);
3401
3402 DOUT;
3403
3405 if (session != NULL) {
3406 release_session(&g_ctx, session);
3407 if (terminate == true) {
3410 }
3411 }
3412
3413 return rv;
3414}
3415
3416CK_DEFINE_FUNCTION(CK_RV, C_SignInit)
3417(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
3418 CK_OBJECT_HANDLE hKey) {
3419
3420 DIN;
3421
3422 CK_RV rv = CKR_OK;
3423
3424 if (g_yh_initialized == false) {
3425 DBG_ERR("libyubihsm is not initialized or already finalized");
3427 }
3428
3429 if (pMechanism == NULL) {
3430 DBG_ERR("Invalid Mechanism");
3431 return CKR_ARGUMENTS_BAD;
3432 }
3433
3436 if (rv != CKR_OK) {
3437 DBG_ERR("Invalid session ID %lu", hSession);
3438 return rv;
3439 }
3440
3442 DBG_ERR("Other operation in progress");
3444 goto c_si_out;
3445 }
3446
3447 DBG_INFO("Trying to sign data with mechanism 0x%04lx and key %08lx",
3449
3450 int type = hKey >> 16;
3451 if (type == ECDH_KEY_TYPE) {
3452 DBG_ERR("Signing using an ECDH session key is not supported");
3454 goto c_si_out;
3455 }
3456
3459 hKey);
3460
3461 if (object == NULL) {
3462 DBG_ERR("Unable to retrieve object");
3464 goto c_si_out;
3465 }
3466
3469 if (yrc != YHR_SUCCESS) {
3470 DBG_ERR("Unable to get key length: %s", yh_strerror(yrc));
3472 goto c_si_out;
3473 }
3474
3476
3478 DBG_ERR("Signing mechanism %lu not supported", pMechanism->mechanism);
3480 goto c_si_out;
3481 }
3483 pMechanism->mechanism; // TODO(adma): also need to check/copy the
3484 // mechanism's parameter, if any
3485
3486 if (object->object.type == YH_ASYMMETRIC_KEY) {
3487 if (yh_is_rsa(object->object.algorithm)) {
3489 true) {
3490 DBG_INFO("RSA signature requested");
3492 (session->operation.op.sign.key_len + 7) / 8;
3494 if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS)) {
3495 DBG_ERR("Length of mechanism parameters does not match expected "
3496 "value, "
3497 "%lu != %zu",
3498 pMechanism->ulParameterLen, sizeof(CK_RSA_PKCS_PSS_PARAMS));
3500 goto c_si_out;
3501 }
3502
3504 // TODO: validate that params->hashAlg matches mechanism
3505
3506 if (params->sLen > 0xffff) {
3507 DBG_ERR("Salt is too big for device");
3509 goto c_si_out;
3510 }
3511 session->operation.mechanism.pss.salt_len = params->sLen;
3512
3513 switch (params->mgf) {
3514 case CKG_MGF1_SHA1:
3516 break;
3517 case CKG_MGF1_SHA256:
3519 break;
3520 case CKG_MGF1_SHA384:
3522 break;
3523 case CKG_MGF1_SHA512:
3525 break;
3526 default:
3528 goto c_si_out;
3529 };
3530 }
3531 } else {
3532 DBG_ERR("Mechanism %lu not supported",
3535 goto c_si_out;
3536 }
3537 } else {
3539 true) {
3540 DBG_INFO("ECDSA signature requested");
3542 ((session->operation.op.sign.key_len + 7) / 8) * 2;
3543 } else {
3544 DBG_ERR("Mechanism %lu not supported",
3547 goto c_si_out;
3548 }
3549 }
3550 } else if (object->object.type == YH_HMAC_KEY) {
3552 true) {
3553 DBG_INFO("HMAC signature requested (len %lu)",
3554 (unsigned long) (key_length / 8));
3556 (session->operation.op.sign.key_len + 7) / 8;
3557 } else {
3558 DBG_ERR("Mechanism %lu not supported",
3561 goto c_si_out;
3562 }
3563 } else {
3566 }
3567
3569 hKey; // TODO(adma): should we store something else rather than the key ID?
3570
3571 // TODO(adma): check mechanism parameters and key length and key supported
3572 // parameters
3573
3575 if (rv != CKR_OK) {
3576 DBG_ERR("Unable to initialize signing operation");
3577 goto c_si_out;
3578 }
3579
3581
3582 DOUT;
3583
3585
3586 release_session(&g_ctx, session);
3587
3588 return rv;
3589}
3590
3591CK_DEFINE_FUNCTION(CK_RV, C_Sign)
3592(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
3594
3595 DIN;
3596
3597 CK_RV rv = CKR_OK;
3598 bool terminate = true;
3599
3601
3602 if (g_yh_initialized == false) {
3603 DBG_ERR("libyubihsm is not initialized or already finalized");
3605 goto c_s_out;
3606 }
3607
3609 if (rv != CKR_OK) {
3610 DBG_ERR("Invalid session ID %lu", hSession);
3611 goto c_s_out;
3612 }
3613
3615 DBG_ERR("Signature operation not initialized");
3617 goto c_s_out;
3618 }
3619
3620 DBG_INFO("The size of the signature will be %u",
3622
3623 if (pSignature == NULL) {
3624 // NOTE(adma): Just return the size of the signature
3626
3627 rv = CKR_OK;
3628 terminate = false;
3629 DOUT;
3630 goto c_s_out;
3631 }
3632
3633 if (*pulSignatureLen < session->operation.op.sign.sig_len) {
3634 DBG_ERR("pulSignatureLen too small, signature will not fit, expected %u, "
3635 "got %lu",
3639 terminate = false;
3641 }
3642
3643 DBG_INFO("Sending %lu bytes to sign", ulDataLen);
3644
3646 if (rv != CKR_OK) {
3647 DBG_ERR("Unable to perform signing operation step");
3648 goto c_s_out;
3649 }
3650
3652 if (rv != CKR_OK) {
3653 DBG_ERR("Unable to finalize signing operation");
3654 goto c_s_out;
3655 }
3656
3658 DBG_INFO("After padding and transformation there are %u bytes",
3660
3663 if (rv != CKR_OK) {
3664 DBG_ERR("Unable to sign data");
3665 goto c_s_out;
3666 }
3667
3668 DBG_INFO("Got %lu bytes back", *pulSignatureLen);
3669
3670 DOUT;
3671
3673 if (session != NULL) {
3674 release_session(&g_ctx, session);
3675 if (terminate == true) {
3678 }
3679 }
3680
3681 return rv;
3682}
3683
3684CK_DEFINE_FUNCTION(CK_RV, C_SignUpdate)
3685(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) {
3686
3687 DIN;
3688
3689 CK_RV rv = CKR_OK;
3690
3691 // TODO(adma): somebody should check that this is a proper mult-part
3692 // mechanism/operation
3693
3695
3696 if (g_yh_initialized == false) {
3697 DBG_ERR("libyubihsm is not initialized or already finalized");
3699 goto c_su_out;
3700 }
3701
3703 if (rv != CKR_OK) {
3704 DBG_ERR("Invalid session ID %lu", hSession);
3705 goto c_su_out;
3706 }
3707
3709 DBG_ERR("Signature operation not initialized");
3711 goto c_su_out;
3712 }
3713
3714 if (pPart == NULL) {
3715 DBG_ERR("No data provided");
3717 goto c_su_out;
3718 }
3719
3720 DBG_INFO("Signature update with %lu bytes", ulPartLen);
3721
3723 if (rv != CKR_OK) {
3724 DBG_ERR("Unable to perform signing operation step");
3725 goto c_su_out;
3726 }
3727
3728 DOUT;
3729
3730c_su_out:
3731 if (session != NULL) {
3732 release_session(&g_ctx, session);
3733 if (rv != CKR_OK) {
3736 }
3737 }
3738
3739 return rv;
3740}
3741
3742CK_DEFINE_FUNCTION(CK_RV, C_SignFinal)
3743(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
3745
3746 DIN;
3747
3748 CK_RV rv = CKR_OK;
3749 bool terminate = false;
3750
3752
3753 if (g_yh_initialized == false) {
3754 DBG_ERR("libyubihsm is not initialized or already finalized");
3756 goto c_sf_out;
3757 }
3758
3760 if (rv != CKR_OK) {
3761 DBG_ERR("Invalid session ID %lu", hSession);
3762 goto c_sf_out;
3763 }
3764
3766 DBG_ERR("Signature operation not initialized");
3768 goto c_sf_out;
3769 }
3770
3771 if (pSignature == NULL) {
3772 DBG_ERR("No buffer provided, length check only");
3774 rv = CKR_OK;
3775 DOUT;
3776 goto c_sf_out;
3777 }
3778
3779 terminate = true;
3780
3782 if (rv != CKR_OK) {
3783 DBG_ERR("Unable to finalize signing operation");
3784 goto c_sf_out;
3785 }
3786
3789 if (rv != CKR_OK) {
3790 DBG_ERR("Unable to sign data");
3791 goto c_sf_out;
3792 }
3793
3794 DBG_INFO("Got %lu bytes back", *pulSignatureLen);
3795
3796 DOUT;
3797
3798c_sf_out:
3799 if (session != NULL) {
3800 release_session(&g_ctx, session);
3801 if (terminate == true) {
3804 }
3805 }
3806
3807 return rv;
3808}
3809
3810CK_DEFINE_FUNCTION(CK_RV, C_SignRecoverInit)
3811(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
3812 CK_OBJECT_HANDLE hKey) {
3813
3814 DIN;
3815
3818 UNUSED(hKey);
3819
3820 DOUT;
3822}
3823
3824CK_DEFINE_FUNCTION(CK_RV, C_SignRecover)
3825(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
3827
3828 DIN;
3829
3835
3836 DOUT;
3838}
3839
3840CK_DEFINE_FUNCTION(CK_RV, C_VerifyInit)
3841(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
3842 CK_OBJECT_HANDLE hKey) {
3843
3844 DIN;
3845
3846 CK_RV rv = CKR_OK;
3847
3848 if (g_yh_initialized == false) {
3849 DBG_ERR("libyubihsm is not initialized or already finalized");
3851 }
3852
3853 if (pMechanism == NULL) {
3854 DBG_ERR("Invalid Mechanism");
3855 return CKR_ARGUMENTS_BAD;
3856 }
3857
3860 if (rv != CKR_OK) {
3861 DBG_ERR("Invalid session ID %lu", hSession);
3862 return rv;
3863 }
3864
3866 DBG_ERR("Other operation in progress");
3868 goto c_vi_out;
3869 }
3870
3871 DBG_INFO("Trying to verify data with mechanism 0x%04lx and key %lx",
3873
3874 int type = hKey >> 16;
3875 if (type == ECDH_KEY_TYPE) {
3876 DBG_ERR("Wrong key type");
3878 goto c_vi_out;
3879 }
3880
3883 hKey);
3884
3885 if (object == NULL) {
3886 DBG_ERR("Unable to retrieve object");
3888 goto c_vi_out;
3889 }
3890
3891 size_t key_length;
3893 if (yrc != YHR_SUCCESS) {
3894 DBG_ERR("Unable to get key length: %s", yh_strerror(yrc));
3896 goto c_vi_out;
3897 }
3898
3900
3902 DBG_ERR("Verification mechanism %lu not supported", pMechanism->mechanism);
3904 goto c_vi_out;
3905 }
3907 pMechanism->mechanism; // TODO(adma): also need to check/copy the
3908 // mechanism's parameter, if any
3909
3910 if (object->object.type == YH_HMAC_KEY) {
3911 DBG_INFO("HMAC verification requested");
3912 } else if (object->object.type == YH_PUBLIC_KEY) {
3913 DBG_INFO("Asymmetric verification requested");
3914 } else {
3917 }
3918
3920
3922 if (rv != CKR_OK) {
3923 DBG_ERR("Unable to initialize verification operation");
3924 goto c_vi_out;
3925 }
3926
3929 if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS)) {
3930 DBG_ERR("Length of mechanism parameters does not match expected value, "
3931 "%lu != %zu",
3932 pMechanism->ulParameterLen, sizeof(CK_RSA_PKCS_PSS_PARAMS));
3934 goto c_vi_out;
3935 }
3936
3937 // TODO: validate that params->hashAlg matches mechanism
3939
3940 session->operation.op.verify.padding = RSA_PKCS1_PSS_PADDING;
3942 switch (params->mgf) {
3943 case CKG_MGF1_SHA1:
3944 session->operation.op.verify.mgf1md = EVP_sha1();
3945 break;
3946 case CKG_MGF1_SHA256:
3947 session->operation.op.verify.mgf1md = EVP_sha256();
3948 break;
3949 case CKG_MGF1_SHA384:
3950 session->operation.op.verify.mgf1md = EVP_sha384();
3951 break;
3952 case CKG_MGF1_SHA512:
3953 session->operation.op.verify.mgf1md = EVP_sha512();
3954 break;
3955 default:
3956 DBG_ERR("Unsupported mgf algorithm: %lu", params->mgf);
3958 goto c_vi_out;
3959 }
3960 switch (params->hashAlg) {
3961 case CKM_SHA_1:
3962 session->operation.op.verify.md = EVP_sha1();
3963 break;
3964 case CKM_SHA256:
3965 session->operation.op.verify.md = EVP_sha256();
3966 break;
3967 case CKM_SHA384:
3968 session->operation.op.verify.md = EVP_sha384();
3969 break;
3970 case CKM_SHA512:
3971 session->operation.op.verify.md = EVP_sha512();
3972 break;
3973 default:
3974 DBG_ERR("Unsupported pss hash algorithm: %lu", params->hashAlg);
3976 goto c_vi_out;
3977 }
3978 } else if (is_PKCS1v1_5_sign_mechanism(
3980 session->operation.op.verify.padding = RSA_PKCS1_PADDING;
3981 }
3982 }
3983
3985
3986 DOUT;
3987
3989
3990 release_session(&g_ctx, session);
3991
3992 return rv;
3993}
3994
3995CK_DEFINE_FUNCTION(CK_RV, C_Verify)
3996(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
3998
3999 DIN;
4000
4001 CK_RV rv = CKR_OK;
4002
4004
4005 if (g_yh_initialized == false) {
4006 DBG_ERR("libyubihsm is not initialized or already finalized");
4008 goto c_v_out;
4009 }
4010
4012 if (rv != CKR_OK) {
4013 DBG_ERR("Invalid session ID %lu", hSession);
4014 goto c_v_out;
4015 }
4016
4017 if (pData == NULL || pSignature == NULL) {
4018 DBG_ERR("Invalid parameters");
4020 goto c_v_out;
4021 }
4022
4024 DBG_ERR("Verification operation not initialized");
4026 goto c_v_out;
4027 }
4028
4032 case CKM_SHA_1_HMAC:
4033 siglen = 20;
4034 break;
4035
4036 case CKM_SHA256_HMAC:
4037 siglen = 32;
4038 break;
4039
4040 case CKM_SHA384_HMAC:
4041 siglen = 48;
4042 break;
4043
4044 case CKM_SHA512_HMAC:
4045 siglen = 64;
4046 break;
4047 default:
4049 goto c_v_out;
4050 }
4052 true) {
4053 siglen = (session->operation.op.verify.key_len + 7) / 8;
4055 siglen = ((session->operation.op.verify.key_len + 7) / 8) * 2;
4056 } else {
4057 DBG_ERR("Mechanism %lu not supported",
4061 }
4062
4064 DBG_ERR("Wrong data length, expected %lu, got %lu", siglen, ulSignatureLen);
4066 goto c_v_out;
4067 }
4068
4070 if (rv != CKR_OK) {
4071 DBG_ERR("Unable to perform verification operation step");
4072 goto c_v_out;
4073 }
4074
4076 if (rv != CKR_OK) {
4077 DBG_ERR("Unable to finalize verification operation");
4078 goto c_v_out;
4079 }
4080
4082
4085 if (rv != CKR_OK) {
4086 DBG_ERR("Unable to verify signature");
4087 goto c_v_out;
4088 }
4089
4090 DBG_INFO("Signature successfully verified");
4091
4092 DOUT;
4093
4095 if (session != NULL) {
4096 release_session(&g_ctx, session);
4099 }
4100
4101 return rv;
4102}
4103
4104CK_DEFINE_FUNCTION(CK_RV, C_VerifyUpdate)
4105(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) {
4106
4107 DIN;
4108
4109 CK_RV rv = CKR_OK;
4110
4111 // TODO(adma): somebody should check that this is a proper mult-part
4112 // mechanism/operation
4113
4115
4116 if (g_yh_initialized == false) {
4117 DBG_ERR("libyubihsm is not initialized or already finalized");
4119 goto c_vu_out;
4120 }
4121
4123 if (rv != CKR_OK) {
4124 DBG_ERR("Invalid session ID %lu", hSession);
4125 goto c_vu_out;
4126 }
4127
4129 DBG_ERR("Verification operation not initialized");
4131 goto c_vu_out;
4132 }
4133
4134 if (pPart == NULL) {
4135 DBG_ERR("No data provided");
4137 goto c_vu_out;
4138 }
4139
4140 DBG_ERR("Verification update with %lu bytes", ulPartLen);
4141
4143 if (rv != CKR_OK) {
4144 DBG_ERR("Unable to perform verification operation step");
4145 goto c_vu_out;
4146 }
4147
4148 DOUT;
4149
4150c_vu_out:
4151 if (session != NULL) {
4152 release_session(&g_ctx, session);
4153 if (rv != CKR_OK) {
4156 }
4157 }
4158
4159 return rv;
4160}
4161
4162CK_DEFINE_FUNCTION(CK_RV, C_VerifyFinal)
4164
4165 DIN;
4166
4167 CK_RV rv = CKR_OK;
4168
4170
4171 if (g_yh_initialized == false) {
4172 DBG_ERR("libyubihsm is not initialized or already finalized");
4174 goto c_vf_out;
4175 }
4176
4178 if (rv != CKR_OK) {
4179 DBG_ERR("Invalid session ID %lu", hSession);
4180 goto c_vf_out;
4181 }
4182
4184 DBG_ERR("Verification operation not initialized");
4186 goto c_vf_out;
4187 }
4188
4189 if (pSignature == NULL) {
4190 DBG_ERR("No buffer provided");
4192 goto c_vf_out;
4193 }
4194
4196 if (rv != CKR_OK) {
4197 DBG_ERR("Unable to finalize verification operation");
4198 goto c_vf_out;
4199 }
4200
4203 if (rv != CKR_OK) {
4204 DBG_ERR("Unable to verify data");
4205 goto c_vf_out;
4206 }
4207
4208 DOUT;
4209
4210c_vf_out:
4211 if (session != NULL) {
4212 release_session(&g_ctx, session);
4215 }
4216
4217 return rv;
4218}
4219
4220CK_DEFINE_FUNCTION(CK_RV, C_VerifyRecoverInit)
4221(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
4222 CK_OBJECT_HANDLE hKey) {
4223
4224 DIN;
4225
4228 UNUSED(hKey);
4229
4230 DOUT;
4232}
4233
4234CK_DEFINE_FUNCTION(CK_RV, C_VerifyRecover)
4237
4238 DIN;
4239
4243 UNUSED(pData);
4245
4246 DOUT;
4248}
4249
4250CK_DEFINE_FUNCTION(CK_RV, C_DigestEncryptUpdate)
4251(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen,
4253
4254 DIN;
4255
4257 UNUSED(pPart);
4261
4262 DOUT;
4264}
4265
4266CK_DEFINE_FUNCTION(CK_RV, C_DecryptDigestUpdate)
4267(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart,
4269
4270 DIN;
4271
4275 UNUSED(pPart);
4277
4278 DOUT;
4280}
4281
4282CK_DEFINE_FUNCTION(CK_RV, C_SignEncryptUpdate)
4283(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen,
4285
4286 DIN;
4287
4289 UNUSED(pPart);
4293
4294 DOUT;
4296}
4297
4298CK_DEFINE_FUNCTION(CK_RV, C_DecryptVerifyUpdate)
4299(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart,
4301
4302 DIN;
4303
4307 UNUSED(pPart);
4309
4310 DOUT;
4312}
4313
4314CK_DEFINE_FUNCTION(CK_RV, C_GenerateKey)
4315(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
4317
4318 DIN;
4319
4320 CK_RV rv = CKR_OK;
4321
4322 if (g_yh_initialized == false) {
4323 DBG_ERR("libyubihsm is not initialized or already finalized");
4325 }
4326
4327 if (pMechanism == NULL || pTemplate == NULL || phKey == NULL) {
4328 DBG_ERR("Invalid argument");
4329 return CKR_ARGUMENTS_BAD;
4330 }
4331
4334 if (rv != CKR_OK) {
4335 DBG_ERR("Invalid session ID: %lu", hSession);
4336 return rv;
4337 }
4338
4340 DBG_ERR("A different operation is already active");
4342 goto c_gk_out;
4343 }
4344
4346 DBG_ERR("Invalid mechanism %lu", pMechanism->mechanism);
4348 goto c_gk_out;
4349 }
4350
4353 struct {
4354 bool set;
4355 CK_ULONG d;
4356 } class, key_type, id;
4357 class.set = key_type.set = id.set = false;
4358 class.d = key_type.d = id.d = 0;
4359
4360 for (CK_ULONG i = 0; i < ulCount; i++) {
4361 switch (pTemplate[i].type) {
4362 case CKA_CLASS:
4363 if (class.set == false) {
4364 class.d = *((CK_ULONG_PTR) pTemplate[i].pValue);
4365 class.set = true;
4366 } else {
4368 goto c_gk_out;
4369 }
4370 break;
4371
4372 case CKA_KEY_TYPE:
4373 if (key_type.set == false) {
4374 key_type.d = *((CK_ULONG_PTR) pTemplate[i].pValue);
4375 key_type.set = true;
4376 } else {
4378 goto c_gk_out;
4379 }
4380 break;
4381
4382 case CKA_ID:
4383 if (id.set == false) {
4384 id.d = parse_id_value(pTemplate[i].pValue, pTemplate[i].ulValueLen);
4385 if (id.d == (CK_ULONG) -1) {
4387 goto c_gk_out;
4388 }
4389 id.set = true;
4390 } else {
4392 goto c_gk_out;
4393 }
4394 break;
4395
4396 case CKA_LABEL:
4397 if (pTemplate[i].ulValueLen > YH_OBJ_LABEL_LEN) {
4399 }
4400
4401 memcpy(template.label, pTemplate[i].pValue, pTemplate[i].ulValueLen);
4402
4403 break;
4404
4405 case CKA_EXTRACTABLE:
4406 if ((rv = set_template_attribute(&template.exportable,
4407 pTemplate[i].pValue)) != CKR_OK) {
4408 return rv;
4409 }
4410 }
4411 }
4412
4413 if (key_type.set == false || class.set == false) {
4415 goto c_gk_out;
4416 }
4417
4418 template.id = id.d;
4421 uint8_t type;
4422 yh_rc rc;
4423
4424 if (template.exportable == ATTRIBUTE_TRUE) {
4425 rc = yh_string_to_capabilities("exportable-under-wrap", &capabilities);
4426 if (rc != YHR_SUCCESS) {
4428 goto c_gk_out;
4429 }
4430 }
4431
4432 if (class.d == CKO_SECRET_KEY) {
4435 type = YH_HMAC_KEY;
4436 rv = parse_hmac_template(pTemplate, ulCount, &template, true);
4437 if (rv != CKR_OK) {
4438 goto c_gk_out;
4439 }
4440
4441 if (template.sign == ATTRIBUTE_TRUE) {
4442 rc = yh_string_to_capabilities("sign-hmac", &capabilities);
4443 if (rc != YHR_SUCCESS) {
4445 goto c_gk_out;
4446 }
4447 }
4448
4449 if (template.verify == ATTRIBUTE_TRUE) {
4450 rc = yh_string_to_capabilities("verify-hmac", &capabilities);
4451 if (rc != YHR_SUCCESS) {
4453 goto c_gk_out;
4454 }
4455 }
4456
4458 template.label, 0xffff, &capabilities,
4459 template.algorithm) != YHR_SUCCESS) {
4460 DBG_ERR("Failed generating HMAC key");
4462 goto c_gk_out;
4463 }
4464 } else if (key_type.d == CKK_YUBICO_AES128_CCM_WRAP ||
4467 yh_algorithm algo = key_type.d & 0xff;
4468 type = YH_WRAP_KEY;
4469 rv = parse_wrap_template(pTemplate, ulCount, &template, true);
4470 if (rv != CKR_OK) {
4471 goto c_gk_out;
4472 }
4473
4474 DBG_INFO("parsed WRAP key, objlen: %d", template.objlen);
4475
4476 if (template.wrap == ATTRIBUTE_TRUE) {
4477 rc = yh_string_to_capabilities("export-wrapped", &capabilities);
4478 if (rc != YHR_SUCCESS) {
4480 goto c_gk_out;
4481 }
4482 }
4483
4484 if (template.unwrap == ATTRIBUTE_TRUE) {
4485 rc = yh_string_to_capabilities("import-wrapped", &capabilities);
4486 if (rc != YHR_SUCCESS) {
4488 goto c_gk_out;
4489 }
4490 }
4491
4493 if (rc != YHR_SUCCESS) {
4495 goto c_gk_out;
4496 }
4497
4499 template.label, 0xffff, &capabilities, algo,
4501 DBG_ERR("Failed generating wrap key");
4503 goto c_gk_out;
4504 }
4505 } else {
4506 DBG_ERR("Unknown key_type: %lx", class.d);
4508 goto c_gk_out;
4509 }
4510 } else {
4513 }
4514
4516 if (yh_util_get_object_info(session->slot->device_session, template.id, type,
4517 &object) != YHR_SUCCESS) {
4518 DBG_ERR("Failed getting new object %04x", template.id);
4520 goto c_gk_out;
4521 }
4522 *phKey = object.sequence << 24 | object.type << 16 | object.id;
4523
4524 DBG_INFO("Created object %08lx", *phKey);
4525
4526 DOUT;
4527
4529
4530 release_session(&g_ctx, session);
4531
4532 return rv;
4533}
4534
4535CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)
4536(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
4540
4541 DIN;
4542
4543 CK_RV rv = CKR_OK;
4544
4546 memset(&template, 0, sizeof(yubihsm_pkcs11_object_template));
4547
4548 if (g_yh_initialized == false) {
4549 DBG_ERR("libyubihsm is not initialized or already finalized");
4551 }
4552
4553 if (pMechanism == NULL || pPublicKeyTemplate == NULL ||
4554 pPrivateKeyTemplate == NULL || phPublicKey == NULL ||
4555 phPrivateKey == NULL) {
4556 DBG_ERR("Invalid argument");
4557 return CKR_ARGUMENTS_BAD;
4558 }
4559
4562 if (rv != CKR_OK) {
4563 DBG_ERR("Invalid session ID: %lu", hSession);
4564 return rv;
4565 }
4566
4568 DBG_ERR("A different operation is already active");
4570 goto c_gkp_out;
4571 }
4572
4579 rv =
4582 ulPrivateKeyAttributeCount, &template);
4583 } else {
4584 DBG_ERR("Invalid mechanism for key generation: %lu", pMechanism->mechanism);
4587 }
4588
4589 if (rv != CKR_OK) {
4590 DBG_ERR("Unable to parse generation template");
4591 goto c_gkp_out;
4592 }
4593
4595 yh_rc rc;
4596
4597 if (template.exportable == ATTRIBUTE_TRUE) {
4598 rc = yh_string_to_capabilities("exportable-under-wrap", &capabilities);
4599 if (rc != YHR_SUCCESS) {
4601 goto c_gkp_out;
4602 }
4603 }
4604
4605 // TODO(adma): check more return values
4606
4607 if (yh_is_rsa(template.algorithm)) {
4608
4609 if (template.sign == ATTRIBUTE_TRUE) {
4610 rc = yh_string_to_capabilities("sign-pkcs,sign-pss", &capabilities);
4611 if (rc != YHR_SUCCESS) {
4613 goto c_gkp_out;
4614 }
4615 }
4616
4617 if (template.decrypt == ATTRIBUTE_TRUE) {
4618 rc =
4619 yh_string_to_capabilities("decrypt-pkcs,decrypt-oaep", &capabilities);
4620 if (rc != YHR_SUCCESS) {
4622 goto c_gkp_out;
4623 }
4624 }
4625
4627 template.label, 0xffff, &capabilities,
4628 template.algorithm);
4629 if (rc != YHR_SUCCESS) {
4630 DBG_ERR("Failed writing RSA key to device");
4632 goto c_gkp_out;
4633 }
4634 } else {
4635
4636 if (template.sign == ATTRIBUTE_TRUE) {
4637 rc = yh_string_to_capabilities("sign-ecdsa", &capabilities);
4638 if (rc != YHR_SUCCESS) {
4640 goto c_gkp_out;
4641 }
4642 }
4643
4644 if (template.derive == ATTRIBUTE_TRUE) {
4645 rc = yh_string_to_capabilities("derive-ecdh", &capabilities);
4646
4647 if (rc != YHR_SUCCESS) {
4649 goto c_gkp_out;
4650 }
4651 }
4652
4654 template.label, 0xffff, &capabilities,
4655 template.algorithm);
4656 if (rc != YHR_SUCCESS) {
4657 DBG_ERR("Failed writing EC key to device");
4659 goto c_gkp_out;
4660 }
4661 }
4662
4665 YH_ASYMMETRIC_KEY, &object) != YHR_SUCCESS) {
4667 goto c_gkp_out;
4668 }
4669 *phPublicKey = object.sequence << 24 | (object.type | 0x80) << 16 | object.id;
4670 *phPrivateKey = object.sequence << 24 | object.type << 16 | object.id;
4671
4672 DOUT;
4673
4675
4676 insecure_memzero(&template, sizeof(template));
4677
4678 release_session(&g_ctx, session);
4679
4680 return rv;
4681}
4682
4683CK_DEFINE_FUNCTION(CK_RV, C_WrapKey)
4684(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
4685 CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey,
4687
4688 DIN;
4689
4690 CK_RV rv = CKR_OK;
4691
4692 if (g_yh_initialized == false) {
4693 DBG_ERR("libyubihsm is not initialized or already finalized");
4695 }
4696
4697 if (pMechanism == NULL || pulWrappedKeyLen == NULL) {
4698 DBG_ERR("Invalid argument");
4699 return CKR_ARGUMENTS_BAD;
4700 }
4701
4704 if (rv != CKR_OK) {
4705 DBG_ERR("Unknown session %lu", hSession);
4706 return rv;
4707 }
4708
4712 DBG_ERR("Wrapping involving ECDH session keys is not supported");
4714 goto c_wk_out;
4715 }
4716
4719 hKey);
4720 if (object == NULL) {
4721 DBG_ERR("Wrapped key not found");
4723 goto c_wk_out;
4724 }
4725
4726 // NOTE: pWrappedKey is NULL so we just return the length we need
4727 if (pWrappedKey == NULL) {
4730 DBG_INFO("Calculated that wrapping will need %lu bytes", *pulWrappedKeyLen);
4731 rv = CKR_OK;
4732 goto c_wk_out;
4733 }
4734
4736 DBG_ERR("A different operation is already active");
4738 goto c_wk_out;
4739 }
4740
4742 DBG_ERR("Wrapping mechanism %lu not supported", pMechanism->mechanism);
4744 goto c_wk_out;
4745 }
4746
4749 hWrappingKey);
4750 if (key == NULL) {
4751 DBG_ERR("No wrap key found");
4753 goto c_wk_out;
4754 }
4755
4756 if (yh_check_capability(&key->object.capabilities, "export-wrapped") ==
4757 false) {
4758 DBG_ERR("Wrap key does not have \"export-wrapped\" set");
4759 rv = CKR_WRAPPING_KEY_TYPE_INCONSISTENT; // TODO: say something better?
4760 goto c_wk_out;
4761 }
4762
4764 "exportable-under-wrap") == false) {
4765 DBG_ERR("Key to be wrapped does not have \"exportable-under-wrap\" set");
4767 goto c_wk_out;
4768 }
4769
4771 size_t len = sizeof(buf);
4772
4773 yh_rc yrc =
4775 object->object.type, object->object.id, buf, &len);
4776 if (yrc != YHR_SUCCESS) {
4777 DBG_ERR("Wrapping failed: %s", yh_strerror(yrc));
4779 goto c_wk_out;
4780 }
4781
4783 DBG_ERR("buffer to small, needed %lu, got %lu", (unsigned long) len,
4786 goto c_wk_out;
4787 }
4788
4791
4792 DOUT;
4793
4794c_wk_out:
4795
4796 release_session(&g_ctx, session);
4797
4798 return rv;
4799}
4800
4801CK_DEFINE_FUNCTION(CK_RV, C_UnwrapKey)
4802(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
4806
4807 DIN;
4808
4809 CK_RV rv = CKR_OK;
4810
4811 // NOTE: since the wrap is opaque we just ignore the template..
4814
4815 if (g_yh_initialized == false) {
4816 DBG_ERR("libyubihsm is not initialized or already finalized");
4818 }
4819
4820 if (pMechanism == NULL || pWrappedKey == NULL || phKey == NULL) {
4821 DBG_ERR("Invalid argument");
4822 return CKR_ARGUMENTS_BAD;
4823 }
4824
4827 if (rv != CKR_OK) {
4828 DBG_ERR("Unknown session %lu", hSession);
4829 return rv;
4830 }
4831
4833 DBG_ERR("A different operation is already active");
4835 goto c_uk_out;
4836 }
4837
4840 DBG_ERR("Unwrapping using ECDH session key is not supported");
4842 goto c_uk_out;
4843 }
4844
4846 DBG_ERR("Wrapping mechanism %lu not supported", pMechanism->mechanism);
4848 goto c_uk_out;
4849 }
4850
4854 if (key == NULL) {
4855 DBG_ERR("No wrap key found");
4857 goto c_uk_out;
4858 }
4859
4860 if (yh_check_capability(&key->object.capabilities, "import-wrapped") ==
4861 false) {
4862 DBG_ERR("Wrap key can't unwrap");
4863 rv = CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; // TODO: say something better?
4864 goto c_uk_out;
4865 }
4866
4870 key->object.id, pWrappedKey,
4872 if (yrc != YHR_SUCCESS) {
4873 DBG_ERR("Unwrapping failed: %s", yh_strerror(yrc));
4875 goto c_uk_out;
4876 }
4877
4880 target_type, &object) != YHR_SUCCESS) {
4882 goto c_uk_out;
4883 }
4884 *phKey = object.sequence << 24 | object.type << 16 | object.id;
4885
4886 DBG_INFO("Unwrapped object %08lx", *phKey);
4887
4888 DOUT;
4889
4890c_uk_out:
4891
4892 release_session(&g_ctx, session);
4893
4894 return rv;
4895}
4896
4897CK_DEFINE_FUNCTION(CK_RV, C_DeriveKey)
4898(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
4901
4902 DIN;
4903
4904 CK_RV rv = CKR_OK;
4905
4906 if (g_yh_initialized == false) {
4907 DBG_ERR("libyubihsm is not initialized or already finalized");
4909 }
4910
4913 if (rv != CKR_OK) {
4914 DBG_ERR("Unknown session %lu", hSession);
4915 return rv;
4916 }
4917
4918 if (pMechanism == NULL || phKey == NULL) {
4919 DBG_ERR("Invalid argument");
4921 goto c_drv_out;
4922 }
4923
4925 DBG_ERR("Invalid mechanism for key generation: %lu", pMechanism->mechanism);
4927 goto c_drv_out;
4928 }
4929
4932 DBG_ERR("Cannot derive an ECDH key from another ECDH key");
4934 goto c_drv_out;
4935 }
4936
4937 char *label_buf = NULL;
4938 size_t label_len = 0;
4940 for (CK_ULONG i = 0; i < ulAttributeCount; i++) {
4941 switch (pTemplate[i].type) {
4942 case CKA_VALUE_LEN:
4943 expected_key_length = *((CK_ULONG *) pTemplate[i].pValue);
4944 break;
4945 case CKA_LABEL:
4946 if (pTemplate[i].ulValueLen > YH_OBJ_LABEL_LEN) {
4948 goto c_drv_out;
4949 }
4950 label_buf = pTemplate[i].pValue;
4951 label_len = pTemplate[i].ulValueLen;
4952 break;
4953 default:
4954 rv =
4956 if (rv != CKR_OK) {
4957 goto c_drv_out;
4958 }
4959 break;
4960 }
4961 }
4962
4964
4965 if (params->kdf == CKD_NULL) {
4966 if ((params->pSharedData != NULL) || (params->ulSharedDataLen != 0)) {
4967 DBG_ERR("Mechanism parameters incompatible with key derivation function "
4968 "CKD_NULL");
4970 goto c_drv_out;
4971 }
4972 } else {
4973 DBG_ERR("Unsupported value of mechanism parameter key derivation function");
4976 }
4977
4978 size_t in_len = params->ulPublicDataLen;
4979 if (in_len != params->ulPublicDataLen) {
4980 DBG_ERR("Invalid parameter");
4981 return CKR_ARGUMENTS_BAD;
4982 }
4983
4984 CK_BYTE_PTR pubkey = params->pPublicData;
4985
4988 DBG_ERR("There are already %d ECDH keys available for this session. "
4989 "Cannot derive more",
4992 goto c_drv_out;
4993 }
4994
4995 // Read the base key as the private keyID
4997
4999 memset(&ecdh_key, 0, sizeof(ecdh_key));
5000 size_t out_len = sizeof(ecdh_key.ecdh_key);
5003 if (rv != CKR_OK) {
5004 DBG_ERR("Unable to derive ECDH key: %s", yh_strerror(rv));
5005 goto c_drv_out;
5006 }
5007
5009 DBG_ERR("Failed to derive a key with the expected length");
5011 goto c_drv_out;
5012 }
5013
5014 // Make a session variable to store the derived key
5015 ecdh_key.id = ECDH_KEY_TYPE << 16 | seq;
5019
5021
5022 *phKey = ecdh_key.id;
5023
5024 DBG_INFO("Created object %04lx", *phKey);
5025
5026 DOUT;
5027
5029
5030 release_session(&g_ctx, session);
5031
5032 return rv;
5033}
5034
5035/* Random number generation functions */
5036
5037CK_DEFINE_FUNCTION(CK_RV, C_SeedRandom)
5039
5040 DIN;
5041
5045
5046 DOUT;
5048}
5049
5050CK_DEFINE_FUNCTION(CK_RV, C_GenerateRandom)
5052
5053 DIN;
5054
5055 CK_RV rv = CKR_OK;
5056
5057 if (g_yh_initialized == false) {
5058 DBG_ERR("libyubihsm is not initialized or already finalized");
5060 }
5061
5062 size_t len = ulRandomLen;
5063 if (len != ulRandomLen || pRandomData == NULL) {
5064 DBG_ERR("Invalid parameter");
5065 return CKR_ARGUMENTS_BAD;
5066 }
5067
5070 if (rv != CKR_OK) {
5071 DBG_ERR("Unknown session %lu", hSession);
5072 return rv;
5073 }
5074
5075 // the OpenSC pkcs11 test calls with 0 and expects CKR_OK, do that..
5076 if (len != 0) {
5079 if (rc != YHR_SUCCESS) {
5080 DBG_ERR("Failed to get random data");
5082 goto c_gr_out;
5083 }
5084 }
5085
5086 if (len != ulRandomLen) {
5087 DBG_ERR("Incorrect amount of data returned");
5089 goto c_gr_out;
5090 }
5091
5092 DOUT;
5093
5094c_gr_out:
5095
5096 release_session(&g_ctx, session);
5097
5098 return rv;
5099}
5100
5101CK_DEFINE_FUNCTION(CK_RV, C_GetFunctionStatus)
5102(CK_SESSION_HANDLE hSession)
5103
5104{
5105
5106 DIN;
5107
5109
5110 DOUT;
5112}
5113
5114CK_DEFINE_FUNCTION(CK_RV, C_CancelFunction)(CK_SESSION_HANDLE hSession) {
5115
5116 DIN;
5117
5119
5120 DOUT;
5122}
5123
5126 C_Initialize,
5127 C_Finalize,
5128 C_GetInfo,
5129 C_GetFunctionList,
5130 C_GetSlotList,
5131 C_GetSlotInfo,
5132 C_GetTokenInfo,
5133 C_GetMechanismList,
5134 C_GetMechanismInfo,
5135 C_InitToken,
5136 C_InitPIN,
5137 C_SetPIN,
5138 C_OpenSession,
5139 C_CloseSession,
5140 C_CloseAllSessions,
5141 C_GetSessionInfo,
5142 C_GetOperationState,
5143 C_SetOperationState,
5144 C_Login,
5145 C_Logout,
5146 C_CreateObject,
5147 C_CopyObject,
5148 C_DestroyObject,
5149 C_GetObjectSize,
5150 C_GetAttributeValue,
5151 C_SetAttributeValue,
5152 C_FindObjectsInit,
5153 C_FindObjects,
5154 C_FindObjectsFinal,
5155 C_EncryptInit,
5156 C_Encrypt,
5157 C_EncryptUpdate,
5158 C_EncryptFinal,
5159 C_DecryptInit,
5160 C_Decrypt,
5161 C_DecryptUpdate,
5162 C_DecryptFinal,
5163 C_DigestInit,
5164 C_Digest,
5165 C_DigestUpdate,
5166 C_DigestKey,
5167 C_DigestFinal,
5168 C_SignInit,
5169 C_Sign,
5170 C_SignUpdate,
5171 C_SignFinal,
5172 C_SignRecoverInit,
5173 C_SignRecover,
5174 C_VerifyInit,
5175 C_Verify,
5176 C_VerifyUpdate,
5177 C_VerifyFinal,
5178 C_VerifyRecoverInit,
5179 C_VerifyRecover,
5180 C_DigestEncryptUpdate,
5181 C_DecryptDigestUpdate,
5182 C_SignEncryptUpdate,
5183 C_DecryptVerifyUpdate,
5184 C_GenerateKey,
5185 C_GenerateKeyPair,
5186 C_WrapKey,
5187 C_UnwrapKey,
5188 C_DeriveKey,
5189 C_SeedRandom,
5190 C_GenerateRandom,
5191 C_GetFunctionStatus,
5192 C_CancelFunction,
5193 C_WaitForSlotEvent,
5194};
#define DBG_ERR(...)
Definition debug_lib.h:76
#define DBG_INFO(...)
Definition debug_lib.h:63
FILE * _YHP11_OUTPUT
Definition debug_p11.c:25
void yh_dbg_init(int dbg, int dinout, int libdbg, const char *debug_file)
Definition debug_p11.c:27
#define insecure_memzero(buf, len)
const char * yh_strerror(yh_rc err)
Definition error.c:65
bool list_append(List *list, void *item)
Definition list.c:78
void list_delete(List *list, ListItem *item)
Definition list.c:117
void list_iterate(List *list, IteratorFn iterator_fn)
Definition list.c:175
ListItem * list_get(List *list, void *data, CompareItemFn compare_item_fn)
Definition list.c:105
void list_create(List *list, int item_size, FreeItemFn free_item_fn)
Definition list.c:24
void list_destroy(List *list)
Definition list.c:33
void verify(const char *msg, const T &a, const S &b)
Definition minitest.cpp:13
#define CKD_NULL
Definition pkcs11.h:732
#define CKR_SESSION_COUNT
Definition pkcs11.h:1137
#define CKA_TOKEN
Definition pkcs11.h:364
#define CKR_MECHANISM_INVALID
Definition pkcs11.h:1126
#define CKR_SLOT_ID_INVALID
Definition pkcs11.h:1095
#define CKG_MGF1_SHA256
Definition pkcs11.h:746
#define CKM_RSA_PKCS
Definition pkcs11.h:470
#define CKF_LOGIN_REQUIRED
Definition pkcs11.h:248
#define CKF_HW_SLOT
Definition pkcs11.h:222
#define CKO_PUBLIC_KEY
Definition pkcs11.h:302
#define CKR_KEY_UNEXTRACTABLE
Definition pkcs11.h:1125
#define CKR_UNWRAPPING_KEY_HANDLE_INVALID
Definition pkcs11.h:1151
#define CKK_SHA256_HMAC
Definition pkcs11.h:345
#define CK_DEFINE_FUNCTION(retval, name)
Definition pkcs11.h:1185
#define CKS_RW_PUBLIC_SESSION
Definition pkcs11.h:282
#define CKR_MECHANISM_PARAM_INVALID
Definition pkcs11.h:1127
#define CKF_TOKEN_INITIALIZED
Definition pkcs11.h:254
#define CKM_SHA_1_HMAC
Definition pkcs11.h:533
#define CKG_MGF1_SHA512
Definition pkcs11.h:748
#define CKC_X_509
Definition pkcs11.h:356
#define CKR_DEVICE_ERROR
Definition pkcs11.h:1108
#define CKR_SESSION_PARALLEL_NOT_SUPPORTED
Definition pkcs11.h:1139
ck_session_handle_t * CK_SESSION_HANDLE_PTR
Definition pkcs11.h:1227
#define CKA_ID
Definition pkcs11.h:385
ck_mechanism_type_t * CK_MECHANISM_TYPE_PTR
Definition pkcs11.h:1242
#define CKA_APPLICATION
Definition pkcs11.h:367
CK_ULONG * CK_ULONG_PTR
Definition pkcs11.h:1199
#define CKM_ECDH1_DERIVE
Definition pkcs11.h:652
#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT
Definition pkcs11.h:1164
#define value
Definition pkcs11.h:157
unsigned long int CK_ULONG
Definition pkcs11.h:1194
#define CKO_SECRET_KEY
Definition pkcs11.h:304
#define CKK_RSA
Definition pkcs11.h:319
#define CRYPTOKI_VERSION_MINOR
Definition pkcs11.h:66
#define CKM_RSA_PKCS_KEY_PAIR_GEN
Definition pkcs11.h:469
#define CKR_SESSION_HANDLE_INVALID
Definition pkcs11.h:1138
#define CKO_CERTIFICATE
Definition pkcs11.h:301
#define CKF_USER_PIN_INITIALIZED
Definition pkcs11.h:249
#define CKF_RW_SESSION
Definition pkcs11.h:293
#define CKS_RO_USER_FUNCTIONS
Definition pkcs11.h:281
#define CKR_ARGUMENTS_BAD
Definition pkcs11.h:1098
#define CKM_SHA256
Definition pkcs11.h:541
#define CKU_USER
Definition pkcs11.h:275
#define CKA_PRIVATE
Definition pkcs11.h:365
#define CKG_MGF1_SHA384
Definition pkcs11.h:747
ck_slot_id_t * CK_SLOT_ID_PTR
Definition pkcs11.h:1219
#define CKR_TOKEN_NOT_PRESENT
Definition pkcs11.h:1148
#define CKR_CRYPTOKI_NOT_INITIALIZED
Definition pkcs11.h:1173
#define CKA_SENSITIVE
Definition pkcs11.h:386
#define CKR_PIN_INCORRECT
Definition pkcs11.h:1131
ck_object_handle_t * CK_OBJECT_HANDLE_PTR
Definition pkcs11.h:1232
#define CKF_REMOVABLE_DEVICE
Definition pkcs11.h:221
#define CKZ_DATA_SPECIFIED
Definition pkcs11.h:752
#define CKM_RSA_PKCS_OAEP
Definition pkcs11.h:478
#define CKA_SIGN
Definition pkcs11.h:391
#define CKR_WRAPPING_KEY_HANDLE_INVALID
Definition pkcs11.h:1162
#define CK_UNAVAILABLE_INFORMATION
Definition pkcs11.h:265
#define CK_TRUE
Definition pkcs11.h:1203
#define CKA_VALUE
Definition pkcs11.h:368
CK_BYTE * CK_BYTE_PTR
Definition pkcs11.h:1196
#define CKF_OS_LOCKING_OK
Definition pkcs11.h:1090
#define CKR_OBJECT_HANDLE_INVALID
Definition pkcs11.h:1128
#define CKM_SHA256_HMAC
Definition pkcs11.h:542
void * CK_VOID_PTR
Definition pkcs11.h:1200
#define CKO_DATA
Definition pkcs11.h:300
#define CKO_PRIVATE_KEY
Definition pkcs11.h:303
#define CKR_ENCRYPTED_DATA_INVALID
Definition pkcs11.h:1111
#define CKR_CRYPTOKI_ALREADY_INITIALIZED
Definition pkcs11.h:1174
#define CKM_GENERIC_SECRET_KEY_GEN
Definition pkcs11.h:586
#define CKF_SERIAL_SESSION
Definition pkcs11.h:294
#define CKR_FUNCTION_FAILED
Definition pkcs11.h:1097
#define CKM_SHA384
Definition pkcs11.h:544
#define CKR_OPERATION_NOT_INITIALIZED
Definition pkcs11.h:1130
#define CKM_EC_KEY_PAIR_GEN
Definition pkcs11.h:645
#define CKM_SHA384_HMAC
Definition pkcs11.h:545
#define CKR_TEMPLATE_INCONSISTENT
Definition pkcs11.h:1147
#define CKR_OPERATION_ACTIVE
Definition pkcs11.h:1129
#define CK_EFFECTIVELY_INFINITE
Definition pkcs11.h:266
#define CKA_UNWRAP
Definition pkcs11.h:390
#define CKM_SHA512
Definition pkcs11.h:547
unsigned char CK_BBOOL
Definition pkcs11.h:1193
#define CKR_BUFFER_TOO_SMALL
Definition pkcs11.h:1169
#define CKS_RW_USER_FUNCTIONS
Definition pkcs11.h:283
#define CKS_RO_PUBLIC_SESSION
Definition pkcs11.h:280
#define CKA_DECRYPT
Definition pkcs11.h:388
#define CKA_KEY_TYPE
Definition pkcs11.h:383
#define CKA_VALUE_LEN
Definition pkcs11.h:414
#define CKK_SHA384_HMAC
Definition pkcs11.h:346
#define CKF_RNG
Definition pkcs11.h:246
#define CKA_DESTROYABLE
Definition pkcs11.h:422
#define CKR_ATTRIBUTE_VALUE_INVALID
Definition pkcs11.h:1105
#define CKA_ALWAYS_SENSITIVE
Definition pkcs11.h:418
#define CKG_MGF1_SHA1
Definition pkcs11.h:744
#define CKA_CERTIFICATE_TYPE
Definition pkcs11.h:370
#define CKA_LABEL
Definition pkcs11.h:366
#define CKA_EXTRACTABLE
Definition pkcs11.h:415
#define CKR_TEMPLATE_INCOMPLETE
Definition pkcs11.h:1146
#define CKA_ENCRYPT
Definition pkcs11.h:387
#define CKR_HOST_MEMORY
Definition pkcs11.h:1094
#define CKR_SIGNATURE_LEN_RANGE
Definition pkcs11.h:1145
#define CKR_USER_TYPE_INVALID
Definition pkcs11.h:1157
#define CRYPTOKI_VERSION_MAJOR
Definition pkcs11.h:65
#define CKM_SHA512_HMAC
Definition pkcs11.h:548
#define CKR_KEY_HANDLE_INVALID
Definition pkcs11.h:1116
#define CKF_TOKEN_PRESENT
Definition pkcs11.h:220
#define CKK_EC
Definition pkcs11.h:323
#define CKK_SHA_1_HMAC
Definition pkcs11.h:344
CK_UTF8CHAR * CK_UTF8CHAR_PTR
Definition pkcs11.h:1198
#define CKR_KEY_TYPE_INCONSISTENT
Definition pkcs11.h:1118
#define CKM_SHA_1
Definition pkcs11.h:532
#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT
Definition pkcs11.h:1153
#define CKA_WRAP
Definition pkcs11.h:389
#define CKA_CLASS
Definition pkcs11.h:363
#define CKK_SHA512_HMAC
Definition pkcs11.h:347
#define CKK_YUBICO_AES192_CCM_WRAP
Definition pkcs11y.h:28
#define CKK_YUBICO_AES128_CCM_WRAP
Definition pkcs11y.h:26
#define CKM_YUBICO_AES_CCM_WRAP
Definition pkcs11y.h:33
#define CKK_YUBICO_AES256_CCM_WRAP
Definition pkcs11y.h:30
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181
unsigned short uint16_t
Definition stdint.h:125
unsigned int uint32_t
Definition stdint.h:126
unsigned char uint8_t
Definition stdint.h:124
int length
Definition list.h:36
ListItem * head
Definition list.h:38
void * data
Definition list.h:31
ListItem * next
Definition list.h:32
ck_attribute_type_t type
Definition pkcs11.h:456
ck_flags_t flags
Definition pkcs11.h:1085
struct ck_version version
Definition pkcs11.h:1004
ck_mechanism_type_t mechanism
Definition pkcs11.h:695
ck_flags_t flags
Definition pkcs11.h:215
CK_ULONG key_len
uint16_t key_id
CK_ULONG digest_len
uint8_t ecdh_key[ECDH_KEY_BUF_SIZE]
The key itself.
size_t len
The length of the key.
char label[YH_OBJ_LABEL_LEN+1]
Object label.
CK_OBJECT_HANDLE id
uint16_t key_id
uint16_t current_object
bool only_private
size_t n_objects
yh_object_descriptor objects[YH_MAX_ITEMS_COUNT]
struct mechanism::@110::@112 oaep
struct mechanism::@110::@113 pss
CK_MECHANISM_TYPE mechanism
uint16_t key_id
uint16_t sig_len
CK_ULONG key_len
uint16_t key_id
unsigned long saltLen
const EVP_MD * md
CK_ULONG key_len
const EVP_MD * mgf1md
Capabilities representation.
Definition yubihsm.h:162
yh_algorithm algorithm
Object algorithm.
Definition yubihsm.h:552
uint16_t len
Object length.
Definition yubihsm.h:546
uint16_t id
Object ID.
Definition yubihsm.h:544
yh_capabilities capabilities
Object capabilities.
Definition yubihsm.h:542
char label[YH_OBJ_LABEL_LEN+1]
Object label.
Definition yubihsm.h:558
yh_object_type type
Object type.
Definition yubihsm.h:550
CK_UNLOCKMUTEX unlock_mutex
CK_DESTROYMUTEX destroy_mutex
CK_CREATEMUTEX create_mutex
yubihsm_pkcs11_op_type type
yubihsm_pkcs11_op_info operation
yubihsm_pkcs11_slot * slot
yubihsm_pkcs11_session_state session_state
yh_connector * connector
yh_session * device_session
yubihsm_pkcs11_object_desc objects[YH_MAX_ITEMS_COUNT]
account_query_db::get_accounts_by_authorizers_params params
digest_info digest
find_info find
decrypt_info decrypt
verify_info verify
encrypt_info encrypt
sign_info sign
bool is_PKCS1v1_5_sign_mechanism(CK_MECHANISM_TYPE m)
bool is_ECDSA_sign_mechanism(CK_MECHANISM_TYPE m)
CK_RV set_template_attribute(yubihsm_pkcs11_attribute *attribute, void *value)
CK_RV get_mechanism_list(yubihsm_pkcs11_slot *slot, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR count)
Definition util_pkcs11.c:73
bool add_connectors(yubihsm_pkcs11_context *ctx, int n_connectors, char **connector_names, yh_connector **connectors)
CK_RV apply_verify_mechanism_finalize(yubihsm_pkcs11_op_info *op_info __attribute((unused)))
bool decrypt_mechanism_cleanup(yubihsm_pkcs11_op_info *op_info)
bool verify_mechanism_cleanup(yubihsm_pkcs11_op_info *op_info)
CK_RV populate_template(int type, void *object, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, yh_session *session)
bool check_encrypt_mechanism(yubihsm_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism)
CK_RV parse_ec_generate_template(CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, yubihsm_pkcs11_object_template *template)
CK_RV apply_verify_mechanism_init(yubihsm_pkcs11_op_info *op_info)
CK_RV perform_digest(yubihsm_pkcs11_op_info *op_info, uint8_t *digest, uint16_t *digest_len)
bool is_PSS_sign_mechanism(CK_MECHANISM_TYPE m)
void release_slot(yubihsm_pkcs11_context *ctx, yubihsm_pkcs11_slot *slot)
CK_RV apply_decrypt_mechanism_finalize(yubihsm_pkcs11_op_info *op_info __attribute((unused)))
CK_RV parse_rsa_generate_template(CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, yubihsm_pkcs11_object_template *template)
bool is_HMAC_sign_mechanism(CK_MECHANISM_TYPE m)
CK_RV get_session(yubihsm_pkcs11_context *ctx, CK_SESSION_HANDLE hSession, yubihsm_pkcs11_session **session, int session_state)
bool parse_hex(CK_UTF8CHAR_PTR hex, CK_ULONG hex_len, uint8_t *parsed)
CK_RV apply_digest_mechanism_init(yubihsm_pkcs11_op_info *op_info)
CK_RV perform_signature(yh_session *session, yubihsm_pkcs11_op_info *op_info, uint8_t *signature, uint16_t *signature_len)
CK_RV validate_derive_key_attribute(CK_ATTRIBUTE_TYPE type, void *value)
CK_RV apply_encrypt_mechanism_update(yubihsm_pkcs11_op_info *op_info, CK_BYTE_PTR in, CK_ULONG in_len)
bool check_decrypt_mechanism(yubihsm_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism)
bool check_digest_mechanism(CK_MECHANISM_PTR pMechanism)
CK_RV parse_wrap_template(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, yubihsm_pkcs11_object_template *template, bool generate)
int parse_id_value(void *value, CK_ULONG len)
CK_RV parse_ec_template(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, yubihsm_pkcs11_object_template *template)
bool sign_mechanism_cleanup(yubihsm_pkcs11_op_info *op_info)
bool create_session(yubihsm_pkcs11_slot *slot, CK_FLAGS flags, CK_SESSION_HANDLE_PTR phSession)
CK_RV apply_sign_mechanism_finalize(yubihsm_pkcs11_op_info *op_info)
yubihsm_pkcs11_slot * get_slot(yubihsm_pkcs11_context *ctx, CK_ULONG id)
CK_RV parse_hmac_template(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, yubihsm_pkcs11_object_template *template, bool generate)
bool is_RSA_sign_mechanism(CK_MECHANISM_TYPE m)
CK_RV apply_sign_mechanism_update(yubihsm_pkcs11_op_info *op_info, CK_BYTE_PTR in, CK_ULONG in_len)
void set_native_locking(yubihsm_pkcs11_context *ctx)
CK_RV apply_decrypt_mechanism_update(yubihsm_pkcs11_op_info *op_info, CK_BYTE_PTR in, CK_ULONG in_len)
bool check_wrap_mechanism(yubihsm_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism)
yubihsm_pkcs11_object_desc * get_object_desc(yh_session *session, yubihsm_pkcs11_object_desc *objects, CK_OBJECT_HANDLE objHandle)
bool delete_session(yubihsm_pkcs11_context *ctx, CK_SESSION_HANDLE_PTR phSession)
CK_RV apply_digest_mechanism_update(yubihsm_pkcs11_op_info *op_info, CK_BYTE_PTR in, CK_ULONG in_len)
bool check_verify_mechanism(yubihsm_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism)
CK_RV perform_decrypt(yh_session *session, yubihsm_pkcs11_op_info *op_info, uint8_t *data, uint16_t *data_len)
CK_RV apply_decrypt_mechanism_init(yubihsm_pkcs11_op_info *op_info)
CK_RV apply_digest_mechanism_finalize(yubihsm_pkcs11_op_info *op_info)
bool get_mechanism_info(yubihsm_pkcs11_slot *slot, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo)
void release_session(yubihsm_pkcs11_context *ctx, yubihsm_pkcs11_session *session)
CK_RV perform_verify(yh_session *session, yubihsm_pkcs11_op_info *op_info, uint8_t *signature, uint16_t signature_len)
CK_RV parse_rsa_template(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, yubihsm_pkcs11_object_template *template)
CK_ULONG get_digest_bytelength(CK_MECHANISM_TYPE m)
CK_RV apply_sign_mechanism_init(yubihsm_pkcs11_op_info *op_info)
bool digest_mechanism_cleanup(yubihsm_pkcs11_op_info *op_info)
CK_RV apply_verify_mechanism_update(yubihsm_pkcs11_op_info *op_info, CK_BYTE_PTR in, CK_ULONG in_len)
bool check_sign_mechanism(yubihsm_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism)
CK_RV perform_encrypt(yh_session *session, yubihsm_pkcs11_op_info *op_info, uint8_t *data, uint16_t *data_len)
bool yh_is_rsa(yh_algorithm algorithm)
Definition yubihsm.c:4245
yh_rc yh_util_import_opaque(yh_session *session, uint16_t *object_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const uint8_t *in, size_t in_len)
Definition yubihsm.c:2666
bool yh_connector_has_device(yh_connector *connector)
Definition yubihsm.c:906
yh_rc yh_util_import_hmac_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const uint8_t *key, size_t key_len)
Definition yubihsm.c:1750
yh_rc yh_destroy_session(yh_session **session)
Definition yubihsm.c:890
yh_rc yh_util_generate_hmac_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm)
Definition yubihsm.c:1992
yh_rc yh_util_generate_wrap_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const yh_capabilities *delegated_capabilities)
Definition yubihsm.c:2458
yh_rc yh_util_derive_ecdh(yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len)
Definition yubihsm.c:2174
yh_rc yh_util_generate_ec_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm)
Definition yubihsm.c:1913
yh_rc yh_exit(void)
Definition yubihsm.c:3910
yh_rc yh_get_key_bitlength(yh_algorithm algorithm, size_t *result)
Definition yubihsm.c:4309
yh_rc yh_util_import_wrap_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const yh_capabilities *delegated_capabilities, const uint8_t *in, size_t in_len)
Definition yubihsm.c:2363
yh_rc yh_create_session_derived(yh_connector *connector, uint16_t authkey_id, const uint8_t *password, size_t password_len, bool recreate, yh_session **session)
Definition yubihsm.c:593
yh_rc yh_init(void)
Definition yubihsm.c:3857
yh_rc yh_util_close_session(yh_session *session)
Definition yubihsm.c:1257
yh_rc yh_util_get_device_info(yh_connector *connector, uint8_t *major, uint8_t *minor, uint8_t *patch, uint32_t *serial, uint8_t *log_total, uint8_t *log_used, yh_algorithm *algorithms, size_t *n_algorithms)
Definition yubihsm.c:938
yh_rc yh_authenticate_session(yh_session *session)
Definition yubihsm.c:2927
yh_rc yh_util_get_object_info(yh_session *session, uint16_t id, yh_object_type type, yh_object_descriptor *object)
Definition yubihsm.c:1128
yh_rc yh_util_list_objects(yh_session *session, uint16_t id, yh_object_type type, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const char *label, yh_object_descriptor *objects, size_t *n_objects)
Definition yubihsm.c:1030
yh_rc yh_set_connector_option(yh_connector *connector, yh_connector_option opt, const void *val)
Definition yubihsm.c:4063
yh_rc yh_init_connector(const char *url, yh_connector **connector)
Definition yubihsm.c:4024
yh_rc yh_connect(yh_connector *connector, int timeout)
Definition yubihsm.c:4079
yh_rc yh_util_export_wrapped(yh_session *session, uint16_t wrapping_key_id, yh_object_type target_type, uint16_t target_id, uint8_t *out, size_t *out_len)
Definition yubihsm.c:2265
yh_rc yh_string_to_capabilities(const char *capability, yh_capabilities *result)
Definition yubihsm.c:4115
yh_rc yh_util_import_rsa_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const uint8_t *p, const uint8_t *q)
Definition yubihsm.c:1655
yh_rc yh_disconnect(yh_connector *connector)
Definition yubihsm.c:4097
yh_rc yh_util_generate_rsa_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm)
Definition yubihsm.c:1900
bool yh_check_capability(const yh_capabilities *capabilities, const char *capability)
Definition yubihsm.c:4198
yh_rc yh_util_import_ec_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const uint8_t *s)
Definition yubihsm.c:1689
yh_rc yh_util_import_wrapped(yh_session *session, uint16_t wrapping_key_id, const uint8_t *in, size_t in_len, yh_object_type *target_type, uint16_t *target_id)
Definition yubihsm.c:2309
yh_rc yh_util_delete_object(yh_session *session, uint16_t id, yh_object_type type)
Definition yubihsm.c:2222
yh_rc yh_util_get_pseudo_random(yh_session *session, size_t len, uint8_t *out, size_t *out_len)
Definition yubihsm.c:1560
yh_object_type
Definition yubihsm.h:359
@ YH_WRAP_KEY
Definition yubihsm.h:369
@ YH_OPAQUE
Definition yubihsm.h:362
@ YH_HMAC_KEY
HMAC Key is a secret key used when computing and verifying HMAC signatures.
Definition yubihsm.h:371
@ YH_ASYMMETRIC_KEY
Asymmetric Key is the private key of an asymmetric key-pair.
Definition yubihsm.h:366
@ YH_PUBLIC_KEY
Definition yubihsm.h:379
#define YH_MAX_ITEMS_COUNT
Max items the device may hold.
Definition yubihsm.h:103
#define YH_OBJ_LABEL_LEN
Max length of object labels.
Definition yubihsm.h:123
yh_algorithm
Definition yubihsm.h:390
@ YH_ALGO_MGF1_SHA512
mgf1-sha512
Definition yubihsm.h:460
@ YH_ALGO_OPAQUE_X509_CERTIFICATE
opaque-x509-certificate
Definition yubihsm.h:452
@ YH_ALGO_MGF1_SHA384
mgf1-sha384
Definition yubihsm.h:458
@ YH_ALGO_OPAQUE_DATA
opaque-data
Definition yubihsm.h:450
@ YH_ALGO_MGF1_SHA1
mgf1-sha1
Definition yubihsm.h:454
@ YH_ALGO_MGF1_SHA256
mgf1-sha256
Definition yubihsm.h:456
@ YH_CONNECTOR_PROXY_SERVER
Definition yubihsm.h:506
@ YH_CONNECTOR_HTTPS_CA
Definition yubihsm.h:503
#define YH_CCM_WRAP_OVERHEAD
Definition yubihsm.h:149
yh_rc
Definition yubihsm.h:170
@ YHR_SUCCESS
Returned value when function was successful.
Definition yubihsm.h:172
@ YHR_CRYPTOGRAM_MISMATCH
Returned value when failing to verify cryptogram.
Definition yubihsm.h:189
uint8_t patch
CK_SESSION_HANDLE CK_OBJECT_HANDLE CK_ULONG_PTR pulSize
goto c_df_out
yubihsm_pkcs11_slot * slot
CK_SESSION_HANDLE CK_OBJECT_HANDLE hObject
CK_SLOT_ID CK_SLOT_INFO_PTR pInfo
CK_SESSION_HANDLE CK_MECHANISM_PTR CK_ATTRIBUTE_PTR CK_ULONG CK_ATTRIBUTE_PTR CK_ULONG ulPrivateKeyAttributeCount
CK_SESSION_HANDLE CK_BYTE_PTR pPart
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG CK_BYTE_PTR CK_ULONG_PTR pulDataLen
yh_capabilities capabilities
yubihsm_pkcs11_session * session
CK_SESSION_HANDLE CK_MECHANISM_PTR CK_OBJECT_HANDLE CK_OBJECT_HANDLE CK_BYTE_PTR CK_ULONG_PTR pulWrappedKeyLen
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG CK_BYTE_PTR CK_ULONG_PTR pulEncryptedDataLen
goto c_s_out
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG_PTR pulLastEncryptedPartLen
goto c_vi_out
CK_ULONG d
uint32_t serial
CK_ULONG datalen
goto c_gkp_out
yh_object_type target_type
CK_SESSION_HANDLE hSession
bool secret_key
bool full
#define YUBIHSM_PKCS11_MAX_PIN_LEN
CK_SLOT_ID CK_MECHANISM_TYPE type
CK_SESSION_HANDLE CK_OBJECT_HANDLE_PTR CK_ULONG ulMaxObjectCount
char * label
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG ulPartLen
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG CK_BYTE_PTR CK_ULONG ulSignatureLen
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG ulOperationStateLen
CK_SESSION_HANDLE CK_MECHANISM_PTR CK_ATTRIBUTE_PTR CK_ULONG CK_ATTRIBUTE_PTR CK_ULONG CK_OBJECT_HANDLE_PTR CK_OBJECT_HANDLE_PTR phPrivateKey
return CKR_FUNCTION_NOT_PARALLEL
uint16_t privkey_id
bool pub
int wrapping_key_type
CK_SESSION_HANDLE CK_UTF8CHAR_PTR CK_ULONG CK_UTF8CHAR_PTR pNewPin
CK_SLOT_ID CK_FLAGS CK_VOID_PTR CK_NOTIFY Notify
yh_get_connector_version(slot->connector, &major, &minor, &patch)
CK_RV ret
CK_SESSION_HANDLE CK_MECHANISM_PTR CK_OBJECT_HANDLE hBaseKey
return CKR_OK
EVP_MD_CTX * mdctx
CK_SESSION_HANDLE CK_USER_TYPE userType
CK_BBOOL CK_SLOT_ID_PTR pSlotList
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG CK_BYTE_PTR CK_ULONG_PTR pulPartLen
CK_SESSION_HANDLE CK_MECHANISM_PTR CK_OBJECT_HANDLE hWrappingKey
CK_SESSION_HANDLE CK_ATTRIBUTE_PTR CK_ULONG ulCount
bool extractable_set
bool overflow
CK_SLOT_ID CK_FLAGS CK_VOID_PTR CK_NOTIFY CK_SESSION_HANDLE_PTR phSession
goto c_si_out
goto c_e_out
char * s
uint16_t j
uint16_t domains
size_t out_len
goto c_gk_out
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG ulEncryptedPartLen
uint8_t major
CK_FLAGS CK_SLOT_ID_PTR pSlot
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG ulRandomLen
CK_SESSION_HANDLE CK_MECHANISM_PTR CK_OBJECT_HANDLE CK_OBJECT_HANDLE CK_BYTE_PTR pWrappedKey
CK_SESSION_HANDLE CK_MECHANISM_PTR CK_ATTRIBUTE_PTR CK_ULONG CK_ATTRIBUTE_PTR CK_ULONG CK_OBJECT_HANDLE_PTR phPublicKey
CK_SESSION_HANDLE CK_BYTE_PTR pData
CK_ULONG digest_length
yh_algorithm algorithm
CK_FUNCTION_LIST function_list
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG CK_BYTE_PTR pEncryptedData
CK_SESSION_HANDLE CK_UTF8CHAR_PTR CK_ULONG CK_UTF8CHAR_PTR CK_ULONG ulNewLen
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG_PTR pulLastPartLen
CK_SESSION_HANDLE CK_MECHANISM_PTR CK_OBJECT_HANDLE hKey
goto c_di_out
size_t len
bool terminate
CK_SESSION_HANDLE CK_BYTE_PTR pRandomData
CK_SESSION_HANDLE CK_OBJECT_HANDLE CK_ATTRIBUTE_PTR CK_ULONG CK_OBJECT_HANDLE_PTR phNewObject
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG CK_BYTE_PTR CK_ULONG_PTR pulSignatureLen
int unwrapping_key_type
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG CK_OBJECT_HANDLE hEncryptionKey
CK_SLOT_ID slotID
CK_SESSION_HANDLE CK_MECHANISM_PTR CK_OBJECT_HANDLE CK_BYTE_PTR CK_ULONG ulWrappedKeyLen
CK_FUNCTION_LIST_PTR_PTR ppFunctionList
CK_SLOT_ID CK_MECHANISM_TYPE_PTR pMechanismList
goto c_d_out
CK_SESSION_HANDLE CK_BYTE_PTR pOperationState
uint8_t buf[2048]
yh_object_descriptor object
#define UNUSED(x)
CK_SLOT_ID CK_FLAGS CK_VOID_PTR pApplication
bool set
int l
#define YUBIHSM_PKCS11_MANUFACTURER
CK_BYTE_PTR pubkey
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG CK_BYTE_PTR CK_ULONG_PTR pulDigestLen
CK_SESSION_HANDLE CK_BYTE_PTR pSeed
CK_SESSION_HANDLE CK_BYTE_PTR pLastEncryptedPart
int basekey_type
int seq
yh_rc rc
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG ulSeedLen
CK_SESSION_HANDLE CK_MECHANISM_PTR CK_OBJECT_HANDLE CK_BYTE_PTR CK_ULONG CK_ATTRIBUTE_PTR CK_ULONG ulAttributeCount
yh_rc yrc
goto c_drv_out
CK_RV rv
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG ulDataLen
CK_SESSION_HANDLE CK_MECHANISM_PTR CK_ATTRIBUTE_PTR CK_ULONG CK_ATTRIBUTE_PTR pPrivateKeyTemplate
struct @108 id
CK_SESSION_HANDLE CK_ATTRIBUTE_PTR CK_ULONG CK_OBJECT_HANDLE_PTR phObject
CK_SESSION_HANDLE CK_ATTRIBUTE_PTR pTemplate
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG CK_OBJECT_HANDLE CK_OBJECT_HANDLE hAuthenticationKey
int wrapped_key_type
CK_SESSION_HANDLE CK_MECHANISM_PTR CK_ATTRIBUTE_PTR CK_ULONG ulPublicKeyAttributeCount
goto c_co_out
size_t expected_key_length
CK_VERSION ver
#define YUBIHSM_PKCS11_MIN_PIN_LEN
delete_object_from_cache(session->slot->objects, hObject)
return CKR_RANDOM_SEED_NOT_SUPPORTED
CK_SESSION_HANDLE CK_MECHANISM_PTR pMechanism
CK_ULONG siglen
CK_FLAGS CK_SLOT_ID_PTR CK_VOID_PTR pReserved
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG CK_BYTE_PTR CK_ULONG_PTR pulEncryptedPartLen
size_t key_length
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG CK_BYTE_PTR pDigest
CK_SLOT_ID CK_UTF8CHAR_PTR CK_ULONG ulPinLen
goto c_ef_out
bool unknown
CK_SESSION_HANDLE CK_UTF8CHAR_PTR CK_ULONG ulOldLen
CK_SLOT_ID CK_UTF8CHAR_PTR pPin
#define GLOBAL_UNLOCK_OR_RETURN
return CKR_FUNCTION_NOT_SUPPORTED
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG ulEncryptedDataLen
#define GLOBAL_LOCK_OR_RETURN
uint16_t target_id
CK_BBOOL CK_SLOT_ID_PTR CK_ULONG_PTR pulCount
uint16_t key_id
memset(pInfo->slotDescription, ' ', 64)
CK_SESSION_HANDLE CK_MECHANISM_PTR CK_ATTRIBUTE_PTR pPublicKeyTemplate
ecdh_session_key ecdh_key
char * label_buf
pInfo flags
yh_get_connector_address(slot->connector, &s)
uint8_t minor
size_t label_len
memcpy((char *) pInfo->slotDescription, s, l)
goto c_v_out
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG CK_BYTE_PTR pEncryptedPart
#define YUBIHSM_PKCS11_LIBDESC
CK_SESSION_HANDLE CK_BYTE_PTR pLastPart
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG_PTR pulOperationStateLen
size_t in_len
CK_BBOOL tokenPresent
CK_SESSION_HANDLE CK_UTF8CHAR_PTR pOldPin
CK_SESSION_HANDLE CK_MECHANISM_PTR CK_OBJECT_HANDLE hUnwrappingKey
struct @108 key_type
yh_capabilities delegated_capabilities
CK_SESSION_HANDLE CK_OBJECT_HANDLE_PTR CK_ULONG CK_ULONG_PTR pulObjectCount
CK_SLOT_ID CK_UTF8CHAR_PTR CK_ULONG CK_UTF8CHAR_PTR pLabel
CK_SESSION_HANDLE CK_MECHANISM_PTR CK_ATTRIBUTE_PTR CK_ULONG CK_OBJECT_HANDLE_PTR phKey
CK_SESSION_HANDLE CK_BYTE_PTR CK_ULONG CK_BYTE_PTR pSignature
@ SESSION_AUTHENTICATED_RW
@ SESSION_AUTHENTICATED_RO
@ SESSION_RESERVED_RO
@ SESSION_RESERVED_RW
#define SESSION_NOT_AUTHENTICATED
#define MAX_ECDH_SESSION_KEYS
#define SESSION_AUTHENTICATED
@ ATTRIBUTE_TRUE
@ OPERATION_FIND
@ OPERATION_DIGEST
@ OPERATION_ENCRYPT
@ OPERATION_SIGN
@ OPERATION_NOOP
@ OPERATION_VERIFY
@ OPERATION_DECRYPT
#define ECDH_KEY_TYPE