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