1 /* -*- mode:C; c-file-style: "bsd" -*- */
3 * Copyright (c) 2008-2014 Yubico AB
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "ykpers_lcl.h"
34 #include "ykpers-json.h"
45 static const YK_CONFIG default_config1 = {
46 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* fixed */
47 { 0, 0, 0, 0, 0, 0 }, /* uid */
48 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* key */
49 { 0, 0, 0, 0, 0, 0 }, /* accCode */
52 TKTFLAG_APPEND_CR, /* tktFlags */
58 static const YK_CONFIG default_config2 = {
59 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* fixed */
60 { 0, 0, 0, 0, 0, 0 }, /* uid */
61 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* key */
62 { 0, 0, 0, 0, 0, 0 }, /* accCode */
65 TKTFLAG_APPEND_CR, /* tktFlags */
67 CFGFLAG_STATIC_TICKET | CFGFLAG_STRONG_PW1 | CFGFLAG_STRONG_PW2 | CFGFLAG_MAN_UPDATE,
72 /* From nfcforum-ts-rtd-uri-1.0.pdf */
73 static const char *ndef_identifiers[] = {
80 "ftp://anonymous:anonymous@",
111 YKP_CONFIG *ykp_create_config(void)
113 YKP_CONFIG *cfg = malloc(sizeof(YKP_CONFIG));
115 memcpy(&cfg->ykcore_config, &default_config1,
116 sizeof(default_config1));
117 cfg->yk_major_version = 1;
118 cfg->yk_minor_version = 3;
119 cfg->yk_build_version = 0;
120 cfg->command = SLOT_CONFIG;
126 YKP_CONFIG *ykp_alloc(void)
128 YKP_CONFIG *cfg = malloc(sizeof(YKP_CONFIG));
130 memset(cfg, 0, sizeof(YKP_CONFIG));
136 int ykp_free_config(YKP_CONFIG *cfg)
145 int ykp_clear_config(YKP_CONFIG *cfg)
148 cfg->ykcore_config.tktFlags = 0;
149 cfg->ykcore_config.cfgFlags = 0;
150 cfg->ykcore_config.extFlags = 0;
156 void ykp_configure_version(YKP_CONFIG *cfg, YK_STATUS *st)
158 cfg->yk_major_version = st->versionMajor;
159 cfg->yk_minor_version = st->versionMinor;
160 cfg->yk_build_version = st->versionBuild;
163 int ykp_configure_command(YKP_CONFIG *cfg, uint8_t command)
169 if (!cfg->yk_major_version >= 2) {
170 ykp_errno = YKP_EOLDYUBIKEY;
173 /* The NEO Beta key is versioned from 2.1.4 but doesn't support slot2 */
174 else if( cfg->yk_major_version == 2 && cfg->yk_minor_version == 1 &&
175 cfg->yk_build_version >= 4) {
176 ykp_errno = YKP_EYUBIKEYVER;
183 if (!((cfg->yk_major_version == 2 && cfg->yk_minor_version >= 3)
184 || cfg->yk_major_version > 2)) {
185 ykp_errno = YKP_EOLDYUBIKEY;
189 case SLOT_DEVICE_CONFIG:
192 if(!(cfg->yk_major_version >= 3)) {
193 ykp_errno = YKP_EYUBIKEYVER;
198 /* NDEF is available for neo, thus within 2.1 from build 4 */
199 if (!((cfg->yk_major_version == 2 && cfg->yk_minor_version == 1 &&
200 cfg->yk_build_version >= 4) || cfg->yk_major_version == 3)) {
201 ykp_errno = YKP_EYUBIKEYVER;
206 ykp_errno = YKP_EINVCONFNUM;
209 cfg->command = command;
213 int ykp_configure_for(YKP_CONFIG *cfg, int confnum, YK_STATUS *st)
215 ykp_configure_version(cfg, st);
218 memcpy(&cfg->ykcore_config, &default_config1,
219 sizeof(default_config1));
220 return ykp_configure_command(cfg, SLOT_CONFIG);
222 memcpy(&cfg->ykcore_config, &default_config2,
223 sizeof(default_config2));
224 return ykp_configure_command(cfg, SLOT_CONFIG2);
226 ykp_errno = YKP_EINVCONFNUM;
231 /* Return number of bytes of key data for this configuration.
232 * 20 bytes is 160 bits, 16 bytes is 128.
234 int ykp_get_supported_key_length(const YKP_CONFIG *cfg)
236 /* OATH-HOTP and HMAC-SHA1 challenge response support 20 byte (160 bits)
237 * keys, holding the last four bytes in the uid field.
239 if((ykp_get_tktflag_OATH_HOTP(cfg) &&
240 !ykp_get_cfgflag_CHAL_YUBICO(cfg)) ||
241 (ykp_get_tktflag_CHAL_RESP(cfg) &&
242 ykp_get_cfgflag_CHAL_HMAC(cfg))) {
249 /* Decode 128 bit AES key into cfg->ykcore_config.key */
250 int ykp_AES_key_from_hex(YKP_CONFIG *cfg, const char *hexkey) {
253 /* Make sure that the hexkey is exactly 32 characters */
254 if (strlen(hexkey) != 32) {
255 ykp_errno = YKP_EINVAL;
256 return 1; /* Bad AES key */
259 /* Make sure that the hexkey is made up of only [0-9a-f] */
260 if (! yubikey_hex_p(hexkey)) {
261 ykp_errno = YKP_EINVAL;
265 yubikey_hex_decode(aesbin, hexkey, sizeof(aesbin));
266 memcpy(cfg->ykcore_config.key, aesbin, sizeof(cfg->ykcore_config.key));
271 /* Store a 16 byte AES key.
273 * copy 16 bytes from key to cfg->ykcore_config.key
275 int ykp_AES_key_from_raw(YKP_CONFIG *cfg, const char *key) {
276 memcpy(cfg->ykcore_config.key, key, sizeof(cfg->ykcore_config.key));
280 /* Store a 20 byte HMAC key.
282 * store the first 16 bytes of key in cfg->ykcore_config.key
283 * and the remaining 4 bytes in cfg->ykcore_config.uid
285 int ykp_HMAC_key_from_raw(YKP_CONFIG *cfg, const char *key) {
286 size_t size = sizeof(cfg->ykcore_config.key);
287 memcpy(cfg->ykcore_config.key, key, size);
288 memcpy(cfg->ykcore_config.uid, key + size, 20 - size);
292 /* Decode 160 bits HMAC key, used with OATH and HMAC challenge-response.
294 * The first 128 bits of the HMAC go key into cfg->ykcore_config.key,
295 * and 32 bits into the first four bytes of cfg->ykcore_config.uid.
297 int ykp_HMAC_key_from_hex(YKP_CONFIG *cfg, const char *hexkey) {
301 /* Make sure that the hexkey is exactly 40 characters */
302 if (strlen(hexkey) != 40) {
303 ykp_errno = YKP_EINVAL;
304 return 1; /* Bad HMAC key */
307 /* Make sure that the hexkey is made up of only [0-9a-f] */
308 if (! yubikey_hex_p(hexkey)) {
309 ykp_errno = YKP_EINVAL;
313 yubikey_hex_decode(aesbin, hexkey, sizeof(aesbin));
314 i = sizeof(cfg->ykcore_config.key);
315 memcpy(cfg->ykcore_config.key, aesbin, i);
316 memcpy(cfg->ykcore_config.uid, aesbin + i, 20 - i);
321 /* Generate an AES (128 bits) or HMAC (despite the function name) (160 bits)
322 * key from user entered input.
324 * Use user provided salt, or use salt from an available random device.
325 * If no random device is available we return with an error.
327 int ykp_AES_key_from_passphrase(YKP_CONFIG *cfg, const char *passphrase,
331 const char *random_places[] = {
337 const char **random_place;
339 size_t _salt_len = 0;
340 unsigned char buf[sizeof(cfg->ykcore_config.key) + 4];
342 int key_bytes = ykp_get_supported_key_length(cfg);
343 YK_PRF_METHOD prf_method = {20, yk_hmac_sha1};
345 assert (key_bytes <= sizeof(buf));
348 _salt_len = strlen(salt);
351 memcpy(_salt, salt, _salt_len);
353 for (random_place = random_places;
356 FILE *random_file = fopen(*random_place, "r");
358 size_t read_bytes = 0;
360 while (read_bytes < sizeof(_salt)) {
361 size_t n = fread(&_salt[read_bytes],
362 1, sizeof (_salt) - read_bytes,
369 _salt_len = sizeof(_salt);
371 break; /* from for loop */
375 if (_salt_len == 0) {
376 /* There was no randomness files, so don't do
378 ykp_errno = YKP_ENORANDOM;
382 rc = yk_pbkdf2(passphrase,
389 memcpy(cfg->ykcore_config.key, buf, sizeof(cfg->ykcore_config.key));
391 if (key_bytes == 20) {
392 memcpy(cfg->ykcore_config.uid, buf + sizeof(cfg->ykcore_config.key), 4);
396 memset (buf, 0, sizeof(buf));
402 YK_NDEF *ykp_alloc_ndef(void)
404 YK_NDEF *ndef = malloc(sizeof(YK_NDEF));
406 memset(ndef, 0, sizeof(YK_NDEF));
412 int ykp_free_ndef(YK_NDEF *ndef)
422 /* Fill in the data and len parts of the YK_NDEF struct based on supplied uri. */
423 int ykp_construct_ndef_uri(YK_NDEF *ndef, const char *uri)
425 int num_identifiers = sizeof(ndef_identifiers) / sizeof(char*);
428 for(; indx < num_identifiers; indx++) {
429 size_t len = strlen(ndef_identifiers[indx]);
430 if(strncmp(uri, ndef_identifiers[indx], len) == 0) {
435 data_length = strlen(uri);
436 if(data_length + 1 > NDEF_DATA_SIZE) {
437 ykp_errno = YKP_EINVAL;
440 if(indx == num_identifiers) {
443 ndef->data[0] = indx + 1;
445 memcpy(ndef->data + 1, uri, data_length);
446 ndef->len = data_length + 1;
451 /* Fill in the data and len parts of the YK_NDEF struct based on supplied text. */
452 int ykp_construct_ndef_text(YK_NDEF *ndef, const char *text, const char *lang, bool isutf16)
454 size_t data_length = strlen(text);
455 size_t lang_length = strlen(lang);
456 unsigned char status = lang_length;
460 if((data_length + lang_length + 1) > NDEF_DATA_SIZE) {
461 ykp_errno = YKP_EINVAL;
464 ndef->data[0] = status;
465 memcpy(ndef->data + 1, lang, lang_length);
466 memcpy(ndef->data + lang_length + 1, text, data_length);
467 ndef->len = data_length + lang_length + 1;
472 int ykp_ndef_as_text(YK_NDEF *ndef, char *text, size_t len)
474 if(ndef->type == 'U') {
475 const char *part = NULL;
477 if(ndef->data[0] > 0) {
478 part = ndef_identifiers[ndef->data[0] - 1];
479 offset = strlen(part);
481 if(offset + ndef->len - 1 > len) {
482 ykp_errno = YKP_EINVAL;
486 memcpy(text, part, offset);
488 memcpy(text + offset, ndef->data + 1, ndef->len - 1);
489 text[ndef->len + offset] = 0;
492 else if(ndef->type == 'T') {
493 unsigned char status = ndef->data[0];
496 if(ndef->len - status - 1 > len) {
497 ykp_errno = YKP_EINVAL;
500 memcpy(text, ndef->data + status + 1, ndef->len - status - 1);
501 text[ndef->len - status] = 0;
509 int ykp_set_ndef_access_code(YK_NDEF *ndef, unsigned char *access_code)
513 memcpy(ndef->curAccCode, access_code, ACC_CODE_SIZE);
519 YK_DEVICE_CONFIG *ykp_alloc_device_config(void)
521 YK_DEVICE_CONFIG *cfg = malloc(sizeof(YK_DEVICE_CONFIG));
523 memset(cfg, 0, sizeof(YK_DEVICE_CONFIG));
529 int ykp_free_device_config(YK_DEVICE_CONFIG *device_config)
538 int ykp_set_device_mode(YK_DEVICE_CONFIG *device_config, unsigned char mode)
541 device_config->mode = mode;
544 ykp_errno = YKP_EINVAL;
548 int ykp_set_device_chalresp_timeout(YK_DEVICE_CONFIG *device_config, unsigned char timeout)
551 device_config->crTimeout = timeout;
554 ykp_errno = YKP_EINVAL;
558 int ykp_set_device_autoeject_time(YK_DEVICE_CONFIG *device_config, unsigned short eject_time)
561 device_config->autoEjectTime = eject_time;
564 ykp_errno = YKP_EINVAL;
568 static bool vcheck_all(const YKP_CONFIG *cfg)
572 static bool vcheck_v1(const YKP_CONFIG *cfg)
574 return cfg->yk_major_version == 1;
576 static bool vcheck_no_v1(const YKP_CONFIG *cfg)
578 return cfg->yk_major_version > 1;
581 static bool vcheck_v21_or_greater(const YKP_CONFIG *cfg)
583 /* the NEO Beta is versioned from 2.1.4 but shouldn't be identified as a 2.1 above key */
584 return (cfg->yk_major_version == 2 && cfg->yk_minor_version > 1) ||
585 (cfg->yk_major_version == 2 && cfg->yk_minor_version == 1 && cfg->yk_build_version <= 3)
586 || cfg->yk_major_version > 2;
589 static bool vcheck_v22_or_greater(const YKP_CONFIG *cfg)
591 return (cfg->yk_major_version == 2 &&
592 cfg->yk_minor_version >= 2) ||
593 cfg->yk_major_version > 2;
596 static bool vcheck_v23_or_greater(const YKP_CONFIG *cfg)
598 return (cfg->yk_major_version == 2 &&
599 cfg->yk_minor_version >= 3) ||
600 cfg->yk_major_version > 2;
603 static bool vcheck_v24_or_greater(const YKP_CONFIG *cfg)
605 return (cfg->yk_major_version == 2 &&
606 cfg->yk_minor_version >= 4) ||
607 cfg->yk_major_version > 2;
610 static bool vcheck_v30(const YKP_CONFIG *cfg)
612 return (cfg->yk_major_version == 3 &&
613 cfg->yk_minor_version == 0);
616 static bool vcheck_neo(const YKP_CONFIG *cfg)
618 return (cfg->yk_major_version == 2 &&
619 cfg->yk_minor_version == 1 &&
620 cfg->yk_build_version >= 4);
624 static bool vcheck_neo_before_5(const YKP_CONFIG *cfg)
626 return vcheck_neo(cfg) && cfg->yk_build_version < 5;
629 static bool vcheck_neo_after_6(const YKP_CONFIG *cfg)
631 return vcheck_neo(cfg) && cfg->yk_build_version > 6;
634 bool capability_has_hidtrig(const YKP_CONFIG *cfg)
636 return vcheck_v1(cfg);
639 bool capability_has_ticket_first(const YKP_CONFIG *cfg)
641 return vcheck_v1(cfg);
644 bool capability_has_static(const YKP_CONFIG *cfg)
646 return vcheck_all(cfg) && !vcheck_neo_before_5(cfg);
649 bool capability_has_static_extras(const YKP_CONFIG *cfg)
651 return vcheck_no_v1(cfg) && !vcheck_neo_before_5(cfg);
654 bool capability_has_slot_two(const YKP_CONFIG *cfg)
656 return vcheck_no_v1(cfg) && !vcheck_neo(cfg);
659 bool capability_has_chal_resp(const YKP_CONFIG *cfg)
661 return vcheck_v22_or_greater(cfg);
664 bool capability_has_oath_imf(const YKP_CONFIG *cfg)
666 return vcheck_v22_or_greater(cfg) || vcheck_neo_after_6(cfg);
669 bool capability_has_serial_api(const YKP_CONFIG *cfg)
671 return vcheck_v22_or_greater(cfg) || vcheck_neo(cfg);
674 bool capability_has_serial(const YKP_CONFIG *cfg)
676 return vcheck_v22_or_greater(cfg);
679 bool capability_has_oath(const YKP_CONFIG *cfg)
681 return vcheck_v21_or_greater(cfg) || vcheck_neo(cfg);
684 bool capability_has_ticket_mods(const YKP_CONFIG *cfg)
686 return vcheck_all(cfg);
689 bool capability_has_update(const YKP_CONFIG *cfg)
691 return vcheck_v23_or_greater(cfg);
694 bool capability_has_fast(const YKP_CONFIG *cfg)
696 return vcheck_v23_or_greater(cfg);
699 bool capability_has_numeric(const YKP_CONFIG *cfg)
701 return vcheck_v23_or_greater(cfg);
704 bool capability_has_dormant(const YKP_CONFIG *cfg)
706 return vcheck_v23_or_greater(cfg);
709 bool capability_has_led_inv(const YKP_CONFIG *cfg)
711 return (vcheck_v24_or_greater(cfg) && !vcheck_v30(cfg));
714 int ykp_set_oath_imf(YKP_CONFIG *cfg, unsigned long imf)
716 if (!capability_has_oath_imf(cfg)) {
717 ykp_errno = YKP_EYUBIKEYVER;
720 if (imf > 65535*16) {
721 ykp_errno = YKP_EINVAL;
725 ykp_errno = YKP_EINVAL;
728 /* IMF/16 is 16 bits stored big-endian in uid[4] */
730 cfg->ykcore_config.uid[4] = imf >> 8;
731 cfg->ykcore_config.uid[5] = imf;
735 unsigned long ykp_get_oath_imf(const YKP_CONFIG *cfg)
737 if (!capability_has_oath_imf(cfg)) {
741 /* we can't do a simple cast due to alignment issues */
742 return ((cfg->ykcore_config.uid[4] << 8)
743 | cfg->ykcore_config.uid[5]) << 4;
746 #define def_set_charfield(fnname,fieldname,size,extra,capability) \
747 int ykp_set_ ## fnname(YKP_CONFIG *cfg, unsigned char *input, size_t len) \
750 size_t max_chars = len; \
752 if (!capability(cfg)) { \
753 ykp_errno = YKP_EYUBIKEYVER; \
756 if (max_chars > (size)) \
757 max_chars = (size); \
759 memcpy(cfg->ykcore_config.fieldname, (input), max_chars); \
760 memset(cfg->ykcore_config.fieldname + max_chars, 0, \
761 (size) - max_chars); \
766 ykp_errno = YKP_ENOCFG; \
770 def_set_charfield(access_code,accCode,ACC_CODE_SIZE,,vcheck_all)
771 def_set_charfield(fixed,fixed,FIXED_SIZE,cfg->ykcore_config.fixedSize = max_chars,vcheck_all)
772 def_set_charfield(uid,uid,UID_SIZE,,vcheck_all)
774 #define def_set_tktflag(type,capability) \
775 int ykp_set_tktflag_ ## type(YKP_CONFIG *cfg, bool state) \
778 if (!capability(cfg)) { \
779 ykp_errno = YKP_EYUBIKEYVER; \
783 cfg->ykcore_config.tktFlags |= TKTFLAG_ ## type; \
785 cfg->ykcore_config.tktFlags &= ~TKTFLAG_ ## type; \
788 ykp_errno = YKP_ENOCFG; \
791 bool ykp_get_tktflag_ ## type(const YKP_CONFIG *cfg) \
794 if((cfg->ykcore_config.tktFlags & TKTFLAG_ ## type) == TKTFLAG_ ## type) \
804 #define def_set_cfgflag(type,capability) \
805 int ykp_set_cfgflag_ ## type(YKP_CONFIG *cfg, bool state) \
808 if (!capability(cfg)) { \
809 ykp_errno = YKP_EYUBIKEYVER; \
813 cfg->ykcore_config.cfgFlags |= CFGFLAG_ ## type; \
815 cfg->ykcore_config.cfgFlags &= ~CFGFLAG_ ## type; \
818 ykp_errno = YKP_ENOCFG; \
821 bool ykp_get_cfgflag_ ## type(const YKP_CONFIG *cfg) \
824 if((cfg->ykcore_config.cfgFlags & CFGFLAG_ ## type) == CFGFLAG_ ## type) \
833 #define def_set_extflag(type,capability) \
834 int ykp_set_extflag_ ## type(YKP_CONFIG *cfg, bool state) \
837 if (!capability(cfg)) { \
838 ykp_errno = YKP_EYUBIKEYVER; \
842 cfg->ykcore_config.extFlags |= EXTFLAG_ ## type; \
844 cfg->ykcore_config.extFlags &= ~EXTFLAG_ ## type; \
847 ykp_errno = YKP_ENOCFG; \
850 bool ykp_get_extflag_ ## type(const YKP_CONFIG *cfg) \
853 if((cfg->ykcore_config.extFlags & EXTFLAG_ ## type) == EXTFLAG_ ## type) \
861 def_set_tktflag(TAB_FIRST,capability_has_ticket_mods)
862 def_set_tktflag(APPEND_TAB1,capability_has_ticket_mods)
863 def_set_tktflag(APPEND_TAB2,capability_has_ticket_mods)
864 def_set_tktflag(APPEND_DELAY1,capability_has_ticket_mods)
865 def_set_tktflag(APPEND_DELAY2,capability_has_ticket_mods)
866 def_set_tktflag(APPEND_CR,capability_has_ticket_mods)
867 def_set_tktflag(PROTECT_CFG2,capability_has_slot_two)
868 def_set_tktflag(OATH_HOTP,capability_has_oath)
869 def_set_tktflag(CHAL_RESP,capability_has_chal_resp)
871 def_set_cfgflag(SEND_REF,capability_has_ticket_mods)
872 def_set_cfgflag(TICKET_FIRST,capability_has_ticket_first)
873 def_set_cfgflag(PACING_10MS,capability_has_ticket_mods)
874 def_set_cfgflag(PACING_20MS,capability_has_ticket_mods)
875 def_set_cfgflag(ALLOW_HIDTRIG,capability_has_hidtrig)
876 def_set_cfgflag(STATIC_TICKET,capability_has_static)
877 def_set_cfgflag(SHORT_TICKET,capability_has_static_extras)
878 def_set_cfgflag(STRONG_PW1,capability_has_static_extras)
879 def_set_cfgflag(STRONG_PW2,capability_has_static_extras)
880 def_set_cfgflag(MAN_UPDATE,capability_has_static_extras)
881 def_set_cfgflag(OATH_HOTP8,capability_has_oath)
882 def_set_cfgflag(OATH_FIXED_MODHEX1,capability_has_oath)
883 def_set_cfgflag(OATH_FIXED_MODHEX2,capability_has_oath)
884 def_set_cfgflag(OATH_FIXED_MODHEX,capability_has_oath)
885 def_set_cfgflag(CHAL_YUBICO,capability_has_chal_resp)
886 def_set_cfgflag(CHAL_HMAC,capability_has_chal_resp)
887 def_set_cfgflag(HMAC_LT64,capability_has_chal_resp)
888 def_set_cfgflag(CHAL_BTN_TRIG,capability_has_chal_resp)
890 def_set_extflag(SERIAL_BTN_VISIBLE,capability_has_serial)
891 def_set_extflag(SERIAL_USB_VISIBLE,capability_has_serial)
892 def_set_extflag(SERIAL_API_VISIBLE,capability_has_serial_api)
893 def_set_extflag(USE_NUMERIC_KEYPAD,capability_has_numeric)
894 def_set_extflag(FAST_TRIG,capability_has_fast)
895 def_set_extflag(ALLOW_UPDATE,capability_has_update)
896 def_set_extflag(DORMANT,capability_has_dormant)
897 def_set_extflag(LED_INV,capability_has_led_inv)
899 static const char str_key_value_separator[] = ": ";
900 static const char str_hex_prefix[] = "h:";
901 static const char str_modhex_prefix[] = "m:";
902 static const char str_fixed[] = "fixed";
903 static const char str_oath_id[] = "OATH id";
904 static const char str_uid[] = "uid";
905 static const char str_key[] = "key";
906 static const char str_acc_code[] = "acc_code";
907 static const char str_oath_imf[] = "OATH IMF";
909 static const char str_flags_separator[] = "|";
911 static const char str_ticket_flags[] = "ticket_flags";
912 static const char str_config_flags[] = "config_flags";
913 static const char str_extended_flags[] = "extended_flags";
916 static int _ykp_legacy_export_config(const YKP_CONFIG *cfg, char *buf, size_t len) {
920 unsigned char t_flags;
921 bool key_bits_in_uid = false;
922 YK_CONFIG ycfg = cfg->ykcore_config;
923 int mode = MODE_OTP_YUBICO;
927 if((ycfg.tktFlags & TKTFLAG_OATH_HOTP) == TKTFLAG_OATH_HOTP){
928 if((ycfg.cfgFlags & CFGFLAG_CHAL_HMAC) == CFGFLAG_CHAL_HMAC) {
929 mode = MODE_CHAL_HMAC;
930 } else if((ycfg.cfgFlags & CFGFLAG_CHAL_YUBICO) == CFGFLAG_CHAL_YUBICO) {
931 mode = MODE_CHAL_YUBICO;
933 mode = MODE_OATH_HOTP;
936 else if((ycfg.cfgFlags & CFGFLAG_STATIC_TICKET) == CFGFLAG_STATIC_TICKET) {
937 mode = MODE_STATIC_TICKET;
940 /* for OATH-HOTP and HMAC-SHA1 challenge response, there is four bytes
941 * additional key data in the uid field
943 key_bits_in_uid = (ykp_get_supported_key_length(cfg) == 20);
945 /* fixed: or OATH id: */
946 if ((ycfg.tktFlags & TKTFLAG_OATH_HOTP) == TKTFLAG_OATH_HOTP &&
948 /* First byte (vendor id) */
949 if ((ycfg.cfgFlags & CFGFLAG_OATH_FIXED_MODHEX1) == CFGFLAG_OATH_FIXED_MODHEX1 ||
950 (ycfg.cfgFlags & CFGFLAG_OATH_FIXED_MODHEX2) == CFGFLAG_OATH_FIXED_MODHEX2 ||
951 (ycfg.cfgFlags & CFGFLAG_OATH_FIXED_MODHEX) == CFGFLAG_OATH_FIXED_MODHEX) {
952 yubikey_modhex_encode(buffer, (const char *)ycfg.fixed, 1);
954 yubikey_hex_encode(buffer, (const char *)ycfg.fixed, 1);
956 /* Second byte (token type) */
957 if ((ycfg.cfgFlags & CFGFLAG_OATH_FIXED_MODHEX2) == CFGFLAG_OATH_FIXED_MODHEX2 ||
958 (ycfg.cfgFlags & CFGFLAG_OATH_FIXED_MODHEX) == CFGFLAG_OATH_FIXED_MODHEX) {
959 yubikey_modhex_encode(buffer + 2, (const char *)ycfg.fixed + 1, 1);
961 yubikey_hex_encode(buffer + 2, (const char *)ycfg.fixed + 1, 1);
963 /* bytes 3-12 - MUI */
964 if ((ycfg.cfgFlags & CFGFLAG_OATH_FIXED_MODHEX) == CFGFLAG_OATH_FIXED_MODHEX) {
965 yubikey_modhex_encode(buffer + 4, (const char *)ycfg.fixed + 2, 8);
967 yubikey_hex_encode(buffer + 4, (const char *)ycfg.fixed + 2, 8);
970 pos += snprintf(buf, len - (size_t)pos, "%s%s%s\n", str_oath_id, str_key_value_separator, buffer);
972 yubikey_modhex_encode(buffer, (const char *)ycfg.fixed, ycfg.fixedSize);
973 pos += snprintf(buf, len - (size_t)pos, "%s%s%s%s\n", str_fixed, str_key_value_separator, str_modhex_prefix, buffer);
977 if (key_bits_in_uid) {
978 strncpy(buffer, "n/a", 3);
980 yubikey_hex_encode(buffer, (const char *)ycfg.uid, UID_SIZE);
982 pos += snprintf(buf + pos, len - (size_t)pos, "%s%s%s\n", str_uid, str_key_value_separator, buffer);
985 yubikey_hex_encode(buffer, (const char *)ycfg.key, KEY_SIZE);
986 if (key_bits_in_uid) {
987 yubikey_hex_encode(buffer + KEY_SIZE * 2, (const char *)ycfg.uid, 4);
989 pos += snprintf(buf + pos, len - (size_t)pos, "%s%s%s%s\n", str_key, str_key_value_separator, str_hex_prefix, buffer);
992 yubikey_hex_encode(buffer, (const char*)ycfg.accCode, ACC_CODE_SIZE);
993 pos += snprintf(buf + pos, len - (size_t)pos, "%s%s%s%s\n", str_acc_code, str_key_value_separator, str_hex_prefix, buffer);
996 if ((ycfg.tktFlags & TKTFLAG_OATH_HOTP) == TKTFLAG_OATH_HOTP &&
997 capability_has_oath_imf(cfg)) {
998 pos += snprintf(buf + pos, len - (size_t)pos, "%s%s%s%lx\n", str_oath_imf, str_key_value_separator, str_hex_prefix, ykp_get_oath_imf(cfg));
1003 for (p = _ticket_flags_map; p->flag; p++) {
1004 if ((ycfg.tktFlags & p->flag) == p->flag
1005 && p->capability(cfg)
1006 && (mode & p->mode) == mode) {
1008 strncat(buffer, str_flags_separator, 256 - strlen(buffer));
1010 strncat(buffer, p->flag_text, 256 - strlen(buffer));
1013 pos += snprintf(buf + pos, len - (size_t)pos, "%s%s%s\n", str_ticket_flags, str_key_value_separator, buffer);
1017 t_flags = ycfg.cfgFlags;
1018 for (p = _config_flags_map; p->flag; p++) {
1019 if ((t_flags & p->flag) == p->flag
1020 && p->capability(cfg)
1021 && (mode & p->mode) == mode) {
1023 strncat(buffer, str_flags_separator, 256 - strlen(buffer));
1025 strncat(buffer, p->flag_text, 256 - strlen(buffer));
1026 /* make sure we don't show more than one cfgFlag per value -
1027 some cfgflags share value in different contexts
1032 pos += snprintf(buf + pos, len - (size_t)pos, "%s%s%s\n", str_config_flags, str_key_value_separator, buffer);
1034 /* extended_flags: */
1036 for (p = _extended_flags_map; p->flag; p++) {
1037 if ((ycfg.extFlags & p->flag) == p->flag
1038 && p->capability(cfg)
1039 && (mode & p->mode) == mode) {
1041 strncat(buffer, str_flags_separator, 256 - strlen(buffer));
1043 strncat(buffer, p->flag_text, 256 - strlen(buffer));
1046 pos += snprintf(buf + pos, len - (size_t)pos, "%s%s%s\n", str_extended_flags, str_key_value_separator, buffer);
1053 int ykp_export_config(const YKP_CONFIG *cfg, char *buf, size_t len,
1055 if(format == YKP_FORMAT_YCFG) {
1056 return _ykp_json_export_cfg(cfg, buf, len);
1057 } else if(format == YKP_FORMAT_LEGACY) {
1058 return _ykp_legacy_export_config(cfg, buf, len);
1060 ykp_errno = YKP_EINVAL;
1065 int ykp_import_config(YKP_CONFIG *cfg, const char *buf, size_t len,
1067 if(format == YKP_FORMAT_YCFG) {
1068 return _ykp_json_import_cfg(cfg, buf, len);
1069 } else if(format == YKP_FORMAT_LEGACY) {
1070 ykp_errno = YKP_ENOTYETIMPL;
1072 ykp_errno = YKP_EINVAL;
1075 int ykp_write_config(const YKP_CONFIG *cfg,
1076 int (*writer)(const char *buf, size_t count,
1081 int ret = _ykp_legacy_export_config(cfg, buffer, 1024);
1083 writer(buffer, strlen(buffer), userdata);
1088 ykp_errno = YKP_ENOCFG;
1092 int ykp_read_config(YKP_CONFIG *cfg,
1093 int (*reader)(char *buf, size_t count,
1097 ykp_errno = YKP_ENOTYETIMPL;
1101 YK_CONFIG *ykp_core_config(YKP_CONFIG *cfg)
1104 return &cfg->ykcore_config;
1105 ykp_errno = YKP_ENOCFG;
1109 int ykp_command(YKP_CONFIG *cfg) {
1111 return cfg->command;
1113 ykp_errno = YKP_ENOCFG;
1117 int ykp_config_num(YKP_CONFIG *cfg)
1120 if (cfg->command == SLOT_CONFIG) {
1122 } else if (cfg->command == SLOT_CONFIG2) {
1126 ykp_errno = YKP_ENOCFG;
1130 void ykp_set_acccode_type(YKP_CONFIG *cfg, unsigned int type)
1132 cfg->ykp_acccode_type = type;
1135 unsigned int ykp_get_acccode_type(const YKP_CONFIG *cfg)
1137 return cfg->ykp_acccode_type;
1140 int * _ykp_errno_location(void)
1142 static int tsd_init = 0;
1143 static int nothread_errno = 0;
1144 YK_DEFINE_TSD_METADATA(errno_key);
1147 if (tsd_init == 0) {
1148 if ((rc = YK_TSD_INIT(errno_key, free)) == 0) {
1155 if(YK_TSD_GET(int *, errno_key) == NULL) {
1156 void *p = calloc(1, sizeof(int));
1160 YK_TSD_SET(errno_key, p);
1163 if (tsd_init == 1) {
1164 return YK_TSD_GET(int *, errno_key);
1166 return ¬hread_errno;
1169 static const char *errtext[] = {
1171 "not yet implemented",
1172 "no configuration structure given",
1173 "option not available for this Yubikey version",
1174 "too old yubikey for this operation",
1175 "invalid configuration number (this is a programming error)",
1176 "invalid option/argument value",
1177 "no randomness source available",
1179 const char *ykp_strerror(int errnum)
1181 if (errnum < sizeof(errtext)/sizeof(errtext[0]))
1182 return errtext[errnum];