43#define STATIC_USB_BACKEND "usb"
44#define STATIC_HTTP_BACKEND "http"
49 "Host challenge length mismatch");
52 "Message buffer size mismatch");
55#define LIST_SEPARATORS ":,;|"
69 DBG_CRYPTO(data, data_len,
"Compute MAC (%3d Bytes): ", data_len);
78 if (connector == NULL || connector->
bf == NULL) {
83 yrc = connector->
bf->backend_send_msg(connector->
connection, msg, response);
98 msg_len = msg->
st.len;
105 msg->
st.len = htons(msg->
st.len);
107 msg->
st.len = ntohs(msg->
st.len);
110 session->s.mac_chaining_value);
114 return send_msg(
session->parent, msg, response);
121 while (!++ctr[i--] && i > 0)
127 const uint8_t *data,
size_t data_len,
129 size_t *response_len) {
136 if (connector == NULL || (data_len != 0 && data == NULL) ||
137 response_cmd == NULL || response == NULL || response_len == NULL) {
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));
149 msg.
st.len = data_len;
151 memcpy(msg.
st.data, data, data_len);
154 DBG_DUMPINFO(msg.
raw, data_len + 3,
"Sending cmd %02x (%3zu Bytes): ", cmd,
157 yrc = send_msg(connector, &msg, &response_msg);
163 if (*response_len < response_msg.
st.len) {
165 "%s (received %3d Bytes, can fit %3zu Bytes) ",
171 *response_cmd = response_msg.
st.cmd;
173 memcpy(response, response_msg.
st.data, response_msg.
st.len);
174 *response_len = response_msg.
st.len;
183 _DEVICE_INVALID_COMMAND = 0x01,
184 _DEVICE_INVALID_DATA = 0x02,
185 _DEVICE_INVALID_SESSION = 0x03,
186 _DEVICE_AUTHENTICATION_FAILED =
188 _DEVICE_SESSIONS_FULL = 0x05,
189 _DEVICE_SESSION_FAILED = 0x06,
190 _DEVICE_STORAGE_FAILED = 0x07,
191 _DEVICE_WRONG_LENGTH = 0x08,
192 _DEVICE_INSUFFICIENT_PERMISSIONS = 0x09,
193 _DEVICE_LOG_FULL = 0x0a,
194 _DEVICE_OBJECT_NOT_FOUND = 0x0b,
195 _DEVICE_INVALID_ID = 0x0c,
196 _DEVICE_SSH_CA_CONSTRAINT_VIOLIATION = 0x0e,
197 _DEVICE_INVALID_OTP = 0x0f,
198 _DEVICE_DEMO_MODE = 0x10,
199 _DEVICE_OBJECT_EXISTS = 0x11,
200 _DEVICE_COMMAND_UNEXECUTED =
208 case _DEVICE_INVALID_COMMAND:
211 case _DEVICE_INVALID_DATA:
214 case _DEVICE_INVALID_SESSION:
217 case _DEVICE_AUTHENTICATION_FAILED:
220 case _DEVICE_SESSIONS_FULL:
223 case _DEVICE_SESSION_FAILED:
226 case _DEVICE_STORAGE_FAILED:
229 case _DEVICE_WRONG_LENGTH:
232 case _DEVICE_INSUFFICIENT_PERMISSIONS:
235 case _DEVICE_LOG_FULL:
238 case _DEVICE_OBJECT_NOT_FOUND:
241 case _DEVICE_INVALID_ID:
244 case _DEVICE_SSH_CA_CONSTRAINT_VIOLIATION:
247 case _DEVICE_INVALID_OTP:
250 case _DEVICE_DEMO_MODE:
253 case _DEVICE_OBJECT_EXISTS:
256 case _DEVICE_COMMAND_UNEXECUTED:
264 const uint8_t *data,
size_t data_len,
266 size_t *response_len) {
284 if (
session == NULL || (data_len != 0 && data == NULL) ||
285 response_cmd == NULL || response == NULL || response_len == NULL) {
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;
303 "Sending cmd %02x (%3lu Bytes): ", cmd,
304 (
unsigned long) data_len + 3);
313 "CBC encrypting (%3d Bytes): ", work_buf_len);
316 aes_cbc_encrypt(decrypted_data, work_buf + 1, work_buf_len, encrypted_ctr,
322 "Ciphertext (%3d Bytes): ", work_buf_len);
324 msg.
st.cmd = YHC_SESSION_MESSAGE;
325 msg.
st.len = 1 + work_buf_len;
327 memcpy(msg.
st.data, work_buf, work_buf_len + 1);
329 yrc = send_authenticated_msg(
session, &msg, &response_msg);
336 yh_rc translated = translate_device_error(response_msg.
st.data[0]);
340 response[0] = response_msg.
st.data[0];
351 response_msg.
st.len = htons(response_msg.
st.len);
355 response_msg.
st.len = ntohs(response_msg.
st.len);
357 if (memcmp(response_msg.
st.data + response_msg.
st.len -
SCP_MAC_LEN, mac_buf,
365 DBG_INFO(
"Response MAC successfully verified");
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]);
384 "CBC decrypting (%3d Bytes): ",
out_len);
388 encrypted_ctr, &aes_ctx);
404 *response_cmd = decrypted_data[0];
405 memcpy(response, decrypted_data + 3, *response_len);
417 size_t data_len,
yh_cmd *response_cmd,
418 uint8_t *response,
size_t *response_len) {
420 size_t saved_len = *response_len;
422 yh_rc yrc = _send_secure_msg(
session, cmd, data, data_len, response_cmd,
423 response, response_len);
438 *response_len = saved_len;
439 yrc = _send_secure_msg(
session, cmd, data, data_len, response_cmd, response,
457 if (L == 0x40 || L == 0x80)
459 else if (L == 0xc0 || L == 0x100)
473 *ptr++ = (L & 0xff00) >> 8;
474 *ptr++ = (L & 0x00ff);
486 for (i = 0; i < n_iterations; i++) {
493 memcpy(key_out, result, L / 8);
557 return memcmp(card_cryptogram, calculated_card_cryptogram,
574static yh_rc derive_keys(
const uint8_t *password,
size_t password_len,
594 const uint8_t *password,
size_t password_len,
597 if (connector == NULL || password == NULL ||
session == NULL) {
605 yh_rc yrc = derive_keys(password, password_len, key_enc, key_mac);
617 const uint8_t *key_enc,
size_t key_enc_len,
618 const uint8_t *key_mac,
size_t key_mac_len,
629 if (connector == NULL || key_enc == NULL || key_enc_len !=
SCP_KEY_LEN ||
635 if (!
rand_generate(host_challenge,
sizeof(host_challenge))) {
641 if (new_session == NULL) {
658 msg.
st.cmd = YHC_CREATE_SESSION;
661 uint16_t authkey_id_n = htons(authkey_id);
668 yrc = send_msg(connector, &msg, &response_msg);
674 if (response_msg.
st.cmd != YHC_CREATE_SESSION_R) {
675 yh_rc translated = translate_device_error(response_msg.
st.data[0]);
677 response_msg.
st.data[0]);
687 ptr = response_msg.
st.data;
690 new_session->
s.
sid = (*ptr++);
699 DBG_INFO(
"Received Session ID: %d", new_session->
s.
sid);
707 derive_s_enc(&new_session->
s, key_enc, key_enc_len, new_session->
context);
712 derive_s_mac(&new_session->
s, key_mac, key_mac_len, new_session->
context);
717 derive_s_rmac(&new_session->
s, key_mac, key_enc_len, new_session->
context);
725 yrc = verify_card_cryptogram(&new_session->
s, new_session->
context,
732 DBG_INFO(
"Card cryptogram successfully verified");
735 new_session->
parent = connector;
744 (new_session) = NULL;
753 size_t card_cryptogram_len,
763 if (connector == NULL ||
context == NULL || card_cryptogram == NULL ||
769 if (!
rand_generate(host_challenge,
sizeof(host_challenge))) {
777 if (new_session == NULL) {
783 msg.
st.cmd = YHC_CREATE_SESSION;
786 uint16_t authkey_id_n = htons(authkey_id);
793 yrc = send_msg(connector, &msg, &response_msg);
799 if (response_msg.
st.cmd != YHC_CREATE_SESSION_R) {
800 yh_rc translated = translate_device_error(response_msg.
st.data[0]);
802 response_msg.
st.data[0]);
812 ptr = response_msg.
st.data;
815 new_session->
s.
sid = (*ptr++);
824 DBG_INFO(
"Received Session ID: %d", new_session->
s.
sid);
831 new_session->
parent = connector;
840 (new_session) = NULL;
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) {
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 ||
885 DBG_INFO(
"Card cryptogram successfully verified");
914 if (connector == NULL ||
major == NULL ||
minor == NULL ||
patch == NULL) {
928 if (connector == NULL || address == NULL) {
933 *address = (
char *) connector->
address;
943 if (connector == NULL) {
964 size_t response_len =
sizeof(response);
968 &response_cmd, response.buf, &response_len);
975 yh_rc translated = translate_device_error(response.buf[0]);
982 *
major = response.major;
986 *
minor = response.minor;
990 *
patch = response.patch;
994 *
serial = ntohl(response.serial);
997 if (log_total != NULL) {
998 *log_total = response.log_total;
1001 if (log_used != NULL) {
1002 *log_used = response.log_used;
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");
1014 for (
size_t i = 0; i < items; i++) {
1015 algorithms[i] = response.algorithms[i];
1017 *n_algorithms = items;
1025#define LIST_DOMAINS 3
1026#define LIST_CAPABILITIES 4
1027#define LIST_ALGORITHM 5
1046 size_t response_len =
sizeof(response);
1053 *dataptr++ =
id >> 8 & 0xff;
1054 *dataptr++ =
id & 0xff;
1064 *dataptr++ =
domains >> 8 & 0xff;
1080 bool send_capabilities =
false;
1083 send_capabilities =
true;
1088 if (send_capabilities ==
true) {
1096 &response_cmd, response, &response_len);
1103 yh_rc translated = translate_device_error(response[0]);
1110 DBG_ERR(
"Objects buffer too small");
1115 for (
uint16_t i = 0; i < response_len; i += 4) {
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];
1140#pragma pack(push, 1)
1156 size_t response_len =
sizeof(response);
1162 *dataptr++ =
id >> 8 & 0xff;
1163 *dataptr++ =
id & 0xff;
1168 &response_cmd, response.buf, &response_len);
1175 yh_rc translated = translate_device_error(response.buf[0]);
1181 if (response_len ==
sizeof(response)) {
1186 object->id = htons(response.id);
1188 object->len = htons(response.len);
1190 object->domains = htons(response.domains);
1192 object->type = response.type;
1194 object->algorithm = response.algorithm;
1196 object->sequence = response.sequence;
1198 object->origin = response.origin;
1207 DBG_ERR(
"Wrong response length, expecting %lu or 0, received %lu",
1209 (
unsigned long) response_len);
1219 if (
session == NULL || data == NULL || data_len == NULL) {
1224 uint8_t cmd[2] = {
id >> 8,
id & 0xff};
1227 size_t response_len =
sizeof(response);
1230 &response_cmd, response, &response_len);
1238 yh_rc translated = translate_device_error(response[0]);
1244 if (response_len > *data_len) {
1251 *data_len = response_len - 1;
1252 memcpy(data, response + 1, *data_len);
1267 size_t response_len =
sizeof(response);
1271 response, &response_len);
1278 yh_rc translated = translate_device_error(response[0]);
1291 if (
session == NULL || in == NULL || out == NULL ||
out_len == NULL) {
1305 DBG_ERR(
"Data length must be 20, 32, 48 or 64");
1311#pragma pack(push, 1)
1324 data.key_id = htons(
key_id);
1337 yh_rc translated = translate_device_error(out[0]);
1350 if (
session == NULL || in == NULL || out == NULL ||
out_len == NULL) {
1363 DBG_ERR(
"Data length must be 20, 32, 48 or 64");
1369#pragma pack(push, 1)
1384 data.key_id = htons(
key_id);
1386 data.mgf1Algo = mgf1Algo;
1390 data.salt_len = htons(salt_len);
1402 yh_rc translated = translate_device_error(out[0]);
1415 if (
session == NULL || in == NULL || out == NULL ||
out_len == NULL) {
1430 DBG_ERR(
"Data length must be 20, 28, 32, 48, 64 or 66");
1436#pragma pack(push, 1)
1449 data.key_id = htons(
key_id);
1461 yh_rc translated = translate_device_error(out[0]);
1474 if (
session == NULL || in == NULL || out == NULL ||
out_len == NULL) {
1486#pragma pack(push, 1)
1499 data.key_id = htons(
key_id);
1511 yh_rc translated = translate_device_error(out[0]);
1523 if (
session == NULL || in == NULL || out == NULL ||
out_len == NULL) {
1538 data[0] = htons(
key_id) & 0xff;
1539 data[1] = htons(
key_id) >> 8;
1552 yh_rc translated = translate_device_error(out[0]);
1574 data.len = htons(
len);
1577 sizeof(data), &response_cmd, out,
out_len);
1584 yh_rc translated = translate_device_error(out[0]);
1597#pragma pack(push, 1)
1616 size_t response_len =
sizeof(response);
1619 k.key_id = htons(*
key_id);
1632 uint16_t len =
sizeof(k.key_id) +
sizeof(k.domains) +
sizeof(k.capabilities) +
1633 sizeof(k.algo) +
sizeof(k.label) +
key_len;
1635 &response_cmd, response.buf, &response_len);
1643 yh_rc translated = translate_device_error(response.buf[0]);
1649 *
key_id = ntohs(response.key_id);
1671 component_len = 128;
1673 component_len = 192;
1675 component_len = 256;
1679 memcpy(keybuf,
p, component_len);
1680 memcpy(keybuf + component_len, q, component_len);
1762#pragma pack(push, 1)
1782 size_t response_len =
sizeof(response);
1784 size_t max_len = 64;
1785 int len =
sizeof(k) -
sizeof(k.key);
1787 k.key_id = htons(*
key_id);
1803 DBG_ERR(
"Too long key supplied, max %lu bytes allowed",
1804 (
unsigned long) max_len);
1812 response.buf, &response_len);
1820 yh_rc translated = translate_device_error(response.buf[0]);
1826 *
key_id = ntohs(response.key_id);
1845#pragma pack(push, 1)
1856 int data_len =
sizeof(data);
1864 size_t response_len =
sizeof(response);
1867 data.key_id = htons(*
key_id);
1872 data.domains = htons(
domains);
1880 &response_cmd, response.buf, &response_len);
1882 DBG_ERR(
"Failed to send GENERATE ASYMMETRIC KEY command: %s",
1888 yh_rc translated = translate_device_error(response.buf[0]);
1894 *
key_id = ntohs(response.key_id);
1940 const uint8_t *signature,
size_t signature_len,
1941 const uint8_t *data,
size_t data_len,
1944 if (
session == NULL || signature == NULL || data == NULL ||
1961 size_t response_len =
sizeof(response);
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;
1974 &response_cmd, response, &response_len);
1981 yh_rc translated = translate_device_error(response[0]);
1987 *verified = response[0];
2005#pragma pack(push, 1)
2024 size_t response_len =
sizeof(response);
2027 data.key_id = htons(*
key_id);
2032 data.domains = htons(
domains);
2040 &response_cmd, response.buf, &response_len);
2047 yh_rc translated = translate_device_error(response.buf[0]);
2053 *
key_id = ntohs(response.key_id);
2063 if (
session == NULL || in == NULL || out == NULL ||
out_len == NULL) {
2073#pragma pack(push, 1)
2086 data.key_id = htons(
key_id);
2098 yh_rc translated = translate_device_error(out[0]);
2112 if (
session == NULL || in == NULL || out == NULL ||
out_len == NULL ||
2118#pragma pack(push, 1)
2133 data.key_id = htons(
key_id);
2134 len +=
sizeof(data.key_id);
2136 data.mgf1Algo = mgf1Algo;
2137 len +=
sizeof(data.mgf1Algo);
2141 DBG_ERR(
"Wrong input length");
2148 DBG_ERR(
"Wrong label length");
2165 yh_rc translated = translate_device_error(out[0]);
2178 if (
session == NULL || in == NULL || out == NULL ||
out_len == NULL) {
2188#pragma pack(push, 1)
2201 data.key_id = htons(
key_id);
2213 yh_rc translated = translate_device_error(out[0]);
2230#pragma pack(push, 1)
2243 size_t response_len =
sizeof(response);
2246 data.id = htons(
id);
2249 &response_cmd, response, &response_len);
2256 yh_rc translated = translate_device_error(response[0]);
2274#pragma pack(push, 1)
2288 data.key_id = htons(wrapping_key_id);
2300 yh_rc translated = translate_device_error(out[0]);
2324#pragma pack(push, 1)
2336 size_t response_len =
sizeof(response);
2340 data.key_id = htons(wrapping_key_id);
2344 &response_cmd, response, &response_len);
2351 yh_rc translated = translate_device_error(response[0]);
2377#pragma pack(push, 1)
2399 size_t response_len =
sizeof(response);
2427 data.key_id = htons(*
key_id);
2430 data.domains = htons(
domains);
2438 &response_cmd, response.buf, &response_len);
2446 yh_rc translated = translate_device_error(response.buf[0]);
2452 *
key_id = ntohs(response.key_id);
2473#pragma pack(push, 1)
2494 size_t response_len =
sizeof(response);
2497 data.key_id = htons(*
key_id);
2502 data.domains = htons(
domains);
2512 &response_cmd, response.buf, &response_len);
2519 yh_rc translated = translate_device_error(response.buf[0]);
2525 *
key_id = ntohs(response.key_id);
2535 if (
session == NULL || out == NULL || n_items == NULL) {
2551 size_t response_len =
sizeof(response);
2555 response.buf, &response_len);
2562 yh_rc translated = translate_device_error(response.buf[0]);
2568 if (unlogged_boot) {
2569 *unlogged_boot = ntohs(response.log_overflow_boot);
2572 if (unlogged_auth) {
2573 *unlogged_auth = ntohs(response.log_overflow_auth);
2578 "Response contain more items than the maximum number of log entries");
2582 if (response.items > *n_items) {
2583 DBG_ERR(
"Log buffer too small, needed at lest %d, got %zu", response.items,
2588 *n_items = response.items;
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);
2615 size_t response_len =
sizeof(response);
2618 memcpy(data, &index_h,
sizeof(index_h));
2620 &response_cmd, response, &response_len);
2627 yh_rc translated = translate_device_error(response[0]);
2648 uint16_t object_id_h = htons(object_id);
2649 memcpy(data, &object_id_h,
sizeof(object_id_h));
2658 yh_rc translated = translate_device_error(out[0]);
2672 if (
session == NULL || object_id == NULL ||
label == NULL ||
2680#pragma pack(push, 1)
2701 size_t response_len =
sizeof(response);
2704 data.object_id = htons(*object_id);
2709 data.domains = htons(
domains);
2715 if (
in_len >
sizeof(data.bytes)) {
2716 DBG_ERR(
"Data length must be in [0, %lu]\n",
2717 (
unsigned long)
sizeof(data.bytes));
2721 data_len =
in_len +
sizeof(data) -
sizeof(data.bytes);
2725 &response_cmd, response.buf, &response_len);
2733 yh_rc translated = translate_device_error(response.buf[0]);
2739 *object_id = ntohs(response.object_id);
2740 DBG_INFO(
"Stored Opaque Object 0x%04x", *object_id);
2749 if (
session == NULL || in == NULL || out == NULL ||
out_len == NULL ||
2757#pragma pack(push, 1)
2772 data.key_id = htons(
key_id);
2774 data.template_id = htons(template_id);
2776 data.algo = sig_algo;
2778 if (
in_len >
sizeof(data.bytes)) {
2779 DBG_ERR(
"Data length must be in [0, %lu]\n",
2780 (
unsigned long)
sizeof(data.bytes));
2788 data_len, &response_cmd, out,
out_len);
2790 DBG_ERR(
"Failed to send SIGN SSH CERTIFICATE command: %s",
2796 yh_rc translated = translate_device_error(out[0]);
2807 if (
session == NULL || out == NULL) {
2816 uint16_t object_id_h = htons(object_id);
2817 memcpy(data, &object_id_h,
sizeof(object_id_h));
2826 yh_rc translated = translate_device_error(out[0]);
2841 if (
session == NULL || object_id == NULL ||
label == NULL ||
2849#pragma pack(push, 1)
2871 size_t response_len =
sizeof(response);
2874 data.object_id = htons(*object_id);
2879 data.domains = htons(
domains);
2885 if (
in_len >
sizeof(data.bytes)) {
2886 DBG_ERR(
"Data length must be in [0, %lu]\n",
2887 (
unsigned long)
sizeof(data.bytes));
2891 data_len =
in_len +
sizeof(data.object_id) +
sizeof(data.domains) +
2896 &response_cmd, response.buf, &response_len);
2903 yh_rc translated = translate_device_error(response.buf[0]);
2909 *object_id = ntohs(response.object_id);
2910 DBG_INFO(
"Stored Opaque Object 0x%04x", *object_id);
2917 if (
session == NULL || sid == NULL) {
2942 msg.
st.cmd = YHC_AUTHENTICATE_SESSION;
2948 yrc = compute_host_cryptogram(
session, msg.
st.data + 1);
2958 msg.
st.len = htons(msg.
st.len);
2960 msg.
st.len = ntohs(msg.
st.len);
2963 session->s.mac_chaining_value);
2971 yrc = send_msg(
session->parent, &msg, &response_msg);
2977 if (response_msg.
st.cmd != YHC_AUTHENTICATE_SESSION_R) {
2989 size_t key_enc_len,
const uint8_t *key_mac,
size_t key_mac_len) {
2994 key_enc_len !=
YH_KEY_LEN || key_mac == NULL ||
3000#pragma pack(push, 1)
3021 size_t response_len =
sizeof(response);
3027 data.key_id = htons(*
key_id);
3032 data.domains = htons(
domains);
3042 sizeof(data), &response_cmd, response.buf,
3046 DBG_ERR(
"Failed to send PUT AUTHENTICATION KEY command: %s\n",
3052 yh_rc translated = translate_device_error(response.buf[0]);
3053 DBG_ERR(
"Unable to store authentication key: %s (%x)\n",
3058 *
key_id = ntohs(response.key_id);
3068 size_t password_len) {
3080 yh_rc yrc = derive_keys(password, password_len, key_enc, key_mac);
3086 key_enc,
sizeof(key_enc), key_mac,
3098 size_t key_mac_len) {
3101 key_enc_len !=
YH_KEY_LEN || key_mac == NULL ||
3107#pragma pack(push, 1)
3124 size_t response_len =
sizeof(response);
3127 data.key_id = htons(*
key_id);
3129 memcpy(data.key_enc, key_enc, key_enc_len);
3130 memcpy(data.key_mac, key_mac, key_mac_len);
3133 data.buf,
sizeof(data), &response_cmd,
3134 response.buf, &response_len);
3137 DBG_ERR(
"Failed to send CHANGE AUTHENTICATION KEY command: %s\n",
3143 yh_rc translated = translate_device_error(response.buf[0]);
3144 DBG_ERR(
"Unable to change authentication key: %s (%x)\n",
3149 *
key_id = ntohs(response.key_id);
3158 size_t password_len) {
3159 if (
session == NULL ||
key_id == NULL || password == NULL) {
3167 yh_rc yrc = derive_keys(password, password_len, key_enc, key_mac);
3171 sizeof(key_enc), key_mac,
3183 if (
session == NULL || key == NULL || private_id == NULL || out == NULL ||
3188#pragma pack(push, 1)
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));
3206 sizeof(data), &response_cmd, out,
out_len);
3214 yh_rc translated = translate_device_error(out[0]);
3230#pragma pack(push, 1)
3241 data.key_id = htons(
key_id);
3244 sizeof(data), &response_cmd, out,
out_len);
3246 DBG_ERR(
"Failed to send RANDOMIZE OTP AEAD command: %s\n",
3252 yh_rc translated = translate_device_error(out[0]);
3262 const uint8_t *aead,
size_t aead_len,
3267#pragma pack(push, 1)
3287 if (
session == NULL || aead == NULL ||
otp == NULL ||
3288 aead_len !=
sizeof(data.aead)) {
3294 size_t response_len =
sizeof(response);
3296 data.key_id = htons(
key_id);
3297 memcpy(data.aead, aead,
sizeof(data.aead));
3298 memcpy(data.otp,
otp,
sizeof(data.otp));
3302 &response_cmd, response.buf, &response_len);
3310 yh_rc translated = translate_device_error(response.buf[0]);
3316 if (response_len !=
sizeof(response)) {
3317 DBG_ERR(
"Wrong size returned");
3322 *useCtr = response.useCtr;
3325 *sessionCtr = response.sessionCtr;
3328 *tstph = response.tstph;
3331 *tstpl = response.tstpl;
3348#pragma pack(push, 1)
3370 size_t response_len =
sizeof(response);
3378 }
else if (
in_len == 24) {
3381 }
else if (
in_len == 32) {
3384 DBG_ERR(
"Key length has to be 16, 24 or 32 bytes.");
3388 data.key_id = htons(*
key_id);
3393 data.domains = htons(
domains);
3397 data.nonce_id = nonce_id;
3402 &response_cmd, response.buf, &response_len);
3410 yh_rc translated = translate_device_error(response.buf[0]);
3416 *
key_id = ntohs(response.key_id);
3435#pragma pack(push, 1)
3456 size_t response_len =
sizeof(response);
3459 data.key_id = htons(*
key_id);
3464 data.domains = htons(
domains);
3470 data.nonce_id = nonce_id;
3474 &response_cmd, response.buf, &response_len);
3477 DBG_ERR(
"Failed to send GENERATE OTP AEAD KEY command: %s",
3483 yh_rc translated = translate_device_error(response.buf[0]);
3489 *
key_id = ntohs(response.key_id);
3503#pragma pack(push, 1)
3515 data.key_id = htons(
key_id);
3516 data.attest_id = htons(attest_id);
3520 sizeof(data), &response_cmd, out,
out_len);
3522 DBG_ERR(
"Failed to send SIGN ATTESTATION CERTIFICATE command: %s\n",
3528 yh_rc translated = translate_device_error(out[0]);
3540 if (
session == NULL || val == NULL) {
3550#pragma pack(push, 1)
3561 size_t outlen =
sizeof(out);
3565 data.len = htons(
len);
3569 &response_cmd, out, &outlen);
3576 yh_rc translated = translate_device_error(out[0]);
3602 yh_rc translated = translate_device_error(out[0]);
3620#pragma pack(push, 1)
3632 size_t response_len =
sizeof(response);
3635 &response_cmd, response.buf, &response_len);
3642 yh_rc translated = translate_device_error(response.buf[0]);
3648 if (total_records) {
3649 *total_records = ntohs(response.total_records);
3652 *free_records = ntohs(response.free_records);
3655 *total_pages = ntohs(response.total_pages);
3658 *free_pages = ntohs(response.free_pages);
3661 *page_size = ntohs(response.page_size);
3670 if (
session == NULL || in == NULL || out == NULL ||
out_len == NULL) {
3682#pragma pack(push, 1)
3695 data.key_id = htons(
key_id);
3707 yh_rc translated = translate_device_error(out[0]);
3720 if (
session == NULL || in == NULL || out == NULL ||
out_len == NULL) {
3732#pragma pack(push, 1)
3745 data.key_id = htons(
key_id);
3757 yh_rc translated = translate_device_error(out[0]);
3776 size_t response_len =
sizeof(response);
3780 &response_cmd, response, &response_len);
3787 yh_rc translated = translate_device_error(response[0]);
3807 size_t response_len =
sizeof(response);
3810 response, &response_len);
3817 yh_rc translated = translate_device_error(response[0]);
3829 if (connector != NULL && connector->
bf != NULL) {
3839 if (verbosity == NULL) {
3851 if (connector != NULL && connector->
bf != NULL) {
3865static yh_rc load_backend(
const char *
name,
3869 DBG_ERR(
"No name given to load_backend");
3873 *bf = usb_backend_functions();
3876 *bf = http_backend_functions();
3879 DBG_ERR(
"Failed finding backend named '%s'",
name);
3886static yh_rc load_backend(
const char *
name,
void **backend,
3890 *backend = LoadLibrary(
name);
3891 if (*backend == NULL) {
3896 (void (*)(void)) GetProcAddress(*backend,
"backend_functions"));
3898 *backend = dlopen(
name, RTLD_NOW);
3899 if (*backend == NULL) {
3900 DBG_ERR(
"Failed loading '%s' with error: '%s'",
name, dlerror());
3912#define STATUS_ENDPOINT "/connector/status"
3913#define API_ENDPOINT "/connector/api"
3920 if (connector == NULL) {
3925 if (*connector == NULL) {
3930 (*connector)->status_url = strdup(
url);
3931 if ((*connector)->status_url == NULL) {
3935 (*connector)->api_url = strdup(
url);
3936 if ((*connector)->api_url == NULL) {
3941 (*connector)->status_url =
3943 if ((*connector)->status_url == NULL) {
3949 (*connector)->api_url = calloc(1, strlen(
url) + strlen(
API_ENDPOINT) + 1);
3950 if ((*connector)->api_url == NULL) {
3958 if ((*connector)->connection == NULL) {
3963 (*connector)->backend = backend;
3964 (*connector)->bf = bf;
3969 if ((*connector)->status_url) {
3970 free((*connector)->status_url);
3971 (*connector)->status_url = NULL;
3974 if ((*connector)->api_url) {
3975 free((*connector)->api_url);
3976 (*connector)->api_url = NULL;
3987static void destroy_connector(
yh_connector *connector) {
3989 if (connector == NULL) {
3993 if (connector->
bf != NULL && connector->
connection != NULL) {
3994 connector->
bf->backend_disconnect(connector->
connection);
4003 if (connector->
api_url != NULL) {
4008 if (connector->
bf) {
4009 connector->
bf->backend_cleanup();
4012 FreeLibrary(connector->
backend);
4018 connector->
bf = NULL;
4025 if (
url == NULL || connector == NULL) {
4026 DBG_ERR(
"Invalid parameters: undefined pointer");
4031#define USB_LIB STATIC_USB_BACKEND
4032#define HTTP_LIB STATIC_HTTP_BACKEND
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"
4040#define USB_LIB "libyubihsm_usb.so." SOVERSION
4041#define HTTP_LIB "libyubihsm_http.so." SOVERSION
4044 void *backend = NULL;
4049 load_backend(
USB_LIB, &backend, &bf);
4050 }
else if (strncmp(
url,
"http://", strlen(
"http://")) == 0 ||
4051 strncmp(
url,
"https://", strlen(
"https://")) == 0) {
4053 load_backend(
HTTP_LIB, &backend, &bf);
4056 DBG_ERR(
"Failed loading the backend");
4060 return create_connector(connector,
url, backend, bf);
4066 if (connector == NULL || val == NULL) {
4067 DBG_ERR(
"Invalid parameters: undefined pointer");
4071 if (connector->
bf == NULL) {
4076 return connector->
bf->backend_option(connector->
connection, opt, val);
4081 if (connector == NULL || connector->
bf == NULL) {
4082 DBG_ERR(
"Invalid parameters: undefined pointer");
4088 rc = connector->
bf->backend_connect(connector, timeout);
4099 if (connector == NULL) {
4104 destroy_connector(connector);
4113 : ((uint64_t) htonl((x) &0xFFFFFFFF) << 32) | htonl((x) >> 32))
4119 char *saveptr = NULL;
4121 char tmp[2048] = {0};
4124 if (capability == NULL || result == NULL) {
4130 value = strtoull(capability, &endptr, 0);
4132 if (capability != endptr && errno != ERANGE) {
4134 memcpy(result, &actual, 8);
4138 if (strcasecmp(capability,
"all") == 0) {
4141 }
else if (strcasecmp(capability,
"none") == 0) {
4146 if (strlen(capability) >
sizeof(tmp)) {
4149 strncpy(tmp, capability,
sizeof(tmp) - 1);
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]);
4154 if (strcasecmp(str, yh_capability[i].
name) == 0) {
4157 1ULL << (yh_capability[i].bit % 8);
4159 }
else if (i + 1 ==
sizeof(yh_capability) /
sizeof(yh_capability[0])) {
4169 const char *result[],
size_t *n_result) {
4171 if (num == 0 || result == NULL || n_result == NULL) {
4176 size_t matching = 0;
4178 for (
size_t i = 0; i <
sizeof(yh_capability) /
sizeof(yh_capability[0]);
4180 if (((1ULL << (yh_capability[i].
bit % 8)) &
4182 (yh_capability[i].bit / 8)]) != 0) {
4183 if (++matching > *n_result) {
4184 memset(result, 0, *n_result);
4189 result[matching - 1] = yh_capability[i].name;
4193 *n_result = matching;
4199 const char *capability) {
4221 if (
a == NULL || b == NULL || result == NULL) {
4226 result->capabilities[i] =
a->capabilities[i] | b->
capabilities[i];
4234 if (
capabilities == NULL || filter == NULL || result == NULL) {
4239 result->capabilities[i] =
4311 if (result == NULL) {
4386 if (result == NULL) {
4391 for (
size_t i = 0; i <
sizeof(yh_algorithms) /
sizeof(yh_algorithms[0]);
4393 if (algo == yh_algorithms[i].
algorithm) {
4394 *result = yh_algorithms[i].name;
4399 *result =
"Unknown";
4405 if (
string == NULL || algo == NULL) {
4409 if (strcasecmp(
string,
"any") == 0) {
4413 for (
size_t i = 0; i <
sizeof(yh_algorithms) /
sizeof(yh_algorithms[0]);
4415 if (strcasecmp(
string, yh_algorithms[i].
name) == 0) {
4416 *algo = yh_algorithms[i].algorithm;
4426 if (result == NULL) {
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;
4438 *result =
"Unknown";
4444 if (
string == NULL || type == NULL) {
4449 if (strcasecmp(
string,
"any") == 0) {
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;
4465 if (
string == NULL ||
option == NULL) {
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;
4482 if (logs == NULL || n_items == 0) {
4488 size_t previous_hash_len = 32;
4496 if (last_previous_log != NULL) {
4504 for (
uint16_t i = start; i < n_items; i++) {
4506 inverted.
number = htons(logs[i].number);
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);
4513 inverted.
systick = htonl(logs[i].systick);
4519 hash_final(hashctx, previous_hash, &previous_hash_len);
4537 char *saveptr = NULL;
4540 unsigned long value;
4542 if (
domains == NULL || result == NULL) {
4548 if (strcasecmp(
domains,
"all") == 0) {
4551 }
else if (strcmp(
domains,
"0") == 0) {
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");
4566 if (strlen(
domains) >
sizeof(tmp)) {
4569 strncpy(tmp,
domains,
sizeof(tmp) - 1);
4571 while ((str = strtok_r(str ? NULL : tmp,
LIST_SEPARATORS, &saveptr))) {
4573 value = strtoul(str, &endptr, 0);
4578 *result |= 1 << (
value - 1);
4583 DBG_INFO(
"Domains parsed as %x", *result);
4592 size_t wrote = snprintf(ptr, max_len,
"%d:", i + 1);
4593 if (wrote >= max_len) {
4600 if (ptr !=
string) {
void aes_remove_padding(uint8_t *in, uint16_t *len)
uint8_t aes_set_encrypt_key(uint8_t *key, uint16_t key_len, aes_context *ctx)
void aes_destroy(aes_context *ctx)
uint8_t aes_encrypt(uint8_t *in, uint8_t *out, const aes_context *ctx)
uint8_t aes_cbc_decrypt(uint8_t *in, uint8_t *out, uint16_t len, uint8_t *iv, aes_context *ctx)
void aes_add_padding(uint8_t *in, uint16_t *len)
uint8_t aes_set_decrypt_key(uint8_t *key, uint16_t key_len, aes_context *ctx)
uint8_t aes_cbc_encrypt(uint8_t *in, uint8_t *out, uint16_t len, uint8_t *iv, aes_context *ctx)
uint8_t aes_cmac_init(uint8_t *key, uint16_t key_len, aes_cmac_context_t *ctx)
void aes_cmac_destroy(aes_cmac_context_t *ctx)
void aes_cmac_encrypt(const aes_cmac_context_t *ctx, const uint8_t *message, const uint16_t message_len, uint8_t *mac)
#define DBG_CRYPTO(var, len,...)
#define DBG_DUMPERR(var, len,...)
#define DBG_NET(var, dump)
#define DBG_INT(var, len,...)
#define DBG_DUMPINFO(var, len,...)
CK_SESSION_HANDLE session
bool hash_update(_hash_ctx *ctx, const uint8_t *in, size_t cb_in)
bool hash_create(_hash_ctx **ctx, hash_t hash)
bool hash_init(_hash_ctx *ctx)
bool hash_destroy(_hash_ctx *ctx)
bool hash_final(_hash_ctx *ctx, uint8_t *out, size_t *pcb_out)
#define insecure_memzero(buf, len)
const char * yh_strerror(yh_rc err)
void YH_INTERNAL dump_response(FILE *file, const Msg *msg)
void YH_INTERNAL dump_msg(FILE *file, const Msg *msg)
struct sysio::chain::eosvmoc::code_cache_header __attribute__((packed))
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)
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
bool rand_generate(uint8_t *buf, size_t cb_buf)
#define SCP_S_RMAC_DERIVATION
#define SCP_CARD_CRYPTOGRAM
#define SCP_S_MAC_DERIVATION
#define SCP_CARD_CHAL_LEN
#define SCP_S_ENC_DERIVATION
#define SCP_AUTHKEY_ID_LEN
#define SCP_HOST_CRYPTO_LEN
#define SCP_HOST_CHAL_LEN
#define SCP_HOST_CRYPTOGRAM
#define SCP_CARD_CRYPTO_LEN
unsigned __int64 uint64_t
uint8_t s_mac[SCP_KEY_LEN]
uint8_t s_rmac[SCP_KEY_LEN]
uint8_t s_enc[SCP_KEY_LEN]
yh_backend *(* backend_create)(void)
Capabilities representation.
uint8_t capabilities[YH_CAPABILITIES_LEN]
Capabilities is represented as an 8 byte uint8_t array.
struct backend_functions * bf
uint8_t digest[YH_LOG_DIGEST_SIZE]
Truncated sha256 digest of this last digest + this entry.
uint16_t second_key
ID of second Object used.
uint8_t result
Command result.
uint32_t systick
Systick at time of execution.
uint16_t session_key
ID of Authentication Key used.
uint16_t target_key
ID of first Object used.
uint16_t length
Length of in-data.
uint8_t command
What command was executed.
uint16_t number
Monotonically increasing index.
uint8_t sequence
Object sequence.
yh_capabilities capabilities
Object capabilities.
yh_capabilities delegated_capabilities
Object delegated capabilities.
char label[YH_OBJ_LABEL_LEN+1]
Object label.
yh_object_type type
Object type.
uint8_t key_enc[SCP_KEY_LEN]
struct yh_connector * parent
uint8_t key_mac[SCP_KEY_LEN]
uint8_t context[SCP_CONTEXT_LEN]
uint8_t raw[3+SCP_MSG_BUF_SIZE]
bool yh_verify_logs(yh_log_entry *logs, size_t n_items, yh_log_entry *last_previous_log)
yh_rc yh_domains_to_string(uint16_t domains, char *string, size_t max_len)
bool yh_is_rsa(yh_algorithm algorithm)
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)
yh_rc yh_util_get_option(yh_session *session, yh_option option, uint8_t *out, size_t *out_len)
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)
bool yh_connector_has_device(yh_connector *connector)
bool yh_is_ed(yh_algorithm algorithm)
yh_rc yh_get_verbosity(uint8_t *verbosity)
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)
yh_rc yh_destroy_session(yh_session **session)
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)
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)
yh_rc yh_set_verbosity(yh_connector *connector, uint8_t verbosity)
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)
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)
yh_rc yh_algo_to_string(yh_algorithm algo, char const **result)
yh_rc yh_get_connector_version(yh_connector *connector, uint8_t *major, uint8_t *minor, uint8_t *patch)
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)
bool yh_is_ec(yh_algorithm algorithm)
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)
yh_rc yh_get_key_bitlength(yh_algorithm algorithm, size_t *result)
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)
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)
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)
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)
yh_rc yh_util_get_template(yh_session *session, uint16_t object_id, uint8_t *out, size_t *out_len)
yh_rc yh_util_randomize_otp_aead(yh_session *session, uint16_t key_id, uint8_t *out, size_t *out_len)
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)
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)
uint8_t _yh_verbosity YH_INTERNAL
yh_rc yh_string_to_option(const char *string, yh_option *option)
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)
yh_rc yh_util_get_opaque(yh_session *session, uint16_t object_id, uint8_t *out, size_t *out_len)
yh_rc yh_string_to_type(const char *string, yh_object_type *type)
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)
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)
yh_rc yh_util_reset_device(yh_session *session)
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)
yh_rc yh_util_close_session(yh_session *session)
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)
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)
yh_rc yh_authenticate_session(yh_session *session)
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)
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)
yh_rc yh_util_get_object_info(yh_session *session, uint16_t id, yh_object_type type, yh_object_descriptor *object)
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)
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)
void yh_set_debug_output(yh_connector *connector, FILE *output)
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)
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)
yh_rc yh_util_set_option(yh_session *session, yh_option option, size_t len, uint8_t *val)
yh_rc yh_util_change_authentication_key_derived(yh_session *session, uint16_t *key_id, const uint8_t *password, size_t password_len)
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)
yh_rc yh_filter_capabilities(const yh_capabilities *capabilities, const yh_capabilities *filter, yh_capabilities *result)
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)
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)
yh_rc yh_string_to_domains(const char *domains, uint16_t *result)
yh_rc yh_set_connector_option(yh_connector *connector, yh_connector_option opt, const void *val)
yh_rc yh_init_connector(const char *url, yh_connector **connector)
yh_rc yh_util_set_log_index(yh_session *session, uint16_t index)
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)
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)
yh_rc yh_connect(yh_connector *connector, int timeout)
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)
yh_rc yh_util_get_public_key(yh_session *session, uint16_t id, uint8_t *data, size_t *data_len, yh_algorithm *algorithm)
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)
yh_rc yh_string_to_capabilities(const char *capability, yh_capabilities *result)
yh_rc yh_string_to_algo(const char *string, yh_algorithm *algo)
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)
yh_rc yh_disconnect(yh_connector *connector)
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)
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)
bool yh_check_capability(const yh_capabilities *capabilities, const char *capability)
#define STATIC_HTTP_BACKEND
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)
yh_rc yh_capabilities_to_strings(const yh_capabilities *num, const char *result[], size_t *n_result)
#define STATIC_USB_BACKEND
bool yh_is_hmac(yh_algorithm algorithm)
yh_rc yh_get_connector_address(yh_connector *connector, char **const address)
yh_rc yh_util_blink_device(yh_session *session, uint8_t seconds)
#define LIST_CAPABILITIES
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)
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)
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)
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)
yh_rc yh_util_delete_object(yh_session *session, uint16_t id, yh_object_type type)
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)
yh_rc yh_get_session_id(yh_session *session, uint8_t *sid)
yh_rc yh_util_get_pseudo_random(yh_session *session, size_t len, uint8_t *out, size_t *out_len)
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)
yh_rc yh_merge_capabilities(const yh_capabilities *a, const yh_capabilities *b, yh_capabilities *result)
yh_rc yh_type_to_string(yh_object_type type, char const **result)
#define YH_DEFAULT_ITERS
Number of iterations for PBKDF2 key derivation.
#define YH_LOG_DIGEST_SIZE
Size that the log digest is truncated to.
#define YH_HOST_CHAL_LEN
Length of host challenge for authentication.
#define YH_OBJ_LABEL_LEN
Max length of object labels.
@ YH_ALGO_EC_BP384
ecbp384
@ YH_ALGO_AES128_YUBICO_AUTHENTICATION
aes128-yubico-authentication
@ YH_ALGO_AES192_YUBICO_OTP
aes192-yubico-otp
@ YH_ALGO_AES128_YUBICO_OTP
aes128-yubico-otp
@ YH_ALGO_EC_ED25519
ed25519
@ YH_ALGO_HMAC_SHA512
hmac-sha512
@ YH_ALGO_HMAC_SHA384
hmac-sha384
@ YH_ALGO_AES256_CCM_WRAP
aes256-ccm-wrap
@ YH_ALGO_HMAC_SHA1
hmac-sha1
@ YH_ALGO_RSA_2048
rsa2048
@ YH_ALGO_HMAC_SHA256
hmac-sha256
@ YH_ALGO_AES192_CCM_WRAP
aes192-ccm-wrap
@ YH_ALGO_EC_BP512
ecbp512
@ YH_ALGO_EC_BP256
ecbp256
@ YH_ALGO_AES256_YUBICO_OTP
aes256-yubico-otp
@ YH_ALGO_AES128_CCM_WRAP
aes128-ccm-wrap
@ YH_ALGO_RSA_4096
rsa4096
@ YH_ALGO_RSA_3072
rsa3072
#define YH_USB_URL_SCHEME
URL scheme used for direct USB access.
#define YH_MAX_ALGORITHM_COUNT
Max number of algorithms defined here.
#define YH_MSG_BUF_SIZE
Maximum length of message buffer.
#define YH_DEFAULT_SALT
Salt to be used for PBKDF2 key derivation.
#define YH_KEY_LEN
Length of authentication keys.
#define YH_CAPABILITIES_LEN
Length of capabilities array.
#define YH_MAX_LOG_ENTRIES
Max log entries the device may hold.
@ YHR_DEVICE_INSUFFICIENT_PERMISSIONS
Return value when the permissions to perform the operation are wrong.
@ YHR_DEVICE_INVALID_SESSION
Returned value when the device session is invalid.
@ YHR_GENERIC_ERROR
Return value when encountering an unknown error.
@ YHR_SUCCESS
Returned value when function was successful.
@ YHR_DEVICE_COMMAND_UNEXECUTED
Return value when the command execution has not terminated.
@ YHR_INVALID_PARAMETERS
Returned value when an argument to a function is invalid.
@ YHR_MEMORY_ERROR
Returned value when unable to allocate memory.
@ YHR_DEVICE_INVALID_COMMAND
Returned value when the device receives and invalid command.
@ YHR_DEVICE_SESSIONS_FULL
Return value when no more sessions can be opened on the device.
@ YHR_DEVICE_SESSION_FAILED
Return value when failing to create a device session.
@ YHR_DEVICE_OBJECT_NOT_FOUND
Return value when the object not found on the device.
@ YHR_DEVICE_AUTHENTICATION_FAILED
Return value when the device fails to encrypt or verify the message.
@ YHR_DEVICE_LOG_FULL
Return value when the log buffer is full and forced audit is set.
@ YHR_DEVICE_INVALID_OTP
Return value when an invalid OTP is submitted.
@ YHR_DEVICE_DEMO_MODE
Return value when the device is in demo mode and has to be power cycled.
@ YHR_DEVICE_INVALID_DATA
Returned value when the device receives a malformed command invalid data.
@ YHR_DEVICE_STORAGE_FAILED
Return value when encountering a storage failure on the device.
@ YHR_DEVICE_OBJECT_EXISTS
Return value when trying to add an object with an ID that already exists.
@ YHR_BUFFER_TOO_SMALL
Returned value when there is not enough space to store data.
@ YHR_MAC_MISMATCH
Returned value when failing to verify MAC.
@ YHR_DEVICE_WRONG_LENGTH
@ YHR_CONNECTION_ERROR
Returned value when a connection error was encountered.
@ YHR_DEVICE_SSH_CA_CONSTRAINT_VIOLATION
Return value when encountering SSH CA constraint violation.
@ YHR_DEVICE_OK
Returned value when the device returned no error.
@ YHR_DEVICE_INVALID_ID
Return value when an invalid Object ID is used.
@ YHR_SESSION_AUTHENTICATION_FAILED
Returned value when failing to authenticate the session.
@ YHR_CRYPTOGRAM_MISMATCH
Returned value when failing to verify cryptogram.
#define YH_MAX_DOMAINS
Max number of domains.
#define YH_CONTEXT_LEN
Length of context array for authentication.
struct backend_functions * backend_functions(void)
yh_capabilities capabilities
yh_object_type target_type
session operation op find n_objects
yh_object_descriptor object
session operation op sign key_len
memset(pInfo->slotDescription, ' ', 64)
memcpy((char *) pInfo->slotDescription, s, l)
yh_capabilities delegated_capabilities