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