17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
56f3f1c68Skrishna * Common Development and Distribution License (the "License").
66f3f1c68Skrishna * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22e8ab7b17SZdenek Kotala * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23a8793c76SJason King * Copyright 2018, Joyent, Inc.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <stdlib.h>
277c478bd9Sstevel@tonic-gate #include <string.h>
287c478bd9Sstevel@tonic-gate #include <strings.h>
292321aa36Sda #include <stdio.h>
307c478bd9Sstevel@tonic-gate #include <cryptoutil.h>
317c478bd9Sstevel@tonic-gate #include <errno.h>
327c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
337c478bd9Sstevel@tonic-gate #include <sys/crypto/common.h>
347c478bd9Sstevel@tonic-gate #include <sys/crypto/ioctl.h>
357c478bd9Sstevel@tonic-gate #include "kernelGlobal.h"
367c478bd9Sstevel@tonic-gate #include "kernelObject.h"
377c478bd9Sstevel@tonic-gate #include "kernelSlot.h"
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate #define ENCODE_ATTR(type, value, len) { \
407c478bd9Sstevel@tonic-gate cur_attr->oa_type = type; \
417c478bd9Sstevel@tonic-gate (void) memcpy(ptr, value, len); \
427c478bd9Sstevel@tonic-gate cur_attr->oa_value = ptr; \
437c478bd9Sstevel@tonic-gate cur_attr->oa_value_len = len; \
447c478bd9Sstevel@tonic-gate cur_attr++; \
457c478bd9Sstevel@tonic-gate }
467c478bd9Sstevel@tonic-gate
476f3f1c68Skrishna #define MECH_HASH(type) (((uintptr_t)type) % KMECH_HASHTABLE_SIZE)
486f3f1c68Skrishna /*
496f3f1c68Skrishna * Serialize writes to the hash table. We don't need a per bucket lock as
506f3f1c68Skrishna * there are only a few writes and we don't need the lock for reads.
516f3f1c68Skrishna */
521f49a79aSZdenek Kotala pthread_mutex_t mechhash_mutex = PTHREAD_MUTEX_INITIALIZER;
536f3f1c68Skrishna
546f3f1c68Skrishna static CK_RV
kmech_hash_insert(CK_MECHANISM_TYPE type,crypto_mech_type_t kmech)556f3f1c68Skrishna kmech_hash_insert(CK_MECHANISM_TYPE type, crypto_mech_type_t kmech)
566f3f1c68Skrishna {
576f3f1c68Skrishna uint_t h;
586f3f1c68Skrishna kmh_elem_t *elem, *cur;
596f3f1c68Skrishna
606f3f1c68Skrishna elem = malloc(sizeof (kmh_elem_t));
616f3f1c68Skrishna if (elem == NULL)
626f3f1c68Skrishna return (CKR_HOST_MEMORY);
636f3f1c68Skrishna
646f3f1c68Skrishna h = MECH_HASH(type);
656f3f1c68Skrishna elem->type = type;
666f3f1c68Skrishna elem->kmech = kmech;
676f3f1c68Skrishna
686f3f1c68Skrishna (void) pthread_mutex_lock(&mechhash_mutex);
696f3f1c68Skrishna for (cur = kernel_mechhash[h]; cur != NULL; cur = cur->knext) {
706f3f1c68Skrishna if (type == cur->type) {
716f3f1c68Skrishna /* Some other thread beat us to it. */
726f3f1c68Skrishna (void) pthread_mutex_unlock(&mechhash_mutex);
736f3f1c68Skrishna free(elem);
746f3f1c68Skrishna return (CKR_OK);
756f3f1c68Skrishna }
766f3f1c68Skrishna }
776f3f1c68Skrishna elem->knext = kernel_mechhash[h];
786f3f1c68Skrishna kernel_mechhash[h] = elem;
796f3f1c68Skrishna (void) pthread_mutex_unlock(&mechhash_mutex);
806f3f1c68Skrishna
816f3f1c68Skrishna return (CKR_OK);
826f3f1c68Skrishna }
836f3f1c68Skrishna
847c478bd9Sstevel@tonic-gate CK_RV
kernel_mech(CK_MECHANISM_TYPE type,crypto_mech_type_t * k_number)857c478bd9Sstevel@tonic-gate kernel_mech(CK_MECHANISM_TYPE type, crypto_mech_type_t *k_number)
867c478bd9Sstevel@tonic-gate {
877c478bd9Sstevel@tonic-gate crypto_get_mechanism_number_t get_number;
882321aa36Sda const char *string;
897c478bd9Sstevel@tonic-gate CK_RV rv;
907c478bd9Sstevel@tonic-gate int r;
916f3f1c68Skrishna kmh_elem_t *elem;
926f3f1c68Skrishna uint_t h;
932321aa36Sda char buf[11]; /* Num chars for representing ulong in ASCII */
946f3f1c68Skrishna
956f3f1c68Skrishna /*
966f3f1c68Skrishna * Search for an existing entry. No need to lock since we are
976f3f1c68Skrishna * just a reader and we never free the entries in the hash table.
986f3f1c68Skrishna */
996f3f1c68Skrishna h = MECH_HASH(type);
1006f3f1c68Skrishna for (elem = kernel_mechhash[h]; elem != NULL; elem = elem->knext) {
1016f3f1c68Skrishna if (type == elem->type) {
1026f3f1c68Skrishna *k_number = elem->kmech;
1036f3f1c68Skrishna return (CKR_OK);
1046f3f1c68Skrishna }
1056f3f1c68Skrishna }
1067c478bd9Sstevel@tonic-gate
10776d1b5a9Sda if (type >= CKM_VENDOR_DEFINED) {
1082321aa36Sda (void) snprintf(buf, sizeof (buf), "%#lx", type);
1092321aa36Sda string = buf;
1102321aa36Sda } else {
1112321aa36Sda string = pkcs11_mech2str(type);
1122321aa36Sda }
1132321aa36Sda
1147c478bd9Sstevel@tonic-gate if (string == NULL)
1157c478bd9Sstevel@tonic-gate return (CKR_MECHANISM_INVALID);
1167c478bd9Sstevel@tonic-gate
1172321aa36Sda get_number.pn_mechanism_string = (char *)string;
1187c478bd9Sstevel@tonic-gate get_number.pn_mechanism_len = strlen(string) + 1;
1197c478bd9Sstevel@tonic-gate
1207c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_GET_MECHANISM_NUMBER,
1217c478bd9Sstevel@tonic-gate &get_number)) < 0) {
1227c478bd9Sstevel@tonic-gate if (errno != EINTR)
1237c478bd9Sstevel@tonic-gate break;
1247c478bd9Sstevel@tonic-gate }
1257c478bd9Sstevel@tonic-gate if (r < 0) {
1267c478bd9Sstevel@tonic-gate rv = CKR_MECHANISM_INVALID;
1277c478bd9Sstevel@tonic-gate } else {
1287c478bd9Sstevel@tonic-gate if (get_number.pn_return_value != CRYPTO_SUCCESS) {
1297c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(
1307c478bd9Sstevel@tonic-gate get_number.pn_return_value);
1317c478bd9Sstevel@tonic-gate } else {
1327c478bd9Sstevel@tonic-gate rv = CKR_OK;
1337c478bd9Sstevel@tonic-gate }
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate
1366f3f1c68Skrishna if (rv == CKR_OK) {
1377c478bd9Sstevel@tonic-gate *k_number = get_number.pn_internal_number;
1386f3f1c68Skrishna /* Add this to the hash table */
1396f3f1c68Skrishna (void) kmech_hash_insert(type, *k_number);
1406f3f1c68Skrishna }
1417c478bd9Sstevel@tonic-gate
1427c478bd9Sstevel@tonic-gate return (rv);
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate /*
1477c478bd9Sstevel@tonic-gate * Return the value of a secret key object.
1487c478bd9Sstevel@tonic-gate * This routine allocates memory for the value.
1497c478bd9Sstevel@tonic-gate * A null pointer is returned on error.
1507c478bd9Sstevel@tonic-gate */
1517c478bd9Sstevel@tonic-gate unsigned char *
get_symmetric_key_value(kernel_object_t * key_p)1527c478bd9Sstevel@tonic-gate get_symmetric_key_value(kernel_object_t *key_p)
1537c478bd9Sstevel@tonic-gate {
1547c478bd9Sstevel@tonic-gate uint8_t *cipherKey;
1557c478bd9Sstevel@tonic-gate
1567c478bd9Sstevel@tonic-gate switch (key_p->class) {
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate case CKO_SECRET_KEY:
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate cipherKey = malloc(OBJ_SEC(key_p)->sk_value_len);
1617c478bd9Sstevel@tonic-gate if (cipherKey == NULL)
1627c478bd9Sstevel@tonic-gate return (NULL);
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate (void) memcpy(cipherKey, OBJ_SEC(key_p)->sk_value,
1657c478bd9Sstevel@tonic-gate OBJ_SEC(key_p)->sk_value_len);
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate return (cipherKey);
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate default:
1707c478bd9Sstevel@tonic-gate return (NULL);
1717c478bd9Sstevel@tonic-gate }
1727c478bd9Sstevel@tonic-gate }
1737c478bd9Sstevel@tonic-gate
1747c478bd9Sstevel@tonic-gate /*
1757c478bd9Sstevel@tonic-gate * Convert a RSA private key object into a crypto_key structure.
1767c478bd9Sstevel@tonic-gate * Memory is allocated for each attribute stored in the crypto_key
1777c478bd9Sstevel@tonic-gate * structure. Memory for the crypto_key structure is not
1787c478bd9Sstevel@tonic-gate * allocated. Attributes can be freed by free_key_attributes().
1797c478bd9Sstevel@tonic-gate */
1807c478bd9Sstevel@tonic-gate CK_RV
get_rsa_private_key(kernel_object_t * object_p,crypto_key_t * key)1817c478bd9Sstevel@tonic-gate get_rsa_private_key(kernel_object_t *object_p, crypto_key_t *key)
1827c478bd9Sstevel@tonic-gate {
1837c478bd9Sstevel@tonic-gate biginteger_t *big;
1847c478bd9Sstevel@tonic-gate crypto_object_attribute_t *attrs, *cur_attr;
1857c478bd9Sstevel@tonic-gate char *ptr;
1867c478bd9Sstevel@tonic-gate CK_RV rv;
1877c478bd9Sstevel@tonic-gate
1887c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&object_p->object_mutex);
1897c478bd9Sstevel@tonic-gate if (object_p->key_type != CKK_RSA ||
1907c478bd9Sstevel@tonic-gate object_p->class != CKO_PRIVATE_KEY) {
1917c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object_p->object_mutex);
1927c478bd9Sstevel@tonic-gate return (CKR_ATTRIBUTE_TYPE_INVALID);
1937c478bd9Sstevel@tonic-gate }
1947c478bd9Sstevel@tonic-gate
1957c478bd9Sstevel@tonic-gate attrs = calloc(1,
1967c478bd9Sstevel@tonic-gate RSA_PRI_ATTR_COUNT * sizeof (crypto_object_attribute_t));
1977c478bd9Sstevel@tonic-gate if (attrs == NULL) {
1987c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object_p->object_mutex);
1997c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY);
2007c478bd9Sstevel@tonic-gate }
2017c478bd9Sstevel@tonic-gate
2027c478bd9Sstevel@tonic-gate key->ck_format = CRYPTO_KEY_ATTR_LIST;
2037c478bd9Sstevel@tonic-gate key->ck_attrs = attrs;
2047c478bd9Sstevel@tonic-gate cur_attr = attrs;
2057c478bd9Sstevel@tonic-gate
2067c478bd9Sstevel@tonic-gate /*
2077c478bd9Sstevel@tonic-gate * Allocate memory for each key attribute and set up the value
2087c478bd9Sstevel@tonic-gate * value length.
2097c478bd9Sstevel@tonic-gate */
2107c478bd9Sstevel@tonic-gate key->ck_count = 0;
2117c478bd9Sstevel@tonic-gate
2127c478bd9Sstevel@tonic-gate /* CKA_MODULUS is required. */
2137c478bd9Sstevel@tonic-gate big = OBJ_PRI_RSA_MOD(object_p);
2147c478bd9Sstevel@tonic-gate if (big->big_value == NULL) {
2157c478bd9Sstevel@tonic-gate rv = CKR_ATTRIBUTE_TYPE_INVALID;
2167c478bd9Sstevel@tonic-gate goto fail_cleanup;
2177c478bd9Sstevel@tonic-gate } else {
2187c478bd9Sstevel@tonic-gate if ((ptr = malloc(big->big_value_len)) == NULL) {
2197c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
2207c478bd9Sstevel@tonic-gate goto fail_cleanup;
2217c478bd9Sstevel@tonic-gate }
2227c478bd9Sstevel@tonic-gate ENCODE_ATTR(CKA_MODULUS, big->big_value, big->big_value_len);
2237c478bd9Sstevel@tonic-gate key->ck_count++;
2247c478bd9Sstevel@tonic-gate }
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate /* CKA_PRIVATE_EXPONENT is required. */
2277c478bd9Sstevel@tonic-gate big = OBJ_PRI_RSA_PRIEXPO(object_p);
2287c478bd9Sstevel@tonic-gate if (big->big_value == NULL) {
2297c478bd9Sstevel@tonic-gate rv = CKR_ATTRIBUTE_TYPE_INVALID;
2307c478bd9Sstevel@tonic-gate goto fail_cleanup;
2317c478bd9Sstevel@tonic-gate } else {
2327c478bd9Sstevel@tonic-gate if ((ptr = malloc(big->big_value_len)) == NULL) {
2337c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
2347c478bd9Sstevel@tonic-gate goto fail_cleanup;
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate ENCODE_ATTR(CKA_PRIVATE_EXPONENT, big->big_value,
2377c478bd9Sstevel@tonic-gate big->big_value_len);
2387c478bd9Sstevel@tonic-gate key->ck_count++;
2397c478bd9Sstevel@tonic-gate }
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate /* CKA_PRIME_1 is optional. */
2427c478bd9Sstevel@tonic-gate big = OBJ_PRI_RSA_PRIME1(object_p);
2437c478bd9Sstevel@tonic-gate if (big->big_value != NULL) {
2447c478bd9Sstevel@tonic-gate if ((ptr = malloc(big->big_value_len)) == NULL) {
2457c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
2467c478bd9Sstevel@tonic-gate goto fail_cleanup;
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate ENCODE_ATTR(CKA_PRIME_1, big->big_value, big->big_value_len);
2497c478bd9Sstevel@tonic-gate key->ck_count++;
2507c478bd9Sstevel@tonic-gate }
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate /* CKA_PRIME_2 is optional. */
2537c478bd9Sstevel@tonic-gate big = OBJ_PRI_RSA_PRIME2(object_p);
2547c478bd9Sstevel@tonic-gate if (big->big_value != NULL) {
2557c478bd9Sstevel@tonic-gate if ((ptr = malloc(big->big_value_len)) == NULL) {
2567c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
2577c478bd9Sstevel@tonic-gate goto fail_cleanup;
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate ENCODE_ATTR(CKA_PRIME_2, big->big_value, big->big_value_len);
2607c478bd9Sstevel@tonic-gate key->ck_count++;
2617c478bd9Sstevel@tonic-gate }
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate /* CKA_EXPONENT_1 is optional. */
2647c478bd9Sstevel@tonic-gate big = OBJ_PRI_RSA_EXPO1(object_p);
2657c478bd9Sstevel@tonic-gate if (big->big_value != NULL) {
2667c478bd9Sstevel@tonic-gate if ((ptr = malloc(big->big_value_len)) == NULL) {
2677c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
2687c478bd9Sstevel@tonic-gate goto fail_cleanup;
2697c478bd9Sstevel@tonic-gate }
2707c478bd9Sstevel@tonic-gate ENCODE_ATTR(CKA_EXPONENT_1, big->big_value,
2717c478bd9Sstevel@tonic-gate big->big_value_len);
2727c478bd9Sstevel@tonic-gate key->ck_count++;
2737c478bd9Sstevel@tonic-gate }
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gate /* CKA_EXPONENT_2 is optional. */
2767c478bd9Sstevel@tonic-gate big = OBJ_PRI_RSA_EXPO2(object_p);
2777c478bd9Sstevel@tonic-gate if (big->big_value != NULL) {
2787c478bd9Sstevel@tonic-gate if ((ptr = malloc(big->big_value_len)) == NULL) {
2797c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
2807c478bd9Sstevel@tonic-gate goto fail_cleanup;
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate ENCODE_ATTR(CKA_EXPONENT_2, big->big_value,
2837c478bd9Sstevel@tonic-gate big->big_value_len);
2847c478bd9Sstevel@tonic-gate key->ck_count++;
2857c478bd9Sstevel@tonic-gate }
2867c478bd9Sstevel@tonic-gate
2877c478bd9Sstevel@tonic-gate /* CKA_COEFFICIENT is optional. */
2887c478bd9Sstevel@tonic-gate big = OBJ_PRI_RSA_COEF(object_p);
2897c478bd9Sstevel@tonic-gate if (big->big_value != NULL) {
2907c478bd9Sstevel@tonic-gate if ((ptr = malloc(big->big_value_len)) == NULL) {
2917c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
2927c478bd9Sstevel@tonic-gate goto fail_cleanup;
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate ENCODE_ATTR(CKA_COEFFICIENT, big->big_value,
2957c478bd9Sstevel@tonic-gate big->big_value_len);
2967c478bd9Sstevel@tonic-gate key->ck_count++;
2977c478bd9Sstevel@tonic-gate }
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object_p->object_mutex);
3007c478bd9Sstevel@tonic-gate return (CKR_OK);
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate fail_cleanup:
3037c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object_p->object_mutex);
3047c478bd9Sstevel@tonic-gate free_key_attributes(key);
3057c478bd9Sstevel@tonic-gate return (rv);
3067c478bd9Sstevel@tonic-gate }
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate /*
3097c478bd9Sstevel@tonic-gate * Convert a RSA public key object into a crypto_key structure.
3107c478bd9Sstevel@tonic-gate * Memory is allocated for each attribute stored in the crypto_key
3117c478bd9Sstevel@tonic-gate * structure. Memory for the crypto_key structure is not
3127c478bd9Sstevel@tonic-gate * allocated. Attributes can be freed by free_key_attributes().
3137c478bd9Sstevel@tonic-gate */
3147c478bd9Sstevel@tonic-gate CK_RV
get_rsa_public_key(kernel_object_t * object_p,crypto_key_t * key)3157c478bd9Sstevel@tonic-gate get_rsa_public_key(kernel_object_t *object_p, crypto_key_t *key)
3167c478bd9Sstevel@tonic-gate {
3177c478bd9Sstevel@tonic-gate biginteger_t *big;
3187c478bd9Sstevel@tonic-gate crypto_object_attribute_t *attrs, *cur_attr;
3197c478bd9Sstevel@tonic-gate char *ptr;
3207c478bd9Sstevel@tonic-gate
3217c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&object_p->object_mutex);
3227c478bd9Sstevel@tonic-gate if (object_p->key_type != CKK_RSA ||
3237c478bd9Sstevel@tonic-gate object_p->class != CKO_PUBLIC_KEY) {
3247c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object_p->object_mutex);
3257c478bd9Sstevel@tonic-gate return (CKR_ATTRIBUTE_TYPE_INVALID);
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate attrs = calloc(1,
3297c478bd9Sstevel@tonic-gate RSA_PUB_ATTR_COUNT * sizeof (crypto_object_attribute_t));
3307c478bd9Sstevel@tonic-gate if (attrs == NULL) {
3317c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object_p->object_mutex);
3327c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY);
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate
3357c478bd9Sstevel@tonic-gate key->ck_format = CRYPTO_KEY_ATTR_LIST;
3367c478bd9Sstevel@tonic-gate key->ck_count = RSA_PUB_ATTR_COUNT;
3377c478bd9Sstevel@tonic-gate key->ck_attrs = attrs;
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate cur_attr = attrs;
3407c478bd9Sstevel@tonic-gate big = OBJ_PUB_RSA_PUBEXPO(object_p);
3417c478bd9Sstevel@tonic-gate if ((ptr = malloc(big->big_value_len)) == NULL)
3427c478bd9Sstevel@tonic-gate goto mem_failure;
3437c478bd9Sstevel@tonic-gate ENCODE_ATTR(CKA_PUBLIC_EXPONENT, big->big_value, big->big_value_len);
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate big = OBJ_PUB_RSA_MOD(object_p);
3467c478bd9Sstevel@tonic-gate if ((ptr = malloc(big->big_value_len)) == NULL)
3477c478bd9Sstevel@tonic-gate goto mem_failure;
3487c478bd9Sstevel@tonic-gate ENCODE_ATTR(CKA_MODULUS, big->big_value, big->big_value_len);
3497c478bd9Sstevel@tonic-gate
3507c478bd9Sstevel@tonic-gate if ((ptr = malloc(sizeof (CK_ULONG))) == NULL)
3517c478bd9Sstevel@tonic-gate goto mem_failure;
3527c478bd9Sstevel@tonic-gate ENCODE_ATTR(CKA_MODULUS_BITS, &OBJ_PUB_RSA_MOD_BITS(object_p),
3537c478bd9Sstevel@tonic-gate sizeof (CK_ULONG));
3547c478bd9Sstevel@tonic-gate
3557c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object_p->object_mutex);
3567c478bd9Sstevel@tonic-gate return (CKR_OK);
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate mem_failure:
3597c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object_p->object_mutex);
3607c478bd9Sstevel@tonic-gate free_key_attributes(key);
3617c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY);
3627c478bd9Sstevel@tonic-gate }
3637c478bd9Sstevel@tonic-gate
3647c478bd9Sstevel@tonic-gate /*
3657c478bd9Sstevel@tonic-gate * Free attribute storage in a crypto_key structure.
3667c478bd9Sstevel@tonic-gate */
3677c478bd9Sstevel@tonic-gate void
free_key_attributes(crypto_key_t * key)3687c478bd9Sstevel@tonic-gate free_key_attributes(crypto_key_t *key)
3697c478bd9Sstevel@tonic-gate {
3707c478bd9Sstevel@tonic-gate int i;
3717c478bd9Sstevel@tonic-gate
3727c478bd9Sstevel@tonic-gate if (key->ck_format == CRYPTO_KEY_ATTR_LIST &&
3737c478bd9Sstevel@tonic-gate (key->ck_count > 0) && key->ck_attrs != NULL) {
3747c478bd9Sstevel@tonic-gate for (i = 0; i < key->ck_count; i++) {
375a8793c76SJason King freezero(key->ck_attrs[i].oa_value,
376a8793c76SJason King key->ck_attrs[i].oa_value_len);
3777c478bd9Sstevel@tonic-gate }
3787c478bd9Sstevel@tonic-gate free(key->ck_attrs);
3797c478bd9Sstevel@tonic-gate }
3807c478bd9Sstevel@tonic-gate }
3817c478bd9Sstevel@tonic-gate
3827c478bd9Sstevel@tonic-gate
3837c478bd9Sstevel@tonic-gate /*
3847c478bd9Sstevel@tonic-gate * Convert a DSA private key object into a crypto_key structure.
3857c478bd9Sstevel@tonic-gate * Memory is allocated for each attribute stored in the crypto_key
3867c478bd9Sstevel@tonic-gate * structure. Memory for the crypto_key structure is not
3877c478bd9Sstevel@tonic-gate * allocated. Attributes can be freed by free_dsa_key_attributes().
3887c478bd9Sstevel@tonic-gate */
3897c478bd9Sstevel@tonic-gate CK_RV
get_dsa_private_key(kernel_object_t * object_p,crypto_key_t * key)3907c478bd9Sstevel@tonic-gate get_dsa_private_key(kernel_object_t *object_p, crypto_key_t *key)
3917c478bd9Sstevel@tonic-gate {
3927c478bd9Sstevel@tonic-gate biginteger_t *big;
3937c478bd9Sstevel@tonic-gate crypto_object_attribute_t *attrs, *cur_attr;
3947c478bd9Sstevel@tonic-gate char *ptr;
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&object_p->object_mutex);
3977c478bd9Sstevel@tonic-gate if (object_p->key_type != CKK_DSA ||
3987c478bd9Sstevel@tonic-gate object_p->class != CKO_PRIVATE_KEY) {
3997c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object_p->object_mutex);
4007c478bd9Sstevel@tonic-gate return (CKR_ATTRIBUTE_TYPE_INVALID);
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate
4037c478bd9Sstevel@tonic-gate attrs = calloc(1,
4047c478bd9Sstevel@tonic-gate DSA_ATTR_COUNT * sizeof (crypto_object_attribute_t));
4057c478bd9Sstevel@tonic-gate if (attrs == NULL) {
4067c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object_p->object_mutex);
4077c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY);
4087c478bd9Sstevel@tonic-gate }
4097c478bd9Sstevel@tonic-gate
4107c478bd9Sstevel@tonic-gate key->ck_format = CRYPTO_KEY_ATTR_LIST;
4117c478bd9Sstevel@tonic-gate key->ck_count = DSA_ATTR_COUNT;
4127c478bd9Sstevel@tonic-gate key->ck_attrs = attrs;
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate cur_attr = attrs;
4157c478bd9Sstevel@tonic-gate big = OBJ_PRI_DSA_PRIME(object_p);
4167c478bd9Sstevel@tonic-gate if ((ptr = malloc(big->big_value_len)) == NULL)
4177c478bd9Sstevel@tonic-gate goto mem_failure;
4187c478bd9Sstevel@tonic-gate ENCODE_ATTR(CKA_PRIME, big->big_value, big->big_value_len);
4197c478bd9Sstevel@tonic-gate
4207c478bd9Sstevel@tonic-gate big = OBJ_PRI_DSA_SUBPRIME(object_p);
4217c478bd9Sstevel@tonic-gate if ((ptr = malloc(big->big_value_len)) == NULL)
4227c478bd9Sstevel@tonic-gate goto mem_failure;
4237c478bd9Sstevel@tonic-gate ENCODE_ATTR(CKA_SUBPRIME, big->big_value, big->big_value_len);
4247c478bd9Sstevel@tonic-gate
4257c478bd9Sstevel@tonic-gate big = OBJ_PRI_DSA_BASE(object_p);
4267c478bd9Sstevel@tonic-gate if ((ptr = malloc(big->big_value_len)) == NULL)
4277c478bd9Sstevel@tonic-gate goto mem_failure;
4287c478bd9Sstevel@tonic-gate ENCODE_ATTR(CKA_BASE, big->big_value, big->big_value_len);
4297c478bd9Sstevel@tonic-gate
4307c478bd9Sstevel@tonic-gate big = OBJ_PRI_DSA_VALUE(object_p);
4317c478bd9Sstevel@tonic-gate if ((ptr = malloc(big->big_value_len)) == NULL)
4327c478bd9Sstevel@tonic-gate goto mem_failure;
4337c478bd9Sstevel@tonic-gate ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
4347c478bd9Sstevel@tonic-gate
4357c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object_p->object_mutex);
4367c478bd9Sstevel@tonic-gate return (CKR_OK);
4377c478bd9Sstevel@tonic-gate
4387c478bd9Sstevel@tonic-gate mem_failure:
4397c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object_p->object_mutex);
4407c478bd9Sstevel@tonic-gate free_key_attributes(key);
4417c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY);
4427c478bd9Sstevel@tonic-gate }
4437c478bd9Sstevel@tonic-gate
4447c478bd9Sstevel@tonic-gate
4457c478bd9Sstevel@tonic-gate /*
4467c478bd9Sstevel@tonic-gate * Convert a DSA public key object into a crypto_key structure.
4477c478bd9Sstevel@tonic-gate * Memory is allocated for each attribute stored in the crypto_key
4487c478bd9Sstevel@tonic-gate * structure. Memory for the crypto_key structure is not
4497c478bd9Sstevel@tonic-gate * allocated. Attributes can be freed by free_dsa_key_attributes().
4507c478bd9Sstevel@tonic-gate */
4517c478bd9Sstevel@tonic-gate CK_RV
get_dsa_public_key(kernel_object_t * object_p,crypto_key_t * key)4527c478bd9Sstevel@tonic-gate get_dsa_public_key(kernel_object_t *object_p, crypto_key_t *key)
4537c478bd9Sstevel@tonic-gate {
4547c478bd9Sstevel@tonic-gate biginteger_t *big;
4557c478bd9Sstevel@tonic-gate crypto_object_attribute_t *attrs, *cur_attr;
4567c478bd9Sstevel@tonic-gate char *ptr;
4577c478bd9Sstevel@tonic-gate
4587c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&object_p->object_mutex);
4597c478bd9Sstevel@tonic-gate if (object_p->key_type != CKK_DSA ||
4607c478bd9Sstevel@tonic-gate object_p->class != CKO_PUBLIC_KEY) {
4617c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object_p->object_mutex);
4627c478bd9Sstevel@tonic-gate return (CKR_ATTRIBUTE_TYPE_INVALID);
4637c478bd9Sstevel@tonic-gate }
4647c478bd9Sstevel@tonic-gate
4657c478bd9Sstevel@tonic-gate attrs = calloc(1,
4667c478bd9Sstevel@tonic-gate DSA_ATTR_COUNT * sizeof (crypto_object_attribute_t));
4677c478bd9Sstevel@tonic-gate if (attrs == NULL) {
4687c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object_p->object_mutex);
4697c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY);
4707c478bd9Sstevel@tonic-gate }
4717c478bd9Sstevel@tonic-gate
4727c478bd9Sstevel@tonic-gate key->ck_format = CRYPTO_KEY_ATTR_LIST;
4737c478bd9Sstevel@tonic-gate key->ck_count = DSA_ATTR_COUNT;
4747c478bd9Sstevel@tonic-gate key->ck_attrs = attrs;
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate cur_attr = attrs;
4777c478bd9Sstevel@tonic-gate big = OBJ_PUB_DSA_PRIME(object_p);
4787c478bd9Sstevel@tonic-gate if ((ptr = malloc(big->big_value_len)) == NULL)
4797c478bd9Sstevel@tonic-gate goto mem_failure;
4807c478bd9Sstevel@tonic-gate ENCODE_ATTR(CKA_PRIME, big->big_value, big->big_value_len);
4817c478bd9Sstevel@tonic-gate
4827c478bd9Sstevel@tonic-gate big = OBJ_PUB_DSA_SUBPRIME(object_p);
4837c478bd9Sstevel@tonic-gate if ((ptr = malloc(big->big_value_len)) == NULL)
4847c478bd9Sstevel@tonic-gate goto mem_failure;
4857c478bd9Sstevel@tonic-gate ENCODE_ATTR(CKA_SUBPRIME, big->big_value, big->big_value_len);
4867c478bd9Sstevel@tonic-gate
4877c478bd9Sstevel@tonic-gate big = OBJ_PUB_DSA_BASE(object_p);
4887c478bd9Sstevel@tonic-gate if ((ptr = malloc(big->big_value_len)) == NULL)
4897c478bd9Sstevel@tonic-gate goto mem_failure;
4907c478bd9Sstevel@tonic-gate ENCODE_ATTR(CKA_BASE, big->big_value, big->big_value_len);
4917c478bd9Sstevel@tonic-gate
4927c478bd9Sstevel@tonic-gate big = OBJ_PUB_DSA_VALUE(object_p);
4937c478bd9Sstevel@tonic-gate if ((ptr = malloc(big->big_value_len)) == NULL)
4947c478bd9Sstevel@tonic-gate goto mem_failure;
4957c478bd9Sstevel@tonic-gate ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
4967c478bd9Sstevel@tonic-gate
4977c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object_p->object_mutex);
4987c478bd9Sstevel@tonic-gate return (CKR_OK);
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate mem_failure:
5017c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object_p->object_mutex);
5027c478bd9Sstevel@tonic-gate free_key_attributes(key);
5037c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY);
5047c478bd9Sstevel@tonic-gate }
5057c478bd9Sstevel@tonic-gate
5067c478bd9Sstevel@tonic-gate
507034448feSmcpowers /*
508034448feSmcpowers * Convert a EC private key object into a crypto_key structure.
509034448feSmcpowers * Memory is allocated for each attribute stored in the crypto_key
510034448feSmcpowers * structure. Memory for the crypto_key structure is not
511034448feSmcpowers * allocated. Attributes can be freed by free_ec_key_attributes().
512034448feSmcpowers */
513034448feSmcpowers CK_RV
get_ec_private_key(kernel_object_t * object_p,crypto_key_t * key)514034448feSmcpowers get_ec_private_key(kernel_object_t *object_p, crypto_key_t *key)
515034448feSmcpowers {
516034448feSmcpowers biginteger_t *big;
517034448feSmcpowers crypto_object_attribute_t *attrs, *cur_attr;
518034448feSmcpowers CK_ATTRIBUTE tmp;
519034448feSmcpowers char *ptr;
520034448feSmcpowers int rv;
521034448feSmcpowers
522034448feSmcpowers (void) pthread_mutex_lock(&object_p->object_mutex);
523034448feSmcpowers if (object_p->key_type != CKK_EC ||
524034448feSmcpowers object_p->class != CKO_PRIVATE_KEY) {
525034448feSmcpowers (void) pthread_mutex_unlock(&object_p->object_mutex);
526034448feSmcpowers return (CKR_ATTRIBUTE_TYPE_INVALID);
527034448feSmcpowers }
528034448feSmcpowers
529d2b32306Smcpowers attrs = calloc(EC_ATTR_COUNT, sizeof (crypto_object_attribute_t));
530034448feSmcpowers if (attrs == NULL) {
531034448feSmcpowers (void) pthread_mutex_unlock(&object_p->object_mutex);
532034448feSmcpowers return (CKR_HOST_MEMORY);
533034448feSmcpowers }
534034448feSmcpowers
535034448feSmcpowers key->ck_format = CRYPTO_KEY_ATTR_LIST;
536d2b32306Smcpowers key->ck_count = EC_ATTR_COUNT;
537034448feSmcpowers key->ck_attrs = attrs;
538034448feSmcpowers
539034448feSmcpowers cur_attr = attrs;
540034448feSmcpowers big = OBJ_PRI_EC_VALUE(object_p);
541034448feSmcpowers if ((ptr = malloc(big->big_value_len)) == NULL) {
542034448feSmcpowers rv = CKR_HOST_MEMORY;
543034448feSmcpowers goto fail;
544034448feSmcpowers }
545034448feSmcpowers ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
546034448feSmcpowers
547034448feSmcpowers tmp.type = CKA_EC_PARAMS;
548034448feSmcpowers tmp.pValue = NULL;
549034448feSmcpowers rv = kernel_get_attribute(object_p, &tmp);
550034448feSmcpowers if (rv != CKR_OK) {
551034448feSmcpowers goto fail;
552034448feSmcpowers }
553034448feSmcpowers
554034448feSmcpowers tmp.pValue = malloc(tmp.ulValueLen);
555034448feSmcpowers if (tmp.pValue == NULL) {
556034448feSmcpowers rv = CKR_HOST_MEMORY;
557034448feSmcpowers goto fail;
558034448feSmcpowers }
559034448feSmcpowers
560034448feSmcpowers rv = kernel_get_attribute(object_p, &tmp);
561034448feSmcpowers if (rv != CKR_OK) {
562034448feSmcpowers free(tmp.pValue);
563034448feSmcpowers goto fail;
564034448feSmcpowers }
565034448feSmcpowers
566034448feSmcpowers cur_attr->oa_type = tmp.type;
567034448feSmcpowers cur_attr->oa_value = tmp.pValue;
568034448feSmcpowers cur_attr->oa_value_len = tmp.ulValueLen;
569034448feSmcpowers
570034448feSmcpowers (void) pthread_mutex_unlock(&object_p->object_mutex);
571034448feSmcpowers return (CKR_OK);
572034448feSmcpowers
573034448feSmcpowers fail:
574034448feSmcpowers (void) pthread_mutex_unlock(&object_p->object_mutex);
575034448feSmcpowers free_key_attributes(key);
576034448feSmcpowers return (rv);
577034448feSmcpowers }
578034448feSmcpowers
579034448feSmcpowers /*
580034448feSmcpowers * Convert an EC public key object into a crypto_key structure.
581034448feSmcpowers * Memory is allocated for each attribute stored in the crypto_key
582034448feSmcpowers * structure. Memory for the crypto_key structure is not
583034448feSmcpowers * allocated. Attributes can be freed by free_ec_key_attributes().
584034448feSmcpowers */
585034448feSmcpowers CK_RV
get_ec_public_key(kernel_object_t * object_p,crypto_key_t * key)586034448feSmcpowers get_ec_public_key(kernel_object_t *object_p, crypto_key_t *key)
587034448feSmcpowers {
588034448feSmcpowers biginteger_t *big;
589034448feSmcpowers crypto_object_attribute_t *attrs, *cur_attr;
590d2b32306Smcpowers CK_ATTRIBUTE tmp;
591034448feSmcpowers char *ptr;
592d2b32306Smcpowers int rv;
593034448feSmcpowers
594034448feSmcpowers (void) pthread_mutex_lock(&object_p->object_mutex);
595034448feSmcpowers if (object_p->key_type != CKK_EC ||
596034448feSmcpowers object_p->class != CKO_PUBLIC_KEY) {
597034448feSmcpowers (void) pthread_mutex_unlock(&object_p->object_mutex);
598034448feSmcpowers return (CKR_ATTRIBUTE_TYPE_INVALID);
599034448feSmcpowers }
600034448feSmcpowers
601d2b32306Smcpowers attrs = calloc(EC_ATTR_COUNT, sizeof (crypto_object_attribute_t));
602034448feSmcpowers if (attrs == NULL) {
603034448feSmcpowers (void) pthread_mutex_unlock(&object_p->object_mutex);
604034448feSmcpowers return (CKR_HOST_MEMORY);
605034448feSmcpowers }
606034448feSmcpowers
607034448feSmcpowers key->ck_format = CRYPTO_KEY_ATTR_LIST;
608034448feSmcpowers key->ck_count = EC_ATTR_COUNT;
609034448feSmcpowers key->ck_attrs = attrs;
610034448feSmcpowers
611034448feSmcpowers cur_attr = attrs;
612034448feSmcpowers big = OBJ_PUB_EC_POINT(object_p);
613034448feSmcpowers if ((ptr = malloc(big->big_value_len)) == NULL) {
614d2b32306Smcpowers rv = CKR_HOST_MEMORY;
615d2b32306Smcpowers goto fail;
616034448feSmcpowers }
617034448feSmcpowers ENCODE_ATTR(CKA_EC_POINT, big->big_value, big->big_value_len);
618034448feSmcpowers
619d2b32306Smcpowers tmp.type = CKA_EC_PARAMS;
620d2b32306Smcpowers tmp.pValue = NULL;
621d2b32306Smcpowers rv = kernel_get_attribute(object_p, &tmp);
622d2b32306Smcpowers if (rv != CKR_OK) {
623d2b32306Smcpowers goto fail;
624d2b32306Smcpowers }
625d2b32306Smcpowers
626d2b32306Smcpowers tmp.pValue = malloc(tmp.ulValueLen);
627d2b32306Smcpowers if (tmp.pValue == NULL) {
628d2b32306Smcpowers rv = CKR_HOST_MEMORY;
629d2b32306Smcpowers goto fail;
630d2b32306Smcpowers }
631d2b32306Smcpowers
632d2b32306Smcpowers rv = kernel_get_attribute(object_p, &tmp);
633d2b32306Smcpowers if (rv != CKR_OK) {
634d2b32306Smcpowers free(tmp.pValue);
635d2b32306Smcpowers goto fail;
636d2b32306Smcpowers }
637d2b32306Smcpowers
638d2b32306Smcpowers cur_attr->oa_type = tmp.type;
639d2b32306Smcpowers cur_attr->oa_value = tmp.pValue;
640d2b32306Smcpowers cur_attr->oa_value_len = tmp.ulValueLen;
641d2b32306Smcpowers
642034448feSmcpowers (void) pthread_mutex_unlock(&object_p->object_mutex);
643034448feSmcpowers return (CKR_OK);
644d2b32306Smcpowers
645d2b32306Smcpowers fail:
646d2b32306Smcpowers (void) pthread_mutex_unlock(&object_p->object_mutex);
647d2b32306Smcpowers free_key_attributes(key);
648d2b32306Smcpowers return (rv);
649034448feSmcpowers }
650034448feSmcpowers
6517c478bd9Sstevel@tonic-gate /*
6527c478bd9Sstevel@tonic-gate * Convert an attribute template into an obj_attrs array.
6537c478bd9Sstevel@tonic-gate * Memory is allocated for each attribute stored in the obj_attrs.
6547c478bd9Sstevel@tonic-gate * The memory can be freed by free_object_attributes().
6557c478bd9Sstevel@tonic-gate *
6567c478bd9Sstevel@tonic-gate * If the boolean pointer is_token_obj is not NULL, the caller wants to
6577c478bd9Sstevel@tonic-gate * retrieve the value of the CKA_TOKEN attribute if it is specified in the
6587c478bd9Sstevel@tonic-gate * template.
6597c478bd9Sstevel@tonic-gate * - When this routine is called thru C_CreateObject(), C_CopyObject(), or
6607c478bd9Sstevel@tonic-gate * any key management function, is_token_obj should NOT be NULL.
6617c478bd9Sstevel@tonic-gate * - When this routine is called thru C_GetAttributeValue() or
6627c478bd9Sstevel@tonic-gate * C_SetAttributeValue(), "is_token_obj" should be NULL.
6637c478bd9Sstevel@tonic-gate */
6647c478bd9Sstevel@tonic-gate CK_RV
process_object_attributes(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,caddr_t * obj_attrs,CK_BBOOL * is_token_obj)6657c478bd9Sstevel@tonic-gate process_object_attributes(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
6667c478bd9Sstevel@tonic-gate caddr_t *obj_attrs, CK_BBOOL *is_token_obj)
6677c478bd9Sstevel@tonic-gate {
6687c478bd9Sstevel@tonic-gate crypto_object_attribute_t *attrs, *cur_attr;
6697c478bd9Sstevel@tonic-gate int i, cur_i;
6707c478bd9Sstevel@tonic-gate char *ptr;
6717c478bd9Sstevel@tonic-gate CK_RV rv;
6727c478bd9Sstevel@tonic-gate ssize_t value_len;
6737c478bd9Sstevel@tonic-gate
6747c478bd9Sstevel@tonic-gate if (ulCount == 0) {
6757c478bd9Sstevel@tonic-gate obj_attrs = NULL;
6767c478bd9Sstevel@tonic-gate return (CKR_OK);
6777c478bd9Sstevel@tonic-gate }
6787c478bd9Sstevel@tonic-gate
6797c478bd9Sstevel@tonic-gate attrs = calloc(1, ulCount * sizeof (crypto_object_attribute_t));
6807c478bd9Sstevel@tonic-gate if (attrs == NULL) {
6817c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY);
6827c478bd9Sstevel@tonic-gate }
6837c478bd9Sstevel@tonic-gate
6847c478bd9Sstevel@tonic-gate cur_attr = attrs;
6857c478bd9Sstevel@tonic-gate for (i = 0; i < ulCount; i++) {
6867c478bd9Sstevel@tonic-gate /*
6877c478bd9Sstevel@tonic-gate * The length of long attributes must be set correctly
6887c478bd9Sstevel@tonic-gate * so providers can determine whether they came from 32
6897c478bd9Sstevel@tonic-gate * or 64-bit applications.
6907c478bd9Sstevel@tonic-gate */
6917c478bd9Sstevel@tonic-gate switch (pTemplate[i].type) {
6927c478bd9Sstevel@tonic-gate case CKA_CLASS:
6937c478bd9Sstevel@tonic-gate case CKA_CERTIFICATE_TYPE:
6947c478bd9Sstevel@tonic-gate case CKA_KEY_TYPE:
695034448feSmcpowers case CKA_MODULUS_BITS:
6967c478bd9Sstevel@tonic-gate case CKA_HW_FEATURE_TYPE:
6977c478bd9Sstevel@tonic-gate value_len = sizeof (ulong_t);
698894b2776Smcpowers if (pTemplate[i].pValue != NULL &&
699894b2776Smcpowers (pTemplate[i].ulValueLen < value_len)) {
7007739299dSAnthony Scarpino rv = CKR_ATTRIBUTE_VALUE_INVALID;
7017c478bd9Sstevel@tonic-gate cur_i = i;
7027c478bd9Sstevel@tonic-gate goto fail_cleanup;
7037c478bd9Sstevel@tonic-gate }
7047c478bd9Sstevel@tonic-gate break;
7057c478bd9Sstevel@tonic-gate default:
7067c478bd9Sstevel@tonic-gate value_len = pTemplate[i].ulValueLen;
7077c478bd9Sstevel@tonic-gate }
7087c478bd9Sstevel@tonic-gate
7097c478bd9Sstevel@tonic-gate cur_attr->oa_type = pTemplate[i].type;
7107c478bd9Sstevel@tonic-gate cur_attr->oa_value_len = value_len;
7117c478bd9Sstevel@tonic-gate cur_attr->oa_value = NULL;
7127c478bd9Sstevel@tonic-gate
7137c478bd9Sstevel@tonic-gate if ((pTemplate[i].pValue != NULL) &&
7147c478bd9Sstevel@tonic-gate (pTemplate[i].ulValueLen > 0)) {
7157c478bd9Sstevel@tonic-gate ptr = malloc(pTemplate[i].ulValueLen);
7167c478bd9Sstevel@tonic-gate if (ptr == NULL) {
7177c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
7187c478bd9Sstevel@tonic-gate cur_i = i;
7197c478bd9Sstevel@tonic-gate goto fail_cleanup;
7207c478bd9Sstevel@tonic-gate } else {
7217c478bd9Sstevel@tonic-gate (void) memcpy(ptr, pTemplate[i].pValue,
7227c478bd9Sstevel@tonic-gate pTemplate[i].ulValueLen);
7237c478bd9Sstevel@tonic-gate cur_attr->oa_value = ptr;
7247c478bd9Sstevel@tonic-gate }
7257c478bd9Sstevel@tonic-gate }
7267c478bd9Sstevel@tonic-gate
7277c478bd9Sstevel@tonic-gate if ((is_token_obj != NULL) &&
7287c478bd9Sstevel@tonic-gate (pTemplate[i].type == CKA_TOKEN)) {
7297c478bd9Sstevel@tonic-gate /* Get the CKA_TOKEN attribute value. */
7307c478bd9Sstevel@tonic-gate if (pTemplate[i].pValue == NULL) {
7317c478bd9Sstevel@tonic-gate rv = CKR_ATTRIBUTE_VALUE_INVALID;
7327c478bd9Sstevel@tonic-gate cur_i = i;
7337c478bd9Sstevel@tonic-gate goto fail_cleanup;
7347c478bd9Sstevel@tonic-gate } else {
7357c478bd9Sstevel@tonic-gate *is_token_obj =
7367c478bd9Sstevel@tonic-gate *(CK_BBOOL *)pTemplate[i].pValue;
7377c478bd9Sstevel@tonic-gate }
7387c478bd9Sstevel@tonic-gate }
7397c478bd9Sstevel@tonic-gate
7407c478bd9Sstevel@tonic-gate cur_attr++;
7417c478bd9Sstevel@tonic-gate }
7427c478bd9Sstevel@tonic-gate
7437c478bd9Sstevel@tonic-gate *obj_attrs = (char *)attrs;
7447c478bd9Sstevel@tonic-gate return (CKR_OK);
7457c478bd9Sstevel@tonic-gate
7467c478bd9Sstevel@tonic-gate fail_cleanup:
7477c478bd9Sstevel@tonic-gate cur_attr = attrs;
7487c478bd9Sstevel@tonic-gate for (i = 0; i < cur_i; i++) {
7497c478bd9Sstevel@tonic-gate if (cur_attr->oa_value != NULL) {
7507c478bd9Sstevel@tonic-gate (void) free(cur_attr->oa_value);
7517c478bd9Sstevel@tonic-gate }
7527c478bd9Sstevel@tonic-gate cur_attr++;
7537c478bd9Sstevel@tonic-gate }
7547c478bd9Sstevel@tonic-gate
7557c478bd9Sstevel@tonic-gate (void) free(attrs);
7567c478bd9Sstevel@tonic-gate return (rv);
7577c478bd9Sstevel@tonic-gate }
7587c478bd9Sstevel@tonic-gate
7597c478bd9Sstevel@tonic-gate
7607c478bd9Sstevel@tonic-gate /*
7617c478bd9Sstevel@tonic-gate * Copy the attribute values from obj_attrs to pTemplate.
7627c478bd9Sstevel@tonic-gate * The obj_attrs is an image of the Template and is expected to have the
7637c478bd9Sstevel@tonic-gate * same attributes in the same order and each one of the attribute pValue
7647c478bd9Sstevel@tonic-gate * in obj_attr has enough space allocated for the corresponding valueLen
7657c478bd9Sstevel@tonic-gate * in pTemplate.
7667c478bd9Sstevel@tonic-gate */
7677c478bd9Sstevel@tonic-gate CK_RV
get_object_attributes(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,caddr_t obj_attrs)7687c478bd9Sstevel@tonic-gate get_object_attributes(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
7697c478bd9Sstevel@tonic-gate caddr_t obj_attrs)
7707c478bd9Sstevel@tonic-gate {
7717c478bd9Sstevel@tonic-gate crypto_object_attribute_t *cur_attr;
7727c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK;
7737c478bd9Sstevel@tonic-gate int i;
7747c478bd9Sstevel@tonic-gate
7757c478bd9Sstevel@tonic-gate /* LINTED */
7767c478bd9Sstevel@tonic-gate cur_attr = (crypto_object_attribute_t *)obj_attrs;
7777c478bd9Sstevel@tonic-gate for (i = 0; i < ulCount; i++) {
7787c478bd9Sstevel@tonic-gate if (pTemplate[i].type != cur_attr->oa_type) {
7797c478bd9Sstevel@tonic-gate /* The attribute type doesn't match, this is bad. */
7807c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
7817c478bd9Sstevel@tonic-gate return (rv);
7827c478bd9Sstevel@tonic-gate }
7837c478bd9Sstevel@tonic-gate
7847c478bd9Sstevel@tonic-gate pTemplate[i].ulValueLen = cur_attr->oa_value_len;
7857c478bd9Sstevel@tonic-gate
7867c478bd9Sstevel@tonic-gate if ((pTemplate[i].pValue != NULL) &&
7877c478bd9Sstevel@tonic-gate ((CK_LONG)pTemplate[i].ulValueLen != -1)) {
7887c478bd9Sstevel@tonic-gate (void) memcpy(pTemplate[i].pValue, cur_attr->oa_value,
7897c478bd9Sstevel@tonic-gate pTemplate[i].ulValueLen);
7907c478bd9Sstevel@tonic-gate }
7917c478bd9Sstevel@tonic-gate cur_attr++;
7927c478bd9Sstevel@tonic-gate }
7937c478bd9Sstevel@tonic-gate
7947c478bd9Sstevel@tonic-gate return (rv);
7957c478bd9Sstevel@tonic-gate }
7967c478bd9Sstevel@tonic-gate
7977c478bd9Sstevel@tonic-gate /*
7987c478bd9Sstevel@tonic-gate * Free the attribute storage in a crypto_object_attribute_t structure.
7997c478bd9Sstevel@tonic-gate */
8007c478bd9Sstevel@tonic-gate void
free_object_attributes(caddr_t obj_attrs,CK_ULONG ulCount)8017c478bd9Sstevel@tonic-gate free_object_attributes(caddr_t obj_attrs, CK_ULONG ulCount)
8027c478bd9Sstevel@tonic-gate {
8037c478bd9Sstevel@tonic-gate crypto_object_attribute_t *cur_attr;
8047c478bd9Sstevel@tonic-gate int i;
8057c478bd9Sstevel@tonic-gate
8067c478bd9Sstevel@tonic-gate if ((ulCount == 0) || (obj_attrs == NULL)) {
8077c478bd9Sstevel@tonic-gate return;
8087c478bd9Sstevel@tonic-gate }
8097c478bd9Sstevel@tonic-gate
8107c478bd9Sstevel@tonic-gate /* LINTED */
8117c478bd9Sstevel@tonic-gate cur_attr = (crypto_object_attribute_t *)obj_attrs;
8127c478bd9Sstevel@tonic-gate for (i = 0; i < ulCount; i++) {
813034448feSmcpowers /* XXX check that oa_value > 0 */
8147c478bd9Sstevel@tonic-gate if (cur_attr->oa_value != NULL) {
8157c478bd9Sstevel@tonic-gate free(cur_attr->oa_value);
8167c478bd9Sstevel@tonic-gate }
8177c478bd9Sstevel@tonic-gate cur_attr++;
8187c478bd9Sstevel@tonic-gate }
8197c478bd9Sstevel@tonic-gate
8207c478bd9Sstevel@tonic-gate free(obj_attrs);
8217c478bd9Sstevel@tonic-gate }
8227c478bd9Sstevel@tonic-gate
8237c478bd9Sstevel@tonic-gate /*
8247c478bd9Sstevel@tonic-gate * This function is called by process_found_objects(). It will check the
8257c478bd9Sstevel@tonic-gate * CKA_PRIVATE and CKA_TOKEN attributes for the kernel object "oid", then
8267c478bd9Sstevel@tonic-gate * initialize all the necessary fields in the object wrapper "objp".
8277c478bd9Sstevel@tonic-gate */
8287c478bd9Sstevel@tonic-gate static CK_RV
create_new_tobj_in_lib(kernel_slot_t * pslot,kernel_session_t * sp,kernel_object_t * objp,crypto_object_id_t oid)8297c478bd9Sstevel@tonic-gate create_new_tobj_in_lib(kernel_slot_t *pslot, kernel_session_t *sp,
8307c478bd9Sstevel@tonic-gate kernel_object_t *objp, crypto_object_id_t oid)
8317c478bd9Sstevel@tonic-gate {
8327c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK;
8337c478bd9Sstevel@tonic-gate crypto_object_get_attribute_value_t obj_ga;
8347c478bd9Sstevel@tonic-gate boolean_t is_pri_obj;
8357c478bd9Sstevel@tonic-gate boolean_t is_token_obj;
8367c478bd9Sstevel@tonic-gate CK_BBOOL pri_value, token_value;
8377c478bd9Sstevel@tonic-gate CK_ATTRIBUTE pTemplate[2];
8387c478bd9Sstevel@tonic-gate int r;
8397c478bd9Sstevel@tonic-gate
8407c478bd9Sstevel@tonic-gate /*
8417c478bd9Sstevel@tonic-gate * Make a CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE ioctl call to get this
8427c478bd9Sstevel@tonic-gate * kernel object's attribute values for CKA_PRIVATE and CKA_TOKEN.
8437c478bd9Sstevel@tonic-gate */
8447c478bd9Sstevel@tonic-gate obj_ga.og_session = sp->k_session;
8457c478bd9Sstevel@tonic-gate obj_ga.og_handle = oid;
8467c478bd9Sstevel@tonic-gate obj_ga.og_count = 2;
8477c478bd9Sstevel@tonic-gate
8487c478bd9Sstevel@tonic-gate pTemplate[0].type = CKA_PRIVATE;
8497c478bd9Sstevel@tonic-gate pTemplate[0].pValue = &pri_value;
8507c478bd9Sstevel@tonic-gate pTemplate[0].ulValueLen = sizeof (pri_value);
8517c478bd9Sstevel@tonic-gate pTemplate[1].type = CKA_TOKEN;
8527c478bd9Sstevel@tonic-gate pTemplate[1].pValue = &token_value;
8537c478bd9Sstevel@tonic-gate pTemplate[1].ulValueLen = sizeof (token_value);
8547c478bd9Sstevel@tonic-gate rv = process_object_attributes(pTemplate, 2, &obj_ga.og_attributes,
8557c478bd9Sstevel@tonic-gate NULL);
8567c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
8577c478bd9Sstevel@tonic-gate return (rv);
8587c478bd9Sstevel@tonic-gate }
8597c478bd9Sstevel@tonic-gate
8607c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
8617c478bd9Sstevel@tonic-gate &obj_ga)) < 0) {
8627c478bd9Sstevel@tonic-gate if (errno != EINTR)
8637c478bd9Sstevel@tonic-gate break;
8647c478bd9Sstevel@tonic-gate }
8657c478bd9Sstevel@tonic-gate if (r < 0) {
8667c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
8677c478bd9Sstevel@tonic-gate } else {
8687c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(obj_ga.og_return_value);
8697c478bd9Sstevel@tonic-gate }
8707c478bd9Sstevel@tonic-gate
8717c478bd9Sstevel@tonic-gate if (rv == CKR_OK) {
8727c478bd9Sstevel@tonic-gate rv = get_object_attributes(pTemplate, 2, obj_ga.og_attributes);
8737c478bd9Sstevel@tonic-gate if (rv == CKR_OK) {
8747c478bd9Sstevel@tonic-gate is_pri_obj = *(CK_BBOOL *)pTemplate[0].pValue;
8757c478bd9Sstevel@tonic-gate is_token_obj = *(CK_BBOOL *)pTemplate[1].pValue;
8767c478bd9Sstevel@tonic-gate }
8777c478bd9Sstevel@tonic-gate }
8787c478bd9Sstevel@tonic-gate
8797c478bd9Sstevel@tonic-gate free_object_attributes(obj_ga.og_attributes, 2);
8807c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
8817c478bd9Sstevel@tonic-gate return (rv);
8827c478bd9Sstevel@tonic-gate }
8837c478bd9Sstevel@tonic-gate
8847c478bd9Sstevel@tonic-gate /* Make sure it is a token object. */
8857c478bd9Sstevel@tonic-gate if (!is_token_obj) {
8867c478bd9Sstevel@tonic-gate rv = CKR_ATTRIBUTE_VALUE_INVALID;
8877c478bd9Sstevel@tonic-gate return (rv);
8887c478bd9Sstevel@tonic-gate }
8897c478bd9Sstevel@tonic-gate
8907c478bd9Sstevel@tonic-gate /* If it is a private object, make sure the user has logged in. */
8917c478bd9Sstevel@tonic-gate if (is_pri_obj && (pslot->sl_state != CKU_USER)) {
8927c478bd9Sstevel@tonic-gate rv = CKR_ATTRIBUTE_VALUE_INVALID;
8937c478bd9Sstevel@tonic-gate return (rv);
8947c478bd9Sstevel@tonic-gate }
8957c478bd9Sstevel@tonic-gate
8967c478bd9Sstevel@tonic-gate objp->is_lib_obj = B_FALSE;
8977c478bd9Sstevel@tonic-gate objp->k_handle = oid;
8987c478bd9Sstevel@tonic-gate objp->bool_attr_mask |= TOKEN_BOOL_ON;
8997c478bd9Sstevel@tonic-gate if (is_pri_obj) {
9007c478bd9Sstevel@tonic-gate objp->bool_attr_mask |= PRIVATE_BOOL_ON;
9017c478bd9Sstevel@tonic-gate } else {
9027c478bd9Sstevel@tonic-gate objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
9037c478bd9Sstevel@tonic-gate }
9047c478bd9Sstevel@tonic-gate
9057c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&objp->object_mutex, NULL);
9067c478bd9Sstevel@tonic-gate objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
9077c478bd9Sstevel@tonic-gate objp->session_handle = (CK_SESSION_HANDLE) sp;
9087c478bd9Sstevel@tonic-gate
9097c478bd9Sstevel@tonic-gate return (CKR_OK);
9107c478bd9Sstevel@tonic-gate }
9117c478bd9Sstevel@tonic-gate
9127c478bd9Sstevel@tonic-gate /*
9137c478bd9Sstevel@tonic-gate * This function processes the kernel object handles returned from the
9147c478bd9Sstevel@tonic-gate * CRYPTO_OBJECT_FIND_UPDATE ioctl and returns an object handle list
9157c478bd9Sstevel@tonic-gate * and the number of object handles to the caller - C_FindObjects().
9167c478bd9Sstevel@tonic-gate * The caller acquires the slot lock and the session lock.
9177c478bd9Sstevel@tonic-gate */
9187c478bd9Sstevel@tonic-gate CK_RV
process_found_objects(kernel_session_t * cur_sp,CK_OBJECT_HANDLE * obj_found,CK_ULONG * found_obj_count,crypto_object_find_update_t obj_fu)9197c478bd9Sstevel@tonic-gate process_found_objects(kernel_session_t *cur_sp, CK_OBJECT_HANDLE *obj_found,
9207c478bd9Sstevel@tonic-gate CK_ULONG *found_obj_count, crypto_object_find_update_t obj_fu)
9217c478bd9Sstevel@tonic-gate {
9227c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK;
9237c478bd9Sstevel@tonic-gate crypto_object_id_t *oid_p;
9247c478bd9Sstevel@tonic-gate kernel_slot_t *pslot;
9257c478bd9Sstevel@tonic-gate kernel_object_t *objp;
9267c478bd9Sstevel@tonic-gate kernel_object_t *objp1;
9277c478bd9Sstevel@tonic-gate kernel_object_t *new_tobj_list = NULL;
9287c478bd9Sstevel@tonic-gate kernel_session_t *sp;
9297c478bd9Sstevel@tonic-gate CK_ULONG num_obj_found = 0;
9307c478bd9Sstevel@tonic-gate boolean_t is_in_lib;
9317c478bd9Sstevel@tonic-gate int i;
9327c478bd9Sstevel@tonic-gate
9337c478bd9Sstevel@tonic-gate if (obj_fu.fu_count == 0) {
9347c478bd9Sstevel@tonic-gate *found_obj_count = 0;
9357c478bd9Sstevel@tonic-gate return (CKR_OK);
9367c478bd9Sstevel@tonic-gate }
9377c478bd9Sstevel@tonic-gate
9387c478bd9Sstevel@tonic-gate pslot = slot_table[cur_sp->ses_slotid];
9397c478bd9Sstevel@tonic-gate
9407c478bd9Sstevel@tonic-gate /* LINTED */
9417c478bd9Sstevel@tonic-gate oid_p = (crypto_object_id_t *)obj_fu.fu_handles;
9427c478bd9Sstevel@tonic-gate for (i = 0; i < obj_fu.fu_count; i++) {
9437c478bd9Sstevel@tonic-gate is_in_lib = B_FALSE;
9447c478bd9Sstevel@tonic-gate /*
9457c478bd9Sstevel@tonic-gate * Check if this oid has an object wrapper in the library
9467c478bd9Sstevel@tonic-gate * already. First, search the slot's token object list.
9477c478bd9Sstevel@tonic-gate */
9487c478bd9Sstevel@tonic-gate objp = pslot->sl_tobj_list;
9497c478bd9Sstevel@tonic-gate while (!is_in_lib && objp) {
9507c478bd9Sstevel@tonic-gate if (objp->k_handle == *oid_p) {
9517c478bd9Sstevel@tonic-gate is_in_lib = B_TRUE;
9527c478bd9Sstevel@tonic-gate } else {
9537c478bd9Sstevel@tonic-gate objp = objp->next;
9547c478bd9Sstevel@tonic-gate }
9557c478bd9Sstevel@tonic-gate }
9567c478bd9Sstevel@tonic-gate
9577c478bd9Sstevel@tonic-gate /*
9587c478bd9Sstevel@tonic-gate * If it is not in the slot's token object list,
9597c478bd9Sstevel@tonic-gate * search it in all the sessions.
9607c478bd9Sstevel@tonic-gate */
9617c478bd9Sstevel@tonic-gate if (!is_in_lib) {
9627c478bd9Sstevel@tonic-gate sp = pslot->sl_sess_list;
9637c478bd9Sstevel@tonic-gate while (!is_in_lib && sp) {
9647c478bd9Sstevel@tonic-gate objp = sp->object_list;
9657c478bd9Sstevel@tonic-gate while (!is_in_lib && objp) {
9667c478bd9Sstevel@tonic-gate if (objp->k_handle == *oid_p) {
9677c478bd9Sstevel@tonic-gate is_in_lib = B_TRUE;
9687c478bd9Sstevel@tonic-gate } else {
9697c478bd9Sstevel@tonic-gate objp = objp->next;
9707c478bd9Sstevel@tonic-gate }
9717c478bd9Sstevel@tonic-gate }
9727c478bd9Sstevel@tonic-gate sp = sp->next;
9737c478bd9Sstevel@tonic-gate }
9747c478bd9Sstevel@tonic-gate }
9757c478bd9Sstevel@tonic-gate
9767c478bd9Sstevel@tonic-gate /*
9777c478bd9Sstevel@tonic-gate * If this object is in the library already, add its object
9787c478bd9Sstevel@tonic-gate * wrapper to the returned find object list.
9797c478bd9Sstevel@tonic-gate */
9807c478bd9Sstevel@tonic-gate if (is_in_lib) {
9817c478bd9Sstevel@tonic-gate obj_found[num_obj_found++] = (CK_OBJECT_HANDLE)objp;
9827c478bd9Sstevel@tonic-gate }
9837c478bd9Sstevel@tonic-gate
9847c478bd9Sstevel@tonic-gate /*
9857c478bd9Sstevel@tonic-gate * If we still do not find it in the library. This object
9867c478bd9Sstevel@tonic-gate * must be a token object pre-existed in the HW provider.
9877c478bd9Sstevel@tonic-gate * We need to create an object wrapper for it in the library.
9887c478bd9Sstevel@tonic-gate */
9897c478bd9Sstevel@tonic-gate if (!is_in_lib) {
9907c478bd9Sstevel@tonic-gate objp1 = calloc(1, sizeof (kernel_object_t));
9917c478bd9Sstevel@tonic-gate if (objp1 == NULL) {
9927c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
9937c478bd9Sstevel@tonic-gate goto failed_exit;
9947c478bd9Sstevel@tonic-gate }
9957c478bd9Sstevel@tonic-gate rv = create_new_tobj_in_lib(pslot, cur_sp, objp1,
9967c478bd9Sstevel@tonic-gate *oid_p);
9977c478bd9Sstevel@tonic-gate
9987c478bd9Sstevel@tonic-gate if (rv == CKR_OK) {
9997c478bd9Sstevel@tonic-gate /* Save the new object to the new_tobj_list. */
10007c478bd9Sstevel@tonic-gate if (new_tobj_list == NULL) {
10017c478bd9Sstevel@tonic-gate new_tobj_list = objp1;
10027c478bd9Sstevel@tonic-gate objp1->next = NULL;
10037c478bd9Sstevel@tonic-gate objp1->prev = NULL;
10047c478bd9Sstevel@tonic-gate } else {
10057c478bd9Sstevel@tonic-gate new_tobj_list->prev = objp1;
10067c478bd9Sstevel@tonic-gate objp1->next = new_tobj_list;
10077c478bd9Sstevel@tonic-gate objp1->prev = NULL;
10087c478bd9Sstevel@tonic-gate new_tobj_list = objp1;
10097c478bd9Sstevel@tonic-gate }
10107c478bd9Sstevel@tonic-gate } else {
10117c478bd9Sstevel@tonic-gate /*
10127c478bd9Sstevel@tonic-gate * If create_new_tobj_in_lib() doesn't fail
10137c478bd9Sstevel@tonic-gate * with CKR_HOST_MEMORY, the failure should be
10147c478bd9Sstevel@tonic-gate * caused by the attributes' checking. We will
10157c478bd9Sstevel@tonic-gate * just ignore this object and continue on.
10167c478bd9Sstevel@tonic-gate */
10177c478bd9Sstevel@tonic-gate free(objp1);
10187c478bd9Sstevel@tonic-gate if (rv == CKR_HOST_MEMORY) {
10197c478bd9Sstevel@tonic-gate goto failed_exit;
10207c478bd9Sstevel@tonic-gate }
10217c478bd9Sstevel@tonic-gate }
10227c478bd9Sstevel@tonic-gate }
10237c478bd9Sstevel@tonic-gate
10247c478bd9Sstevel@tonic-gate /* Process next one */
10257c478bd9Sstevel@tonic-gate oid_p++;
10267c478bd9Sstevel@tonic-gate }
10277c478bd9Sstevel@tonic-gate
10287c478bd9Sstevel@tonic-gate /*
10297c478bd9Sstevel@tonic-gate * Add the newly created token object wrappers to the found object
10307c478bd9Sstevel@tonic-gate * list and to the slot's token object list.
10317c478bd9Sstevel@tonic-gate */
10327c478bd9Sstevel@tonic-gate if (new_tobj_list != NULL) {
10337c478bd9Sstevel@tonic-gate /* Add to the obj_found array. */
10347c478bd9Sstevel@tonic-gate objp = new_tobj_list;
10357c478bd9Sstevel@tonic-gate while (objp) {
10367c478bd9Sstevel@tonic-gate obj_found[num_obj_found++] = (CK_OBJECT_HANDLE)objp;
10377c478bd9Sstevel@tonic-gate if (objp->next == NULL) {
10387c478bd9Sstevel@tonic-gate break;
10397c478bd9Sstevel@tonic-gate }
10407c478bd9Sstevel@tonic-gate objp = objp->next;
10417c478bd9Sstevel@tonic-gate }
10427c478bd9Sstevel@tonic-gate
10437c478bd9Sstevel@tonic-gate /* Add to the beginning of the slot's token object list. */
10447c478bd9Sstevel@tonic-gate if (pslot->sl_tobj_list != NULL) {
10457c478bd9Sstevel@tonic-gate objp->next = pslot->sl_tobj_list;
10467c478bd9Sstevel@tonic-gate pslot->sl_tobj_list->prev = objp;
10477c478bd9Sstevel@tonic-gate }
10487c478bd9Sstevel@tonic-gate pslot->sl_tobj_list = new_tobj_list;
10497c478bd9Sstevel@tonic-gate }
10507c478bd9Sstevel@tonic-gate
10517c478bd9Sstevel@tonic-gate *found_obj_count = num_obj_found;
10527c478bd9Sstevel@tonic-gate return (CKR_OK);
10537c478bd9Sstevel@tonic-gate
10547c478bd9Sstevel@tonic-gate failed_exit:
10557c478bd9Sstevel@tonic-gate
10567c478bd9Sstevel@tonic-gate /* Free the newly created token object wrappers. */
10577c478bd9Sstevel@tonic-gate objp = new_tobj_list;
10587c478bd9Sstevel@tonic-gate while (objp) {
10597c478bd9Sstevel@tonic-gate objp1 = objp->next;
10607c478bd9Sstevel@tonic-gate (void) pthread_mutex_destroy(&objp->object_mutex);
10617c478bd9Sstevel@tonic-gate free(objp);
10627c478bd9Sstevel@tonic-gate objp = objp1;
10637c478bd9Sstevel@tonic-gate }
10647c478bd9Sstevel@tonic-gate
10657c478bd9Sstevel@tonic-gate return (rv);
10667c478bd9Sstevel@tonic-gate }
10677c478bd9Sstevel@tonic-gate
10687c478bd9Sstevel@tonic-gate
10697c478bd9Sstevel@tonic-gate /*
10707c478bd9Sstevel@tonic-gate * Get the value of the CKA_PRIVATE attribute for the object just returned
10717c478bd9Sstevel@tonic-gate * from the HW provider. This function will be called by any function
10727c478bd9Sstevel@tonic-gate * that creates a new object, because the CKA_PRIVATE value of an object is
10732321aa36Sda * token specific. The CKA_PRIVATE attribute value of the new object will be
10747c478bd9Sstevel@tonic-gate * stored in the object structure in the library, which will be used later at
10757c478bd9Sstevel@tonic-gate * C_Logout to clean up all private objects.
10767c478bd9Sstevel@tonic-gate */
10777c478bd9Sstevel@tonic-gate CK_RV
get_cka_private_value(kernel_session_t * sp,crypto_object_id_t oid,CK_BBOOL * is_pri_obj)10787c478bd9Sstevel@tonic-gate get_cka_private_value(kernel_session_t *sp, crypto_object_id_t oid,
10797c478bd9Sstevel@tonic-gate CK_BBOOL *is_pri_obj)
10807c478bd9Sstevel@tonic-gate {
10817c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK;
10827c478bd9Sstevel@tonic-gate crypto_object_get_attribute_value_t obj_ga;
10837c478bd9Sstevel@tonic-gate crypto_object_attribute_t obj_attr;
10847c478bd9Sstevel@tonic-gate CK_BBOOL pri_value;
10857c478bd9Sstevel@tonic-gate int r;
10867c478bd9Sstevel@tonic-gate
10877c478bd9Sstevel@tonic-gate obj_ga.og_session = sp->k_session;
10887c478bd9Sstevel@tonic-gate obj_ga.og_handle = oid;
10897c478bd9Sstevel@tonic-gate obj_ga.og_count = 1;
10907c478bd9Sstevel@tonic-gate
10917c478bd9Sstevel@tonic-gate obj_attr.oa_type = CKA_PRIVATE;
10927c478bd9Sstevel@tonic-gate obj_attr.oa_value = (char *)&pri_value;
10937c478bd9Sstevel@tonic-gate obj_attr.oa_value_len = sizeof (CK_BBOOL);
10947c478bd9Sstevel@tonic-gate obj_ga.og_attributes = (char *)&obj_attr;
10957c478bd9Sstevel@tonic-gate
10967c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
10977c478bd9Sstevel@tonic-gate &obj_ga)) < 0) {
10987c478bd9Sstevel@tonic-gate if (errno != EINTR)
10997c478bd9Sstevel@tonic-gate break;
11007c478bd9Sstevel@tonic-gate }
11017c478bd9Sstevel@tonic-gate if (r < 0) {
11027c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
11037c478bd9Sstevel@tonic-gate } else {
11047c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(obj_ga.og_return_value);
11057c478bd9Sstevel@tonic-gate }
11067c478bd9Sstevel@tonic-gate
11077c478bd9Sstevel@tonic-gate if (rv == CKR_OK) {
11087c478bd9Sstevel@tonic-gate *is_pri_obj = *(CK_BBOOL *)obj_attr.oa_value;
11097c478bd9Sstevel@tonic-gate }
11107c478bd9Sstevel@tonic-gate
11117c478bd9Sstevel@tonic-gate return (rv);
11127c478bd9Sstevel@tonic-gate }
11137c478bd9Sstevel@tonic-gate
11147c478bd9Sstevel@tonic-gate
11157c478bd9Sstevel@tonic-gate CK_RV
get_mechanism_info(kernel_slot_t * pslot,CK_MECHANISM_TYPE type,CK_MECHANISM_INFO_PTR pInfo,uint32_t * k_mi_flags)11167c478bd9Sstevel@tonic-gate get_mechanism_info(kernel_slot_t *pslot, CK_MECHANISM_TYPE type,
11177c478bd9Sstevel@tonic-gate CK_MECHANISM_INFO_PTR pInfo, uint32_t *k_mi_flags)
11187c478bd9Sstevel@tonic-gate {
11197c478bd9Sstevel@tonic-gate crypto_get_provider_mechanism_info_t mechanism_info;
11202321aa36Sda const char *string;
11217c478bd9Sstevel@tonic-gate CK_FLAGS flags, mi_flags;
11227c478bd9Sstevel@tonic-gate CK_RV rv;
11237c478bd9Sstevel@tonic-gate int r;
11242321aa36Sda char buf[11]; /* Num chars for representing ulong in ASCII */
11252321aa36Sda
112676d1b5a9Sda if (type >= CKM_VENDOR_DEFINED) {
11272321aa36Sda /* allocate/build a string containing the mechanism number */
11282321aa36Sda (void) snprintf(buf, sizeof (buf), "%#lx", type);
11292321aa36Sda string = buf;
11302321aa36Sda } else {
11312321aa36Sda string = pkcs11_mech2str(type);
11322321aa36Sda }
11337c478bd9Sstevel@tonic-gate
11347c478bd9Sstevel@tonic-gate if (string == NULL)
11357c478bd9Sstevel@tonic-gate return (CKR_MECHANISM_INVALID);
11367c478bd9Sstevel@tonic-gate
11377c478bd9Sstevel@tonic-gate (void) strcpy(mechanism_info.mi_mechanism_name, string);
11387c478bd9Sstevel@tonic-gate mechanism_info.mi_provider_id = pslot->sl_provider_id;
11397c478bd9Sstevel@tonic-gate
11407c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_MECHANISM_INFO,
11417c478bd9Sstevel@tonic-gate &mechanism_info)) < 0) {
11427c478bd9Sstevel@tonic-gate if (errno != EINTR)
11437c478bd9Sstevel@tonic-gate break;
11447c478bd9Sstevel@tonic-gate }
11457c478bd9Sstevel@tonic-gate if (r < 0) {
11467c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
11477c478bd9Sstevel@tonic-gate } else {
11487c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(
11497c478bd9Sstevel@tonic-gate mechanism_info.mi_return_value);
11507c478bd9Sstevel@tonic-gate }
11517c478bd9Sstevel@tonic-gate
11527c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
11532321aa36Sda return (rv);
11547c478bd9Sstevel@tonic-gate }
11557c478bd9Sstevel@tonic-gate
11567c478bd9Sstevel@tonic-gate /*
11577c478bd9Sstevel@tonic-gate * Atomic flags are not part of PKCS#11 so we filter
11587c478bd9Sstevel@tonic-gate * them out here.
11597c478bd9Sstevel@tonic-gate */
11607c478bd9Sstevel@tonic-gate mi_flags = mechanism_info.mi_flags;
11617c478bd9Sstevel@tonic-gate mi_flags &= ~(CRYPTO_FG_DIGEST_ATOMIC | CRYPTO_FG_ENCRYPT_ATOMIC |
11627c478bd9Sstevel@tonic-gate CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_MAC_ATOMIC |
11637c478bd9Sstevel@tonic-gate CRYPTO_FG_SIGN_ATOMIC | CRYPTO_FG_VERIFY_ATOMIC |
11647c478bd9Sstevel@tonic-gate CRYPTO_FG_SIGN_RECOVER_ATOMIC |
11657c478bd9Sstevel@tonic-gate CRYPTO_FG_VERIFY_RECOVER_ATOMIC |
11667c478bd9Sstevel@tonic-gate CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
11677c478bd9Sstevel@tonic-gate CRYPTO_FG_MAC_DECRYPT_ATOMIC);
11687c478bd9Sstevel@tonic-gate
11697c478bd9Sstevel@tonic-gate if (mi_flags == 0) {
11702321aa36Sda return (CKR_MECHANISM_INVALID);
11717c478bd9Sstevel@tonic-gate }
11727c478bd9Sstevel@tonic-gate
11737c478bd9Sstevel@tonic-gate if (rv == CKR_OK) {
11747c478bd9Sstevel@tonic-gate /* set the value of k_mi_flags first */
11757c478bd9Sstevel@tonic-gate *k_mi_flags = mi_flags;
11767c478bd9Sstevel@tonic-gate
11777c478bd9Sstevel@tonic-gate /* convert KEF flags into pkcs11 flags */
11787c478bd9Sstevel@tonic-gate flags = CKF_HW;
11797c478bd9Sstevel@tonic-gate if (mi_flags & CRYPTO_FG_ENCRYPT)
11807c478bd9Sstevel@tonic-gate flags |= CKF_ENCRYPT;
11817c478bd9Sstevel@tonic-gate if (mi_flags & CRYPTO_FG_DECRYPT) {
11827c478bd9Sstevel@tonic-gate flags |= CKF_DECRYPT;
11837c478bd9Sstevel@tonic-gate /*
11847c478bd9Sstevel@tonic-gate * Since we'll be emulating C_UnwrapKey() for some
11857c478bd9Sstevel@tonic-gate * cases, we can go ahead and claim CKF_UNWRAP
11867c478bd9Sstevel@tonic-gate */
11877c478bd9Sstevel@tonic-gate flags |= CKF_UNWRAP;
11887c478bd9Sstevel@tonic-gate }
11897c478bd9Sstevel@tonic-gate if (mi_flags & CRYPTO_FG_DIGEST)
11907c478bd9Sstevel@tonic-gate flags |= CKF_DIGEST;
11917c478bd9Sstevel@tonic-gate if (mi_flags & CRYPTO_FG_SIGN)
11927c478bd9Sstevel@tonic-gate flags |= CKF_SIGN;
11937c478bd9Sstevel@tonic-gate if (mi_flags & CRYPTO_FG_SIGN_RECOVER)
11947c478bd9Sstevel@tonic-gate flags |= CKF_SIGN_RECOVER;
11957c478bd9Sstevel@tonic-gate if (mi_flags & CRYPTO_FG_VERIFY)
11967c478bd9Sstevel@tonic-gate flags |= CKF_VERIFY;
11977c478bd9Sstevel@tonic-gate if (mi_flags & CRYPTO_FG_VERIFY_RECOVER)
11987c478bd9Sstevel@tonic-gate flags |= CKF_VERIFY_RECOVER;
11997c478bd9Sstevel@tonic-gate if (mi_flags & CRYPTO_FG_GENERATE)
12007c478bd9Sstevel@tonic-gate flags |= CKF_GENERATE;
12017c478bd9Sstevel@tonic-gate if (mi_flags & CRYPTO_FG_GENERATE_KEY_PAIR)
12027c478bd9Sstevel@tonic-gate flags |= CKF_GENERATE_KEY_PAIR;
12037c478bd9Sstevel@tonic-gate if (mi_flags & CRYPTO_FG_WRAP)
12047c478bd9Sstevel@tonic-gate flags |= CKF_WRAP;
12057c478bd9Sstevel@tonic-gate if (mi_flags & CRYPTO_FG_UNWRAP)
12067c478bd9Sstevel@tonic-gate flags |= CKF_UNWRAP;
12077c478bd9Sstevel@tonic-gate if (mi_flags & CRYPTO_FG_DERIVE)
12087c478bd9Sstevel@tonic-gate flags |= CKF_DERIVE;
12097c478bd9Sstevel@tonic-gate
12107c478bd9Sstevel@tonic-gate pInfo->ulMinKeySize = mechanism_info.mi_min_key_size;
12117c478bd9Sstevel@tonic-gate pInfo->ulMaxKeySize = mechanism_info.mi_max_key_size;
12127c478bd9Sstevel@tonic-gate pInfo->flags = flags;
12137c478bd9Sstevel@tonic-gate
12147c478bd9Sstevel@tonic-gate }
12157c478bd9Sstevel@tonic-gate
12167c478bd9Sstevel@tonic-gate return (rv);
12177c478bd9Sstevel@tonic-gate }
1218*fb261280SJason King
1219*fb261280SJason King /*
1220*fb261280SJason King * Unfortunately the kernel and PKCS#11 use a slightly different struct to
1221*fb261280SJason King * specify CCM parameters.
1222*fb261280SJason King */
1223*fb261280SJason King void
p11_to_kernel_ccm_params(const CK_CCM_PARAMS * in,CK_AES_CCM_PARAMS * out)1224*fb261280SJason King p11_to_kernel_ccm_params(const CK_CCM_PARAMS *in, CK_AES_CCM_PARAMS *out)
1225*fb261280SJason King {
1226*fb261280SJason King out->ulMACSize = in->ulMACLen;
1227*fb261280SJason King out->ulNonceSize = in->ulNonceLen;
1228*fb261280SJason King out->ulAuthDataSize = in->ulAADLen;
1229*fb261280SJason King out->ulDataSize = in->ulDataLen;
1230*fb261280SJason King out->nonce = in->pNonce;
1231*fb261280SJason King out->authData = in->pAAD;
1232*fb261280SJason King }
1233