#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <cryptoutil.h>
#include <errno.h>
#include <security/cryptoki.h>
#include <sys/crypto/common.h>
#include <sys/crypto/ioctl.h>
#include "kernelGlobal.h"
#include "kernelObject.h"
#include "kernelSlot.h"
#define ENCODE_ATTR(type, value, len) { \
cur_attr->oa_type = type; \
(void) memcpy(ptr, value, len); \
cur_attr->oa_value = ptr; \
cur_attr->oa_value_len = len; \
cur_attr++; \
}
#define MECH_HASH(type) (((uintptr_t)type) % KMECH_HASHTABLE_SIZE)
pthread_mutex_t mechhash_mutex = PTHREAD_MUTEX_INITIALIZER;
static CK_RV
kmech_hash_insert(CK_MECHANISM_TYPE type, crypto_mech_type_t kmech)
{
uint_t h;
kmh_elem_t *elem, *cur;
elem = malloc(sizeof (kmh_elem_t));
if (elem == NULL)
return (CKR_HOST_MEMORY);
h = MECH_HASH(type);
elem->type = type;
elem->kmech = kmech;
(void) pthread_mutex_lock(&mechhash_mutex);
for (cur = kernel_mechhash[h]; cur != NULL; cur = cur->knext) {
if (type == cur->type) {
(void) pthread_mutex_unlock(&mechhash_mutex);
free(elem);
return (CKR_OK);
}
}
elem->knext = kernel_mechhash[h];
kernel_mechhash[h] = elem;
(void) pthread_mutex_unlock(&mechhash_mutex);
return (CKR_OK);
}
CK_RV
kernel_mech(CK_MECHANISM_TYPE type, crypto_mech_type_t *k_number)
{
crypto_get_mechanism_number_t get_number;
const char *string;
CK_RV rv;
int r;
kmh_elem_t *elem;
uint_t h;
char buf[11];
h = MECH_HASH(type);
for (elem = kernel_mechhash[h]; elem != NULL; elem = elem->knext) {
if (type == elem->type) {
*k_number = elem->kmech;
return (CKR_OK);
}
}
if (type >= CKM_VENDOR_DEFINED) {
(void) snprintf(buf, sizeof (buf), "%#lx", type);
string = buf;
} else {
string = pkcs11_mech2str(type);
}
if (string == NULL)
return (CKR_MECHANISM_INVALID);
get_number.pn_mechanism_string = (char *)string;
get_number.pn_mechanism_len = strlen(string) + 1;
while ((r = ioctl(kernel_fd, CRYPTO_GET_MECHANISM_NUMBER,
&get_number)) < 0) {
if (errno != EINTR)
break;
}
if (r < 0) {
rv = CKR_MECHANISM_INVALID;
} else {
if (get_number.pn_return_value != CRYPTO_SUCCESS) {
rv = crypto2pkcs11_error_number(
get_number.pn_return_value);
} else {
rv = CKR_OK;
}
}
if (rv == CKR_OK) {
*k_number = get_number.pn_internal_number;
(void) kmech_hash_insert(type, *k_number);
}
return (rv);
}
unsigned char *
get_symmetric_key_value(kernel_object_t *key_p)
{
uint8_t *cipherKey;
switch (key_p->class) {
case CKO_SECRET_KEY:
cipherKey = malloc(OBJ_SEC(key_p)->sk_value_len);
if (cipherKey == NULL)
return (NULL);
(void) memcpy(cipherKey, OBJ_SEC(key_p)->sk_value,
OBJ_SEC(key_p)->sk_value_len);
return (cipherKey);
default:
return (NULL);
}
}
CK_RV
get_rsa_private_key(kernel_object_t *object_p, crypto_key_t *key)
{
biginteger_t *big;
crypto_object_attribute_t *attrs, *cur_attr;
char *ptr;
CK_RV rv;
(void) pthread_mutex_lock(&object_p->object_mutex);
if (object_p->key_type != CKK_RSA ||
object_p->class != CKO_PRIVATE_KEY) {
(void) pthread_mutex_unlock(&object_p->object_mutex);
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
attrs = calloc(1,
RSA_PRI_ATTR_COUNT * sizeof (crypto_object_attribute_t));
if (attrs == NULL) {
(void) pthread_mutex_unlock(&object_p->object_mutex);
return (CKR_HOST_MEMORY);
}
key->ck_format = CRYPTO_KEY_ATTR_LIST;
key->ck_attrs = attrs;
cur_attr = attrs;
key->ck_count = 0;
big = OBJ_PRI_RSA_MOD(object_p);
if (big->big_value == NULL) {
rv = CKR_ATTRIBUTE_TYPE_INVALID;
goto fail_cleanup;
} else {
if ((ptr = malloc(big->big_value_len)) == NULL) {
rv = CKR_HOST_MEMORY;
goto fail_cleanup;
}
ENCODE_ATTR(CKA_MODULUS, big->big_value, big->big_value_len);
key->ck_count++;
}
big = OBJ_PRI_RSA_PRIEXPO(object_p);
if (big->big_value == NULL) {
rv = CKR_ATTRIBUTE_TYPE_INVALID;
goto fail_cleanup;
} else {
if ((ptr = malloc(big->big_value_len)) == NULL) {
rv = CKR_HOST_MEMORY;
goto fail_cleanup;
}
ENCODE_ATTR(CKA_PRIVATE_EXPONENT, big->big_value,
big->big_value_len);
key->ck_count++;
}
big = OBJ_PRI_RSA_PRIME1(object_p);
if (big->big_value != NULL) {
if ((ptr = malloc(big->big_value_len)) == NULL) {
rv = CKR_HOST_MEMORY;
goto fail_cleanup;
}
ENCODE_ATTR(CKA_PRIME_1, big->big_value, big->big_value_len);
key->ck_count++;
}
big = OBJ_PRI_RSA_PRIME2(object_p);
if (big->big_value != NULL) {
if ((ptr = malloc(big->big_value_len)) == NULL) {
rv = CKR_HOST_MEMORY;
goto fail_cleanup;
}
ENCODE_ATTR(CKA_PRIME_2, big->big_value, big->big_value_len);
key->ck_count++;
}
big = OBJ_PRI_RSA_EXPO1(object_p);
if (big->big_value != NULL) {
if ((ptr = malloc(big->big_value_len)) == NULL) {
rv = CKR_HOST_MEMORY;
goto fail_cleanup;
}
ENCODE_ATTR(CKA_EXPONENT_1, big->big_value,
big->big_value_len);
key->ck_count++;
}
big = OBJ_PRI_RSA_EXPO2(object_p);
if (big->big_value != NULL) {
if ((ptr = malloc(big->big_value_len)) == NULL) {
rv = CKR_HOST_MEMORY;
goto fail_cleanup;
}
ENCODE_ATTR(CKA_EXPONENT_2, big->big_value,
big->big_value_len);
key->ck_count++;
}
big = OBJ_PRI_RSA_COEF(object_p);
if (big->big_value != NULL) {
if ((ptr = malloc(big->big_value_len)) == NULL) {
rv = CKR_HOST_MEMORY;
goto fail_cleanup;
}
ENCODE_ATTR(CKA_COEFFICIENT, big->big_value,
big->big_value_len);
key->ck_count++;
}
(void) pthread_mutex_unlock(&object_p->object_mutex);
return (CKR_OK);
fail_cleanup:
(void) pthread_mutex_unlock(&object_p->object_mutex);
free_key_attributes(key);
return (rv);
}
CK_RV
get_rsa_public_key(kernel_object_t *object_p, crypto_key_t *key)
{
biginteger_t *big;
crypto_object_attribute_t *attrs, *cur_attr;
char *ptr;
(void) pthread_mutex_lock(&object_p->object_mutex);
if (object_p->key_type != CKK_RSA ||
object_p->class != CKO_PUBLIC_KEY) {
(void) pthread_mutex_unlock(&object_p->object_mutex);
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
attrs = calloc(1,
RSA_PUB_ATTR_COUNT * sizeof (crypto_object_attribute_t));
if (attrs == NULL) {
(void) pthread_mutex_unlock(&object_p->object_mutex);
return (CKR_HOST_MEMORY);
}
key->ck_format = CRYPTO_KEY_ATTR_LIST;
key->ck_count = RSA_PUB_ATTR_COUNT;
key->ck_attrs = attrs;
cur_attr = attrs;
big = OBJ_PUB_RSA_PUBEXPO(object_p);
if ((ptr = malloc(big->big_value_len)) == NULL)
goto mem_failure;
ENCODE_ATTR(CKA_PUBLIC_EXPONENT, big->big_value, big->big_value_len);
big = OBJ_PUB_RSA_MOD(object_p);
if ((ptr = malloc(big->big_value_len)) == NULL)
goto mem_failure;
ENCODE_ATTR(CKA_MODULUS, big->big_value, big->big_value_len);
if ((ptr = malloc(sizeof (CK_ULONG))) == NULL)
goto mem_failure;
ENCODE_ATTR(CKA_MODULUS_BITS, &OBJ_PUB_RSA_MOD_BITS(object_p),
sizeof (CK_ULONG));
(void) pthread_mutex_unlock(&object_p->object_mutex);
return (CKR_OK);
mem_failure:
(void) pthread_mutex_unlock(&object_p->object_mutex);
free_key_attributes(key);
return (CKR_HOST_MEMORY);
}
void
free_key_attributes(crypto_key_t *key)
{
int i;
if (key->ck_format == CRYPTO_KEY_ATTR_LIST &&
(key->ck_count > 0) && key->ck_attrs != NULL) {
for (i = 0; i < key->ck_count; i++) {
freezero(key->ck_attrs[i].oa_value,
key->ck_attrs[i].oa_value_len);
}
free(key->ck_attrs);
}
}
CK_RV
get_dsa_private_key(kernel_object_t *object_p, crypto_key_t *key)
{
biginteger_t *big;
crypto_object_attribute_t *attrs, *cur_attr;
char *ptr;
(void) pthread_mutex_lock(&object_p->object_mutex);
if (object_p->key_type != CKK_DSA ||
object_p->class != CKO_PRIVATE_KEY) {
(void) pthread_mutex_unlock(&object_p->object_mutex);
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
attrs = calloc(1,
DSA_ATTR_COUNT * sizeof (crypto_object_attribute_t));
if (attrs == NULL) {
(void) pthread_mutex_unlock(&object_p->object_mutex);
return (CKR_HOST_MEMORY);
}
key->ck_format = CRYPTO_KEY_ATTR_LIST;
key->ck_count = DSA_ATTR_COUNT;
key->ck_attrs = attrs;
cur_attr = attrs;
big = OBJ_PRI_DSA_PRIME(object_p);
if ((ptr = malloc(big->big_value_len)) == NULL)
goto mem_failure;
ENCODE_ATTR(CKA_PRIME, big->big_value, big->big_value_len);
big = OBJ_PRI_DSA_SUBPRIME(object_p);
if ((ptr = malloc(big->big_value_len)) == NULL)
goto mem_failure;
ENCODE_ATTR(CKA_SUBPRIME, big->big_value, big->big_value_len);
big = OBJ_PRI_DSA_BASE(object_p);
if ((ptr = malloc(big->big_value_len)) == NULL)
goto mem_failure;
ENCODE_ATTR(CKA_BASE, big->big_value, big->big_value_len);
big = OBJ_PRI_DSA_VALUE(object_p);
if ((ptr = malloc(big->big_value_len)) == NULL)
goto mem_failure;
ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
(void) pthread_mutex_unlock(&object_p->object_mutex);
return (CKR_OK);
mem_failure:
(void) pthread_mutex_unlock(&object_p->object_mutex);
free_key_attributes(key);
return (CKR_HOST_MEMORY);
}
CK_RV
get_dsa_public_key(kernel_object_t *object_p, crypto_key_t *key)
{
biginteger_t *big;
crypto_object_attribute_t *attrs, *cur_attr;
char *ptr;
(void) pthread_mutex_lock(&object_p->object_mutex);
if (object_p->key_type != CKK_DSA ||
object_p->class != CKO_PUBLIC_KEY) {
(void) pthread_mutex_unlock(&object_p->object_mutex);
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
attrs = calloc(1,
DSA_ATTR_COUNT * sizeof (crypto_object_attribute_t));
if (attrs == NULL) {
(void) pthread_mutex_unlock(&object_p->object_mutex);
return (CKR_HOST_MEMORY);
}
key->ck_format = CRYPTO_KEY_ATTR_LIST;
key->ck_count = DSA_ATTR_COUNT;
key->ck_attrs = attrs;
cur_attr = attrs;
big = OBJ_PUB_DSA_PRIME(object_p);
if ((ptr = malloc(big->big_value_len)) == NULL)
goto mem_failure;
ENCODE_ATTR(CKA_PRIME, big->big_value, big->big_value_len);
big = OBJ_PUB_DSA_SUBPRIME(object_p);
if ((ptr = malloc(big->big_value_len)) == NULL)
goto mem_failure;
ENCODE_ATTR(CKA_SUBPRIME, big->big_value, big->big_value_len);
big = OBJ_PUB_DSA_BASE(object_p);
if ((ptr = malloc(big->big_value_len)) == NULL)
goto mem_failure;
ENCODE_ATTR(CKA_BASE, big->big_value, big->big_value_len);
big = OBJ_PUB_DSA_VALUE(object_p);
if ((ptr = malloc(big->big_value_len)) == NULL)
goto mem_failure;
ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
(void) pthread_mutex_unlock(&object_p->object_mutex);
return (CKR_OK);
mem_failure:
(void) pthread_mutex_unlock(&object_p->object_mutex);
free_key_attributes(key);
return (CKR_HOST_MEMORY);
}
CK_RV
get_ec_private_key(kernel_object_t *object_p, crypto_key_t *key)
{
biginteger_t *big;
crypto_object_attribute_t *attrs, *cur_attr;
CK_ATTRIBUTE tmp;
char *ptr;
int rv;
(void) pthread_mutex_lock(&object_p->object_mutex);
if (object_p->key_type != CKK_EC ||
object_p->class != CKO_PRIVATE_KEY) {
(void) pthread_mutex_unlock(&object_p->object_mutex);
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
attrs = calloc(EC_ATTR_COUNT, sizeof (crypto_object_attribute_t));
if (attrs == NULL) {
(void) pthread_mutex_unlock(&object_p->object_mutex);
return (CKR_HOST_MEMORY);
}
key->ck_format = CRYPTO_KEY_ATTR_LIST;
key->ck_count = EC_ATTR_COUNT;
key->ck_attrs = attrs;
cur_attr = attrs;
big = OBJ_PRI_EC_VALUE(object_p);
if ((ptr = malloc(big->big_value_len)) == NULL) {
rv = CKR_HOST_MEMORY;
goto fail;
}
ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
tmp.type = CKA_EC_PARAMS;
tmp.pValue = NULL;
rv = kernel_get_attribute(object_p, &tmp);
if (rv != CKR_OK) {
goto fail;
}
tmp.pValue = malloc(tmp.ulValueLen);
if (tmp.pValue == NULL) {
rv = CKR_HOST_MEMORY;
goto fail;
}
rv = kernel_get_attribute(object_p, &tmp);
if (rv != CKR_OK) {
free(tmp.pValue);
goto fail;
}
cur_attr->oa_type = tmp.type;
cur_attr->oa_value = tmp.pValue;
cur_attr->oa_value_len = tmp.ulValueLen;
(void) pthread_mutex_unlock(&object_p->object_mutex);
return (CKR_OK);
fail:
(void) pthread_mutex_unlock(&object_p->object_mutex);
free_key_attributes(key);
return (rv);
}
CK_RV
get_ec_public_key(kernel_object_t *object_p, crypto_key_t *key)
{
biginteger_t *big;
crypto_object_attribute_t *attrs, *cur_attr;
CK_ATTRIBUTE tmp;
char *ptr;
int rv;
(void) pthread_mutex_lock(&object_p->object_mutex);
if (object_p->key_type != CKK_EC ||
object_p->class != CKO_PUBLIC_KEY) {
(void) pthread_mutex_unlock(&object_p->object_mutex);
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
attrs = calloc(EC_ATTR_COUNT, sizeof (crypto_object_attribute_t));
if (attrs == NULL) {
(void) pthread_mutex_unlock(&object_p->object_mutex);
return (CKR_HOST_MEMORY);
}
key->ck_format = CRYPTO_KEY_ATTR_LIST;
key->ck_count = EC_ATTR_COUNT;
key->ck_attrs = attrs;
cur_attr = attrs;
big = OBJ_PUB_EC_POINT(object_p);
if ((ptr = malloc(big->big_value_len)) == NULL) {
rv = CKR_HOST_MEMORY;
goto fail;
}
ENCODE_ATTR(CKA_EC_POINT, big->big_value, big->big_value_len);
tmp.type = CKA_EC_PARAMS;
tmp.pValue = NULL;
rv = kernel_get_attribute(object_p, &tmp);
if (rv != CKR_OK) {
goto fail;
}
tmp.pValue = malloc(tmp.ulValueLen);
if (tmp.pValue == NULL) {
rv = CKR_HOST_MEMORY;
goto fail;
}
rv = kernel_get_attribute(object_p, &tmp);
if (rv != CKR_OK) {
free(tmp.pValue);
goto fail;
}
cur_attr->oa_type = tmp.type;
cur_attr->oa_value = tmp.pValue;
cur_attr->oa_value_len = tmp.ulValueLen;
(void) pthread_mutex_unlock(&object_p->object_mutex);
return (CKR_OK);
fail:
(void) pthread_mutex_unlock(&object_p->object_mutex);
free_key_attributes(key);
return (rv);
}
CK_RV
process_object_attributes(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
caddr_t *obj_attrs, CK_BBOOL *is_token_obj)
{
crypto_object_attribute_t *attrs, *cur_attr;
int i, cur_i;
char *ptr;
CK_RV rv;
ssize_t value_len;
if (ulCount == 0) {
obj_attrs = NULL;
return (CKR_OK);
}
attrs = calloc(1, ulCount * sizeof (crypto_object_attribute_t));
if (attrs == NULL) {
return (CKR_HOST_MEMORY);
}
cur_attr = attrs;
for (i = 0; i < ulCount; i++) {
switch (pTemplate[i].type) {
case CKA_CLASS:
case CKA_CERTIFICATE_TYPE:
case CKA_KEY_TYPE:
case CKA_MODULUS_BITS:
case CKA_HW_FEATURE_TYPE:
value_len = sizeof (ulong_t);
if (pTemplate[i].pValue != NULL &&
(pTemplate[i].ulValueLen < value_len)) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
cur_i = i;
goto fail_cleanup;
}
break;
default:
value_len = pTemplate[i].ulValueLen;
}
cur_attr->oa_type = pTemplate[i].type;
cur_attr->oa_value_len = value_len;
cur_attr->oa_value = NULL;
if ((pTemplate[i].pValue != NULL) &&
(pTemplate[i].ulValueLen > 0)) {
ptr = malloc(pTemplate[i].ulValueLen);
if (ptr == NULL) {
rv = CKR_HOST_MEMORY;
cur_i = i;
goto fail_cleanup;
} else {
(void) memcpy(ptr, pTemplate[i].pValue,
pTemplate[i].ulValueLen);
cur_attr->oa_value = ptr;
}
}
if ((is_token_obj != NULL) &&
(pTemplate[i].type == CKA_TOKEN)) {
if (pTemplate[i].pValue == NULL) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
cur_i = i;
goto fail_cleanup;
} else {
*is_token_obj =
*(CK_BBOOL *)pTemplate[i].pValue;
}
}
cur_attr++;
}
*obj_attrs = (char *)attrs;
return (CKR_OK);
fail_cleanup:
cur_attr = attrs;
for (i = 0; i < cur_i; i++) {
if (cur_attr->oa_value != NULL) {
(void) free(cur_attr->oa_value);
}
cur_attr++;
}
(void) free(attrs);
return (rv);
}
CK_RV
get_object_attributes(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
caddr_t obj_attrs)
{
crypto_object_attribute_t *cur_attr;
CK_RV rv = CKR_OK;
int i;
cur_attr = (crypto_object_attribute_t *)obj_attrs;
for (i = 0; i < ulCount; i++) {
if (pTemplate[i].type != cur_attr->oa_type) {
rv = CKR_FUNCTION_FAILED;
return (rv);
}
pTemplate[i].ulValueLen = cur_attr->oa_value_len;
if ((pTemplate[i].pValue != NULL) &&
((CK_LONG)pTemplate[i].ulValueLen != -1)) {
(void) memcpy(pTemplate[i].pValue, cur_attr->oa_value,
pTemplate[i].ulValueLen);
}
cur_attr++;
}
return (rv);
}
void
free_object_attributes(caddr_t obj_attrs, CK_ULONG ulCount)
{
crypto_object_attribute_t *cur_attr;
int i;
if ((ulCount == 0) || (obj_attrs == NULL)) {
return;
}
cur_attr = (crypto_object_attribute_t *)obj_attrs;
for (i = 0; i < ulCount; i++) {
if (cur_attr->oa_value != NULL) {
free(cur_attr->oa_value);
}
cur_attr++;
}
free(obj_attrs);
}
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)
{
CK_RV rv = CKR_OK;
crypto_object_get_attribute_value_t obj_ga;
boolean_t is_pri_obj;
boolean_t is_token_obj;
CK_BBOOL pri_value, token_value;
CK_ATTRIBUTE pTemplate[2];
int r;
obj_ga.og_session = sp->k_session;
obj_ga.og_handle = oid;
obj_ga.og_count = 2;
pTemplate[0].type = CKA_PRIVATE;
pTemplate[0].pValue = &pri_value;
pTemplate[0].ulValueLen = sizeof (pri_value);
pTemplate[1].type = CKA_TOKEN;
pTemplate[1].pValue = &token_value;
pTemplate[1].ulValueLen = sizeof (token_value);
rv = process_object_attributes(pTemplate, 2, &obj_ga.og_attributes,
NULL);
if (rv != CKR_OK) {
return (rv);
}
while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
&obj_ga)) < 0) {
if (errno != EINTR)
break;
}
if (r < 0) {
rv = CKR_FUNCTION_FAILED;
} else {
rv = crypto2pkcs11_error_number(obj_ga.og_return_value);
}
if (rv == CKR_OK) {
rv = get_object_attributes(pTemplate, 2, obj_ga.og_attributes);
if (rv == CKR_OK) {
is_pri_obj = *(CK_BBOOL *)pTemplate[0].pValue;
is_token_obj = *(CK_BBOOL *)pTemplate[1].pValue;
}
}
free_object_attributes(obj_ga.og_attributes, 2);
if (rv != CKR_OK) {
return (rv);
}
if (!is_token_obj) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
return (rv);
}
if (is_pri_obj && (pslot->sl_state != CKU_USER)) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
return (rv);
}
objp->is_lib_obj = B_FALSE;
objp->k_handle = oid;
objp->bool_attr_mask |= TOKEN_BOOL_ON;
if (is_pri_obj) {
objp->bool_attr_mask |= PRIVATE_BOOL_ON;
} else {
objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
}
(void) pthread_mutex_init(&objp->object_mutex, NULL);
objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
objp->session_handle = (CK_SESSION_HANDLE) sp;
return (CKR_OK);
}
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)
{
CK_RV rv = CKR_OK;
crypto_object_id_t *oid_p;
kernel_slot_t *pslot;
kernel_object_t *objp;
kernel_object_t *objp1;
kernel_object_t *new_tobj_list = NULL;
kernel_session_t *sp;
CK_ULONG num_obj_found = 0;
boolean_t is_in_lib;
int i;
if (obj_fu.fu_count == 0) {
*found_obj_count = 0;
return (CKR_OK);
}
pslot = slot_table[cur_sp->ses_slotid];
oid_p = (crypto_object_id_t *)obj_fu.fu_handles;
for (i = 0; i < obj_fu.fu_count; i++) {
is_in_lib = B_FALSE;
objp = pslot->sl_tobj_list;
while (!is_in_lib && objp) {
if (objp->k_handle == *oid_p) {
is_in_lib = B_TRUE;
} else {
objp = objp->next;
}
}
if (!is_in_lib) {
sp = pslot->sl_sess_list;
while (!is_in_lib && sp) {
objp = sp->object_list;
while (!is_in_lib && objp) {
if (objp->k_handle == *oid_p) {
is_in_lib = B_TRUE;
} else {
objp = objp->next;
}
}
sp = sp->next;
}
}
if (is_in_lib) {
obj_found[num_obj_found++] = (CK_OBJECT_HANDLE)objp;
}
if (!is_in_lib) {
objp1 = calloc(1, sizeof (kernel_object_t));
if (objp1 == NULL) {
rv = CKR_HOST_MEMORY;
goto failed_exit;
}
rv = create_new_tobj_in_lib(pslot, cur_sp, objp1,
*oid_p);
if (rv == CKR_OK) {
if (new_tobj_list == NULL) {
new_tobj_list = objp1;
objp1->next = NULL;
objp1->prev = NULL;
} else {
new_tobj_list->prev = objp1;
objp1->next = new_tobj_list;
objp1->prev = NULL;
new_tobj_list = objp1;
}
} else {
free(objp1);
if (rv == CKR_HOST_MEMORY) {
goto failed_exit;
}
}
}
oid_p++;
}
if (new_tobj_list != NULL) {
objp = new_tobj_list;
while (objp) {
obj_found[num_obj_found++] = (CK_OBJECT_HANDLE)objp;
if (objp->next == NULL) {
break;
}
objp = objp->next;
}
if (pslot->sl_tobj_list != NULL) {
objp->next = pslot->sl_tobj_list;
pslot->sl_tobj_list->prev = objp;
}
pslot->sl_tobj_list = new_tobj_list;
}
*found_obj_count = num_obj_found;
return (CKR_OK);
failed_exit:
objp = new_tobj_list;
while (objp) {
objp1 = objp->next;
(void) pthread_mutex_destroy(&objp->object_mutex);
free(objp);
objp = objp1;
}
return (rv);
}
CK_RV
get_cka_private_value(kernel_session_t *sp, crypto_object_id_t oid,
CK_BBOOL *is_pri_obj)
{
CK_RV rv = CKR_OK;
crypto_object_get_attribute_value_t obj_ga;
crypto_object_attribute_t obj_attr;
CK_BBOOL pri_value;
int r;
obj_ga.og_session = sp->k_session;
obj_ga.og_handle = oid;
obj_ga.og_count = 1;
obj_attr.oa_type = CKA_PRIVATE;
obj_attr.oa_value = (char *)&pri_value;
obj_attr.oa_value_len = sizeof (CK_BBOOL);
obj_ga.og_attributes = (char *)&obj_attr;
while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
&obj_ga)) < 0) {
if (errno != EINTR)
break;
}
if (r < 0) {
rv = CKR_FUNCTION_FAILED;
} else {
rv = crypto2pkcs11_error_number(obj_ga.og_return_value);
}
if (rv == CKR_OK) {
*is_pri_obj = *(CK_BBOOL *)obj_attr.oa_value;
}
return (rv);
}
CK_RV
get_mechanism_info(kernel_slot_t *pslot, CK_MECHANISM_TYPE type,
CK_MECHANISM_INFO_PTR pInfo, uint32_t *k_mi_flags)
{
crypto_get_provider_mechanism_info_t mechanism_info;
const char *string;
CK_FLAGS flags, mi_flags;
CK_RV rv;
int r;
char buf[11];
if (type >= CKM_VENDOR_DEFINED) {
(void) snprintf(buf, sizeof (buf), "%#lx", type);
string = buf;
} else {
string = pkcs11_mech2str(type);
}
if (string == NULL)
return (CKR_MECHANISM_INVALID);
(void) strcpy(mechanism_info.mi_mechanism_name, string);
mechanism_info.mi_provider_id = pslot->sl_provider_id;
while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_MECHANISM_INFO,
&mechanism_info)) < 0) {
if (errno != EINTR)
break;
}
if (r < 0) {
rv = CKR_FUNCTION_FAILED;
} else {
rv = crypto2pkcs11_error_number(
mechanism_info.mi_return_value);
}
if (rv != CKR_OK) {
return (rv);
}
mi_flags = mechanism_info.mi_flags;
mi_flags &= ~(CRYPTO_FG_DIGEST_ATOMIC | CRYPTO_FG_ENCRYPT_ATOMIC |
CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_MAC_ATOMIC |
CRYPTO_FG_SIGN_ATOMIC | CRYPTO_FG_VERIFY_ATOMIC |
CRYPTO_FG_SIGN_RECOVER_ATOMIC |
CRYPTO_FG_VERIFY_RECOVER_ATOMIC |
CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
CRYPTO_FG_MAC_DECRYPT_ATOMIC |
CRYPTO_FG_MAC);
if (mi_flags == 0) {
return (CKR_MECHANISM_INVALID);
}
if (rv == CKR_OK) {
*k_mi_flags = mi_flags;
flags = CKF_HW;
if (mi_flags & CRYPTO_FG_ENCRYPT)
flags |= CKF_ENCRYPT;
if (mi_flags & CRYPTO_FG_DECRYPT) {
flags |= CKF_DECRYPT;
flags |= CKF_UNWRAP;
}
if (mi_flags & CRYPTO_FG_DIGEST)
flags |= CKF_DIGEST;
if (mi_flags & CRYPTO_FG_SIGN)
flags |= CKF_SIGN;
if (mi_flags & CRYPTO_FG_SIGN_RECOVER)
flags |= CKF_SIGN_RECOVER;
if (mi_flags & CRYPTO_FG_VERIFY)
flags |= CKF_VERIFY;
if (mi_flags & CRYPTO_FG_VERIFY_RECOVER)
flags |= CKF_VERIFY_RECOVER;
if (mi_flags & CRYPTO_FG_GENERATE)
flags |= CKF_GENERATE;
if (mi_flags & CRYPTO_FG_GENERATE_KEY_PAIR)
flags |= CKF_GENERATE_KEY_PAIR;
if (mi_flags & CRYPTO_FG_WRAP)
flags |= CKF_WRAP;
if (mi_flags & CRYPTO_FG_UNWRAP)
flags |= CKF_UNWRAP;
if (mi_flags & CRYPTO_FG_DERIVE)
flags |= CKF_DERIVE;
pInfo->ulMinKeySize = mechanism_info.mi_min_key_size;
pInfo->ulMaxKeySize = mechanism_info.mi_max_key_size;
pInfo->flags = flags;
}
return (rv);
}
void
p11_to_kernel_ccm_params(const CK_CCM_PARAMS *in, CK_AES_CCM_PARAMS *out)
{
out->ulMACSize = in->ulMACLen;
out->ulNonceSize = in->ulNonceLen;
out->ulAuthDataSize = in->ulAADLen;
out->ulDataSize = in->ulDataLen;
out->nonce = in->pNonce;
out->authData = in->pAAD;
}