1 /*
2  * Copyright (c) 2015-2016,2019-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 
31 #include <string.h>
32 #include "utils.h"
33 #include "token.h"
34 #include "debug.h"
35 #include "objects.h"
36 #include "openssl_utils.h"
37 
38 #include <stdbool.h>
39 #include "../common/util.h"
40 
41 #define MIN_RSA_KEY_SIZE 1024
42 #define MAX_RSA_KEY_SIZE 2048
43 #define MIN_ECC_KEY_SIZE 256
44 #define MAX_ECC_KEY_SIZE 384
45 
46 static const char *token_model = "YubiKey XXX";
47 
48 static const token_mechanism token_mechanisms[] = {
49   CKM_RSA_PKCS_KEY_PAIR_GEN, {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_GENERATE_KEY_PAIR},
50   CKM_RSA_PKCS, {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_SIGN | CKF_VERIFY},
51   CKM_RSA_PKCS_PSS, {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN | CKF_VERIFY},
52   CKM_RSA_PKCS_OAEP, {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT},
53   CKM_RSA_X_509, {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_SIGN | CKF_VERIFY},
54   CKM_SHA1_RSA_PKCS, {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN | CKF_VERIFY},
55   CKM_SHA256_RSA_PKCS, {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN | CKF_VERIFY},
56   CKM_SHA384_RSA_PKCS, {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN | CKF_VERIFY},
57   CKM_SHA512_RSA_PKCS, {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN | CKF_VERIFY},
58   CKM_SHA1_RSA_PKCS_PSS, {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN | CKF_VERIFY},
59   CKM_SHA256_RSA_PKCS_PSS, {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN | CKF_VERIFY},
60   CKM_SHA384_RSA_PKCS_PSS, {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN | CKF_VERIFY},
61   CKM_SHA512_RSA_PKCS_PSS, {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN | CKF_VERIFY},
62   CKM_EC_KEY_PAIR_GEN, {MIN_ECC_KEY_SIZE, MAX_ECC_KEY_SIZE, CKF_HW | CKF_GENERATE_KEY_PAIR},
63   //CKM_ECDSA_KEY_PAIR_GEN, {MIN_ECC_KEY_SIZE, MAX_ECC_KEY_SIZE, CKF_HW | CKF_GENERATE_KEY_PAIR}, //Same as CKM_EC_KEY_PAIR_GEN, deprecated in 2.11
64   CKM_ECDSA, {MIN_ECC_KEY_SIZE, MAX_ECC_KEY_SIZE, CKF_HW | CKF_SIGN | CKF_VERIFY},
65   CKM_ECDSA_SHA1, {MIN_ECC_KEY_SIZE, MAX_ECC_KEY_SIZE, CKF_HW | CKF_SIGN | CKF_VERIFY},
66   CKM_ECDSA_SHA224, {MIN_ECC_KEY_SIZE, MAX_ECC_KEY_SIZE, CKF_HW | CKF_SIGN | CKF_VERIFY},
67   CKM_ECDSA_SHA256, {MIN_ECC_KEY_SIZE, MAX_ECC_KEY_SIZE, CKF_HW | CKF_SIGN | CKF_VERIFY},
68   CKM_ECDSA_SHA384, {MIN_ECC_KEY_SIZE, MAX_ECC_KEY_SIZE, CKF_HW | CKF_SIGN | CKF_VERIFY},
69   CKM_ECDH1_DERIVE, {MIN_ECC_KEY_SIZE, MAX_ECC_KEY_SIZE, CKF_HW | CKF_DERIVE},
70   CKM_SHA_1, {0, 0, CKF_DIGEST},
71   CKM_SHA256, {0, 0, CKF_DIGEST},
72   CKM_SHA384, {0, 0, CKF_DIGEST},
73   CKM_SHA512, {0, 0, CKF_DIGEST}
74 };
75 
76 // The commented out objects below are either not supported (PIV_DATA_OBJ_BITGT) or requires authentication.
77 static const piv_obj_id_t token_objects[] = { // TODO: is there a way to get this from the token?
78     PIV_DATA_OBJ_X509_PIV_AUTH,   // PIV authentication
79     PIV_DATA_OBJ_X509_DS,         // digital signature
80     PIV_DATA_OBJ_X509_KM,         // key management
81     PIV_DATA_OBJ_X509_CARD_AUTH,  // card authentication
82     PIV_DATA_OBJ_X509_RETIRED1,   // Retired key 1
83     PIV_DATA_OBJ_X509_RETIRED2,   // Retired key 2
84     PIV_DATA_OBJ_X509_RETIRED3,   // Retired key 3
85     PIV_DATA_OBJ_X509_RETIRED4,   // Retired key 4
86     PIV_DATA_OBJ_X509_RETIRED5,   // Retired key 5
87     PIV_DATA_OBJ_X509_RETIRED6,   // Retired key 6
88     PIV_DATA_OBJ_X509_RETIRED7,   // Retired key 7
89     PIV_DATA_OBJ_X509_RETIRED8,   // Retired key 8
90     PIV_DATA_OBJ_X509_RETIRED9,   // Retired key 9
91     PIV_DATA_OBJ_X509_RETIRED10,  // Retired key 10
92     PIV_DATA_OBJ_X509_RETIRED11,  // Retired key 11
93     PIV_DATA_OBJ_X509_RETIRED12,  // Retired key 12
94     PIV_DATA_OBJ_X509_RETIRED13,  // Retired key 13
95     PIV_DATA_OBJ_X509_RETIRED14,  // Retired key 14
96     PIV_DATA_OBJ_X509_RETIRED15,  // Retired key 15
97     PIV_DATA_OBJ_X509_RETIRED16,  // Retired key 16
98     PIV_DATA_OBJ_X509_RETIRED17,  // Retired key 17
99     PIV_DATA_OBJ_X509_RETIRED18,  // Retired key 18
100     PIV_DATA_OBJ_X509_RETIRED19,  // Retired key 19
101     PIV_DATA_OBJ_X509_RETIRED20,  // Retired key 20
102     PIV_DATA_OBJ_X509_ATTESTATION,// Attestation key
103     PIV_DATA_OBJ_CCC,             // Card capability container
104     PIV_DATA_OBJ_CHUI,            // Cardholder unique id
105     //PIV_DATA_OBJ_CHF,           // Cardholder fingerprints
106     PIV_DATA_OBJ_SEC_OBJ,         // Security object
107     //PIV_DATA_OBJ_CHFI,          // Cardholder facial images
108     //PIV_DATA_OBJ_PI,            // Cardholder printed information
109     PIV_DATA_OBJ_DISCOVERY,       // Discovery object
110     PIV_DATA_OBJ_HISTORY,         // History object
111     //PIV_DATA_OBJ_IRIS_IMAGE,    // Cardholder iris images
112     //PIV_DATA_OBJ_BITGT,         // Biometric information templates group template
113     PIV_DATA_OBJ_SM_SIGNER,       // Secure messaging signer
114     PIV_DATA_OBJ_PC_REF_DATA,     // Pairing code reference data
115 };
116 
get_token_model(ykpiv_state * state,CK_UTF8CHAR_PTR str,CK_ULONG len)117 CK_RV get_token_model(ykpiv_state *state, CK_UTF8CHAR_PTR str, CK_ULONG len) {
118 
119   if (strlen(token_model) > len)
120     return CKR_BUFFER_TOO_SMALL;
121 
122   ykpiv_devmodel model = ykpiv_util_devicemodel(state);
123 
124   uint8_t *ptr = str + memstrcpy(str, len, token_model) - 3;
125 
126   switch(model) {
127     case DEVTYPE_NEOr3:
128       memstrcpy(ptr, 3, "NEO");
129       break;
130     case DEVTYPE_YK4:
131       memstrcpy(ptr, 3, "YK4");
132       break;
133     case DEVTYPE_YK5:
134       memstrcpy(ptr, 3, "YK5");
135       break;
136   }
137 
138   return CKR_OK;
139 }
140 
get_token_version(ykpiv_state * state,CK_VERSION_PTR version)141 CK_RV get_token_version(ykpiv_state *state, CK_VERSION_PTR version) {
142 
143   char buf[16] = {0};
144 
145   if (version == NULL)
146     return CKR_ARGUMENTS_BAD;
147 
148   if (ykpiv_get_version(state, buf, sizeof(buf)) != YKPIV_OK) {
149     version->major = 0;
150     version->minor = 0;
151     return CKR_DEVICE_ERROR;
152   }
153 
154   version->major = (buf[0] - '0');
155   version->minor = (buf[2] - '0') * 10 + (buf[4] - '0');
156 
157   return CKR_OK;
158 }
159 
get_token_serial(ykpiv_state * state,CK_CHAR_PTR str,CK_ULONG len)160 CK_RV get_token_serial(ykpiv_state *state, CK_CHAR_PTR str, CK_ULONG len) {
161 
162   uint32_t serial;
163   char buf[64] = {0};
164   int actual;
165 
166   ykpiv_rc rc = ykpiv_get_serial(state, &serial);
167 
168   actual = snprintf(buf, sizeof(buf), "%u", serial);
169 
170   if(actual < 0)
171     return CKR_FUNCTION_FAILED;
172 
173   if(actual >= len)
174     return CKR_BUFFER_TOO_SMALL;
175 
176   memstrcpy(str, len, buf);
177 
178   return rc == YKPIV_OK ? CKR_OK : CKR_DEVICE_ERROR;
179 }
180 
get_token_label(ykpiv_state * state,CK_CHAR_PTR str,CK_ULONG len)181 CK_RV get_token_label(ykpiv_state *state, CK_CHAR_PTR str, CK_ULONG len) {
182 
183   uint32_t serial;
184   char buf[64] = {0};
185   int actual;
186 
187   ykpiv_rc rc = ykpiv_get_serial(state, &serial);
188 
189   actual = snprintf(buf, sizeof(buf), "YubiKey PIV #%u", serial);
190 
191   if(actual < 0)
192     return CKR_FUNCTION_FAILED;
193 
194   if(actual >= len)
195     return CKR_BUFFER_TOO_SMALL;
196 
197   memstrcpy(str, len, buf);
198 
199   return rc == YKPIV_OK ? CKR_OK : CKR_DEVICE_ERROR;
200 }
201 
get_token_mechanism_list(CK_MECHANISM_TYPE_PTR mec,CK_ULONG_PTR num)202 CK_RV get_token_mechanism_list(CK_MECHANISM_TYPE_PTR mec, CK_ULONG_PTR num) {
203 
204   if(mec) {
205     if (*num < sizeof(token_mechanisms) / sizeof(token_mechanisms[0])) {
206       return CKR_BUFFER_TOO_SMALL;
207     }
208 
209     for (CK_ULONG i = 0; i < sizeof(token_mechanisms) / sizeof(token_mechanisms[0]); i++) {
210       mec[i] = token_mechanisms[i].type;
211     }
212   }
213 
214   *num = sizeof(token_mechanisms) / sizeof(token_mechanisms[0]);
215   return CKR_OK;
216 }
217 
get_token_mechanism_info(CK_MECHANISM_TYPE mec,CK_MECHANISM_INFO_PTR info)218 CK_RV get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_PTR info) {
219 
220   for (CK_ULONG i = 0; i < sizeof(token_mechanisms) / sizeof(token_mechanisms[0]); i++) {
221     if (token_mechanisms[i].type == mec) {
222       memcpy(info, &token_mechanisms[i].info, sizeof(CK_MECHANISM_INFO));
223       return CKR_OK;
224     }
225   }
226 
227   return CKR_MECHANISM_INVALID;
228 }
229 
get_token_object_ids(const piv_obj_id_t ** obj,CK_ULONG_PTR len)230 CK_RV get_token_object_ids(const piv_obj_id_t **obj, CK_ULONG_PTR len) {
231 
232   *obj = token_objects;
233   *len = sizeof(token_objects) / sizeof(token_objects[0]);
234 
235   return CKR_OK;
236 }
237 
token_change_pin(ykpiv_state * state,CK_USER_TYPE user_type,CK_UTF8CHAR_PTR pOldPin,CK_ULONG ulOldLen,CK_UTF8CHAR_PTR pNewPin,CK_ULONG ulNewLen)238 CK_RV token_change_pin(ykpiv_state *state, CK_USER_TYPE user_type, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen) {
239   int tries;
240   ykpiv_rc res;
241 
242   switch(user_type){
243     case CKU_SO:{
244       unsigned char new_key[24] = {0};
245       size_t new_key_len = sizeof(new_key);
246       if(ykpiv_hex_decode((const char*)pNewPin, ulNewLen, new_key, &new_key_len) != YKPIV_OK) {
247         DBG("Failed to decode new pin")
248         return CKR_PIN_INVALID;
249       }
250       DBG("Changing SO PIN")
251       res = ykpiv_set_mgmkey(state, new_key);
252       OPENSSL_cleanse(new_key, sizeof(new_key));
253       break;
254     }
255     case CKU_USER:
256       if(ulOldLen >= 4 && strncmp((const char*)pOldPin, "puk:", 4) == 0){
257         if(ulNewLen >= 4 && strncmp((const char*)pNewPin, "pin:", 4) == 0) {
258           DBG("Unblocking PIN with PUK")
259           res = ykpiv_unblock_pin(state, (const char*)pOldPin + 4, ulOldLen - 4, (const char*)pNewPin + 4, ulNewLen - 4, &tries);
260         } else {
261           DBG("Changing PUK")
262           if(ulNewLen >= 4 && strncmp((const char*)pNewPin, "puk:", 4) == 0) {
263             res = ykpiv_change_puk(state, (const char*)pOldPin + 4, ulOldLen - 4, (const char*)pNewPin + 4, ulNewLen - 4, &tries);
264           } else {
265             res = ykpiv_change_puk(state, (const char*)pOldPin + 4, ulOldLen - 4, (const char*)pNewPin, ulNewLen, &tries);
266           }
267         }
268       }else{
269         DBG("Changing PIN")
270         res = ykpiv_change_pin(state, (const char*)pOldPin, ulOldLen, (const char*)pNewPin, ulNewLen, &tries);
271       }
272       break;
273     default:
274       DBG("TODO implement other context specific pin change");
275       return CKR_FUNCTION_FAILED;
276   }
277 
278   switch (res) {
279     case YKPIV_OK:
280       return CKR_OK;
281     case YKPIV_SIZE_ERROR:
282       return CKR_PIN_LEN_RANGE;
283     case YKPIV_WRONG_PIN:
284       return CKR_PIN_INCORRECT;
285     case YKPIV_PIN_LOCKED:
286       return CKR_PIN_LOCKED;
287     default:
288       return CKR_DEVICE_ERROR;
289   }
290 }
291 
token_login(ykpiv_state * state,CK_USER_TYPE user,CK_UTF8CHAR_PTR pin,CK_ULONG pin_len)292 CK_RV token_login(ykpiv_state *state, CK_USER_TYPE user, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len) {
293 
294   ykpiv_rc res;
295 
296   if (pin_len >= YKPIV_MIN_PIN_LEN && pin_len <= YKPIV_MAX_PIN_LEN) {
297     char term_pin[YKPIV_MAX_PIN_LEN + 1] = {0};
298 
299     memcpy(term_pin, pin, pin_len);
300     term_pin[pin_len] = 0;
301 
302     int tries;
303     res = ykpiv_verify(state, term_pin, &tries);
304 
305     OPENSSL_cleanse(term_pin, pin_len);
306 
307     if (res != YKPIV_OK) {
308       DBG("Failed to login: %s, %d tries left", ykpiv_strerror(res), tries);
309 
310       if(res == YKPIV_WRONG_PIN)
311         return CKR_PIN_INCORRECT;
312 
313       if(res == YKPIV_PIN_LOCKED)
314         return CKR_PIN_LOCKED;
315 
316       return CKR_DEVICE_ERROR;
317     }
318   } else if(pin_len != YKPIV_MGM_KEY_LEN || user != CKU_SO) {
319     DBG("PIN is wrong length");
320     return CKR_ARGUMENTS_BAD;
321   }
322 
323   if (user == CKU_SO) {
324     unsigned char key[24] = {0};
325 
326     if (pin_len == YKPIV_MGM_KEY_LEN) {
327       size_t key_len = sizeof(key);
328       if(ykpiv_hex_decode((char *)pin, pin_len, key, &key_len) != YKPIV_OK) {
329         DBG("Failed decoding key");
330         OPENSSL_cleanse(key, key_len);
331         return CKR_ARGUMENTS_BAD;
332       }
333     } else {
334       ykpiv_config cfg;
335       res = ykpiv_util_get_config(state, &cfg);
336       if(res != YKPIV_OK) {
337         DBG("Failed to get device configuration: %s", ykpiv_strerror(res));
338         return CKR_DEVICE_ERROR;
339       }
340 
341       if(cfg.mgm_type != YKPIV_CONFIG_MGM_PROTECTED) {
342         DBG("Device configuration invalid, no PIN-protected MGM key available");
343         return CKR_USER_PIN_NOT_INITIALIZED;
344       }
345 
346       memcpy(key, cfg.mgm_key, sizeof(key));
347       OPENSSL_cleanse(cfg.mgm_key, sizeof(cfg.mgm_key));
348     }
349 
350     if((res = ykpiv_authenticate(state, key)) != YKPIV_OK) {
351       DBG("Failed to authenticate: %s", ykpiv_strerror(res));
352       OPENSSL_cleanse(key, sizeof(key));
353 
354       if(res == YKPIV_AUTHENTICATION_ERROR)
355         return CKR_PIN_INCORRECT;
356 
357       return CKR_DEVICE_ERROR;
358     }
359 
360     OPENSSL_cleanse(key, sizeof(key));
361   }
362 
363   return CKR_OK;
364 }
365 
token_generate_key(ykpiv_state * state,CK_BYTE algorithm,CK_BYTE key,CK_BYTE_PTR cert_data,CK_ULONG_PTR cert_len)366 CK_RV token_generate_key(ykpiv_state *state, CK_BYTE algorithm, CK_BYTE key, CK_BYTE_PTR cert_data, CK_ULONG_PTR cert_len) {
367   // TODO: make a function in ykpiv for this
368   unsigned char in_data[11] = {0};
369   unsigned char *in_ptr = in_data;
370   unsigned char data[1024] = {0};
371   unsigned char templ[] = {0, YKPIV_INS_GENERATE_ASYMMETRIC, 0, 0};
372   unsigned char *certptr;
373   unsigned long len, len_bytes, offs, recv_len = sizeof(data);
374   char version[7] = {0};
375   char label[32] = {0};
376   int sw;
377 
378   switch(algorithm) {
379     case YKPIV_ALGO_RSA1024:
380     case YKPIV_ALGO_RSA2048:
381       if(ykpiv_get_version(state, version, sizeof(version)) == YKPIV_OK) {
382         int major, minor, build;
383         int match = sscanf(version, "%d.%d.%d", &major, &minor, &build);
384         if(match == 3 && major == 4 && (minor < 3 || (minor == 3 && build < 5))) {
385           DBG("On-chip RSA key generation on this YubiKey has been blocked.");
386           DBG("Please see https://yubi.co/ysa201701/ for details.");
387           return CKR_FUNCTION_FAILED;
388         }
389       } else {
390         DBG("Failed to communicate.");
391         return CKR_DEVICE_ERROR;
392       }
393       break;
394 
395     case YKPIV_ALGO_ECCP256:
396     case YKPIV_ALGO_ECCP384:
397       break;
398 
399     default:
400       return CKR_FUNCTION_FAILED;
401   }
402 
403   templ[3] = key;
404 
405   *in_ptr++ = 0xac;
406   *in_ptr++ = 3;
407   *in_ptr++ = YKPIV_ALGO_TAG;
408   *in_ptr++ = 1;
409   *in_ptr++ = algorithm;
410 
411   if(ykpiv_transfer_data(state, templ, in_data, in_ptr - in_data, data, &recv_len, &sw) != YKPIV_OK || sw != 0x9000) {
412     DBG("Failed to generate key, sw = %04x.", sw);
413     return CKR_DEVICE_ERROR;
414   }
415 
416   snprintf(label, sizeof(label), "YubiKey PIV Slot %x", key);
417 
418   // Create a new empty certificate for the key
419   offs = 2 + get_length(data + 2, data + recv_len, &len);
420   if(offs == 2)
421     return CKR_DEVICE_ERROR;
422 
423   len = recv_len;
424   recv_len = sizeof(data);
425   CK_RV rv = do_create_empty_cert(data + offs, len - offs, algorithm, label, data, &recv_len);
426   if(rv != CKR_OK)
427     return rv;
428 
429   len_bytes = get_length_size(recv_len);
430 
431   certptr = data;
432   memmove(data + len_bytes + 1, data, recv_len);
433 
434   *certptr++ = 0x70;
435   certptr += set_length(certptr, recv_len);
436   certptr += recv_len;
437   *certptr++ = 0x71;
438   *certptr++ = 1;
439   *certptr++ = 0; /* certinfo (gzip etc) */
440   *certptr++ = 0xfe; /* LRC */
441   *certptr++ = 0;
442 
443   if(*cert_len < certptr - data) {
444     DBG("Certificate buffer too small.");
445     return CKR_BUFFER_TOO_SMALL;
446   }
447 
448   // Store the certificate into the token
449   if (ykpiv_save_object(state, ykpiv_util_slot_object(key), data, certptr - data) != YKPIV_OK)
450     return CKR_DEVICE_ERROR;
451 
452   memcpy(cert_data, data, certptr - data);
453   *cert_len = certptr - data;
454 
455   return CKR_OK;
456 }
457 
token_import_cert(ykpiv_state * state,CK_ULONG cert_id,CK_BYTE_PTR in,CK_ULONG in_len)458 CK_RV token_import_cert(ykpiv_state *state, CK_ULONG cert_id, CK_BYTE_PTR in, CK_ULONG in_len) {
459 
460   unsigned char certdata[YKPIV_OBJ_MAX_SIZE + 16] = {0};
461   unsigned char *certptr;
462   CK_ULONG cert_len;
463 
464   CK_RV rv;
465 
466   // Check whether or not we have a valid cert
467   if ((rv = do_check_cert(in, in_len, &cert_len)) != CKR_OK)
468     return rv;
469 
470   if (cert_len > YKPIV_OBJ_MAX_SIZE)
471     return CKR_FUNCTION_FAILED;
472 
473   certptr = certdata;
474 
475   *certptr++ = 0x70;
476   certptr += set_length(certptr, cert_len);
477   memcpy(certptr, in, cert_len);
478   certptr += cert_len;
479 
480   *certptr++ = 0x71;
481   *certptr++ = 1;
482   *certptr++ = 0; /* certinfo (gzip etc) */
483   *certptr++ = 0xfe; /* LRC */
484   *certptr++ = 0;
485 
486   // Store the certificate into the token
487   if (ykpiv_save_object(state, cert_id, certdata, certptr - certdata) != YKPIV_OK)
488     return CKR_DEVICE_ERROR;
489 
490   return CKR_OK;
491 }
492 
token_import_private_key(ykpiv_state * state,CK_BYTE key_id,CK_BYTE_PTR p,CK_ULONG p_len,CK_BYTE_PTR q,CK_ULONG q_len,CK_BYTE_PTR dp,CK_ULONG dp_len,CK_BYTE_PTR dq,CK_ULONG dq_len,CK_BYTE_PTR qinv,CK_ULONG qinv_len,CK_BYTE_PTR ec_data,CK_ULONG ec_data_len)493 CK_RV token_import_private_key(ykpiv_state *state, CK_BYTE key_id,
494                                       CK_BYTE_PTR p, CK_ULONG p_len,
495                                       CK_BYTE_PTR q, CK_ULONG q_len,
496                                       CK_BYTE_PTR dp, CK_ULONG dp_len,
497                                       CK_BYTE_PTR dq, CK_ULONG dq_len,
498                                       CK_BYTE_PTR qinv, CK_ULONG qinv_len,
499                                       CK_BYTE_PTR ec_data, CK_ULONG ec_data_len) {
500 
501   CK_BYTE  pin_policy;
502   CK_BYTE  touch_policy;
503   CK_BYTE  algo;
504   ykpiv_rc rc;
505 
506   if (p == NULL) {
507     if (ec_data_len == 32 || ec_data_len == 31)
508       algo = YKPIV_ALGO_ECCP256;
509     else
510       algo = YKPIV_ALGO_ECCP384;
511   }
512   else if (ec_data == NULL) {
513     if (p_len == 64)
514       algo = YKPIV_ALGO_RSA1024;
515     else
516       algo = YKPIV_ALGO_RSA2048;
517   }
518   else
519     return CKR_FUNCTION_FAILED;
520 
521   pin_policy = YKPIV_PINPOLICY_DEFAULT;
522   touch_policy = YKPIV_TOUCHPOLICY_DEFAULT;
523 
524   rc = ykpiv_import_private_key(state, key_id, algo,
525                                 p, p_len,
526                                 q, q_len,
527                                 dp, dp_len,
528                                 dq, dq_len,
529                                 qinv, qinv_len,
530                                 ec_data, ec_data_len,
531                                 pin_policy, touch_policy);
532 
533   if (rc != YKPIV_OK) {
534     DBG("ykpiv_import_private_key failed: %s", ykpiv_strerror(rc));
535     return CKR_DEVICE_ERROR;
536   }
537 
538   return CKR_OK;
539 }
540 
token_delete_cert(ykpiv_state * state,CK_ULONG cert_id)541 CK_RV token_delete_cert(ykpiv_state *state, CK_ULONG cert_id) {
542 
543   if (ykpiv_save_object(state, cert_id, NULL, 0) != YKPIV_OK)
544     return CKR_DEVICE_ERROR;
545 
546   return CKR_OK;
547 }
548