]> err.no Git - yubikey-personalization/blob - ykpers.c
Merge tag 'v1.15.1'
[yubikey-personalization] / ykpers.c
1 /* -*- mode:C; c-file-style: "bsd" -*- */
2 /*
3  * Copyright (c) 2008-2014 Yubico AB
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *
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.
17  *
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.
29  */
30
31 #include "ykpers_lcl.h"
32 #include "ykpbkdf2.h"
33 #include "yktsd.h"
34 #include "ykpers-json.h"
35
36 #include <ykpers.h>
37
38 #include <stdio.h>
39 #include <string.h>
40 #include <ctype.h>
41 #include <assert.h>
42
43 #include <yubikey.h>
44
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 */
50         0,                      /* fixedSize */
51         0,                      /* extFlags */
52         TKTFLAG_APPEND_CR,      /* tktFlags */
53         0,                      /* cfgFlags */
54         {0},                    /* ctrOffs */
55         0                       /* crc */
56 };
57
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 */
63         0,                      /* fixedSize */
64         0,                      /* extFlags */
65         TKTFLAG_APPEND_CR,      /* tktFlags */
66         /* cfgFlags */
67         CFGFLAG_STATIC_TICKET | CFGFLAG_STRONG_PW1 | CFGFLAG_STRONG_PW2 | CFGFLAG_MAN_UPDATE,
68         {0},                    /* ctrOffs */
69         0                       /* crc */
70 };
71
72 /* From nfcforum-ts-rtd-uri-1.0.pdf */
73 static const char *ndef_identifiers[] = {
74         "http://www.",
75         "https://www.",
76         "http://",
77         "https://",
78         "tel:",
79         "mailto:",
80         "ftp://anonymous:anonymous@",
81         "ftp://ftp.",
82         "ftps://",
83         "sftp://",
84         "smb://",
85         "nfs://",
86         "ftp://",
87         "dav://",
88         "news:",
89         "telnet://",
90         "imap:",
91         "rtsp://",
92         "urn:",
93         "pop:",
94         "sip:",
95         "sips:",
96         "tftp:",
97         "btspp://",
98         "btl2cap://",
99         "btgoep://",
100         "tcpobex://",
101         "irdaobex://",
102         "file://",
103         "urn:epc:id:",
104         "urn:epc:tag:",
105         "urn:epc:pat:",
106         "urn:epc:raw:",
107         "urn:epc:",
108         "urn:nfc:"
109 };
110
111 YKP_CONFIG *ykp_create_config(void)
112 {
113         YKP_CONFIG *cfg = malloc(sizeof(YKP_CONFIG));
114         if (cfg) {
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;
121                 return cfg;
122         }
123         return 0;
124 }
125
126 YKP_CONFIG *ykp_alloc(void)
127 {
128         YKP_CONFIG *cfg = malloc(sizeof(YKP_CONFIG));
129         if(cfg) {
130                 memset(cfg, 0, sizeof(YKP_CONFIG));
131                 return cfg;
132         }
133         return 0;
134 }
135
136 int ykp_free_config(YKP_CONFIG *cfg)
137 {
138         if (cfg) {
139                 free(cfg);
140                 return 1;
141         }
142         return 0;
143 }
144
145 int ykp_clear_config(YKP_CONFIG *cfg)
146 {
147         if(cfg) {
148                 cfg->ykcore_config.tktFlags = 0;
149                 cfg->ykcore_config.cfgFlags = 0;
150                 cfg->ykcore_config.extFlags = 0;
151                 return 1;
152         }
153         return 0;
154 }
155
156 void ykp_configure_version(YKP_CONFIG *cfg, YK_STATUS *st)
157 {
158         cfg->yk_major_version = st->versionMajor;
159         cfg->yk_minor_version = st->versionMinor;
160         cfg->yk_build_version = st->versionBuild;
161 }
162
163 int ykp_configure_command(YKP_CONFIG *cfg, uint8_t command)
164 {
165         switch(command) {
166         case SLOT_CONFIG:
167                 break;
168         case SLOT_CONFIG2:
169                 if (!cfg->yk_major_version >= 2) {
170                         ykp_errno = YKP_EOLDYUBIKEY;
171                         return 0;
172                 }
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;
177                         return 0;
178                 }
179                 break;
180         case SLOT_UPDATE1:
181         case SLOT_UPDATE2:
182         case SLOT_SWAP:
183                 if (!((cfg->yk_major_version == 2 && cfg->yk_minor_version >= 3)
184                           || cfg->yk_major_version > 2)) {
185                         ykp_errno = YKP_EOLDYUBIKEY;
186                         return 0;
187                 }
188                 break;
189         case SLOT_DEVICE_CONFIG:
190         case SLOT_SCAN_MAP:
191         case SLOT_NDEF2:
192                 if(!(cfg->yk_major_version >= 3)) {
193                         ykp_errno = YKP_EYUBIKEYVER;
194                         return 0;
195                 }
196                 break;
197         case SLOT_NDEF:
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;
202                         return 0;
203                 }
204                 break;
205         default:
206                 ykp_errno = YKP_EINVCONFNUM;
207                 return 0;
208         }
209         cfg->command = command;
210         return 1;
211 }
212
213 int ykp_configure_for(YKP_CONFIG *cfg, int confnum, YK_STATUS *st)
214 {
215         ykp_configure_version(cfg, st);
216         switch(confnum) {
217         case 1:
218                 memcpy(&cfg->ykcore_config, &default_config1,
219                                 sizeof(default_config1));
220                 return ykp_configure_command(cfg, SLOT_CONFIG);
221         case 2:
222                 memcpy(&cfg->ykcore_config, &default_config2,
223                                 sizeof(default_config2));
224                 return ykp_configure_command(cfg, SLOT_CONFIG2);
225         default:
226                 ykp_errno = YKP_EINVCONFNUM;
227                 return 0;
228         }
229 }
230
231 /* Return number of bytes of key data for this configuration.
232  * 20 bytes is 160 bits, 16 bytes is 128.
233  */
234 int ykp_get_supported_key_length(const YKP_CONFIG *cfg)
235 {
236         /* OATH-HOTP and HMAC-SHA1 challenge response support 20 byte (160 bits)
237          * keys, holding the last four bytes in the uid field.
238          */
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))) {
243                 return 20;
244         }
245
246         return 16;
247 }
248
249 /* Decode 128 bit AES key into cfg->ykcore_config.key */
250 int ykp_AES_key_from_hex(YKP_CONFIG *cfg, const char *hexkey) {
251         char aesbin[256];
252
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 */
257         }
258
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;
262                 return 1;
263         }
264
265         yubikey_hex_decode(aesbin, hexkey, sizeof(aesbin));
266         memcpy(cfg->ykcore_config.key, aesbin, sizeof(cfg->ykcore_config.key));
267
268         return 0;
269 }
270
271 /* Store a 16 byte AES key.
272  *
273  * copy 16 bytes from key to cfg->ykcore_config.key
274  */
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));
277         return 0;
278 }
279
280 /* Store a 20 byte HMAC key.
281  *
282  * store the first 16 bytes of key in cfg->ykcore_config.key
283  * and the remaining 4 bytes in cfg->ykcore_config.uid
284  */
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);
289         return 0;
290 }
291
292 /* Decode 160 bits HMAC key, used with OATH and HMAC challenge-response.
293  *
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.
296 */
297 int ykp_HMAC_key_from_hex(YKP_CONFIG *cfg, const char *hexkey) {
298         char aesbin[256];
299         size_t i;
300
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 */
305         }
306
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;
310                 return 1;
311         }
312
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);
317
318         return 0;
319 }
320
321 /* Generate an AES (128 bits) or HMAC (despite the function name) (160 bits)
322  * key from user entered input.
323  *
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.
326  */
327 int ykp_AES_key_from_passphrase(YKP_CONFIG *cfg, const char *passphrase,
328                                 const char *salt)
329 {
330         if (cfg) {
331                 const char *random_places[] = {
332                         "/dev/srandom",
333                         "/dev/urandom",
334                         "/dev/random",
335                         0
336                 };
337                 const char **random_place;
338                 uint8_t _salt[8];
339                 size_t _salt_len = 0;
340                 unsigned char buf[sizeof(cfg->ykcore_config.key) + 4];
341                 int rc;
342                 int key_bytes = ykp_get_supported_key_length(cfg);
343                 YK_PRF_METHOD prf_method = {20, yk_hmac_sha1};
344
345                 assert (key_bytes <= sizeof(buf));
346
347                 if (salt) {
348                         _salt_len = strlen(salt);
349                         if (_salt_len > 8)
350                                 _salt_len = 8;
351                         memcpy(_salt, salt, _salt_len);
352                 } else {
353                         for (random_place = random_places;
354                              *random_place;
355                              random_place++) {
356                                 FILE *random_file = fopen(*random_place, "r");
357                                 if (random_file) {
358                                         size_t read_bytes = 0;
359
360                                         while (read_bytes < sizeof(_salt)) {
361                                                 size_t n = fread(&_salt[read_bytes],
362                                                                  1, sizeof (_salt) - read_bytes,
363                                                                  random_file);
364                                                 read_bytes += n;
365                                         }
366
367                                         fclose(random_file);
368
369                                         _salt_len = sizeof(_salt);
370
371                                         break; /* from for loop */
372                                 }
373                         }
374                 }
375                 if (_salt_len == 0) {
376                         /* There was no randomness files, so don't do
377                          * anything */
378                         ykp_errno = YKP_ENORANDOM;
379                         return 0;
380                 }
381
382                 rc = yk_pbkdf2(passphrase,
383                                _salt, _salt_len,
384                                1024,
385                                buf, key_bytes,
386                                &prf_method);
387
388                 if (rc) {
389                         memcpy(cfg->ykcore_config.key, buf, sizeof(cfg->ykcore_config.key));
390
391                         if (key_bytes == 20) {
392                                 memcpy(cfg->ykcore_config.uid, buf + sizeof(cfg->ykcore_config.key), 4);
393                         }
394                 }
395
396                 memset (buf, 0, sizeof(buf));
397                 return rc;
398         }
399         return 0;
400 }
401
402 YK_NDEF *ykp_alloc_ndef(void)
403 {
404         YK_NDEF *ndef = malloc(sizeof(YK_NDEF));
405         if(ndef) {
406                 memset(ndef, 0, sizeof(YK_NDEF));
407                 return ndef;
408         }
409         return 0;
410 }
411
412 int ykp_free_ndef(YK_NDEF *ndef)
413 {
414         if(ndef)
415         {
416                 free(ndef);
417                 return 1;
418         }
419         return 0;
420 }
421
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)
424 {
425         int num_identifiers = sizeof(ndef_identifiers) / sizeof(char*);
426         size_t data_length;
427         int indx = 0;
428         for(; indx < num_identifiers; indx++) {
429                 size_t len = strlen(ndef_identifiers[indx]);
430                 if(strncmp(uri, ndef_identifiers[indx], len) == 0) {
431                         uri += len;
432                         break;
433                 }
434         }
435         data_length = strlen(uri);
436         if(data_length + 1 > NDEF_DATA_SIZE) {
437                 ykp_errno = YKP_EINVAL;
438                 return 0;
439         }
440         if(indx == num_identifiers) {
441                 ndef->data[0] = 0;
442         } else {
443                 ndef->data[0] = indx + 1;
444         }
445         memcpy(ndef->data + 1, uri, data_length);
446         ndef->len = data_length + 1;
447         ndef->type = 'U';
448         return 1;
449 }
450
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)
453 {
454         size_t data_length = strlen(text);
455         size_t lang_length = strlen(lang);
456         unsigned char status = lang_length;
457         if(isutf16) {
458                 status &= 0x80;
459         }
460         if((data_length + lang_length + 1) > NDEF_DATA_SIZE) {
461                 ykp_errno = YKP_EINVAL;
462                 return 0;
463         }
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;
468         ndef->type = 'T';
469         return 1;
470 }
471
472 int ykp_ndef_as_text(YK_NDEF *ndef, char *text, size_t len)
473 {
474         if(ndef->type == 'U') {
475                 const char *part = NULL;
476                 size_t offset = 0;
477                 if(ndef->data[0] > 0) {
478                         part = ndef_identifiers[ndef->data[0] - 1];
479                         offset = strlen(part);
480                 }
481                 if(offset + ndef->len - 1 > len) {
482                         ykp_errno = YKP_EINVAL;
483                         return 0;
484                 }
485                 if(part) {
486                         memcpy(text, part, offset);
487                 }
488                 memcpy(text + offset, ndef->data + 1, ndef->len - 1);
489                 text[ndef->len + offset] = 0;
490                 return 1;
491         }
492         else if(ndef->type == 'T') {
493                 unsigned char status = ndef->data[0];
494                 if(status & 0x80)
495                         status ^= 0x80;
496                 if(ndef->len - status - 1 > len) {
497                         ykp_errno = YKP_EINVAL;
498                         return 0;
499                 }
500                 memcpy(text, ndef->data + status + 1, ndef->len - status - 1);
501                 text[ndef->len - status] = 0;
502                 return 1;
503         }
504         else {
505                 return 0;
506         }
507 }
508
509 int ykp_set_ndef_access_code(YK_NDEF *ndef, unsigned char *access_code)
510 {
511         if(ndef)
512         {
513                 memcpy(ndef->curAccCode, access_code, ACC_CODE_SIZE);
514                 return 0;
515         }
516         return 1;
517 }
518
519 YK_DEVICE_CONFIG *ykp_alloc_device_config(void)
520 {
521         YK_DEVICE_CONFIG *cfg = malloc(sizeof(YK_DEVICE_CONFIG));
522         if(cfg) {
523                 memset(cfg, 0, sizeof(YK_DEVICE_CONFIG));
524                 return cfg;
525         }
526         return 0;
527 }
528
529 int ykp_free_device_config(YK_DEVICE_CONFIG *device_config)
530 {
531         if(device_config) {
532                 free(device_config);
533                 return 1;
534         }
535         return 0;
536 }
537
538 int ykp_set_device_mode(YK_DEVICE_CONFIG *device_config, unsigned char mode)
539 {
540         if(device_config) {
541                 device_config->mode = mode;
542                 return 1;
543         }
544         ykp_errno = YKP_EINVAL;
545         return 0;
546 }
547
548 int ykp_set_device_chalresp_timeout(YK_DEVICE_CONFIG *device_config, unsigned char timeout)
549 {
550         if(device_config) {
551                 device_config->crTimeout = timeout;
552                 return 1;
553         }
554         ykp_errno = YKP_EINVAL;
555         return 0;
556 }
557
558 int ykp_set_device_autoeject_time(YK_DEVICE_CONFIG *device_config, unsigned short eject_time)
559 {
560         if(device_config) {
561                 device_config->autoEjectTime = eject_time;
562                 return 1;
563         }
564         ykp_errno = YKP_EINVAL;
565         return 0;
566 }
567
568 static bool vcheck_all(const YKP_CONFIG *cfg)
569 {
570         return true;
571 }
572 static bool vcheck_v1(const YKP_CONFIG *cfg)
573 {
574         return cfg->yk_major_version == 1;
575 }
576 static bool vcheck_no_v1(const YKP_CONFIG *cfg)
577 {
578         return cfg->yk_major_version > 1;
579 }
580
581 static bool vcheck_v21_or_greater(const YKP_CONFIG *cfg)
582 {
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;
587 }
588
589 static bool vcheck_v22_or_greater(const YKP_CONFIG *cfg)
590 {
591         return (cfg->yk_major_version == 2 &&
592                 cfg->yk_minor_version >= 2) ||
593                 cfg->yk_major_version > 2;
594 }
595
596 static bool vcheck_v23_or_greater(const YKP_CONFIG *cfg)
597 {
598         return (cfg->yk_major_version == 2 &&
599                 cfg->yk_minor_version >= 3) ||
600                 cfg->yk_major_version > 2;
601 }
602
603 static bool vcheck_v24_or_greater(const YKP_CONFIG *cfg)
604 {
605         return (cfg->yk_major_version == 2 &&
606                 cfg->yk_minor_version >= 4) ||
607                 cfg->yk_major_version > 2;
608 }
609
610 static bool vcheck_v30(const YKP_CONFIG *cfg)
611 {
612         return (cfg->yk_major_version == 3 &&
613                 cfg->yk_minor_version == 0);
614 }
615
616 static bool vcheck_neo(const YKP_CONFIG *cfg)
617 {
618         return (cfg->yk_major_version == 2 &&
619                         cfg->yk_minor_version == 1 &&
620                         cfg->yk_build_version >= 4);
621
622 }
623
624 static bool vcheck_neo_before_5(const YKP_CONFIG *cfg)
625 {
626         return vcheck_neo(cfg) && cfg->yk_build_version < 5;
627 }
628
629 static bool vcheck_neo_after_6(const YKP_CONFIG *cfg)
630 {
631         return vcheck_neo(cfg) && cfg->yk_build_version > 6;
632 }
633
634 bool capability_has_hidtrig(const YKP_CONFIG *cfg)
635 {
636         return vcheck_v1(cfg);
637 }
638
639 bool capability_has_ticket_first(const YKP_CONFIG *cfg)
640 {
641         return vcheck_v1(cfg);
642 }
643
644 bool capability_has_static(const YKP_CONFIG *cfg)
645 {
646         return vcheck_all(cfg) && !vcheck_neo_before_5(cfg);
647 }
648
649 bool capability_has_static_extras(const YKP_CONFIG *cfg)
650 {
651         return vcheck_no_v1(cfg) && !vcheck_neo_before_5(cfg);
652 }
653
654 bool capability_has_slot_two(const YKP_CONFIG *cfg)
655 {
656         return vcheck_no_v1(cfg) && !vcheck_neo(cfg);
657 }
658
659 bool capability_has_chal_resp(const YKP_CONFIG *cfg)
660 {
661         return vcheck_v22_or_greater(cfg);
662 }
663
664 bool capability_has_oath_imf(const YKP_CONFIG *cfg)
665 {
666         return vcheck_v22_or_greater(cfg) || vcheck_neo_after_6(cfg);
667 }
668
669 bool capability_has_serial_api(const YKP_CONFIG *cfg)
670 {
671         return vcheck_v22_or_greater(cfg) || vcheck_neo(cfg);
672 }
673
674 bool capability_has_serial(const YKP_CONFIG *cfg)
675 {
676         return vcheck_v22_or_greater(cfg);
677 }
678
679 bool capability_has_oath(const YKP_CONFIG *cfg)
680 {
681         return vcheck_v21_or_greater(cfg) || vcheck_neo(cfg);
682 }
683
684 bool capability_has_ticket_mods(const YKP_CONFIG *cfg)
685 {
686         return vcheck_all(cfg);
687 }
688
689 bool capability_has_update(const YKP_CONFIG *cfg)
690 {
691         return vcheck_v23_or_greater(cfg);
692 }
693
694 bool capability_has_fast(const YKP_CONFIG *cfg)
695 {
696         return vcheck_v23_or_greater(cfg);
697 }
698
699 bool capability_has_numeric(const YKP_CONFIG *cfg)
700 {
701         return vcheck_v23_or_greater(cfg);
702 }
703
704 bool capability_has_dormant(const YKP_CONFIG *cfg)
705 {
706         return vcheck_v23_or_greater(cfg);
707 }
708
709 bool capability_has_led_inv(const YKP_CONFIG *cfg)
710 {
711         return (vcheck_v24_or_greater(cfg) && !vcheck_v30(cfg));
712 }
713
714 int ykp_set_oath_imf(YKP_CONFIG *cfg, unsigned long imf)
715 {
716         if (!capability_has_oath_imf(cfg)) {
717                 ykp_errno = YKP_EYUBIKEYVER;
718                 return 0;
719         }
720         if (imf > 65535*16) {
721                 ykp_errno = YKP_EINVAL;
722                 return 0;
723         }
724         if (imf % 16 != 0) {
725                 ykp_errno = YKP_EINVAL;
726                 return 0;
727         }
728         /* IMF/16 is 16 bits stored big-endian in uid[4] */
729         imf /= 16;
730         cfg->ykcore_config.uid[4] = imf >> 8;
731         cfg->ykcore_config.uid[5] = imf;
732         return 1;
733 }
734
735 unsigned long ykp_get_oath_imf(const YKP_CONFIG *cfg)
736 {
737         if (!capability_has_oath_imf(cfg)) {
738                 return 0;
739         }
740
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;
744 }
745
746 #define def_set_charfield(fnname,fieldname,size,extra,capability)       \
747 int ykp_set_ ## fnname(YKP_CONFIG *cfg, unsigned char *input, size_t len)       \
748 {                                                               \
749         if (cfg) {                                              \
750                 size_t max_chars = len;                         \
751                                                                 \
752                 if (!capability(cfg)) {                         \
753                         ykp_errno = YKP_EYUBIKEYVER;            \
754                         return 0;                               \
755                 }                                               \
756                 if (max_chars > (size))                         \
757                         max_chars = (size);                     \
758                                                                 \
759                 memcpy(cfg->ykcore_config.fieldname, (input), max_chars);       \
760                 memset(cfg->ykcore_config.fieldname + max_chars, 0,             \
761                        (size) - max_chars);                     \
762                 extra;                                          \
763                                                                 \
764                 return 1;                                       \
765         }                                                       \
766         ykp_errno = YKP_ENOCFG;                                 \
767         return 0;                                               \
768 }
769
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)
773
774 #define def_set_tktflag(type,capability)                        \
775 int ykp_set_tktflag_ ## type(YKP_CONFIG *cfg, bool state)       \
776 {                                                               \
777         if (cfg) {                                              \
778                 if (!capability(cfg)) {                         \
779                         ykp_errno = YKP_EYUBIKEYVER;            \
780                         return 0;                               \
781                 }                                               \
782                 if (state)                                      \
783                         cfg->ykcore_config.tktFlags |= TKTFLAG_ ## type;        \
784                 else                                            \
785                         cfg->ykcore_config.tktFlags &= ~TKTFLAG_ ## type;       \
786                 return 1;                                       \
787         }                                                       \
788         ykp_errno = YKP_ENOCFG;                                 \
789         return 0;                                               \
790 } \
791 bool ykp_get_tktflag_ ## type(const YKP_CONFIG *cfg)            \
792 {                                                               \
793         if (cfg) {                                              \
794                 if((cfg->ykcore_config.tktFlags & TKTFLAG_ ## type) == TKTFLAG_ ## type)        \
795                         return true;                            \
796                 else                                            \
797                         return false;                           \
798         }                                                       \
799         return false;                                           \
800 }
801
802
803
804 #define def_set_cfgflag(type,capability)                        \
805 int ykp_set_cfgflag_ ## type(YKP_CONFIG *cfg, bool state)       \
806 {                                                               \
807         if (cfg) {                                              \
808                 if (!capability(cfg)) {                         \
809                         ykp_errno = YKP_EYUBIKEYVER;            \
810                         return 0;                               \
811                 }                                               \
812                 if (state)                                      \
813                         cfg->ykcore_config.cfgFlags |= CFGFLAG_ ## type;        \
814                 else                                            \
815                         cfg->ykcore_config.cfgFlags &= ~CFGFLAG_ ## type;       \
816                 return 1;                                       \
817         }                                                       \
818         ykp_errno = YKP_ENOCFG;                                 \
819         return 0;                                               \
820 }                                                               \
821 bool ykp_get_cfgflag_ ## type(const YKP_CONFIG *cfg)            \
822 {                                                               \
823         if (cfg) {                                              \
824                 if((cfg->ykcore_config.cfgFlags & CFGFLAG_ ## type) == CFGFLAG_ ## type)        \
825                         return true;                            \
826                 else                                            \
827                         return false;                           \
828         }                                                       \
829         return false;                                           \
830 }
831
832
833 #define def_set_extflag(type,capability)                        \
834 int ykp_set_extflag_ ## type(YKP_CONFIG *cfg, bool state)       \
835 {                                                               \
836         if (cfg) {                                              \
837                 if (!capability(cfg)) {                         \
838                         ykp_errno = YKP_EYUBIKEYVER;            \
839                         return 0;                               \
840                 }                                               \
841                 if (state)                                      \
842                         cfg->ykcore_config.extFlags |= EXTFLAG_ ## type;        \
843                 else                                            \
844                         cfg->ykcore_config.extFlags &= ~EXTFLAG_ ## type;       \
845                 return 1;                                       \
846         }                                                       \
847         ykp_errno = YKP_ENOCFG;                                 \
848         return 0;                                               \
849 }                                                               \
850 bool ykp_get_extflag_ ## type(const YKP_CONFIG *cfg)            \
851 {                                                               \
852         if (cfg) {                                              \
853                 if((cfg->ykcore_config.extFlags & EXTFLAG_ ## type) == EXTFLAG_ ## type)        \
854                         return true;                            \
855                 else                                            \
856                         return false;                           \
857         }                                                       \
858         return false;                                           \
859 }
860
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)
870
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)
889
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)
898
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";
908
909 static const char str_flags_separator[] = "|";
910
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";
914
915
916 static int _ykp_legacy_export_config(const YKP_CONFIG *cfg, char *buf, size_t len) {
917         if (cfg) {
918                 char buffer[256];
919                 struct map_st *p;
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;
924
925                 int pos = 0;
926
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;
932                         } else {
933                                 mode = MODE_OATH_HOTP;
934                         }
935                 }
936                 else if((ycfg.cfgFlags & CFGFLAG_STATIC_TICKET) == CFGFLAG_STATIC_TICKET) {
937                         mode = MODE_STATIC_TICKET;
938                 }
939
940                 /* for OATH-HOTP and HMAC-SHA1 challenge response, there is four bytes
941                  *  additional key data in the uid field
942                  */
943                 key_bits_in_uid = (ykp_get_supported_key_length(cfg) == 20);
944
945                 /* fixed: or OATH id: */
946                 if ((ycfg.tktFlags & TKTFLAG_OATH_HOTP) == TKTFLAG_OATH_HOTP &&
947                     ycfg.fixedSize) {
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);
953                         } else {
954                                 yubikey_hex_encode(buffer, (const char *)ycfg.fixed, 1);
955                         }
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);
960                         } else {
961                                 yubikey_hex_encode(buffer + 2, (const char *)ycfg.fixed + 1, 1);
962                         }
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);
966                         } else {
967                                 yubikey_hex_encode(buffer + 4, (const char *)ycfg.fixed + 2, 8);
968                         }
969                         buffer[12] = 0;
970                         pos += snprintf(buf, len - (size_t)pos, "%s%s%s\n", str_oath_id, str_key_value_separator, buffer);
971                 } else {
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);
974                 }
975
976                 /* uid: */
977                 if (key_bits_in_uid) {
978                         strncpy(buffer, "n/a", 3);
979                 } else {
980                         yubikey_hex_encode(buffer, (const char *)ycfg.uid, UID_SIZE);
981                 }
982                 pos += snprintf(buf + pos, len - (size_t)pos, "%s%s%s\n", str_uid, str_key_value_separator, buffer);
983
984                 /* key: */
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);
988                 }
989                 pos += snprintf(buf + pos, len - (size_t)pos, "%s%s%s%s\n", str_key, str_key_value_separator, str_hex_prefix, buffer);
990
991                 /* acc_code: */
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);
994
995                 /* OATH IMF: */
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));
999                 }
1000
1001                 /* ticket_flags: */
1002                 buffer[0] = '\0';
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) {
1007                                 if (*buffer) {
1008                                         strncat(buffer, str_flags_separator, 256 - strlen(buffer));
1009                                 }
1010                                 strncat(buffer, p->flag_text, 256 - strlen(buffer));
1011                         }
1012                 }
1013                 pos += snprintf(buf + pos, len - (size_t)pos, "%s%s%s\n", str_ticket_flags, str_key_value_separator, buffer);
1014
1015                 /* config_flags: */
1016                 buffer[0] = '\0';
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) {
1022                                 if (*buffer) {
1023                                         strncat(buffer, str_flags_separator, 256 - strlen(buffer));
1024                                 }
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
1028                                 */
1029                                 t_flags -= p->flag;
1030                         }
1031                 }
1032                 pos += snprintf(buf + pos, len - (size_t)pos, "%s%s%s\n", str_config_flags, str_key_value_separator, buffer);
1033
1034                 /* extended_flags: */
1035                 buffer[0] = '\0';
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) {
1040                                 if (*buffer) {
1041                                         strncat(buffer, str_flags_separator, 256 - strlen(buffer));
1042                                 }
1043                                 strncat(buffer, p->flag_text, 256 - strlen(buffer));
1044                         }
1045                 }
1046                 pos += snprintf(buf + pos, len - (size_t)pos, "%s%s%s\n", str_extended_flags, str_key_value_separator, buffer);
1047
1048                 return pos;
1049         }
1050         return 0;
1051 }
1052
1053 int ykp_export_config(const YKP_CONFIG *cfg, char *buf, size_t len,
1054                 int format) {
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);
1059         }
1060         ykp_errno = YKP_EINVAL;
1061         return 0;
1062 }
1063
1064
1065 int ykp_import_config(YKP_CONFIG *cfg, const char *buf, size_t len,
1066                 int format) {
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;
1071         }
1072         ykp_errno = YKP_EINVAL;
1073         return 0;
1074 }
1075 int ykp_write_config(const YKP_CONFIG *cfg,
1076                      int (*writer)(const char *buf, size_t count,
1077                                    void *userdata),
1078                      void *userdata) {
1079         if(cfg) {
1080                 char buffer[1024];
1081                 int ret = _ykp_legacy_export_config(cfg, buffer, 1024);
1082                 if(ret) {
1083                         writer(buffer, strlen(buffer), userdata);
1084                         return 1;
1085                 }
1086                 return 0;
1087         }
1088         ykp_errno = YKP_ENOCFG;
1089         return 0;
1090 }
1091
1092 int ykp_read_config(YKP_CONFIG *cfg,
1093                     int (*reader)(char *buf, size_t count,
1094                                   void *userdata),
1095                     void *userdata)
1096 {
1097         ykp_errno = YKP_ENOTYETIMPL;
1098         return 0;
1099 }
1100
1101 YK_CONFIG *ykp_core_config(YKP_CONFIG *cfg)
1102 {
1103         if (cfg)
1104                 return &cfg->ykcore_config;
1105         ykp_errno = YKP_ENOCFG;
1106         return 0;
1107 }
1108
1109 int ykp_command(YKP_CONFIG *cfg) {
1110         if (cfg) {
1111                 return cfg->command;
1112         }
1113         ykp_errno = YKP_ENOCFG;
1114         return 0;
1115 }
1116
1117 int ykp_config_num(YKP_CONFIG *cfg)
1118 {
1119         if (cfg) {
1120                 if (cfg->command == SLOT_CONFIG) {
1121                         return 1;
1122                 } else if (cfg->command == SLOT_CONFIG2) {
1123                         return 2;
1124                 }
1125         }
1126         ykp_errno = YKP_ENOCFG;
1127         return 0;
1128 }
1129
1130 void ykp_set_acccode_type(YKP_CONFIG *cfg, unsigned int type)
1131 {
1132         cfg->ykp_acccode_type = type;
1133 }
1134
1135 unsigned int ykp_get_acccode_type(const YKP_CONFIG *cfg)
1136 {
1137         return cfg->ykp_acccode_type;
1138 }
1139
1140 int * _ykp_errno_location(void)
1141 {
1142         static int tsd_init = 0;
1143         static int nothread_errno = 0;
1144         YK_DEFINE_TSD_METADATA(errno_key);
1145         int rc = 0;
1146
1147         if (tsd_init == 0) {
1148                 if ((rc = YK_TSD_INIT(errno_key, free)) == 0) {
1149                         tsd_init = 1;
1150                 } else {
1151                         tsd_init = -1;
1152                 }
1153         }
1154
1155         if(YK_TSD_GET(int *, errno_key) == NULL) {
1156                 void *p = calloc(1, sizeof(int));
1157                 if (!p) {
1158                         tsd_init = -1;
1159                 } else {
1160                         YK_TSD_SET(errno_key, p);
1161                 }
1162         }
1163         if (tsd_init == 1) {
1164                 return YK_TSD_GET(int *, errno_key);
1165         }
1166         return &nothread_errno;
1167 }
1168
1169 static const char *errtext[] = {
1170         "",
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",
1178 };
1179 const char *ykp_strerror(int errnum)
1180 {
1181         if (errnum < sizeof(errtext)/sizeof(errtext[0]))
1182                 return errtext[errnum];
1183         return NULL;
1184 }