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