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