26#include <openssl/aes.h>
27#include <openssl/evp.h>
31#ifndef DEFAULT_CONNECTOR_URL
32#define DEFAULT_CONNECTOR_URL "http://127.0.0.1:12345"
38 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f};
51 {{
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
52 "\x01\x02\x03\x04\x05\x06", 0x0001, 0x0001, 0x01, 0x01, 0x0000, 0xfe36,
53 "\x2f\x5d\x71\xa4\x91\x5d\xec\x30\x4a\xa1\x3c\xcf\x97\xbb\x0d\xbb"},
54 {
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
55 "\x01\x02\x03\x04\x05\x06", 0x0001, 0x0001, 0x01, 0x02, 0x0000, 0x1152,
56 "\xcb\x71\x0b\x46\x2b\x7b\x1c\x23\x10\x0c\xb2\x46\x85\xb6\x4d\x33"},
57 {
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
58 "\x01\x02\x03\x04\x05\x06", 0x0fff, 0x0001, 0x01, 0x01, 0x0000, 0x9454,
59 "\x77\x99\x78\x12\x9b\xcc\x26\x42\xc8\xad\xf5\xc1\x99\x81\xa0\x16"},
60 {
"\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88",
61 "\x88\x88\x88\x88\x88\x88", 0x8888, 0x8888, 0x88, 0x88, 0x8888, 0xd3b6,
62 "\x20\x76\x5f\xc6\x83\xe0\xfc\x7b\x62\x42\x21\x86\x48\x4d\x82\x37"},
63 {
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
64 "\x00\x00\x00\x00\x00\x00", 0x0000, 0x0000, 0x00, 0x00, 0x0000, 0xa96a,
65 "\x99\x9b\x08\xbf\x0b\x3b\x98\xf8\x5b\x08\x76\xa8\x77\x15\x16\x16"},
66 {
"\xc4\x42\x28\x90\x65\x30\x76\xcd\xe7\x3d\x44\x9b\x19\x1b\x41\x6a",
67 "\x33\xc6\x9e\x7f\x24\x9e", 0x0001, 0x13a7, 0x24, 0x00, 0xc63c, 0x1c86,
68 "\x7e\x0f\xc9\x87\x35\x16\x72\xc0\x70\xfa\x5c\x05\x95\xec\x68\xb8"}};
76 for (i = 0; i < 8; i++) {
95 const char *connector_url;
97 connector_url = getenv(
"DEFAULT_CONNECTOR_URL");
98 if (connector_url == NULL) {
112 sizeof(password),
false, &
session);
122 printf(
"Successfully established session %02d\n", session_id);
138 printf(
"Generated OTP key with ID %04x\n",
key_id);
148 for (
size_t i = 0; i <
sizeof(test_vectors) /
sizeof(test_vectors[0]); i++) {
150 size_t aead_len =
sizeof(aead);
152 test_vectors[i].
id, aead, &aead_len);
160 printf(
"Checking test vector %zu ... ", i);
175 printf(
"Put OTP key with ID %04x\n",
key_id);
178 size_t otp_data_len =
sizeof(otp_data);
180 size_t nonce_len = 13;
187 EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
190 assert(EVP_DecryptInit_ex(ctx, EVP_aes_128_ccm(), NULL, NULL, NULL) == 1);
193 assert(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, nonce_len, NULL) ==
197 assert(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag_len,
198 otp_data + otp_data_len - tag_len) == 1);
201 memcpy(nonce, &nonce_id, 4);
202 memcpy(nonce + 4, otp_data, 6);
203 assert(EVP_DecryptInit_ex(ctx, NULL, NULL,
otp_key, nonce) == 1);
206 assert(EVP_DecryptUpdate(ctx, out_buf, &
out_len, otp_data + 6,
207 otp_data_len - 6 - tag_len) == 1);
209 EVP_CIPHER_CTX_free(ctx);
224 } token = {.raw = {0}};
228 memcpy(token.id, out_buf + 16, 6);
229 token.use_counter = 0xabcd;
230 token.timestamp_low = 0xdcba;
231 token.timestamp_high = 0xff;
232 token.session_counter = 0x00;
233 token.crc = ~yubikey_crc16(token.raw, 14);
236 AES_set_encrypt_key(out_buf, 128, &k);
237 AES_ecb_encrypt(token.raw,
otp, &k, AES_ENCRYPT);
CK_SESSION_HANDLE session
Capabilities representation.
uint16_t yubikey_crc16(const uint8_t *buf, size_t buf_size)
#define DEFAULT_CONNECTOR_URL
yh_rc yh_destroy_session(yh_session **session)
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_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_randomize_otp_aead(yh_session *session, uint16_t key_id, uint8_t *out, size_t *out_len)
yh_rc yh_util_close_session(yh_session *session)
yh_rc yh_authenticate_session(yh_session *session)
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_init_connector(const char *url, yh_connector **connector)
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_connect(yh_connector *connector, int timeout)
yh_rc yh_string_to_capabilities(const char *capability, yh_capabilities *result)
yh_rc yh_disconnect(yh_connector *connector)
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_delete_object(yh_session *session, uint16_t id, yh_object_type type)
yh_rc yh_get_session_id(yh_session *session, uint8_t *sid)
@ YH_OTP_AEAD_KEY
OTP AEAD Key is a secret key used to decrypt Yubico OTP values.
@ YH_ALGO_AES128_YUBICO_OTP
aes128-yubico-otp
@ YHR_GENERIC_ERROR
Return value when encountering an unknown error.
@ YHR_SUCCESS
Returned value when function was successful.
yh_capabilities capabilities
memcpy((char *) pInfo->slotDescription, s, l)