1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2018, Joyent, Inc.
24 * Copyright 2023 RackTop Systems, Inc.
25 */
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <strings.h>
30 #include <stdio.h>
31 #include <cryptoutil.h>
32 #include <errno.h>
33 #include <security/cryptoki.h>
34 #include <sys/crypto/common.h>
35 #include <sys/crypto/ioctl.h>
36 #include "kernelGlobal.h"
37 #include "kernelObject.h"
38 #include "kernelSlot.h"
39
40 #define ENCODE_ATTR(type, value, len) { \
41 cur_attr->oa_type = type; \
42 (void) memcpy(ptr, value, len); \
43 cur_attr->oa_value = ptr; \
44 cur_attr->oa_value_len = len; \
45 cur_attr++; \
46 }
47
48 #define MECH_HASH(type) (((uintptr_t)type) % KMECH_HASHTABLE_SIZE)
49 /*
50 * Serialize writes to the hash table. We don't need a per bucket lock as
51 * there are only a few writes and we don't need the lock for reads.
52 */
53 pthread_mutex_t mechhash_mutex = PTHREAD_MUTEX_INITIALIZER;
54
55 static CK_RV
kmech_hash_insert(CK_MECHANISM_TYPE type,crypto_mech_type_t kmech)56 kmech_hash_insert(CK_MECHANISM_TYPE type, crypto_mech_type_t kmech)
57 {
58 uint_t h;
59 kmh_elem_t *elem, *cur;
60
61 elem = malloc(sizeof (kmh_elem_t));
62 if (elem == NULL)
63 return (CKR_HOST_MEMORY);
64
65 h = MECH_HASH(type);
66 elem->type = type;
67 elem->kmech = kmech;
68
69 (void) pthread_mutex_lock(&mechhash_mutex);
70 for (cur = kernel_mechhash[h]; cur != NULL; cur = cur->knext) {
71 if (type == cur->type) {
72 /* Some other thread beat us to it. */
73 (void) pthread_mutex_unlock(&mechhash_mutex);
74 free(elem);
75 return (CKR_OK);
76 }
77 }
78 elem->knext = kernel_mechhash[h];
79 kernel_mechhash[h] = elem;
80 (void) pthread_mutex_unlock(&mechhash_mutex);
81
82 return (CKR_OK);
83 }
84
85 CK_RV
kernel_mech(CK_MECHANISM_TYPE type,crypto_mech_type_t * k_number)86 kernel_mech(CK_MECHANISM_TYPE type, crypto_mech_type_t *k_number)
87 {
88 crypto_get_mechanism_number_t get_number;
89 const char *string;
90 CK_RV rv;
91 int r;
92 kmh_elem_t *elem;
93 uint_t h;
94 char buf[11]; /* Num chars for representing ulong in ASCII */
95
96 /*
97 * Search for an existing entry. No need to lock since we are
98 * just a reader and we never free the entries in the hash table.
99 */
100 h = MECH_HASH(type);
101 for (elem = kernel_mechhash[h]; elem != NULL; elem = elem->knext) {
102 if (type == elem->type) {
103 *k_number = elem->kmech;
104 return (CKR_OK);
105 }
106 }
107
108 if (type >= CKM_VENDOR_DEFINED) {
109 (void) snprintf(buf, sizeof (buf), "%#lx", type);
110 string = buf;
111 } else {
112 string = pkcs11_mech2str(type);
113 }
114
115 if (string == NULL)
116 return (CKR_MECHANISM_INVALID);
117
118 get_number.pn_mechanism_string = (char *)string;
119 get_number.pn_mechanism_len = strlen(string) + 1;
120
121 while ((r = ioctl(kernel_fd, CRYPTO_GET_MECHANISM_NUMBER,
122 &get_number)) < 0) {
123 if (errno != EINTR)
124 break;
125 }
126 if (r < 0) {
127 rv = CKR_MECHANISM_INVALID;
128 } else {
129 if (get_number.pn_return_value != CRYPTO_SUCCESS) {
130 rv = crypto2pkcs11_error_number(
131 get_number.pn_return_value);
132 } else {
133 rv = CKR_OK;
134 }
135 }
136
137 if (rv == CKR_OK) {
138 *k_number = get_number.pn_internal_number;
139 /* Add this to the hash table */
140 (void) kmech_hash_insert(type, *k_number);
141 }
142
143 return (rv);
144 }
145
146
147 /*
148 * Return the value of a secret key object.
149 * This routine allocates memory for the value.
150 * A null pointer is returned on error.
151 */
152 unsigned char *
get_symmetric_key_value(kernel_object_t * key_p)153 get_symmetric_key_value(kernel_object_t *key_p)
154 {
155 uint8_t *cipherKey;
156
157 switch (key_p->class) {
158
159 case CKO_SECRET_KEY:
160
161 cipherKey = malloc(OBJ_SEC(key_p)->sk_value_len);
162 if (cipherKey == NULL)
163 return (NULL);
164
165 (void) memcpy(cipherKey, OBJ_SEC(key_p)->sk_value,
166 OBJ_SEC(key_p)->sk_value_len);
167
168 return (cipherKey);
169
170 default:
171 return (NULL);
172 }
173 }
174
175 /*
176 * Convert a RSA private key object into a crypto_key structure.
177 * Memory is allocated for each attribute stored in the crypto_key
178 * structure. Memory for the crypto_key structure is not
179 * allocated. Attributes can be freed by free_key_attributes().
180 */
181 CK_RV
get_rsa_private_key(kernel_object_t * object_p,crypto_key_t * key)182 get_rsa_private_key(kernel_object_t *object_p, crypto_key_t *key)
183 {
184 biginteger_t *big;
185 crypto_object_attribute_t *attrs, *cur_attr;
186 char *ptr;
187 CK_RV rv;
188
189 (void) pthread_mutex_lock(&object_p->object_mutex);
190 if (object_p->key_type != CKK_RSA ||
191 object_p->class != CKO_PRIVATE_KEY) {
192 (void) pthread_mutex_unlock(&object_p->object_mutex);
193 return (CKR_ATTRIBUTE_TYPE_INVALID);
194 }
195
196 attrs = calloc(1,
197 RSA_PRI_ATTR_COUNT * sizeof (crypto_object_attribute_t));
198 if (attrs == NULL) {
199 (void) pthread_mutex_unlock(&object_p->object_mutex);
200 return (CKR_HOST_MEMORY);
201 }
202
203 key->ck_format = CRYPTO_KEY_ATTR_LIST;
204 key->ck_attrs = attrs;
205 cur_attr = attrs;
206
207 /*
208 * Allocate memory for each key attribute and set up the value
209 * value length.
210 */
211 key->ck_count = 0;
212
213 /* CKA_MODULUS is required. */
214 big = OBJ_PRI_RSA_MOD(object_p);
215 if (big->big_value == NULL) {
216 rv = CKR_ATTRIBUTE_TYPE_INVALID;
217 goto fail_cleanup;
218 } else {
219 if ((ptr = malloc(big->big_value_len)) == NULL) {
220 rv = CKR_HOST_MEMORY;
221 goto fail_cleanup;
222 }
223 ENCODE_ATTR(CKA_MODULUS, big->big_value, big->big_value_len);
224 key->ck_count++;
225 }
226
227 /* CKA_PRIVATE_EXPONENT is required. */
228 big = OBJ_PRI_RSA_PRIEXPO(object_p);
229 if (big->big_value == NULL) {
230 rv = CKR_ATTRIBUTE_TYPE_INVALID;
231 goto fail_cleanup;
232 } else {
233 if ((ptr = malloc(big->big_value_len)) == NULL) {
234 rv = CKR_HOST_MEMORY;
235 goto fail_cleanup;
236 }
237 ENCODE_ATTR(CKA_PRIVATE_EXPONENT, big->big_value,
238 big->big_value_len);
239 key->ck_count++;
240 }
241
242 /* CKA_PRIME_1 is optional. */
243 big = OBJ_PRI_RSA_PRIME1(object_p);
244 if (big->big_value != NULL) {
245 if ((ptr = malloc(big->big_value_len)) == NULL) {
246 rv = CKR_HOST_MEMORY;
247 goto fail_cleanup;
248 }
249 ENCODE_ATTR(CKA_PRIME_1, big->big_value, big->big_value_len);
250 key->ck_count++;
251 }
252
253 /* CKA_PRIME_2 is optional. */
254 big = OBJ_PRI_RSA_PRIME2(object_p);
255 if (big->big_value != NULL) {
256 if ((ptr = malloc(big->big_value_len)) == NULL) {
257 rv = CKR_HOST_MEMORY;
258 goto fail_cleanup;
259 }
260 ENCODE_ATTR(CKA_PRIME_2, big->big_value, big->big_value_len);
261 key->ck_count++;
262 }
263
264 /* CKA_EXPONENT_1 is optional. */
265 big = OBJ_PRI_RSA_EXPO1(object_p);
266 if (big->big_value != NULL) {
267 if ((ptr = malloc(big->big_value_len)) == NULL) {
268 rv = CKR_HOST_MEMORY;
269 goto fail_cleanup;
270 }
271 ENCODE_ATTR(CKA_EXPONENT_1, big->big_value,
272 big->big_value_len);
273 key->ck_count++;
274 }
275
276 /* CKA_EXPONENT_2 is optional. */
277 big = OBJ_PRI_RSA_EXPO2(object_p);
278 if (big->big_value != NULL) {
279 if ((ptr = malloc(big->big_value_len)) == NULL) {
280 rv = CKR_HOST_MEMORY;
281 goto fail_cleanup;
282 }
283 ENCODE_ATTR(CKA_EXPONENT_2, big->big_value,
284 big->big_value_len);
285 key->ck_count++;
286 }
287
288 /* CKA_COEFFICIENT is optional. */
289 big = OBJ_PRI_RSA_COEF(object_p);
290 if (big->big_value != NULL) {
291 if ((ptr = malloc(big->big_value_len)) == NULL) {
292 rv = CKR_HOST_MEMORY;
293 goto fail_cleanup;
294 }
295 ENCODE_ATTR(CKA_COEFFICIENT, big->big_value,
296 big->big_value_len);
297 key->ck_count++;
298 }
299
300 (void) pthread_mutex_unlock(&object_p->object_mutex);
301 return (CKR_OK);
302
303 fail_cleanup:
304 (void) pthread_mutex_unlock(&object_p->object_mutex);
305 free_key_attributes(key);
306 return (rv);
307 }
308
309 /*
310 * Convert a RSA public key object into a crypto_key structure.
311 * Memory is allocated for each attribute stored in the crypto_key
312 * structure. Memory for the crypto_key structure is not
313 * allocated. Attributes can be freed by free_key_attributes().
314 */
315 CK_RV
get_rsa_public_key(kernel_object_t * object_p,crypto_key_t * key)316 get_rsa_public_key(kernel_object_t *object_p, crypto_key_t *key)
317 {
318 biginteger_t *big;
319 crypto_object_attribute_t *attrs, *cur_attr;
320 char *ptr;
321
322 (void) pthread_mutex_lock(&object_p->object_mutex);
323 if (object_p->key_type != CKK_RSA ||
324 object_p->class != CKO_PUBLIC_KEY) {
325 (void) pthread_mutex_unlock(&object_p->object_mutex);
326 return (CKR_ATTRIBUTE_TYPE_INVALID);
327 }
328
329 attrs = calloc(1,
330 RSA_PUB_ATTR_COUNT * sizeof (crypto_object_attribute_t));
331 if (attrs == NULL) {
332 (void) pthread_mutex_unlock(&object_p->object_mutex);
333 return (CKR_HOST_MEMORY);
334 }
335
336 key->ck_format = CRYPTO_KEY_ATTR_LIST;
337 key->ck_count = RSA_PUB_ATTR_COUNT;
338 key->ck_attrs = attrs;
339
340 cur_attr = attrs;
341 big = OBJ_PUB_RSA_PUBEXPO(object_p);
342 if ((ptr = malloc(big->big_value_len)) == NULL)
343 goto mem_failure;
344 ENCODE_ATTR(CKA_PUBLIC_EXPONENT, big->big_value, big->big_value_len);
345
346 big = OBJ_PUB_RSA_MOD(object_p);
347 if ((ptr = malloc(big->big_value_len)) == NULL)
348 goto mem_failure;
349 ENCODE_ATTR(CKA_MODULUS, big->big_value, big->big_value_len);
350
351 if ((ptr = malloc(sizeof (CK_ULONG))) == NULL)
352 goto mem_failure;
353 ENCODE_ATTR(CKA_MODULUS_BITS, &OBJ_PUB_RSA_MOD_BITS(object_p),
354 sizeof (CK_ULONG));
355
356 (void) pthread_mutex_unlock(&object_p->object_mutex);
357 return (CKR_OK);
358
359 mem_failure:
360 (void) pthread_mutex_unlock(&object_p->object_mutex);
361 free_key_attributes(key);
362 return (CKR_HOST_MEMORY);
363 }
364
365 /*
366 * Free attribute storage in a crypto_key structure.
367 */
368 void
free_key_attributes(crypto_key_t * key)369 free_key_attributes(crypto_key_t *key)
370 {
371 int i;
372
373 if (key->ck_format == CRYPTO_KEY_ATTR_LIST &&
374 (key->ck_count > 0) && key->ck_attrs != NULL) {
375 for (i = 0; i < key->ck_count; i++) {
376 freezero(key->ck_attrs[i].oa_value,
377 key->ck_attrs[i].oa_value_len);
378 }
379 free(key->ck_attrs);
380 }
381 }
382
383
384 /*
385 * Convert a DSA private key object into a crypto_key structure.
386 * Memory is allocated for each attribute stored in the crypto_key
387 * structure. Memory for the crypto_key structure is not
388 * allocated. Attributes can be freed by free_dsa_key_attributes().
389 */
390 CK_RV
get_dsa_private_key(kernel_object_t * object_p,crypto_key_t * key)391 get_dsa_private_key(kernel_object_t *object_p, crypto_key_t *key)
392 {
393 biginteger_t *big;
394 crypto_object_attribute_t *attrs, *cur_attr;
395 char *ptr;
396
397 (void) pthread_mutex_lock(&object_p->object_mutex);
398 if (object_p->key_type != CKK_DSA ||
399 object_p->class != CKO_PRIVATE_KEY) {
400 (void) pthread_mutex_unlock(&object_p->object_mutex);
401 return (CKR_ATTRIBUTE_TYPE_INVALID);
402 }
403
404 attrs = calloc(1,
405 DSA_ATTR_COUNT * sizeof (crypto_object_attribute_t));
406 if (attrs == NULL) {
407 (void) pthread_mutex_unlock(&object_p->object_mutex);
408 return (CKR_HOST_MEMORY);
409 }
410
411 key->ck_format = CRYPTO_KEY_ATTR_LIST;
412 key->ck_count = DSA_ATTR_COUNT;
413 key->ck_attrs = attrs;
414
415 cur_attr = attrs;
416 big = OBJ_PRI_DSA_PRIME(object_p);
417 if ((ptr = malloc(big->big_value_len)) == NULL)
418 goto mem_failure;
419 ENCODE_ATTR(CKA_PRIME, big->big_value, big->big_value_len);
420
421 big = OBJ_PRI_DSA_SUBPRIME(object_p);
422 if ((ptr = malloc(big->big_value_len)) == NULL)
423 goto mem_failure;
424 ENCODE_ATTR(CKA_SUBPRIME, big->big_value, big->big_value_len);
425
426 big = OBJ_PRI_DSA_BASE(object_p);
427 if ((ptr = malloc(big->big_value_len)) == NULL)
428 goto mem_failure;
429 ENCODE_ATTR(CKA_BASE, big->big_value, big->big_value_len);
430
431 big = OBJ_PRI_DSA_VALUE(object_p);
432 if ((ptr = malloc(big->big_value_len)) == NULL)
433 goto mem_failure;
434 ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
435
436 (void) pthread_mutex_unlock(&object_p->object_mutex);
437 return (CKR_OK);
438
439 mem_failure:
440 (void) pthread_mutex_unlock(&object_p->object_mutex);
441 free_key_attributes(key);
442 return (CKR_HOST_MEMORY);
443 }
444
445
446 /*
447 * Convert a DSA public key object into a crypto_key structure.
448 * Memory is allocated for each attribute stored in the crypto_key
449 * structure. Memory for the crypto_key structure is not
450 * allocated. Attributes can be freed by free_dsa_key_attributes().
451 */
452 CK_RV
get_dsa_public_key(kernel_object_t * object_p,crypto_key_t * key)453 get_dsa_public_key(kernel_object_t *object_p, crypto_key_t *key)
454 {
455 biginteger_t *big;
456 crypto_object_attribute_t *attrs, *cur_attr;
457 char *ptr;
458
459 (void) pthread_mutex_lock(&object_p->object_mutex);
460 if (object_p->key_type != CKK_DSA ||
461 object_p->class != CKO_PUBLIC_KEY) {
462 (void) pthread_mutex_unlock(&object_p->object_mutex);
463 return (CKR_ATTRIBUTE_TYPE_INVALID);
464 }
465
466 attrs = calloc(1,
467 DSA_ATTR_COUNT * sizeof (crypto_object_attribute_t));
468 if (attrs == NULL) {
469 (void) pthread_mutex_unlock(&object_p->object_mutex);
470 return (CKR_HOST_MEMORY);
471 }
472
473 key->ck_format = CRYPTO_KEY_ATTR_LIST;
474 key->ck_count = DSA_ATTR_COUNT;
475 key->ck_attrs = attrs;
476
477 cur_attr = attrs;
478 big = OBJ_PUB_DSA_PRIME(object_p);
479 if ((ptr = malloc(big->big_value_len)) == NULL)
480 goto mem_failure;
481 ENCODE_ATTR(CKA_PRIME, big->big_value, big->big_value_len);
482
483 big = OBJ_PUB_DSA_SUBPRIME(object_p);
484 if ((ptr = malloc(big->big_value_len)) == NULL)
485 goto mem_failure;
486 ENCODE_ATTR(CKA_SUBPRIME, big->big_value, big->big_value_len);
487
488 big = OBJ_PUB_DSA_BASE(object_p);
489 if ((ptr = malloc(big->big_value_len)) == NULL)
490 goto mem_failure;
491 ENCODE_ATTR(CKA_BASE, big->big_value, big->big_value_len);
492
493 big = OBJ_PUB_DSA_VALUE(object_p);
494 if ((ptr = malloc(big->big_value_len)) == NULL)
495 goto mem_failure;
496 ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
497
498 (void) pthread_mutex_unlock(&object_p->object_mutex);
499 return (CKR_OK);
500
501 mem_failure:
502 (void) pthread_mutex_unlock(&object_p->object_mutex);
503 free_key_attributes(key);
504 return (CKR_HOST_MEMORY);
505 }
506
507
508 /*
509 * Convert a EC private key object into a crypto_key structure.
510 * Memory is allocated for each attribute stored in the crypto_key
511 * structure. Memory for the crypto_key structure is not
512 * allocated. Attributes can be freed by free_ec_key_attributes().
513 */
514 CK_RV
get_ec_private_key(kernel_object_t * object_p,crypto_key_t * key)515 get_ec_private_key(kernel_object_t *object_p, crypto_key_t *key)
516 {
517 biginteger_t *big;
518 crypto_object_attribute_t *attrs, *cur_attr;
519 CK_ATTRIBUTE tmp;
520 char *ptr;
521 int rv;
522
523 (void) pthread_mutex_lock(&object_p->object_mutex);
524 if (object_p->key_type != CKK_EC ||
525 object_p->class != CKO_PRIVATE_KEY) {
526 (void) pthread_mutex_unlock(&object_p->object_mutex);
527 return (CKR_ATTRIBUTE_TYPE_INVALID);
528 }
529
530 attrs = calloc(EC_ATTR_COUNT, sizeof (crypto_object_attribute_t));
531 if (attrs == NULL) {
532 (void) pthread_mutex_unlock(&object_p->object_mutex);
533 return (CKR_HOST_MEMORY);
534 }
535
536 key->ck_format = CRYPTO_KEY_ATTR_LIST;
537 key->ck_count = EC_ATTR_COUNT;
538 key->ck_attrs = attrs;
539
540 cur_attr = attrs;
541 big = OBJ_PRI_EC_VALUE(object_p);
542 if ((ptr = malloc(big->big_value_len)) == NULL) {
543 rv = CKR_HOST_MEMORY;
544 goto fail;
545 }
546 ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
547
548 tmp.type = CKA_EC_PARAMS;
549 tmp.pValue = NULL;
550 rv = kernel_get_attribute(object_p, &tmp);
551 if (rv != CKR_OK) {
552 goto fail;
553 }
554
555 tmp.pValue = malloc(tmp.ulValueLen);
556 if (tmp.pValue == NULL) {
557 rv = CKR_HOST_MEMORY;
558 goto fail;
559 }
560
561 rv = kernel_get_attribute(object_p, &tmp);
562 if (rv != CKR_OK) {
563 free(tmp.pValue);
564 goto fail;
565 }
566
567 cur_attr->oa_type = tmp.type;
568 cur_attr->oa_value = tmp.pValue;
569 cur_attr->oa_value_len = tmp.ulValueLen;
570
571 (void) pthread_mutex_unlock(&object_p->object_mutex);
572 return (CKR_OK);
573
574 fail:
575 (void) pthread_mutex_unlock(&object_p->object_mutex);
576 free_key_attributes(key);
577 return (rv);
578 }
579
580 /*
581 * Convert an EC public key object into a crypto_key structure.
582 * Memory is allocated for each attribute stored in the crypto_key
583 * structure. Memory for the crypto_key structure is not
584 * allocated. Attributes can be freed by free_ec_key_attributes().
585 */
586 CK_RV
get_ec_public_key(kernel_object_t * object_p,crypto_key_t * key)587 get_ec_public_key(kernel_object_t *object_p, crypto_key_t *key)
588 {
589 biginteger_t *big;
590 crypto_object_attribute_t *attrs, *cur_attr;
591 CK_ATTRIBUTE tmp;
592 char *ptr;
593 int rv;
594
595 (void) pthread_mutex_lock(&object_p->object_mutex);
596 if (object_p->key_type != CKK_EC ||
597 object_p->class != CKO_PUBLIC_KEY) {
598 (void) pthread_mutex_unlock(&object_p->object_mutex);
599 return (CKR_ATTRIBUTE_TYPE_INVALID);
600 }
601
602 attrs = calloc(EC_ATTR_COUNT, sizeof (crypto_object_attribute_t));
603 if (attrs == NULL) {
604 (void) pthread_mutex_unlock(&object_p->object_mutex);
605 return (CKR_HOST_MEMORY);
606 }
607
608 key->ck_format = CRYPTO_KEY_ATTR_LIST;
609 key->ck_count = EC_ATTR_COUNT;
610 key->ck_attrs = attrs;
611
612 cur_attr = attrs;
613 big = OBJ_PUB_EC_POINT(object_p);
614 if ((ptr = malloc(big->big_value_len)) == NULL) {
615 rv = CKR_HOST_MEMORY;
616 goto fail;
617 }
618 ENCODE_ATTR(CKA_EC_POINT, big->big_value, big->big_value_len);
619
620 tmp.type = CKA_EC_PARAMS;
621 tmp.pValue = NULL;
622 rv = kernel_get_attribute(object_p, &tmp);
623 if (rv != CKR_OK) {
624 goto fail;
625 }
626
627 tmp.pValue = malloc(tmp.ulValueLen);
628 if (tmp.pValue == NULL) {
629 rv = CKR_HOST_MEMORY;
630 goto fail;
631 }
632
633 rv = kernel_get_attribute(object_p, &tmp);
634 if (rv != CKR_OK) {
635 free(tmp.pValue);
636 goto fail;
637 }
638
639 cur_attr->oa_type = tmp.type;
640 cur_attr->oa_value = tmp.pValue;
641 cur_attr->oa_value_len = tmp.ulValueLen;
642
643 (void) pthread_mutex_unlock(&object_p->object_mutex);
644 return (CKR_OK);
645
646 fail:
647 (void) pthread_mutex_unlock(&object_p->object_mutex);
648 free_key_attributes(key);
649 return (rv);
650 }
651
652 /*
653 * Convert an attribute template into an obj_attrs array.
654 * Memory is allocated for each attribute stored in the obj_attrs.
655 * The memory can be freed by free_object_attributes().
656 *
657 * If the boolean pointer is_token_obj is not NULL, the caller wants to
658 * retrieve the value of the CKA_TOKEN attribute if it is specified in the
659 * template.
660 * - When this routine is called thru C_CreateObject(), C_CopyObject(), or
661 * any key management function, is_token_obj should NOT be NULL.
662 * - When this routine is called thru C_GetAttributeValue() or
663 * C_SetAttributeValue(), "is_token_obj" should be NULL.
664 */
665 CK_RV
process_object_attributes(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,caddr_t * obj_attrs,CK_BBOOL * is_token_obj)666 process_object_attributes(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
667 caddr_t *obj_attrs, CK_BBOOL *is_token_obj)
668 {
669 crypto_object_attribute_t *attrs, *cur_attr;
670 int i, cur_i;
671 char *ptr;
672 CK_RV rv;
673 ssize_t value_len;
674
675 if (ulCount == 0) {
676 obj_attrs = NULL;
677 return (CKR_OK);
678 }
679
680 attrs = calloc(1, ulCount * sizeof (crypto_object_attribute_t));
681 if (attrs == NULL) {
682 return (CKR_HOST_MEMORY);
683 }
684
685 cur_attr = attrs;
686 for (i = 0; i < ulCount; i++) {
687 /*
688 * The length of long attributes must be set correctly
689 * so providers can determine whether they came from 32
690 * or 64-bit applications.
691 */
692 switch (pTemplate[i].type) {
693 case CKA_CLASS:
694 case CKA_CERTIFICATE_TYPE:
695 case CKA_KEY_TYPE:
696 case CKA_MODULUS_BITS:
697 case CKA_HW_FEATURE_TYPE:
698 value_len = sizeof (ulong_t);
699 if (pTemplate[i].pValue != NULL &&
700 (pTemplate[i].ulValueLen < value_len)) {
701 rv = CKR_ATTRIBUTE_VALUE_INVALID;
702 cur_i = i;
703 goto fail_cleanup;
704 }
705 break;
706 default:
707 value_len = pTemplate[i].ulValueLen;
708 }
709
710 cur_attr->oa_type = pTemplate[i].type;
711 cur_attr->oa_value_len = value_len;
712 cur_attr->oa_value = NULL;
713
714 if ((pTemplate[i].pValue != NULL) &&
715 (pTemplate[i].ulValueLen > 0)) {
716 ptr = malloc(pTemplate[i].ulValueLen);
717 if (ptr == NULL) {
718 rv = CKR_HOST_MEMORY;
719 cur_i = i;
720 goto fail_cleanup;
721 } else {
722 (void) memcpy(ptr, pTemplate[i].pValue,
723 pTemplate[i].ulValueLen);
724 cur_attr->oa_value = ptr;
725 }
726 }
727
728 if ((is_token_obj != NULL) &&
729 (pTemplate[i].type == CKA_TOKEN)) {
730 /* Get the CKA_TOKEN attribute value. */
731 if (pTemplate[i].pValue == NULL) {
732 rv = CKR_ATTRIBUTE_VALUE_INVALID;
733 cur_i = i;
734 goto fail_cleanup;
735 } else {
736 *is_token_obj =
737 *(CK_BBOOL *)pTemplate[i].pValue;
738 }
739 }
740
741 cur_attr++;
742 }
743
744 *obj_attrs = (char *)attrs;
745 return (CKR_OK);
746
747 fail_cleanup:
748 cur_attr = attrs;
749 for (i = 0; i < cur_i; i++) {
750 if (cur_attr->oa_value != NULL) {
751 (void) free(cur_attr->oa_value);
752 }
753 cur_attr++;
754 }
755
756 (void) free(attrs);
757 return (rv);
758 }
759
760
761 /*
762 * Copy the attribute values from obj_attrs to pTemplate.
763 * The obj_attrs is an image of the Template and is expected to have the
764 * same attributes in the same order and each one of the attribute pValue
765 * in obj_attr has enough space allocated for the corresponding valueLen
766 * in pTemplate.
767 */
768 CK_RV
get_object_attributes(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,caddr_t obj_attrs)769 get_object_attributes(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
770 caddr_t obj_attrs)
771 {
772 crypto_object_attribute_t *cur_attr;
773 CK_RV rv = CKR_OK;
774 int i;
775
776 /* LINTED */
777 cur_attr = (crypto_object_attribute_t *)obj_attrs;
778 for (i = 0; i < ulCount; i++) {
779 if (pTemplate[i].type != cur_attr->oa_type) {
780 /* The attribute type doesn't match, this is bad. */
781 rv = CKR_FUNCTION_FAILED;
782 return (rv);
783 }
784
785 pTemplate[i].ulValueLen = cur_attr->oa_value_len;
786
787 if ((pTemplate[i].pValue != NULL) &&
788 ((CK_LONG)pTemplate[i].ulValueLen != -1)) {
789 (void) memcpy(pTemplate[i].pValue, cur_attr->oa_value,
790 pTemplate[i].ulValueLen);
791 }
792 cur_attr++;
793 }
794
795 return (rv);
796 }
797
798 /*
799 * Free the attribute storage in a crypto_object_attribute_t structure.
800 */
801 void
free_object_attributes(caddr_t obj_attrs,CK_ULONG ulCount)802 free_object_attributes(caddr_t obj_attrs, CK_ULONG ulCount)
803 {
804 crypto_object_attribute_t *cur_attr;
805 int i;
806
807 if ((ulCount == 0) || (obj_attrs == NULL)) {
808 return;
809 }
810
811 /* LINTED */
812 cur_attr = (crypto_object_attribute_t *)obj_attrs;
813 for (i = 0; i < ulCount; i++) {
814 /* XXX check that oa_value > 0 */
815 if (cur_attr->oa_value != NULL) {
816 free(cur_attr->oa_value);
817 }
818 cur_attr++;
819 }
820
821 free(obj_attrs);
822 }
823
824 /*
825 * This function is called by process_found_objects(). It will check the
826 * CKA_PRIVATE and CKA_TOKEN attributes for the kernel object "oid", then
827 * initialize all the necessary fields in the object wrapper "objp".
828 */
829 static CK_RV
create_new_tobj_in_lib(kernel_slot_t * pslot,kernel_session_t * sp,kernel_object_t * objp,crypto_object_id_t oid)830 create_new_tobj_in_lib(kernel_slot_t *pslot, kernel_session_t *sp,
831 kernel_object_t *objp, crypto_object_id_t oid)
832 {
833 CK_RV rv = CKR_OK;
834 crypto_object_get_attribute_value_t obj_ga;
835 boolean_t is_pri_obj;
836 boolean_t is_token_obj;
837 CK_BBOOL pri_value, token_value;
838 CK_ATTRIBUTE pTemplate[2];
839 int r;
840
841 /*
842 * Make a CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE ioctl call to get this
843 * kernel object's attribute values for CKA_PRIVATE and CKA_TOKEN.
844 */
845 obj_ga.og_session = sp->k_session;
846 obj_ga.og_handle = oid;
847 obj_ga.og_count = 2;
848
849 pTemplate[0].type = CKA_PRIVATE;
850 pTemplate[0].pValue = &pri_value;
851 pTemplate[0].ulValueLen = sizeof (pri_value);
852 pTemplate[1].type = CKA_TOKEN;
853 pTemplate[1].pValue = &token_value;
854 pTemplate[1].ulValueLen = sizeof (token_value);
855 rv = process_object_attributes(pTemplate, 2, &obj_ga.og_attributes,
856 NULL);
857 if (rv != CKR_OK) {
858 return (rv);
859 }
860
861 while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
862 &obj_ga)) < 0) {
863 if (errno != EINTR)
864 break;
865 }
866 if (r < 0) {
867 rv = CKR_FUNCTION_FAILED;
868 } else {
869 rv = crypto2pkcs11_error_number(obj_ga.og_return_value);
870 }
871
872 if (rv == CKR_OK) {
873 rv = get_object_attributes(pTemplate, 2, obj_ga.og_attributes);
874 if (rv == CKR_OK) {
875 is_pri_obj = *(CK_BBOOL *)pTemplate[0].pValue;
876 is_token_obj = *(CK_BBOOL *)pTemplate[1].pValue;
877 }
878 }
879
880 free_object_attributes(obj_ga.og_attributes, 2);
881 if (rv != CKR_OK) {
882 return (rv);
883 }
884
885 /* Make sure it is a token object. */
886 if (!is_token_obj) {
887 rv = CKR_ATTRIBUTE_VALUE_INVALID;
888 return (rv);
889 }
890
891 /* If it is a private object, make sure the user has logged in. */
892 if (is_pri_obj && (pslot->sl_state != CKU_USER)) {
893 rv = CKR_ATTRIBUTE_VALUE_INVALID;
894 return (rv);
895 }
896
897 objp->is_lib_obj = B_FALSE;
898 objp->k_handle = oid;
899 objp->bool_attr_mask |= TOKEN_BOOL_ON;
900 if (is_pri_obj) {
901 objp->bool_attr_mask |= PRIVATE_BOOL_ON;
902 } else {
903 objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
904 }
905
906 (void) pthread_mutex_init(&objp->object_mutex, NULL);
907 objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
908 objp->session_handle = (CK_SESSION_HANDLE) sp;
909
910 return (CKR_OK);
911 }
912
913 /*
914 * This function processes the kernel object handles returned from the
915 * CRYPTO_OBJECT_FIND_UPDATE ioctl and returns an object handle list
916 * and the number of object handles to the caller - C_FindObjects().
917 * The caller acquires the slot lock and the session lock.
918 */
919 CK_RV
process_found_objects(kernel_session_t * cur_sp,CK_OBJECT_HANDLE * obj_found,CK_ULONG * found_obj_count,crypto_object_find_update_t obj_fu)920 process_found_objects(kernel_session_t *cur_sp, CK_OBJECT_HANDLE *obj_found,
921 CK_ULONG *found_obj_count, crypto_object_find_update_t obj_fu)
922 {
923 CK_RV rv = CKR_OK;
924 crypto_object_id_t *oid_p;
925 kernel_slot_t *pslot;
926 kernel_object_t *objp;
927 kernel_object_t *objp1;
928 kernel_object_t *new_tobj_list = NULL;
929 kernel_session_t *sp;
930 CK_ULONG num_obj_found = 0;
931 boolean_t is_in_lib;
932 int i;
933
934 if (obj_fu.fu_count == 0) {
935 *found_obj_count = 0;
936 return (CKR_OK);
937 }
938
939 pslot = slot_table[cur_sp->ses_slotid];
940
941 /* LINTED */
942 oid_p = (crypto_object_id_t *)obj_fu.fu_handles;
943 for (i = 0; i < obj_fu.fu_count; i++) {
944 is_in_lib = B_FALSE;
945 /*
946 * Check if this oid has an object wrapper in the library
947 * already. First, search the slot's token object list.
948 */
949 objp = pslot->sl_tobj_list;
950 while (!is_in_lib && objp) {
951 if (objp->k_handle == *oid_p) {
952 is_in_lib = B_TRUE;
953 } else {
954 objp = objp->next;
955 }
956 }
957
958 /*
959 * If it is not in the slot's token object list,
960 * search it in all the sessions.
961 */
962 if (!is_in_lib) {
963 sp = pslot->sl_sess_list;
964 while (!is_in_lib && sp) {
965 objp = sp->object_list;
966 while (!is_in_lib && objp) {
967 if (objp->k_handle == *oid_p) {
968 is_in_lib = B_TRUE;
969 } else {
970 objp = objp->next;
971 }
972 }
973 sp = sp->next;
974 }
975 }
976
977 /*
978 * If this object is in the library already, add its object
979 * wrapper to the returned find object list.
980 */
981 if (is_in_lib) {
982 obj_found[num_obj_found++] = (CK_OBJECT_HANDLE)objp;
983 }
984
985 /*
986 * If we still do not find it in the library. This object
987 * must be a token object pre-existed in the HW provider.
988 * We need to create an object wrapper for it in the library.
989 */
990 if (!is_in_lib) {
991 objp1 = calloc(1, sizeof (kernel_object_t));
992 if (objp1 == NULL) {
993 rv = CKR_HOST_MEMORY;
994 goto failed_exit;
995 }
996 rv = create_new_tobj_in_lib(pslot, cur_sp, objp1,
997 *oid_p);
998
999 if (rv == CKR_OK) {
1000 /* Save the new object to the new_tobj_list. */
1001 if (new_tobj_list == NULL) {
1002 new_tobj_list = objp1;
1003 objp1->next = NULL;
1004 objp1->prev = NULL;
1005 } else {
1006 new_tobj_list->prev = objp1;
1007 objp1->next = new_tobj_list;
1008 objp1->prev = NULL;
1009 new_tobj_list = objp1;
1010 }
1011 } else {
1012 /*
1013 * If create_new_tobj_in_lib() doesn't fail
1014 * with CKR_HOST_MEMORY, the failure should be
1015 * caused by the attributes' checking. We will
1016 * just ignore this object and continue on.
1017 */
1018 free(objp1);
1019 if (rv == CKR_HOST_MEMORY) {
1020 goto failed_exit;
1021 }
1022 }
1023 }
1024
1025 /* Process next one */
1026 oid_p++;
1027 }
1028
1029 /*
1030 * Add the newly created token object wrappers to the found object
1031 * list and to the slot's token object list.
1032 */
1033 if (new_tobj_list != NULL) {
1034 /* Add to the obj_found array. */
1035 objp = new_tobj_list;
1036 while (objp) {
1037 obj_found[num_obj_found++] = (CK_OBJECT_HANDLE)objp;
1038 if (objp->next == NULL) {
1039 break;
1040 }
1041 objp = objp->next;
1042 }
1043
1044 /* Add to the beginning of the slot's token object list. */
1045 if (pslot->sl_tobj_list != NULL) {
1046 objp->next = pslot->sl_tobj_list;
1047 pslot->sl_tobj_list->prev = objp;
1048 }
1049 pslot->sl_tobj_list = new_tobj_list;
1050 }
1051
1052 *found_obj_count = num_obj_found;
1053 return (CKR_OK);
1054
1055 failed_exit:
1056
1057 /* Free the newly created token object wrappers. */
1058 objp = new_tobj_list;
1059 while (objp) {
1060 objp1 = objp->next;
1061 (void) pthread_mutex_destroy(&objp->object_mutex);
1062 free(objp);
1063 objp = objp1;
1064 }
1065
1066 return (rv);
1067 }
1068
1069
1070 /*
1071 * Get the value of the CKA_PRIVATE attribute for the object just returned
1072 * from the HW provider. This function will be called by any function
1073 * that creates a new object, because the CKA_PRIVATE value of an object is
1074 * token specific. The CKA_PRIVATE attribute value of the new object will be
1075 * stored in the object structure in the library, which will be used later at
1076 * C_Logout to clean up all private objects.
1077 */
1078 CK_RV
get_cka_private_value(kernel_session_t * sp,crypto_object_id_t oid,CK_BBOOL * is_pri_obj)1079 get_cka_private_value(kernel_session_t *sp, crypto_object_id_t oid,
1080 CK_BBOOL *is_pri_obj)
1081 {
1082 CK_RV rv = CKR_OK;
1083 crypto_object_get_attribute_value_t obj_ga;
1084 crypto_object_attribute_t obj_attr;
1085 CK_BBOOL pri_value;
1086 int r;
1087
1088 obj_ga.og_session = sp->k_session;
1089 obj_ga.og_handle = oid;
1090 obj_ga.og_count = 1;
1091
1092 obj_attr.oa_type = CKA_PRIVATE;
1093 obj_attr.oa_value = (char *)&pri_value;
1094 obj_attr.oa_value_len = sizeof (CK_BBOOL);
1095 obj_ga.og_attributes = (char *)&obj_attr;
1096
1097 while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
1098 &obj_ga)) < 0) {
1099 if (errno != EINTR)
1100 break;
1101 }
1102 if (r < 0) {
1103 rv = CKR_FUNCTION_FAILED;
1104 } else {
1105 rv = crypto2pkcs11_error_number(obj_ga.og_return_value);
1106 }
1107
1108 if (rv == CKR_OK) {
1109 *is_pri_obj = *(CK_BBOOL *)obj_attr.oa_value;
1110 }
1111
1112 return (rv);
1113 }
1114
1115
1116 CK_RV
get_mechanism_info(kernel_slot_t * pslot,CK_MECHANISM_TYPE type,CK_MECHANISM_INFO_PTR pInfo,uint32_t * k_mi_flags)1117 get_mechanism_info(kernel_slot_t *pslot, CK_MECHANISM_TYPE type,
1118 CK_MECHANISM_INFO_PTR pInfo, uint32_t *k_mi_flags)
1119 {
1120 crypto_get_provider_mechanism_info_t mechanism_info;
1121 const char *string;
1122 CK_FLAGS flags, mi_flags;
1123 CK_RV rv;
1124 int r;
1125 char buf[11]; /* Num chars for representing ulong in ASCII */
1126
1127 if (type >= CKM_VENDOR_DEFINED) {
1128 /* allocate/build a string containing the mechanism number */
1129 (void) snprintf(buf, sizeof (buf), "%#lx", type);
1130 string = buf;
1131 } else {
1132 string = pkcs11_mech2str(type);
1133 }
1134
1135 if (string == NULL)
1136 return (CKR_MECHANISM_INVALID);
1137
1138 (void) strcpy(mechanism_info.mi_mechanism_name, string);
1139 mechanism_info.mi_provider_id = pslot->sl_provider_id;
1140
1141 while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_MECHANISM_INFO,
1142 &mechanism_info)) < 0) {
1143 if (errno != EINTR)
1144 break;
1145 }
1146 if (r < 0) {
1147 rv = CKR_FUNCTION_FAILED;
1148 } else {
1149 rv = crypto2pkcs11_error_number(
1150 mechanism_info.mi_return_value);
1151 }
1152
1153 if (rv != CKR_OK) {
1154 return (rv);
1155 }
1156
1157 /*
1158 * Atomic flags are not part of PKCS#11 so we filter
1159 * them out here.
1160 * Neither is CRYPTO_FG_MAC.
1161 */
1162 mi_flags = mechanism_info.mi_flags;
1163 mi_flags &= ~(CRYPTO_FG_DIGEST_ATOMIC | CRYPTO_FG_ENCRYPT_ATOMIC |
1164 CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_MAC_ATOMIC |
1165 CRYPTO_FG_SIGN_ATOMIC | CRYPTO_FG_VERIFY_ATOMIC |
1166 CRYPTO_FG_SIGN_RECOVER_ATOMIC |
1167 CRYPTO_FG_VERIFY_RECOVER_ATOMIC |
1168 CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
1169 CRYPTO_FG_MAC_DECRYPT_ATOMIC |
1170 CRYPTO_FG_MAC);
1171
1172 if (mi_flags == 0) {
1173 return (CKR_MECHANISM_INVALID);
1174 }
1175
1176 if (rv == CKR_OK) {
1177 /* set the value of k_mi_flags first */
1178 *k_mi_flags = mi_flags;
1179
1180 /* convert KEF flags into pkcs11 flags */
1181 flags = CKF_HW;
1182 if (mi_flags & CRYPTO_FG_ENCRYPT)
1183 flags |= CKF_ENCRYPT;
1184 if (mi_flags & CRYPTO_FG_DECRYPT) {
1185 flags |= CKF_DECRYPT;
1186 /*
1187 * Since we'll be emulating C_UnwrapKey() for some
1188 * cases, we can go ahead and claim CKF_UNWRAP
1189 */
1190 flags |= CKF_UNWRAP;
1191 }
1192 if (mi_flags & CRYPTO_FG_DIGEST)
1193 flags |= CKF_DIGEST;
1194 if (mi_flags & CRYPTO_FG_SIGN)
1195 flags |= CKF_SIGN;
1196 if (mi_flags & CRYPTO_FG_SIGN_RECOVER)
1197 flags |= CKF_SIGN_RECOVER;
1198 if (mi_flags & CRYPTO_FG_VERIFY)
1199 flags |= CKF_VERIFY;
1200 if (mi_flags & CRYPTO_FG_VERIFY_RECOVER)
1201 flags |= CKF_VERIFY_RECOVER;
1202 if (mi_flags & CRYPTO_FG_GENERATE)
1203 flags |= CKF_GENERATE;
1204 if (mi_flags & CRYPTO_FG_GENERATE_KEY_PAIR)
1205 flags |= CKF_GENERATE_KEY_PAIR;
1206 if (mi_flags & CRYPTO_FG_WRAP)
1207 flags |= CKF_WRAP;
1208 if (mi_flags & CRYPTO_FG_UNWRAP)
1209 flags |= CKF_UNWRAP;
1210 if (mi_flags & CRYPTO_FG_DERIVE)
1211 flags |= CKF_DERIVE;
1212
1213 pInfo->ulMinKeySize = mechanism_info.mi_min_key_size;
1214 pInfo->ulMaxKeySize = mechanism_info.mi_max_key_size;
1215 pInfo->flags = flags;
1216
1217 }
1218
1219 return (rv);
1220 }
1221
1222 /*
1223 * Unfortunately the kernel and PKCS#11 use a slightly different struct to
1224 * specify CCM parameters.
1225 */
1226 void
p11_to_kernel_ccm_params(const CK_CCM_PARAMS * in,CK_AES_CCM_PARAMS * out)1227 p11_to_kernel_ccm_params(const CK_CCM_PARAMS *in, CK_AES_CCM_PARAMS *out)
1228 {
1229 out->ulMACSize = in->ulMACLen;
1230 out->ulNonceSize = in->ulNonceLen;
1231 out->ulAuthDataSize = in->ulAADLen;
1232 out->ulDataSize = in->ulDataLen;
1233 out->nonce = in->pNonce;
1234 out->authData = in->pAAD;
1235 }
1236