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