1 /*
2 * Copyright (c) 2014-2020 Yubico AB
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials provided
15 * with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 */
30 /** @file */
31
32 #include <stdlib.h>
33 #include <string.h>
34 #include <stdio.h>
35 #include <stdint.h>
36 #include <ctype.h>
37
38 #include "internal.h"
39 #include "ykpiv.h"
40
41 /**
42 * DISABLE_PIN_CACHE - disable in-RAM cache of PIN
43 *
44 * By default, the PIN is cached in RAM when provided to \p ykpiv_verify() or
45 * changed with \p ykpiv_change_pin(). If the USB connection is lost between
46 * calls, the device will be re-authenticated on the next call using the cached
47 * PIN. The PIN is cleared with a call to \p ykpiv_done().
48 *
49 * The PIN cache prevents problems with long-running applications losing their
50 * authentication in some cases, such as when a laptop sleeps.
51 *
52 * The cache can be disabled by setting this define to 1 if it is not desired
53 * to store the PIN in RAM.
54 *
55 */
56 #ifndef DISABLE_PIN_CACHE
57 #define DISABLE_PIN_CACHE 0
58 #endif
59
60 /**
61 * DISABLE_MGM_KEY_CACHE - disable in-RAM cache of MGM_KEY (SO PIN)
62 *
63 * By default, the MGM_KEY is cached in RAM when provided to \p ykpiv_authenticate() or
64 * changed with \p ykpiv_set_mgmkey(). If the USB connection is lost between
65 * calls, the device will be re-authenticated on the next call using the cached
66 * MGM_KEY. The MGM_KEY is cleared with a call to \p ykpiv_done().
67 *
68 * The MGM_KEY cache prevents problems with long-running applications losing their
69 * authentication in some cases, such as when a laptop sleeps.
70 *
71 * The cache can be disabled by setting this define to 1 if it is not desired
72 * to store the MGM_KEY in RAM.
73 *
74 */
75 #ifndef DISABLE_MGM_KEY_CACHE
76 #define DISABLE_MGM_KEY_CACHE 0
77 #endif
78
79 /**
80 * ENABLE_APPLICATION_RESELECT - re-select application for all public API calls
81 *
82 * If this is enabled, every public call (prefixed with \r ykpiv_) will check
83 * that the PIV application is currently selected, or re-select it if it is
84 * not.
85 *
86 * Auto re-selection allows a long-running PIV application to cooperate on
87 * a system that may simultaneously use the non-PIV applications of connected
88 * devices.
89 *
90 * This is \b DANGEROUS - with this enabled, slots with the policy
91 * \p YKPIV_PINPOLICY_ALWAYS will not be accessible.
92 *
93 */
94 #ifndef ENABLE_APPLICATION_RESELECTION
95 #define ENABLE_APPLICATION_RESELECTION 0
96 #endif
97
98
99 /**
100 * ENABLE_IMPLICIT_TRANSACTIONS - call SCardBeginTransaction for all public API calls
101 *
102 * If this is enabled, every public call (prefixed with \r ykpiv_) will call
103 * SCardBeginTransaction on entry and SCardEndTransaction on exit.
104 *
105 * For applications that do not do their own transaction management, like the piv tool
106 * itself, retaining the default setting of enabled can allow other applications and
107 * threads to make calls to CCID that can interfere with multi-block data sent to the
108 * card via SCardTransmitData.
109 */
110 #ifndef ENABLE_IMPLICIT_TRANSACTIONS
111 #define ENABLE_IMPLICIT_TRANSACTIONS 1
112 #endif
113
114 /**
115 * Platform specific definitions
116 */
117 #ifdef _MSC_VER
118 #define strncasecmp _strnicmp
119 #endif
120
121 #define YKPIV_MGM_DEFAULT "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08"
122
123 static ykpiv_rc _cache_pin(ykpiv_state *state, const char *pin, size_t len);
124 static ykpiv_rc _cache_mgm_key(ykpiv_state *state, unsigned const char *key);
125 static ykpiv_rc _ykpiv_get_serial(ykpiv_state *state);
126 static ykpiv_rc _ykpiv_get_version(ykpiv_state *state);
127 static ykpiv_rc _ykpiv_verify(ykpiv_state *state, const char *pin, const size_t pin_len);
128 static ykpiv_rc _ykpiv_authenticate(ykpiv_state *state, unsigned const char *key);
129 static ykpiv_rc _ykpiv_auth_deauthenticate(ykpiv_state *state);
130
131 static unsigned const char piv_aid[] = {
132 0xa0, 0x00, 0x00, 0x03, 0x08
133 };
134
135 static unsigned const char yk_aid[] = {
136 0xa0, 0x00, 0x00, 0x05, 0x27, 0x20, 0x01, 0x01
137 };
138
139 static unsigned const char mgmt_aid[] = {
140 0xa0, 0x00, 0x00, 0x05, 0x27, 0x47, 0x11, 0x17
141 };
142
_default_alloc(void * data,size_t cb)143 static void* _default_alloc(void *data, size_t cb) {
144 (void)data;
145 return calloc(cb, 1);
146 }
147
_default_realloc(void * data,void * p,size_t cb)148 static void * _default_realloc(void *data, void *p, size_t cb) {
149 (void)data;
150 return realloc(p, cb);
151 }
152
_default_free(void * data,void * p)153 static void _default_free(void *data, void *p) {
154 (void)data;
155 free(p);
156 }
157
158 ykpiv_allocator _default_allocator = {
159 .pfn_alloc = _default_alloc,
160 .pfn_realloc = _default_realloc,
161 .pfn_free = _default_free,
162 .alloc_data = 0
163 };
164
165 /* Memory helper functions */
166
_ykpiv_alloc(ykpiv_state * state,size_t size)167 void* _ykpiv_alloc(ykpiv_state *state, size_t size) {
168 if (!state || !(state->allocator.pfn_alloc)) return NULL;
169 return state->allocator.pfn_alloc(state->allocator.alloc_data, size);
170 }
171
_ykpiv_realloc(ykpiv_state * state,void * address,size_t size)172 void* _ykpiv_realloc(ykpiv_state *state, void *address, size_t size) {
173 if (!state || !(state->allocator.pfn_realloc)) return NULL;
174 return state->allocator.pfn_realloc(state->allocator.alloc_data, address, size);
175 }
176
_ykpiv_free(ykpiv_state * state,void * data)177 void _ykpiv_free(ykpiv_state *state, void *data) {
178 if (!data || !state || !(state->allocator.pfn_free)) return;
179 state->allocator.pfn_free(state->allocator.alloc_data, data);
180 }
181
dump_hex(const unsigned char * buf,unsigned int len)182 static void dump_hex(const unsigned char *buf, unsigned int len) {
183 unsigned int i;
184 for (i = 0; i < len; i++) {
185 fprintf(stderr, "%02x ", buf[i]);
186 }
187 }
188
_ykpiv_get_length_size(size_t length)189 size_t _ykpiv_get_length_size(size_t length) {
190 if(length < 0x80) {
191 return 1;
192 } else if(length < 0x100) {
193 return 2;
194 } else {
195 return 3;
196 }
197 }
198
_ykpiv_set_length(unsigned char * buffer,size_t length)199 size_t _ykpiv_set_length(unsigned char *buffer, size_t length) {
200 if(length < 0x80) {
201 *buffer++ = (unsigned char)length;
202 return 1;
203 } else if(length < 0x100) {
204 *buffer++ = 0x81;
205 *buffer++ = (unsigned char)length;
206 return 2;
207 } else {
208 *buffer++ = 0x82;
209 *buffer++ = (length >> 8) & 0xff;
210 *buffer++ = length & 0xff;
211 return 3;
212 }
213 }
214
_ykpiv_get_length(const unsigned char * buffer,const unsigned char * end,size_t * len)215 size_t _ykpiv_get_length(const unsigned char *buffer, const unsigned char* end, size_t *len) {
216 if(buffer + 1 <= end && buffer[0] < 0x80) {
217 *len = buffer[0];
218 return buffer + 1 + *len <= end ? 1 : 0;
219 } else if(buffer + 2 <= end && buffer[0] == 0x81) {
220 *len = buffer[1];
221 return buffer + 2 + *len <= end ? 2 : 0;
222 } else if(buffer + 3 <= end && buffer[0] == 0x82) {
223 size_t tmp = buffer[1];
224 *len = (tmp << 8) + buffer[2];
225 return buffer + 3 + *len <= end ? 3 : 0;
226 }
227 *len = 0;
228 return 0;
229 }
230
set_object(int object_id,unsigned char * buffer)231 static unsigned char *set_object(int object_id, unsigned char *buffer) {
232 *buffer++ = 0x5c;
233 if(object_id == YKPIV_OBJ_DISCOVERY) {
234 *buffer++ = 1;
235 *buffer++ = YKPIV_OBJ_DISCOVERY;
236 } else if(object_id > 0xffff && object_id <= 0xffffff) {
237 *buffer++ = 3;
238 *buffer++ = (object_id >> 16) & 0xff;
239 *buffer++ = (object_id >> 8) & 0xff;
240 *buffer++ = object_id & 0xff;
241 }
242 return buffer;
243 }
244
ykpiv_init_with_allocator(ykpiv_state ** state,int verbose,const ykpiv_allocator * allocator)245 ykpiv_rc ykpiv_init_with_allocator(ykpiv_state **state, int verbose, const ykpiv_allocator *allocator) {
246 ykpiv_state *s;
247 if (NULL == state) {
248 return YKPIV_GENERIC_ERROR;
249 }
250 if (NULL == allocator || !allocator->pfn_alloc || !allocator->pfn_realloc || !allocator->pfn_free) {
251 return YKPIV_MEMORY_ERROR;
252 }
253
254 s = allocator->pfn_alloc(allocator->alloc_data, sizeof(ykpiv_state));
255 if (NULL == s) {
256 return YKPIV_MEMORY_ERROR;
257 }
258
259 memset(s, 0, sizeof(ykpiv_state));
260 s->allocator = *allocator;
261 s->verbose = verbose;
262 s->context = (SCARDCONTEXT)-1;
263 *state = s;
264 return YKPIV_OK;
265 }
266
ykpiv_init(ykpiv_state ** state,int verbose)267 ykpiv_rc ykpiv_init(ykpiv_state **state, int verbose) {
268 return ykpiv_init_with_allocator(state, verbose, &_default_allocator);
269 }
270
_ykpiv_done(ykpiv_state * state,bool disconnect)271 static ykpiv_rc _ykpiv_done(ykpiv_state *state, bool disconnect) {
272 if (disconnect)
273 ykpiv_disconnect(state);
274 _cache_pin(state, NULL, 0);
275 _cache_mgm_key(state, NULL);
276 _ykpiv_free(state, state);
277 return YKPIV_OK;
278 }
279
ykpiv_done_with_external_card(ykpiv_state * state)280 ykpiv_rc ykpiv_done_with_external_card(ykpiv_state *state) {
281 return _ykpiv_done(state, false);
282 }
283
ykpiv_done(ykpiv_state * state)284 ykpiv_rc ykpiv_done(ykpiv_state *state) {
285 return _ykpiv_done(state, true);
286 }
287
ykpiv_disconnect(ykpiv_state * state)288 ykpiv_rc ykpiv_disconnect(ykpiv_state *state) {
289 if(state->card) {
290 if(state->verbose) {
291 fprintf(stderr, "Disconnect card #%u.\n", state->serial);
292 }
293 SCardDisconnect(state->card, SCARD_RESET_CARD);
294 state->card = 0;
295 }
296
297 if(SCardIsValidContext(state->context) == SCARD_S_SUCCESS) {
298 SCardReleaseContext(state->context);
299 state->context = (SCARDCONTEXT)-1;
300 }
301
302 state->serial = 0;
303 state->ver.major = 0;
304 state->ver.minor = 0;
305 state->ver.patch = 0;
306
307 return YKPIV_OK;
308 }
309
_ykpiv_select_application(ykpiv_state * state)310 ykpiv_rc _ykpiv_select_application(ykpiv_state *state) {
311 APDU apdu = {0};
312 unsigned char data[0xff] = {0};
313 uint32_t recv_len = sizeof(data);
314 int sw;
315 ykpiv_rc res = YKPIV_OK;
316
317 memset(apdu.raw, 0, sizeof(apdu));
318 apdu.st.ins = YKPIV_INS_SELECT_APPLICATION;
319 apdu.st.p1 = 0x04;
320 apdu.st.lc = sizeof(piv_aid);
321 memcpy(apdu.st.data, piv_aid, sizeof(piv_aid));
322
323 if((res = _send_data(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) {
324 if(state->verbose) {
325 fprintf(stderr, "Failed communicating with card: '%s'\n", ykpiv_strerror(res));
326 }
327 return res;
328 }
329 else if(sw != SW_SUCCESS) {
330 if(state->verbose) {
331 fprintf(stderr, "Failed selecting application: %04x\n", sw);
332 }
333 return YKPIV_GENERIC_ERROR;
334 }
335
336 /* now that the PIV application is selected, retrieve the version
337 * and serial number. Previously the NEO/YK4 required switching
338 * to the yk applet to retrieve the serial, YK5 implements this
339 * as a PIV applet command. Unfortunately, this change requires
340 * that we retrieve the version number first, so that get_serial
341 * can determine how to get the serial number, which for the NEO/Yk4
342 * will result in another selection of the PIV applet. */
343
344 // This stores the number of PIN retries left in state
345 _ykpiv_verify(state, NULL, 0);
346 // WRONG_PIN or PIN_LOCKED is expected on successful query.
347
348 res = _ykpiv_get_version(state);
349 if (res != YKPIV_OK) {
350 if (state->verbose) {
351 fprintf(stderr, "Failed to retrieve version: '%s'\n", ykpiv_strerror(res));
352 }
353 }
354
355 res = _ykpiv_get_serial(state);
356 if (res != YKPIV_OK) {
357 if (state->verbose) {
358 fprintf(stderr, "Failed to retrieve serial number: '%s'\n", ykpiv_strerror(res));
359 }
360 res = YKPIV_OK;
361 }
362
363 return res;
364 }
365
_ykpiv_ensure_application_selected(ykpiv_state * state)366 ykpiv_rc _ykpiv_ensure_application_selected(ykpiv_state *state) {
367 ykpiv_rc res = YKPIV_OK;
368 #if ENABLE_APPLICATION_RESELECTION
369 if (NULL == state) {
370 return YKPIV_GENERIC_ERROR;
371 }
372
373 res = _ykpiv_verify(state, NULL, 0);
374
375 if ((YKPIV_OK != res) && (YKPIV_WRONG_PIN != res) && (YKPIV_PIN_LOCKED != res)) {
376 res = _ykpiv_select_application(state);
377 }
378 else {
379 res = YKPIV_OK;
380 }
381
382 return res;
383 #else
384 (void)state;
385 return res;
386 #endif
387 }
388
_ykpiv_connect(ykpiv_state * state,uintptr_t context,uintptr_t card)389 static ykpiv_rc _ykpiv_connect(ykpiv_state *state, uintptr_t context, uintptr_t card) {
390 ykpiv_rc res = YKPIV_OK;
391
392 if (NULL == state) {
393 return YKPIV_GENERIC_ERROR;
394 }
395
396 // if the context has changed, and the new context is not valid, return an error
397 if ((context != state->context) && (SCARD_S_SUCCESS != SCardIsValidContext(context))) {
398 return YKPIV_PCSC_ERROR;
399 }
400
401 // if card handle has changed, determine if handle is valid (less efficient, but complete)
402 if ((card != state->card)) {
403 char reader[CB_BUF_MAX] = {0};
404 pcsc_word reader_len = sizeof(reader);
405 uint8_t atr[CB_ATR_MAX] = {0};
406 pcsc_word atr_len = sizeof(atr);
407
408 // Cannot set the reader len to NULL. Confirmed in OSX 10.10, so we have to retrieve it even though we don't need it.
409 if (SCARD_S_SUCCESS != SCardStatus(card, reader, &reader_len, NULL, NULL, atr, &atr_len)) {
410 return YKPIV_PCSC_ERROR;
411 }
412
413 if(atr_len + 1 == sizeof(YKPIV_ATR_NEO_R3) && !memcmp(atr, YKPIV_ATR_NEO_R3, atr_len))
414 state->model = DEVTYPE_NEOr3;
415 else if(atr_len + 1 == sizeof(YKPIV_ATR_NEO_R3_NFC) && !memcmp(atr, YKPIV_ATR_NEO_R3_NFC, atr_len))
416 state->model = DEVTYPE_NEOr3;
417 else if(atr_len + 1 == sizeof(YKPIV_ATR_YK4) && !memcmp(atr, YKPIV_ATR_YK4, atr_len))
418 state->model = DEVTYPE_YK4;
419 else if(atr_len + 1 == sizeof(YKPIV_ATR_YK5_P1) && !memcmp(atr, YKPIV_ATR_YK5_P1, atr_len))
420 state->model = DEVTYPE_YK5;
421 else if(atr_len + 1 == sizeof(YKPIV_ATR_YK5) && !memcmp(atr, YKPIV_ATR_YK5, atr_len))
422 state->model = DEVTYPE_YK5;
423 else if(atr_len + 1 == sizeof(YKPIV_ATR_YK5_NFC) && !memcmp(atr, YKPIV_ATR_YK5_NFC, atr_len))
424 state->model = DEVTYPE_YK5;
425 else
426 state->model = DEVTYPE_UNKNOWN;
427 }
428
429 state->context = context;
430 state->card = card;
431
432 /*
433 ** Do not select the applet here, as we need to accommodate commands that are
434 ** sensitive to re-select (custom apdu/auth). All commands that can handle explicit
435 ** selection already check the applet state and select accordingly anyway.
436 ** ykpiv_verify_select is supplied for those who want to select explicitly.
437 **
438 ** The applet _is_ selected by ykpiv_connect(), but is not selected when bypassing
439 ** it with ykpiv_connect_with_external_card().
440 */
441 return res;
442 }
443
ykpiv_connect_with_external_card(ykpiv_state * state,uintptr_t context,uintptr_t card)444 ykpiv_rc ykpiv_connect_with_external_card(ykpiv_state *state, uintptr_t context, uintptr_t card) {
445 return _ykpiv_connect(state, context, card);
446 }
447
ykpiv_validate(ykpiv_state * state,const char * wanted)448 ykpiv_rc ykpiv_validate(ykpiv_state *state, const char *wanted) {
449 if(state->card) {
450 if(state->verbose) {
451 fprintf(stderr, "Validate reader '%s'.\n", wanted);
452 }
453 char reader[CB_BUF_MAX] = {0};
454 pcsc_word reader_len = sizeof(reader);
455 uint8_t atr[CB_ATR_MAX] = {0};
456 pcsc_word atr_len = sizeof(atr);
457 LONG rc = SCardStatus(state->card, reader, &reader_len, NULL, NULL, atr, &atr_len);
458 if(rc != SCARD_S_SUCCESS) {
459 if(state->verbose) {
460 fprintf (stderr, "SCardStatus failed on reader '%s', rc=%lx\n", wanted, (long)rc);
461 }
462 rc = SCardDisconnect(state->card, SCARD_RESET_CARD);
463 if(rc != SCARD_S_SUCCESS) {
464 if(state->verbose) {
465 fprintf (stderr, "SCardDisconnect failed on reader '%s', rc=%lx\n", wanted, (long)rc);
466 }
467 }
468 state->card = 0;
469 state->serial = 0;
470 state->ver.major = 0;
471 state->ver.minor = 0;
472 state->ver.patch = 0;
473 _cache_pin(state, NULL, 0);
474 _cache_mgm_key(state, NULL);
475 return YKPIV_PCSC_ERROR;
476 }
477 if (strcmp(wanted, reader)) {
478 if(state->verbose) {
479 fprintf (stderr, "Disconnecting incorrect reader '%s' (wanted '%s'), rc=%lx\n", reader, wanted, (long)rc);
480 }
481 rc = SCardDisconnect(state->card, SCARD_RESET_CARD);
482 if(rc != SCARD_S_SUCCESS) {
483 if(state->verbose) {
484 fprintf (stderr, "SCardDisconnect failed on reader '%s' (wanted '%s'), rc=%lx\n", reader, wanted, (long)rc);
485 }
486 }
487 state->card = 0;
488 state->serial = 0;
489 state->ver.major = 0;
490 state->ver.minor = 0;
491 state->ver.patch = 0;
492 _cache_pin(state, NULL, 0);
493 _cache_mgm_key(state, NULL);
494 return YKPIV_GENERIC_ERROR;
495 }
496 return YKPIV_OK;
497 }
498 return YKPIV_GENERIC_ERROR;
499 }
500
ykpiv_connect(ykpiv_state * state,const char * wanted)501 ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted) {
502 pcsc_word active_protocol;
503 char reader_buf[2048] = {0};
504 size_t num_readers = sizeof(reader_buf);
505 LONG rc;
506 char *reader_ptr;
507 ykpiv_rc ret;
508 SCARDHANDLE card = (SCARDHANDLE)-1;
509
510 if(wanted && *wanted == '@') {
511 wanted++; // Skip the '@'
512 if(state->verbose) {
513 fprintf(stderr, "Connect reader '%s'.\n", wanted);
514 }
515 if(SCardIsValidContext(state->context) != SCARD_S_SUCCESS) {
516 rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &state->context);
517 if (rc != SCARD_S_SUCCESS) {
518 if(state->verbose) {
519 fprintf (stderr, "SCardEstablishContext failed, rc=%lx\n", (long)rc);
520 }
521 return YKPIV_PCSC_ERROR;
522 }
523 }
524 rc = SCardConnect(state->context, wanted, SCARD_SHARE_SHARED,
525 SCARD_PROTOCOL_T1, &card, &active_protocol);
526 if(rc != SCARD_S_SUCCESS)
527 {
528 if(state->verbose) {
529 fprintf(stderr, "SCardConnect failed for '%s', rc=%lx\n", wanted, (long)rc);
530 }
531 SCardReleaseContext(state->context);
532 state->context = (SCARDCONTEXT)-1;
533 return YKPIV_PCSC_ERROR;
534 }
535 } else
536 {
537 ret = ykpiv_list_readers(state, reader_buf, &num_readers);
538 if(ret != YKPIV_OK) {
539 return ret;
540 }
541
542 for(reader_ptr = reader_buf; *reader_ptr != '\0'; reader_ptr += strlen(reader_ptr) + 1) {
543 if(wanted) {
544 char *ptr = reader_ptr;
545 bool found = false;
546 do {
547 if(strlen(ptr) < strlen(wanted)) {
548 break;
549 }
550 if(strncasecmp(ptr, wanted, strlen(wanted)) == 0) {
551 found = true;
552 break;
553 }
554 } while(*ptr++);
555
556 if(found == false) {
557 if(state->verbose) {
558 fprintf(stderr, "Skipping reader '%s' since it doesn't match '%s'.\n", reader_ptr, wanted);
559 }
560 continue;
561 }
562 }
563 if(state->verbose) {
564 fprintf(stderr, "Connect reader '%s' matching '%s'.\n", reader_ptr, wanted);
565 }
566 rc = SCardConnect(state->context, reader_ptr, SCARD_SHARE_SHARED,
567 SCARD_PROTOCOL_T1, &card, &active_protocol);
568 if(rc == SCARD_S_SUCCESS)
569 {
570 break;
571 }
572 if(state->verbose) {
573 fprintf(stderr, "SCardConnect failed for '%s', rc=%lx\n", reader_ptr, (long)rc);
574 }
575 }
576
577 if(*reader_ptr == '\0') {
578 if(state->verbose) {
579 fprintf(stderr, "No usable reader found matching '%s'.\n", wanted);
580 }
581 SCardReleaseContext(state->context);
582 state->context = (SCARDCONTEXT)-1;
583 return YKPIV_PCSC_ERROR;
584 }
585 }
586
587 // at this point, card should not equal state->card, to allow _ykpiv_connect() to determine device type
588 if (YKPIV_OK == _ykpiv_connect(state, state->context, card)) {
589 /*
590 * Select applet. This is done here instead of in _ykpiv_connect() because
591 * you may not want to select the applet when connecting to a card handle that
592 * was supplied by an external library.
593 */
594 if (YKPIV_OK != (ret = _ykpiv_begin_transaction(state))) return ret;
595 #if ENABLE_APPLICATION_RESELECTION
596 ret = _ykpiv_ensure_application_selected(state);
597 #else
598 ret = _ykpiv_select_application(state);
599 #endif
600 _ykpiv_end_transaction(state);
601 return ret;
602 }
603
604 return YKPIV_GENERIC_ERROR;
605 }
606
ykpiv_list_readers(ykpiv_state * state,char * readers,size_t * len)607 ykpiv_rc ykpiv_list_readers(ykpiv_state *state, char *readers, size_t *len) {
608 pcsc_word num_readers = 0;
609 LONG rc;
610
611 if(SCardIsValidContext(state->context) != SCARD_S_SUCCESS) {
612 rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &state->context);
613 if (rc != SCARD_S_SUCCESS) {
614 if(state->verbose) {
615 fprintf (stderr, "SCardEstablishContext failed, rc=%lx\n", (long)rc);
616 }
617 return YKPIV_PCSC_ERROR;
618 }
619 }
620
621 rc = SCardListReaders(state->context, NULL, NULL, &num_readers);
622 if (rc != SCARD_S_SUCCESS) {
623 if(state->verbose) {
624 fprintf (stderr, "SCardListReaders failed, rc=%lx\n", (long)rc);
625 }
626 if(rc == SCARD_E_NO_READERS_AVAILABLE) {
627 *readers = 0;
628 *len = 1;
629 return YKPIV_OK;
630 }
631 SCardReleaseContext(state->context);
632 state->context = (SCARDCONTEXT)-1;
633 return YKPIV_PCSC_ERROR;
634 }
635
636 if (num_readers > *len) {
637 num_readers = (pcsc_word)*len;
638 } else if (num_readers < *len) {
639 *len = (size_t)num_readers;
640 }
641
642 rc = SCardListReaders(state->context, NULL, readers, &num_readers);
643 if (rc != SCARD_S_SUCCESS)
644 {
645 if(state->verbose) {
646 fprintf (stderr, "SCardListReaders failed, rc=%lx\n", (long)rc);
647 }
648 SCardReleaseContext(state->context);
649 state->context = (SCARDCONTEXT)-1;
650 return YKPIV_PCSC_ERROR;
651 }
652
653 *len = num_readers;
654
655 return YKPIV_OK;
656 }
657
_ykpiv_begin_transaction(ykpiv_state * state)658 ykpiv_rc _ykpiv_begin_transaction(ykpiv_state *state) {
659 #if ENABLE_IMPLICIT_TRANSACTIONS
660 LONG rc;
661 int retries = 0;
662 while((rc = SCardBeginTransaction(state->card)) == SCARD_W_RESET_CARD && retries < 5) {
663 retries++;
664 if(state->verbose) {
665 fprintf(stderr, "Reconnect card #%u attempt %d\n", state->serial, retries);
666 }
667 pcsc_word active_protocol = 0;
668 rc = SCardReconnect(state->card, SCARD_SHARE_SHARED,
669 SCARD_PROTOCOL_T1, SCARD_LEAVE_CARD, &active_protocol);
670 if(rc != SCARD_S_SUCCESS) {
671 if(state->verbose) {
672 fprintf(stderr, "SCardReconnect on card #%u failed, rc=%lx\n", state->serial, (long)rc);
673 }
674 return YKPIV_PCSC_ERROR;
675 }
676 }
677 if(rc != SCARD_S_SUCCESS) {
678 if(state->verbose) {
679 fprintf(stderr, "SCardBeginTransaction on card #%u failed after %d retries, rc=%lx\n", state->serial, retries, (long)rc);
680 }
681 return YKPIV_PCSC_ERROR;
682 }
683 if(retries) {
684 ykpiv_rc res;
685 if ((res = _ykpiv_select_application(state)) != YKPIV_OK)
686 return res;
687 if(state->mgm_key) {
688 if((res = _ykpiv_authenticate(state, state->mgm_key)) != YKPIV_OK)
689 return res;
690 }
691 if (state->pin) {
692 if((res = _ykpiv_verify(state, state->pin, strlen(state->pin))) != YKPIV_OK)
693 return res;
694 // De-authenticate always-authenticate keys by running an arbitrary command
695 unsigned char data[80] = {0};
696 unsigned long recv_len = sizeof(data);
697 if((res = _ykpiv_fetch_object(state, YKPIV_OBJ_DISCOVERY, data, &recv_len)) != YKPIV_OK)
698 return res;
699 }
700 }
701 #endif /* ENABLE_IMPLICIT_TRANSACTIONS */
702 return YKPIV_OK;
703 }
704
_ykpiv_end_transaction(ykpiv_state * state)705 ykpiv_rc _ykpiv_end_transaction(ykpiv_state *state) {
706 #if ENABLE_IMPLICIT_TRANSACTIONS
707 LONG rc = SCardEndTransaction(state->card, SCARD_LEAVE_CARD);
708 if(rc != SCARD_S_SUCCESS && state->verbose) {
709 fprintf(stderr, "SCardEndTransaction on card #%u failed, rc=%lx\n", state->serial, (long)rc);
710 // Ending the transaction can only fail because it's already ended - it's ended now either way so we don't fail here
711 }
712 #endif /* ENABLE_IMPLICIT_TRANSACTIONS */
713 return YKPIV_OK;
714 }
715
_ykpiv_transfer_data(ykpiv_state * state,const unsigned char * templ,const unsigned char * in_data,long in_len,unsigned char * out_data,unsigned long * out_len,int * sw)716 ykpiv_rc _ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ,
717 const unsigned char *in_data,
718 long in_len,
719 unsigned char *out_data,
720 unsigned long *out_len,
721 int *sw) {
722 const unsigned char *in_ptr = in_data;
723 unsigned long max_out = *out_len;
724 ykpiv_rc res;
725 *out_len = 0;
726
727 do {
728 size_t this_size = 0xff;
729 unsigned char data[261] = {0};
730 uint32_t recv_len = sizeof(data);
731 APDU apdu = {0};
732
733 memset(apdu.raw, 0, sizeof(apdu));
734 memcpy(apdu.raw, templ, 4);
735 if(in_ptr + 0xff < in_data + in_len) {
736 apdu.st.cla = 0x10;
737 } else {
738 this_size = (size_t)((in_data + in_len) - in_ptr);
739 }
740 if(state->verbose > 2) {
741 fprintf(stderr, "Going to send %lu bytes in this go.\n", (unsigned long)this_size);
742 }
743 apdu.st.lc = (unsigned char)this_size;
744 if(this_size)
745 memcpy(apdu.st.data, in_ptr, this_size);
746 res = _send_data(state, &apdu, data, &recv_len, sw);
747 if(res != YKPIV_OK) {
748 goto Cleanup;
749 } else if(*sw != SW_SUCCESS && *sw >> 8 != 0x61) {
750 goto Cleanup;
751 }
752 if(*out_len + recv_len - 2 > max_out) {
753 if(state->verbose) {
754 fprintf(stderr, "Output buffer to small, wanted to write %lu, max was %lu.\n", *out_len + recv_len - 2, max_out);
755 }
756 res = YKPIV_SIZE_ERROR;
757 goto Cleanup;
758 }
759 if(out_data) {
760 memcpy(out_data, data, recv_len - 2);
761 out_data += recv_len - 2;
762 *out_len += recv_len - 2;
763 }
764 in_ptr += this_size;
765 } while(in_ptr < in_data + in_len);
766 while(*sw >> 8 == 0x61) {
767 APDU apdu = {0};
768 unsigned char data[261] = {0};
769 uint32_t recv_len = sizeof(data);
770
771 if(state->verbose > 2) {
772 fprintf(stderr, "The card indicates there is %d bytes more data for us.\n", *sw & 0xff);
773 }
774
775 memset(apdu.raw, 0, sizeof(apdu));
776 apdu.st.ins = YKPIV_INS_GET_RESPONSE_APDU;
777 res = _send_data(state, &apdu, data, &recv_len, sw);
778 if(res != YKPIV_OK) {
779 goto Cleanup;
780 } else if(*sw != SW_SUCCESS && *sw >> 8 != 0x61) {
781 goto Cleanup;
782 }
783 if(*out_len + recv_len - 2 > max_out) {
784 if(state->verbose) {
785 fprintf(stderr, "Output buffer to small, wanted to write %lu, max was %lu.", *out_len + recv_len - 2, max_out);
786 }
787 res = YKPIV_SIZE_ERROR;
788 goto Cleanup;
789 }
790 if(out_data) {
791 memcpy(out_data, data, recv_len - 2);
792 out_data += recv_len - 2;
793 *out_len += recv_len - 2;
794 }
795 }
796 Cleanup:
797 return res;
798 }
799
ykpiv_transfer_data(ykpiv_state * state,const unsigned char * templ,const unsigned char * in_data,long in_len,unsigned char * out_data,unsigned long * out_len,int * sw)800 ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ,
801 const unsigned char *in_data, long in_len,
802 unsigned char *out_data, unsigned long *out_len, int *sw) {
803 ykpiv_rc res;
804
805 if ((res = _ykpiv_begin_transaction(state)) != YKPIV_OK) {
806 *out_len = 0;
807 return res;
808 }
809 res = _ykpiv_transfer_data(state, templ, in_data, in_len, out_data, out_len, sw);
810 _ykpiv_end_transaction(state);
811 return res;
812 }
813
_send_data(ykpiv_state * state,APDU * apdu,unsigned char * data,uint32_t * recv_len,int * sw)814 ykpiv_rc _send_data(ykpiv_state *state, APDU *apdu,
815 unsigned char *data, uint32_t *recv_len, int *sw) {
816 unsigned int send_len = (unsigned int)apdu->st.lc + 5;
817 pcsc_word tmp_len = *recv_len;
818
819 if(state->verbose > 1) {
820 fprintf(stderr, "> ");
821 dump_hex(apdu->raw, send_len);
822 fprintf(stderr, "\n");
823 }
824 LONG rc = SCardTransmit(state->card, SCARD_PCI_T1, apdu->raw, send_len, NULL, data, &tmp_len);
825 if(rc != SCARD_S_SUCCESS) {
826 if(state->verbose) {
827 fprintf (stderr, "SCardTransmit on card #%u failed, rc=%lx\n", state->serial, (long)rc);
828 }
829 return YKPIV_PCSC_ERROR;
830 }
831 *recv_len = (uint32_t)tmp_len;
832
833 if(state->verbose > 1) {
834 fprintf(stderr, "< ");
835 dump_hex(data, *recv_len);
836 fprintf(stderr, "\n");
837 }
838 if(*recv_len >= 2) {
839 *sw = (data[*recv_len - 2] << 8) | data[*recv_len - 1];
840 } else {
841 *sw = 0;
842 }
843 return YKPIV_OK;
844 }
845
ykpiv_authenticate(ykpiv_state * state,unsigned const char * key)846 ykpiv_rc ykpiv_authenticate(ykpiv_state *state, unsigned const char *key) {
847 ykpiv_rc res;
848 if (NULL == state) return YKPIV_GENERIC_ERROR;
849
850 if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return res;
851 if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;
852
853 res = _ykpiv_authenticate(state, key);
854
855 Cleanup:
856 _ykpiv_end_transaction(state);
857 return res;
858 }
859
_ykpiv_authenticate(ykpiv_state * state,unsigned const char * key)860 static ykpiv_rc _ykpiv_authenticate(ykpiv_state *state, unsigned const char *key) {
861 APDU apdu = {0};
862 unsigned char data[261] = {0};
863 unsigned char challenge[8] = {0};
864 uint32_t recv_len = sizeof(data);
865 int sw;
866 ykpiv_rc res;
867 des_rc drc = DES_OK;
868 des_key* mgm_key = NULL;
869 size_t out_len = 0;
870
871 if (NULL == state) return YKPIV_GENERIC_ERROR;
872
873 if (NULL == key) {
874 /* use the derived mgm key to authenticate, if it hasn't been derived, use default */
875 key = (unsigned const char*)YKPIV_MGM_DEFAULT;
876 }
877
878 /* set up our key */
879 if (DES_OK != des_import_key(DES_TYPE_3DES, key, CB_MGM_KEY, &mgm_key)) {
880 res = YKPIV_ALGORITHM_ERROR;
881 goto Cleanup;
882 }
883
884 /* get a challenge from the card */
885 {
886 memset(apdu.raw, 0, sizeof(apdu));
887 apdu.st.ins = YKPIV_INS_AUTHENTICATE;
888 apdu.st.p1 = YKPIV_ALGO_3DES; /* triple des */
889 apdu.st.p2 = YKPIV_KEY_CARDMGM; /* management key */
890 apdu.st.lc = 0x04;
891 apdu.st.data[0] = 0x7c;
892 apdu.st.data[1] = 0x02;
893 apdu.st.data[2] = 0x80;
894 if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) {
895 goto Cleanup;
896 }
897 else if (sw != SW_SUCCESS) {
898 res = YKPIV_AUTHENTICATION_ERROR;
899 goto Cleanup;
900 }
901 memcpy(challenge, data + 4, 8);
902 }
903
904 /* send a response to the cards challenge and a challenge of our own. */
905 {
906 unsigned char *dataptr = apdu.st.data;
907 unsigned char response[8] = {0};
908 out_len = sizeof(response);
909 drc = des_decrypt(mgm_key, challenge, sizeof(challenge), response, &out_len);
910
911 if (drc != DES_OK) {
912 res = YKPIV_AUTHENTICATION_ERROR;
913 goto Cleanup;
914 }
915
916 recv_len = sizeof(data);
917 memset(apdu.raw, 0, sizeof(apdu));
918 apdu.st.ins = YKPIV_INS_AUTHENTICATE;
919 apdu.st.p1 = YKPIV_ALGO_3DES; /* triple des */
920 apdu.st.p2 = YKPIV_KEY_CARDMGM; /* management key */
921 *dataptr++ = 0x7c;
922 *dataptr++ = 20; /* 2 + 8 + 2 +8 */
923 *dataptr++ = 0x80;
924 *dataptr++ = 8;
925 memcpy(dataptr, response, 8);
926 dataptr += 8;
927 *dataptr++ = 0x81;
928 *dataptr++ = 8;
929 if (PRNG_GENERAL_ERROR == _ykpiv_prng_generate(dataptr, 8)) {
930 if (state->verbose) {
931 fprintf(stderr, "Failed getting randomness for authentication.\n");
932 }
933 res = YKPIV_RANDOMNESS_ERROR;
934 goto Cleanup;
935 }
936 memcpy(challenge, dataptr, 8);
937 dataptr += 8;
938 apdu.st.lc = (unsigned char)(dataptr - apdu.st.data);
939 if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) {
940 goto Cleanup;
941 }
942 else if (sw != SW_SUCCESS) {
943 res = YKPIV_AUTHENTICATION_ERROR;
944 goto Cleanup;
945 }
946 }
947
948 /* compare the response from the card with our challenge */
949 {
950 unsigned char response[8] = {0};
951 out_len = sizeof(response);
952 drc = des_encrypt(mgm_key, challenge, sizeof(challenge), response, &out_len);
953
954 if (drc != DES_OK) {
955 res = YKPIV_AUTHENTICATION_ERROR;
956 goto Cleanup;
957 }
958
959 if (memcmp(response, data + 4, 8) == 0) {
960 _cache_mgm_key(state, key);
961 res = YKPIV_OK;
962 }
963 else {
964 res = YKPIV_AUTHENTICATION_ERROR;
965 }
966 }
967
968 Cleanup:
969
970 if (mgm_key) {
971 des_destroy_key(mgm_key);
972 }
973
974 return res;
975 }
976
ykpiv_set_mgmkey(ykpiv_state * state,const unsigned char * new_key)977 ykpiv_rc ykpiv_set_mgmkey(ykpiv_state *state, const unsigned char *new_key) {
978 return ykpiv_set_mgmkey2(state, new_key, 0);
979 }
980
ykpiv_set_mgmkey2(ykpiv_state * state,const unsigned char * new_key,const unsigned char touch)981 ykpiv_rc ykpiv_set_mgmkey2(ykpiv_state *state, const unsigned char *new_key, const unsigned char touch) {
982 APDU apdu = {0};
983 unsigned char data[261] = {0};
984 uint32_t recv_len = sizeof(data);
985 int sw;
986 ykpiv_rc res = YKPIV_OK;
987
988 if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return res;
989 if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;
990
991 if (yk_des_is_weak_key(new_key, DES_LEN_3DES)) {
992 if (state->verbose) {
993 fprintf(stderr, "Won't set new key '");
994 dump_hex(new_key, DES_LEN_3DES);
995 fprintf(stderr, "' since it's weak (with odd parity).\n");
996 }
997 res = YKPIV_KEY_ERROR;
998 goto Cleanup;
999 }
1000
1001 memset(apdu.raw, 0, sizeof(apdu));
1002 apdu.st.ins = YKPIV_INS_SET_MGMKEY;
1003 apdu.st.p1 = 0xff;
1004 if (touch == 0) {
1005 apdu.st.p2 = 0xff;
1006 }
1007 else if (touch == 1) {
1008 apdu.st.p2 = 0xfe;
1009 }
1010 else {
1011 res = YKPIV_GENERIC_ERROR;
1012 goto Cleanup;
1013 }
1014
1015 apdu.st.lc = DES_LEN_3DES + 3;
1016 apdu.st.data[0] = YKPIV_ALGO_3DES;
1017 apdu.st.data[1] = YKPIV_KEY_CARDMGM;
1018 apdu.st.data[2] = DES_LEN_3DES;
1019 memcpy(apdu.st.data + 3, new_key, DES_LEN_3DES);
1020
1021 if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) {
1022 goto Cleanup;
1023 }
1024 else if (sw == SW_SUCCESS) {
1025 _cache_mgm_key(state, new_key);
1026 goto Cleanup;
1027 }
1028 res = YKPIV_GENERIC_ERROR;
1029
1030 Cleanup:
1031 yc_memzero(&apdu, sizeof(APDU));
1032 _ykpiv_end_transaction(state);
1033 return res;
1034 }
1035
1036 static char hex_translate[] = "0123456789abcdef";
1037
ykpiv_hex_decode(const char * hex_in,size_t in_len,unsigned char * hex_out,size_t * out_len)1038 ykpiv_rc ykpiv_hex_decode(const char *hex_in, size_t in_len,
1039 unsigned char *hex_out, size_t *out_len) {
1040
1041 size_t i;
1042 bool first = true;
1043 if(*out_len < in_len / 2) {
1044 return YKPIV_SIZE_ERROR;
1045 } else if(in_len % 2 != 0) {
1046 return YKPIV_SIZE_ERROR;
1047 }
1048 *out_len = in_len / 2;
1049 for(i = 0; i < in_len; i++) {
1050 char *ind_ptr = strchr(hex_translate, tolower(*hex_in++));
1051 int index = 0;
1052 if(ind_ptr) {
1053 index = (int)(ind_ptr - hex_translate);
1054 } else {
1055 return YKPIV_PARSE_ERROR;
1056 }
1057 if(first) {
1058 *hex_out = index << 4;
1059 } else {
1060 *hex_out++ |= index;
1061 }
1062 first = !first;
1063 }
1064 return YKPIV_OK;
1065 }
1066
_general_authenticate(ykpiv_state * state,const unsigned char * sign_in,size_t in_len,unsigned char * out,size_t * out_len,unsigned char algorithm,unsigned char key,bool decipher)1067 static ykpiv_rc _general_authenticate(ykpiv_state *state,
1068 const unsigned char *sign_in, size_t in_len,
1069 unsigned char *out, size_t *out_len,
1070 unsigned char algorithm, unsigned char key, bool decipher) {
1071 unsigned char indata[1024] = {0};
1072 unsigned char *dataptr = indata;
1073 unsigned char data[1024] = {0};
1074 unsigned char templ[] = {0, YKPIV_INS_AUTHENTICATE, algorithm, key};
1075 unsigned long recv_len = sizeof(data);
1076 size_t key_len = 0;
1077 int sw = 0;
1078 size_t bytes, offs;
1079 size_t len = 0;
1080 ykpiv_rc res;
1081
1082 switch(algorithm) {
1083 case YKPIV_ALGO_RSA1024:
1084 key_len = 128;
1085 // fall through
1086 case YKPIV_ALGO_RSA2048:
1087 if(key_len == 0) {
1088 key_len = 256;
1089 }
1090 if(in_len != key_len) {
1091 return YKPIV_SIZE_ERROR;
1092 }
1093 break;
1094 case YKPIV_ALGO_ECCP256:
1095 key_len = 32;
1096 // fall through
1097 case YKPIV_ALGO_ECCP384:
1098 if(key_len == 0) {
1099 key_len = 48;
1100 }
1101 if(!decipher && in_len > key_len) {
1102 return YKPIV_SIZE_ERROR;
1103 } else if(decipher && in_len != (key_len * 2) + 1) {
1104 return YKPIV_SIZE_ERROR;
1105 }
1106 break;
1107 default:
1108 return YKPIV_ALGORITHM_ERROR;
1109 }
1110
1111 bytes = _ykpiv_get_length_size(in_len);
1112
1113 *dataptr++ = 0x7c;
1114 dataptr += _ykpiv_set_length(dataptr, in_len + bytes + 3);
1115 *dataptr++ = 0x82;
1116 *dataptr++ = 0x00;
1117 *dataptr++ = YKPIV_IS_EC(algorithm) && decipher ? 0x85 : 0x81;
1118 dataptr += _ykpiv_set_length(dataptr, in_len);
1119 memcpy(dataptr, sign_in, in_len);
1120 dataptr += in_len;
1121
1122 if((res = _ykpiv_transfer_data(state, templ, indata, (long)(dataptr - indata), data, &recv_len, &sw)) != YKPIV_OK) {
1123 if(state->verbose) {
1124 fprintf(stderr, "Sign command failed to communicate with status %x.\n", res);
1125 }
1126 return res;
1127 } else if(sw != SW_SUCCESS) {
1128 if(state->verbose) {
1129 fprintf(stderr, "Sign command failed with code %x.\n", sw);
1130 }
1131 if (sw == SW_ERR_SECURITY_STATUS)
1132 return YKPIV_AUTHENTICATION_ERROR;
1133 else if(sw != SW_SUCCESS)
1134 return YKPIV_GENERIC_ERROR;
1135 }
1136 /* skip the first 7c tag */
1137 if(data[0] != 0x7c) {
1138 if(state->verbose) {
1139 fprintf(stderr, "Failed parsing signature reply.\n");
1140 }
1141 return YKPIV_PARSE_ERROR;
1142 }
1143 dataptr = data + 1;
1144 offs = _ykpiv_get_length(dataptr, data + recv_len, &len);
1145 dataptr += offs;
1146 /* skip the 82 tag */
1147 if(!offs || *dataptr != 0x82) {
1148 if(state->verbose) {
1149 fprintf(stderr, "Failed parsing signature reply.\n");
1150 }
1151 return YKPIV_PARSE_ERROR;
1152 }
1153 dataptr++;
1154 offs = _ykpiv_get_length(dataptr, data + recv_len, &len);
1155 dataptr += offs;
1156 if(!offs || len > *out_len) {
1157 if(state->verbose) {
1158 fprintf(stderr, "Wrong size on output buffer.\n");
1159 }
1160 return YKPIV_PARSE_ERROR;
1161 }
1162 *out_len = len;
1163 memcpy(out, dataptr, len);
1164 return YKPIV_OK;
1165 }
1166
ykpiv_sign_data(ykpiv_state * state,const unsigned char * raw_in,size_t in_len,unsigned char * sign_out,size_t * out_len,unsigned char algorithm,unsigned char key)1167 ykpiv_rc ykpiv_sign_data(ykpiv_state *state,
1168 const unsigned char *raw_in, size_t in_len,
1169 unsigned char *sign_out, size_t *out_len,
1170 unsigned char algorithm, unsigned char key) {
1171 ykpiv_rc res = YKPIV_OK;
1172
1173 if (NULL == state) return YKPIV_GENERIC_ERROR;
1174
1175 if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return res;
1176 /* don't attempt to reselect in crypt operations to avoid problems with PIN_ALWAYS */
1177 /*if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;*/
1178
1179 res = _general_authenticate(state, raw_in, in_len, sign_out, out_len,
1180 algorithm, key, false);
1181 /* Cleanup: */
1182 _ykpiv_end_transaction(state);
1183 return res;
1184 }
1185
ykpiv_decipher_data(ykpiv_state * state,const unsigned char * in,size_t in_len,unsigned char * out,size_t * out_len,unsigned char algorithm,unsigned char key)1186 ykpiv_rc ykpiv_decipher_data(ykpiv_state *state, const unsigned char *in,
1187 size_t in_len, unsigned char *out, size_t *out_len,
1188 unsigned char algorithm, unsigned char key) {
1189 ykpiv_rc res = YKPIV_OK;
1190
1191 if (NULL == state) return YKPIV_GENERIC_ERROR;
1192
1193 if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return res;
1194 /* don't attempt to reselect in crypt operations to avoid problems with PIN_ALWAYS */
1195 /*if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;*/
1196
1197 res = _general_authenticate(state, in, in_len, out, out_len,
1198 algorithm, key, true);
1199
1200 /* Cleanup: */
1201
1202 _ykpiv_end_transaction(state);
1203 return res;
1204 }
1205
_ykpiv_get_version(ykpiv_state * state)1206 static ykpiv_rc _ykpiv_get_version(ykpiv_state *state) {
1207 APDU apdu = {0};
1208 unsigned char data[261] = {0};
1209 uint32_t recv_len = sizeof(data);
1210 int sw;
1211 ykpiv_rc res;
1212
1213 if (!state) {
1214 return YKPIV_ARGUMENT_ERROR;
1215 }
1216
1217 /* get version from state if already retrieved from device */
1218 if (state->ver.major || state->ver.minor || state->ver.patch) {
1219 return YKPIV_OK;
1220 }
1221
1222 /* get version from device */
1223
1224 memset(apdu.raw, 0, sizeof(apdu));
1225 apdu.st.ins = YKPIV_INS_GET_VERSION;
1226 if((res = _send_data(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) {
1227 return res;
1228 } else if(sw == SW_SUCCESS) {
1229
1230 /* check that we received enough data for the verson number */
1231 if (recv_len < 3) {
1232 return YKPIV_SIZE_ERROR;
1233 }
1234
1235 state->ver.major = data[0];
1236 state->ver.minor = data[1];
1237 state->ver.patch = data[2];
1238 } else {
1239 res = YKPIV_GENERIC_ERROR;
1240 }
1241
1242 return res;
1243 }
1244
ykpiv_get_version(ykpiv_state * state,char * version,size_t len)1245 ykpiv_rc ykpiv_get_version(ykpiv_state *state, char *version, size_t len) {
1246 ykpiv_rc res;
1247
1248 if ((res = _ykpiv_begin_transaction(state)) < YKPIV_OK) return res;
1249 if ((res = _ykpiv_ensure_application_selected(state)) < YKPIV_OK) goto Cleanup;
1250
1251 if ((res = _ykpiv_get_version(state)) >= YKPIV_OK) {
1252 int result = snprintf(version, len, "%d.%d.%d", state->ver.major, state->ver.minor, state->ver.patch);
1253 if(result < 0 || result >= (int)len) {
1254 res = YKPIV_SIZE_ERROR;
1255 }
1256 }
1257
1258 Cleanup:
1259
1260 _ykpiv_end_transaction(state);
1261 return res;
1262 }
1263
1264 /* caller must make sure that this is wrapped in a transaction for synchronized operation */
_ykpiv_get_serial(ykpiv_state * state)1265 static ykpiv_rc _ykpiv_get_serial(ykpiv_state *state) {
1266 ykpiv_rc res = YKPIV_OK;
1267 APDU apdu = {0};
1268 uint8_t data[0xff] = {0};
1269 uint32_t recv_len = sizeof(data);
1270 int sw;
1271
1272 if (!state) {
1273 return YKPIV_ARGUMENT_ERROR;
1274 }
1275
1276 /* get serial from state if already retrieved from device */
1277 if (state->serial != 0) {
1278 return YKPIV_OK;
1279 }
1280
1281 if (state->ver.major < 5) {
1282 /* get serial from neo/yk4 devices using the otp applet */
1283 uint8_t temp[0xff] = {0};
1284
1285 recv_len = sizeof(temp);
1286 memset(apdu.raw, 0, sizeof(apdu));
1287 apdu.st.ins = YKPIV_INS_SELECT_APPLICATION;
1288 apdu.st.p1 = 0x04;
1289 apdu.st.lc = sizeof(yk_aid);
1290 memcpy(apdu.st.data, yk_aid, sizeof(yk_aid));
1291
1292 if ((res = _send_data(state, &apdu, temp, &recv_len, &sw)) < YKPIV_OK) {
1293 if (state->verbose) {
1294 fprintf(stderr, "Failed communicating with card: '%s'\n", ykpiv_strerror(res));
1295 }
1296 goto Cleanup;
1297 }
1298 else if (sw != SW_SUCCESS) {
1299 if (state->verbose) {
1300 fprintf(stderr, "Failed selecting yk application: %04x\n", sw);
1301 }
1302 res = YKPIV_GENERIC_ERROR;
1303 goto Cleanup;
1304 }
1305
1306 recv_len = sizeof(data);
1307 memset(apdu.raw, 0, sizeof(apdu));
1308 apdu.st.ins = 0x01;
1309 apdu.st.p1 = 0x10;
1310 apdu.st.lc = 0x00;
1311
1312 if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) < YKPIV_OK) {
1313 if (state->verbose) {
1314 fprintf(stderr, "Failed communicating with card: '%s'\n", ykpiv_strerror(res));
1315 }
1316 goto Cleanup;
1317 }
1318 else if (sw != SW_SUCCESS) {
1319 if (state->verbose) {
1320 fprintf(stderr, "Failed retrieving serial number: %04x\n", sw);
1321 }
1322 res = YKPIV_GENERIC_ERROR;
1323 goto Cleanup;
1324 }
1325
1326 recv_len = sizeof(temp);
1327 memset(apdu.raw, 0, sizeof(apdu));
1328 apdu.st.ins = YKPIV_INS_SELECT_APPLICATION;
1329 apdu.st.p1 = 0x04;
1330 apdu.st.lc = sizeof(piv_aid);
1331 memcpy(apdu.st.data, piv_aid, sizeof(piv_aid));
1332
1333 if((res = _send_data(state, &apdu, temp, &recv_len, &sw)) < YKPIV_OK) {
1334 if(state->verbose) {
1335 fprintf(stderr, "Failed communicating with card: '%s'\n", ykpiv_strerror(res));
1336 }
1337 return res;
1338 }
1339 else if(sw != SW_SUCCESS) {
1340 if(state->verbose) {
1341 fprintf(stderr, "Failed selecting application: %04x\n", sw);
1342 }
1343 return YKPIV_GENERIC_ERROR;
1344 }
1345 }
1346 else {
1347 /* get serial from yk5 and later devices using the f8 command */
1348
1349 memset(apdu.raw, 0, sizeof(apdu));
1350 apdu.st.ins = YKPIV_INS_GET_SERIAL;
1351
1352 if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) {
1353 if(state->verbose) {
1354 fprintf(stderr, "Failed communicating with card: '%s'\n", ykpiv_strerror(res));
1355 }
1356 return res;
1357 }
1358 else if(sw != SW_SUCCESS) {
1359 if(state->verbose) {
1360 fprintf(stderr, "Failed retrieving serial number: %04x\n", sw);
1361 }
1362 return YKPIV_GENERIC_ERROR;
1363 }
1364 }
1365
1366 /* check that we received enough data for the serial number */
1367 if (recv_len < 4) {
1368 return YKPIV_SIZE_ERROR;
1369 }
1370
1371 state->serial = data[0];
1372 state->serial <<= 8;
1373 state->serial += data[1];
1374 state->serial <<= 8;
1375 state->serial += data[2];
1376 state->serial <<= 8;
1377 state->serial += data[3];
1378
1379 Cleanup:
1380
1381 return res;
1382 }
1383
ykpiv_get_serial(ykpiv_state * state,uint32_t * p_serial)1384 ykpiv_rc ykpiv_get_serial(ykpiv_state *state, uint32_t *p_serial) {
1385 ykpiv_rc res = YKPIV_OK;
1386
1387 if (!state || !p_serial) return YKPIV_ARGUMENT_ERROR;
1388
1389 if ((res = _ykpiv_begin_transaction(state)) != YKPIV_OK) return res;
1390 if ((res = _ykpiv_ensure_application_selected(state)) != YKPIV_OK) goto Cleanup;
1391
1392 res = _ykpiv_get_serial(state);
1393 *p_serial = state->serial;
1394
1395 Cleanup:
1396
1397 _ykpiv_end_transaction(state);
1398 return res;
1399 }
1400
_cache_pin(ykpiv_state * state,const char * pin,size_t len)1401 static ykpiv_rc _cache_pin(ykpiv_state *state, const char *pin, size_t len) {
1402 #if DISABLE_PIN_CACHE
1403 // Some embedded applications of this library may not want to keep the PIN
1404 // data in RAM for security reasons.
1405 return YKPIV_OK;
1406 #else
1407 if (!state)
1408 return YKPIV_ARGUMENT_ERROR;
1409 if (pin && state->pin == pin) {
1410 return YKPIV_OK;
1411 }
1412 if (state->pin) {
1413 yc_memzero(state->pin, strnlen(state->pin, CB_PIN_MAX));
1414 _ykpiv_free(state, state->pin);
1415 state->pin = NULL;
1416 }
1417 if (pin && len > 0) {
1418 state->pin = _ykpiv_alloc(state, len * sizeof(char) + 1);
1419 if (state->pin == NULL) {
1420 return YKPIV_MEMORY_ERROR;
1421 }
1422 memcpy(state->pin, pin, len);
1423 state->pin[len] = 0;
1424 }
1425 return YKPIV_OK;
1426 #endif
1427 }
1428
_cache_mgm_key(ykpiv_state * state,unsigned const char * key)1429 static ykpiv_rc _cache_mgm_key(ykpiv_state *state, unsigned const char *key) {
1430 #if DISABLE_MGM_KEY_CACHE
1431 // Some embedded applications of this library may not want to keep the MGM_KEY
1432 // data in RAM for security reasons.
1433 return YKPIV_OK;
1434 #else
1435 if (!state)
1436 return YKPIV_ARGUMENT_ERROR;
1437 if (key && state->mgm_key == key) {
1438 return YKPIV_OK;
1439 }
1440 if (state->mgm_key) {
1441 yc_memzero(state->mgm_key, CB_MGM_KEY);
1442 _ykpiv_free(state, state->mgm_key);
1443 state->mgm_key = NULL;
1444 }
1445 if (key) {
1446 state->mgm_key = _ykpiv_alloc(state, CB_MGM_KEY);
1447 if (state->mgm_key == NULL) {
1448 return YKPIV_MEMORY_ERROR;
1449 }
1450 memcpy(state->mgm_key, key, CB_MGM_KEY);
1451 }
1452 return YKPIV_OK;
1453 #endif
1454 }
1455
_ykpiv_verify(ykpiv_state * state,const char * pin,const size_t pin_len)1456 static ykpiv_rc _ykpiv_verify(ykpiv_state *state, const char *pin, const size_t pin_len) {
1457 APDU apdu = {0};
1458 unsigned char data[261] = {0};
1459 uint32_t recv_len = sizeof(data);
1460 int sw;
1461 ykpiv_rc res;
1462
1463 if (pin_len > CB_PIN_MAX) {
1464 state->tries = -1;
1465 return YKPIV_SIZE_ERROR;
1466 }
1467
1468 memset(apdu.raw, 0, sizeof(apdu));
1469 apdu.st.ins = YKPIV_INS_VERIFY;
1470 apdu.st.p1 = 0x00;
1471 apdu.st.p2 = 0x80;
1472 apdu.st.lc = pin ? 0x08 : 0;
1473 if (pin) {
1474 memcpy(apdu.st.data, pin, pin_len);
1475 if (pin_len < CB_PIN_MAX) {
1476 memset(apdu.st.data + pin_len, 0xff, CB_PIN_MAX - pin_len);
1477 }
1478 }
1479
1480 res = _send_data(state, &apdu, data, &recv_len, &sw);
1481 yc_memzero(&apdu, sizeof(apdu));
1482
1483 if (res != YKPIV_OK) {
1484 state->tries = -1;
1485 return res;
1486 }
1487 else if (sw == SW_SUCCESS) {
1488 if (pin) {
1489 // Intentionally ignore errors. If the PIN fails to save, it will only
1490 // be a problem if a reconnect is attempted. Failure deferred until then.
1491 _cache_pin(state, pin, pin_len);
1492 }
1493 state->tries = -1;
1494 return YKPIV_OK;
1495 }
1496 else if ((sw >> 8) == 0x63) {
1497 if(pin)
1498 _cache_pin(state, NULL, 0);
1499 state->tries = (sw & 0xf);
1500 return YKPIV_WRONG_PIN;
1501 }
1502 else if (sw == SW_ERR_AUTH_BLOCKED) {
1503 if(pin)
1504 _cache_pin(state, NULL, 0);
1505 state->tries = 0;
1506 return YKPIV_PIN_LOCKED;
1507 }
1508 else {
1509 state->tries = -1;
1510 return YKPIV_GENERIC_ERROR;
1511 }
1512 }
1513
ykpiv_verify(ykpiv_state * state,const char * pin,int * tries)1514 ykpiv_rc ykpiv_verify(ykpiv_state *state, const char *pin, int *tries) {
1515 return ykpiv_verify_select(state, pin, pin ? strlen(pin) : 0, tries, false);
1516 }
1517
ykpiv_verify_select(ykpiv_state * state,const char * pin,const size_t pin_len,int * tries,bool force_select)1518 ykpiv_rc ykpiv_verify_select(ykpiv_state *state, const char *pin, const size_t pin_len, int *tries, bool force_select) {
1519 ykpiv_rc res = YKPIV_OK;
1520 if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return res;
1521 if (force_select) {
1522 if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;
1523 }
1524 res = _ykpiv_verify(state, pin, pin_len);
1525 if(tries) *tries = state->tries;
1526 Cleanup:
1527
1528 _ykpiv_end_transaction(state);
1529 return res;
1530 }
1531
ykpiv_get_pin_retries(ykpiv_state * state,int * tries)1532 ykpiv_rc ykpiv_get_pin_retries(ykpiv_state *state, int *tries) {
1533 ykpiv_rc res;
1534
1535 if (NULL == state || NULL == tries) {
1536 return YKPIV_ARGUMENT_ERROR;
1537 }
1538
1539 // Just get the stored value if we get the magic flag
1540 if(*tries == YKPIV_RETRIES_MAX) {
1541 *tries = state->tries;
1542 return YKPIV_OK;
1543 }
1544
1545 if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return res;
1546
1547 // Force a re-select to unverify, because once verified the spec dictates that
1548 // subsequent verify calls will return a "verification not needed" instead of
1549 // the number of tries left...
1550
1551 res = _ykpiv_auth_deauthenticate(state);
1552 if (res != YKPIV_OK) goto Cleanup;
1553 res = _ykpiv_select_application(state);
1554 if (res != YKPIV_OK) goto Cleanup;
1555 res = _ykpiv_verify(state, NULL, 0);
1556 // WRONG_PIN or PIN_LOCKED is expected on successful query.
1557 *tries = state->tries;
1558 Cleanup:
1559 _ykpiv_end_transaction(state);
1560 return (res == YKPIV_WRONG_PIN || res == YKPIV_PIN_LOCKED) ? YKPIV_OK : res;
1561 }
1562
ykpiv_set_pin_retries(ykpiv_state * state,int pin_tries,int puk_tries)1563 ykpiv_rc ykpiv_set_pin_retries(ykpiv_state *state, int pin_tries, int puk_tries) {
1564 ykpiv_rc res = YKPIV_OK;
1565 unsigned char templ[] = {0, YKPIV_INS_SET_PIN_RETRIES, 0, 0};
1566 unsigned char data[0xff] = {0};
1567 unsigned long recv_len = sizeof(data);
1568 int sw = 0;
1569
1570 // Special case: if either retry count is 0, it's a successful no-op
1571 if (pin_tries == 0 || puk_tries == 0) {
1572 return YKPIV_OK;
1573 }
1574
1575 if (pin_tries > 0xff || puk_tries > 0xff || pin_tries < 1 || puk_tries < 1) {
1576 return YKPIV_RANGE_ERROR;
1577 }
1578
1579 templ[2] = (unsigned char)pin_tries;
1580 templ[3] = (unsigned char)puk_tries;
1581
1582 if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return res;
1583 if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;
1584
1585 res = _ykpiv_transfer_data(state, templ, NULL, 0, data, &recv_len, &sw);
1586 if (YKPIV_OK == res) {
1587 if (SW_SUCCESS == sw) {
1588 // success, fall through
1589 } else if (sw == SW_ERR_AUTH_BLOCKED) {
1590 res = YKPIV_AUTHENTICATION_ERROR;
1591 } else if (sw == SW_ERR_SECURITY_STATUS) {
1592 res = YKPIV_AUTHENTICATION_ERROR;
1593 } else {
1594 res = YKPIV_GENERIC_ERROR;
1595 }
1596 }
1597
1598 Cleanup:
1599 _ykpiv_end_transaction(state);
1600 return res;
1601 }
1602
_ykpiv_change_pin(ykpiv_state * state,int action,const char * current_pin,size_t current_pin_len,const char * new_pin,size_t new_pin_len,int * tries)1603 static ykpiv_rc _ykpiv_change_pin(ykpiv_state *state, int action, const char * current_pin, size_t current_pin_len, const char * new_pin, size_t new_pin_len, int *tries) {
1604 int sw;
1605 unsigned char templ[] = {0, YKPIV_INS_CHANGE_REFERENCE, 0, 0x80};
1606 unsigned char indata[0x10] = {0};
1607 unsigned char data[0xff] = {0};
1608 unsigned long recv_len = sizeof(data);
1609 ykpiv_rc res;
1610 if (current_pin_len > CB_PIN_MAX) {
1611 return YKPIV_SIZE_ERROR;
1612 }
1613 if (new_pin_len > CB_PIN_MAX) {
1614 return YKPIV_SIZE_ERROR;
1615 }
1616 if(action == CHREF_ACT_UNBLOCK_PIN) {
1617 templ[1] = YKPIV_INS_RESET_RETRY;
1618 }
1619 else if(action == CHREF_ACT_CHANGE_PUK) {
1620 templ[3] = 0x81;
1621 }
1622 memcpy(indata, current_pin, current_pin_len);
1623 if(current_pin_len < CB_PIN_MAX) {
1624 memset(indata + current_pin_len, 0xff, CB_PIN_MAX - current_pin_len);
1625 }
1626 memcpy(indata + CB_PIN_MAX, new_pin, new_pin_len);
1627 if(new_pin_len < CB_PIN_MAX) {
1628 memset(indata + CB_PIN_MAX + new_pin_len, 0xff, CB_PIN_MAX - new_pin_len);
1629 }
1630
1631 res = _ykpiv_transfer_data(state, templ, indata, sizeof(indata), data, &recv_len, &sw);
1632 yc_memzero(indata, sizeof(indata));
1633
1634 if(res != YKPIV_OK) {
1635 return res;
1636 } else if(sw != SW_SUCCESS) {
1637 if((sw >> 8) == 0x63) {
1638 if (tries) *tries = sw & 0xf;
1639 return YKPIV_WRONG_PIN;
1640 } else if(sw == SW_ERR_AUTH_BLOCKED) {
1641 return YKPIV_PIN_LOCKED;
1642 } else {
1643 if(state->verbose) {
1644 fprintf(stderr, "Failed changing pin, token response code: %x.\n", sw);
1645 }
1646 return YKPIV_GENERIC_ERROR;
1647 }
1648 }
1649 return YKPIV_OK;
1650 }
1651
ykpiv_change_pin(ykpiv_state * state,const char * current_pin,size_t current_pin_len,const char * new_pin,size_t new_pin_len,int * tries)1652 ykpiv_rc ykpiv_change_pin(ykpiv_state *state, const char * current_pin, size_t current_pin_len, const char * new_pin, size_t new_pin_len, int *tries) {
1653 ykpiv_rc res = YKPIV_GENERIC_ERROR;
1654
1655 if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return res;
1656 if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;
1657
1658 res = _ykpiv_change_pin(state, CHREF_ACT_CHANGE_PIN, current_pin, current_pin_len, new_pin, new_pin_len, tries);
1659 if (res == YKPIV_OK && new_pin != NULL) {
1660 // Intentionally ignore errors. If the PIN fails to save, it will only
1661 // be a problem if a reconnect is attempted. Failure deferred until then.
1662 _cache_pin(state, new_pin, new_pin_len);
1663 }
1664
1665 Cleanup:
1666 _ykpiv_end_transaction(state);
1667 return res;
1668 }
1669
ykpiv_change_puk(ykpiv_state * state,const char * current_puk,size_t current_puk_len,const char * new_puk,size_t new_puk_len,int * tries)1670 ykpiv_rc ykpiv_change_puk(ykpiv_state *state, const char * current_puk, size_t current_puk_len, const char * new_puk, size_t new_puk_len, int *tries) {
1671 ykpiv_rc res = YKPIV_GENERIC_ERROR;
1672
1673 if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return res;
1674 if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;
1675
1676 res = _ykpiv_change_pin(state, CHREF_ACT_CHANGE_PUK, current_puk, current_puk_len, new_puk, new_puk_len, tries);
1677
1678 Cleanup:
1679 _ykpiv_end_transaction(state);
1680 return res;
1681 }
1682
ykpiv_unblock_pin(ykpiv_state * state,const char * puk,size_t puk_len,const char * new_pin,size_t new_pin_len,int * tries)1683 ykpiv_rc ykpiv_unblock_pin(ykpiv_state *state, const char * puk, size_t puk_len, const char * new_pin, size_t new_pin_len, int *tries) {
1684 ykpiv_rc res = YKPIV_GENERIC_ERROR;
1685
1686 if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return res;
1687 if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;
1688
1689 res = _ykpiv_change_pin(state, CHREF_ACT_UNBLOCK_PIN, puk, puk_len, new_pin, new_pin_len, tries);
1690
1691 Cleanup:
1692 _ykpiv_end_transaction(state);
1693 return res;
1694 }
1695
ykpiv_fetch_object(ykpiv_state * state,int object_id,unsigned char * data,unsigned long * len)1696 ykpiv_rc ykpiv_fetch_object(ykpiv_state *state, int object_id,
1697 unsigned char *data, unsigned long *len) {
1698 ykpiv_rc res;
1699
1700 if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return res;
1701 if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;
1702
1703 res = _ykpiv_fetch_object(state, object_id, data, len);
1704
1705 Cleanup:
1706 _ykpiv_end_transaction(state);
1707 return res;
1708 }
1709
_ykpiv_fetch_object(ykpiv_state * state,int object_id,unsigned char * data,unsigned long * len)1710 ykpiv_rc _ykpiv_fetch_object(ykpiv_state *state, int object_id,
1711 unsigned char *data, unsigned long *len) {
1712 int sw;
1713 unsigned char indata[5] = {0};
1714 unsigned char *inptr = indata;
1715 unsigned char templ[] = {0, YKPIV_INS_GET_DATA, 0x3f, 0xff};
1716 ykpiv_rc res;
1717
1718 inptr = set_object(object_id, inptr);
1719 if(inptr == NULL) {
1720 return YKPIV_INVALID_OBJECT;
1721 }
1722
1723 if((res = _ykpiv_transfer_data(state, templ, indata, (long)(inptr - indata), data, len, &sw))
1724 != YKPIV_OK) {
1725 return res;
1726 }
1727
1728 if(sw == SW_SUCCESS) {
1729 size_t outlen = 0;
1730 size_t offs = _ykpiv_get_length(data + 1, data + *len, &outlen);
1731 if(!offs) {
1732 return YKPIV_PARSE_ERROR;
1733 }
1734 if(outlen + offs + 1 != *len) {
1735 if(state->verbose) {
1736 fprintf(stderr, "Invalid length indicated in object, total objlen is %lu, indicated length is %lu.", *len, (unsigned long)outlen);
1737 }
1738 return YKPIV_SIZE_ERROR;
1739 }
1740 memmove(data, data + 1 + offs, outlen);
1741 *len = (unsigned long)outlen;
1742 return YKPIV_OK;
1743 } else {
1744 if (SW_ERR_FILE_NOT_FOUND == sw) {
1745 return YKPIV_INVALID_OBJECT;
1746 }
1747 if (SW_ERR_SECURITY_STATUS == sw) {
1748 return YKPIV_AUTHENTICATION_ERROR;
1749 }
1750 if(state->verbose) {
1751 fprintf(stderr, "Failed to get data for object %x with status %x\n", object_id, sw);
1752 }
1753 return YKPIV_GENERIC_ERROR;
1754 }
1755 }
1756
ykpiv_save_object(ykpiv_state * state,int object_id,unsigned char * indata,size_t len)1757 ykpiv_rc ykpiv_save_object(ykpiv_state *state, int object_id,
1758 unsigned char *indata, size_t len) {
1759 ykpiv_rc res;
1760
1761 if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return res;
1762 if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;
1763
1764 res = _ykpiv_save_object(state, object_id, indata, len);
1765
1766 Cleanup:
1767 _ykpiv_end_transaction(state);
1768 return res;
1769 }
1770
_ykpiv_save_object(ykpiv_state * state,int object_id,unsigned char * indata,size_t len)1771 ykpiv_rc _ykpiv_save_object(
1772 ykpiv_state *state,
1773 int object_id,
1774 unsigned char *indata,
1775 size_t len) {
1776 unsigned char data[CB_BUF_MAX] = {0};
1777 unsigned char *dataptr = data;
1778 unsigned char templ[] = {0, YKPIV_INS_PUT_DATA, 0x3f, 0xff};
1779 int sw;
1780 ykpiv_rc res;
1781 unsigned long outlen = 0;
1782
1783 if(len > sizeof(data) - 9) {
1784 return YKPIV_SIZE_ERROR;
1785 }
1786 dataptr = set_object(object_id, dataptr);
1787 if(dataptr == NULL) {
1788 return YKPIV_INVALID_OBJECT;
1789 }
1790 *dataptr++ = 0x53;
1791 dataptr += _ykpiv_set_length(dataptr, len);
1792 if(indata)
1793 memcpy(dataptr, indata, len);
1794 dataptr += len;
1795
1796 if((res = _ykpiv_transfer_data(state, templ, data, (long)(dataptr - data), NULL, &outlen,
1797 &sw)) != YKPIV_OK) {
1798 return res;
1799 }
1800
1801 if(SW_SUCCESS == sw) {
1802 return YKPIV_OK;
1803 }
1804 else if (SW_ERR_SECURITY_STATUS == sw) {
1805 return YKPIV_AUTHENTICATION_ERROR;
1806 }
1807 else {
1808 return YKPIV_GENERIC_ERROR;
1809 }
1810 }
1811
ykpiv_import_private_key(ykpiv_state * state,const unsigned char key,unsigned char algorithm,const unsigned char * p,size_t p_len,const unsigned char * q,size_t q_len,const unsigned char * dp,size_t dp_len,const unsigned char * dq,size_t dq_len,const unsigned char * qinv,size_t qinv_len,const unsigned char * ec_data,unsigned char ec_data_len,const unsigned char pin_policy,const unsigned char touch_policy)1812 ykpiv_rc ykpiv_import_private_key(ykpiv_state *state, const unsigned char key, unsigned char algorithm,
1813 const unsigned char *p, size_t p_len,
1814 const unsigned char *q, size_t q_len,
1815 const unsigned char *dp, size_t dp_len,
1816 const unsigned char *dq, size_t dq_len,
1817 const unsigned char *qinv, size_t qinv_len,
1818 const unsigned char *ec_data, unsigned char ec_data_len,
1819 const unsigned char pin_policy, const unsigned char touch_policy) {
1820
1821 unsigned char key_data[1024] = {0};
1822 unsigned char *in_ptr = key_data;
1823 unsigned char templ[] = {0, YKPIV_INS_IMPORT_KEY, algorithm, key};
1824 unsigned char data[256] = {0};
1825 unsigned long recv_len = sizeof(data);
1826 unsigned elem_len;
1827 int sw;
1828 const unsigned char *params[5] = {0};
1829 size_t lens[5] = {0};
1830 size_t padding;
1831 unsigned char n_params;
1832 int i;
1833 int param_tag;
1834 ykpiv_rc res;
1835
1836 if (state == NULL)
1837 return YKPIV_GENERIC_ERROR;
1838
1839 if (key == YKPIV_KEY_CARDMGM ||
1840 key < YKPIV_KEY_RETIRED1 ||
1841 (key > YKPIV_KEY_RETIRED20 && key < YKPIV_KEY_AUTHENTICATION) ||
1842 (key > YKPIV_KEY_CARDAUTH && key != YKPIV_KEY_ATTESTATION)) {
1843 return YKPIV_KEY_ERROR;
1844 }
1845
1846 if (pin_policy != YKPIV_PINPOLICY_DEFAULT &&
1847 pin_policy != YKPIV_PINPOLICY_NEVER &&
1848 pin_policy != YKPIV_PINPOLICY_ONCE &&
1849 pin_policy != YKPIV_PINPOLICY_ALWAYS)
1850 return YKPIV_GENERIC_ERROR;
1851
1852 if (touch_policy != YKPIV_TOUCHPOLICY_DEFAULT &&
1853 touch_policy != YKPIV_TOUCHPOLICY_NEVER &&
1854 touch_policy != YKPIV_TOUCHPOLICY_ALWAYS &&
1855 touch_policy != YKPIV_TOUCHPOLICY_CACHED)
1856 return YKPIV_GENERIC_ERROR;
1857
1858 if (algorithm == YKPIV_ALGO_RSA1024 || algorithm == YKPIV_ALGO_RSA2048) {
1859
1860 if (p_len + q_len + dp_len + dq_len + qinv_len >= sizeof(key_data)) {
1861 return YKPIV_SIZE_ERROR;
1862 }
1863
1864 if (algorithm == YKPIV_ALGO_RSA1024)
1865 elem_len = 64;
1866 if (algorithm == YKPIV_ALGO_RSA2048)
1867 elem_len = 128;
1868
1869 if (p == NULL || q == NULL || dp == NULL ||
1870 dq == NULL || qinv == NULL)
1871 return YKPIV_GENERIC_ERROR;
1872
1873 params[0] = p;
1874 lens[0] = p_len;
1875 params[1] = q;
1876 lens[1] = q_len;
1877 params[2] = dp;
1878 lens[2] = dp_len;
1879 params[3] = dq;
1880 lens[3] = dq_len;
1881 params[4] = qinv;
1882 lens[4] = qinv_len;
1883 param_tag = 0x01;
1884
1885 n_params = 5;
1886 }
1887 else if (algorithm == YKPIV_ALGO_ECCP256 || algorithm == YKPIV_ALGO_ECCP384) {
1888
1889 if ((size_t)ec_data_len >= sizeof(key_data)) {
1890 /* This can never be true, but check to be explicit. */
1891 return YKPIV_SIZE_ERROR;
1892 }
1893
1894 if (algorithm == YKPIV_ALGO_ECCP256)
1895 elem_len = 32;
1896 if (algorithm == YKPIV_ALGO_ECCP384)
1897 elem_len = 48;
1898
1899 if (ec_data == NULL)
1900 return YKPIV_GENERIC_ERROR;
1901
1902 params[0] = ec_data;
1903 lens[0] = ec_data_len;
1904 param_tag = 0x06;
1905 n_params = 1;
1906 }
1907 else
1908 return YKPIV_ALGORITHM_ERROR;
1909
1910 for (i = 0; i < n_params; i++) {
1911 size_t remaining;
1912 *in_ptr++ = param_tag + i;
1913 in_ptr += _ykpiv_set_length(in_ptr, elem_len);
1914 padding = elem_len - lens[i];
1915 remaining = (uintptr_t)key_data + sizeof(key_data) - (uintptr_t)in_ptr;
1916 if (padding > remaining) {
1917 res = YKPIV_ALGORITHM_ERROR;
1918 goto Cleanup;
1919 }
1920 memset(in_ptr, 0, padding);
1921 in_ptr += padding;
1922 memcpy(in_ptr, params[i], lens[i]);
1923 in_ptr += lens[i];
1924 }
1925
1926 if (pin_policy != YKPIV_PINPOLICY_DEFAULT) {
1927 *in_ptr++ = YKPIV_PINPOLICY_TAG;
1928 *in_ptr++ = 0x01;
1929 *in_ptr++ = pin_policy;
1930 }
1931
1932 if (touch_policy != YKPIV_TOUCHPOLICY_DEFAULT) {
1933 *in_ptr++ = YKPIV_TOUCHPOLICY_TAG;
1934 *in_ptr++ = 0x01;
1935 *in_ptr++ = touch_policy;
1936 }
1937
1938 if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return res;
1939 if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;
1940
1941 if ((res = _ykpiv_transfer_data(state, templ, key_data, (long)(in_ptr - key_data), data, &recv_len, &sw)) != YKPIV_OK) {
1942 goto Cleanup;
1943 }
1944 if (SW_SUCCESS != sw) {
1945 res = YKPIV_GENERIC_ERROR;
1946 if (sw == SW_ERR_SECURITY_STATUS) {
1947 res = YKPIV_AUTHENTICATION_ERROR;
1948 }
1949 goto Cleanup;
1950 }
1951
1952 Cleanup:
1953 yc_memzero(key_data, sizeof(key_data));
1954 _ykpiv_end_transaction(state);
1955 return res;
1956 }
1957
ykpiv_attest(ykpiv_state * state,const unsigned char key,unsigned char * data,size_t * data_len)1958 ykpiv_rc ykpiv_attest(ykpiv_state *state, const unsigned char key, unsigned char *data, size_t *data_len) {
1959 ykpiv_rc res;
1960 unsigned char templ[] = {0, YKPIV_INS_ATTEST, key, 0};
1961 int sw;
1962 unsigned long ul_data_len;
1963
1964 if (state == NULL || data == NULL || data_len == NULL) {
1965 return YKPIV_ARGUMENT_ERROR;
1966 }
1967
1968 ul_data_len = (unsigned long)*data_len;
1969
1970 if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return res;
1971 if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;
1972
1973 if ((res = _ykpiv_transfer_data(state, templ, NULL, 0, data, &ul_data_len, &sw)) != YKPIV_OK) {
1974 goto Cleanup;
1975 }
1976 if (SW_SUCCESS != sw) {
1977 res = YKPIV_GENERIC_ERROR;
1978 if (SW_ERR_NOT_SUPPORTED == sw) {
1979 res = YKPIV_NOT_SUPPORTED;
1980 }
1981 if (SW_ERR_REFERENCE_NOT_FOUND == sw) {
1982 res = YKPIV_KEY_ERROR;
1983 }
1984 if (SW_ERR_INCORRECT_PARAM == sw) {
1985 res = YKPIV_ARGUMENT_ERROR;
1986 }
1987 goto Cleanup;
1988 }
1989 if (data[0] != 0x30) {
1990 res = YKPIV_GENERIC_ERROR;
1991 goto Cleanup;
1992 }
1993
1994 *data_len = (size_t)ul_data_len;
1995
1996 Cleanup:
1997 _ykpiv_end_transaction(state);
1998 return res;
1999 }
2000
ykpiv_get_metadata(ykpiv_state * state,const unsigned char key,unsigned char * data,size_t * data_len)2001 ykpiv_rc ykpiv_get_metadata(ykpiv_state *state, const unsigned char key, unsigned char *data, size_t *data_len) {
2002 ykpiv_rc res;
2003 unsigned char templ[] = {0, YKPIV_INS_GET_METADATA, 0, key};
2004 int sw;
2005 unsigned long ul_data_len;
2006
2007 if (state == NULL || data == NULL || data_len == NULL) {
2008 return YKPIV_ARGUMENT_ERROR;
2009 }
2010
2011 ul_data_len = (unsigned long)*data_len;
2012
2013 if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return res;
2014 if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;
2015
2016 if ((res = _ykpiv_transfer_data(state, templ, NULL, 0, data, &ul_data_len, &sw)) != YKPIV_OK) {
2017 goto Cleanup;
2018 }
2019
2020 if (SW_SUCCESS != sw) {
2021 res = YKPIV_GENERIC_ERROR;
2022 if (SW_ERR_NOT_SUPPORTED == sw) {
2023 res = YKPIV_NOT_SUPPORTED;
2024 }
2025 if (SW_ERR_REFERENCE_NOT_FOUND == sw) {
2026 res = YKPIV_KEY_ERROR;
2027 }
2028 if (SW_ERR_INCORRECT_PARAM == sw) {
2029 res = YKPIV_ARGUMENT_ERROR;
2030 }
2031 goto Cleanup;
2032 }
2033
2034 *data_len = (size_t)ul_data_len;
2035
2036 Cleanup:
2037 _ykpiv_end_transaction(state);
2038 return res;
2039 }
2040
ykpiv_auth_getchallenge(ykpiv_state * state,uint8_t * challenge,const size_t challenge_len)2041 ykpiv_rc ykpiv_auth_getchallenge(ykpiv_state *state, uint8_t *challenge, const size_t challenge_len) {
2042 ykpiv_rc res = YKPIV_OK;
2043 APDU apdu = { 0 };
2044 unsigned char data[261] = { 0 };
2045 uint32_t recv_len = sizeof(data);
2046 int sw = 0;
2047
2048 if (NULL == state) return YKPIV_GENERIC_ERROR;
2049 if (NULL == challenge) return YKPIV_GENERIC_ERROR;
2050 if (8 != challenge_len) return YKPIV_SIZE_ERROR;
2051
2052 if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return res;
2053 if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;
2054
2055 /* get a challenge from the card */
2056 memset(apdu.raw, 0, sizeof(apdu));
2057 apdu.st.ins = YKPIV_INS_AUTHENTICATE;
2058 apdu.st.p1 = YKPIV_ALGO_3DES; /* triple des */
2059 apdu.st.p2 = YKPIV_KEY_CARDMGM; /* management key */
2060 apdu.st.lc = 0x04;
2061 apdu.st.data[0] = 0x7c;
2062 apdu.st.data[1] = 0x02;
2063 apdu.st.data[2] = 0x81; //0x80;
2064 if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) {
2065 goto Cleanup;
2066 }
2067 else if (sw != SW_SUCCESS) {
2068 res = YKPIV_AUTHENTICATION_ERROR;
2069 goto Cleanup;
2070 }
2071 memcpy(challenge, data + 4, 8);
2072
2073 Cleanup:
2074
2075 _ykpiv_end_transaction(state);
2076 return res;
2077 }
2078
ykpiv_auth_verifyresponse(ykpiv_state * state,uint8_t * response,const size_t response_len)2079 ykpiv_rc ykpiv_auth_verifyresponse(ykpiv_state *state, uint8_t *response, const size_t response_len) {
2080 ykpiv_rc res = YKPIV_OK;
2081 APDU apdu = { 0 };
2082 unsigned char data[261] = { 0 };
2083 uint32_t recv_len = sizeof(data);
2084 int sw = 0;
2085 unsigned char *dataptr = apdu.st.data;
2086
2087 if (NULL == state) return YKPIV_GENERIC_ERROR;
2088 if (NULL == response) return YKPIV_GENERIC_ERROR;
2089 if (8 != response_len) return YKPIV_SIZE_ERROR;
2090
2091 if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return res;
2092 /* note: do not select the applet here, as it resets the challenge state */
2093
2094 /* send the response to the card and a challenge of our own. */
2095 recv_len = sizeof(data);
2096 memset(apdu.raw, 0, sizeof(apdu));
2097 apdu.st.ins = YKPIV_INS_AUTHENTICATE;
2098 apdu.st.p1 = YKPIV_ALGO_3DES; /* triple des */
2099 apdu.st.p2 = YKPIV_KEY_CARDMGM; /* management key */
2100 *dataptr++ = 0x7c;
2101 *dataptr++ = 0x0a; /* 2 + 8 */
2102 *dataptr++ = 0x82;
2103 *dataptr++ = 8;
2104 memcpy(dataptr, response, response_len);
2105 dataptr += 8;
2106 apdu.st.lc = (unsigned char)(dataptr - apdu.st.data);
2107 if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) {
2108 goto Cleanup;
2109 }
2110 else if (sw != SW_SUCCESS) {
2111 res = YKPIV_AUTHENTICATION_ERROR;
2112 goto Cleanup;
2113 }
2114
2115 Cleanup:
2116
2117 yc_memzero(&apdu, sizeof(apdu));
2118 _ykpiv_end_transaction(state);
2119 return res;
2120 }
2121
2122 /* deauthenticates the user pin and mgm key */
ykpiv_auth_deauthenticate(ykpiv_state * state)2123 ykpiv_rc ykpiv_auth_deauthenticate(ykpiv_state *state) {
2124 ykpiv_rc res = YKPIV_OK;
2125
2126 if (NULL == state) return YKPIV_GENERIC_ERROR;
2127
2128 if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return res;
2129
2130 res = _ykpiv_auth_deauthenticate(state);
2131
2132 _ykpiv_end_transaction(state);
2133 return res;
2134 }
2135
2136 /* deauthenticates the user pin and mgm key */
_ykpiv_auth_deauthenticate(ykpiv_state * state)2137 static ykpiv_rc _ykpiv_auth_deauthenticate(ykpiv_state *state) {
2138 ykpiv_rc res = YKPIV_OK;
2139 APDU apdu = {0};
2140 unsigned char data[0xff] = {0};
2141 uint32_t recv_len = sizeof(data);
2142 int sw;
2143
2144 if (!state) {
2145 return YKPIV_ARGUMENT_ERROR;
2146 }
2147
2148 memset(apdu.raw, 0, sizeof(apdu));
2149 apdu.st.ins = YKPIV_INS_SELECT_APPLICATION;
2150 apdu.st.p1 = 0x04;
2151
2152 // Once mgmt_aid is selected on NEO we can't select piv_aid again... So we use yk_aid.
2153 // But... YK 5 below 5.3 doesn't allow access to yk_aid, so still use mgmt_aid on non-NEO devices
2154
2155 if (state->ver.major < 4) {
2156 apdu.st.lc = sizeof(yk_aid);
2157 memcpy(apdu.st.data, yk_aid, sizeof(yk_aid));
2158 } else {
2159 apdu.st.lc = sizeof(mgmt_aid);
2160 memcpy(apdu.st.data, mgmt_aid, sizeof(mgmt_aid));
2161 }
2162
2163 if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) < YKPIV_OK) {
2164 if (state->verbose) {
2165 fprintf(stderr, "Failed communicating with card: '%s'\n", ykpiv_strerror(res));
2166 }
2167 return res;
2168 }
2169 else if (sw != SW_SUCCESS) {
2170 if (state->verbose) {
2171 fprintf(stderr, "Failed selecting mgmt/yk application: %04x\n", sw);
2172 }
2173 return YKPIV_GENERIC_ERROR;
2174 }
2175
2176 return res;
2177 }
2178