Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
ecdh_derive_test.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#ifdef NDEBUG
18#undef NDEBUG
19#endif
20#include <assert.h>
21#include <dlfcn.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <stdbool.h>
26
27#include <openssl/ec.h>
28#include <openssl/x509.h>
29
30#include "../pkcs11.h"
31
32#ifndef DEFAULT_CONNECTOR_URL
33#define DEFAULT_CONNECTOR_URL "http://127.0.0.1:12345"
34#endif
35
36#define BUFSIZE 1024
37
38CK_BYTE P224_PARAMS[] = {0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x21};
39CK_BYTE P256_PARAMS[] = {0x06, 0x08, 0x2a, 0x86, 0x48,
40 0xce, 0x3d, 0x03, 0x01, 0x07};
41CK_BYTE P384_PARAMS[] = {0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22};
42CK_BYTE P521_PARAMS[] = {0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23};
43
45CK_SESSION_HANDLE session;
46
47char *CURVES[] = {"secp224r1", "secp384r1", "secp521r1"};
50
51static void get_function_list(char *argv[]) {
52 void *handle = dlopen(argv[1], RTLD_NOW | RTLD_GLOBAL);
53 assert(handle != NULL);
54 CK_C_GetFunctionList fn;
55
56 *(void **) (&fn) = dlsym(handle, "C_GetFunctionList");
57 assert(fn != NULL);
58
59 CK_RV rv = ((CK_C_GetFunctionList) fn)(&p11);
60 assert(rv == CKR_OK);
61}
62
63static void open_session() {
64 CK_C_INITIALIZE_ARGS initArgs;
65 memset(&initArgs, 0, sizeof(initArgs));
66
67 const char *connector_url;
68 connector_url = getenv("DEFAULT_CONNECTOR_URL");
69 if (connector_url == NULL) {
70 connector_url = DEFAULT_CONNECTOR_URL;
71 }
72 char config[256];
73 assert(strlen(connector_url) + strlen("connector=") < 256);
74 sprintf(config, "connector=%s", connector_url);
75 initArgs.pReserved = (void *) config;
76 CK_RV rv = p11->C_Initialize(&initArgs);
77 assert(rv == CKR_OK);
78
80 &session);
81 assert(rv == CKR_OK);
82
83 const char *password = "0001password";
85 (CK_ULONG) strlen(password));
86 assert(rv == CKR_OK);
87 printf("Session open and authenticated\n");
88}
89
90static void close_session() {
91 CK_RV rv = p11->C_Logout(session);
92 assert(rv == CKR_OK);
93
94 rv = p11->C_Finalize(NULL);
95 assert(rv == CKR_OK);
96}
97
98static void print_session_state() {
100 CK_RV rv = p11->C_GetSessionInfo(session, &pInfo);
101 assert(rv == CKR_OK);
102 CK_STATE state = pInfo.state;
103
104 printf("session state: ");
105 switch (state) {
106 case 0:
107 printf("read-only public session\n");
108 break;
109 case 1:
110 printf("read-only user functions\n");
111 break;
112 case 2:
113 printf("read-write public session\n");
114 break;
115 case 3:
116 printf("read-write user functions\n");
117 break;
118 case 4:
119 printf("read-write so functions\n");
120 break;
121 default:
122 printf("unknown state\n");
123 break;
124 }
125}
126
127static void success(const char *message) { printf("%s. OK\n", message); }
128
129static void fail(const char *message) { printf("%s. FAIL!\n", message); }
130
131static bool destroy_object(CK_OBJECT_HANDLE key) {
132 if ((p11->C_DestroyObject(session, key)) != CKR_OK) {
133 printf("WARN. Failed to destroy object 0x%lx on HSM. FAIL\n", key);
134 return false;
135 }
136 return true;
137}
138
139static void generate_keypair_yh(CK_BYTE *curve,
140 CK_OBJECT_HANDLE_PTR publicKeyPtr,
141 CK_OBJECT_HANDLE_PTR privateKeyPtr) {
143
144 CK_BBOOL ck_true = CK_TRUE;
145
146 CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY;
147 CK_OBJECT_CLASS privkey_class = CKO_PRIVATE_KEY;
148 CK_KEY_TYPE key_type = CKK_EC;
149 char *label = "ecdhtest";
150
151 CK_ATTRIBUTE publicKeyTemplate[] = {{CKA_CLASS, &pubkey_class,
152 sizeof(pubkey_class)},
153 {CKA_VERIFY, &ck_true, sizeof(ck_true)},
155 sizeof(key_type)},
156 {CKA_LABEL, label, strlen(label)},
157 {CKA_EC_PARAMS, curve, sizeof(curve)}};
158
159 CK_ATTRIBUTE privateKeyTemplate[] = {{CKA_CLASS, &privkey_class,
160 sizeof(privkey_class)},
161 {CKA_LABEL, label, strlen(label)},
162 {CKA_DERIVE, &ck_true, sizeof(ck_true)}};
163
164 if ((p11->C_GenerateKeyPair(session, &mechanism, publicKeyTemplate, 5,
165 privateKeyTemplate, 3, publicKeyPtr,
166 privateKeyPtr)) != CKR_OK) {
167 fail("Failed to generate EC key pair on YubiHSM");
168 exit(EXIT_FAILURE);
169 }
170 success("Generated EC key pair on YubiHSM");
171}
172
173static EVP_PKEY *generate_keypair_openssl(const char *curve) {
174 EVP_PKEY *pkey = NULL;
175 EC_KEY *eckey = NULL;
176 OpenSSL_add_all_algorithms();
177 int eccgrp = OBJ_txt2nid(curve);
178 eckey = EC_KEY_new_by_curve_name(eccgrp);
179 if (!(EC_KEY_generate_key(eckey))) {
180 fail("Failed to generate EC keypair with openssl");
181 } else {
182 pkey = EVP_PKEY_new();
183 if (!EVP_PKEY_assign_EC_KEY(pkey, eckey)) {
184 fail("Failed to assign ECC key to EVP_PKEY structure");
185 }
186 }
187 return pkey;
188}
189
190static CK_ULONG get_yhsize(CK_OBJECT_HANDLE object) {
192 if ((p11->C_GetObjectSize(session, object, &len)) != CKR_OK) {
193 printf("Failed to get size of object 0x%lx from yubihsm-pkcs11. FAIL\n",
194 object);
195 return 0;
196 }
197 return len;
198}
199
200static CK_ULONG get_yhvalue(CK_OBJECT_HANDLE object, unsigned char *value,
201 CK_ULONG object_size) {
202 if (object_size > 0) {
203 CK_ATTRIBUTE template[] = {{CKA_VALUE, value, object_size}};
204 if ((p11->C_GetAttributeValue(session, object, template, 1)) == CKR_OK) {
205 return object_size;
206 } else {
207 printf("Failed to retrieve object value from yubihsm-pkcs11. 0x%lx\n",
208 object);
209 }
210 }
211 return 0;
212}
213
214static bool yh_derive(unsigned char *peerkey_bytes, int peerkey_len,
215 CK_OBJECT_HANDLE privkey, char *label,
219 params.pSharedData = NULL;
220 params.ulSharedDataLen = 0;
221 params.pPublicData = peerkey_bytes;
222 params.ulPublicDataLen = peerkey_len;
223
224 CK_MECHANISM mechanism = {CKM_ECDH1_DERIVE, (void *) &params, sizeof(params)};
225
226 CK_OBJECT_CLASS key_class = CKO_SECRET_KEY;
227 CK_KEY_TYPE key_type = CKK_GENERIC_SECRET;
228
229 CK_ATTRIBUTE derivedKeyTemplate[] = {{CKA_CLASS, &key_class,
230 sizeof(key_class)},
232 sizeof(key_type)},
233 {CKA_LABEL, label, strlen(label)}};
234
235 if ((p11->C_DeriveKey(session, &mechanism, privkey, derivedKeyTemplate, 3,
236 ecdh_key)) != CKR_OK) {
237 return false;
238 }
239 return true;
240}
241
242static bool yh_derive_ecdh(CK_OBJECT_HANDLE priv_key, EVP_PKEY *peer_keypair,
244 bool print_fail) {
245 EC_KEY *peerkey = EVP_PKEY_get1_EC_KEY(peer_keypair);
246 unsigned char *peerkey_bytes = NULL;
247 int peerkey_len = i2o_ECPublicKey(peerkey, &peerkey_bytes);
248 if (peerkey_len < 0) {
249 fail("Failed to extract public key from EC keypair generated with openssl");
250 return false;
251 }
252
253 EC_KEY_free(peerkey);
254
255 if (!yh_derive(peerkey_bytes, peerkey_len, priv_key, label, ecdh_key)) {
256 if (print_fail) {
257 fail("Failed to derive ECDH key on yubihsm-pkcs11");
258 }
259 OPENSSL_free(peerkey_bytes);
260 return false;
261 }
262
263 OPENSSL_free(peerkey_bytes);
264
265 return true;
266}
267
268static size_t openssl_derive(EVP_PKEY *private_key, EVP_PKEY *peer_key,
269 unsigned char **ecdh_key) {
270 /* Create the context for the shared secret derivation */
271 EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(private_key, NULL);
272 if (!ctx) {
273 fail("Failed to create new openssl context");
274 return 0;
275 }
276
277 size_t len = 0;
278 /* Initialize derivation function*/
279 if (EVP_PKEY_derive_init(ctx) != 1) {
280 fail("Failed to initialize openssl contex");
281 goto c_free;
282 }
283
284 /* Set the peer public key */
285 if (EVP_PKEY_derive_set_peer(ctx, peer_key) != 1) {
286 fail("Failed to set the peer public key in the openssl context");
287 goto c_free;
288 }
289
290 /* Determine buffer length for shared secret */
291 if (EVP_PKEY_derive(ctx, NULL, &len) != 1) {
292 fail("Failed to determine derived key expected size with openssl");
293 goto c_free;
294 }
295
296 /* Create the buffer */
297 *ecdh_key = OPENSSL_malloc(len);
298 if (*ecdh_key == NULL) {
299 fail("Failed to allocate the buffer to hold the ECDH key derived with "
300 "openssl");
301 len = 0;
302 goto c_free;
303 }
304
305 /* Derive the shared secret */
306 if ((EVP_PKEY_derive(ctx, *ecdh_key, &len)) != 1) {
307 fail("Failed to derive ECDH key with openssl");
308 len = 0;
309 goto c_free;
310 }
311
312c_free:
313 EVP_PKEY_CTX_free(ctx);
314 EVP_PKEY_free(peer_key);
315 EVP_PKEY_free(private_key);
316
317 return len;
318}
319
320static unsigned char *openssl_derive_ecdh(EVP_PKEY *private_key,
321 CK_OBJECT_HANDLE peer_key,
322 size_t *ecdh_len) {
323 CK_LONG peerkey_len = get_yhsize(peer_key);
324 if (peerkey_len == 0) {
325 return 0;
326 }
327
328 unsigned char peerkey_bytes[peerkey_len]; // public key in DER
329 if (get_yhvalue(peer_key, peerkey_bytes, peerkey_len) == 0) {
330 fail("Failed to retrieve public key from yubihsm-pkcs11");
331 return 0;
332 }
333
334 const unsigned char *p = peerkey_bytes;
335 EVP_PKEY *pkey = d2i_PUBKEY(NULL, &p, peerkey_len);
336
337 unsigned char *derivekey_openssl = NULL;
338 *ecdh_len = openssl_derive(private_key, pkey, &derivekey_openssl);
339 if (*ecdh_len == 0) {
340 fail("Failed to derive key with openssl");
341 }
342 return derivekey_openssl;
343}
344
345static bool test_ecdh_value(const char *curve, CK_OBJECT_HANDLE yh_privkey,
346 CK_OBJECT_HANDLE yh_pubkey,
347 CK_OBJECT_HANDLE_PTR ecdh1) {
348
349 // Generate keypair with openssl
350 EVP_PKEY *openssl_keypair = generate_keypair_openssl(curve);
351 if (openssl_keypair == NULL) {
352 return false;
353 }
354
355 // Derive with yubihsm
356 yh_derive_ecdh(yh_privkey, openssl_keypair, ecdh1, "ecdh1", true);
357
358 // Derive with openssl
359 size_t ecdh_openssl_len = 0;
360 unsigned char *ecdh_openssl =
361 openssl_derive_ecdh(openssl_keypair, yh_pubkey, &ecdh_openssl_len);
362 if (ecdh_openssl_len == 0) {
363 fail("Failed to derive key with openssl");
364 return false;
365 }
366
367 // Compare sizes
368 CK_ULONG ecdh1_len = get_yhsize(*ecdh1);
369 if (ecdh1_len != ecdh_openssl_len) {
370 fail(
371 "ECDH keys derived with yubihsm-pkcs11 and with openssl do not have the "
372 "same size");
373 return false;
374 }
375
376 // Compare values
377 unsigned char ecdh1_bytes[BUFSIZE]; // public key in DER
378 if (get_yhvalue(*ecdh1, ecdh1_bytes, ecdh1_len) == 0) {
379 fail("Failed to retrieve derived key from yubihsm-pkcs11");
380 return false;
381 }
382
383 bool equal = true;
384 for (unsigned int i = 0; i < ecdh_openssl_len; i++) {
385 if (ecdh1_bytes[i] != ecdh_openssl[i]) {
386 equal = false;
387 break;
388 }
389 }
390
391 OPENSSL_free(ecdh_openssl);
392
393 if (!equal) {
394 fail(
395 "ECDH keys derived with yubihsm-pkcs11 and with openssl do not have the "
396 "same value");
397 return false;
398 }
399
400 return true;
401}
402
403static bool test_duplicate_ecdh(const char *curve, CK_OBJECT_HANDLE yh_privkey,
405 CK_OBJECT_HANDLE_PTR ecdh3) {
406 EVP_PKEY *openssl_keypair = generate_keypair_openssl(curve);
407 if (openssl_keypair == NULL) {
408 return false;
409 }
410
411 if (!yh_derive_ecdh(yh_privkey, openssl_keypair, ecdh2, "ecdh2", true)) {
412 EVP_PKEY_free(openssl_keypair);
413 return false;
414 }
415 if (!yh_derive_ecdh(yh_privkey, openssl_keypair, ecdh3, "ecdh3", true)) {
416 EVP_PKEY_free(openssl_keypair);
417 return false;
418 }
419
420 EVP_PKEY_free(openssl_keypair);
421
422 size_t ecdh1_len = get_yhsize(*ecdh2);
423 size_t ecdh2_len = get_yhsize(*ecdh3);
424 if (ecdh1_len == 0 || ecdh2_len == 0) {
425 return false;
426 }
427
428 if (ecdh1_len != ecdh2_len) {
429 fail(
430 "2 ECDH keys derived from the same base keys do not have the same size");
431 return false;
432 }
433
434 unsigned char ecdh1_value[BUFSIZE], ecdh2_value[BUFSIZE];
435 if (get_yhvalue(*ecdh2, ecdh1_value, ecdh1_len) == 0) {
436 return false;
437 }
438 if (get_yhvalue(*ecdh3, ecdh2_value, ecdh2_len) == 0) {
439 return false;
440 }
441
442 bool equal = true;
443 for (unsigned int i = 0; i < ecdh1_len; i++) {
444 if (ecdh1_value[i] != ecdh2_value[i]) {
445 equal = false;
446 break;
447 }
448 }
449 if (!equal) {
450 fail(
451 "ECDH keys derived from the same base keys do not have the same value");
452 return false;
453 }
454
455 return true;
456}
457
458static bool test_faulty_ecdh(const char *curve1, const char *curve2,
459 CK_OBJECT_HANDLE_PTR yh_privkey,
461 // Derive from keys of different curves
462 EVP_PKEY *openssl_keypair = generate_keypair_openssl(curve2);
463 if (openssl_keypair == NULL) {
464 return false;
465 }
466
467 CK_OBJECT_HANDLE faulty_ecdh;
468 if (yh_derive_ecdh(*yh_privkey, openssl_keypair, &faulty_ecdh, "", false)) {
469 fail("Was able to derive ECDH key from EC keys of different curves");
470 EVP_PKEY_free(openssl_keypair);
471 return false;
472 }
473 EVP_PKEY_free(openssl_keypair);
474
475 // Derive key from another derived key
476 EVP_PKEY *key_openssl2 = generate_keypair_openssl(curve1);
477 if (yh_derive_ecdh(*ecdh_key, key_openssl2, &faulty_ecdh, "", false)) {
478 fail("Was able to derive ECDH key using another ECDH key");
479 EVP_PKEY_free(key_openssl2);
480 return false;
481 }
482 EVP_PKEY_free(key_openssl2);
483
484 // Derive key using the wrong mechanism
486
487 CK_OBJECT_CLASS key_class = CKO_SECRET_KEY;
488 CK_KEY_TYPE key_type = CKK_GENERIC_SECRET;
489 CK_ATTRIBUTE template[] = {
490 {CKA_CLASS, &key_class, sizeof(key_class)},
491 {CKA_KEY_TYPE, &key_type, sizeof(key_type)},
492 };
493
494 CK_RV rv = p11->C_DeriveKey(session, &mechanism, *yh_privkey, template, 2,
495 &faulty_ecdh);
496 if (rv != CKR_MECHANISM_INVALID) {
497 fail("Expected CKR_MECHANISM_INVALID when invalid mechanism is "
498 "specified");
499 return false;
500 }
501
502 return true;
503}
504
505static bool validate_ecdh_attributes(CK_OBJECT_HANDLE key_id,
506 char *expected_label) {
507
508 CK_OBJECT_CLASS key_class;
509 CK_KEY_TYPE key_type;
510 CK_BBOOL is_local;
511 CK_BBOOL is_token;
512 CK_BBOOL is_destroyable;
513 CK_BBOOL is_extractable;
514 CK_BBOOL is_never_extractable;
515 CK_BBOOL is_sensitive;
516 CK_BBOOL is_always_sensitive;
517 CK_BBOOL is_modifiable;
518 CK_BBOOL is_copyable;
519 CK_BBOOL is_sign;
520 CK_BBOOL is_sign_recover;
521 CK_BBOOL is_always_authenticated;
522 CK_BBOOL is_unwrap;
523 CK_BBOOL is_wrap;
524 CK_BBOOL is_wrap_with_trusted;
525 CK_BBOOL is_verify;
526 CK_BBOOL is_encrypt;
527 CK_BBOOL is_derive;
528
529 CK_BYTE publicValue[128];
530 char label[41] = {0};
531 size_t label_len = sizeof(label) - 1;
532
533 CK_ATTRIBUTE template[] =
534 {{CKA_CLASS, &key_class, sizeof(key_class)},
535 {CKA_KEY_TYPE, &key_type, sizeof(key_type)},
536 {CKA_LOCAL, &is_local, sizeof(is_local)},
537 {CKA_TOKEN, &is_token, sizeof(is_token)},
538 {CKA_DESTROYABLE, &is_destroyable, sizeof(is_destroyable)},
539 {CKA_EXTRACTABLE, &is_extractable, sizeof(is_extractable)},
540 {CKA_NEVER_EXTRACTABLE, &is_never_extractable,
541 sizeof(is_never_extractable)},
542 {CKA_SENSITIVE, &is_sensitive, sizeof(is_sensitive)},
543 {CKA_ALWAYS_SENSITIVE, &is_always_sensitive, sizeof(is_always_sensitive)},
544 {CKA_MODIFIABLE, &is_modifiable, sizeof(is_modifiable)},
545 {CKA_COPYABLE, &is_copyable, sizeof(is_copyable)},
546 {CKA_SIGN, &is_sign, sizeof(is_sign)},
547 {CKA_SIGN_RECOVER, &is_sign_recover, sizeof(is_sign_recover)},
548 {CKA_ALWAYS_AUTHENTICATE, &is_always_authenticated,
549 sizeof(is_always_authenticated)},
550 {CKA_UNWRAP, &is_unwrap, sizeof(is_unwrap)},
551 {CKA_WRAP, &is_wrap, sizeof(is_wrap)},
552 {CKA_WRAP_WITH_TRUSTED, &is_wrap_with_trusted,
553 sizeof(is_wrap_with_trusted)},
554 {CKA_VERIFY, &is_verify, sizeof(is_verify)},
555 {CKA_ENCRYPT, &is_encrypt, sizeof(is_encrypt)},
556 {CKA_DERIVE, &is_derive, sizeof(is_derive)},
557 {CKA_VALUE, &publicValue, sizeof(publicValue)},
559
560 CK_ULONG attribute_count = 22;
561
562 CK_RV rv =
563 p11->C_GetAttributeValue(session, key_id, template, attribute_count);
564 if (rv != CKR_OK) {
565 fail("Failed to retrieve ECDH key attributes from yubihsm-pkcs11");
566 return false;
567 }
568
569 if (key_class != CKO_SECRET_KEY) {
570 fail("Derived ECDH key class is not CKO_SECRET_KEY");
571 return false;
572 }
573
575 fail("Derived ECDH key type is not CKK_GENERIC_SECRET");
576 return false;
577 }
578
579 if (is_local != CK_FALSE) {
580 fail("Derived ECDH key LOCAL attribute is not CK_FALSE");
581 return false;
582 }
583
584 if (is_token != CK_FALSE) {
585 fail("Derived ECDH key TOKEN attribute is not CK_FALSE");
586 return false;
587 }
588
589 if (is_destroyable != CK_TRUE) {
590 fail("Derived ECDH key DESTROYABLE attribute is not CK_TRUE");
591 return false;
592 }
593
594 if (is_extractable != CK_TRUE) {
595 fail("Derived ECDH key EXTRACTABLE attribute is not CK_TRUE");
596 return false;
597 }
598
599 if (is_never_extractable != CK_FALSE) {
600 fail("Derived ECDH key NEVER_EXTRACTABLE attribute is not CK_FALSE");
601 return false;
602 }
603
604 if (is_sensitive != CK_FALSE) {
605 fail("Derived ECDH key SENSITIVE attribute is not CK_FALSE");
606 return false;
607 }
608
609 if (is_always_sensitive != CK_FALSE) {
610 fail("Derived ECDH key ALWAYS_SENSITIVE attribute is not CK_FALSE");
611 return false;
612 }
613
614 if (is_modifiable != CK_FALSE) {
615 fail("Derived ECDH key MODIFIABLE attribute is not CK_FALSE");
616 return false;
617 }
618
619 if (is_copyable != CK_FALSE) {
620 fail("Derived ECDH key COPYABLE attribute is not CK_FALSE");
621 return false;
622 }
623
624 if (is_sign != CK_FALSE) {
625 fail("Derived ECDH key SIGN attribute is not CK_FALSE");
626 return false;
627 }
628
629 if (is_sign_recover != CK_FALSE) {
630 fail("Derived ECDH key SIGN_RECOVER attribute is not CK_FALSE");
631 return false;
632 }
633
634 if (is_always_authenticated != CK_FALSE) {
635 fail("Derived ECDH key ALWAYS_AUTHENTICATED attribute is not CK_FALSE");
636 return false;
637 }
638
639 if (is_unwrap != CK_FALSE) {
640 fail("Derived ECDH key UNWRAP attribute is not CK_FALSE");
641 return false;
642 }
643
644 if (is_wrap != CK_FALSE) {
645 fail("Derived ECDH key WRAP attribute is not CK_FALSE");
646 return false;
647 }
648
649 if (is_wrap_with_trusted != CK_FALSE) {
650 fail("Derived ECDH key WRAP_WITH_TRUSTED attribute is not CK_FALSE");
651 return false;
652 }
653
654 if (is_verify != CK_FALSE) {
655 fail("Derived ECDH key VERIFY attribute is not CK_FALSE");
656 return false;
657 }
658
659 if (is_encrypt != CK_FALSE) {
660 fail("Derived ECDH key ENCRYPT attribute is not CK_FALSE");
661 return false;
662 }
663
664 if (is_derive != CK_FALSE) {
665 fail("Derived ECDH key DERIVE attribute is not CK_FALSE");
666 return false;
667 }
668
669 if (strcmp(label, expected_label) != 0) {
670 fail("Derived ECDH key does not have the expected label");
671 return false;
672 }
673
674 return true;
675}
676
677static bool find(CK_ATTRIBUTE template[], CK_ULONG attribute_count,
679 CK_OBJECT_HANDLE_PTR ecdh3, int expected_ecdh_count) {
680 bool ret = true;
681 if ((p11->C_FindObjectsInit(session, template, attribute_count)) != CKR_OK) {
682 fail("Failed to initialize search function");
683 return false;
684 } else {
685 int max_items_count = 256 + 255;
686 CK_OBJECT_HANDLE found_objects[max_items_count];
687 CK_ULONG total_objects_found;
688 if ((p11->C_FindObjects(session, found_objects, max_items_count,
689 &total_objects_found)) == CKR_OK) {
690 if ((expected_ecdh_count > 0) && (total_objects_found == 0)) {
691 fail("Not enough objects were found");
692 ret = false;
693 } else {
694 int found = 0;
695 for (size_t i = 0; i < total_objects_found; i++) {
696 if (found_objects[i] == *ecdh1 || found_objects[i] == *ecdh2 ||
697 found_objects[i] == *ecdh3) {
698 found++;
699 }
700 }
701 if (found != expected_ecdh_count) {
702 fail("Target object were not found or were found when they should "
703 "not have");
704 ret = false;
705 }
706 }
707 } else {
708 fail("Search operation failed");
709 ret = false;
710 }
711
713 fail("Failed to finalize search function");
714 ret = false;
715 }
716 }
717 return ret;
718}
719
720static bool find_secret_keys(CK_OBJECT_HANDLE_PTR ecdh1,
722 CK_OBJECT_HANDLE_PTR ecdh3) {
723 CK_OBJECT_CLASS secret_key_class = CKO_SECRET_KEY;
724
725 CK_ATTRIBUTE template[] = {
726 {CKA_CLASS, &secret_key_class, sizeof(secret_key_class)}};
727 return find(template, 1, ecdh1, ecdh2, ecdh3, 3);
728}
729
730static bool find_public_keys(CK_OBJECT_HANDLE_PTR ecdh1,
732 CK_OBJECT_HANDLE_PTR ecdh3) {
733 CK_OBJECT_CLASS public_key_class = CKO_PUBLIC_KEY;
734
735 CK_ATTRIBUTE template[] = {
736 {CKA_CLASS, &public_key_class, sizeof(public_key_class)}};
737 return find(template, 1, ecdh1, ecdh2, ecdh3, 0);
738}
739
740static bool find_secret_extractable_keys(CK_OBJECT_HANDLE_PTR ecdh1,
743 int expected_count) {
744 CK_OBJECT_CLASS secret_key_class = CKO_SECRET_KEY;
745 CK_BBOOL ck_true = CK_TRUE;
746
747 CK_ATTRIBUTE template[] = {{CKA_CLASS, &secret_key_class,
748 sizeof(secret_key_class)},
749 {CKA_EXTRACTABLE, &ck_true, sizeof(ck_true)}};
750 return find(template, 2, ecdh1, ecdh2, ecdh3, expected_count);
751}
752
753static bool find_secret_unextractable_keys(CK_OBJECT_HANDLE_PTR ecdh1,
755 CK_OBJECT_HANDLE_PTR ecdh3) {
756 CK_OBJECT_CLASS secret_key_class = CKO_SECRET_KEY;
757 CK_BBOOL ck_false = CK_FALSE;
758
759 CK_ATTRIBUTE template[] = {{CKA_CLASS, &secret_key_class,
760 sizeof(secret_key_class)},
761 {CKA_EXTRACTABLE, &ck_false, sizeof(ck_false)}};
762 return find(template, 2, ecdh1, ecdh2, ecdh3, 0);
763}
764
765static bool
766find_secret_extractable_keys_wrong_label(CK_OBJECT_HANDLE_PTR ecdh1,
768 CK_OBJECT_HANDLE_PTR ecdh3) {
769 CK_OBJECT_CLASS secret_key_class = CKO_SECRET_KEY;
770 CK_BBOOL ck_true = CK_TRUE;
771
772 char *label = "ecdhtest";
773 CK_ATTRIBUTE template[] = {{CKA_CLASS, &secret_key_class,
774 sizeof(secret_key_class)},
775 {CKA_EXTRACTABLE, &ck_true, sizeof(ck_true)},
776 {CKA_LABEL, label, strlen(label)}};
777 return find(template, 3, ecdh1, ecdh2, ecdh3, 0);
778}
779
780static bool find_secret_key_with_id(CK_OBJECT_HANDLE_PTR ecdh1,
784 CK_OBJECT_CLASS secret_key_class = CKO_SECRET_KEY;
785
786 CK_ATTRIBUTE template[] = {{CKA_CLASS, &secret_key_class,
787 sizeof(secret_key_class)},
788 {CKA_ID, key, sizeof(*key)}};
789 return find(template, 2, ecdh1, ecdh2, ecdh3, 0);
790}
791
792static bool find_secret_key_right_label(CK_OBJECT_HANDLE_PTR ecdh1,
794 CK_OBJECT_HANDLE_PTR ecdh3) {
795 CK_OBJECT_CLASS secret_key_class = CKO_SECRET_KEY;
796
797 char *label = "ecdh2";
798 CK_ATTRIBUTE template[] = {{CKA_CLASS, &secret_key_class,
799 sizeof(secret_key_class)},
800 {CKA_LABEL, label, strlen(label)}};
801 return find(template, 2, ecdh1, ecdh2, ecdh3, 1);
802}
803
804static bool find_public_key_right_label(CK_OBJECT_HANDLE_PTR ecdh1,
806 CK_OBJECT_HANDLE_PTR ecdh3) {
807
808 CK_OBJECT_CLASS public_key_class = CKO_PUBLIC_KEY;
809
810 CK_ATTRIBUTE template[] = {{CKA_CLASS, &public_key_class,
811 sizeof(public_key_class)},
812 {CKA_LABEL, "ecdh2", strlen("ecdh2")}};
813 return find(template, 2, ecdh1, ecdh2, ecdh3, 0);
814}
815
816static bool find_empty_template(CK_OBJECT_HANDLE_PTR ecdh1,
818 CK_OBJECT_HANDLE_PTR ecdh3) {
819 CK_ATTRIBUTE *template = NULL;
820 return find(template, 0, ecdh1, ecdh2, ecdh3, 3);
821}
822
823static bool test_decrypt(CK_OBJECT_HANDLE_PTR ecdh) {
824 CK_MECHANISM rsa_mechanism = {CKM_RSA_PKCS, NULL, 0};
825 if ((p11->C_DecryptInit(session, &rsa_mechanism, *ecdh)) !=
827 fail("Initializing decryption did not return the error code "
828 "CKR_KEY_TYPE_INCONSISTENT");
829 return false;
830 }
831 return true;
832}
833
834static bool test_sign(CK_OBJECT_HANDLE_PTR ecdh) {
835 CK_MECHANISM rsa_mechanism = {CKM_RSA_PKCS, NULL, 0};
836 if ((p11->C_SignInit(session, &rsa_mechanism, *ecdh)) !=
838 fail("Initializing signing did not return the error code "
839 "CKR_FUNCTION_NOT_SUPPORTED");
840 return false;
841 }
842 return true;
843}
844
845int main(int argc, char **argv) {
846
847 if (argc != 2) {
848 fprintf(stderr, "usage: /path/to/yubihsm_pkcs11/module\n");
849 exit(EXIT_FAILURE);
850 }
851
852 get_function_list(argv);
853 open_session();
854 print_session_state();
855
856 int exit_status = EXIT_SUCCESS;
857
858 CK_OBJECT_HANDLE yh_pubkey, yh_privkey;
859
860 for (int i = 0; i < CURVE_COUNT; i++) {
861
862 printf("\n/////// Testing curve %s\n", CURVES[i]);
863
864 generate_keypair_yh(CURVE_PARAMS[i], &yh_pubkey, &yh_privkey);
865 CK_OBJECT_HANDLE ecdh1, ecdh2, ecdh3;
866
867 printf("Testing the value of ECDH key derived by yubihsm-pkcs11... ");
868 if (test_ecdh_value(CURVES[i], yh_privkey, yh_pubkey, &ecdh1)) {
869 printf("OK!\n");
870 } else {
871 printf("FAIL!\n");
872 exit_status = EXIT_FAILURE;
873 goto c_clean;
874 }
875
876 printf(
877 "Testing that 2 ECDH keys derived from the same base keys are equal... ");
878 if (test_duplicate_ecdh(CURVES[i], yh_privkey, &ecdh2, &ecdh3)) {
879 printf("OK!\n");
880 } else {
881 printf("FAIL!\n");
882 exit_status = EXIT_FAILURE;
883 goto c_clean;
884 }
885
886 printf("Testing deriving ECDH keys with faulty parameters... ");
887 if (test_faulty_ecdh(CURVES[i], "prime256v1", &yh_privkey, &ecdh1)) {
888 printf("OK!\n");
889 } else {
890 printf("FAIL!\n");
891 exit_status = EXIT_FAILURE;
892 goto c_clean;
893 }
894
895 printf("Validating ECDH attributes... ");
896 if (validate_ecdh_attributes(ecdh1, "ecdh1")) {
897 printf("OK!\n");
898 } else {
899 printf("FAIL!\n");
900 exit_status = EXIT_FAILURE;
901 goto c_clean;
902 }
903
904 // ------- Start C_FindObjects functions test
905
906 printf("Finding ECDH keys: secret keys... ");
907 if (find_secret_keys(&ecdh1, &ecdh2, &ecdh3)) {
908 printf("OK!\n");
909 } else {
910 printf("FAIL!\n");
911 exit_status = EXIT_FAILURE;
912 goto c_clean;
913 }
914
915 printf("Finding ECDH keys: public keys... ");
916 if (find_public_keys(&ecdh1, &ecdh2, &ecdh3)) {
917 printf("OK!\n");
918 } else {
919 printf("FAIL!\n");
920 exit_status = EXIT_FAILURE;
921 goto c_clean;
922 }
923
924 printf("Finding ECDH keys: secret, extractable keys... ");
925 if (find_secret_extractable_keys(&ecdh1, &ecdh2, &ecdh3, 3)) {
926 printf("OK!\n");
927 } else {
928 printf("FAIL!\n");
929 exit_status = EXIT_FAILURE;
930 goto c_clean;
931 }
932
933 printf("Finding ECDH keys: secret, un-extractable keys... ");
934 if (find_secret_unextractable_keys(&ecdh1, &ecdh2, &ecdh3)) {
935 printf("OK!\n");
936 } else {
937 printf("FAIL!\n");
938 exit_status = EXIT_FAILURE;
939 goto c_clean;
940 }
941
942 printf("Finding ECDH keys: secret, extractable keys with wrong label... ");
943 if (find_secret_extractable_keys_wrong_label(&ecdh1, &ecdh2, &ecdh3)) {
944 printf("OK!\n");
945 } else {
946 printf("FAIL!\n");
947 exit_status = EXIT_FAILURE;
948 goto c_clean;
949 }
950
951 printf("Finding ECDH keys: secret key with specific ID... ");
952 if (find_secret_key_with_id(&ecdh1, &ecdh2, &ecdh3, &yh_privkey)) {
953 printf("OK!\n");
954 } else {
955 printf("FAIL!\n");
956 exit_status = EXIT_FAILURE;
957 goto c_clean;
958 }
959
960 printf("Finding ECDH keys: secret key with right label... ");
961 if (find_secret_key_right_label(&ecdh1, &ecdh2, &ecdh3)) {
962 printf("OK!\n");
963 } else {
964 printf("FAIL!\n");
965 exit_status = EXIT_FAILURE;
966 goto c_clean;
967 }
968
969 printf("Finding ECDH keys: public key with right label... ");
970 if (find_public_key_right_label(&ecdh1, &ecdh2, &ecdh3)) {
971 printf("OK!\n");
972 } else {
973 printf("FAIL!\n");
974 exit_status = EXIT_FAILURE;
975 goto c_clean;
976 }
977
978 printf("Finding ECDH keys: use empty template... ");
979 if (find_empty_template(&ecdh1, &ecdh2, &ecdh3)) {
980 printf("OK!\n");
981 } else {
982 printf("FAIL!\n");
983 exit_status = EXIT_FAILURE;
984 goto c_clean;
985 }
986
987 // ------- End C_FindObjects functions test
988
989 printf("Destroying ECDH key 1... ");
990 destroy_object(ecdh1);
991 if (find_secret_extractable_keys(&ecdh1, &ecdh2, &ecdh3, 2)) {
992 printf("OK!\n");
993 } else {
994 printf("FAIL!\n");
995 exit_status = EXIT_FAILURE;
996 goto c_clean;
997 }
998
999 printf("Destroying ECDH key 2... ");
1000 destroy_object(ecdh3);
1001 if (find_secret_extractable_keys(&ecdh1, &ecdh2, &ecdh3, 1)) {
1002 printf("OK!\n");
1003 } else {
1004 printf("FAIL!\n");
1005 exit_status = EXIT_FAILURE;
1006 goto c_clean;
1007 }
1008
1009 printf("Testing decryption... ");
1010 if (test_decrypt(&ecdh2)) {
1011 printf("OK!\n");
1012 } else {
1013 printf("FAIL!\n");
1014 exit_status = EXIT_FAILURE;
1015 goto c_clean;
1016 }
1017
1018 printf("Testing signing... ");
1019 if (test_sign(&ecdh2)) {
1020 printf("OK!\n");
1021 } else {
1022 printf("FAIL!\n");
1023 exit_status = EXIT_FAILURE;
1024 goto c_clean;
1025 }
1026
1027 printf("Destroying ECDH key 3... ");
1028 destroy_object(ecdh2);
1029 if (find_secret_extractable_keys(&ecdh1, &ecdh2, &ecdh3, 0)) {
1030 printf("OK!\n");
1031 } else {
1032 printf("FAIL!\n");
1033 exit_status = EXIT_FAILURE;
1034 goto c_clean;
1035 }
1036
1037 destroy_object(yh_privkey);
1038 }
1039
1040c_clean:
1041 if (exit_status == EXIT_FAILURE) {
1042 destroy_object(yh_privkey);
1043 }
1044 close_session();
1045 return (exit_status);
1046}
const mie::Vuint & p
Definition bn.cpp:27
CK_BYTE P384_PARAMS[]
CK_SESSION_HANDLE session
int CURVE_COUNT
#define DEFAULT_CONNECTOR_URL
CK_BYTE P224_PARAMS[]
CK_BYTE P521_PARAMS[]
CK_BYTE * CURVE_PARAMS[]
char * CURVES[]
CK_FUNCTION_LIST_PTR p11
#define BUFSIZE
CK_BYTE P256_PARAMS[]
char ** argv
RUNTIME_API Runtime::ObjectInstance * find(const std::string &name, const IR::ObjectType &type)
LOGGING_API void printf(Category category, const char *format,...)
Definition Logging.cpp:30
#define CKD_NULL
Definition pkcs11.h:732
#define CKA_NEVER_EXTRACTABLE
Definition pkcs11.h:417
#define CKA_TOKEN
Definition pkcs11.h:364
#define CKR_MECHANISM_INVALID
Definition pkcs11.h:1126
#define CKM_RSA_PKCS
Definition pkcs11.h:470
#define CKO_PUBLIC_KEY
Definition pkcs11.h:302
#define CK_FALSE
Definition pkcs11.h:1202
#define CKA_ID
Definition pkcs11.h:385
#define CKM_ECDH1_DERIVE
Definition pkcs11.h:652
#define value
Definition pkcs11.h:157
unsigned long int CK_ULONG
Definition pkcs11.h:1194
#define CKO_SECRET_KEY
Definition pkcs11.h:304
#define CKA_MODIFIABLE
Definition pkcs11.h:420
#define CKR_OK
Definition pkcs11.h:1092
#define CKF_RW_SESSION
Definition pkcs11.h:293
#define CKU_USER
Definition pkcs11.h:275
unsigned char CK_BYTE
Definition pkcs11.h:1190
#define NULL_PTR
Definition pkcs11.h:1257
#define CKA_SENSITIVE
Definition pkcs11.h:386
ck_object_handle_t * CK_OBJECT_HANDLE_PTR
Definition pkcs11.h:1232
#define CKA_SIGN_RECOVER
Definition pkcs11.h:392
#define CKA_SIGN
Definition pkcs11.h:391
#define CK_TRUE
Definition pkcs11.h:1203
#define CKA_VALUE
Definition pkcs11.h:368
#define CKA_LOCAL
Definition pkcs11.h:416
#define CKA_VERIFY
Definition pkcs11.h:393
#define CKO_PRIVATE_KEY
Definition pkcs11.h:303
#define CKF_SERIAL_SESSION
Definition pkcs11.h:294
#define CKA_COPYABLE
Definition pkcs11.h:421
#define CKM_EC_KEY_PAIR_GEN
Definition pkcs11.h:645
#define CKA_UNWRAP
Definition pkcs11.h:390
unsigned char CK_BBOOL
Definition pkcs11.h:1193
#define CKA_WRAP_WITH_TRUSTED
Definition pkcs11.h:429
#define CKA_KEY_TYPE
Definition pkcs11.h:383
#define CKA_ALWAYS_AUTHENTICATE
Definition pkcs11.h:428
#define CKK_GENERIC_SECRET
Definition pkcs11.h:326
#define CKA_DESTROYABLE
Definition pkcs11.h:422
#define CKA_DERIVE
Definition pkcs11.h:395
#define CKA_ALWAYS_SENSITIVE
Definition pkcs11.h:418
#define CKA_LABEL
Definition pkcs11.h:366
#define CKA_EXTRACTABLE
Definition pkcs11.h:415
#define CKR_FUNCTION_NOT_SUPPORTED
Definition pkcs11.h:1115
long int CK_LONG
Definition pkcs11.h:1195
#define CKA_ENCRYPT
Definition pkcs11.h:387
#define CKK_EC
Definition pkcs11.h:323
CK_UTF8CHAR * CK_UTF8CHAR_PTR
Definition pkcs11.h:1198
#define CKR_KEY_TYPE_INCONSISTENT
Definition pkcs11.h:1118
#define CKA_EC_PARAMS
Definition pkcs11.h:424
#define CKA_WRAP
Definition pkcs11.h:389
#define CKA_CLASS
Definition pkcs11.h:363
unsigned long kdf
Definition pkcs11.h:735
CK_C_OpenSession C_OpenSession
Definition pkcs11.h:1017
CK_C_Login C_Login
Definition pkcs11.h:1023
CK_C_GenerateKeyPair C_GenerateKeyPair
Definition pkcs11.h:1064
CK_C_FindObjectsFinal C_FindObjectsFinal
Definition pkcs11.h:1033
CK_C_DestroyObject C_DestroyObject
Definition pkcs11.h:1027
CK_C_FindObjectsInit C_FindObjectsInit
Definition pkcs11.h:1031
CK_C_FindObjects C_FindObjects
Definition pkcs11.h:1032
CK_C_DeriveKey C_DeriveKey
Definition pkcs11.h:1067
CK_C_SignInit C_SignInit
Definition pkcs11.h:1047
CK_C_Initialize C_Initialize
Definition pkcs11.h:1005
CK_C_Logout C_Logout
Definition pkcs11.h:1024
CK_C_GetAttributeValue C_GetAttributeValue
Definition pkcs11.h:1029
CK_C_DecryptInit C_DecryptInit
Definition pkcs11.h:1038
CK_C_GetObjectSize C_GetObjectSize
Definition pkcs11.h:1028
CK_C_Finalize C_Finalize
Definition pkcs11.h:1006
CK_C_GetSessionInfo C_GetSessionInfo
Definition pkcs11.h:1020
account_query_db::get_accounts_by_authorizers_params params
uint8_t key[16]
Definition yubico_otp.c:41
CK_SLOT_ID CK_SLOT_INFO_PTR pInfo
char * label
CK_RV ret
size_t len
CK_RV rv
uint16_t key_id
memset(pInfo->slotDescription, ' ', 64)
ecdh_session_key ecdh_key
size_t label_len
struct @108 key_type