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
52static CK_RV error_number_table[CRYPTO_LAST_ERROR+1] = {
53CKR_OK,					/* SUCCESS */
54CKR_CANCEL,				/* CANCEL */
55CKR_HOST_MEMORY,			/* HOST_MEMORY */
56CKR_GENERAL_ERROR,			/* GENERAL_ERROR */
57CKR_FUNCTION_FAILED,			/* FAILED */
58CKR_ARGUMENTS_BAD,			/* ARGUMENTS_BAD */
59CKR_ATTRIBUTE_READ_ONLY,		/* ATTRIBUTE_READ_ONLY */
60CKR_ATTRIBUTE_SENSITIVE,		/* ATTRIBUTE_SENSITIVE */
61CKR_ATTRIBUTE_TYPE_INVALID,		/* ATTRIBUTE_TYPE_INVALID */
62CKR_ATTRIBUTE_VALUE_INVALID,		/* ATTRIBUTE_VALUE_INVALID */
63CKR_FUNCTION_FAILED,			/* CANCELED */
64CKR_DATA_INVALID,			/* DATA_INVALID */
65CKR_DATA_LEN_RANGE,			/* DATA_LEN_RANGE */
66CKR_DEVICE_ERROR,			/* DEVICE_ERROR */
67CKR_DEVICE_MEMORY,			/* DEVICE_MEMORY */
68CKR_DEVICE_REMOVED,			/* DEVICE_REMOVED */
69CKR_ENCRYPTED_DATA_INVALID,		/* ENCRYPTED_DATA_INVALID */
70CKR_ENCRYPTED_DATA_LEN_RANGE,		/* ENCRYPTED_DATA_LEN_RANGE */
71CKR_KEY_HANDLE_INVALID,			/* KEY_HANDLE_INVALID */
72CKR_KEY_SIZE_RANGE,			/* KEY_SIZE_RANGE */
73CKR_KEY_TYPE_INCONSISTENT,		/* KEY_TYPE_INCONSISTENT */
74CKR_KEY_NOT_NEEDED,			/* KEY_NOT_NEEDED */
75CKR_KEY_CHANGED,			/* KEY_CHANGED */
76CKR_KEY_NEEDED,				/* KEY_NEEDED */
77CKR_KEY_INDIGESTIBLE,			/* KEY_INDIGESTIBLE */
78CKR_KEY_FUNCTION_NOT_PERMITTED,		/* KEY_FUNCTION_NOT_PERMITTED */
79CKR_KEY_NOT_WRAPPABLE,			/* KEY_NOT_WRAPPABLE */
80CKR_KEY_UNEXTRACTABLE,			/* KEY_UNEXTRACTABLE */
81CKR_MECHANISM_INVALID,			/* MECHANISM_INVALID */
82CKR_MECHANISM_PARAM_INVALID,		/* MECHANISM_PARAM_INVALID */
83CKR_OBJECT_HANDLE_INVALID,		/* OBJECT_HANDLE_INVALID */
84CKR_OPERATION_ACTIVE,			/* OPERATION_ACTIVE */
85CKR_OPERATION_NOT_INITIALIZED,		/* OPERATION_NOT_INITIALIZED */
86CKR_PIN_INCORRECT,			/* PIN_INCORRECT */
87CKR_PIN_INVALID,			/* PIN_INVALID */
88CKR_PIN_LEN_RANGE,			/* PIN_LEN_RANGE */
89CKR_PIN_EXPIRED,			/* PIN_EXPIRED */
90CKR_PIN_LOCKED,				/* PIN_LOCKED */
91CKR_SESSION_CLOSED,			/* SESSION_CLOSED */
92CKR_SESSION_COUNT,			/* SESSION_COUNT */
93CKR_SESSION_HANDLE_INVALID,		/* SESSION_HANDLE_INVALID */
94CKR_SESSION_READ_ONLY,			/* SESSION_READ_ONLY */
95CKR_SESSION_EXISTS,			/* SESSION_EXISTS */
96CKR_SESSION_READ_ONLY_EXISTS,		/* SESSION_READ_ONLY_EXISTS */
97CKR_SESSION_READ_WRITE_SO_EXISTS,	/* SESSION_READ_WRITE_SO_EXISTS */
98CKR_SIGNATURE_INVALID,			/* SIGNATURE_INVALID */
99CKR_SIGNATURE_LEN_RANGE,		/* SIGNATURE_LEN_RANGE */
100CKR_TEMPLATE_INCOMPLETE,		/* TEMPLATE_INCOMPLETE */
101CKR_TEMPLATE_INCONSISTENT,		/* TEMPLATE_INCONSISTENT */
102CKR_UNWRAPPING_KEY_HANDLE_INVALID,	/* UNWRAPPING_KEY_HANDLE_INVALID */
103CKR_UNWRAPPING_KEY_SIZE_RANGE,		/* UNWRAPPING_KEY_SIZE_RANGE */
104CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT,	/* UNWRAPPING_KEY_TYPE_INCONSISTENT */
105CKR_USER_ALREADY_LOGGED_IN,		/* USER_ALREADY_LOGGED_IN */
106CKR_USER_NOT_LOGGED_IN,			/* USER_NOT_LOGGED_IN */
107CKR_USER_PIN_NOT_INITIALIZED,		/* USER_PIN_NOT_INITIALIZED */
108CKR_USER_TYPE_INVALID,			/* USER_TYPE_INVALID */
109CKR_USER_ANOTHER_ALREADY_LOGGED_IN,	/* USER_ANOTHER_ALREADY_LOGGED_IN */
110CKR_USER_TOO_MANY_TYPES,		/* USER_TOO_MANY_TYPES */
111CKR_WRAPPED_KEY_INVALID,		/* WRAPPED_KEY_INVALID */
112CKR_WRAPPED_KEY_LEN_RANGE,		/* WRAPPED_KEY_LEN_RANGE */
113CKR_WRAPPING_KEY_HANDLE_INVALID,	/* WRAPPING_KEY_HANDLE_INVALID */
114CKR_WRAPPING_KEY_SIZE_RANGE,		/* WRAPPING_KEY_SIZE_RANGE */
115CKR_WRAPPING_KEY_TYPE_INCONSISTENT,	/* WRAPPING_KEY_TYPE_INCONSISTENT */
116CKR_RANDOM_SEED_NOT_SUPPORTED,		/* RANDOM_SEED_NOT_SUPPORTED */
117CKR_RANDOM_NO_RNG,			/* RANDOM_NO_RNG */
118CKR_DOMAIN_PARAMS_INVALID,		/* DOMAIN_PARAMS_INVALID */
119CKR_BUFFER_TOO_SMALL,			/* BUFFER_TOO_SMALL */
120CKR_INFORMATION_SENSITIVE,		/* INFORMATION_SENSITIVE */
121CKR_FUNCTION_NOT_SUPPORTED,		/* NOT_SUPPORTED */
122CKR_GENERAL_ERROR,			/* QUEUED */
123CKR_GENERAL_ERROR,			/* BUFFER_TOO_BIG */
124CKR_OPERATION_NOT_INITIALIZED,		/* INVALID_CONTEXT */
125CKR_GENERAL_ERROR,			/* INVALID_MAC */
126CKR_GENERAL_ERROR,			/* MECH_NOT_SUPPORTED */
127CKR_GENERAL_ERROR,			/* INCONSISTENT_ATTRIBUTE */
128CKR_GENERAL_ERROR,			/* NO_PERMISSION */
129CKR_SLOT_ID_INVALID,			/* INVALID_PROVIDER_ID */
130CKR_GENERAL_ERROR,			/* VERSION_MISMATCH */
131CKR_GENERAL_ERROR,			/* BUSY */
132CKR_GENERAL_ERROR,			/* UNKNOWN_PROVIDER */
133CKR_GENERAL_ERROR,			/* MODVERIFICATION_FAILED */
134CKR_GENERAL_ERROR,			/* OLD_CTX_TEMPLATE */
135CKR_GENERAL_ERROR,			/* WEAK_KEY */
136CKR_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 */
146CK_RV
147crypto2pkcs11_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 */
160pthread_mutex_t mechhash_mutex = PTHREAD_MUTEX_INITIALIZER;
161
162static CK_RV
163kmech_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
192CK_RV
193kernel_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 */
259unsigned char *
260get_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 */
288CK_RV
289get_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
410fail_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 */
422CK_RV
423get_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
466mem_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 */
475void
476free_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			if (key->ck_attrs[i].oa_value != NULL) {
484				bzero(key->ck_attrs[i].oa_value,
485				    key->ck_attrs[i].oa_value_len);
486				free(key->ck_attrs[i].oa_value);
487			}
488		}
489		free(key->ck_attrs);
490	}
491}
492
493
494/*
495 * Convert a DSA private key object into a crypto_key structure.
496 * Memory is allocated for each attribute stored in the crypto_key
497 * structure.  Memory for the crypto_key structure is not
498 * allocated.  Attributes can be freed by free_dsa_key_attributes().
499 */
500CK_RV
501get_dsa_private_key(kernel_object_t *object_p, crypto_key_t *key)
502{
503	biginteger_t *big;
504	crypto_object_attribute_t *attrs, *cur_attr;
505	char *ptr;
506
507	(void) pthread_mutex_lock(&object_p->object_mutex);
508	if (object_p->key_type != CKK_DSA ||
509	    object_p->class != CKO_PRIVATE_KEY) {
510		(void) pthread_mutex_unlock(&object_p->object_mutex);
511		return (CKR_ATTRIBUTE_TYPE_INVALID);
512	}
513
514	attrs = calloc(1,
515	    DSA_ATTR_COUNT * sizeof (crypto_object_attribute_t));
516	if (attrs == NULL) {
517		(void) pthread_mutex_unlock(&object_p->object_mutex);
518		return (CKR_HOST_MEMORY);
519	}
520
521	key->ck_format = CRYPTO_KEY_ATTR_LIST;
522	key->ck_count = DSA_ATTR_COUNT;
523	key->ck_attrs = attrs;
524
525	cur_attr = attrs;
526	big = OBJ_PRI_DSA_PRIME(object_p);
527	if ((ptr = malloc(big->big_value_len)) == NULL)
528		goto mem_failure;
529	ENCODE_ATTR(CKA_PRIME, big->big_value, big->big_value_len);
530
531	big = OBJ_PRI_DSA_SUBPRIME(object_p);
532	if ((ptr = malloc(big->big_value_len)) == NULL)
533		goto mem_failure;
534	ENCODE_ATTR(CKA_SUBPRIME, big->big_value, big->big_value_len);
535
536	big = OBJ_PRI_DSA_BASE(object_p);
537	if ((ptr = malloc(big->big_value_len)) == NULL)
538		goto mem_failure;
539	ENCODE_ATTR(CKA_BASE, big->big_value, big->big_value_len);
540
541	big = OBJ_PRI_DSA_VALUE(object_p);
542	if ((ptr = malloc(big->big_value_len)) == NULL)
543		goto mem_failure;
544	ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
545
546	(void) pthread_mutex_unlock(&object_p->object_mutex);
547	return (CKR_OK);
548
549mem_failure:
550	(void) pthread_mutex_unlock(&object_p->object_mutex);
551	free_key_attributes(key);
552	return (CKR_HOST_MEMORY);
553}
554
555
556/*
557 * Convert a DSA public key object into a crypto_key structure.
558 * Memory is allocated for each attribute stored in the crypto_key
559 * structure.  Memory for the crypto_key structure is not
560 * allocated.  Attributes can be freed by free_dsa_key_attributes().
561 */
562CK_RV
563get_dsa_public_key(kernel_object_t *object_p, crypto_key_t *key)
564{
565	biginteger_t *big;
566	crypto_object_attribute_t *attrs, *cur_attr;
567	char *ptr;
568
569	(void) pthread_mutex_lock(&object_p->object_mutex);
570	if (object_p->key_type != CKK_DSA ||
571	    object_p->class != CKO_PUBLIC_KEY) {
572		(void) pthread_mutex_unlock(&object_p->object_mutex);
573		return (CKR_ATTRIBUTE_TYPE_INVALID);
574	}
575
576	attrs = calloc(1,
577	    DSA_ATTR_COUNT * sizeof (crypto_object_attribute_t));
578	if (attrs == NULL) {
579		(void) pthread_mutex_unlock(&object_p->object_mutex);
580		return (CKR_HOST_MEMORY);
581	}
582
583	key->ck_format = CRYPTO_KEY_ATTR_LIST;
584	key->ck_count = DSA_ATTR_COUNT;
585	key->ck_attrs = attrs;
586
587	cur_attr = attrs;
588	big = OBJ_PUB_DSA_PRIME(object_p);
589	if ((ptr = malloc(big->big_value_len)) == NULL)
590		goto mem_failure;
591	ENCODE_ATTR(CKA_PRIME, big->big_value, big->big_value_len);
592
593	big = OBJ_PUB_DSA_SUBPRIME(object_p);
594	if ((ptr = malloc(big->big_value_len)) == NULL)
595		goto mem_failure;
596	ENCODE_ATTR(CKA_SUBPRIME, big->big_value, big->big_value_len);
597
598	big = OBJ_PUB_DSA_BASE(object_p);
599	if ((ptr = malloc(big->big_value_len)) == NULL)
600		goto mem_failure;
601	ENCODE_ATTR(CKA_BASE, big->big_value, big->big_value_len);
602
603	big = OBJ_PUB_DSA_VALUE(object_p);
604	if ((ptr = malloc(big->big_value_len)) == NULL)
605		goto mem_failure;
606	ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
607
608	(void) pthread_mutex_unlock(&object_p->object_mutex);
609	return (CKR_OK);
610
611mem_failure:
612	(void) pthread_mutex_unlock(&object_p->object_mutex);
613	free_key_attributes(key);
614	return (CKR_HOST_MEMORY);
615}
616
617
618/*
619 * Convert a EC private key object into a crypto_key structure.
620 * Memory is allocated for each attribute stored in the crypto_key
621 * structure.  Memory for the crypto_key structure is not
622 * allocated.  Attributes can be freed by free_ec_key_attributes().
623 */
624CK_RV
625get_ec_private_key(kernel_object_t *object_p, crypto_key_t *key)
626{
627	biginteger_t *big;
628	crypto_object_attribute_t *attrs, *cur_attr;
629	CK_ATTRIBUTE tmp;
630	char *ptr;
631	int rv;
632
633	(void) pthread_mutex_lock(&object_p->object_mutex);
634	if (object_p->key_type != CKK_EC ||
635	    object_p->class != CKO_PRIVATE_KEY) {
636		(void) pthread_mutex_unlock(&object_p->object_mutex);
637		return (CKR_ATTRIBUTE_TYPE_INVALID);
638	}
639
640	attrs = calloc(EC_ATTR_COUNT, sizeof (crypto_object_attribute_t));
641	if (attrs == NULL) {
642		(void) pthread_mutex_unlock(&object_p->object_mutex);
643		return (CKR_HOST_MEMORY);
644	}
645
646	key->ck_format = CRYPTO_KEY_ATTR_LIST;
647	key->ck_count = EC_ATTR_COUNT;
648	key->ck_attrs = attrs;
649
650	cur_attr = attrs;
651	big = OBJ_PRI_EC_VALUE(object_p);
652	if ((ptr = malloc(big->big_value_len)) == NULL) {
653		rv = CKR_HOST_MEMORY;
654		goto fail;
655	}
656	ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
657
658	tmp.type = CKA_EC_PARAMS;
659	tmp.pValue = NULL;
660	rv = kernel_get_attribute(object_p, &tmp);
661	if (rv != CKR_OK) {
662		goto fail;
663	}
664
665	tmp.pValue = malloc(tmp.ulValueLen);
666	if (tmp.pValue == NULL) {
667		rv = CKR_HOST_MEMORY;
668		goto fail;
669	}
670
671	rv = kernel_get_attribute(object_p, &tmp);
672	if (rv != CKR_OK) {
673		free(tmp.pValue);
674		goto fail;
675	}
676
677	cur_attr->oa_type = tmp.type;
678	cur_attr->oa_value = tmp.pValue;
679	cur_attr->oa_value_len = tmp.ulValueLen;
680
681	(void) pthread_mutex_unlock(&object_p->object_mutex);
682	return (CKR_OK);
683
684fail:
685	(void) pthread_mutex_unlock(&object_p->object_mutex);
686	free_key_attributes(key);
687	return (rv);
688}
689
690/*
691 * Convert an EC public key object into a crypto_key structure.
692 * Memory is allocated for each attribute stored in the crypto_key
693 * structure.  Memory for the crypto_key structure is not
694 * allocated.  Attributes can be freed by free_ec_key_attributes().
695 */
696CK_RV
697get_ec_public_key(kernel_object_t *object_p, crypto_key_t *key)
698{
699	biginteger_t *big;
700	crypto_object_attribute_t *attrs, *cur_attr;
701	CK_ATTRIBUTE tmp;
702	char *ptr;
703	int rv;
704
705	(void) pthread_mutex_lock(&object_p->object_mutex);
706	if (object_p->key_type != CKK_EC ||
707	    object_p->class != CKO_PUBLIC_KEY) {
708		(void) pthread_mutex_unlock(&object_p->object_mutex);
709		return (CKR_ATTRIBUTE_TYPE_INVALID);
710	}
711
712	attrs = calloc(EC_ATTR_COUNT, sizeof (crypto_object_attribute_t));
713	if (attrs == NULL) {
714		(void) pthread_mutex_unlock(&object_p->object_mutex);
715		return (CKR_HOST_MEMORY);
716	}
717
718	key->ck_format = CRYPTO_KEY_ATTR_LIST;
719	key->ck_count = EC_ATTR_COUNT;
720	key->ck_attrs = attrs;
721
722	cur_attr = attrs;
723	big = OBJ_PUB_EC_POINT(object_p);
724	if ((ptr = malloc(big->big_value_len)) == NULL) {
725		rv = CKR_HOST_MEMORY;
726		goto fail;
727	}
728	ENCODE_ATTR(CKA_EC_POINT, big->big_value, big->big_value_len);
729
730	tmp.type = CKA_EC_PARAMS;
731	tmp.pValue = NULL;
732	rv = kernel_get_attribute(object_p, &tmp);
733	if (rv != CKR_OK) {
734		goto fail;
735	}
736
737	tmp.pValue = malloc(tmp.ulValueLen);
738	if (tmp.pValue == NULL) {
739		rv = CKR_HOST_MEMORY;
740		goto fail;
741	}
742
743	rv = kernel_get_attribute(object_p, &tmp);
744	if (rv != CKR_OK) {
745		free(tmp.pValue);
746		goto fail;
747	}
748
749	cur_attr->oa_type = tmp.type;
750	cur_attr->oa_value = tmp.pValue;
751	cur_attr->oa_value_len = tmp.ulValueLen;
752
753	(void) pthread_mutex_unlock(&object_p->object_mutex);
754	return (CKR_OK);
755
756fail:
757	(void) pthread_mutex_unlock(&object_p->object_mutex);
758	free_key_attributes(key);
759	return (rv);
760}
761
762/*
763 * Convert an attribute template into an obj_attrs array.
764 * Memory is allocated for each attribute stored in the obj_attrs.
765 * The memory can be freed by free_object_attributes().
766 *
767 * If the boolean pointer is_token_obj is not NULL, the caller wants to
768 * retrieve the value of the CKA_TOKEN attribute if it is specified in the
769 * template.
770 * - When this routine is called thru C_CreateObject(), C_CopyObject(), or
771 *   any key management function, is_token_obj should NOT be NULL.
772 * - When this routine is called thru C_GetAttributeValue() or
773 *   C_SetAttributeValue(), "is_token_obj" should be NULL.
774 */
775CK_RV
776process_object_attributes(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
777    caddr_t *obj_attrs, CK_BBOOL *is_token_obj)
778{
779	crypto_object_attribute_t *attrs, *cur_attr;
780	int i, cur_i;
781	char *ptr;
782	CK_RV rv;
783	ssize_t value_len;
784
785	if (ulCount == 0) {
786		obj_attrs = NULL;
787		return (CKR_OK);
788	}
789
790	attrs = calloc(1, ulCount * sizeof (crypto_object_attribute_t));
791	if (attrs == NULL) {
792		return (CKR_HOST_MEMORY);
793	}
794
795	cur_attr = attrs;
796	for (i = 0; i < ulCount; i++) {
797		/*
798		 * The length of long attributes must be set correctly
799		 * so providers can determine whether they came from 32
800		 * or 64-bit applications.
801		 */
802		switch (pTemplate[i].type) {
803		case CKA_CLASS:
804		case CKA_CERTIFICATE_TYPE:
805		case CKA_KEY_TYPE:
806		case CKA_MODULUS_BITS:
807		case CKA_HW_FEATURE_TYPE:
808			value_len = sizeof (ulong_t);
809			if (pTemplate[i].pValue != NULL &&
810			    (pTemplate[i].ulValueLen < value_len)) {
811				rv = CKR_ATTRIBUTE_VALUE_INVALID;
812				cur_i = i;
813				goto fail_cleanup;
814			}
815			break;
816		default:
817			value_len = pTemplate[i].ulValueLen;
818		}
819
820		cur_attr->oa_type = pTemplate[i].type;
821		cur_attr->oa_value_len = value_len;
822		cur_attr->oa_value = NULL;
823
824		if ((pTemplate[i].pValue != NULL) &&
825		    (pTemplate[i].ulValueLen > 0)) {
826			ptr = malloc(pTemplate[i].ulValueLen);
827			if (ptr == NULL) {
828				rv = CKR_HOST_MEMORY;
829				cur_i = i;
830				goto fail_cleanup;
831			} else {
832				(void) memcpy(ptr, pTemplate[i].pValue,
833				    pTemplate[i].ulValueLen);
834				cur_attr->oa_value = ptr;
835			}
836		}
837
838		if ((is_token_obj != NULL) &&
839		    (pTemplate[i].type == CKA_TOKEN)) {
840			/* Get the CKA_TOKEN attribute value. */
841			if (pTemplate[i].pValue == NULL) {
842				rv = CKR_ATTRIBUTE_VALUE_INVALID;
843				cur_i = i;
844				goto fail_cleanup;
845			} else {
846				*is_token_obj =
847				    *(CK_BBOOL *)pTemplate[i].pValue;
848			}
849		}
850
851		cur_attr++;
852	}
853
854	*obj_attrs = (char *)attrs;
855	return (CKR_OK);
856
857fail_cleanup:
858	cur_attr = attrs;
859	for (i = 0; i < cur_i; i++) {
860		if (cur_attr->oa_value != NULL) {
861			(void) free(cur_attr->oa_value);
862		}
863		cur_attr++;
864	}
865
866	(void) free(attrs);
867	return (rv);
868}
869
870
871/*
872 * Copy the attribute values from obj_attrs to pTemplate.
873 * The obj_attrs is an image of the Template and is expected to have the
874 * same attributes in the same order and each one of the attribute pValue
875 * in obj_attr has enough space allocated for the corresponding valueLen
876 * in pTemplate.
877 */
878CK_RV
879get_object_attributes(CK_ATTRIBUTE_PTR pTemplate,  CK_ULONG ulCount,
880    caddr_t obj_attrs)
881{
882	crypto_object_attribute_t *cur_attr;
883	CK_RV rv = CKR_OK;
884	int i;
885
886	/* LINTED */
887	cur_attr = (crypto_object_attribute_t *)obj_attrs;
888	for (i = 0; i < ulCount; i++) {
889		if (pTemplate[i].type != cur_attr->oa_type) {
890			/* The attribute type doesn't match, this is bad. */
891			rv = CKR_FUNCTION_FAILED;
892			return (rv);
893		}
894
895		pTemplate[i].ulValueLen = cur_attr->oa_value_len;
896
897		if ((pTemplate[i].pValue != NULL) &&
898		    ((CK_LONG)pTemplate[i].ulValueLen != -1)) {
899			(void) memcpy(pTemplate[i].pValue, cur_attr->oa_value,
900			    pTemplate[i].ulValueLen);
901		}
902		cur_attr++;
903	}
904
905	return (rv);
906}
907
908/*
909 * Free the attribute storage in a crypto_object_attribute_t structure.
910 */
911void
912free_object_attributes(caddr_t obj_attrs, CK_ULONG ulCount)
913{
914	crypto_object_attribute_t *cur_attr;
915	int i;
916
917	if ((ulCount == 0) || (obj_attrs == NULL)) {
918		return;
919	}
920
921	/* LINTED */
922	cur_attr = (crypto_object_attribute_t *)obj_attrs;
923	for (i = 0; i < ulCount; i++) {
924		/* XXX check that oa_value > 0 */
925		if (cur_attr->oa_value != NULL) {
926			free(cur_attr->oa_value);
927		}
928		cur_attr++;
929	}
930
931	free(obj_attrs);
932}
933
934/*
935 * This function is called by process_found_objects().  It will check the
936 * CKA_PRIVATE and CKA_TOKEN attributes for the kernel object "oid", then
937 * initialize all the necessary fields in the object wrapper "objp".
938 */
939static CK_RV
940create_new_tobj_in_lib(kernel_slot_t *pslot, kernel_session_t *sp,
941    kernel_object_t *objp,  crypto_object_id_t oid)
942{
943	CK_RV  rv = CKR_OK;
944	crypto_object_get_attribute_value_t obj_ga;
945	boolean_t is_pri_obj;
946	boolean_t is_token_obj;
947	CK_BBOOL pri_value, token_value;
948	CK_ATTRIBUTE  pTemplate[2];
949	int r;
950
951	/*
952	 * Make a CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE ioctl call to get this
953	 * kernel object's attribute values for CKA_PRIVATE and CKA_TOKEN.
954	 */
955	obj_ga.og_session = sp->k_session;
956	obj_ga.og_handle = oid;
957	obj_ga.og_count = 2;
958
959	pTemplate[0].type = CKA_PRIVATE;
960	pTemplate[0].pValue = &pri_value;
961	pTemplate[0].ulValueLen = sizeof (pri_value);
962	pTemplate[1].type = CKA_TOKEN;
963	pTemplate[1].pValue = &token_value;
964	pTemplate[1].ulValueLen = sizeof (token_value);
965	rv = process_object_attributes(pTemplate, 2, &obj_ga.og_attributes,
966	    NULL);
967	if (rv != CKR_OK) {
968		return (rv);
969	}
970
971	while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
972	    &obj_ga)) < 0) {
973		if (errno != EINTR)
974			break;
975	}
976	if (r < 0) {
977		rv = CKR_FUNCTION_FAILED;
978	} else {
979		rv = crypto2pkcs11_error_number(obj_ga.og_return_value);
980	}
981
982	if (rv == CKR_OK) {
983		rv = get_object_attributes(pTemplate, 2, obj_ga.og_attributes);
984		if (rv == CKR_OK) {
985			is_pri_obj = *(CK_BBOOL *)pTemplate[0].pValue;
986			is_token_obj = *(CK_BBOOL *)pTemplate[1].pValue;
987		}
988	}
989
990	free_object_attributes(obj_ga.og_attributes, 2);
991	if (rv != CKR_OK) {
992		return (rv);
993	}
994
995	/* Make sure it is a token object. */
996	if (!is_token_obj) {
997		rv = CKR_ATTRIBUTE_VALUE_INVALID;
998		return (rv);
999	}
1000
1001	/* If it is a private object, make sure the user has logged in. */
1002	if (is_pri_obj && (pslot->sl_state != CKU_USER)) {
1003		rv = CKR_ATTRIBUTE_VALUE_INVALID;
1004		return (rv);
1005	}
1006
1007	objp->is_lib_obj = B_FALSE;
1008	objp->k_handle = oid;
1009	objp->bool_attr_mask |= TOKEN_BOOL_ON;
1010	if (is_pri_obj) {
1011		objp->bool_attr_mask |= PRIVATE_BOOL_ON;
1012	} else {
1013		objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
1014	}
1015
1016	(void) pthread_mutex_init(&objp->object_mutex, NULL);
1017	objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
1018	objp->session_handle = (CK_SESSION_HANDLE) sp;
1019
1020	return (CKR_OK);
1021}
1022
1023/*
1024 * This function processes the kernel object handles returned from the
1025 * CRYPTO_OBJECT_FIND_UPDATE ioctl and returns an object handle list
1026 * and the number of object handles to the caller - C_FindObjects().
1027 * The caller acquires the slot lock and the session lock.
1028 */
1029CK_RV
1030process_found_objects(kernel_session_t *cur_sp, CK_OBJECT_HANDLE *obj_found,
1031    CK_ULONG *found_obj_count, crypto_object_find_update_t obj_fu)
1032{
1033	CK_RV rv = CKR_OK;
1034	crypto_object_id_t  *oid_p;
1035	kernel_slot_t *pslot;
1036	kernel_object_t *objp;
1037	kernel_object_t *objp1;
1038	kernel_object_t *new_tobj_list = NULL;
1039	kernel_session_t  *sp;
1040	CK_ULONG num_obj_found = 0;
1041	boolean_t is_in_lib;
1042	int i;
1043
1044	if (obj_fu.fu_count == 0) {
1045		*found_obj_count = 0;
1046		return (CKR_OK);
1047	}
1048
1049	pslot = slot_table[cur_sp->ses_slotid];
1050
1051	/* LINTED */
1052	oid_p = (crypto_object_id_t *)obj_fu.fu_handles;
1053	for (i = 0; i < obj_fu.fu_count; i++) {
1054		is_in_lib = B_FALSE;
1055		/*
1056		 * Check if this oid has an object wrapper in the library
1057		 * already.  First, search the slot's token object list.
1058		 */
1059		objp = pslot->sl_tobj_list;
1060		while (!is_in_lib && objp) {
1061			if (objp->k_handle == *oid_p) {
1062				is_in_lib = B_TRUE;
1063			} else {
1064				objp = objp->next;
1065			}
1066		}
1067
1068		/*
1069		 * If it is not in the slot's token object list,
1070		 * search it in all the sessions.
1071		 */
1072		if (!is_in_lib) {
1073			sp = pslot->sl_sess_list;
1074			while (!is_in_lib && sp) {
1075				objp = sp->object_list;
1076				while (!is_in_lib && objp) {
1077					if (objp->k_handle == *oid_p) {
1078						is_in_lib = B_TRUE;
1079					} else {
1080						objp = objp->next;
1081					}
1082				}
1083				sp = sp->next;
1084			}
1085		}
1086
1087		/*
1088		 * If this object is in the library already, add its object
1089		 * wrapper to the returned find object list.
1090		 */
1091		if (is_in_lib) {
1092			obj_found[num_obj_found++] = (CK_OBJECT_HANDLE)objp;
1093		}
1094
1095		/*
1096		 * If we still do not find it in the library.  This object
1097		 * must be a token object pre-existed in the HW provider.
1098		 * We need to create an object wrapper for it in the library.
1099		 */
1100		if (!is_in_lib) {
1101			objp1 = calloc(1, sizeof (kernel_object_t));
1102			if (objp1 == NULL) {
1103				rv = CKR_HOST_MEMORY;
1104				goto failed_exit;
1105			}
1106			rv = create_new_tobj_in_lib(pslot, cur_sp, objp1,
1107			    *oid_p);
1108
1109			if (rv == CKR_OK) {
1110				/* Save the new object to the new_tobj_list. */
1111				if (new_tobj_list == NULL) {
1112					new_tobj_list = objp1;
1113					objp1->next = NULL;
1114					objp1->prev = NULL;
1115				} else {
1116					new_tobj_list->prev = objp1;
1117					objp1->next = new_tobj_list;
1118					objp1->prev = NULL;
1119					new_tobj_list = objp1;
1120				}
1121			} else {
1122				/*
1123				 * If create_new_tobj_in_lib() doesn't fail
1124				 * with CKR_HOST_MEMORY, the failure should be
1125				 * caused by the attributes' checking. We will
1126				 * just ignore this object and continue on.
1127				 */
1128				free(objp1);
1129				if (rv == CKR_HOST_MEMORY) {
1130					goto failed_exit;
1131				}
1132			}
1133		}
1134
1135		/* Process next one */
1136		oid_p++;
1137	}
1138
1139	/*
1140	 * Add the newly created token object wrappers to the found object
1141	 * list and to the slot's token object list.
1142	 */
1143	if (new_tobj_list != NULL) {
1144		/* Add to the obj_found array. */
1145		objp = new_tobj_list;
1146		while (objp) {
1147			obj_found[num_obj_found++] = (CK_OBJECT_HANDLE)objp;
1148			if (objp->next == NULL) {
1149				break;
1150			}
1151			objp = objp->next;
1152		}
1153
1154		/* Add to the beginning of the slot's token object list. */
1155		if (pslot->sl_tobj_list != NULL) {
1156			objp->next = pslot->sl_tobj_list;
1157			pslot->sl_tobj_list->prev = objp;
1158		}
1159		pslot->sl_tobj_list = new_tobj_list;
1160	}
1161
1162	*found_obj_count = num_obj_found;
1163	return (CKR_OK);
1164
1165failed_exit:
1166
1167	/* Free the newly created token object wrappers. */
1168	objp = new_tobj_list;
1169	while (objp) {
1170		objp1 = objp->next;
1171		(void) pthread_mutex_destroy(&objp->object_mutex);
1172		free(objp);
1173		objp = objp1;
1174	}
1175
1176	return (rv);
1177}
1178
1179
1180/*
1181 * Get the value of the CKA_PRIVATE attribute for the object just returned
1182 * from the HW provider.  This function will be called by any function
1183 * that creates a new object, because the CKA_PRIVATE value of an object is
1184 * token specific.  The CKA_PRIVATE attribute value of the new object will be
1185 * stored in the object structure in the library, which will be used later at
1186 * C_Logout to clean up all private objects.
1187 */
1188CK_RV
1189get_cka_private_value(kernel_session_t *sp, crypto_object_id_t oid,
1190    CK_BBOOL *is_pri_obj)
1191{
1192	CK_RV  rv = CKR_OK;
1193	crypto_object_get_attribute_value_t obj_ga;
1194	crypto_object_attribute_t obj_attr;
1195	CK_BBOOL pri_value;
1196	int r;
1197
1198	obj_ga.og_session = sp->k_session;
1199	obj_ga.og_handle = oid;
1200	obj_ga.og_count = 1;
1201
1202	obj_attr.oa_type = CKA_PRIVATE;
1203	obj_attr.oa_value = (char *)&pri_value;
1204	obj_attr.oa_value_len = sizeof (CK_BBOOL);
1205	obj_ga.og_attributes = (char *)&obj_attr;
1206
1207	while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
1208	    &obj_ga)) < 0) {
1209		if (errno != EINTR)
1210			break;
1211	}
1212	if (r < 0) {
1213		rv = CKR_FUNCTION_FAILED;
1214	} else {
1215		rv = crypto2pkcs11_error_number(obj_ga.og_return_value);
1216	}
1217
1218	if (rv == CKR_OK) {
1219		*is_pri_obj = *(CK_BBOOL *)obj_attr.oa_value;
1220	}
1221
1222	return (rv);
1223}
1224
1225
1226CK_RV
1227get_mechanism_info(kernel_slot_t *pslot, CK_MECHANISM_TYPE type,
1228    CK_MECHANISM_INFO_PTR pInfo, uint32_t *k_mi_flags)
1229{
1230	crypto_get_provider_mechanism_info_t mechanism_info;
1231	const char *string;
1232	CK_FLAGS flags, mi_flags;
1233	CK_RV rv;
1234	int r;
1235	char buf[11];   /* Num chars for representing ulong in ASCII */
1236
1237	if (type >= CKM_VENDOR_DEFINED) {
1238		/* allocate/build a string containing the mechanism number */
1239		(void) snprintf(buf, sizeof (buf), "%#lx", type);
1240		string = buf;
1241	} else {
1242		string = pkcs11_mech2str(type);
1243	}
1244
1245	if (string == NULL)
1246		return (CKR_MECHANISM_INVALID);
1247
1248	(void) strcpy(mechanism_info.mi_mechanism_name, string);
1249	mechanism_info.mi_provider_id = pslot->sl_provider_id;
1250
1251	while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_MECHANISM_INFO,
1252	    &mechanism_info)) < 0) {
1253		if (errno != EINTR)
1254			break;
1255	}
1256	if (r < 0) {
1257		rv = CKR_FUNCTION_FAILED;
1258	} else {
1259		rv = crypto2pkcs11_error_number(
1260		    mechanism_info.mi_return_value);
1261	}
1262
1263	if (rv != CKR_OK) {
1264		return (rv);
1265	}
1266
1267	/*
1268	 * Atomic flags are not part of PKCS#11 so we filter
1269	 * them out here.
1270	 */
1271	mi_flags = mechanism_info.mi_flags;
1272	mi_flags &= ~(CRYPTO_FG_DIGEST_ATOMIC | CRYPTO_FG_ENCRYPT_ATOMIC |
1273	    CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_MAC_ATOMIC |
1274	    CRYPTO_FG_SIGN_ATOMIC | CRYPTO_FG_VERIFY_ATOMIC |
1275	    CRYPTO_FG_SIGN_RECOVER_ATOMIC |
1276	    CRYPTO_FG_VERIFY_RECOVER_ATOMIC |
1277	    CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
1278	    CRYPTO_FG_MAC_DECRYPT_ATOMIC);
1279
1280	if (mi_flags == 0) {
1281		return (CKR_MECHANISM_INVALID);
1282	}
1283
1284	if (rv == CKR_OK) {
1285		/* set the value of k_mi_flags first */
1286		*k_mi_flags = mi_flags;
1287
1288		/* convert KEF flags into pkcs11 flags */
1289		flags = CKF_HW;
1290		if (mi_flags & CRYPTO_FG_ENCRYPT)
1291			flags |= CKF_ENCRYPT;
1292		if (mi_flags & CRYPTO_FG_DECRYPT) {
1293			flags |= CKF_DECRYPT;
1294			/*
1295			 * Since we'll be emulating C_UnwrapKey() for some
1296			 * cases, we can go ahead and claim CKF_UNWRAP
1297			 */
1298			flags |= CKF_UNWRAP;
1299		}
1300		if (mi_flags & CRYPTO_FG_DIGEST)
1301			flags |= CKF_DIGEST;
1302		if (mi_flags & CRYPTO_FG_SIGN)
1303			flags |= CKF_SIGN;
1304		if (mi_flags & CRYPTO_FG_SIGN_RECOVER)
1305			flags |= CKF_SIGN_RECOVER;
1306		if (mi_flags & CRYPTO_FG_VERIFY)
1307			flags |= CKF_VERIFY;
1308		if (mi_flags & CRYPTO_FG_VERIFY_RECOVER)
1309			flags |= CKF_VERIFY_RECOVER;
1310		if (mi_flags & CRYPTO_FG_GENERATE)
1311			flags |= CKF_GENERATE;
1312		if (mi_flags & CRYPTO_FG_GENERATE_KEY_PAIR)
1313			flags |= CKF_GENERATE_KEY_PAIR;
1314		if (mi_flags & CRYPTO_FG_WRAP)
1315			flags |= CKF_WRAP;
1316		if (mi_flags & CRYPTO_FG_UNWRAP)
1317			flags |= CKF_UNWRAP;
1318		if (mi_flags & CRYPTO_FG_DERIVE)
1319			flags |= CKF_DERIVE;
1320
1321		pInfo->ulMinKeySize = mechanism_info.mi_min_key_size;
1322		pInfo->ulMaxKeySize = mechanism_info.mi_max_key_size;
1323		pInfo->flags = flags;
1324
1325	}
1326
1327	return (rv);
1328}
1329