Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
yubihsm.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 <yubihsm.h>
18#include "internal.h"
19
20#ifdef __WIN32
21#include <winsock.h>
22#else
23#include <arpa/inet.h>
24#include <dlfcn.h>
25#endif
26#include <errno.h>
27#include <stdlib.h>
28#include <string.h>
29#include <strings.h>
30#include <stdio.h>
31#include <limits.h>
32
33#include "../common/rand.h"
34#include "../common/pkcs5.h"
35#include "../common/hash.h"
36
38
39#include "debug_lib.h"
40
42
43#define STATIC_USB_BACKEND "usb"
44#define STATIC_HTTP_BACKEND "http"
45
46// If any of the values in scp.h are changed
47// they should be mirrored in yubihsm.h
48_Static_assert(SCP_HOST_CHAL_LEN == YH_HOST_CHAL_LEN,
49 "Host challenge length mismatch");
50_Static_assert(SCP_CONTEXT_LEN == YH_CONTEXT_LEN, "Context length mismatch");
51_Static_assert(SCP_MSG_BUF_SIZE == YH_MSG_BUF_SIZE,
52 "Message buffer size mismatch");
53_Static_assert(SCP_KEY_LEN == YH_KEY_LEN, "Message buffer size mismatch");
54
55#define LIST_SEPARATORS ":,;|"
56
58FILE *_yh_output YH_INTERNAL = NULL;
59
60static void compute_full_mac(uint8_t *data, uint16_t data_len, uint8_t *key,
61 uint16_t key_len, uint8_t *mac) {
62
64
65 insecure_memzero(&ctx, sizeof(ctx));
66 aes_cmac_init((uint8_t *) key, key_len, &ctx);
67 aes_cmac_encrypt(&ctx, data, data_len, mac);
68
69 DBG_CRYPTO(data, data_len, "Compute MAC (%3d Bytes): ", data_len);
70 DBG_CRYPTO(mac, SCP_PRF_LEN, "Full result is: ");
71
72 insecure_memzero(&ctx, sizeof(ctx));
73}
74
75static yh_rc send_msg(yh_connector *connector, Msg *msg, Msg *response) {
76
77 yh_rc yrc;
78 if (connector == NULL || connector->bf == NULL) {
79 DBG_ERR("No backend loaded");
81 }
82 DBG_NET(msg, dump_msg);
83 yrc = connector->bf->backend_send_msg(connector->connection, msg, response);
84 if (yrc == YHR_SUCCESS) {
85 DBG_NET(response, dump_response);
86 }
87 return yrc;
88}
89
90static yh_rc send_authenticated_msg(yh_session *session, Msg *msg,
91 Msg *response) {
92
94 uint16_t mac_buf_len;
95 uint16_t msg_len;
96
97 msg->st.len += SCP_MAC_LEN;
98 msg_len = msg->st.len;
99
100 if (msg->st.len > SCP_MSG_BUF_SIZE - 3) {
102 }
103
104 memcpy(mac_buf, session->s.mac_chaining_value, SCP_PRF_LEN);
105 msg->st.len = htons(msg->st.len);
106 memcpy(mac_buf + SCP_PRF_LEN, msg->raw, msg_len + 3 - SCP_MAC_LEN);
107 msg->st.len = ntohs(msg->st.len);
108 mac_buf_len = SCP_PRF_LEN + msg->st.len + 3 - SCP_MAC_LEN;
109 compute_full_mac(mac_buf, mac_buf_len, session->s.s_mac, SCP_KEY_LEN,
110 session->s.mac_chaining_value);
111 memcpy(msg->st.data + msg->st.len - SCP_MAC_LEN,
112 session->s.mac_chaining_value, SCP_MAC_LEN);
113
114 return send_msg(session->parent, msg, response);
115}
116
117static void increment_ctr(uint8_t ctr[SCP_PRF_LEN]) {
118
119 if (++ctr[SCP_PRF_LEN - 1] == 0) {
120 uint8_t i = SCP_PRF_LEN - 2;
121 while (!++ctr[i--] && i > 0)
122 ;
123 }
124}
125
127 const uint8_t *data, size_t data_len,
128 yh_cmd *response_cmd, uint8_t *response,
129 size_t *response_len) {
130
131 Msg msg;
132 Msg response_msg;
133
134 yh_rc yrc;
135
136 if (connector == NULL || (data_len != 0 && data == NULL) ||
137 response_cmd == NULL || response == NULL || response_len == NULL) {
140 }
141
142 if (data_len > sizeof(msg.st.data)) {
143 DBG_ERR("Tried to transfer oversized data (%zu > %zu)", data_len,
144 sizeof(msg.st.data));
146 }
147
148 msg.st.cmd = cmd;
149 msg.st.len = data_len;
150 if (data_len > 0) {
151 memcpy(msg.st.data, data, data_len);
152 }
153
154 DBG_DUMPINFO(msg.raw, data_len + 3, "Sending cmd %02x (%3zu Bytes): ", cmd,
155 data_len + 3);
156
157 yrc = send_msg(connector, &msg, &response_msg);
158 if (yrc != YHR_SUCCESS) {
159 DBG_ERR("%s", yh_strerror(yrc));
160 return yrc;
161 }
162
163 if (*response_len < response_msg.st.len) {
164 DBG_DUMPERR(response_msg.raw, response_msg.st.len + 3,
165 "%s (received %3d Bytes, can fit %3zu Bytes) ",
166 yh_strerror(YHR_BUFFER_TOO_SMALL), response_msg.st.len,
167 *response_len);
169 }
170
171 *response_cmd = response_msg.st.cmd;
172
173 memcpy(response, response_msg.st.data, response_msg.st.len);
174 *response_len = response_msg.st.len;
175
176 return YHR_SUCCESS;
177}
178
179static yh_rc translate_device_error(uint8_t device_error) {
180
181 enum {
182 _DEVICE_OK = 0x00, // No error
183 _DEVICE_INVALID_COMMAND = 0x01, // Invalid command
184 _DEVICE_INVALID_DATA = 0x02, // Malformed command / invalid data
185 _DEVICE_INVALID_SESSION = 0x03, // Invalid session
186 _DEVICE_AUTHENTICATION_FAILED =
187 0x04, // Message encryption / verification failed
188 _DEVICE_SESSIONS_FULL = 0x05, // All sessions are allocated
189 _DEVICE_SESSION_FAILED = 0x06, // Session creation failed
190 _DEVICE_STORAGE_FAILED = 0x07, // Storage failure
191 _DEVICE_WRONG_LENGTH = 0x08, // Wrong length
192 _DEVICE_INSUFFICIENT_PERMISSIONS = 0x09, // Wrong permissions for operation
193 _DEVICE_LOG_FULL = 0x0a, // Log buffer is full and forced audit is set
194 _DEVICE_OBJECT_NOT_FOUND = 0x0b, // Object not found
195 _DEVICE_INVALID_ID = 0x0c, // Invalid ID
196 _DEVICE_SSH_CA_CONSTRAINT_VIOLIATION = 0x0e, // CA constraint violation
197 _DEVICE_INVALID_OTP = 0x0f, // Invalid OTP
198 _DEVICE_DEMO_MODE = 0x10, // Demo mode, power cycle device
199 _DEVICE_OBJECT_EXISTS = 0x11, // Object with that ID already exists
200 _DEVICE_COMMAND_UNEXECUTED =
201 0xff, // The command execution has not terminated
202 };
203
204 switch (device_error) {
205 case _DEVICE_OK:
206 return YHR_DEVICE_OK;
207
208 case _DEVICE_INVALID_COMMAND:
210
211 case _DEVICE_INVALID_DATA:
213
214 case _DEVICE_INVALID_SESSION:
216
217 case _DEVICE_AUTHENTICATION_FAILED:
219
220 case _DEVICE_SESSIONS_FULL:
222
223 case _DEVICE_SESSION_FAILED:
225
226 case _DEVICE_STORAGE_FAILED:
228
229 case _DEVICE_WRONG_LENGTH:
231
232 case _DEVICE_INSUFFICIENT_PERMISSIONS:
234
235 case _DEVICE_LOG_FULL:
236 return YHR_DEVICE_LOG_FULL;
237
238 case _DEVICE_OBJECT_NOT_FOUND:
240
241 case _DEVICE_INVALID_ID:
243
244 case _DEVICE_SSH_CA_CONSTRAINT_VIOLIATION:
246
247 case _DEVICE_INVALID_OTP:
249
250 case _DEVICE_DEMO_MODE:
252
253 case _DEVICE_OBJECT_EXISTS:
255
256 case _DEVICE_COMMAND_UNEXECUTED:
258 }
259
260 return YHR_GENERIC_ERROR;
261}
262
263static yh_rc _send_secure_msg(yh_session *session, yh_cmd cmd,
264 const uint8_t *data, size_t data_len,
265 yh_cmd *response_cmd, uint8_t *response,
266 size_t *response_len) {
267
269 uint8_t decrypted_data[SCP_MSG_BUF_SIZE]; // NOTE(adma): this exists because
270 // OpenSSL encryption doesn't work
271 // when using the same buffer for in
272 // and out
273 uint8_t encrypted_ctr[SCP_PRF_LEN];
274 uint8_t mac_buf[SCP_PRF_LEN];
275 uint16_t work_buf_len;
277 aes_context aes_ctx;
278 yh_rc yrc;
279 Msg msg;
280 Msg response_msg;
281
282 insecure_memzero(&aes_ctx, sizeof(aes_ctx));
283
284 if (session == NULL || (data_len != 0 && data == NULL) ||
285 response_cmd == NULL || response == NULL || response_len == NULL) {
288 }
289
290 // Check length for the worst case
291 if (4 + data_len + SCP_PRF_LEN > SCP_MSG_BUF_SIZE) {
294 }
295
296 decrypted_data[0] = cmd;
297 decrypted_data[1] = (data_len & 0xff00) >> 8;
298 decrypted_data[2] = data_len & 0x00ff;
299 memcpy(decrypted_data + 3, data, data_len);
300 work_buf_len = 3 + data_len;
301
302 DBG_DUMPINFO(decrypted_data, data_len + 3,
303 "Sending cmd %02x (%3lu Bytes): ", cmd,
304 (unsigned long) data_len + 3);
305
306 aes_set_encrypt_key((uint8_t *) session->s.s_enc, SCP_KEY_LEN, &aes_ctx);
307
308 aes_add_padding(decrypted_data, &work_buf_len);
309
310 aes_encrypt(session->s.ctr, encrypted_ctr, &aes_ctx);
311
312 DBG_CRYPTO(decrypted_data, work_buf_len,
313 "CBC encrypting (%3d Bytes): ", work_buf_len);
314 DBG_CRYPTO(encrypted_ctr, SCP_PRF_LEN, "IV: ");
315
316 aes_cbc_encrypt(decrypted_data, work_buf + 1, work_buf_len, encrypted_ctr,
317 &aes_ctx); // Make room for sid
318
319 aes_destroy(&aes_ctx);
320
321 DBG_CRYPTO(work_buf + 1, work_buf_len,
322 "Ciphertext (%3d Bytes): ", work_buf_len);
323
324 msg.st.cmd = YHC_SESSION_MESSAGE;
325 msg.st.len = 1 + work_buf_len;
326 work_buf[0] = session->s.sid;
327 memcpy(msg.st.data, work_buf, work_buf_len + 1);
328
329 yrc = send_authenticated_msg(session, &msg, &response_msg);
330 if (yrc != YHR_SUCCESS) {
331 DBG_ERR("%s", yh_strerror(yrc));
332 goto cleanup;
333 }
334
335 if (response_msg.st.cmd == YHC_ERROR) {
336 yh_rc translated = translate_device_error(response_msg.st.data[0]);
337 DBG_ERR("%s", yh_strerror(translated));
338
339 *response_cmd = YHC_ERROR;
340 response[0] = response_msg.st.data[0];
341 *response_len = 1;
342
343 yrc = translated;
344 goto cleanup;
345 }
346
347 // Response is MAC'ed and encrypted. Unwrap it
348 out_len = response_msg.st.len;
349
350 memcpy(work_buf, session->s.mac_chaining_value, SCP_PRF_LEN);
351 response_msg.st.len = htons(response_msg.st.len);
352 memcpy(work_buf + SCP_PRF_LEN, response_msg.raw, 3 + out_len - SCP_MAC_LEN);
353 compute_full_mac(work_buf, SCP_PRF_LEN + 3 + out_len - SCP_MAC_LEN,
354 session->s.s_rmac, SCP_KEY_LEN, mac_buf);
355 response_msg.st.len = ntohs(response_msg.st.len);
356
357 if (memcmp(response_msg.st.data + response_msg.st.len - SCP_MAC_LEN, mac_buf,
358 SCP_MAC_LEN) != 0) {
359 DBG_DUMPERR(response_msg.st.data + out_len - SCP_MAC_LEN, SCP_MAC_LEN,
360 "%s, expected: ", yh_strerror(YHR_MAC_MISMATCH));
362 goto cleanup;
363 }
364
365 DBG_INFO("Response MAC successfully verified");
366
368
369 if (session->s.sid != response_msg.st.data[0]) {
370 DBG_ERR("Session ID mismatch, expected %d, got %d", session->s.sid,
371 response_msg.st.data[0]);
373 goto cleanup;
374 }
375 out_len -= 1;
376
377 // Recompute IV, apparently OpenSSL's CBC destroys it
378 aes_set_encrypt_key((uint8_t *) session->s.s_enc, SCP_KEY_LEN, &aes_ctx);
379 aes_encrypt(session->s.ctr, encrypted_ctr, &aes_ctx);
380
381 aes_set_decrypt_key(session->s.s_enc, SCP_KEY_LEN, &aes_ctx);
382
383 DBG_CRYPTO(response_msg.st.data + 1, out_len,
384 "CBC decrypting (%3d Bytes): ", out_len);
385 DBG_CRYPTO(encrypted_ctr, SCP_PRF_LEN, "IV: ");
386
387 aes_cbc_decrypt(response_msg.st.data + 1, decrypted_data, out_len,
388 encrypted_ctr, &aes_ctx);
389 aes_remove_padding(decrypted_data, &out_len);
390
391 aes_destroy(&aes_ctx);
392
393 DBG_CRYPTO(decrypted_data, out_len, "Plaintext (%3d Bytes): ", out_len);
394
395 increment_ctr(session->s.ctr);
396
397 out_len -= 3;
398 if (out_len > *response_len) {
400 goto cleanup;
401 }
402
403 *response_len = out_len;
404 *response_cmd = decrypted_data[0];
405 memcpy(response, decrypted_data + 3, *response_len);
406
407cleanup:
408
409 insecure_memzero(decrypted_data, sizeof(decrypted_data));
410
411 aes_destroy(&aes_ctx);
412
413 return yrc;
414}
415
417 size_t data_len, yh_cmd *response_cmd,
418 uint8_t *response, size_t *response_len) {
419
420 size_t saved_len = *response_len;
421
422 yh_rc yrc = _send_secure_msg(session, cmd, data, data_len, response_cmd,
423 response, response_len);
426 session->recreate) {
427 DBG_INFO("Recreating session");
428 yrc = yh_create_session(session->parent, session->authkey_id,
429 session->key_enc, SCP_KEY_LEN, session->key_mac,
430 SCP_KEY_LEN, true, &session);
431 if (yrc != YHR_SUCCESS) {
432 return yrc;
433 }
435 if (yrc != YHR_SUCCESS) {
436 return yrc;
437 }
438 *response_len = saved_len;
439 yrc = _send_secure_msg(session, cmd, data, data_len, response_cmd, response,
440 response_len);
441 }
442 return yrc;
443}
444
445static yh_rc compute_cryptogram(const uint8_t *key, uint16_t key_len,
447 uint16_t L, uint8_t *key_out) {
448
449 uint8_t n_iterations;
450 uint8_t i;
451 uint8_t result[SCP_KEY_LEN];
452 uint8_t input[16 + SCP_CONTEXT_LEN];
453 uint8_t *ptr = input;
454
456
457 if (L == 0x40 || L == 0x80)
458 n_iterations = 1;
459 else if (L == 0xc0 || L == 0x100)
460 n_iterations = 2;
461 else
463
464 // Label
465 memset(ptr, 0, 11);
466 ptr += 11;
467 *ptr++ = type;
468
469 // Delimiter byte
470 *ptr++ = 0;
471
472 // L
473 *ptr++ = (L & 0xff00) >> 8;
474 *ptr++ = (L & 0x00ff);
475
476 // i
477 *ptr++ = 0x01;
478
479 // Context
481 ptr += SCP_CONTEXT_LEN;
482
483 insecure_memzero(&ctx, sizeof(ctx));
484 aes_cmac_init((uint8_t *) key, key_len, &ctx);
485
486 for (i = 0; i < n_iterations; i++) {
487 aes_cmac_encrypt(&ctx, input, ptr - input, result + (i * SCP_PRF_LEN));
488
489 // Update i
490 input[15]++;
491 }
492
493 memcpy(key_out, result, L / 8);
494
495 aes_cmac_destroy(&ctx);
496
497 return YHR_SUCCESS;
498}
499
500/*
501 * Derive a session encryption key
502 * starting from a static encryption key
503 */
504static yh_rc derive_s_enc(Scp_ctx *ctx, const uint8_t *key_enc,
505 uint16_t key_enc_len, uint8_t *context) {
506
507 return compute_cryptogram(key_enc, key_enc_len, SCP_S_ENC_DERIVATION, context,
508 SCP_KEY_LEN * 8, ctx->s_enc);
509}
510
511/*
512 * Derive a session message authentication key
513 * starting from a static message authentication key
514 */
515static yh_rc derive_s_mac(Scp_ctx *ctx, const uint8_t *key_mac,
516 uint16_t key_mac_len,
518
519 // ctx->s_mac_len = s_mac_len / 8;
520
521 return compute_cryptogram(key_mac, key_mac_len, SCP_S_MAC_DERIVATION, context,
522 SCP_KEY_LEN * 8, ctx->s_mac);
523}
524
525/*
526 * Derive a session message authentication key
527 * for responses starting from a static message
528 * authentication key
529 */
530static yh_rc derive_s_rmac(Scp_ctx *ctx, const uint8_t *key_mac,
531 uint16_t key_mac_len,
533
534 // ctx->s_rmac_len = s_rmac_len / 8;
535
536 return compute_cryptogram(key_mac, key_mac_len, SCP_S_RMAC_DERIVATION,
537 context, SCP_KEY_LEN * 8, ctx->s_rmac);
538}
539
540/*
541 * Recompute and verify a card cryptogram
542 */
543static yh_rc
544verify_card_cryptogram(Scp_ctx *ctx, uint8_t context[SCP_CONTEXT_LEN],
545 uint8_t card_cryptogram[SCP_CARD_CRYPTO_LEN]) {
546
547 uint8_t calculated_card_cryptogram[SCP_CARD_CRYPTO_LEN];
548 yh_rc yrc;
549
550 yrc =
551 compute_cryptogram(ctx->s_mac, SCP_KEY_LEN, SCP_CARD_CRYPTOGRAM, context,
552 SCP_CARD_CRYPTO_LEN * 8, calculated_card_cryptogram);
553 if (yrc != YHR_SUCCESS) {
554 return yrc;
555 }
556
557 return memcmp(card_cryptogram, calculated_card_cryptogram,
561}
562
563/*
564 * Compute a host cryptogram
565 */
566static yh_rc compute_host_cryptogram(yh_session *session,
567 uint8_t *host_cryptogram) {
568
569 return compute_cryptogram(session->s.s_mac, SCP_KEY_LEN, SCP_HOST_CRYPTOGRAM,
570 session->context, SCP_HOST_CRYPTO_LEN * 8,
571 host_cryptogram);
572}
573
574static yh_rc derive_keys(const uint8_t *password, size_t password_len,
575 uint8_t *key_enc, uint8_t *key_mac) {
576
577 uint8_t key[SCP_KEY_LEN * 2];
578
579 if (!pkcs5_pbkdf2_hmac(password, password_len,
580 (const uint8_t *) YH_DEFAULT_SALT,
582 key, sizeof(key))) {
583 return YHR_GENERIC_ERROR;
584 }
585
586 memcpy(key_enc, key, SCP_KEY_LEN);
587 memcpy(key_mac, key + SCP_KEY_LEN, SCP_KEY_LEN);
588 insecure_memzero(&key, sizeof(key));
589
590 return YHR_SUCCESS;
591}
592
594 const uint8_t *password, size_t password_len,
595 bool recreate, yh_session **session) {
596
597 if (connector == NULL || password == NULL || session == NULL) {
600 }
601
602 uint8_t key_enc[SCP_KEY_LEN];
603 uint8_t key_mac[SCP_KEY_LEN];
604
605 yh_rc yrc = derive_keys(password, password_len, key_enc, key_mac);
606
607 if (yrc == YHR_SUCCESS) {
608 yrc = yh_create_session(connector, authkey_id, key_enc, SCP_KEY_LEN,
609 key_mac, SCP_KEY_LEN, recreate, session);
610 insecure_memzero(key_enc, sizeof(key_enc));
611 insecure_memzero(key_mac, sizeof(key_mac));
612 }
613 return yrc;
614}
615
617 const uint8_t *key_enc, size_t key_enc_len,
618 const uint8_t *key_mac, size_t key_mac_len,
619 bool recreate, yh_session **session) {
620
621 Msg msg;
622 Msg response_msg;
623 yh_rc yrc;
624 uint8_t *ptr;
625 uint8_t card_cryptogram[SCP_CARD_CRYPTO_LEN];
626 yh_session *new_session;
627 uint8_t host_challenge[YH_HOST_CHAL_LEN];
628
629 if (connector == NULL || key_enc == NULL || key_enc_len != SCP_KEY_LEN ||
630 key_mac == NULL || key_mac_len != SCP_KEY_LEN || session == NULL) {
633 }
634
635 if (!rand_generate(host_challenge, sizeof(host_challenge))) {
636 return YHR_GENERIC_ERROR;
637 }
638
639 if (!*session) {
640 new_session = calloc(1, sizeof(yh_session));
641 if (new_session == NULL) {
643 return YHR_MEMORY_ERROR;
644 }
645 } else {
646 new_session = *session;
647 }
648
649 new_session->authkey_id = authkey_id;
650
651 if (recreate) {
652 new_session->recreate = true;
653 memcpy(new_session->key_enc, key_enc, SCP_KEY_LEN);
654 memcpy(new_session->key_mac, key_mac, SCP_KEY_LEN);
655 }
656
657 // Send CREATE SESSION command
658 msg.st.cmd = YHC_CREATE_SESSION;
660
661 uint16_t authkey_id_n = htons(authkey_id);
662 memcpy(msg.st.data, &authkey_id_n, SCP_AUTHKEY_ID_LEN);
663 memcpy(msg.st.data + SCP_AUTHKEY_ID_LEN, host_challenge, SCP_HOST_CHAL_LEN);
664 memcpy(new_session->context, host_challenge, SCP_HOST_CHAL_LEN);
665
666 DBG_INT(host_challenge, SCP_HOST_CHAL_LEN, "Host challenge: ");
667
668 yrc = send_msg(connector, &msg, &response_msg);
669 if (yrc != YHR_SUCCESS) {
670 goto cs_failure;
671 }
672
673 // Parse response
674 if (response_msg.st.cmd != YHC_CREATE_SESSION_R) {
675 yh_rc translated = translate_device_error(response_msg.st.data[0]);
676 DBG_ERR("Device error %s (%d)", yh_strerror(translated),
677 response_msg.st.data[0]);
678 yrc = translated;
679 goto cs_failure;
680 }
681
682 if (response_msg.st.len != 1 + SCP_CARD_CHAL_LEN + SCP_CARD_CRYPTO_LEN) {
684 goto cs_failure;
685 }
686
687 ptr = response_msg.st.data;
688
689 // Save sid
690 new_session->s.sid = (*ptr++);
691
692 // Save card challenge
694 ptr += SCP_CARD_CHAL_LEN;
695
696 memcpy(card_cryptogram, ptr, SCP_CARD_CRYPTO_LEN);
697 ptr += SCP_CARD_CRYPTO_LEN;
698
699 DBG_INFO("Received Session ID: %d", new_session->s.sid);
700
702 "Card challenge: ");
703 DBG_INT(card_cryptogram, SCP_CARD_CRYPTO_LEN, "Card cryptogram: ");
704
705 // Derive session keys
706 yrc =
707 derive_s_enc(&new_session->s, key_enc, key_enc_len, new_session->context);
708 if (yrc != YHR_SUCCESS)
709 goto cs_failure;
710
711 yrc =
712 derive_s_mac(&new_session->s, key_mac, key_mac_len, new_session->context);
713 if (yrc != YHR_SUCCESS)
714 goto cs_failure;
715
716 yrc =
717 derive_s_rmac(&new_session->s, key_mac, key_enc_len, new_session->context);
718 if (yrc != YHR_SUCCESS)
719 goto cs_failure;
720
721 DBG_INT(new_session->s.s_enc, SCP_KEY_LEN, "S-ENC: ");
722 DBG_INT(new_session->s.s_mac, SCP_KEY_LEN, "S-MAC: ");
723 DBG_INT(new_session->s.s_rmac, SCP_KEY_LEN, "S-RMAC: ");
724 // Verify card cryptogram
725 yrc = verify_card_cryptogram(&new_session->s, new_session->context,
726 card_cryptogram);
727 if (yrc != YHR_SUCCESS) {
728 DBG_ERR("%s", yh_strerror(yrc));
729 goto cs_failure;
730 }
731
732 DBG_INFO("Card cryptogram successfully verified");
733
734 // Save link back to connector
735 new_session->parent = connector;
736
737 *session = new_session;
738
739 return YHR_SUCCESS;
740
741cs_failure:
742 insecure_memzero(new_session, sizeof(yh_session));
743 free(new_session);
744 (new_session) = NULL;
745
746 DBG_ERR("%s", yh_strerror(yrc));
747
748 return yrc;
749}
750
752 uint8_t **context, uint8_t *card_cryptogram,
753 size_t card_cryptogram_len,
755
756 Msg msg;
757 Msg response_msg;
758 yh_rc yrc;
759 uint8_t *ptr;
760 yh_session *new_session;
761 uint8_t host_challenge[YH_HOST_CHAL_LEN];
762
763 if (connector == NULL || context == NULL || card_cryptogram == NULL ||
764 card_cryptogram_len != SCP_CARD_CRYPTO_LEN || session == NULL) {
767 }
768
769 if (!rand_generate(host_challenge, sizeof(host_challenge))) {
770 return YHR_GENERIC_ERROR;
771 } // TODO(adma): take this as an input so that it can be generated from the
772 // YubiKey
773
774 /**********/
775 // TODO(adma): replace with func
776 new_session = calloc(1, sizeof(yh_session));
777 if (new_session == NULL) {
779 return YHR_MEMORY_ERROR;
780 }
781
782 // Send CREATE SESSION command
783 msg.st.cmd = YHC_CREATE_SESSION;
785
786 uint16_t authkey_id_n = htons(authkey_id);
787 memcpy(msg.st.data, &authkey_id_n, SCP_AUTHKEY_ID_LEN);
788 memcpy(msg.st.data + SCP_AUTHKEY_ID_LEN, host_challenge, SCP_HOST_CHAL_LEN);
789 memcpy(new_session->context, host_challenge, SCP_HOST_CHAL_LEN);
790
791 DBG_INT(host_challenge, SCP_HOST_CHAL_LEN, "Host challenge: ");
792
793 yrc = send_msg(connector, &msg, &response_msg);
794 if (yrc != YHR_SUCCESS) {
795 goto bcse_failure;
796 }
797
798 // Parse response
799 if (response_msg.st.cmd != YHC_CREATE_SESSION_R) {
800 yh_rc translated = translate_device_error(response_msg.st.data[0]);
801 DBG_ERR("Device error %s (%d)", yh_strerror(translated),
802 response_msg.st.data[0]);
803 yrc = translated;
804 goto bcse_failure;
805 }
806
807 if (response_msg.st.len != 1 + SCP_CARD_CHAL_LEN + SCP_CARD_CRYPTO_LEN) {
809 goto bcse_failure;
810 }
811
812 ptr = response_msg.st.data;
813
814 // Save sid
815 new_session->s.sid = (*ptr++);
816
817 // Save card challenge
819 ptr += SCP_CARD_CHAL_LEN;
820
821 memcpy(card_cryptogram, ptr, SCP_CARD_CRYPTO_LEN);
822 ptr += SCP_CARD_CRYPTO_LEN;
823
824 DBG_INFO("Received Session ID: %d", new_session->s.sid);
825
827 "Card challenge: ");
828 DBG_INT(card_cryptogram, SCP_CARD_CRYPTO_LEN, "Card cryptogram: ");
829
830 // Save link back to connector
831 new_session->parent = connector;
832
833 *session = new_session;
834 *context = new_session->context;
835
836 return YHR_SUCCESS;
837
838bcse_failure:
839 free(new_session);
840 (new_session) = NULL;
841
842 DBG_ERR("%s", yh_strerror(yrc));
843
844 return yrc;
845}
846
848 yh_connector *connector, yh_session *session, const uint8_t *key_senc,
849 size_t key_senc_len, const uint8_t *key_smac, size_t key_smac_len,
850 const uint8_t *key_srmac, size_t key_srmac_len, uint8_t *card_cryptogram,
851 size_t card_cryptogram_len) { // TODO(adma): remove all these
852
853 if (connector == NULL || session == NULL || key_senc == NULL ||
854 key_senc_len != YH_KEY_LEN || key_smac == NULL ||
855 key_smac_len != YH_KEY_LEN || key_srmac == NULL ||
856 key_srmac_len != YH_KEY_LEN || card_cryptogram == NULL ||
857 card_cryptogram_len != SCP_CARD_CRYPTO_LEN) {
860 }
861
862 yh_rc yrc;
863
864 memcpy(session->s.s_enc, key_senc, key_senc_len);
865 memcpy(session->s.s_mac, key_smac, key_smac_len);
866 memcpy(session->s.s_rmac, key_srmac, key_srmac_len);
867
868 DBG_INT(session->s.s_enc, SCP_KEY_LEN, "S-ENC: ");
869 DBG_INT(session->s.s_mac, SCP_KEY_LEN, "S-MAC: ");
870 DBG_INT(session->s.s_rmac, SCP_KEY_LEN, "S-RMAC: ");
871
872 // Verify card cryptogram
873 yrc = verify_card_cryptogram(&session->s, session->context, card_cryptogram);
874 if (yrc != YHR_SUCCESS) {
875 DBG_ERR("%s", yh_strerror(yrc));
876
877 free(session);
878 session = NULL;
879
880 DBG_ERR("%s", yh_strerror(yrc));
881
882 return yrc;
883 }
884
885 DBG_INFO("Card cryptogram successfully verified");
886
887 return YHR_SUCCESS;
888}
889
891
892 if (session == NULL) {
895 } else if (*session == NULL) {
896 return YHR_SUCCESS;
897 }
898
900 free(*session);
901 *session = NULL;
902
903 return YHR_SUCCESS;
904}
905
907
908 return connector && connector->has_device;
909}
910
913
914 if (connector == NULL || major == NULL || minor == NULL || patch == NULL) {
917 }
918
919 *major = connector->version_major;
920 *minor = connector->version_minor;
921 *patch = connector->version_patch;
922
923 return YHR_SUCCESS;
924}
925
926yh_rc yh_get_connector_address(yh_connector *connector, char **const address) {
927
928 if (connector == NULL || address == NULL) {
931 }
932
933 *address = (char *) connector->address;
934
935 return YHR_SUCCESS;
936}
937
940 uint8_t *log_total, uint8_t *log_used,
941 yh_algorithm *algorithms, size_t *n_algorithms) {
942
943 if (connector == NULL) {
946 }
947
948 yh_rc yrc;
949
950#pragma pack(push, 1)
951 union {
952 struct {
957 uint8_t log_total;
958 uint8_t log_used;
960 };
961 uint8_t buf[1];
962 } response;
963#pragma pack(pop)
964 size_t response_len = sizeof(response);
965 yh_cmd response_cmd;
966
967 yrc = yh_send_plain_msg(connector, YHC_GET_DEVICE_INFO, NULL, 0,
968 &response_cmd, response.buf, &response_len);
969 if (yrc != YHR_SUCCESS) {
970 DBG_ERR("Failed to send GET DEVICE INFO command: %s", yh_strerror(yrc));
971 return yrc;
972 }
973
974 if (response_cmd == YHC_ERROR) {
975 yh_rc translated = translate_device_error(response.buf[0]);
976 DBG_ERR("Unable to get data: %s (%x)", yh_strerror(translated),
977 response.buf[0]);
978 return translated;
979 }
980
981 if (major != NULL) {
982 *major = response.major;
983 }
984
985 if (minor != NULL) {
986 *minor = response.minor;
987 }
988
989 if (patch != NULL) {
990 *patch = response.patch;
991 }
992
993 if (serial != NULL) {
994 *serial = ntohl(response.serial);
995 }
996
997 if (log_total != NULL) {
998 *log_total = response.log_total;
999 }
1000
1001 if (log_used != NULL) {
1002 *log_used = response.log_used;
1003 }
1004
1005 if (algorithms != NULL && n_algorithms) {
1006 size_t items = response_len - sizeof(response.major) -
1007 sizeof(response.minor) - sizeof(response.patch) -
1008 sizeof(response.serial) - sizeof(response.log_total) -
1009 sizeof(response.log_used);
1010 if (*n_algorithms < items) {
1011 DBG_ERR("Algorithms buffer too small");
1012 return YHR_BUFFER_TOO_SMALL;
1013 }
1014 for (size_t i = 0; i < items; i++) {
1015 algorithms[i] = response.algorithms[i];
1016 }
1017 *n_algorithms = items;
1018 }
1019
1020 return YHR_SUCCESS;
1021}
1022
1023#define LIST_ID 1
1024#define LIST_TYPE 2
1025#define LIST_DOMAINS 3
1026#define LIST_CAPABILITIES 4
1027#define LIST_ALGORITHM 5
1028#define LIST_LABEL 6
1029
1033 yh_algorithm algorithm, const char *label,
1034 yh_object_descriptor *objects, size_t *n_objects) {
1035
1036 if (session == NULL || objects == NULL || n_objects == NULL ||
1037 (label != NULL && strlen(label) > YH_OBJ_LABEL_LEN)) {
1040 }
1041
1043 uint8_t *dataptr = data;
1044
1045 uint8_t response[YH_MSG_BUF_SIZE];
1046 size_t response_len = sizeof(response);
1047
1048 yh_rc yrc;
1049 yh_cmd response_cmd;
1050
1051 if (id) {
1052 *dataptr++ = LIST_ID;
1053 *dataptr++ = id >> 8 & 0xff;
1054 *dataptr++ = id & 0xff;
1055 }
1056
1057 if (type) {
1058 *dataptr++ = LIST_TYPE;
1059 *dataptr++ = type;
1060 }
1061
1062 if (domains) {
1063 *dataptr++ = LIST_DOMAINS;
1064 *dataptr++ = domains >> 8 & 0xff;
1065 *dataptr++ = domains & 0xff;
1066 }
1067
1068 if (algorithm) {
1069 *dataptr++ = LIST_ALGORITHM;
1070 *dataptr++ = algorithm;
1071 }
1072
1073 if (label && strlen(label)) {
1074 *dataptr++ = LIST_LABEL;
1075 memcpy(dataptr, label, strlen(label));
1076 memset(dataptr + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
1077 dataptr += YH_OBJ_LABEL_LEN;
1078 }
1079
1080 bool send_capabilities = false;
1081 for (uint16_t i = 0; i < YH_CAPABILITIES_LEN; i++) {
1082 if (capabilities->capabilities[i]) {
1083 send_capabilities = true;
1084 break;
1085 }
1086 }
1087
1088 if (send_capabilities == true) {
1089 *dataptr++ = LIST_CAPABILITIES;
1090 for (uint16_t i = 0; i < YH_CAPABILITIES_LEN; i++) {
1091 *dataptr++ = capabilities->capabilities[i];
1092 }
1093 }
1094
1095 yrc = yh_send_secure_msg(session, YHC_LIST_OBJECTS, data, dataptr - data,
1096 &response_cmd, response, &response_len);
1097 if (yrc != YHR_SUCCESS) {
1098 DBG_ERR("Failed to send LIST OBJECTS command: %s", yh_strerror(yrc));
1099 return yrc;
1100 }
1101
1102 if (response_cmd == YHC_ERROR) {
1103 yh_rc translated = translate_device_error(response[0]);
1104 DBG_ERR("Unable to list objects: %s (%x)", yh_strerror(translated),
1105 response[0]);
1106 return translated;
1107 }
1108
1109 if ((response_len / 4) > *n_objects) {
1110 DBG_ERR("Objects buffer too small");
1111 return YHR_BUFFER_TOO_SMALL;
1112 }
1113
1114 *n_objects = response_len / 4;
1115 for (uint16_t i = 0; i < response_len; i += 4) {
1116 // NOTE: clear the fields that we didn't set
1117 memset(&objects[i / 4], 0, sizeof(yh_object_descriptor));
1118 objects[i / 4].id = ntohs(*((uint16_t *) (response + i)));
1119 objects[i / 4].type = response[i + 2];
1120 objects[i / 4].sequence = response[i + 3];
1121 }
1122
1123 DBG_INFO("Found %zu objects", *n_objects);
1124
1125 return YHR_SUCCESS;
1126}
1127
1129 yh_object_type type,
1130 yh_object_descriptor *object) {
1131
1132 if (session == NULL) {
1135 }
1136
1137 uint8_t data[3];
1138 uint8_t *dataptr = data;
1139
1140#pragma pack(push, 1)
1141 union {
1142 struct {
1144 uint16_t id;
1145 uint16_t len;
1147 uint8_t type;
1149 uint8_t sequence;
1150 uint8_t origin;
1153 };
1154 uint8_t buf[1];
1155 } response;
1156 size_t response_len = sizeof(response);
1157#pragma pack(pop)
1158
1159 yh_rc yrc;
1160 yh_cmd response_cmd;
1161
1162 *dataptr++ = id >> 8 & 0xff;
1163 *dataptr++ = id & 0xff;
1164
1165 *dataptr++ = (uint16_t) type;
1166
1167 yrc = yh_send_secure_msg(session, YHC_GET_OBJECT_INFO, data, sizeof(data),
1168 &response_cmd, response.buf, &response_len);
1169 if (yrc != YHR_SUCCESS) {
1170 DBG_ERR("Failed to send GET OBJECT INFO command: %s", yh_strerror(yrc));
1171 return yrc;
1172 }
1173
1174 if (response_cmd == YHC_ERROR) {
1175 yh_rc translated = translate_device_error(response.buf[0]);
1176 DBG_ERR("Unable to get object info: %s (%x)", yh_strerror(translated),
1177 response.buf[0]);
1178 return translated;
1179 }
1180
1181 if (response_len == sizeof(response)) {
1182 if (object) {
1183 memcpy(object->capabilities.capabilities, response.capabilities,
1185
1186 object->id = htons(response.id);
1187
1188 object->len = htons(response.len);
1189
1190 object->domains = htons(response.domains);
1191
1192 object->type = response.type;
1193
1194 object->algorithm = response.algorithm;
1195
1196 object->sequence = response.sequence;
1197
1198 object->origin = response.origin;
1199
1200 memcpy(object->label, response.label, YH_OBJ_LABEL_LEN);
1201 object->label[YH_OBJ_LABEL_LEN] = 0;
1202
1204 response.delegated_capabilities, YH_CAPABILITIES_LEN);
1205 }
1206 } else {
1207 DBG_ERR("Wrong response length, expecting %lu or 0, received %lu",
1208 (unsigned long) sizeof(yh_object_descriptor),
1209 (unsigned long) response_len);
1210 return YHR_WRONG_LENGTH;
1211 }
1212
1213 return YHR_SUCCESS;
1214}
1215
1217 size_t *data_len, yh_algorithm *algorithm) {
1218
1219 if (session == NULL || data == NULL || data_len == NULL) {
1222 }
1223
1224 uint8_t cmd[2] = {id >> 8, id & 0xff};
1225 yh_cmd response_cmd;
1226 uint8_t response[YH_MSG_BUF_SIZE];
1227 size_t response_len = sizeof(response);
1228
1229 yh_rc yrc = yh_send_secure_msg(session, YHC_GET_PUBLIC_KEY, cmd, sizeof(cmd),
1230 &response_cmd, response, &response_len);
1231
1232 if (yrc != YHR_SUCCESS) {
1233 DBG_ERR("Failed to send GET PUBLIC KEY command: %s", yh_strerror(yrc));
1234 return yrc;
1235 }
1236
1237 if (response_cmd == YHC_ERROR) {
1238 yh_rc translated = translate_device_error(response[0]);
1239 DBG_ERR("Unable to get public key: %s (%x)", yh_strerror(translated),
1240 response[0]);
1241 return translated;
1242 }
1243
1244 if (response_len > *data_len) {
1245 return YHR_BUFFER_TOO_SMALL;
1246 }
1247
1248 if (algorithm) {
1249 *algorithm = *response;
1250 }
1251 *data_len = response_len - 1;
1252 memcpy(data, response + 1, *data_len);
1253
1254 return YHR_SUCCESS;
1255}
1256
1258
1259 if (session == NULL) {
1262 }
1263
1264 yh_rc yrc;
1265
1266 uint8_t response[5];
1267 size_t response_len = sizeof(response);
1268 yh_cmd response_cmd;
1269
1270 yrc = yh_send_secure_msg(session, YHC_CLOSE_SESSION, NULL, 0, &response_cmd,
1271 response, &response_len);
1272 if (yrc != YHR_SUCCESS) {
1273 DBG_ERR("Failed to send CLOSE SESSION command: %s", yh_strerror(yrc));
1274 return yrc;
1275 }
1276
1277 if (response_cmd == YHC_ERROR) {
1278 yh_rc translated = translate_device_error(response[0]);
1279 DBG_ERR("Unable to close session: %s (%x)", yh_strerror(translated),
1280 response[0]);
1281 return translated;
1282 }
1283
1284 return YHR_SUCCESS;
1285}
1286
1288 const uint8_t *in, size_t in_len, uint8_t *out,
1289 size_t *out_len) {
1290
1291 if (session == NULL || in == NULL || out == NULL || out_len == NULL) {
1294 }
1295
1296 if (hashed)
1297 switch (in_len) {
1298 case 20:
1299 case 32:
1300 case 48:
1301 case 64:
1302 break;
1303
1304 default:
1305 DBG_ERR("Data length must be 20, 32, 48 or 64");
1307 }
1308
1309 yh_rc yrc;
1310
1311#pragma pack(push, 1)
1312 union {
1313 struct {
1315 uint8_t bytes[YH_MSG_BUF_SIZE];
1316 };
1317 uint8_t buf[1];
1318 } data;
1319#pragma pack(pop)
1320 uint16_t data_len;
1321
1322 yh_cmd response_cmd;
1323
1324 data.key_id = htons(key_id);
1325
1326 memcpy(data.bytes, in, in_len);
1327 data_len = in_len;
1328
1329 yrc = yh_send_secure_msg(session, YHC_SIGN_PKCS1, data.buf, data_len + 2,
1330 &response_cmd, out, out_len);
1331 if (yrc != YHR_SUCCESS) {
1332 DBG_ERR("Failed to send SIGN PKCS1 command: %s", yh_strerror(yrc));
1333 return yrc;
1334 }
1335
1336 if (response_cmd == YHC_ERROR) {
1337 yh_rc translated = translate_device_error(out[0]);
1338 DBG_ERR("Unable to get signature: %s (%x)", yh_strerror(translated),
1339 out[0]);
1340 return translated;
1341 }
1342
1343 return YHR_SUCCESS;
1344}
1345
1347 size_t in_len, uint8_t *out, size_t *out_len,
1348 size_t salt_len, yh_algorithm mgf1Algo) {
1349
1350 if (session == NULL || in == NULL || out == NULL || out_len == NULL) {
1353 }
1354
1355 switch (in_len) {
1356 case 20:
1357 case 32:
1358 case 48:
1359 case 64:
1360 break;
1361
1362 default:
1363 DBG_ERR("Data length must be 20, 32, 48 or 64");
1365 }
1366
1367 yh_rc yrc;
1368
1369#pragma pack(push, 1)
1370 union {
1371 struct {
1373 uint8_t mgf1Algo;
1374 uint16_t salt_len;
1375 uint8_t bytes[YH_MSG_BUF_SIZE];
1376 };
1377 uint8_t buf[1];
1378 } data;
1379#pragma pack(pop)
1380 uint16_t data_len = in_len;
1381
1382 yh_cmd response_cmd;
1383
1384 data.key_id = htons(key_id);
1385
1386 data.mgf1Algo = mgf1Algo;
1387
1388 // NOTE(adma): 'in' is already a hash of the data, which type is inferred from
1389 // the length
1390 data.salt_len = htons(salt_len);
1391
1392 memcpy(data.bytes, in, in_len);
1393
1394 yrc = yh_send_secure_msg(session, YHC_SIGN_PSS, data.buf, data_len + 5,
1395 &response_cmd, out, out_len);
1396 if (yrc != YHR_SUCCESS) {
1397 DBG_ERR("Failed to send SIGN PSS command: %s", yh_strerror(yrc));
1398 return yrc;
1399 }
1400
1401 if (response_cmd == YHC_ERROR) {
1402 yh_rc translated = translate_device_error(out[0]);
1403 DBG_ERR("Unable to get signature: %s (%x)", yh_strerror(translated),
1404 out[0]);
1405 return translated;
1406 }
1407
1408 return YHR_SUCCESS;
1409}
1410
1412 const uint8_t *in, size_t in_len, uint8_t *out,
1413 size_t *out_len) {
1414
1415 if (session == NULL || in == NULL || out == NULL || out_len == NULL) {
1418 }
1419
1420 switch (in_len) {
1421 case 20:
1422 case 28: // p224..
1423 case 32:
1424 case 48:
1425 case 64:
1426 case 66: // p521 needs 66 bytes input
1427 break;
1428
1429 default:
1430 DBG_ERR("Data length must be 20, 28, 32, 48, 64 or 66");
1432 }
1433
1434 yh_rc yrc;
1435
1436#pragma pack(push, 1)
1437 union {
1438 struct {
1440 uint8_t bytes[YH_MSG_BUF_SIZE];
1441 };
1442 uint8_t buf[1];
1443 } data;
1444#pragma pack(pop)
1445 uint16_t data_len = in_len;
1446
1447 yh_cmd response_cmd;
1448
1449 data.key_id = htons(key_id);
1450
1451 memcpy(data.bytes, in, in_len);
1452
1453 yrc = yh_send_secure_msg(session, YHC_SIGN_ECDSA, data.buf, data_len + 2,
1454 &response_cmd, out, out_len);
1455 if (yrc != YHR_SUCCESS) {
1456 DBG_ERR("Failed to send SIGN ECDSA command: %s", yh_strerror(yrc));
1457 return yrc;
1458 }
1459
1460 if (response_cmd == YHC_ERROR) {
1461 yh_rc translated = translate_device_error(out[0]);
1462 DBG_ERR("Unable to get signature: %s (%x)", yh_strerror(translated),
1463 out[0]);
1464 return translated;
1465 }
1466
1467 return YHR_SUCCESS;
1468}
1469
1471 const uint8_t *in, size_t in_len, uint8_t *out,
1472 size_t *out_len) {
1473
1474 if (session == NULL || in == NULL || out == NULL || out_len == NULL) {
1477 }
1478
1479 if (in_len > YH_MSG_BUF_SIZE - 2) {
1480 DBG_ERR("Too much data, must be < %d", YH_MSG_BUF_SIZE - 2);
1482 }
1483
1484 yh_rc yrc;
1485
1486#pragma pack(push, 1)
1487 union {
1488 struct {
1490 uint8_t bytes[YH_MSG_BUF_SIZE];
1491 };
1492 uint8_t buf[1];
1493 } data;
1494#pragma pack(pop)
1495 uint16_t data_len = in_len;
1496
1497 yh_cmd response_cmd;
1498
1499 data.key_id = htons(key_id);
1500
1501 memcpy(data.bytes, in, in_len);
1502
1503 yrc = yh_send_secure_msg(session, YHC_SIGN_EDDSA, data.buf, data_len + 2,
1504 &response_cmd, out, out_len);
1505 if (yrc != YHR_SUCCESS) {
1506 DBG_ERR("Failed to send SIGN EDDSA command: %s", yh_strerror(yrc));
1507 return yrc;
1508 }
1509
1510 if (response_cmd == YHC_ERROR) {
1511 yh_rc translated = translate_device_error(out[0]);
1512 DBG_ERR("Unable to get signature: %s (%x)", yh_strerror(translated),
1513 out[0]);
1514 return translated;
1515 }
1516
1517 return YHR_SUCCESS;
1518}
1519
1521 size_t in_len, uint8_t *out, size_t *out_len) {
1522
1523 if (session == NULL || in == NULL || out == NULL || out_len == NULL) {
1526 }
1527
1528 if (in_len > YH_MSG_BUF_SIZE - 2) {
1529 DBG_ERR("Too much data, must be < %d", YH_MSG_BUF_SIZE - 2);
1531 }
1532
1534 uint16_t data_len = 2;
1535
1536 yh_cmd response_cmd;
1537
1538 data[0] = htons(key_id) & 0xff;
1539 data[1] = htons(key_id) >> 8;
1540
1541 memcpy(data + 2, in, in_len);
1542 data_len += in_len;
1543
1544 yh_rc yrc = yh_send_secure_msg(session, YHC_SIGN_HMAC, data, data_len,
1545 &response_cmd, out, out_len);
1546 if (yrc != YHR_SUCCESS) {
1547 DBG_ERR("Failed to send SIGN HMAC command: %s", yh_strerror(yrc));
1548 return yrc;
1549 }
1550
1551 if (response_cmd == YHC_ERROR) {
1552 yh_rc translated = translate_device_error(out[0]);
1553 DBG_ERR("Unable to get data: %s (%x)", yh_strerror(translated), out[0]);
1554 return translated;
1555 }
1556
1557 return YHR_SUCCESS;
1558}
1559
1561 size_t *out_len) {
1562 yh_rc yrc;
1563 yh_cmd response_cmd;
1564
1565 if (session == NULL || out == NULL || out_len == NULL) {
1568 }
1569
1570 union {
1571 uint16_t len;
1572 uint8_t buf[2];
1573 } data;
1574 data.len = htons(len);
1575
1576 yrc = yh_send_secure_msg(session, YHC_GET_PSEUDO_RANDOM, data.buf,
1577 sizeof(data), &response_cmd, out, out_len);
1578 if (yrc != YHR_SUCCESS) {
1579 DBG_ERR("Failed to send GET PSEUDO RANDOM command: %s", yh_strerror(yrc));
1580 return yrc;
1581 }
1582
1583 if (response_cmd == YHC_ERROR) {
1584 yh_rc translated = translate_device_error(out[0]);
1585 DBG_ERR("Unable to get data: %s (%x)", yh_strerror(translated), out[0]);
1586 return translated;
1587 }
1588
1589 return yrc;
1590}
1591
1592static yh_rc import_asymmetric(yh_session *session, uint16_t *key_id,
1593 const char *label, uint16_t domains,
1595 yh_algorithm algorithm, const uint8_t *key,
1596 uint16_t key_len) {
1597#pragma pack(push, 1)
1598 union {
1599 struct {
1604 uint8_t algo;
1605 uint8_t bytes[512];
1606 };
1607 uint8_t buf[1];
1608 } k;
1609 union {
1610 struct {
1612 };
1613 uint8_t buf[1];
1614 } response;
1615#pragma pack(pop)
1616 size_t response_len = sizeof(response);
1617 yh_cmd response_cmd;
1618
1619 k.key_id = htons(*key_id);
1620
1621 memcpy(k.label, label, strlen(label));
1622 memset(k.label + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
1623
1624 k.domains = htons(domains);
1625
1626 k.algo = algorithm;
1627
1628 memcpy(k.capabilities, capabilities, YH_CAPABILITIES_LEN);
1629
1630 memcpy(k.bytes, key, key_len);
1631
1632 uint16_t len = sizeof(k.key_id) + sizeof(k.domains) + sizeof(k.capabilities) +
1633 sizeof(k.algo) + sizeof(k.label) + key_len;
1634 yh_rc yrc = yh_send_secure_msg(session, YHC_PUT_ASYMMETRIC_KEY, k.buf, len,
1635 &response_cmd, response.buf, &response_len);
1636 insecure_memzero(k.buf, len);
1637 if (yrc != YHR_SUCCESS) {
1638 DBG_ERR("Failed to send PUT ASYMMETRIC KEY command: %s", yh_strerror(yrc));
1639 return yrc;
1640 }
1641
1642 if (response_cmd == YHC_ERROR) {
1643 yh_rc translated = translate_device_error(response.buf[0]);
1644 DBG_ERR("Unable to put key: %s (%x)", yh_strerror(translated),
1645 response.buf[0]);
1646 return translated;
1647 }
1648
1649 *key_id = ntohs(response.key_id);
1650 DBG_INFO("Stored Asymmetric key 0x%04x", *key_id);
1651
1652 return yrc;
1653}
1654
1656 const char *label, uint16_t domains,
1659 const uint8_t *q) {
1660
1661 if (session == NULL || key_id == NULL || label == NULL ||
1662 strlen(label) > YH_OBJ_LABEL_LEN || p == NULL || q == NULL) {
1665 }
1666
1667 uint8_t keybuf[256 * 2];
1668 uint16_t component_len;
1669
1670 if (algorithm == YH_ALGO_RSA_2048) {
1671 component_len = 128;
1672 } else if (algorithm == YH_ALGO_RSA_3072) {
1673 component_len = 192;
1674 } else if (algorithm == YH_ALGO_RSA_4096) {
1675 component_len = 256;
1676 } else {
1678 }
1679 memcpy(keybuf, p, component_len);
1680 memcpy(keybuf + component_len, q, component_len);
1681
1682 yh_rc yrc = import_asymmetric(session, key_id, label, domains, capabilities,
1683 algorithm, keybuf, component_len * 2);
1684 insecure_memzero(keybuf, sizeof(keybuf));
1685
1686 return yrc;
1687}
1688
1690 const char *label, uint16_t domains,
1692 yh_algorithm algorithm, const uint8_t *s) {
1693
1694 if (session == NULL || key_id == NULL || label == NULL ||
1695 strlen(label) > YH_OBJ_LABEL_LEN || s == NULL) {
1698 }
1699
1700 uint16_t component_len;
1701 switch (algorithm) {
1702 case YH_ALGO_EC_P224:
1703 component_len = 28;
1704 break;
1705 case YH_ALGO_EC_P256:
1706 case YH_ALGO_EC_K256:
1707 case YH_ALGO_EC_BP256:
1708 component_len = 32;
1709 break;
1710 case YH_ALGO_EC_P384:
1711 case YH_ALGO_EC_BP384:
1712 component_len = 48;
1713 break;
1714 case YH_ALGO_EC_BP512:
1715 component_len = 64;
1716 break;
1717 case YH_ALGO_EC_P521:
1718 component_len = 66;
1719 break;
1720 default:
1722 }
1723 return import_asymmetric(session, key_id, label, domains, capabilities,
1724 algorithm, s, component_len);
1725}
1726
1728 const char *label, uint16_t domains,
1730 yh_algorithm algorithm, const uint8_t *k) {
1731
1732 if (session == NULL || key_id == NULL || label == NULL ||
1733 strlen(label) > YH_OBJ_LABEL_LEN || k == NULL) {
1736 }
1737
1738 uint16_t component_len;
1739 switch (algorithm) {
1740 case YH_ALGO_EC_ED25519:
1741 component_len = 32;
1742 break;
1743 default:
1745 }
1746 return import_asymmetric(session, key_id, label, domains, capabilities,
1747 algorithm, k, component_len);
1748}
1749
1751 const char *label, uint16_t domains,
1753 yh_algorithm algorithm, const uint8_t *key,
1754 size_t key_len) {
1755
1756 if (session == NULL || key_id == NULL || label == NULL ||
1757 strlen(label) > YH_OBJ_LABEL_LEN || key == NULL) {
1760 }
1761
1762#pragma pack(push, 1)
1763 union {
1764 struct {
1770 uint8_t key[128];
1771 };
1772 uint8_t buf[1];
1773 } k;
1774 union {
1775 struct {
1777 };
1778 uint8_t buf[1];
1779 } response;
1780#pragma pack(pop)
1781 yh_rc yrc;
1782 size_t response_len = sizeof(response);
1783 yh_cmd response_cmd;
1784 size_t max_len = 64;
1785 int len = sizeof(k) - sizeof(k.key);
1786
1787 k.key_id = htons(*key_id);
1788
1789 memcpy(k.label, label, strlen(label));
1790 memset(k.label + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
1791
1792 k.domains = htons(domains);
1793
1794 k.algorithm = algorithm;
1795
1796 memcpy(k.capabilities, capabilities, YH_CAPABILITIES_LEN);
1797
1799 max_len = 128;
1800 }
1801
1802 if (key_len > max_len) {
1803 DBG_ERR("Too long key supplied, max %lu bytes allowed",
1804 (unsigned long) max_len);
1805 return YHR_WRONG_LENGTH;
1806 }
1807
1808 memcpy(k.key, key, key_len);
1809 len += key_len;
1810
1811 yrc = yh_send_secure_msg(session, YHC_PUT_HMAC_KEY, k.buf, len, &response_cmd,
1812 response.buf, &response_len);
1813 insecure_memzero(k.buf, len);
1814 if (yrc != YHR_SUCCESS) {
1815 DBG_ERR("Failed to send PUT HMAC KEY command: %s", yh_strerror(yrc));
1816 return yrc;
1817 }
1818
1819 if (response_cmd == YHC_ERROR) {
1820 yh_rc translated = translate_device_error(response.buf[0]);
1821 DBG_ERR("Unable to put key: %s (%x)", yh_strerror(translated),
1822 response.buf[0]);
1823 return translated;
1824 }
1825
1826 *key_id = ntohs(response.key_id);
1827 DBG_INFO("Stored HMAC key 0x%04x", *key_id);
1828
1829 return yrc;
1830}
1831
1832static yh_rc generate_key(yh_session *session, uint16_t *key_id,
1833 const char *label, uint16_t domains,
1836
1837 if (session == NULL || key_id == NULL || label == NULL ||
1838 strlen(label) > YH_OBJ_LABEL_LEN) {
1841 }
1842
1843 yh_rc yrc;
1844
1845#pragma pack(push, 1)
1846 union {
1847 struct {
1852 uint8_t algo;
1853 };
1854 uint8_t buf[1];
1855 } data;
1856 int data_len = sizeof(data);
1857 union {
1858 struct {
1860 };
1861 uint8_t buf[1];
1862 } response;
1863#pragma pack(pop)
1864 size_t response_len = sizeof(response);
1865 yh_cmd response_cmd;
1866
1867 data.key_id = htons(*key_id);
1868
1869 memcpy(data.label, label, strlen(label));
1870 memset(data.label + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
1871
1872 data.domains = htons(domains);
1873
1874 data.algo = algorithm;
1875
1876 memcpy(data.capabilities, capabilities, YH_CAPABILITIES_LEN);
1877
1878 yrc =
1879 yh_send_secure_msg(session, YHC_GENERATE_ASYMMETRIC_KEY, data.buf, data_len,
1880 &response_cmd, response.buf, &response_len);
1881 if (yrc != YHR_SUCCESS) {
1882 DBG_ERR("Failed to send GENERATE ASYMMETRIC KEY command: %s",
1883 yh_strerror(yrc));
1884 return yrc;
1885 }
1886
1887 if (response_cmd == YHC_ERROR) {
1888 yh_rc translated = translate_device_error(response.buf[0]);
1889 DBG_ERR("Unable to generate key: %s (%x)", yh_strerror(translated),
1890 response.buf[0]);
1891 return translated;
1892 }
1893
1894 *key_id = ntohs(response.key_id);
1895 DBG_INFO("Generated Asymmetric key 0x%04x", *key_id);
1896
1897 return YHR_SUCCESS;
1898}
1899
1901 const char *label, uint16_t domains,
1904
1905 if (!yh_is_rsa(algorithm)) {
1906 DBG_ERR("Invalid algorithm %d", algorithm);
1908 }
1909
1910 return generate_key(session, key_id, label, domains, capabilities, algorithm);
1911}
1912
1914 const char *label, uint16_t domains,
1917
1918 if (!yh_is_ec(algorithm)) {
1919 DBG_ERR("Invalid algorithm %d", algorithm);
1921 }
1922
1923 return generate_key(session, key_id, label, domains, capabilities, algorithm);
1924}
1925
1927 const char *label, uint16_t domains,
1930
1931 if (!yh_is_ed(algorithm)) {
1932 DBG_ERR("Invalid algorithm %d", algorithm);
1934 }
1935
1936 return generate_key(session, key_id, label, domains, capabilities, algorithm);
1937}
1938
1940 const uint8_t *signature, size_t signature_len,
1941 const uint8_t *data, size_t data_len,
1942 bool *verified) {
1943
1944 if (session == NULL || signature == NULL || data == NULL ||
1945 verified == NULL) {
1948 }
1949
1950 if (data_len + signature_len > YH_MSG_BUF_SIZE - 2) {
1951 DBG_ERR("Too much data, must be < %d", YH_MSG_BUF_SIZE - 2);
1953 }
1954
1955 yh_rc yrc;
1956
1957 uint8_t cmd_data[YH_MSG_BUF_SIZE];
1958 int cmd_data_len;
1959
1960 uint8_t response[3];
1961 size_t response_len = sizeof(response);
1962 yh_cmd response_cmd;
1963
1964 key_id = htons(key_id);
1965
1966 memcpy(cmd_data, (uint8_t *) &key_id, 2);
1967 cmd_data_len = 2;
1968 memcpy(cmd_data + cmd_data_len, signature, signature_len);
1969 cmd_data_len += signature_len;
1970 memcpy(cmd_data + cmd_data_len, data, data_len);
1971 cmd_data_len += data_len;
1972
1973 yrc = yh_send_secure_msg(session, YHC_VERIFY_HMAC, cmd_data, cmd_data_len,
1974 &response_cmd, response, &response_len);
1975 if (yrc != YHR_SUCCESS) {
1976 DBG_ERR("Failed to send HMAC VERIFY command: %s", yh_strerror(yrc));
1977 return yrc;
1978 }
1979
1980 if (response_cmd == YHC_ERROR) {
1981 yh_rc translated = translate_device_error(response[0]);
1982 DBG_ERR("Unable to verify data: %s (%x)", yh_strerror(translated),
1983 response[0]);
1984 return translated;
1985 }
1986
1987 *verified = response[0];
1988
1989 return YHR_SUCCESS;
1990}
1991
1993 const char *label, uint16_t domains,
1996
1997 if (session == NULL || label == NULL || strlen(label) > YH_OBJ_LABEL_LEN ||
1998 key_id == NULL) {
2001 }
2002
2003 yh_rc yrc;
2004
2005#pragma pack(push, 1)
2006 union {
2007 struct {
2013 };
2014 uint8_t buf[1];
2015 } data;
2016 union {
2017 struct {
2019 };
2020 uint8_t buf[1];
2021 } response;
2022#pragma pack(pop)
2023
2024 size_t response_len = sizeof(response);
2025 yh_cmd response_cmd;
2026
2027 data.key_id = htons(*key_id);
2028
2029 memcpy(data.label, label, strlen(label));
2030 memset(data.label + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
2031
2032 data.domains = htons(domains);
2033
2034 memcpy(data.capabilities, capabilities, YH_CAPABILITIES_LEN);
2035
2036 data.algorithm = algorithm;
2037
2038 yrc =
2039 yh_send_secure_msg(session, YHC_GENERATE_HMAC_KEY, data.buf, sizeof(data),
2040 &response_cmd, response.buf, &response_len);
2041 if (yrc != YHR_SUCCESS) {
2042 DBG_ERR("Failed to send GENERATE HMAC command: %s", yh_strerror(yrc));
2043 return yrc;
2044 }
2045
2046 if (response_cmd == YHC_ERROR) {
2047 yh_rc translated = translate_device_error(response.buf[0]);
2048 DBG_ERR("Unable to generate key: %s (%x)", yh_strerror(translated),
2049 response.buf[0]);
2050 return translated;
2051 }
2052
2053 *key_id = ntohs(response.key_id);
2054 DBG_INFO("Generated HMAC key 0x%04x", *key_id);
2055
2056 return YHR_SUCCESS;
2057}
2058
2060 const uint8_t *in, size_t in_len, uint8_t *out,
2061 size_t *out_len) {
2062
2063 if (session == NULL || in == NULL || out == NULL || out_len == NULL) {
2066 }
2067
2068 if (in_len > YH_MSG_BUF_SIZE - 2) {
2069 DBG_ERR("Too much data, must be < %d", YH_MSG_BUF_SIZE - 2);
2071 }
2072
2073#pragma pack(push, 1)
2074 union {
2075 struct {
2077 uint8_t bytes[YH_MSG_BUF_SIZE];
2078 };
2079 uint8_t buf[1];
2080 } data;
2081#pragma pack(pop)
2082
2083 yh_cmd response_cmd;
2084 yh_rc yrc;
2085
2086 data.key_id = htons(key_id);
2087
2088 memcpy(data.bytes, in, in_len);
2089
2090 yrc = yh_send_secure_msg(session, YHC_DECRYPT_PKCS1, data.buf, in_len + 2,
2091 &response_cmd, out, out_len);
2092 if (yrc != YHR_SUCCESS) {
2093 DBG_ERR("Failed to send DECRYPT PKCS1 command: %s", yh_strerror(yrc));
2094 return yrc;
2095 }
2096
2097 if (response_cmd == YHC_ERROR) {
2098 yh_rc translated = translate_device_error(out[0]);
2099 DBG_ERR("Unable to get decrypted data: %s (%x)", yh_strerror(translated),
2100 out[0]);
2101 return translated;
2102 }
2103
2104 return YHR_SUCCESS;
2105}
2106
2108 const uint8_t *in, size_t in_len, uint8_t *out,
2109 size_t *out_len, const uint8_t *label,
2110 size_t label_len, yh_algorithm mgf1Algo) {
2111
2112 if (session == NULL || in == NULL || out == NULL || out_len == NULL ||
2113 label == NULL) {
2116 }
2117
2118#pragma pack(push, 1)
2119 union {
2120 struct {
2122 uint8_t mgf1Algo;
2123 uint8_t bytes[YH_MSG_BUF_SIZE];
2124 };
2125 uint8_t buf[1];
2126 } data;
2127#pragma pack(pop)
2128
2129 yh_cmd response_cmd;
2130 yh_rc yrc;
2131 uint16_t len = 0;
2132
2133 data.key_id = htons(key_id);
2134 len += sizeof(data.key_id);
2135
2136 data.mgf1Algo = mgf1Algo;
2137 len += sizeof(data.mgf1Algo);
2138
2139 // in_len has to match the rsa key size
2140 if (in_len != 256 && in_len != 384 && in_len != 512) {
2141 DBG_ERR("Wrong input length");
2142 return YHR_WRONG_LENGTH;
2143 }
2144
2145 // label_len is hashed and specified the mgf hash
2146 if (label_len != 20 && label_len != 32 && label_len != 48 &&
2147 label_len != 64) {
2148 DBG_ERR("Wrong label length");
2149 return YHR_WRONG_LENGTH;
2150 }
2151
2152 memcpy(data.bytes, in, in_len);
2153 len += in_len;
2154 memcpy(data.bytes + in_len, label, label_len);
2155 len += label_len;
2156
2157 yrc = yh_send_secure_msg(session, YHC_DECRYPT_OAEP, data.buf, len,
2158 &response_cmd, out, out_len);
2159 if (yrc != YHR_SUCCESS) {
2160 DBG_ERR("Failed to send DECRYPT OAEP command: %s", yh_strerror(yrc));
2161 return yrc;
2162 }
2163
2164 if (response_cmd == YHC_ERROR) {
2165 yh_rc translated = translate_device_error(out[0]);
2166 DBG_ERR("Unable to get decrypted data: %s (%x)", yh_strerror(translated),
2167 out[0]);
2168 return translated;
2169 }
2170
2171 return YHR_SUCCESS;
2172}
2173
2175 const uint8_t *in, size_t in_len, uint8_t *out,
2176 size_t *out_len) {
2177
2178 if (session == NULL || in == NULL || out == NULL || out_len == NULL) {
2181 }
2182
2183 if (in_len > YH_MSG_BUF_SIZE - 2) {
2184 DBG_ERR("Too much data, must be < %d", YH_MSG_BUF_SIZE - 2);
2186 }
2187
2188#pragma pack(push, 1)
2189 union {
2190 struct {
2192 uint8_t bytes[YH_MSG_BUF_SIZE];
2193 };
2194 uint8_t buf[1];
2195 } data;
2196#pragma pack(pop)
2197
2198 yh_cmd response_cmd;
2199 yh_rc yrc;
2200
2201 data.key_id = htons(key_id);
2202
2203 memcpy(data.bytes, in, in_len);
2204
2205 yrc = yh_send_secure_msg(session, YHC_DERIVE_ECDH, data.buf, in_len + 2,
2206 &response_cmd, out, out_len);
2207 if (yrc != YHR_SUCCESS) {
2208 DBG_ERR("Failed to send DERIVE ECDH command: %s", yh_strerror(yrc));
2209 return yrc;
2210 }
2211
2212 if (response_cmd == YHC_ERROR) {
2213 yh_rc translated = translate_device_error(out[0]);
2214 DBG_ERR("Unable to get decrypted data: %s (%x)", yh_strerror(translated),
2215 out[0]);
2216 return translated;
2217 }
2218
2219 return YHR_SUCCESS;
2220}
2221
2223 yh_object_type type) {
2224
2225 if (session == NULL) {
2228 }
2229
2230#pragma pack(push, 1)
2231 union {
2232 struct {
2233 uint16_t id;
2234 uint8_t type;
2235 };
2236 uint8_t buf[1];
2237 } data;
2238#pragma pack(pop)
2239
2240 yh_rc yrc;
2241 yh_cmd response_cmd;
2242 uint8_t response[YH_MSG_BUF_SIZE];
2243 size_t response_len = sizeof(response);
2244
2245 data.type = type;
2246 data.id = htons(id);
2247
2248 yrc = yh_send_secure_msg(session, YHC_DELETE_OBJECT, data.buf, sizeof(data),
2249 &response_cmd, response, &response_len);
2250 if (yrc != YHR_SUCCESS) {
2251 DBG_ERR("Failed to send DELETE command: %s", yh_strerror(yrc));
2252 return yrc;
2253 }
2254
2255 if (response_cmd == YHC_ERROR) {
2256 yh_rc translated = translate_device_error(response[0]);
2257 DBG_ERR("Unable to delete object: %s (%x)", yh_strerror(translated),
2258 response[0]);
2259 return translated;
2260 }
2261
2262 return YHR_SUCCESS;
2263}
2264
2267 uint8_t *out, size_t *out_len) {
2268
2269 if (session == NULL || out == NULL || out_len == NULL) {
2272 }
2273
2274#pragma pack(push, 1)
2275 union {
2276 struct {
2278 uint8_t type;
2279 uint16_t tgt_id;
2280 };
2281 uint8_t buf[1];
2282 } data;
2283#pragma pack(pop)
2284
2285 yh_cmd response_cmd;
2286 yh_rc yrc;
2287
2288 data.key_id = htons(wrapping_key_id);
2289 data.type = (uint8_t) target_type;
2290 data.tgt_id = htons(target_id);
2291
2292 yrc = yh_send_secure_msg(session, YHC_EXPORT_WRAPPED, data.buf, sizeof(data),
2293 &response_cmd, out, out_len);
2294 if (yrc != YHR_SUCCESS) {
2295 DBG_ERR("Failed to send EXPORT WRAPPED command: %s", yh_strerror(yrc));
2296 return yrc;
2297 }
2298
2299 if (response_cmd == YHC_ERROR) {
2300 yh_rc translated = translate_device_error(out[0]);
2301 DBG_ERR("Unable to get wrapped object: %s (%x)", yh_strerror(translated),
2302 out[0]);
2303 return translated;
2304 }
2305
2306 return YHR_SUCCESS;
2307}
2308
2310 const uint8_t *in, size_t in_len,
2312
2313 if (session == NULL || in == NULL || target_type == NULL ||
2314 target_id == NULL) {
2317 }
2318
2319 if (in_len > YH_MSG_BUF_SIZE - 2) {
2320 DBG_ERR("Too much data, must be < %d", YH_MSG_BUF_SIZE - 2);
2322 }
2323
2324#pragma pack(push, 1)
2325 union {
2326 struct {
2328 uint8_t bytes[YH_MSG_BUF_SIZE - 2];
2329 };
2330 uint8_t buf[1];
2331 } data;
2332#pragma pack(pop)
2333 uint16_t data_len = 2 + in_len;
2334
2335 uint8_t response[YH_MSG_BUF_SIZE];
2336 size_t response_len = sizeof(response);
2337 yh_cmd response_cmd;
2338 yh_rc yrc;
2339
2340 data.key_id = htons(wrapping_key_id);
2341 memcpy(data.bytes, in, in_len);
2342
2343 yrc = yh_send_secure_msg(session, YHC_IMPORT_WRAPPED, data.buf, data_len,
2344 &response_cmd, response, &response_len);
2345 if (yrc != YHR_SUCCESS) {
2346 DBG_ERR("Failed to send IMPORT WRAPPED command: %s", yh_strerror(yrc));
2347 return yrc;
2348 }
2349
2350 if (response_cmd == YHC_ERROR) {
2351 yh_rc translated = translate_device_error(response[0]);
2352 DBG_ERR("Unable to get data: %s (%x)", yh_strerror(translated),
2353 response[0]);
2354 return translated;
2355 }
2356
2357 *target_type = response[0];
2358 *target_id = ntohs(*((uint16_t *) (response + 1)));
2359
2360 return YHR_SUCCESS;
2361}
2362
2364 const char *label, uint16_t domains,
2368 const uint8_t *in, size_t in_len) {
2369
2370 if (session == NULL || key_id == NULL || label == NULL ||
2371 strlen(label) > YH_OBJ_LABEL_LEN || capabilities == NULL ||
2372 delegated_capabilities == NULL || in == NULL) {
2375 }
2376
2377#pragma pack(push, 1)
2378 union {
2379 struct {
2386 uint8_t key[32];
2387 };
2388 uint8_t buf[1];
2389 } data;
2390 uint16_t data_len = sizeof(data);
2391 union {
2392 struct {
2394 };
2395 uint8_t buf[1];
2396 } response;
2397#pragma pack(pop)
2398
2399 size_t response_len = sizeof(response);
2400 yh_cmd response_cmd;
2402
2403 yh_rc yrc;
2404
2405 switch (algorithm) {
2407 key_len = 16;
2408 data_len -= 16;
2409 break;
2411 key_len = 24;
2412 data_len -= 8;
2413 break;
2415 key_len = 32;
2416 break;
2417 default:
2418 DBG_ERR("Bad algorithm specified: %x", algorithm);
2420 }
2421
2422 if (in_len != key_len) {
2423 DBG_ERR("Key length not matching, should be %d", key_len);
2425 }
2426
2427 data.key_id = htons(*key_id);
2428 memcpy(data.label, label, strlen(label));
2429 memset(data.label + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
2430 data.domains = htons(domains);
2431 memcpy(data.capabilities, capabilities, YH_CAPABILITIES_LEN);
2432 data.algorithm = algorithm;
2433 memcpy(data.delegated_capabilities, delegated_capabilities,
2435 memcpy(data.key, in, key_len);
2436
2437 yrc = yh_send_secure_msg(session, YHC_PUT_WRAP_KEY, data.buf, data_len,
2438 &response_cmd, response.buf, &response_len);
2439 insecure_memzero(data.buf, data_len);
2440 if (yrc != YHR_SUCCESS) {
2441 DBG_ERR("Failed to send PUT WRAP KEY command: %s", yh_strerror(yrc));
2442 return yrc;
2443 }
2444
2445 if (response_cmd == YHC_ERROR) {
2446 yh_rc translated = translate_device_error(response.buf[0]);
2447 DBG_ERR("Unable to store wrapping key: %s (%x)", yh_strerror(translated),
2448 response.buf[0]);
2449 return translated;
2450 }
2451
2452 *key_id = ntohs(response.key_id);
2453 DBG_INFO("Imported Wrap key 0x%04x", *key_id);
2454
2455 return YHR_SUCCESS;
2456}
2457
2459 const char *label, uint16_t domains,
2463
2464 if (session == NULL || key_id == NULL || label == NULL ||
2465 strlen(label) > YH_OBJ_LABEL_LEN || capabilities == NULL ||
2466 delegated_capabilities == NULL) {
2469 }
2470
2471 yh_rc yrc;
2472
2473#pragma pack(push, 1)
2474 union {
2475 struct {
2482 };
2483 uint8_t buf[1];
2484 } data;
2485 uint16_t data_len = sizeof(data);
2486 union {
2487 struct {
2489 };
2490 uint8_t buf[1];
2491 } response;
2492#pragma pack(pop)
2493
2494 size_t response_len = sizeof(response);
2495 yh_cmd response_cmd;
2496
2497 data.key_id = htons(*key_id);
2498
2499 memcpy(data.label, label, strlen(label));
2500 memset(data.label + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
2501
2502 data.domains = htons(domains);
2503
2504 memcpy(data.capabilities, capabilities, YH_CAPABILITIES_LEN);
2505
2506 data.algorithm = algorithm;
2507
2508 memcpy(data.delegated_capabilities, delegated_capabilities,
2510
2511 yrc = yh_send_secure_msg(session, YHC_GENERATE_WRAP_KEY, data.buf, data_len,
2512 &response_cmd, response.buf, &response_len);
2513 if (yrc != YHR_SUCCESS) {
2514 DBG_ERR("Failed to send GENERATE WRAP KEY command: %s", yh_strerror(yrc));
2515 return yrc;
2516 }
2517
2518 if (response_cmd == YHC_ERROR) {
2519 yh_rc translated = translate_device_error(response.buf[0]);
2520 DBG_ERR("Unable to generate key: %s (%x)", yh_strerror(translated),
2521 response.buf[0]);
2522 return translated;
2523 }
2524
2525 *key_id = ntohs(response.key_id);
2526 DBG_INFO("Generated Wrap key 0x%04x\n", *key_id);
2527
2528 return YHR_SUCCESS;
2529}
2530
2532 uint16_t *unlogged_auth, yh_log_entry *out,
2533 size_t *n_items) {
2534
2535 if (session == NULL || out == NULL || n_items == NULL) {
2538 }
2539
2540 yh_rc yrc;
2541
2542 union {
2543 struct {
2544 uint16_t log_overflow_boot;
2545 uint16_t log_overflow_auth;
2546 uint8_t items;
2547 uint8_t data[1];
2548 };
2550 } response;
2551 size_t response_len = sizeof(response);
2552 yh_cmd response_cmd;
2553
2554 yrc = yh_send_secure_msg(session, YHC_GET_LOG_ENTRIES, NULL, 0, &response_cmd,
2555 response.buf, &response_len);
2556 if (yrc != YHR_SUCCESS) {
2557 DBG_ERR("Failed to send GET LOGS command: %s", yh_strerror(yrc));
2558 return yrc;
2559 }
2560
2561 if (response_cmd == YHC_ERROR) {
2562 yh_rc translated = translate_device_error(response.buf[0]);
2563 DBG_ERR("Unable to get logs: %s (%x)", yh_strerror(translated),
2564 response.buf[0]);
2565 return translated;
2566 }
2567
2568 if (unlogged_boot) {
2569 *unlogged_boot = ntohs(response.log_overflow_boot);
2570 }
2571
2572 if (unlogged_auth) {
2573 *unlogged_auth = ntohs(response.log_overflow_auth);
2574 }
2575
2576 if (response.items > YH_MAX_LOG_ENTRIES) {
2577 DBG_ERR(
2578 "Response contain more items than the maximum number of log entries");
2580 }
2581
2582 if (response.items > *n_items) {
2583 DBG_ERR("Log buffer too small, needed at lest %d, got %zu", response.items,
2584 *n_items);
2585 return YHR_BUFFER_TOO_SMALL;
2586 }
2587
2588 *n_items = response.items;
2589
2590 yh_log_entry *ptr = (yh_log_entry *) response.data;
2591 for (uint16_t i = 0; i < *n_items; i++) {
2592 out[i].number = ntohs(ptr[i].number);
2593 out[i].command = ptr[i].command;
2594 out[i].length = ntohs(ptr[i].length);
2595 out[i].session_key = ntohs(ptr[i].session_key);
2596 out[i].target_key = ntohs(ptr[i].target_key);
2597 out[i].second_key = ntohs(ptr[i].second_key);
2598 out[i].result = ptr[i].result;
2599 out[i].systick = ntohl(ptr[i].systick);
2600 memcpy(out[i].digest, ptr[i].digest, YH_LOG_DIGEST_SIZE);
2601 }
2602
2603 return YHR_SUCCESS;
2604}
2605
2607 if (session == NULL) {
2610 }
2611 uint8_t data[2];
2612 yh_cmd response_cmd;
2613 yh_rc yrc;
2614 uint8_t response[YH_MSG_BUF_SIZE];
2615 size_t response_len = sizeof(response);
2616
2617 uint16_t index_h = htons(index);
2618 memcpy(data, &index_h, sizeof(index_h));
2619 yrc = yh_send_secure_msg(session, YHC_SET_LOG_INDEX, data, sizeof(data),
2620 &response_cmd, response, &response_len);
2621 if (yrc != YHR_SUCCESS) {
2622 DBG_ERR("Failed to send SET LOG INDEX command: %s", yh_strerror(yrc));
2623 return yrc;
2624 }
2625
2626 if (response_cmd == YHC_ERROR) {
2627 yh_rc translated = translate_device_error(response[0]);
2628 DBG_ERR("Unable to set log index: %s (%x)", yh_strerror(translated),
2629 response[0]);
2630 return translated;
2631 }
2632
2633 return YHR_SUCCESS;
2634}
2635
2637 size_t *out_len) {
2638
2639 if (session == NULL || out == NULL || out_len == NULL) {
2642 }
2643
2644 uint8_t data[2];
2645 yh_cmd response_cmd;
2646 yh_rc yrc;
2647
2648 uint16_t object_id_h = htons(object_id);
2649 memcpy(data, &object_id_h, sizeof(object_id_h));
2650 yrc = yh_send_secure_msg(session, YHC_GET_OPAQUE, data, sizeof(data),
2651 &response_cmd, out, out_len);
2652 if (yrc != YHR_SUCCESS) {
2653 DBG_ERR("Failed to send GET OPAQUE command: %s", yh_strerror(yrc));
2654 return yrc;
2655 }
2656
2657 if (response_cmd == YHC_ERROR) {
2658 yh_rc translated = translate_device_error(out[0]);
2659 DBG_ERR("Unable to get object: %s (%x)", yh_strerror(translated), out[0]);
2660 return translated;
2661 }
2662
2663 return YHR_SUCCESS;
2664}
2665
2667 const char *label, uint16_t domains,
2669 yh_algorithm algorithm, const uint8_t *in,
2670 size_t in_len) {
2671
2672 if (session == NULL || object_id == NULL || label == NULL ||
2673 strlen(label) > YH_OBJ_LABEL_LEN || in == NULL) {
2676 }
2677
2678 yh_rc yrc;
2679
2680#pragma pack(push, 1)
2681 union {
2682 struct {
2683 uint16_t object_id;
2688 uint8_t bytes[YH_MSG_BUF_SIZE - sizeof(object_id) - sizeof(domains) -
2690 };
2691 uint8_t buf[1];
2692 } data;
2693 uint16_t data_len;
2694 union {
2695 struct {
2696 uint16_t object_id;
2697 };
2698 uint8_t buf[1];
2699 } response;
2700#pragma pack(pop)
2701 size_t response_len = sizeof(response);
2702 yh_cmd response_cmd;
2703
2704 data.object_id = htons(*object_id);
2705
2706 memcpy(data.label, label, strlen(label));
2707 memset(data.label + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
2708
2709 data.domains = htons(domains);
2710
2711 memcpy(data.capabilities, capabilities, YH_CAPABILITIES_LEN);
2712
2713 data.algorithm = algorithm;
2714
2715 if (in_len > sizeof(data.bytes)) {
2716 DBG_ERR("Data length must be in [0, %lu]\n",
2717 (unsigned long) sizeof(data.bytes));
2719 }
2720
2721 data_len = in_len + sizeof(data) - sizeof(data.bytes);
2722 memcpy(data.bytes, in, in_len);
2723
2724 yrc = yh_send_secure_msg(session, YHC_PUT_OPAQUE, data.buf, data_len,
2725 &response_cmd, response.buf, &response_len);
2726 insecure_memzero(data.buf, data_len);
2727 if (yrc != YHR_SUCCESS) {
2728 DBG_ERR("Failed to send PUT OPAQUE command: %s", yh_strerror(yrc));
2729 return yrc;
2730 }
2731
2732 if (response_cmd == YHC_ERROR) {
2733 yh_rc translated = translate_device_error(response.buf[0]);
2734 DBG_ERR("Unable to store opaque object: %s (%x)", yh_strerror(translated),
2735 response.buf[0]);
2736 return translated;
2737 }
2738
2739 *object_id = ntohs(response.object_id);
2740 DBG_INFO("Stored Opaque Object 0x%04x", *object_id);
2741
2742 return YHR_SUCCESS;
2743}
2744
2746 uint16_t template_id, yh_algorithm sig_algo,
2747 const uint8_t *in, size_t in_len,
2748 uint8_t *out, size_t *out_len) {
2749 if (session == NULL || in == NULL || out == NULL || out_len == NULL ||
2750 in_len == 0) {
2753 }
2754
2755 yh_rc yrc;
2756
2757#pragma pack(push, 1)
2758 union {
2759 struct {
2761 uint16_t template_id;
2762 uint8_t algo;
2763 uint8_t bytes[YH_MSG_BUF_SIZE - sizeof(key_id) - sizeof(template_id) - 2];
2764 };
2765 uint8_t buf[1];
2766 } data;
2767 uint16_t data_len;
2768#pragma pack(pop)
2769
2770 yh_cmd response_cmd;
2771
2772 data.key_id = htons(key_id);
2773
2774 data.template_id = htons(template_id);
2775
2776 data.algo = sig_algo;
2777
2778 if (in_len > sizeof(data.bytes)) {
2779 DBG_ERR("Data length must be in [0, %lu]\n",
2780 (unsigned long) sizeof(data.bytes));
2782 }
2783
2784 data_len = in_len + 5;
2785 memcpy(data.bytes, in, in_len);
2786
2787 yrc = yh_send_secure_msg(session, YHC_SIGN_SSH_CERTIFICATE, data.buf,
2788 data_len, &response_cmd, out, out_len);
2789 if (yrc != YHR_SUCCESS) {
2790 DBG_ERR("Failed to send SIGN SSH CERTIFICATE command: %s",
2791 yh_strerror(yrc));
2792 return yrc;
2793 }
2794
2795 if (response_cmd == YHC_ERROR) {
2796 yh_rc translated = translate_device_error(out[0]);
2797 DBG_ERR("Unable to get certificate: %s (%x)", yh_strerror(translated),
2798 out[0]);
2799 return translated;
2800 }
2801
2802 return YHR_SUCCESS;
2803}
2804
2806 uint8_t *out, size_t *out_len) {
2807 if (session == NULL || out == NULL) {
2810 }
2811
2812 uint8_t data[2];
2813 yh_cmd response_cmd;
2814 yh_rc yrc;
2815
2816 uint16_t object_id_h = htons(object_id);
2817 memcpy(data, &object_id_h, sizeof(object_id_h));
2818 yrc = yh_send_secure_msg(session, YHC_GET_TEMPLATE, data, sizeof(data),
2819 &response_cmd, out, out_len);
2820 if (yrc != YHR_SUCCESS) {
2821 DBG_ERR("Failed to send GET TEMPLATE command: %s", yh_strerror(yrc));
2822 return yrc;
2823 }
2824
2825 if (response_cmd == YHC_ERROR) {
2826 yh_rc translated = translate_device_error(out[0]);
2827 DBG_ERR("Unable to get template object: %s (%x)", yh_strerror(translated),
2828 out[0]);
2829 return translated;
2830 }
2831
2832 return YHR_SUCCESS;
2833}
2834
2836 const char *label, uint16_t domains,
2838 yh_algorithm algorithm, const uint8_t *in,
2839 size_t in_len) {
2840
2841 if (session == NULL || object_id == NULL || label == NULL ||
2842 strlen(label) > YH_OBJ_LABEL_LEN || in == NULL || in_len == 0) {
2845 }
2846
2847 yh_rc yrc;
2848
2849#pragma pack(push, 1)
2850 union {
2851 struct {
2852 uint16_t object_id;
2857 uint8_t bytes[YH_MSG_BUF_SIZE - sizeof(object_id) - sizeof(domains) -
2859 };
2860 uint8_t buf[1];
2861 } data;
2862 uint16_t data_len;
2863 union {
2864 struct {
2865 uint16_t object_id;
2866 };
2867 uint8_t buf[1];
2868 } response;
2869#pragma pack(pop)
2870
2871 size_t response_len = sizeof(response);
2872 yh_cmd response_cmd;
2873
2874 data.object_id = htons(*object_id);
2875
2876 memcpy(data.label, label, strlen(label));
2877 memset(data.label + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
2878
2879 data.domains = htons(domains);
2880
2881 memcpy(data.capabilities, capabilities, YH_CAPABILITIES_LEN);
2882
2883 data.algorithm = algorithm;
2884
2885 if (in_len > sizeof(data.bytes)) {
2886 DBG_ERR("Data length must be in [0, %lu]\n",
2887 (unsigned long) sizeof(data.bytes));
2889 }
2890
2891 data_len = in_len + sizeof(data.object_id) + sizeof(data.domains) +
2892 YH_CAPABILITIES_LEN + YH_OBJ_LABEL_LEN + sizeof(data.algorithm);
2893 memcpy(data.bytes, in, in_len);
2894
2895 yrc = yh_send_secure_msg(session, YHC_PUT_TEMPLATE, data.buf, data_len,
2896 &response_cmd, response.buf, &response_len);
2897 if (yrc != YHR_SUCCESS) {
2898 DBG_ERR("Failed to send PUT TEMPLATE command: %s", yh_strerror(yrc));
2899 return yrc;
2900 }
2901
2902 if (response_cmd == YHC_ERROR) {
2903 yh_rc translated = translate_device_error(response.buf[0]);
2904 DBG_ERR("Unable to store template object: %s (%x)", yh_strerror(translated),
2905 response.buf[0]);
2906 return translated;
2907 }
2908
2909 *object_id = ntohs(response.object_id);
2910 DBG_INFO("Stored Opaque Object 0x%04x", *object_id);
2911
2912 return YHR_SUCCESS;
2913}
2914
2916
2917 if (session == NULL || sid == NULL) {
2920 }
2921
2922 *sid = session->s.sid;
2923
2924 return YHR_SUCCESS;
2925}
2926
2928
2929 Msg msg;
2930 Msg response_msg;
2931 yh_rc yrc;
2932
2933 uint8_t mac_buf[64];
2934 uint16_t mac_buf_len;
2935
2936 if (session == NULL) {
2939 }
2940
2941 // Send AUTHENTICATE SESSION command
2942 msg.st.cmd = YHC_AUTHENTICATE_SESSION;
2943 msg.st.len = 1 + SCP_HOST_CRYPTO_LEN + SCP_MAC_LEN;
2944
2945 msg.st.data[0] = session->s.sid;
2946
2947 // Compute host cryptogram
2948 yrc = compute_host_cryptogram(session, msg.st.data + 1);
2949 if (yrc != YHR_SUCCESS) {
2950 DBG_ERR("%s", yh_strerror(yrc));
2951 return yrc;
2952 }
2953
2954 DBG_INT(msg.st.data + 1, SCP_HOST_CRYPTO_LEN, "Host cryptogram: ");
2955
2956 mac_buf_len = SCP_PRF_LEN + msg.st.len + 3 - SCP_MAC_LEN;
2957 memset(mac_buf, 0, SCP_PRF_LEN); // Initial mac chaining value
2958 msg.st.len = htons(msg.st.len);
2959 memcpy(mac_buf + SCP_PRF_LEN, msg.raw, mac_buf_len);
2960 msg.st.len = ntohs(msg.st.len);
2961
2962 compute_full_mac(mac_buf, mac_buf_len, session->s.s_mac, SCP_KEY_LEN,
2963 session->s.mac_chaining_value);
2964 memcpy(msg.st.data + 1 + SCP_HOST_CRYPTO_LEN, session->s.mac_chaining_value,
2965 SCP_MAC_LEN);
2966
2967 // Reset counter to 1
2968 memset(session->s.ctr, 0, SCP_PRF_LEN);
2969 session->s.ctr[SCP_PRF_LEN - 1]++;
2970
2971 yrc = send_msg(session->parent, &msg, &response_msg);
2972 if (yrc != YHR_SUCCESS) {
2973 DBG_ERR("%s", yh_strerror(yrc));
2974 return yrc;
2975 }
2976
2977 if (response_msg.st.cmd != YHC_AUTHENTICATE_SESSION_R) {
2978 DBG_ERR("%s", yh_strerror(yrc));
2980 }
2981
2982 return YHR_SUCCESS;
2983}
2984
2988 const yh_capabilities *delegated_capabilities, const uint8_t *key_enc,
2989 size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len) {
2990
2991 if (session == NULL || key_id == NULL || label == NULL ||
2992 strlen(label) > YH_OBJ_LABEL_LEN || capabilities == NULL ||
2993 delegated_capabilities == NULL || key_enc == NULL ||
2994 key_enc_len != YH_KEY_LEN || key_mac == NULL ||
2995 key_mac_len != YH_KEY_LEN) {
2998 }
2999
3000#pragma pack(push, 1)
3001 union {
3002 struct {
3009 uint8_t key_enc[YH_KEY_LEN];
3010 uint8_t key_mac[YH_KEY_LEN];
3011 };
3012 uint8_t buf[1];
3013 } data;
3014 union {
3015 struct {
3017 };
3018 uint8_t buf[1];
3019 } response;
3020#pragma pack(pop)
3021 size_t response_len = sizeof(response);
3022 yh_cmd response_cmd;
3023
3024 memcpy(data.key_enc, key_enc, YH_KEY_LEN);
3025 memcpy(data.key_mac, key_mac, YH_KEY_LEN);
3026
3027 data.key_id = htons(*key_id);
3028
3029 memcpy(data.label, label, strlen(label));
3030 memset(data.label + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
3031
3032 data.domains = htons(domains);
3033
3034 memcpy(data.capabilities, capabilities, YH_CAPABILITIES_LEN);
3035
3036 data.algorithm = YH_ALGO_AES128_YUBICO_AUTHENTICATION;
3037
3038 memcpy(data.delegated_capabilities, delegated_capabilities,
3040
3041 yh_rc yrc = yh_send_secure_msg(session, YHC_PUT_AUTHENTICATION_KEY, data.buf,
3042 sizeof(data), &response_cmd, response.buf,
3043 &response_len);
3044 insecure_memzero(data.buf, sizeof(data));
3045 if (yrc != YHR_SUCCESS) {
3046 DBG_ERR("Failed to send PUT AUTHENTICATION KEY command: %s\n",
3047 yh_strerror(yrc));
3048 return yrc;
3049 }
3050
3051 if (response_cmd == YHC_ERROR) {
3052 yh_rc translated = translate_device_error(response.buf[0]);
3053 DBG_ERR("Unable to store authentication key: %s (%x)\n",
3054 yh_strerror(translated), response.buf[0]);
3055 return translated;
3056 }
3057
3058 *key_id = ntohs(response.key_id);
3059 DBG_INFO("Stored Authentication key 0x%04x", *key_id);
3060
3061 return YHR_SUCCESS;
3062}
3063
3067 const yh_capabilities *delegated_capabilities, const uint8_t *password,
3068 size_t password_len) {
3069
3070 if (session == NULL || key_id == NULL || label == NULL ||
3071 strlen(label) > YH_OBJ_LABEL_LEN || capabilities == NULL ||
3072 delegated_capabilities == NULL || password == NULL) {
3075 }
3076
3077 uint8_t key_enc[SCP_KEY_LEN];
3078 uint8_t key_mac[SCP_KEY_LEN];
3079
3080 yh_rc yrc = derive_keys(password, password_len, key_enc, key_mac);
3081
3082 if (yrc == YHR_SUCCESS) {
3083 yrc =
3086 key_enc, sizeof(key_enc), key_mac,
3087 sizeof(key_mac));
3088 insecure_memzero(key_enc, sizeof(key_enc));
3089 insecure_memzero(key_mac, sizeof(key_mac));
3090 }
3091 return yrc;
3092}
3093
3095 const uint8_t *key_enc,
3096 size_t key_enc_len,
3097 const uint8_t *key_mac,
3098 size_t key_mac_len) {
3099
3100 if (session == NULL || key_id == NULL || key_enc == NULL ||
3101 key_enc_len != YH_KEY_LEN || key_mac == NULL ||
3102 key_mac_len != YH_KEY_LEN) {
3105 }
3106
3107#pragma pack(push, 1)
3108 union {
3109 struct {
3112 uint8_t key_enc[YH_KEY_LEN];
3113 uint8_t key_mac[YH_KEY_LEN];
3114 };
3115 uint8_t buf[1];
3116 } data;
3117 union {
3118 struct {
3120 };
3121 uint8_t buf[1];
3122 } response;
3123#pragma pack(pop)
3124 size_t response_len = sizeof(response);
3125 yh_cmd response_cmd;
3126
3127 data.key_id = htons(*key_id);
3128 data.algorithm = YH_ALGO_AES128_YUBICO_AUTHENTICATION;
3129 memcpy(data.key_enc, key_enc, key_enc_len);
3130 memcpy(data.key_mac, key_mac, key_mac_len);
3131
3132 yh_rc yrc = yh_send_secure_msg(session, YHC_CHANGE_AUTHENTICATION_KEY,
3133 data.buf, sizeof(data), &response_cmd,
3134 response.buf, &response_len);
3135 insecure_memzero(data.buf, sizeof(data));
3136 if (yrc != YHR_SUCCESS) {
3137 DBG_ERR("Failed to send CHANGE AUTHENTICATION KEY command: %s\n",
3138 yh_strerror(yrc));
3139 return yrc;
3140 }
3141
3142 if (response_cmd == YHC_ERROR) {
3143 yh_rc translated = translate_device_error(response.buf[0]);
3144 DBG_ERR("Unable to change authentication key: %s (%x)\n",
3145 yh_strerror(translated), response.buf[0]);
3146 return translated;
3147 }
3148
3149 *key_id = ntohs(response.key_id);
3150 DBG_INFO("Changed Authentication key 0x%04x", *key_id);
3151
3152 return YHR_SUCCESS;
3153}
3154
3157 const uint8_t *password,
3158 size_t password_len) {
3159 if (session == NULL || key_id == NULL || password == NULL) {
3162 }
3163
3164 uint8_t key_enc[SCP_KEY_LEN];
3165 uint8_t key_mac[SCP_KEY_LEN];
3166
3167 yh_rc yrc = derive_keys(password, password_len, key_enc, key_mac);
3168
3169 if (yrc == YHR_SUCCESS) {
3171 sizeof(key_enc), key_mac,
3172 sizeof(key_mac));
3173 insecure_memzero(key_enc, sizeof(key_enc));
3174 insecure_memzero(key_mac, sizeof(key_mac));
3175 }
3176 return yrc;
3177}
3178
3180 const uint8_t *key, const uint8_t *private_id,
3181 uint8_t *out, size_t *out_len) {
3182
3183 if (session == NULL || key == NULL || private_id == NULL || out == NULL ||
3184 out_len == NULL) {
3187 }
3188#pragma pack(push, 1)
3189 union {
3190 struct {
3192 uint8_t key[16];
3193 uint8_t private_id[6];
3194 };
3195 uint8_t buf[1];
3196 } data;
3197#pragma pack(pop)
3198
3199 yh_cmd response_cmd;
3200
3201 data.key_id = htons(key_id);
3202 memcpy(data.key, key, sizeof(data.key));
3203 memcpy(data.private_id, private_id, sizeof(data.private_id));
3204
3205 yh_rc yrc = yh_send_secure_msg(session, YHC_CREATE_OTP_AEAD, data.buf,
3206 sizeof(data), &response_cmd, out, out_len);
3207 insecure_memzero(data.buf, sizeof(data));
3208 if (yrc != YHR_SUCCESS) {
3209 DBG_ERR("Failed to send CREATE OTP AEAD command: %s\n", yh_strerror(yrc));
3210 return yrc;
3211 }
3212
3213 if (response_cmd == YHC_ERROR) {
3214 yh_rc translated = translate_device_error(out[0]);
3215 DBG_ERR("Unable to get OTP AEAD: %s (%x)\n", yh_strerror(translated),
3216 out[0]);
3217 return translated;
3218 }
3219
3220 return YHR_SUCCESS;
3221}
3222
3224 uint8_t *out, size_t *out_len) {
3225
3226 if (session == NULL || out == NULL || out_len == NULL) {
3229 }
3230#pragma pack(push, 1)
3231 union {
3232 struct {
3234 };
3235 uint8_t buf[1];
3236 } data;
3237#pragma pack(pop)
3238
3239 yh_cmd response_cmd;
3240
3241 data.key_id = htons(key_id);
3242
3243 yh_rc yrc = yh_send_secure_msg(session, YHC_RANDOMIZE_OTP_AEAD, data.buf,
3244 sizeof(data), &response_cmd, out, out_len);
3245 if (yrc != YHR_SUCCESS) {
3246 DBG_ERR("Failed to send RANDOMIZE OTP AEAD command: %s\n",
3247 yh_strerror(yrc));
3248 return yrc;
3249 }
3250
3251 if (response_cmd == YHC_ERROR) {
3252 yh_rc translated = translate_device_error(out[0]);
3253 DBG_ERR("Unable to get OTP AEAD: %s (%x)\n", yh_strerror(translated),
3254 out[0]);
3255 return translated;
3256 }
3257
3258 return YHR_SUCCESS;
3259}
3260
3262 const uint8_t *aead, size_t aead_len,
3263 const uint8_t *otp, uint16_t *useCtr,
3264 uint8_t *sessionCtr, uint8_t *tstph,
3265 uint16_t *tstpl) {
3266
3267#pragma pack(push, 1)
3268 union {
3269 struct {
3271 uint8_t aead[6 + 16 + 6 + 8]; // FIXME: ya.. magic numbers!
3272 uint8_t otp[16];
3273 };
3274 uint8_t buf[1];
3275 } data;
3276 union {
3277 struct {
3278 uint16_t useCtr;
3279 uint8_t sessionCtr;
3280 uint8_t tstph;
3281 uint16_t tstpl;
3282 };
3283 uint8_t buf[1];
3284 } response;
3285#pragma pack(pop)
3286
3287 if (session == NULL || aead == NULL || otp == NULL ||
3288 aead_len != sizeof(data.aead)) {
3291 }
3292
3293 yh_cmd response_cmd;
3294 size_t response_len = sizeof(response);
3295
3296 data.key_id = htons(key_id);
3297 memcpy(data.aead, aead, sizeof(data.aead));
3298 memcpy(data.otp, otp, sizeof(data.otp));
3299
3300 yh_rc yrc =
3301 yh_send_secure_msg(session, YHC_DECRYPT_OTP, data.buf, sizeof(data),
3302 &response_cmd, response.buf, &response_len);
3303 insecure_memzero(data.buf, sizeof(data));
3304 if (yrc != YHR_SUCCESS) {
3305 DBG_ERR("Failed to send DECRYPT OTP command: %s\n", yh_strerror(yrc));
3306 return yrc;
3307 }
3308
3309 if (response_cmd == YHC_ERROR) {
3310 yh_rc translated = translate_device_error(response.buf[0]);
3311 DBG_ERR("Unable to decrypt OTP: %s (%x)\n", yh_strerror(translated),
3312 response.buf[0]);
3313 return translated;
3314 }
3315
3316 if (response_len != sizeof(response)) {
3317 DBG_ERR("Wrong size returned");
3318 return YHR_WRONG_LENGTH;
3319 }
3320
3321 if (useCtr) {
3322 *useCtr = response.useCtr;
3323 }
3324 if (sessionCtr) {
3325 *sessionCtr = response.sessionCtr;
3326 }
3327 if (tstph) {
3328 *tstph = response.tstph;
3329 }
3330 if (tstpl) {
3331 *tstpl = response.tstpl;
3332 }
3333
3334 return YHR_SUCCESS;
3335}
3336
3338 const char *label, uint16_t domains,
3340 uint32_t nonce_id, const uint8_t *in,
3341 size_t in_len) {
3342
3343 if (session == NULL || key_id == NULL || label == NULL ||
3344 strlen(label) > YH_OBJ_LABEL_LEN || capabilities == NULL || in == NULL) {
3347 }
3348#pragma pack(push, 1)
3349 union {
3350 struct {
3356 uint32_t nonce_id;
3357 uint8_t key[32];
3358 };
3359 uint8_t buf[1];
3360 } data;
3361 union {
3362 struct {
3364 };
3365 uint8_t buf[1];
3366 } response;
3367#pragma pack(pop)
3368
3369 uint16_t data_len = sizeof(data);
3370 size_t response_len = sizeof(response);
3371 yh_cmd response_cmd;
3372
3373 yh_rc yrc;
3374
3375 if (in_len == 16) {
3376 data.algorithm = YH_ALGO_AES128_YUBICO_OTP;
3377 data_len -= 16;
3378 } else if (in_len == 24) {
3379 data.algorithm = YH_ALGO_AES192_YUBICO_OTP;
3380 data_len -= 8;
3381 } else if (in_len == 32) {
3382 data.algorithm = YH_ALGO_AES256_YUBICO_OTP;
3383 } else {
3384 DBG_ERR("Key length has to be 16, 24 or 32 bytes.");
3386 }
3387
3388 data.key_id = htons(*key_id);
3389
3390 memcpy(data.label, label, strlen(label));
3391 memset(data.label + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
3392
3393 data.domains = htons(domains);
3394
3395 memcpy(data.capabilities, capabilities, YH_CAPABILITIES_LEN);
3396
3397 data.nonce_id = nonce_id;
3398
3399 memcpy(data.key, in, in_len);
3400
3401 yrc = yh_send_secure_msg(session, YHC_PUT_OTP_AEAD_KEY, data.buf, data_len,
3402 &response_cmd, response.buf, &response_len);
3403 insecure_memzero(data.buf, data_len);
3404 if (yrc != YHR_SUCCESS) {
3405 DBG_ERR("Failed to send PUT OTP AEAD KEY command: %s", yh_strerror(yrc));
3406 return yrc;
3407 }
3408
3409 if (response_cmd == YHC_ERROR) {
3410 yh_rc translated = translate_device_error(response.buf[0]);
3411 DBG_ERR("Unable to store OTP AEAD key: %s (%x)", yh_strerror(translated),
3412 response.buf[0]);
3413 return translated;
3414 }
3415
3416 *key_id = ntohs(response.key_id);
3417 DBG_INFO("Imported OTP AEAD key 0x%04x", *key_id);
3418
3419 return YHR_SUCCESS;
3420}
3421
3423 const char *label, uint16_t domains,
3425 yh_algorithm algorithm, uint32_t nonce_id) {
3426
3427 if (session == NULL || key_id == NULL || label == NULL ||
3428 strlen(label) > YH_OBJ_LABEL_LEN || capabilities == NULL) {
3431 }
3432
3433 yh_rc yrc;
3434
3435#pragma pack(push, 1)
3436 union {
3437 struct {
3443 uint32_t nonce_id;
3444 };
3445 uint8_t buf[1];
3446 } data;
3447 uint16_t data_len = sizeof(data);
3448 union {
3449 struct {
3451 };
3452 uint8_t buf[1];
3453 } response;
3454#pragma pack(pop)
3455
3456 size_t response_len = sizeof(response);
3457 yh_cmd response_cmd;
3458
3459 data.key_id = htons(*key_id);
3460
3461 memcpy(data.label, label, strlen(label));
3462 memset(data.label + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
3463
3464 data.domains = htons(domains);
3465
3466 memcpy(data.capabilities, capabilities, YH_CAPABILITIES_LEN);
3467
3468 data.algorithm = algorithm;
3469
3470 data.nonce_id = nonce_id;
3471
3472 yrc =
3473 yh_send_secure_msg(session, YHC_GENERATE_OTP_AEAD_KEY, data.buf, data_len,
3474 &response_cmd, response.buf, &response_len);
3475 insecure_memzero(data.buf, data_len);
3476 if (yrc != YHR_SUCCESS) {
3477 DBG_ERR("Failed to send GENERATE OTP AEAD KEY command: %s",
3478 yh_strerror(yrc));
3479 return yrc;
3480 }
3481
3482 if (response_cmd == YHC_ERROR) {
3483 yh_rc translated = translate_device_error(response.buf[0]);
3484 DBG_ERR("Unable to generate key: %s (%x)", yh_strerror(translated),
3485 response.buf[0]);
3486 return translated;
3487 }
3488
3489 *key_id = ntohs(response.key_id);
3490 DBG_INFO("Generated OTP AEAD key 0x%04x\n", *key_id);
3491
3492 return YHR_SUCCESS;
3493}
3494
3496 uint16_t attest_id, uint8_t *out,
3497 size_t *out_len) {
3498
3499 if (session == NULL || out == NULL || out_len == NULL) {
3502 }
3503#pragma pack(push, 1)
3504 union {
3505 struct {
3507 uint16_t attest_id;
3508 };
3509 uint8_t buf[1];
3510 } data;
3511#pragma pack(pop)
3512
3513 yh_cmd response_cmd;
3514
3515 data.key_id = htons(key_id);
3516 data.attest_id = htons(attest_id);
3517
3518 yh_rc yrc =
3519 yh_send_secure_msg(session, YHC_SIGN_ATTESTATION_CERTIFICATE, data.buf,
3520 sizeof(data), &response_cmd, out, out_len);
3521 if (yrc != YHR_SUCCESS) {
3522 DBG_ERR("Failed to send SIGN ATTESTATION CERTIFICATE command: %s\n",
3523 yh_strerror(yrc));
3524 return yrc;
3525 }
3526
3527 if (response_cmd == YHC_ERROR) {
3528 yh_rc translated = translate_device_error(out[0]);
3529 DBG_ERR("Unable to get attestation: %s (%x)\n", yh_strerror(translated),
3530 out[0]);
3531 return translated;
3532 }
3533
3534 return YHR_SUCCESS;
3535}
3536
3538 uint8_t *val) {
3539
3540 if (session == NULL || val == NULL) {
3543 }
3544
3545 if (len > YH_MSG_BUF_SIZE - 3) {
3546 DBG_ERR("Too much data, must be < %d", YH_MSG_BUF_SIZE - 3);
3548 }
3549
3550#pragma pack(push, 1)
3551 union {
3552 struct {
3554 uint16_t len;
3555 uint8_t bytes[1];
3556 };
3558 } data;
3559#pragma pack(pop)
3561 size_t outlen = sizeof(out);
3562 yh_cmd response_cmd;
3563
3564 data.option = option;
3565 data.len = htons(len);
3566 memcpy(data.bytes, val, len);
3567
3568 yh_rc yrc = yh_send_secure_msg(session, YHC_SET_OPTION, data.buf, len + 3,
3569 &response_cmd, out, &outlen);
3570 if (yrc != YHR_SUCCESS) {
3571 DBG_ERR("Failed to send SET OPTION command: %s\n", yh_strerror(yrc));
3572 return yrc;
3573 }
3574
3575 if (response_cmd == YHC_ERROR) {
3576 yh_rc translated = translate_device_error(out[0]);
3577 DBG_ERR("Unable to put option: %s (%x)\n", yh_strerror(translated), out[0]);
3578 return translated;
3579 }
3580
3581 return YHR_SUCCESS;
3582}
3583
3585 size_t *out_len) {
3586
3587 if (session == NULL || out == NULL || out_len == NULL) {
3590 }
3591 uint8_t buf[1] = {option};
3592 yh_cmd response_cmd;
3593
3594 yh_rc yrc = yh_send_secure_msg(session, YHC_GET_OPTION, buf, sizeof(buf),
3595 &response_cmd, out, out_len);
3596 if (yrc != YHR_SUCCESS) {
3597 DBG_ERR("Failed to send GET OPTION command: %s\n", yh_strerror(yrc));
3598 return yrc;
3599 }
3600
3601 if (response_cmd == YHC_ERROR) {
3602 yh_rc translated = translate_device_error(out[0]);
3603 DBG_ERR("Unable to get option: %s (%x)\n", yh_strerror(translated), out[0]);
3604 return translated;
3605 }
3606
3607 return YHR_SUCCESS;
3608}
3609
3611 uint16_t *free_records, uint16_t *total_pages,
3612 uint16_t *free_pages, uint16_t *page_size) {
3613
3614 if (session == NULL) {
3617 }
3618
3619 yh_cmd response_cmd;
3620#pragma pack(push, 1)
3621 union {
3622 struct {
3623 uint16_t total_records;
3624 uint16_t free_records;
3625 uint16_t total_pages;
3626 uint16_t free_pages;
3627 uint16_t page_size;
3628 };
3629 uint8_t buf[1];
3630 } response;
3631#pragma pack(pop)
3632 size_t response_len = sizeof(response);
3633
3634 yh_rc yrc = yh_send_secure_msg(session, YHC_GET_STORAGE_INFO, NULL, 0,
3635 &response_cmd, response.buf, &response_len);
3636 if (yrc != YHR_SUCCESS) {
3637 DBG_ERR("Failed to send GET STORAGE INFO command: %s\n", yh_strerror(yrc));
3638 return yrc;
3639 }
3640
3641 if (response_cmd == YHC_ERROR) {
3642 yh_rc translated = translate_device_error(response.buf[0]);
3643 DBG_ERR("Unable to get storage stats: %s (%x)\n", yh_strerror(translated),
3644 response.buf[0]);
3645 return translated;
3646 }
3647
3648 if (total_records) {
3649 *total_records = ntohs(response.total_records);
3650 }
3651 if (free_records) {
3652 *free_records = ntohs(response.free_records);
3653 }
3654 if (total_pages) {
3655 *total_pages = ntohs(response.total_pages);
3656 }
3657 if (free_pages) {
3658 *free_pages = ntohs(response.free_pages);
3659 }
3660 if (page_size) {
3661 *page_size = ntohs(response.page_size);
3662 }
3663
3664 return YHR_SUCCESS;
3665}
3666
3668 size_t in_len, uint8_t *out, size_t *out_len) {
3669
3670 if (session == NULL || in == NULL || out == NULL || out_len == NULL) {
3673 }
3674
3675 if (in_len > YH_MSG_BUF_SIZE - 2) {
3676 DBG_ERR("Too much data, must be < %d", YH_MSG_BUF_SIZE - 2);
3678 }
3679
3680 yh_rc yrc;
3681
3682#pragma pack(push, 1)
3683 union {
3684 struct {
3686 uint8_t bytes[YH_MSG_BUF_SIZE];
3687 };
3688 uint8_t buf[1];
3689 } data;
3690#pragma pack(pop)
3691 uint16_t data_len = in_len + 2;
3692
3693 yh_cmd response_cmd;
3694
3695 data.key_id = htons(key_id);
3696 memcpy(data.bytes, in, in_len);
3697
3698 yrc = yh_send_secure_msg(session, YHC_WRAP_DATA, data.buf, data_len,
3699 &response_cmd, out, out_len);
3700 insecure_memzero(data.buf, data_len);
3701 if (yrc != YHR_SUCCESS) {
3702 DBG_ERR("Failed to send WRAP DATA command: %s", yh_strerror(yrc));
3703 return yrc;
3704 }
3705
3706 if (response_cmd == YHC_ERROR) {
3707 yh_rc translated = translate_device_error(out[0]);
3708 DBG_ERR("Unable to get wrapped data: %s (%x)", yh_strerror(translated),
3709 out[0]);
3710 return translated;
3711 }
3712
3713 return YHR_SUCCESS;
3714}
3715
3717 const uint8_t *in, size_t in_len, uint8_t *out,
3718 size_t *out_len) {
3719
3720 if (session == NULL || in == NULL || out == NULL || out_len == NULL) {
3723 }
3724
3725 if (in_len > YH_MSG_BUF_SIZE - 2) {
3726 DBG_ERR("Too much data, must be < %d", YH_MSG_BUF_SIZE - 2);
3728 }
3729
3730 yh_rc yrc;
3731
3732#pragma pack(push, 1)
3733 union {
3734 struct {
3736 uint8_t bytes[YH_MSG_BUF_SIZE];
3737 };
3738 uint8_t buf[1];
3739 } data;
3740#pragma pack(pop)
3741 uint16_t data_len = in_len + 2;
3742
3743 yh_cmd response_cmd;
3744
3745 data.key_id = htons(key_id);
3746 memcpy(data.bytes, in, in_len);
3747
3748 yrc = yh_send_secure_msg(session, YHC_UNWRAP_DATA, data.buf, data_len,
3749 &response_cmd, out, out_len);
3750 insecure_memzero(data.buf, data_len);
3751 if (yrc != YHR_SUCCESS) {
3752 DBG_ERR("Failed to send UNWRAP DATA command: %s", yh_strerror(yrc));
3753 return yrc;
3754 }
3755
3756 if (response_cmd == YHC_ERROR) {
3757 yh_rc translated = translate_device_error(out[0]);
3758 DBG_ERR("Unable to get unwrapped data: %s (%x)", yh_strerror(translated),
3759 out[0]);
3760 return translated;
3761 }
3762
3763 return YHR_SUCCESS;
3764}
3765
3767
3768 if (session == NULL) {
3771 }
3772
3773 yh_rc yrc;
3774
3775 uint8_t response[5];
3776 size_t response_len = sizeof(response);
3777 yh_cmd response_cmd;
3778
3779 yrc = yh_send_secure_msg(session, YHC_BLINK_DEVICE, &seconds, sizeof(seconds),
3780 &response_cmd, response, &response_len);
3781 if (yrc != YHR_SUCCESS) {
3782 DBG_ERR("Failed to send BLINK DEVICE command: %s", yh_strerror(yrc));
3783 return yrc;
3784 }
3785
3786 if (response_cmd == YHC_ERROR) {
3787 yh_rc translated = translate_device_error(response[0]);
3788 DBG_ERR("Unable to blink the device: %s (%x)", yh_strerror(translated),
3789 response[0]);
3790 return translated;
3791 }
3792
3793 return YHR_SUCCESS;
3794}
3795
3797
3798 if (session == NULL) {
3801 }
3802
3803 yh_rc yrc;
3804
3805 yh_cmd response_cmd;
3806 uint8_t response[1];
3807 size_t response_len = sizeof(response);
3808
3809 yrc = yh_send_secure_msg(session, YHC_RESET_DEVICE, NULL, 0, &response_cmd,
3810 response, &response_len);
3811 if (yrc != YHR_SUCCESS) {
3812 DBG_ERR("Failed to send RESET DEVICE command: %s\n", yh_strerror(yrc));
3813 return yrc;
3814 }
3815
3816 if (response_cmd == YHC_ERROR) {
3817 yh_rc translated = translate_device_error(response[0]);
3818 DBG_ERR("Unable to reset: %s (%x)\n", yh_strerror(translated), response[0]);
3819 return translated;
3820 }
3821
3822 return YHR_SUCCESS;
3823}
3824
3826
3827 _yh_verbosity = verbosity;
3828
3829 if (connector != NULL && connector->bf != NULL) {
3830 // TODO(adma): should we error out if NULL?
3831 connector->bf->backend_set_verbosity(_yh_verbosity, _yh_output);
3832 }
3833
3834 return YHR_SUCCESS;
3835}
3836
3838
3839 if (verbosity == NULL) {
3841 }
3842
3843 *verbosity = _yh_verbosity;
3844
3845 return YHR_SUCCESS;
3846}
3847
3848void yh_set_debug_output(yh_connector *connector, FILE *output) {
3849 _yh_output = output;
3850
3851 if (connector != NULL && connector->bf != NULL) {
3852 // TODO(adma): should we error out if NULL?
3853 connector->bf->backend_set_verbosity(_yh_verbosity, _yh_output);
3854 }
3855}
3856
3858 if (_yh_output == NULL) {
3859 _yh_output = stderr;
3860 }
3861 return YHR_SUCCESS;
3862}
3863
3864#ifdef STATIC
3865static yh_rc load_backend(const char *name,
3866 void **backend __attribute__((unused)),
3867 struct backend_functions **bf) {
3868 if (name == NULL) {
3869 DBG_ERR("No name given to load_backend");
3870 return YHR_GENERIC_ERROR;
3871 }
3872 else if (strncmp(name, STATIC_USB_BACKEND, strlen(STATIC_USB_BACKEND)) == 0) {
3873 *bf = usb_backend_functions();
3874 }
3875 else if (strncmp(name, STATIC_HTTP_BACKEND, strlen(STATIC_HTTP_BACKEND)) == 0) {
3876 *bf = http_backend_functions();
3877 }
3878 else {
3879 DBG_ERR("Failed finding backend named '%s'", name);
3880 return YHR_GENERIC_ERROR;
3881 }
3882
3883 return (*bf)->backend_init(_yh_verbosity, _yh_output);
3884}
3885#else
3886static yh_rc load_backend(const char *name, void **backend,
3887 struct backend_functions **bf) {
3888 struct backend_functions *(*backend_functions)(void);
3889#ifdef WIN32
3890 *backend = LoadLibrary(name);
3891 if (*backend == NULL) {
3892 DBG_ERR("Failed loading library '%s'", name);
3893 return YHR_GENERIC_ERROR;
3894 }
3895 backend_functions = (struct backend_functions * (*) (void) )(
3896 (void (*)(void)) GetProcAddress(*backend, "backend_functions"));
3897#else
3898 *backend = dlopen(name, RTLD_NOW);
3899 if (*backend == NULL) {
3900 DBG_ERR("Failed loading '%s' with error: '%s'", name, dlerror());
3901 return YHR_GENERIC_ERROR;
3902 }
3903 *(void **) (&backend_functions) = dlsym(*backend, "backend_functions");
3904#endif
3905 *bf = backend_functions();
3906 return (*bf)->backend_init(_yh_verbosity, _yh_output);
3907}
3908#endif
3909
3910yh_rc yh_exit(void) { return YHR_SUCCESS; }
3911
3912#define STATUS_ENDPOINT "/connector/status"
3913#define API_ENDPOINT "/connector/api"
3914
3915static yh_rc create_connector(yh_connector **connector, const char *url,
3916 void *backend, struct backend_functions *bf) {
3917
3918 yh_rc rc;
3919
3920 if (connector == NULL) {
3922 }
3923
3924 *connector = calloc(1, sizeof(yh_connector));
3925 if (*connector == NULL) {
3926 return YHR_MEMORY_ERROR;
3927 }
3928
3929 if (strncmp(url, YH_USB_URL_SCHEME, strlen(YH_USB_URL_SCHEME)) == 0) {
3930 (*connector)->status_url = strdup(url);
3931 if ((*connector)->status_url == NULL) {
3933 goto cc_failure;
3934 }
3935 (*connector)->api_url = strdup(url);
3936 if ((*connector)->api_url == NULL) {
3938 goto cc_failure;
3939 }
3940 } else {
3941 (*connector)->status_url =
3942 calloc(1, strlen(url) + strlen(STATUS_ENDPOINT) + 1);
3943 if ((*connector)->status_url == NULL) {
3945 goto cc_failure;
3946 }
3947 sprintf((*connector)->status_url, "%s%s", url, STATUS_ENDPOINT);
3948
3949 (*connector)->api_url = calloc(1, strlen(url) + strlen(API_ENDPOINT) + 1);
3950 if ((*connector)->api_url == NULL) {
3952 goto cc_failure;
3953 }
3954 sprintf((*connector)->api_url, "%s%s", url, API_ENDPOINT);
3955 }
3956
3957 (*connector)->connection = bf->backend_create();
3958 if ((*connector)->connection == NULL) {
3960 goto cc_failure;
3961 }
3962
3963 (*connector)->backend = backend;
3964 (*connector)->bf = bf;
3965
3966 return YHR_SUCCESS;
3967
3968cc_failure:
3969 if ((*connector)->status_url) {
3970 free((*connector)->status_url);
3971 (*connector)->status_url = NULL;
3972 }
3973
3974 if ((*connector)->api_url) {
3975 free((*connector)->api_url);
3976 (*connector)->api_url = NULL;
3977 }
3978
3979 if (*connector) {
3980 free(*connector);
3981 *connector = NULL;
3982 }
3983
3984 return rc;
3985}
3986
3987static void destroy_connector(yh_connector *connector) {
3988
3989 if (connector == NULL) {
3990 return;
3991 }
3992
3993 if (connector->bf != NULL && connector->connection != NULL) {
3994 connector->bf->backend_disconnect(connector->connection);
3995 connector->connection = NULL;
3996 }
3997
3998 if (connector->status_url != NULL) {
3999 free(connector->status_url);
4000 connector->status_url = NULL;
4001 }
4002
4003 if (connector->api_url != NULL) {
4004 free(connector->api_url);
4005 connector->api_url = NULL;
4006 }
4007
4008 if (connector->bf) {
4009 connector->bf->backend_cleanup();
4010#ifndef STATIC
4011#ifdef WIN32
4012 FreeLibrary(connector->backend);
4013#else
4014 dlclose(connector->backend);
4015#endif
4016#endif
4017 connector->backend = NULL;
4018 connector->bf = NULL;
4019 }
4020
4021 free(connector);
4022}
4023
4024yh_rc yh_init_connector(const char *url, yh_connector **connector) {
4025 if (url == NULL || connector == NULL) {
4026 DBG_ERR("Invalid parameters: undefined pointer");
4028 }
4029
4030#ifdef STATIC
4031#define USB_LIB STATIC_USB_BACKEND
4032#define HTTP_LIB STATIC_HTTP_BACKEND
4033#elif defined WIN32
4034#define USB_LIB "libyubihsm_usb.dll"
4035#define HTTP_LIB "libyubihsm_http.dll"
4036#elif defined __APPLE__
4037#define USB_LIB "libyubihsm_usb." SOVERSION ".dylib"
4038#define HTTP_LIB "libyubihsm_http." SOVERSION ".dylib"
4039#else
4040#define USB_LIB "libyubihsm_usb.so." SOVERSION
4041#define HTTP_LIB "libyubihsm_http.so." SOVERSION
4042#endif
4043
4044 void *backend = NULL;
4045 struct backend_functions *bf = NULL;
4046
4047 if (strncmp(url, YH_USB_URL_SCHEME, strlen(YH_USB_URL_SCHEME)) == 0) {
4048 DBG_INFO("Loading usb backend");
4049 load_backend(USB_LIB, &backend, &bf);
4050 } else if (strncmp(url, "http://", strlen("http://")) == 0 ||
4051 strncmp(url, "https://", strlen("https://")) == 0) {
4052 DBG_INFO("Loading http backend");
4053 load_backend(HTTP_LIB, &backend, &bf);
4054 }
4055 if (bf == NULL) {
4056 DBG_ERR("Failed loading the backend");
4057 return YHR_GENERIC_ERROR;
4058 }
4059
4060 return create_connector(connector, url, backend, bf);
4061}
4062
4064 const void *val) {
4065
4066 if (connector == NULL || val == NULL) {
4067 DBG_ERR("Invalid parameters: undefined pointer");
4069 }
4070
4071 if (connector->bf == NULL) {
4072 DBG_ERR("No backend loaded");
4074 }
4075
4076 return connector->bf->backend_option(connector->connection, opt, val);
4077}
4078
4079yh_rc yh_connect(yh_connector *connector, int timeout) {
4080
4081 if (connector == NULL || connector->bf == NULL) {
4082 DBG_ERR("Invalid parameters: undefined pointer");
4084 }
4085
4086 yh_rc rc;
4087
4088 rc = connector->bf->backend_connect(connector, timeout);
4089
4090 if (rc != YHR_SUCCESS) {
4091 DBG_ERR("Failed when connecting: %s", yh_strerror(rc));
4092 }
4093
4094 return rc;
4095}
4096
4098
4099 if (connector == NULL) {
4102 }
4103
4104 destroy_connector(connector);
4105
4106 return YHR_SUCCESS;
4107}
4108
4109#ifndef htonll
4110#define htonll(x) \
4111 ((1 == htonl(1)) \
4112 ? (x) \
4113 : ((uint64_t) htonl((x) &0xFFFFFFFF) << 32) | htonl((x) >> 32))
4114#endif
4115yh_rc yh_string_to_capabilities(const char *capability,
4116 yh_capabilities *result) {
4117
4118 char *endptr;
4119 char *saveptr = NULL;
4120 char *str = NULL;
4121 char tmp[2048] = {0};
4123
4124 if (capability == NULL || result == NULL) {
4127 }
4128
4129 errno = 0;
4130 value = strtoull(capability, &endptr, 0);
4131
4132 if (capability != endptr && errno != ERANGE) {
4133 uint64_t actual = htonll(value);
4134 memcpy(result, &actual, 8);
4135 return YHR_SUCCESS;
4136 }
4137
4138 if (strcasecmp(capability, "all") == 0) {
4139 memset(result->capabilities, 0xff, YH_CAPABILITIES_LEN);
4140 return YHR_SUCCESS;
4141 } else if (strcasecmp(capability, "none") == 0) {
4142 memset(result->capabilities, 0x00, YH_CAPABILITIES_LEN);
4143 return YHR_SUCCESS;
4144 }
4145
4146 if (strlen(capability) > sizeof(tmp)) {
4147 return YHR_BUFFER_TOO_SMALL;
4148 }
4149 strncpy(tmp, capability, sizeof(tmp) - 1);
4150
4151 while ((str = strtok_r(str ? NULL : tmp, LIST_SEPARATORS, &saveptr))) {
4152 for (size_t i = 0; i < sizeof(yh_capability) / sizeof(yh_capability[0]);
4153 i++) {
4154 if (strcasecmp(str, yh_capability[i].name) == 0) {
4155 result
4156 ->capabilities[YH_CAPABILITIES_LEN - 1 - yh_capability[i].bit / 8] |=
4157 1ULL << (yh_capability[i].bit % 8);
4158 break;
4159 } else if (i + 1 == sizeof(yh_capability) / sizeof(yh_capability[0])) {
4161 }
4162 }
4163 }
4164
4165 return YHR_SUCCESS;
4166}
4167
4169 const char *result[], size_t *n_result) {
4170
4171 if (num == 0 || result == NULL || n_result == NULL) {
4174 }
4175
4176 size_t matching = 0;
4177
4178 for (size_t i = 0; i < sizeof(yh_capability) / sizeof(yh_capability[0]);
4179 i++) {
4180 if (((1ULL << (yh_capability[i].bit % 8)) &
4181 num->capabilities[YH_CAPABILITIES_LEN - 1 -
4182 (yh_capability[i].bit / 8)]) != 0) {
4183 if (++matching > *n_result) {
4184 memset(result, 0, *n_result);
4185
4186 return YHR_BUFFER_TOO_SMALL;
4187 }
4188
4189 result[matching - 1] = yh_capability[i].name;
4190 }
4191 }
4192
4193 *n_result = matching;
4194
4195 return YHR_SUCCESS;
4196}
4197
4199 const char *capability) {
4200
4201 yh_capabilities check_capabilities = {{0}};
4202
4203 if (yh_string_to_capabilities(capability, &check_capabilities) !=
4204 YHR_SUCCESS) {
4205 return false;
4206 }
4207
4208 for (int i = 0; i < YH_CAPABILITIES_LEN; i++) {
4209 if (check_capabilities.capabilities[i] != 0 &&
4210 (check_capabilities.capabilities[i] & capabilities->capabilities[i]) !=
4211 0) {
4212 return true;
4213 }
4214 }
4215
4216 return false;
4217}
4218
4220 yh_capabilities *result) {
4221 if (a == NULL || b == NULL || result == NULL) {
4223 }
4224
4225 for (int i = 0; i < YH_CAPABILITIES_LEN; i++) {
4226 result->capabilities[i] = a->capabilities[i] | b->capabilities[i];
4227 }
4228 return YHR_SUCCESS;
4229}
4230
4232 const yh_capabilities *filter,
4233 yh_capabilities *result) {
4234 if (capabilities == NULL || filter == NULL || result == NULL) {
4236 }
4237
4238 for (int i = 0; i < YH_CAPABILITIES_LEN; i++) {
4239 result->capabilities[i] =
4240 capabilities->capabilities[i] & filter->capabilities[i];
4241 }
4242 return YHR_SUCCESS;
4243}
4244
4246
4247 switch (algorithm) {
4248 case YH_ALGO_RSA_2048:
4249 case YH_ALGO_RSA_3072:
4250 case YH_ALGO_RSA_4096:
4251 return true;
4252
4253 default:
4254 break;
4255 }
4256
4257 return false;
4258}
4259
4261
4262 switch (algorithm) {
4263 case YH_ALGO_EC_P224:
4264 case YH_ALGO_EC_P256:
4265 case YH_ALGO_EC_P384:
4266 case YH_ALGO_EC_P521:
4267 case YH_ALGO_EC_K256:
4268 case YH_ALGO_EC_BP256:
4269 case YH_ALGO_EC_BP384:
4270 case YH_ALGO_EC_BP512:
4271 return true;
4272
4273 default:
4274 break;
4275 }
4276
4277 return false;
4278}
4279
4281
4282 switch (algorithm) {
4283 case YH_ALGO_EC_ED25519:
4284 return true;
4285
4286 default:
4287 break;
4288 }
4289
4290 return false;
4291}
4292
4294
4295 switch (algorithm) {
4296 case YH_ALGO_HMAC_SHA1:
4300 return true;
4301
4302 default:
4303 break;
4304 }
4305
4306 return false;
4307}
4308
4310
4311 if (result == NULL) {
4313 }
4314
4315 switch (algorithm) {
4316 case YH_ALGO_RSA_2048:
4317 *result = 2048;
4318 break;
4319
4320 case YH_ALGO_RSA_3072:
4321 *result = 3072;
4322 break;
4323
4324 case YH_ALGO_RSA_4096:
4325 *result = 4096;
4326 break;
4327
4328 case YH_ALGO_EC_P256:
4329 *result = 256;
4330 break;
4331
4332 case YH_ALGO_EC_P384:
4333 *result = 384;
4334 break;
4335
4336 case YH_ALGO_EC_P521:
4337 *result = 521;
4338 break;
4339
4340 case YH_ALGO_EC_P224:
4341 *result = 224;
4342 break;
4343
4344 case YH_ALGO_EC_K256:
4345 *result = 256;
4346 break;
4347
4348 case YH_ALGO_EC_BP256:
4349 *result = 256;
4350 break;
4351
4352 case YH_ALGO_EC_BP384:
4353 *result = 394;
4354 break;
4355
4356 case YH_ALGO_EC_BP512:
4357 *result = 512;
4358 break;
4359
4360 case YH_ALGO_HMAC_SHA1:
4361 *result = 160;
4362 break;
4363
4365 *result = 256;
4366 break;
4367
4369 *result = 384;
4370 break;
4371
4373 *result = 512;
4374 break;
4375
4376 default:
4377 *result = 0;
4379 }
4380
4381 return YHR_SUCCESS;
4382}
4383
4384yh_rc yh_algo_to_string(yh_algorithm algo, char const **result) {
4385
4386 if (result == NULL) {
4389 }
4390
4391 for (size_t i = 0; i < sizeof(yh_algorithms) / sizeof(yh_algorithms[0]);
4392 i++) {
4393 if (algo == yh_algorithms[i].algorithm) {
4394 *result = yh_algorithms[i].name;
4395 return YHR_SUCCESS;
4396 }
4397 }
4398
4399 *result = "Unknown";
4400 return YHR_SUCCESS;
4401}
4402
4403yh_rc yh_string_to_algo(const char *string, yh_algorithm *algo) {
4404
4405 if (string == NULL || algo == NULL) {
4408 }
4409 if (strcasecmp(string, "any") == 0) {
4410 *algo = 0;
4411 return YHR_SUCCESS;
4412 }
4413 for (size_t i = 0; i < sizeof(yh_algorithms) / sizeof(yh_algorithms[0]);
4414 i++) {
4415 if (strcasecmp(string, yh_algorithms[i].name) == 0) {
4416 *algo = yh_algorithms[i].algorithm;
4417 return YHR_SUCCESS;
4418 }
4419 }
4420
4422}
4423
4424yh_rc yh_type_to_string(yh_object_type type, char const **result) {
4425
4426 if (result == NULL) {
4429 }
4430
4431 for (size_t i = 0; i < sizeof(yh_types) / sizeof(yh_types[0]); i++) {
4432 if (type == yh_types[i].type) {
4433 *result = yh_types[i].name;
4434 return YHR_SUCCESS;
4435 }
4436 }
4437
4438 *result = "Unknown";
4439 return YHR_SUCCESS;
4440}
4441
4442yh_rc yh_string_to_type(const char *string, yh_object_type *type) {
4443
4444 if (string == NULL || type == NULL) {
4447 }
4448
4449 if (strcasecmp(string, "any") == 0) {
4450 *type = 0;
4451 return YHR_SUCCESS;
4452 }
4453 for (size_t i = 0; i < sizeof(yh_types) / sizeof(yh_types[0]); i++) {
4454 if (strcasecmp(string, yh_types[i].name) == 0) {
4455 *type = yh_types[i].type;
4456 return YHR_SUCCESS;
4457 }
4458 }
4459
4461}
4462
4464
4465 if (string == NULL || option == NULL) {
4468 }
4469
4470 for (size_t i = 0; i < sizeof(yh_options) / sizeof(yh_options[0]); i++) {
4471 if (strcasecmp(string, yh_options[i].name) == 0) {
4472 *option = yh_options[i].option;
4473 return YHR_SUCCESS;
4474 }
4475 }
4476
4478}
4479
4480bool yh_verify_logs(yh_log_entry *logs, size_t n_items,
4481 yh_log_entry *last_previous_log) {
4482 if (logs == NULL || n_items == 0) {
4483 return false;
4484 }
4485
4486 hash_ctx hashctx = NULL;
4487 uint8_t previous_hash[32];
4488 size_t previous_hash_len = 32;
4489 int start;
4490 bool ret = false;
4491
4492 if (!hash_create(&hashctx, _SHA256)) {
4493 return false;
4494 }
4495
4496 if (last_previous_log != NULL) {
4497 memcpy(previous_hash, last_previous_log->digest, YH_LOG_DIGEST_SIZE);
4498 start = 0;
4499 } else {
4500 memcpy(previous_hash, logs[0].digest, YH_LOG_DIGEST_SIZE);
4501 start = 1;
4502 }
4503
4504 for (uint16_t i = start; i < n_items; i++) {
4505 yh_log_entry inverted;
4506 inverted.number = htons(logs[i].number);
4507 inverted.command = logs[i].command;
4508 inverted.length = htons(logs[i].length);
4509 inverted.session_key = htons(logs[i].session_key);
4510 inverted.target_key = htons(logs[i].target_key);
4511 inverted.second_key = htons(logs[i].second_key);
4512 inverted.result = logs[i].result;
4513 inverted.systick = htonl(logs[i].systick);
4514
4515 hash_init(hashctx);
4516 hash_update(hashctx, (const uint8_t *) &inverted,
4518 hash_update(hashctx, previous_hash, YH_LOG_DIGEST_SIZE);
4519 hash_final(hashctx, previous_hash, &previous_hash_len);
4520
4521 if (memcmp(logs[i].digest, previous_hash, YH_LOG_DIGEST_SIZE) != 0) {
4522 goto out;
4523 }
4524 }
4525
4526 ret = true;
4527
4528out:
4529 hash_destroy(hashctx);
4530 hashctx = NULL;
4531
4532 return ret;
4533}
4534
4536 char *endptr;
4537 char *saveptr = NULL;
4538 char *str = NULL;
4539 char tmp[64] = {0};
4540 unsigned long value;
4541
4542 if (domains == NULL || result == NULL) {
4545 }
4546 *result = 0;
4547
4548 if (strcasecmp(domains, "all") == 0) {
4549 *result = 0xffff;
4550 goto out;
4551 } else if (strcmp(domains, "0") == 0) {
4552 goto out;
4553 }
4554
4555 errno = 0;
4556 value = strtoul(domains, &endptr, 0);
4557
4558 if (strncmp(domains, "0x", 2) == 0 && *endptr == '\0' && errno != ERANGE &&
4559 value != ULONG_MAX) {
4560 if (value > USHRT_MAX) {
4561 DBG_ERR("Tried to parse to long number for domains");
4563 }
4564 *result = value;
4565 } else {
4566 if (strlen(domains) > sizeof(tmp)) {
4567 return YHR_BUFFER_TOO_SMALL;
4568 }
4569 strncpy(tmp, domains, sizeof(tmp) - 1);
4570
4571 while ((str = strtok_r(str ? NULL : tmp, LIST_SEPARATORS, &saveptr))) {
4572 endptr = NULL;
4573 value = strtoul(str, &endptr, 0);
4574 if (errno == ERANGE || value > YH_MAX_DOMAINS || value == 0) {
4575 DBG_ERR("Domains are numbered from 1 to %d", YH_MAX_DOMAINS);
4577 }
4578 *result |= 1 << (value - 1);
4579 }
4580 }
4581
4582out:
4583 DBG_INFO("Domains parsed as %x", *result);
4584 return YHR_SUCCESS;
4585}
4586
4587yh_rc yh_domains_to_string(uint16_t domains, char *string, size_t max_len) {
4588 char *ptr = string;
4589 *ptr = '\0';
4590 for (uint16_t i = 0; i < YH_MAX_DOMAINS; i++) {
4591 if (domains & (1 << i)) {
4592 size_t wrote = snprintf(ptr, max_len, "%d:", i + 1);
4593 if (wrote >= max_len) {
4594 return YHR_BUFFER_TOO_SMALL;
4595 }
4596 ptr += wrote;
4597 max_len -= wrote;
4598 }
4599 }
4600 if (ptr != string) {
4601 *(ptr - 1) = '\0';
4602 }
4603 return YHR_SUCCESS;
4604}
void aes_remove_padding(uint8_t *in, uint16_t *len)
Definition aes.c:321
uint8_t aes_set_encrypt_key(uint8_t *key, uint16_t key_len, aes_context *ctx)
Definition aes.c:172
void aes_destroy(aes_context *ctx)
Definition aes.c:330
uint8_t aes_encrypt(uint8_t *in, uint8_t *out, const aes_context *ctx)
Definition aes.c:229
uint8_t aes_cbc_decrypt(uint8_t *in, uint8_t *out, uint16_t len, uint8_t *iv, aes_context *ctx)
Definition aes.c:292
void aes_add_padding(uint8_t *in, uint16_t *len)
Definition aes.c:313
uint8_t aes_set_decrypt_key(uint8_t *key, uint16_t key_len, aes_context *ctx)
Definition aes.c:201
uint8_t aes_cbc_encrypt(uint8_t *in, uint8_t *out, uint16_t len, uint8_t *iv, aes_context *ctx)
Definition aes.c:271
uint8_t aes_cmac_init(uint8_t *key, uint16_t key_len, aes_cmac_context_t *ctx)
Definition aes_cmac.c:130
void aes_cmac_destroy(aes_cmac_context_t *ctx)
Definition aes_cmac.c:147
void aes_cmac_encrypt(const aes_cmac_context_t *ctx, const uint8_t *message, const uint16_t message_len, uint8_t *mac)
Definition aes_cmac.c:85
const mie::Vuint & p
Definition bn.cpp:27
std::string name
uint64_t id
Definition code_cache.cpp:0
#define DBG_ERR(...)
Definition debug_lib.h:76
uint8_t _yh_verbosity
#define DBG_CRYPTO(var, len,...)
Definition debug_lib.h:47
#define DBG_DUMPERR(var, len,...)
Definition debug_lib.h:83
FILE * _yh_output
#define DBG_NET(var, dump)
Definition debug_lib.h:54
#define DBG_INT(var, len,...)
Definition debug_lib.h:40
#define DBG_INFO(...)
Definition debug_lib.h:63
#define DBG_DUMPINFO(var, len,...)
Definition debug_lib.h:69
CK_SESSION_HANDLE session
bool hash_update(_hash_ctx *ctx, const uint8_t *in, size_t cb_in)
Definition hash.c:319
bool hash_create(_hash_ctx **ctx, hash_t hash)
Definition hash.c:189
bool hash_init(_hash_ctx *ctx)
Definition hash.c:294
bool hash_destroy(_hash_ctx *ctx)
Definition hash.c:387
bool hash_final(_hash_ctx *ctx, uint8_t *out, size_t *pcb_out)
Definition hash.c:351
#define insecure_memzero(buf, len)
const char * yh_strerror(yh_rc err)
Definition error.c:65
void YH_INTERNAL dump_response(FILE *file, const Msg *msg)
Definition lib_util.c:55
void YH_INTERNAL dump_msg(FILE *file, const Msg *msg)
Definition lib_util.c:45
struct sysio::chain::eosvmoc::code_cache_header __attribute__((packed))
vector< char > bytes
Definition types.hpp:243
#define value
Definition pkcs11.h:157
#define device_error
Definition pkcs11.h:147
bool pkcs5_pbkdf2_hmac(const uint8_t *password, size_t cb_password, const uint8_t *salt, size_t cb_salt, uint64_t iterations, hash_t hash, uint8_t *key, size_t cb_key)
Definition pkcs5.c:27
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181
string url
Definition main.cpp:166
bool rand_generate(uint8_t *buf, size_t cb_buf)
Definition rand.c:27
#define SCP_S_RMAC_DERIVATION
Definition scp.h:31
#define SCP_KEY_LEN
Definition scp.h:37
#define SCP_CONTEXT_LEN
Definition scp.h:48
#define SCP_MAC_LEN
Definition scp.h:46
#define SCP_CARD_CRYPTOGRAM
Definition scp.h:24
#define SCP_S_MAC_DERIVATION
Definition scp.h:30
#define SCP_PRF_LEN
Definition scp.h:38
#define SCP_CARD_CHAL_LEN
Definition scp.h:40
#define SCP_S_ENC_DERIVATION
Definition scp.h:29
#define SCP_AUTHKEY_ID_LEN
Definition scp.h:50
#define SCP_MSG_BUF_SIZE
Definition scp.h:52
#define SCP_HOST_CRYPTO_LEN
Definition scp.h:44
#define SCP_HOST_CHAL_LEN
Definition scp.h:41
#define SCP_HOST_CRYPTOGRAM
Definition scp.h:25
#define SCP_CARD_CRYPTO_LEN
Definition scp.h:43
unsigned short uint16_t
Definition stdint.h:125
unsigned int uint32_t
Definition stdint.h:126
unsigned char uint8_t
Definition stdint.h:124
unsigned __int64 uint64_t
Definition stdint.h:136
Definition scp.h:68
uint8_t s_mac[SCP_KEY_LEN]
Definition scp.h:71
uint8_t s_rmac[SCP_KEY_LEN]
Definition scp.h:72
uint8_t sid
Definition scp.h:69
uint8_t s_enc[SCP_KEY_LEN]
Definition scp.h:70
yh_backend *(* backend_create)(void)
Definition internal.h:67
Capabilities representation.
Definition yubihsm.h:162
uint8_t capabilities[YH_CAPABILITIES_LEN]
Capabilities is represented as an 8 byte uint8_t array.
Definition yubihsm.h:164
char * status_url
Definition internal.h:41
void * backend
Definition internal.h:38
char * api_url
Definition internal.h:42
bool has_device
Definition internal.h:43
uint8_t address[32]
Definition internal.h:47
struct backend_functions * bf
Definition internal.h:39
uint8_t version_patch
Definition internal.h:46
yh_backend * connection
Definition internal.h:40
uint8_t version_minor
Definition internal.h:45
uint8_t version_major
Definition internal.h:44
Definition yubihsm.h:516
uint8_t digest[YH_LOG_DIGEST_SIZE]
Truncated sha256 digest of this last digest + this entry.
Definition yubihsm.h:534
uint16_t second_key
ID of second Object used.
Definition yubihsm.h:528
uint8_t result
Command result.
Definition yubihsm.h:530
uint32_t systick
Systick at time of execution.
Definition yubihsm.h:532
uint16_t session_key
ID of Authentication Key used.
Definition yubihsm.h:524
uint16_t target_key
ID of first Object used.
Definition yubihsm.h:526
uint16_t length
Length of in-data.
Definition yubihsm.h:522
uint8_t command
What command was executed.
Definition yubihsm.h:520
uint16_t number
Monotonically increasing index.
Definition yubihsm.h:518
uint8_t sequence
Object sequence.
Definition yubihsm.h:554
uint16_t id
Object ID.
Definition yubihsm.h:544
yh_capabilities capabilities
Object capabilities.
Definition yubihsm.h:542
yh_capabilities delegated_capabilities
Object delegated capabilities.
Definition yubihsm.h:560
char label[YH_OBJ_LABEL_LEN+1]
Object label.
Definition yubihsm.h:558
yh_object_type type
Object type.
Definition yubihsm.h:550
bool recreate
Definition internal.h:28
uint8_t key_enc[SCP_KEY_LEN]
Definition internal.h:29
struct yh_connector * parent
Definition internal.h:26
Scp_ctx s
Definition internal.h:31
uint16_t authkey_id
Definition internal.h:27
uint8_t key_mac[SCP_KEY_LEN]
Definition internal.h:30
uint8_t context[SCP_CONTEXT_LEN]
Definition internal.h:32
Definition scp.h:56
struct _Msg::@103 st
uint8_t raw[3+SCP_MSG_BUF_SIZE]
Definition scp.h:62
uint8_t otp[32]
Definition yubico_otp.c:49
@ _SHA256
Definition hash.h:36
bool yh_verify_logs(yh_log_entry *logs, size_t n_items, yh_log_entry *last_previous_log)
Definition yubihsm.c:4480
yh_rc yh_domains_to_string(uint16_t domains, char *string, size_t max_len)
Definition yubihsm.c:4587
#define USB_LIB
#define STATUS_ENDPOINT
Definition yubihsm.c:3912
bool yh_is_rsa(yh_algorithm algorithm)
Definition yubihsm.c:4245
#define LIST_LABEL
Definition yubihsm.c:1028
#define LIST_ID
Definition yubihsm.c:1023
yh_rc yh_create_session(yh_connector *connector, uint16_t authkey_id, const uint8_t *key_enc, size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len, bool recreate, yh_session **session)
Definition yubihsm.c:616
yh_rc yh_util_get_option(yh_session *session, yh_option option, uint8_t *out, size_t *out_len)
Definition yubihsm.c:3584
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
bool yh_is_ed(yh_algorithm algorithm)
Definition yubihsm.c:4280
yh_rc yh_get_verbosity(uint8_t *verbosity)
Definition yubihsm.c:3837
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_set_verbosity(yh_connector *connector, uint8_t verbosity)
Definition yubihsm.c:3825
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_begin_create_session_ext(yh_connector *connector, uint16_t authkey_id, uint8_t **context, uint8_t *card_cryptogram, size_t card_cryptogram_len, yh_session **session)
Definition yubihsm.c:751
yh_rc yh_algo_to_string(yh_algorithm algo, char const **result)
Definition yubihsm.c:4384
yh_rc yh_get_connector_version(yh_connector *connector, uint8_t *major, uint8_t *minor, uint8_t *patch)
Definition yubihsm.c:911
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
#define LIST_DOMAINS
Definition yubihsm.c:1025
bool yh_is_ec(yh_algorithm algorithm)
Definition yubihsm.c:4260
yh_rc yh_util_decrypt_otp(yh_session *session, uint16_t key_id, const uint8_t *aead, size_t aead_len, const uint8_t *otp, uint16_t *useCtr, uint8_t *sessionCtr, uint8_t *tstph, uint16_t *tstpl)
Definition yubihsm.c:3261
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
#define LIST_ALGORITHM
Definition yubihsm.c:1027
yh_rc yh_util_generate_ed_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm)
Definition yubihsm.c:1926
yh_rc yh_util_sign_ssh_certificate(yh_session *session, uint16_t key_id, uint16_t template_id, yh_algorithm sig_algo, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len)
Definition yubihsm.c:2745
yh_rc yh_util_get_template(yh_session *session, uint16_t object_id, uint8_t *out, size_t *out_len)
Definition yubihsm.c:2805
yh_rc yh_util_randomize_otp_aead(yh_session *session, uint16_t key_id, uint8_t *out, size_t *out_len)
Definition yubihsm.c:3223
yh_rc yh_send_secure_msg(yh_session *session, yh_cmd cmd, const uint8_t *data, size_t data_len, yh_cmd *response_cmd, uint8_t *response, size_t *response_len)
Definition yubihsm.c:416
yh_rc yh_util_sign_ecdsa(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:1411
yh_rc yh_init(void)
Definition yubihsm.c:3857
uint8_t _yh_verbosity YH_INTERNAL
Definition yubihsm.c:57
yh_rc yh_string_to_option(const char *string, yh_option *option)
Definition yubihsm.c:4463
yh_rc yh_util_unwrap_data(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:3716
yh_rc yh_util_get_opaque(yh_session *session, uint16_t object_id, uint8_t *out, size_t *out_len)
Definition yubihsm.c:2636
yh_rc yh_string_to_type(const char *string, yh_object_type *type)
Definition yubihsm.c:4442
yh_rc yh_util_sign_attestation_certificate(yh_session *session, uint16_t key_id, uint16_t attest_id, uint8_t *out, size_t *out_len)
Definition yubihsm.c:3495
yh_rc yh_util_get_log_entries(yh_session *session, uint16_t *unlogged_boot, uint16_t *unlogged_auth, yh_log_entry *out, size_t *n_items)
Definition yubihsm.c:2531
yh_rc yh_util_reset_device(yh_session *session)
Definition yubihsm.c:3796
yh_rc yh_util_decrypt_pkcs1v1_5(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:2059
yh_rc yh_util_close_session(yh_session *session)
Definition yubihsm.c:1257
yh_rc yh_util_sign_eddsa(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:1470
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
#define API_ENDPOINT
Definition yubihsm.c:3913
yh_rc yh_authenticate_session(yh_session *session)
Definition yubihsm.c:2927
yh_rc yh_send_plain_msg(yh_connector *connector, yh_cmd cmd, const uint8_t *data, size_t data_len, yh_cmd *response_cmd, uint8_t *response, size_t *response_len)
Definition yubihsm.c:126
yh_rc yh_util_import_ed_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const uint8_t *k)
Definition yubihsm.c:1727
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_wrap_data(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:3667
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
void yh_set_debug_output(yh_connector *connector, FILE *output)
Definition yubihsm.c:3848
yh_rc yh_util_import_authentication_key_derived(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, const yh_capabilities *delegated_capabilities, const uint8_t *password, size_t password_len)
Definition yubihsm.c:3064
yh_rc yh_util_create_otp_aead(yh_session *session, uint16_t key_id, const uint8_t *key, const uint8_t *private_id, uint8_t *out, size_t *out_len)
Definition yubihsm.c:3179
yh_rc yh_util_set_option(yh_session *session, yh_option option, size_t len, uint8_t *val)
Definition yubihsm.c:3537
yh_rc yh_util_change_authentication_key_derived(yh_session *session, uint16_t *key_id, const uint8_t *password, size_t password_len)
Definition yubihsm.c:3155
yh_rc yh_util_change_authentication_key(yh_session *session, uint16_t *key_id, const uint8_t *key_enc, size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len)
Definition yubihsm.c:3094
yh_rc yh_filter_capabilities(const yh_capabilities *capabilities, const yh_capabilities *filter, yh_capabilities *result)
Definition yubihsm.c:4231
yh_rc yh_util_sign_hmac(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:1520
yh_rc yh_util_sign_pss(yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len, size_t salt_len, yh_algorithm mgf1Algo)
Definition yubihsm.c:1346
yh_rc yh_string_to_domains(const char *domains, uint16_t *result)
Definition yubihsm.c:4535
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_util_set_log_index(yh_session *session, uint16_t index)
Definition yubihsm.c:2606
yh_rc yh_util_generate_otp_aead_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, uint32_t nonce_id)
Definition yubihsm.c:3422
#define htonll(x)
Definition yubihsm.c:4110
yh_rc yh_util_sign_pkcs1v1_5(yh_session *session, uint16_t key_id, bool hashed, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len)
Definition yubihsm.c:1287
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
#define LIST_TYPE
Definition yubihsm.c:1024
yh_rc yh_util_get_public_key(yh_session *session, uint16_t id, uint8_t *data, size_t *data_len, yh_algorithm *algorithm)
Definition yubihsm.c:1216
yh_rc yh_util_decrypt_oaep(yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len, const uint8_t *label, size_t label_len, yh_algorithm mgf1Algo)
Definition yubihsm.c:2107
yh_rc yh_string_to_capabilities(const char *capability, yh_capabilities *result)
Definition yubihsm.c:4115
yh_rc yh_string_to_algo(const char *string, yh_algorithm *algo)
Definition yubihsm.c:4403
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
yh_rc yh_util_verify_hmac(yh_session *session, uint16_t key_id, const uint8_t *signature, size_t signature_len, const uint8_t *data, size_t data_len, bool *verified)
Definition yubihsm.c:1939
#define LIST_SEPARATORS
Definition yubihsm.c:55
bool yh_check_capability(const yh_capabilities *capabilities, const char *capability)
Definition yubihsm.c:4198
#define STATIC_HTTP_BACKEND
Definition yubihsm.c:44
yh_rc yh_util_import_authentication_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, const yh_capabilities *delegated_capabilities, const uint8_t *key_enc, size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len)
Definition yubihsm.c:2985
yh_rc yh_capabilities_to_strings(const yh_capabilities *num, const char *result[], size_t *n_result)
Definition yubihsm.c:4168
#define STATIC_USB_BACKEND
Definition yubihsm.c:43
#define HTTP_LIB
bool yh_is_hmac(yh_algorithm algorithm)
Definition yubihsm.c:4293
yh_rc yh_get_connector_address(yh_connector *connector, char **const address)
Definition yubihsm.c:926
yh_rc yh_util_blink_device(yh_session *session, uint8_t seconds)
Definition yubihsm.c:3766
#define LIST_CAPABILITIES
Definition yubihsm.c:1026
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_otp_aead_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, uint32_t nonce_id, const uint8_t *in, size_t in_len)
Definition yubihsm.c:3337
yh_rc yh_util_import_template(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:2835
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_storage_info(yh_session *session, uint16_t *total_records, uint16_t *free_records, uint16_t *total_pages, uint16_t *free_pages, uint16_t *page_size)
Definition yubihsm.c:3610
yh_rc yh_get_session_id(yh_session *session, uint8_t *sid)
Definition yubihsm.c:2915
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_rc yh_finish_create_session_ext(yh_connector *connector, yh_session *session, const uint8_t *key_senc, size_t key_senc_len, const uint8_t *key_smac, size_t key_smac_len, const uint8_t *key_srmac, size_t key_srmac_len, uint8_t *card_cryptogram, size_t card_cryptogram_len)
Definition yubihsm.c:847
yh_rc yh_merge_capabilities(const yh_capabilities *a, const yh_capabilities *b, yh_capabilities *result)
Definition yubihsm.c:4219
yh_rc yh_type_to_string(yh_object_type type, char const **result)
Definition yubihsm.c:4424
yh_option option
Definition yubihsm.h:685
#define YH_DEFAULT_ITERS
Number of iterations for PBKDF2 key derivation.
Definition yubihsm.h:117
yh_object_type type
Definition yubihsm.h:672
int bit
Definition yubihsm.h:566
#define YH_LOG_DIGEST_SIZE
Size that the log digest is truncated to.
Definition yubihsm.h:127
yh_object_type
Definition yubihsm.h:359
#define YH_HOST_CHAL_LEN
Length of host challenge for authentication.
Definition yubihsm.h:91
#define YH_OBJ_LABEL_LEN
Max length of object labels.
Definition yubihsm.h:123
yh_algorithm
Definition yubihsm.h:390
@ YH_ALGO_EC_P521
ecp521
Definition yubihsm.h:418
@ YH_ALGO_EC_BP384
ecbp384
Definition yubihsm.h:424
@ YH_ALGO_EC_P384
ecp384
Definition yubihsm.h:416
@ YH_ALGO_AES128_YUBICO_AUTHENTICATION
aes128-yubico-authentication
Definition yubihsm.h:466
@ YH_ALGO_AES192_YUBICO_OTP
aes192-yubico-otp
Definition yubihsm.h:468
@ YH_ALGO_AES128_YUBICO_OTP
aes128-yubico-otp
Definition yubihsm.h:464
@ YH_ALGO_EC_ED25519
ed25519
Definition yubihsm.h:482
@ YH_ALGO_HMAC_SHA512
hmac-sha512
Definition yubihsm.h:434
@ YH_ALGO_HMAC_SHA384
hmac-sha384
Definition yubihsm.h:432
@ YH_ALGO_AES256_CCM_WRAP
aes256-ccm-wrap
Definition yubihsm.h:474
@ YH_ALGO_HMAC_SHA1
hmac-sha1
Definition yubihsm.h:428
@ YH_ALGO_RSA_2048
rsa2048
Definition yubihsm.h:408
@ YH_ALGO_HMAC_SHA256
hmac-sha256
Definition yubihsm.h:430
@ YH_ALGO_AES192_CCM_WRAP
aes192-ccm-wrap
Definition yubihsm.h:472
@ YH_ALGO_EC_BP512
ecbp512
Definition yubihsm.h:426
@ YH_ALGO_EC_BP256
ecbp256
Definition yubihsm.h:422
@ YH_ALGO_AES256_YUBICO_OTP
aes256-yubico-otp
Definition yubihsm.h:470
@ YH_ALGO_EC_K256
eck256
Definition yubihsm.h:420
@ YH_ALGO_AES128_CCM_WRAP
aes128-ccm-wrap
Definition yubihsm.h:448
@ YH_ALGO_EC_P256
ecp256
Definition yubihsm.h:414
@ YH_ALGO_RSA_4096
rsa4096
Definition yubihsm.h:412
@ YH_ALGO_EC_P224
ecp224
Definition yubihsm.h:484
@ YH_ALGO_RSA_3072
rsa3072
Definition yubihsm.h:410
#define YH_USB_URL_SCHEME
URL scheme used for direct USB access.
Definition yubihsm.h:129
yh_connector_option
Definition yubihsm.h:500
yh_algorithm algorithm
Definition yubihsm.h:619
#define YH_MAX_ALGORITHM_COUNT
Max number of algorithms defined here.
Definition yubihsm.h:383
#define YH_MSG_BUF_SIZE
Maximum length of message buffer.
Definition yubihsm.h:93
#define YH_DEFAULT_SALT
Salt to be used for PBKDF2 key derivation.
Definition yubihsm.h:115
yh_cmd
Definition yubihsm.h:243
@ YHC_ERROR
Definition yubihsm.h:348
#define YH_KEY_LEN
Length of authentication keys.
Definition yubihsm.h:95
yh_option
Definition yubihsm.h:490
#define YH_CAPABILITIES_LEN
Length of capabilities array.
Definition yubihsm.h:119
#define YH_MAX_LOG_ENTRIES
Max log entries the device may hold.
Definition yubihsm.h:121
yh_rc
Definition yubihsm.h:170
@ YHR_DEVICE_INSUFFICIENT_PERMISSIONS
Return value when the permissions to perform the operation are wrong.
Definition yubihsm.h:214
@ YHR_DEVICE_INVALID_SESSION
Returned value when the device session is invalid.
Definition yubihsm.h:201
@ YHR_GENERIC_ERROR
Return value when encountering an unknown error.
Definition yubihsm.h:228
@ YHR_SUCCESS
Returned value when function was successful.
Definition yubihsm.h:172
@ YHR_DEVICE_COMMAND_UNEXECUTED
Return value when the command execution has not terminated.
Definition yubihsm.h:226
@ YHR_INVALID_PARAMETERS
Returned value when an argument to a function is invalid.
Definition yubihsm.h:182
@ YHR_MEMORY_ERROR
Returned value when unable to allocate memory.
Definition yubihsm.h:174
@ YHR_DEVICE_INVALID_COMMAND
Returned value when the device receives and invalid command.
Definition yubihsm.h:197
@ YHR_DEVICE_SESSIONS_FULL
Return value when no more sessions can be opened on the device.
Definition yubihsm.h:205
@ YHR_DEVICE_SESSION_FAILED
Return value when failing to create a device session.
Definition yubihsm.h:207
@ YHR_DEVICE_OBJECT_NOT_FOUND
Return value when the object not found on the device.
Definition yubihsm.h:218
@ YHR_DEVICE_AUTHENTICATION_FAILED
Return value when the device fails to encrypt or verify the message.
Definition yubihsm.h:203
@ YHR_DEVICE_LOG_FULL
Return value when the log buffer is full and forced audit is set.
Definition yubihsm.h:216
@ YHR_DEVICE_INVALID_OTP
Return value when an invalid OTP is submitted.
Definition yubihsm.h:222
@ YHR_DEVICE_DEMO_MODE
Return value when the device is in demo mode and has to be power cycled.
Definition yubihsm.h:224
@ YHR_DEVICE_INVALID_DATA
Returned value when the device receives a malformed command invalid data.
Definition yubihsm.h:199
@ YHR_DEVICE_STORAGE_FAILED
Return value when encountering a storage failure on the device.
Definition yubihsm.h:209
@ YHR_DEVICE_OBJECT_EXISTS
Return value when trying to add an object with an ID that already exists.
Definition yubihsm.h:230
@ YHR_BUFFER_TOO_SMALL
Returned value when there is not enough space to store data.
Definition yubihsm.h:187
@ YHR_MAC_MISMATCH
Returned value when failing to verify MAC.
Definition yubihsm.h:193
@ YHR_WRONG_LENGTH
Definition yubihsm.h:185
@ YHR_DEVICE_WRONG_LENGTH
Definition yubihsm.h:212
@ YHR_CONNECTION_ERROR
Returned value when a connection error was encountered.
Definition yubihsm.h:178
@ YHR_DEVICE_SSH_CA_CONSTRAINT_VIOLATION
Return value when encountering SSH CA constraint violation.
Definition yubihsm.h:234
@ YHR_DEVICE_OK
Returned value when the device returned no error.
Definition yubihsm.h:195
@ YHR_DEVICE_INVALID_ID
Return value when an invalid Object ID is used.
Definition yubihsm.h:220
@ YHR_SESSION_AUTHENTICATION_FAILED
Returned value when failing to authenticate the session.
Definition yubihsm.h:191
@ YHR_CRYPTOGRAM_MISMATCH
Returned value when failing to verify cryptogram.
Definition yubihsm.h:189
#define YH_MAX_DOMAINS
Max number of domains.
Definition yubihsm.h:125
#define YH_CONTEXT_LEN
Length of context array for authentication.
Definition yubihsm.h:89
struct backend_functions * backend_functions(void)
uint8_t patch
yh_capabilities capabilities
uint32_t serial
yh_object_type target_type
char * label
session operation op find n_objects
CK_RV ret
char * s
uint16_t domains
size_t out_len
uint8_t major
size_t len
uint8_t buf[2048]
yh_object_descriptor object
session operation op sign key_len
yh_rc rc
yh_rc yrc
uint16_t target_id
uint16_t key_id
memset(pInfo->slotDescription, ' ', 64)
uint8_t minor
size_t label_len
memcpy((char *) pInfo->slotDescription, s, l)
size_t in_len
yh_capabilities delegated_capabilities