softAttributeUtil.c revision f9fbec18f5b458b560ecf45d3db8e8bd56bf6942
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdlib.h>
#include <string.h>
#include <security/cryptoki.h>
#include <arcfour.h>
#include <aes_impl.h>
#include <blowfish_impl.h>
#include <bignum.h>
#include <des_impl.h>
#include <rsa_impl.h>
#include "softGlobal.h"
#include "softObject.h"
#include "softSession.h"
#include "softKeystore.h"
#include "softKeystoreUtil.h"
#include "softCrypt.h"
/*
* This attribute table is used by the soft_lookup_attr()
* to validate the attributes.
*/
CK_ATTRIBUTE_TYPE attr_map[] = {
CKA_PRIVATE,
CKA_LABEL,
CKA_APPLICATION,
CKA_OBJECT_ID,
CKA_CERTIFICATE_TYPE,
CKA_ISSUER,
CKA_SERIAL_NUMBER,
CKA_AC_ISSUER,
CKA_OWNER,
CKA_ATTR_TYPES,
CKA_SUBJECT,
CKA_ID,
CKA_SENSITIVE,
CKA_START_DATE,
CKA_END_DATE,
CKA_MODULUS,
CKA_MODULUS_BITS,
CKA_PUBLIC_EXPONENT,
CKA_PRIVATE_EXPONENT,
CKA_PRIME_1,
CKA_PRIME_2,
CKA_EXPONENT_1,
CKA_EXPONENT_2,
CKA_COEFFICIENT,
CKA_PRIME,
CKA_SUBPRIME,
CKA_BASE,
CKA_EXTRACTABLE,
CKA_LOCAL,
CKA_NEVER_EXTRACTABLE,
CKA_ALWAYS_SENSITIVE,
CKA_MODIFIABLE,
CKA_ECDSA_PARAMS,
CKA_EC_PARAMS,
CKA_EC_POINT,
CKA_SECONDARY_AUTH,
CKA_AUTH_PIN_FLAGS,
CKA_HW_FEATURE_TYPE,
CKA_RESET_ON_INIT,
CKA_HAS_RESET
};
/*
* attributes that exists only in public key objects
* Note: some attributes may also exist in one or two
* other object classes, but they are also listed
* because not all object have them.
*/
CK_ATTRIBUTE_TYPE PUB_KEY_ATTRS[] =
{
CKA_SUBJECT,
CKA_ENCRYPT,
CKA_WRAP,
CKA_VERIFY,
CKA_VERIFY_RECOVER,
CKA_MODULUS,
CKA_MODULUS_BITS,
CKA_PUBLIC_EXPONENT,
CKA_PRIME,
CKA_SUBPRIME,
CKA_BASE,
CKA_TRUSTED,
CKA_ECDSA_PARAMS,
CKA_EC_PARAMS,
CKA_EC_POINT
};
/*
* attributes that exists only in private key objects
* Note: some attributes may also exist in one or two
* other object classes, but they are also listed
* because not all object have them.
*/
CK_ATTRIBUTE_TYPE PRIV_KEY_ATTRS[] =
{
CKA_DECRYPT,
CKA_UNWRAP,
CKA_SIGN,
CKA_SIGN_RECOVER,
CKA_MODULUS,
CKA_PUBLIC_EXPONENT,
CKA_PRIVATE_EXPONENT,
CKA_PRIME,
CKA_SUBPRIME,
CKA_BASE,
CKA_PRIME_1,
CKA_PRIME_2,
CKA_EXPONENT_1,
CKA_EXPONENT_2,
CKA_COEFFICIENT,
CKA_VALUE_BITS,
CKA_SUBJECT,
CKA_SENSITIVE,
CKA_EXTRACTABLE,
CKA_NEVER_EXTRACTABLE,
CKA_ALWAYS_SENSITIVE,
CKA_EC_PARAMS
};
/*
* attributes that exists only in secret key objects
* Note: some attributes may also exist in one or two
* other object classes, but they are also listed
* because not all object have them.
*/
CK_ATTRIBUTE_TYPE SECRET_KEY_ATTRS[] =
{
CKA_VALUE_LEN,
CKA_ENCRYPT,
CKA_DECRYPT,
CKA_WRAP,
CKA_UNWRAP,
CKA_SIGN,
CKA_VERIFY,
CKA_SENSITIVE,
CKA_EXTRACTABLE,
CKA_NEVER_EXTRACTABLE,
CKA_ALWAYS_SENSITIVE
};
/*
* attributes that exists only in domain parameter objects
* Note: some attributes may also exist in one or two
* other object classes, but they are also listed
* because not all object have them.
*/
CK_ATTRIBUTE_TYPE DOMAIN_ATTRS[] =
{
CKA_PRIME,
CKA_SUBPRIME,
CKA_BASE,
CKA_PRIME_BITS,
CKA_SUBPRIME_BITS,
CKA_SUB_PRIME_BITS
};
/*
* attributes that exists only in hardware feature objects
*
*/
CK_ATTRIBUTE_TYPE HARDWARE_ATTRS[] =
{
CKA_HW_FEATURE_TYPE,
CKA_RESET_ON_INIT,
CKA_HAS_RESET
};
/*
* attributes that exists only in certificate objects
*/
CK_ATTRIBUTE_TYPE CERT_ATTRS[] =
{
CKA_CERTIFICATE_TYPE,
CKA_TRUSTED,
CKA_SUBJECT,
CKA_ID,
CKA_ISSUER,
CKA_AC_ISSUER,
CKA_SERIAL_NUMBER,
CKA_OWNER,
CKA_ATTR_TYPES
};
/*
* Validate the attribute by using binary search algorithm.
*/
CK_RV
soft_lookup_attr(CK_ATTRIBUTE_TYPE type)
{
size_t lower, middle, upper;
lower = 0;
upper = (sizeof (attr_map) / sizeof (CK_ATTRIBUTE_TYPE)) - 1;
while (lower <= upper) {
/* Always starts from middle. */
middle = (lower + upper) / 2;
if (type > attr_map[middle]) {
/* Adjust the lower bound to upper half. */
lower = middle + 1;
continue;
}
if (type == attr_map[middle]) {
/* Found it. */
return (CKR_OK);
}
if (type < attr_map[middle]) {
/* Adjust the upper bound to lower half. */
upper = middle - 1;
continue;
}
}
/* Failed to find the matching attribute from the attribute table. */
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
/*
* Validate the attribute by using the following search algorithm:
*
* 1) Search for the most frequently used attributes first.
* 2) If not found, search for the usage-purpose attributes - these
* attributes have dense set of values, therefore compiler will
* optimize it with a branch table and branch to the appropriate
* case.
* 3) If still not found, use binary search for the rest of the
* attributes in the attr_map[] table.
*/
CK_RV
soft_validate_attr(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
CK_OBJECT_CLASS *class)
{
CK_ULONG i;
CK_RV rv = CKR_OK;
for (i = 0; i < ulAttrNum; i++) {
/* First tier search */
switch (template[i].type) {
case CKA_CLASS:
*class = *((CK_OBJECT_CLASS*)template[i].pValue);
break;
case CKA_TOKEN:
break;
case CKA_KEY_TYPE:
break;
case CKA_VALUE:
break;
case CKA_VALUE_LEN:
break;
case CKA_VALUE_BITS:
break;
default:
/* Second tier search */
switch (template[i].type) {
case CKA_ENCRYPT:
break;
case CKA_DECRYPT:
break;
case CKA_WRAP:
break;
case CKA_UNWRAP:
break;
case CKA_SIGN:
break;
case CKA_SIGN_RECOVER:
break;
case CKA_VERIFY:
break;
case CKA_VERIFY_RECOVER:
break;
case CKA_DERIVE:
break;
default:
/* Third tier search */
rv = soft_lookup_attr(template[i].type);
if (rv != CKR_OK)
return (rv);
break;
}
break;
}
}
return (rv);
}
static void
cleanup_cert_attr(cert_attr_t *attr)
{
if (attr) {
if (attr->value) {
(void) memset(attr->value, 0, attr->length);
free(attr->value);
}
attr->value = NULL;
attr->length = 0;
}
}
static CK_RV
copy_cert_attr(cert_attr_t *src_attr, cert_attr_t **dest_attr)
{
CK_RV rv = CKR_OK;
if (src_attr == NULL || dest_attr == NULL)
return (CKR_HOST_MEMORY);
if (src_attr->value == NULL)
return (CKR_HOST_MEMORY);
/* free memory if its already allocated */
if (*dest_attr != NULL) {
if ((*dest_attr)->value != (CK_BYTE *)NULL)
free((*dest_attr)->value);
} else {
*dest_attr = malloc(sizeof (cert_attr_t));
if (*dest_attr == NULL)
return (CKR_HOST_MEMORY);
}
(*dest_attr)->value = NULL;
(*dest_attr)->length = 0;
if (src_attr->length) {
(*dest_attr)->value = malloc(src_attr->length);
if ((*dest_attr)->value == NULL) {
free(*dest_attr);
return (CKR_HOST_MEMORY);
}
(void) memcpy((*dest_attr)->value, src_attr->value,
src_attr->length);
(*dest_attr)->length = src_attr->length;
}
return (rv);
}
void
soft_cleanup_cert_object(soft_object_t *object_p)
{
CK_CERTIFICATE_TYPE certtype = object_p->cert_type;
if (object_p->class != CKO_CERTIFICATE ||
OBJ_CERT(object_p) == NULL)
return;
if (certtype == CKC_X_509) {
if (X509_CERT_SUBJECT(object_p) != NULL) {
cleanup_cert_attr(X509_CERT_SUBJECT(object_p));
free(X509_CERT_SUBJECT(object_p));
X509_CERT_SUBJECT(object_p) = NULL;
}
if (X509_CERT_VALUE(object_p) != NULL) {
cleanup_cert_attr(X509_CERT_VALUE(object_p));
free(X509_CERT_VALUE(object_p));
X509_CERT_VALUE(object_p) = NULL;
}
free(OBJ_CERT(object_p));
} else if (certtype == CKC_X_509_ATTR_CERT) {
if (X509_ATTR_CERT_VALUE(object_p) != NULL) {
cleanup_cert_attr(X509_ATTR_CERT_VALUE(object_p));
free(X509_ATTR_CERT_VALUE(object_p));
X509_ATTR_CERT_VALUE(object_p) = NULL;
}
if (X509_ATTR_CERT_OWNER(object_p) != NULL) {
cleanup_cert_attr(X509_ATTR_CERT_OWNER(object_p));
free(X509_ATTR_CERT_OWNER(object_p));
X509_ATTR_CERT_OWNER(object_p) = NULL;
}
free(OBJ_CERT(object_p));
}
}
/*
* Clean up and release all the storage in the extra attribute list
* of an object.
*/
void
soft_cleanup_extra_attr(soft_object_t *object_p)
{
CK_ATTRIBUTE_INFO_PTR extra_attr;
CK_ATTRIBUTE_INFO_PTR tmp;
extra_attr = object_p->extra_attrlistp;
while (extra_attr) {
tmp = extra_attr->next;
if (extra_attr->attr.pValue)
/*
* All extra attributes in the extra attribute
* list have pValue points to the value of the
* attribute (with simple byte array type).
* Free the storage for the value of the attribute.
*/
free(extra_attr->attr.pValue);
/* Free the storage for the attribute_info struct. */
free(extra_attr);
extra_attr = tmp;
}
object_p->extra_attrlistp = NULL;
}
/*
* Create the attribute_info struct to hold the object's attribute,
* and add it to the extra attribute list of an object.
*/
CK_RV
soft_add_extra_attr(CK_ATTRIBUTE_PTR template, soft_object_t *object_p)
{
CK_ATTRIBUTE_INFO_PTR attrp;
/* Allocate the storage for the attribute_info struct. */
attrp = calloc(1, sizeof (attribute_info_t));
if (attrp == NULL) {
return (CKR_HOST_MEMORY);
}
/* Set up attribute_info struct. */
attrp->attr.type = template->type;
attrp->attr.ulValueLen = template->ulValueLen;
if ((template->pValue != NULL) &&
(template->ulValueLen > 0)) {
/* Allocate storage for the value of the attribute. */
attrp->attr.pValue = malloc(template->ulValueLen);
if (attrp->attr.pValue == NULL) {
free(attrp);
return (CKR_HOST_MEMORY);
}
(void) memcpy(attrp->attr.pValue, template->pValue,
template->ulValueLen);
} else {
attrp->attr.pValue = NULL;
}
/* Insert the new attribute in front of extra attribute list. */
if (object_p->extra_attrlistp == NULL) {
object_p->extra_attrlistp = attrp;
attrp->next = NULL;
} else {
attrp->next = object_p->extra_attrlistp;
object_p->extra_attrlistp = attrp;
}
return (CKR_OK);
}
CK_RV
soft_copy_certificate(certificate_obj_t *oldcert, certificate_obj_t **newcert,
CK_CERTIFICATE_TYPE type)
{
CK_RV rv = CKR_OK;
certificate_obj_t *cert;
x509_cert_t x509;
x509_attr_cert_t x509_attr;
cert = calloc(1, sizeof (certificate_obj_t));
if (cert == NULL) {
return (CKR_HOST_MEMORY);
}
if (type == CKC_X_509) {
x509 = oldcert->cert_type_u.x509;
if (x509.subject)
if ((rv = copy_cert_attr(x509.subject,
&cert->cert_type_u.x509.subject)))
return (rv);
if (x509.value)
if ((rv = copy_cert_attr(x509.value,
&cert->cert_type_u.x509.value)))
return (rv);
} else if (type == CKC_X_509_ATTR_CERT) {
x509_attr = oldcert->cert_type_u.x509_attr;
if (x509_attr.owner)
if ((rv = copy_cert_attr(x509_attr.owner,
&cert->cert_type_u.x509_attr.owner)))
return (rv);
if (x509_attr.value)
if ((rv = copy_cert_attr(x509_attr.value,
&cert->cert_type_u.x509_attr.value)))
return (rv);
} else {
/* wrong certificate type */
rv = CKR_ATTRIBUTE_TYPE_INVALID;
}
if (rv == CKR_OK)
*newcert = cert;
return (rv);
}
/*
* Copy the attribute_info struct from the old object to a new attribute_info
* struct, and add that new struct to the extra attribute list of the new
* object.
*/
CK_RV
soft_copy_extra_attr(CK_ATTRIBUTE_INFO_PTR old_attrp, soft_object_t *object_p)
{
CK_ATTRIBUTE_INFO_PTR attrp;
/* Allocate attribute_info struct. */
attrp = calloc(1, sizeof (attribute_info_t));
if (attrp == NULL) {
return (CKR_HOST_MEMORY);
}
attrp->attr.type = old_attrp->attr.type;
attrp->attr.ulValueLen = old_attrp->attr.ulValueLen;
if ((old_attrp->attr.pValue != NULL) &&
(old_attrp->attr.ulValueLen > 0)) {
attrp->attr.pValue = malloc(old_attrp->attr.ulValueLen);
if (attrp->attr.pValue == NULL) {
free(attrp);
return (CKR_HOST_MEMORY);
}
(void) memcpy(attrp->attr.pValue, old_attrp->attr.pValue,
old_attrp->attr.ulValueLen);
} else {
attrp->attr.pValue = NULL;
}
/* Insert the new attribute in front of extra attribute list */
if (object_p->extra_attrlistp == NULL) {
object_p->extra_attrlistp = attrp;
attrp->next = NULL;
} else {
attrp->next = object_p->extra_attrlistp;
object_p->extra_attrlistp = attrp;
}
return (CKR_OK);
}
/*
* Get the attribute triple from the extra attribute list in the object
* (if the specified attribute type is found), and copy it to a template.
* Note the type of the attribute to be copied is specified by the template,
* and the storage is pre-allocated for the atrribute value in the template
* for doing the copy.
*/
CK_RV
get_extra_attr_from_object(soft_object_t *object_p, CK_ATTRIBUTE_PTR template)
{
CK_ATTRIBUTE_INFO_PTR extra_attr;
CK_ATTRIBUTE_TYPE type = template->type;
extra_attr = object_p->extra_attrlistp;
while (extra_attr) {
if (type == extra_attr->attr.type) {
/* Found it. */
break;
} else {
/* Does not match, try next one. */
extra_attr = extra_attr->next;
}
}
if (extra_attr == NULL) {
/* A valid but un-initialized attribute. */
template->ulValueLen = 0;
return (CKR_OK);
}
/*
* We found the attribute in the extra attribute list.
*/
if (template->pValue == NULL) {
template->ulValueLen = extra_attr->attr.ulValueLen;
return (CKR_OK);
}
if (template->ulValueLen >= extra_attr->attr.ulValueLen) {
/*
* The buffer provided by the application is large
* enough to hold the value of the attribute.
*/
(void) memcpy(template->pValue, extra_attr->attr.pValue,
extra_attr->attr.ulValueLen);
template->ulValueLen = extra_attr->attr.ulValueLen;
return (CKR_OK);
} else {
/*
* The buffer provided by the application does
* not have enough space to hold the value.
*/
template->ulValueLen = (CK_ULONG)-1;
return (CKR_BUFFER_TOO_SMALL);
}
}
/*
* Modify the attribute triple in the extra attribute list of the object
* if the specified attribute type is found. Otherwise, just add it to
* list.
*/
CK_RV
set_extra_attr_to_object(soft_object_t *object_p, CK_ATTRIBUTE_TYPE type,
CK_ATTRIBUTE_PTR template)
{
CK_ATTRIBUTE_INFO_PTR extra_attr;
extra_attr = object_p->extra_attrlistp;
while (extra_attr) {
if (type == extra_attr->attr.type) {
/* Found it. */
break;
} else {
/* Does not match, try next one. */
extra_attr = extra_attr->next;
}
}
if (extra_attr == NULL) {
/*
* This attribute is a new one, go ahead adding it to
* the extra attribute list.
*/
return (soft_add_extra_attr(template, object_p));
}
/* We found the attribute in the extra attribute list. */
if ((template->pValue != NULL) &&
(template->ulValueLen > 0)) {
if (template->ulValueLen > extra_attr->attr.ulValueLen) {
/* The old buffer is too small to hold the new value. */
if (extra_attr->attr.pValue != NULL)
/* Free storage for the old attribute value. */
free(extra_attr->attr.pValue);
/* Allocate storage for the new attribute value. */
extra_attr->attr.pValue = malloc(template->ulValueLen);
if (extra_attr->attr.pValue == NULL) {
return (CKR_HOST_MEMORY);
}
}
/* Replace the attribute with new value. */
extra_attr->attr.ulValueLen = template->ulValueLen;
(void) memcpy(extra_attr->attr.pValue, template->pValue,
template->ulValueLen);
} else {
extra_attr->attr.pValue = NULL;
}
return (CKR_OK);
}
/*
* Copy the big integer attribute value from template to a biginteger_t struct.
*/
CK_RV
get_bigint_attr_from_template(biginteger_t *big, CK_ATTRIBUTE_PTR template)
{
if ((template->pValue != NULL) &&
(template->ulValueLen > 0)) {
/* Allocate storage for the value of the attribute. */
big->big_value = malloc(template->ulValueLen);
if (big->big_value == NULL) {
return (CKR_HOST_MEMORY);
}
(void) memcpy(big->big_value, template->pValue,
template->ulValueLen);
big->big_value_len = template->ulValueLen;
} else {
big->big_value = NULL;
big->big_value_len = 0;
}
return (CKR_OK);
}
/*
* Copy the big integer attribute value from a biginteger_t struct in the
* object to a template.
*/
CK_RV
get_bigint_attr_from_object(biginteger_t *big, CK_ATTRIBUTE_PTR template)
{
if (template->pValue == NULL) {
template->ulValueLen = big->big_value_len;
return (CKR_OK);
}
if (big->big_value == NULL) {
template->ulValueLen = 0;
return (CKR_OK);
}
if (template->ulValueLen >= big->big_value_len) {
/*
* The buffer provided by the application is large
* enough to hold the value of the attribute.
*/
(void) memcpy(template->pValue, big->big_value,
big->big_value_len);
template->ulValueLen = big->big_value_len;
return (CKR_OK);
} else {
/*
* The buffer provided by the application does
* not have enough space to hold the value.
*/
template->ulValueLen = (CK_ULONG)-1;
return (CKR_BUFFER_TOO_SMALL);
}
}
/*
* Copy the boolean data type attribute value from an object for the
* specified attribute to the template.
*/
CK_RV
get_bool_attr_from_object(soft_object_t *object_p, CK_ULONG bool_flag,
CK_ATTRIBUTE_PTR template)
{
if (template->pValue == NULL) {
template->ulValueLen = sizeof (CK_BBOOL);
return (CKR_OK);
}
if (template->ulValueLen >= sizeof (CK_BBOOL)) {
/*
* The buffer provided by the application is large
* enough to hold the value of the attribute.
*/
if (object_p->bool_attr_mask & bool_flag) {
*((CK_BBOOL *)template->pValue) = B_TRUE;
} else {
*((CK_BBOOL *)template->pValue) = B_FALSE;
}
template->ulValueLen = sizeof (CK_BBOOL);
return (CKR_OK);
} else {
/*
* The buffer provided by the application does
* not have enough space to hold the value.
*/
template->ulValueLen = (CK_ULONG)-1;
return (CKR_BUFFER_TOO_SMALL);
}
}
/*
* Set the boolean data type attribute value in the object.
*/
CK_RV
set_bool_attr_to_object(soft_object_t *object_p, CK_ULONG bool_flag,
CK_ATTRIBUTE_PTR template)
{
if (*(CK_BBOOL *)template->pValue)
object_p->bool_attr_mask |= bool_flag;
else
object_p->bool_attr_mask &= ~bool_flag;
return (CKR_OK);
}
/*
* Copy the CK_ULONG data type attribute value from an object to the
* template.
*/
CK_RV
get_ulong_attr_from_object(CK_ULONG value, CK_ATTRIBUTE_PTR template)
{
if (template->pValue == NULL) {
template->ulValueLen = sizeof (CK_ULONG);
return (CKR_OK);
}
if (template->ulValueLen >= sizeof (CK_ULONG)) {
/*
* The buffer provided by the application is large
* enough to hold the value of the attribute.
* It is also assumed to be correctly aligned.
*/
*(CK_ULONG_PTR)template->pValue = value;
template->ulValueLen = sizeof (CK_ULONG);
return (CKR_OK);
} else {
/*
* The buffer provided by the application does
* not have enough space to hold the value.
*/
template->ulValueLen = (CK_ULONG)-1;
return (CKR_BUFFER_TOO_SMALL);
}
}
/*
* Copy the CK_ULONG data type attribute value from a template to the
* object.
*/
void
get_ulong_attr_from_template(CK_ULONG *value, CK_ATTRIBUTE_PTR template)
{
if (template->pValue != NULL) {
*value = *(CK_ULONG_PTR)template->pValue;
} else {
*value = 0;
}
}
/*
* Copy the big integer attribute value from source's biginteger_t to
* destination's biginteger_t.
*/
void
copy_bigint_attr(biginteger_t *src, biginteger_t *dst)
{
if ((src->big_value != NULL) &&
(src->big_value_len > 0)) {
/*
* To do the copy, just have dst's big_value points
* to src's.
*/
dst->big_value = src->big_value;
dst->big_value_len = src->big_value_len;
/*
* After the copy, nullify the src's big_value pointer.
* It prevents any double freeing the value.
*/
src->big_value = NULL;
src->big_value_len = 0;
} else {
dst->big_value = NULL;
dst->big_value_len = 0;
}
}
CK_RV
get_string_from_template(CK_ATTRIBUTE_PTR dest, CK_ATTRIBUTE_PTR src)
{
if ((src->pValue != NULL) &&
(src->ulValueLen > 0)) {
/* Allocate storage for the value of the attribute. */
dest->pValue = malloc(src->ulValueLen);
if (dest->pValue == NULL) {
return (CKR_HOST_MEMORY);
}
(void) memcpy(dest->pValue, src->pValue,
src->ulValueLen);
dest->ulValueLen = src->ulValueLen;
dest->type = src->type;
} else {
dest->pValue = NULL;
dest->ulValueLen = 0;
dest->type = src->type;
}
return (CKR_OK);
}
CK_RV
get_cert_attr_from_template(cert_attr_t **dest, CK_ATTRIBUTE_PTR src)
{
if (src->pValue != NULL && src->ulValueLen > 0) {
/*
* If the attribute was already set, clear out the
* existing value and release the memory.
*/
if (*dest != NULL) {
if ((*dest)->value != NULL) {
(void) memset((*dest)->value, 0,
(*dest)->length);
free((*dest)->value);
}
} else {
*dest = malloc(sizeof (cert_attr_t));
if (*dest == NULL) {
return (CKR_HOST_MEMORY);
}
(void) memset(*dest, 0, sizeof (cert_attr_t));
}
(*dest)->value = malloc(src->ulValueLen);
if ((*dest)->value == NULL) {
free(*dest);
*dest = NULL;
return (CKR_HOST_MEMORY);
}
(void) memcpy((*dest)->value, src->pValue, src->ulValueLen);
(*dest)->length = src->ulValueLen;
}
return (CKR_OK);
}
/*
* Copy the certificate attribute information to the template.
* If the template attribute is not big enough, set the ulValueLen=-1
* and return CKR_BUFFER_TOO_SMALL.
*/
static CK_RV
get_cert_attr_from_object(cert_attr_t *src, CK_ATTRIBUTE_PTR template)
{
if (template->pValue == NULL) {
template->ulValueLen = src->length;
return (CKR_OK);
} else if (template->ulValueLen >= src->length) {
/*
* The buffer provided by the application is large
* enough to hold the value of the attribute.
*/
(void) memcpy(template->pValue, src->value, src->length);
template->ulValueLen = src->length;
return (CKR_OK);
} else {
/*
* The buffer provided by the application does
* not have enough space to hold the value.
*/
template->ulValueLen = (CK_ULONG)-1;
return (CKR_BUFFER_TOO_SMALL);
}
}
void
string_attr_cleanup(CK_ATTRIBUTE_PTR template)
{
if (template->pValue) {
free(template->pValue);
template->pValue = NULL;
template->ulValueLen = 0;
}
}
/*
* Release the storage allocated for object attribute with big integer
* value.
*/
void
bigint_attr_cleanup(biginteger_t *big)
{
if (big == NULL)
return;
if (big->big_value) {
(void) memset(big->big_value, 0, big->big_value_len);
free(big->big_value);
big->big_value = NULL;
big->big_value_len = 0;
}
}
/*
* Clean up and release all the storage allocated to hold the big integer
* attributes associated with the type (i.e. class) of the object. Also,
* release the storage allocated to the type of the object.
*/
void
soft_cleanup_object_bigint_attrs(soft_object_t *object_p)
{
CK_OBJECT_CLASS class = object_p->class;
CK_KEY_TYPE keytype = object_p->key_type;
switch (class) {
case CKO_PUBLIC_KEY:
if (OBJ_PUB(object_p)) {
switch (keytype) {
case CKK_RSA:
bigint_attr_cleanup(OBJ_PUB_RSA_MOD(
object_p));
bigint_attr_cleanup(OBJ_PUB_RSA_PUBEXPO(
object_p));
break;
case CKK_DSA:
bigint_attr_cleanup(OBJ_PUB_DSA_PRIME(
object_p));
bigint_attr_cleanup(OBJ_PUB_DSA_SUBPRIME(
object_p));
bigint_attr_cleanup(OBJ_PUB_DSA_BASE(
object_p));
bigint_attr_cleanup(OBJ_PUB_DSA_VALUE(
object_p));
break;
case CKK_DH:
bigint_attr_cleanup(OBJ_PUB_DH_PRIME(
object_p));
bigint_attr_cleanup(OBJ_PUB_DH_BASE(
object_p));
bigint_attr_cleanup(OBJ_PUB_DH_VALUE(
object_p));
break;
case CKK_X9_42_DH:
bigint_attr_cleanup(OBJ_PUB_DH942_PRIME(
object_p));
bigint_attr_cleanup(OBJ_PUB_DH942_BASE(
object_p));
bigint_attr_cleanup(OBJ_PUB_DH942_SUBPRIME(
object_p));
bigint_attr_cleanup(OBJ_PUB_DH942_VALUE(
object_p));
break;
case CKK_EC:
bigint_attr_cleanup(OBJ_PUB_EC_POINT(
object_p));
break;
}
/* Release Public Key Object struct */
free(OBJ_PUB(object_p));
OBJ_PUB(object_p) = NULL;
}
break;
case CKO_PRIVATE_KEY:
if (OBJ_PRI(object_p)) {
switch (keytype) {
case CKK_RSA:
bigint_attr_cleanup(OBJ_PRI_RSA_MOD(
object_p));
bigint_attr_cleanup(OBJ_PRI_RSA_PUBEXPO(
object_p));
bigint_attr_cleanup(OBJ_PRI_RSA_PRIEXPO(
object_p));
bigint_attr_cleanup(OBJ_PRI_RSA_PRIME1(
object_p));
bigint_attr_cleanup(OBJ_PRI_RSA_PRIME2(
object_p));
bigint_attr_cleanup(OBJ_PRI_RSA_EXPO1(
object_p));
bigint_attr_cleanup(OBJ_PRI_RSA_EXPO2(
object_p));
bigint_attr_cleanup(OBJ_PRI_RSA_COEF(
object_p));
break;
case CKK_DSA:
bigint_attr_cleanup(OBJ_PRI_DSA_PRIME(
object_p));
bigint_attr_cleanup(OBJ_PRI_DSA_SUBPRIME(
object_p));
bigint_attr_cleanup(OBJ_PRI_DSA_BASE(
object_p));
bigint_attr_cleanup(OBJ_PRI_DSA_VALUE(
object_p));
break;
case CKK_DH:
bigint_attr_cleanup(OBJ_PRI_DH_PRIME(
object_p));
bigint_attr_cleanup(OBJ_PRI_DH_BASE(
object_p));
bigint_attr_cleanup(OBJ_PRI_DH_VALUE(
object_p));
break;
case CKK_X9_42_DH:
bigint_attr_cleanup(OBJ_PRI_DH942_PRIME(
object_p));
bigint_attr_cleanup(OBJ_PRI_DH942_BASE(
object_p));
bigint_attr_cleanup(OBJ_PRI_DH942_SUBPRIME(
object_p));
bigint_attr_cleanup(OBJ_PRI_DH942_VALUE(
object_p));
break;
case CKK_EC:
bigint_attr_cleanup(OBJ_PRI_EC_VALUE(
object_p));
break;
}
/* Release Private Key Object struct. */
free(OBJ_PRI(object_p));
OBJ_PRI(object_p) = NULL;
}
break;
case CKO_SECRET_KEY:
if (OBJ_SEC(object_p)) {
/* cleanup key data area */
if (OBJ_SEC_VALUE(object_p) != NULL &&
OBJ_SEC_VALUE_LEN(object_p) > 0) {
(void) memset(OBJ_SEC_VALUE(object_p), 0,
OBJ_SEC_VALUE_LEN(object_p));
free(OBJ_SEC_VALUE(object_p));
}
/* cleanup key schedule data area */
if (OBJ_KEY_SCHED(object_p) != NULL &&
OBJ_KEY_SCHED_LEN(object_p) > 0) {
(void) memset(OBJ_KEY_SCHED(object_p), 0,
OBJ_KEY_SCHED_LEN(object_p));
free(OBJ_KEY_SCHED(object_p));
}
/* Release Secret Key Object struct. */
free(OBJ_SEC(object_p));
OBJ_SEC(object_p) = NULL;
}
break;
case CKO_DOMAIN_PARAMETERS:
if (OBJ_DOM(object_p)) {
switch (keytype) {
case CKK_DSA:
bigint_attr_cleanup(OBJ_DOM_DSA_PRIME(
object_p));
bigint_attr_cleanup(OBJ_DOM_DSA_SUBPRIME(
object_p));
bigint_attr_cleanup(OBJ_DOM_DSA_BASE(
object_p));
break;
case CKK_DH:
bigint_attr_cleanup(OBJ_DOM_DH_PRIME(
object_p));
bigint_attr_cleanup(OBJ_DOM_DH_BASE(
object_p));
break;
case CKK_X9_42_DH:
bigint_attr_cleanup(OBJ_DOM_DH942_PRIME(
object_p));
bigint_attr_cleanup(OBJ_DOM_DH942_BASE(
object_p));
bigint_attr_cleanup(OBJ_DOM_DH942_SUBPRIME(
object_p));
break;
}
/* Release Domain Parameters Object struct. */
free(OBJ_DOM(object_p));
OBJ_DOM(object_p) = NULL;
}
break;
}
}
/*
* Parse the common attributes. Return to caller with appropriate return
* value to indicate if the supplied template specifies a valid attribute
* with a valid value.
*/
CK_RV
soft_parse_common_attrs(CK_ATTRIBUTE_PTR template, uchar_t *object_type)
{
CK_RV rv = CKR_OK;
switch (template->type) {
case CKA_CLASS:
break;
/* default boolean attributes */
case CKA_TOKEN:
if ((*(CK_BBOOL *)template->pValue) == B_TRUE) {
if (!soft_keystore_status(KEYSTORE_INITIALIZED))
return (CKR_DEVICE_REMOVED);
*object_type |= TOKEN_OBJECT;
}
break;
case CKA_PRIVATE:
if ((*(CK_BBOOL *)template->pValue) == B_TRUE) {
(void) pthread_mutex_lock(&soft_giant_mutex);
if (!soft_slot.authenticated) {
/*
* Check if this is the special case when
* the PIN is never initialized in the keystore.
* If true, we will let it pass here and let
* it fail with CKR_PIN_EXPIRED later on.
*/
if (!soft_slot.userpin_change_needed) {
(void) pthread_mutex_unlock(
&soft_giant_mutex);
return (CKR_USER_NOT_LOGGED_IN);
}
}
(void) pthread_mutex_unlock(&soft_giant_mutex);
*object_type |= PRIVATE_OBJECT;
}
break;
case CKA_LABEL:
break;
default:
rv = CKR_TEMPLATE_INCONSISTENT;
}
return (rv);
}
/*
* Build a Public Key Object.
*
* - Parse the object's template, and when an error is detected such as
* invalid attribute type, invalid attribute value, etc., return
* with appropriate return value.
* - Set up attribute mask field in the object for the supplied common
* attributes that have boolean type.
* - Build the attribute_info struct to hold the value of each supplied
* attribute that has byte array type. Link attribute_info structs
* together to form the extra attribute list of the object.
* - Allocate storage for the Public Key object.
* - Build the Public Key object according to the key type. Allocate
* storage to hold the big integer value for the supplied attributes
* that are required for a certain key type.
*
*/
CK_RV
soft_build_public_key_object(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
soft_object_t *new_object, CK_ULONG mode, CK_KEY_TYPE key_type)
{
ulong_t i;
CK_KEY_TYPE keytype = (CK_KEY_TYPE)~0UL;
uint64_t attr_mask = PUBLIC_KEY_DEFAULT;
CK_RV rv = CKR_OK;
int isLabel = 0;
/* Must set flags */
int isModulus = 0;
int isPubExpo = 0;
int isPrime = 0;
int isSubprime = 0;
int isBase = 0;
int isValue = 0;
int isECParam = 0;
int isECPoint = 0;
/* Must not set flags */
int isModulusBits = 0;
CK_ULONG modulus_bits = 0;
biginteger_t modulus;
biginteger_t pubexpo;
biginteger_t prime;
biginteger_t subprime;
biginteger_t base;
biginteger_t value;
biginteger_t point;
CK_ATTRIBUTE string_tmp;
CK_ATTRIBUTE param_tmp;
public_key_obj_t *pbk;
uchar_t object_type = 0;
/* prevent bigint_attr_cleanup from freeing invalid attr value */
(void) memset(&modulus, 0x0, sizeof (biginteger_t));
(void) memset(&pubexpo, 0x0, sizeof (biginteger_t));
(void) memset(&prime, 0x0, sizeof (biginteger_t));
(void) memset(&subprime, 0x0, sizeof (biginteger_t));
(void) memset(&base, 0x0, sizeof (biginteger_t));
(void) memset(&value, 0x0, sizeof (biginteger_t));
(void) memset(&point, 0x0, sizeof (biginteger_t));
string_tmp.pValue = NULL;
param_tmp.pValue = NULL;
for (i = 0; i < ulAttrNum; i++) {
/* Public Key Object Attributes */
switch (template[i].type) {
/* common key attributes */
case CKA_KEY_TYPE:
keytype = *((CK_KEY_TYPE*)template[i].pValue);
break;
case CKA_ID:
case CKA_START_DATE:
case CKA_END_DATE:
/* common public key attribute */
case CKA_SUBJECT:
/*
* Allocate storage to hold the attribute
* value with byte array type, and add it to
* the extra attribute list of the object.
*/
rv = soft_add_extra_attr(&template[i],
new_object);
if (rv != CKR_OK) {
goto fail_cleanup;
}
break;
/*
* The following key related attribute types must
* not be specified by C_CreateObject, C_GenerateKey(Pair).
*/
case CKA_LOCAL:
case CKA_KEY_GEN_MECHANISM:
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
/* Key related boolean attributes */
case CKA_DERIVE:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= DERIVE_BOOL_ON;
break;
case CKA_ENCRYPT:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= ENCRYPT_BOOL_ON;
else
attr_mask &= ~ENCRYPT_BOOL_ON;
break;
case CKA_VERIFY:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= VERIFY_BOOL_ON;
else
attr_mask &= ~VERIFY_BOOL_ON;
break;
case CKA_VERIFY_RECOVER:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= VERIFY_RECOVER_BOOL_ON;
else
attr_mask &= ~VERIFY_RECOVER_BOOL_ON;
break;
case CKA_WRAP:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= WRAP_BOOL_ON;
else
attr_mask &= ~WRAP_BOOL_ON;
break;
case CKA_TRUSTED:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= TRUSTED_BOOL_ON;
break;
case CKA_MODIFIABLE:
if ((*(CK_BBOOL *)template[i].pValue) == B_FALSE)
attr_mask |= NOT_MODIFIABLE_BOOL_ON;
break;
/*
* The following key related attribute types must
* be specified according to the key type by
* C_CreateObject.
*/
case CKA_MODULUS:
isModulus = 1;
/*
* Copyin big integer attribute from template
* to a local variable.
*/
rv = get_bigint_attr_from_template(&modulus,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
/*
* Modulus length needs to be between min key length and
* max key length.
*/
if ((modulus.big_value_len <
MIN_RSA_KEYLENGTH_IN_BYTES) ||
(modulus.big_value_len >
MAX_RSA_KEYLENGTH_IN_BYTES)) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
break;
case CKA_PUBLIC_EXPONENT:
isPubExpo = 1;
rv = get_bigint_attr_from_template(&pubexpo,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_PRIME:
isPrime = 1;
rv = get_bigint_attr_from_template(&prime,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_SUBPRIME:
isSubprime = 1;
rv = get_bigint_attr_from_template(&subprime,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_BASE:
isBase = 1;
rv = get_bigint_attr_from_template(&base,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_VALUE:
isValue = 1;
if (mode == SOFT_CREATE_OBJ) {
if ((template[i].ulValueLen == 0) ||
(template[i].pValue == NULL)) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
}
rv = get_bigint_attr_from_template(&value,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_MODULUS_BITS:
isModulusBits = 1;
get_ulong_attr_from_template(&modulus_bits,
&template[i]);
break;
case CKA_LABEL:
isLabel = 1;
rv = get_string_from_template(&string_tmp,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_EC_PARAMS:
isECParam = 1;
rv = get_string_from_template(&param_tmp, &template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_EC_POINT:
isECPoint = 1;
rv = get_bigint_attr_from_template(&point,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
default:
rv = soft_parse_common_attrs(&template[i],
&object_type);
if (rv != CKR_OK)
goto fail_cleanup;
break;
}
} /* For */
/* Allocate storage for Public Key Object. */
pbk = calloc(1, sizeof (public_key_obj_t));
if (pbk == NULL) {
rv = CKR_HOST_MEMORY;
goto fail_cleanup;
}
new_object->object_class_u.public_key = pbk;
new_object->class = CKO_PUBLIC_KEY;
if ((mode == SOFT_CREATE_OBJ) && (keytype == (CK_KEY_TYPE)~0UL)) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
if ((mode == SOFT_GEN_KEY) && (keytype == (CK_KEY_TYPE)~0UL)) {
keytype = key_type;
}
if ((mode == SOFT_GEN_KEY) && (keytype != key_type)) {
/*
* The key type specified in the template does not
* match the implied key type based on the mechanism.
*/
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
new_object->key_type = keytype;
/* Supported key types of the Public Key Object */
switch (keytype) {
case CKK_RSA:
if (mode == SOFT_CREATE_OBJ) {
if (isModulusBits || isPrime || isSubprime ||
isBase || isValue) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
if (isModulus && isPubExpo) {
/*
* Copy big integer attribute value to the
* designated place in the public key object.
*/
copy_bigint_attr(&modulus,
KEY_PUB_RSA_MOD(pbk));
copy_bigint_attr(&pubexpo,
KEY_PUB_RSA_PUBEXPO(pbk));
} else {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
} else {
if (isModulus || isPrime || isSubprime ||
isBase || isValue) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
if (isModulusBits && isPubExpo) {
/*
* Copy big integer attribute value to the
* designated place in the public key object.
*/
copy_bigint_attr(&pubexpo,
KEY_PUB_RSA_PUBEXPO(pbk));
KEY_PUB_RSA_MOD_BITS(pbk) = modulus_bits;
} else {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
}
break;
case CKK_DSA:
if (mode == SOFT_CREATE_OBJ) {
if (isModulusBits || isModulus || isPubExpo) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
if (isPrime && isSubprime && isBase && isValue) {
copy_bigint_attr(&value,
KEY_PUB_DSA_VALUE(pbk));
} else {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
} else {
if (isModulusBits || isModulus || isPubExpo ||
isValue) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
if (!(isPrime && isSubprime && isBase)) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
}
copy_bigint_attr(&prime, KEY_PUB_DSA_PRIME(pbk));
copy_bigint_attr(&subprime, KEY_PUB_DSA_SUBPRIME(pbk));
copy_bigint_attr(&base, KEY_PUB_DSA_BASE(pbk));
break;
case CKK_DH:
if (mode == SOFT_CREATE_OBJ) {
if (isModulusBits || isModulus || isPubExpo ||
isSubprime) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
if (isPrime && isBase && isValue) {
copy_bigint_attr(&value,
KEY_PUB_DH_VALUE(pbk));
} else {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
} else {
if (isModulusBits || isModulus || isPubExpo ||
isSubprime || isValue) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
if (!(isPrime && isBase)) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
}
copy_bigint_attr(&prime, KEY_PUB_DH_PRIME(pbk));
copy_bigint_attr(&base, KEY_PUB_DH_BASE(pbk));
break;
case CKK_X9_42_DH:
if (mode == SOFT_CREATE_OBJ) {
if (isModulusBits || isModulus || isPubExpo) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
if (isPrime && isSubprime && isBase && isValue) {
copy_bigint_attr(&value,
KEY_PUB_DH942_VALUE(pbk));
} else {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
} else {
if (isModulusBits || isModulus || isPubExpo ||
isValue) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
if (!(isPrime && isSubprime && isBase)) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
}
copy_bigint_attr(&prime, KEY_PUB_DH942_PRIME(pbk));
copy_bigint_attr(&base, KEY_PUB_DH942_BASE(pbk));
copy_bigint_attr(&subprime, KEY_PUB_DH942_SUBPRIME(pbk));
break;
case CKK_EC:
if (mode == SOFT_CREATE_OBJ) {
if (isModulusBits || isModulus || isPubExpo ||
isPrime || isSubprime || isBase || isValue) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
} else if (!isECParam || !isECPoint) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
} else {
if (isModulusBits || isModulus || isPubExpo ||
isPrime || isSubprime || isBase || isValue) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
} else if (!isECParam) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
}
if (isECPoint) {
copy_bigint_attr(&point, KEY_PUB_EC_POINT(pbk));
}
rv = soft_add_extra_attr(&param_tmp, new_object);
if (rv != CKR_OK)
goto fail_cleanup;
string_attr_cleanup(&param_tmp);
break;
default:
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
/* Set up object. */
new_object->object_type = object_type;
new_object->bool_attr_mask = attr_mask;
if (isLabel) {
rv = soft_add_extra_attr(&string_tmp, new_object);
if (rv != CKR_OK)
goto fail_cleanup;
string_attr_cleanup(&string_tmp);
}
return (rv);
fail_cleanup:
/*
* cleanup the storage allocated to the local variables.
*/
bigint_attr_cleanup(&modulus);
bigint_attr_cleanup(&pubexpo);
bigint_attr_cleanup(&prime);
bigint_attr_cleanup(&subprime);
bigint_attr_cleanup(&base);
bigint_attr_cleanup(&value);
bigint_attr_cleanup(&point);
string_attr_cleanup(&string_tmp);
string_attr_cleanup(&param_tmp);
/*
* cleanup the storage allocated inside the object itself.
*/
soft_cleanup_object(new_object);
return (rv);
}
/*
* Build a Private Key Object.
*
* - Parse the object's template, and when an error is detected such as
* invalid attribute type, invalid attribute value, etc., return
* with appropriate return value.
* - Set up attribute mask field in the object for the supplied common
* attributes that have boolean type.
* - Build the attribute_info struct to hold the value of each supplied
* attribute that has byte array type. Link attribute_info structs
* together to form the extra attribute list of the object.
* - Allocate storage for the Private Key object.
* - Build the Private Key object according to the key type. Allocate
* storage to hold the big integer value for the supplied attributes
* that are required for a certain key type.
*
*/
CK_RV
soft_build_private_key_object(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
soft_object_t *new_object, CK_ULONG mode, CK_KEY_TYPE key_type)
{
ulong_t i;
CK_KEY_TYPE keytype = (CK_KEY_TYPE)~0UL;
uint64_t attr_mask = PRIVATE_KEY_DEFAULT;
CK_RV rv = CKR_OK;
int isLabel = 0;
int isECParam = 0;
/* Must set flags unless mode == SOFT_UNWRAP_KEY */
int isModulus = 0;
int isPriExpo = 0;
int isPrime = 0;
int isSubprime = 0;
int isBase = 0;
/* Must set flags if mode == SOFT_GEN_KEY */
int isValue = 0;
/* Must not set flags */
int isValueBits = 0;
CK_ULONG value_bits = 0;
/* Private Key RSA optional */
int isPubExpo = 0;
int isPrime1 = 0;
int isPrime2 = 0;
int isExpo1 = 0;
int isExpo2 = 0;
int isCoef = 0;
biginteger_t modulus;
biginteger_t priexpo;
biginteger_t prime;
biginteger_t subprime;
biginteger_t base;
biginteger_t value;
biginteger_t pubexpo;
biginteger_t prime1;
biginteger_t prime2;
biginteger_t expo1;
biginteger_t expo2;
biginteger_t coef;
CK_ATTRIBUTE string_tmp;
CK_ATTRIBUTE param_tmp;
BIGNUM x, q;
private_key_obj_t *pvk;
uchar_t object_type = 0;
/* prevent bigint_attr_cleanup from freeing invalid attr value */
(void) memset(&modulus, 0x0, sizeof (biginteger_t));
(void) memset(&priexpo, 0x0, sizeof (biginteger_t));
(void) memset(&prime, 0x0, sizeof (biginteger_t));
(void) memset(&subprime, 0x0, sizeof (biginteger_t));
(void) memset(&base, 0x0, sizeof (biginteger_t));
(void) memset(&value, 0x0, sizeof (biginteger_t));
(void) memset(&pubexpo, 0x0, sizeof (biginteger_t));
(void) memset(&prime1, 0x0, sizeof (biginteger_t));
(void) memset(&prime2, 0x0, sizeof (biginteger_t));
(void) memset(&expo1, 0x0, sizeof (biginteger_t));
(void) memset(&expo2, 0x0, sizeof (biginteger_t));
(void) memset(&coef, 0x0, sizeof (biginteger_t));
string_tmp.pValue = NULL;
param_tmp.pValue = NULL;
x.malloced = 0;
q.malloced = 0;
for (i = 0; i < ulAttrNum; i++) {
/* Private Key Object Attributes */
switch (template[i].type) {
/* common key attributes */
case CKA_KEY_TYPE:
keytype = *((CK_KEY_TYPE*)template[i].pValue);
break;
case CKA_ID:
case CKA_START_DATE:
case CKA_END_DATE:
/* common private key attribute */
case CKA_SUBJECT:
/*
* Allocate storage to hold the attribute
* value with byte array type, and add it to
* the extra attribute list of the object.
*/
rv = soft_add_extra_attr(&template[i],
new_object);
if (rv != CKR_OK) {
goto fail_cleanup;
}
break;
/*
* The following key related attribute types must
* not be specified by C_CreateObject or C_GenerateKey(Pair).
*/
case CKA_LOCAL:
case CKA_KEY_GEN_MECHANISM:
case CKA_AUTH_PIN_FLAGS:
case CKA_ALWAYS_SENSITIVE:
case CKA_NEVER_EXTRACTABLE:
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
/* Key related boolean attributes */
case CKA_DERIVE:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= DERIVE_BOOL_ON;
break;
case CKA_SENSITIVE:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= SENSITIVE_BOOL_ON;
break;
case CKA_SECONDARY_AUTH:
if (*(CK_BBOOL *)template[i].pValue) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
break;
case CKA_DECRYPT:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= DECRYPT_BOOL_ON;
else
attr_mask &= ~DECRYPT_BOOL_ON;
break;
case CKA_SIGN:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= SIGN_BOOL_ON;
else
attr_mask &= ~SIGN_BOOL_ON;
break;
case CKA_SIGN_RECOVER:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= SIGN_RECOVER_BOOL_ON;
else
attr_mask &= ~SIGN_RECOVER_BOOL_ON;
break;
case CKA_UNWRAP:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= UNWRAP_BOOL_ON;
else
attr_mask &= ~UNWRAP_BOOL_ON;
break;
case CKA_EXTRACTABLE:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= EXTRACTABLE_BOOL_ON;
else
attr_mask &= ~EXTRACTABLE_BOOL_ON;
break;
case CKA_MODIFIABLE:
if ((*(CK_BBOOL *)template[i].pValue) == B_FALSE)
attr_mask |= NOT_MODIFIABLE_BOOL_ON;
break;
/*
* The following key related attribute types must
* be specified according to the key type by
* C_CreateObject.
*/
case CKA_MODULUS:
isModulus = 1;
/*
* Copyin big integer attribute from template
* to a local variable.
*/
rv = get_bigint_attr_from_template(&modulus,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
/*
* Modulus length needs to be between min key length and
* max key length.
*/
if ((modulus.big_value_len <
MIN_RSA_KEYLENGTH_IN_BYTES) ||
(modulus.big_value_len >
MAX_RSA_KEYLENGTH_IN_BYTES)) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
break;
case CKA_PUBLIC_EXPONENT:
isPubExpo = 1;
rv = get_bigint_attr_from_template(&pubexpo,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_PRIVATE_EXPONENT:
isPriExpo = 1;
rv = get_bigint_attr_from_template(&priexpo,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_PRIME_1:
isPrime1 = 1;
rv = get_bigint_attr_from_template(&prime1,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_PRIME_2:
isPrime2 = 1;
rv = get_bigint_attr_from_template(&prime2,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_EXPONENT_1:
isExpo1 = 1;
rv = get_bigint_attr_from_template(&expo1,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_EXPONENT_2:
isExpo2 = 1;
rv = get_bigint_attr_from_template(&expo2,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_COEFFICIENT:
isCoef = 1;
rv = get_bigint_attr_from_template(&coef,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_PRIME:
isPrime = 1;
rv = get_bigint_attr_from_template(&prime,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_SUBPRIME:
isSubprime = 1;
rv = get_bigint_attr_from_template(&subprime,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_BASE:
isBase = 1;
rv = get_bigint_attr_from_template(&base,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_VALUE:
isValue = 1;
if (mode == SOFT_CREATE_OBJ) {
if ((template[i].ulValueLen == 0) ||
(template[i].pValue == NULL)) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
}
rv = get_bigint_attr_from_template(&value,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_VALUE_BITS:
isValueBits = 1;
get_ulong_attr_from_template(&value_bits,
&template[i]);
break;
case CKA_LABEL:
isLabel = 1;
rv = get_string_from_template(&string_tmp,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_EC_PARAMS:
isECParam = 1;
rv = get_string_from_template(&param_tmp,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
default:
rv = soft_parse_common_attrs(&template[i],
&object_type);
if (rv != CKR_OK)
goto fail_cleanup;
break;
}
} /* For */
/* Allocate storage for Private Key Object. */
pvk = calloc(1, sizeof (private_key_obj_t));
if (pvk == NULL) {
rv = CKR_HOST_MEMORY;
goto fail_cleanup;
}
new_object->object_class_u.private_key = pvk;
new_object->class = CKO_PRIVATE_KEY;
if ((mode == SOFT_CREATE_OBJ) && (keytype == (CK_KEY_TYPE)~0UL)) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
if (mode == SOFT_GEN_KEY) {
/*
* The key type is not specified in the application's
* template, so we use the implied key type based on
* the mechanism.
*/
if (keytype == (CK_KEY_TYPE)~0UL) {
keytype = key_type;
}
/* If still unspecified, template is incomplete */
if (keytype == (CK_KEY_TYPE)~0UL) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
/*
* The key type specified in the template does not
* match the implied key type based on the mechanism.
*/
if (keytype != key_type) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
}
if (mode == SOFT_UNWRAP_KEY) {
/*
* Note that, for mode SOFT_UNWRAP_KEY, key type is not
* implied by the mechanism (key_type), so if it is not
* specified from the attribute template (keytype), it is
* incomplete.
*/
if (keytype == (CK_KEY_TYPE)~0UL) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
}
new_object->key_type = keytype;
/* Supported key types of the Private Key Object */
switch (keytype) {
case CKK_RSA:
if (isPrime || isSubprime || isBase || isValue ||
isValueBits) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
if (mode == SOFT_GEN_KEY || mode == SOFT_UNWRAP_KEY) {
if (isModulus || isPubExpo || isPriExpo || isPrime1 ||
isPrime2 || isExpo1 || isExpo2 || isCoef) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
} else
break;
}
if (isModulus && isPriExpo) {
/*
* Copy big integer attribute value to the
* designated place in the Private Key object.
*/
copy_bigint_attr(&modulus, KEY_PRI_RSA_MOD(pvk));
copy_bigint_attr(&priexpo, KEY_PRI_RSA_PRIEXPO(pvk));
} else {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
/* The following attributes are optional. */
if (isPubExpo) {
copy_bigint_attr(&pubexpo, KEY_PRI_RSA_PUBEXPO(pvk));
}
if (isPrime1) {
copy_bigint_attr(&prime1, KEY_PRI_RSA_PRIME1(pvk));
}
if (isPrime2) {
copy_bigint_attr(&prime2, KEY_PRI_RSA_PRIME2(pvk));
}
if (isExpo1) {
copy_bigint_attr(&expo1, KEY_PRI_RSA_EXPO1(pvk));
}
if (isExpo2) {
copy_bigint_attr(&expo2, KEY_PRI_RSA_EXPO2(pvk));
}
if (isCoef) {
copy_bigint_attr(&coef, KEY_PRI_RSA_COEF(pvk));
}
break;
case CKK_DSA:
if (isModulus || isPubExpo || isPriExpo || isPrime1 ||
isPrime2 || isExpo1 || isExpo2 || isCoef ||
isValueBits) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
if (mode == SOFT_GEN_KEY || mode == SOFT_UNWRAP_KEY) {
if (isPrime || isSubprime || isBase || isValue) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
} else
break;
}
if (isPrime && isSubprime && isBase && isValue) {
/*
* The private value x must be less than subprime q.
* Size for big_init is in (32-bit) words.
*/
#ifdef __sparcv9
/* LINTED */
if (big_init(&x, ((int)value.big_value_len +
(int)sizeof (uint32_t) - 1) /
(int)sizeof (uint32_t)) != BIG_OK) {
#else /* !__sparcv9 */
if (big_init(&x, (value.big_value_len +
(int)sizeof (uint32_t) - 1) /
(int)sizeof (uint32_t)) != BIG_OK) {
#endif /* __sparcv9 */
rv = CKR_HOST_MEMORY;
goto fail_cleanup;
}
#ifdef __sparcv9
/* LINTED */
if (big_init(&q, ((int)subprime.big_value_len +
(int)sizeof (uint32_t) - 1) /
(int)sizeof (uint32_t)) != BIG_OK) {
#else /* !__sparcv9 */
if (big_init(&q, (subprime.big_value_len +
(int)sizeof (uint32_t) - 1) /
(int)sizeof (uint32_t)) != BIG_OK) {
#endif /* __sparcv9 */
rv = CKR_HOST_MEMORY;
goto fail_cleanup;
}
bytestring2bignum(&x, value.big_value,
value.big_value_len);
bytestring2bignum(&q, subprime.big_value,
subprime.big_value_len);
if (big_cmp_abs(&x, &q) > 0) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
copy_bigint_attr(&prime, KEY_PRI_DSA_PRIME(pvk));
copy_bigint_attr(&subprime, KEY_PRI_DSA_SUBPRIME(pvk));
copy_bigint_attr(&base, KEY_PRI_DSA_BASE(pvk));
copy_bigint_attr(&value, KEY_PRI_DSA_VALUE(pvk));
} else {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
break;
case CKK_DH:
if (isModulus || isPubExpo || isPriExpo || isPrime1 ||
isPrime2 || isExpo1 || isExpo2 || isCoef ||
isSubprime) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
/* CKA_VALUE_BITS is for key gen but not unwrap */
if (mode == SOFT_GEN_KEY)
KEY_PRI_DH_VAL_BITS(pvk) = (isValueBits) ?
value_bits : 0;
else if (mode == SOFT_UNWRAP_KEY) {
if (isValueBits) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
}
if (mode == SOFT_GEN_KEY || mode == SOFT_UNWRAP_KEY) {
if (isPrime || isBase || isValue) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
} else
break;
}
if (isValueBits) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
if (isPrime && isBase && isValue) {
copy_bigint_attr(&prime, KEY_PRI_DH_PRIME(pvk));
copy_bigint_attr(&base, KEY_PRI_DH_BASE(pvk));
copy_bigint_attr(&value, KEY_PRI_DH_VALUE(pvk));
} else {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
break;
case CKK_X9_42_DH:
if (isModulus || isPubExpo || isPriExpo || isPrime1 ||
isPrime2 || isExpo1 || isExpo2 || isCoef ||
isValueBits) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
if (mode == SOFT_GEN_KEY || mode == SOFT_UNWRAP_KEY) {
if (isPrime || isSubprime || isBase || isValue) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
} else
break;
}
if (isPrime && isSubprime && isBase && isValue) {
copy_bigint_attr(&prime, KEY_PRI_DH942_PRIME(pvk));
copy_bigint_attr(&base, KEY_PRI_DH942_BASE(pvk));
copy_bigint_attr(&subprime,
KEY_PRI_DH942_SUBPRIME(pvk));
copy_bigint_attr(&value, KEY_PRI_DH942_VALUE(pvk));
} else {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
break;
case CKK_EC:
if (isModulus || isPubExpo || isPrime ||
isPrime1 || isPrime2 || isExpo1 || isExpo2 || isCoef ||
isValueBits || isBase) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
} else if (isECParam) {
rv = soft_add_extra_attr(&param_tmp, new_object);
if (rv != CKR_OK)
goto fail_cleanup;
string_attr_cleanup(&param_tmp);
}
if (isValue) {
copy_bigint_attr(&value, KEY_PRI_EC_VALUE(pvk));
}
break;
default:
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
/* Set up object. */
new_object->object_type = object_type;
new_object->bool_attr_mask = attr_mask;
if (isLabel) {
rv = soft_add_extra_attr(&string_tmp, new_object);
if (rv != CKR_OK)
goto fail_cleanup;
string_attr_cleanup(&string_tmp);
}
big_finish(&x);
big_finish(&q);
return (rv);
fail_cleanup:
/*
* cleanup the storage allocated to the local variables.
*/
bigint_attr_cleanup(&modulus);
bigint_attr_cleanup(&priexpo);
bigint_attr_cleanup(&prime);
bigint_attr_cleanup(&subprime);
bigint_attr_cleanup(&base);
bigint_attr_cleanup(&value);
bigint_attr_cleanup(&pubexpo);
bigint_attr_cleanup(&prime1);
bigint_attr_cleanup(&prime2);
bigint_attr_cleanup(&expo1);
bigint_attr_cleanup(&expo2);
bigint_attr_cleanup(&coef);
string_attr_cleanup(&string_tmp);
string_attr_cleanup(&param_tmp);
big_finish(&x);
big_finish(&q);
/*
* cleanup the storage allocated inside the object itself.
*/
soft_cleanup_object(new_object);
return (rv);
}
/*
* Build a Secret Key Object.
*
* - Parse the object's template, and when an error is detected such as
* invalid attribute type, invalid attribute value, etc., return
* with appropriate return value.
* - Set up attribute mask field in the object for the supplied common
* attributes that have boolean type.
* - Build the attribute_info struct to hold the value of each supplied
* attribute that has byte array type. Link attribute_info structs
* together to form the extra attribute list of the object.
* - Allocate storage for the Secret Key object.
* - Build the Secret Key object. Allocate storage to hold the big integer
* value for the attribute CKA_VALUE that is required for all the key
* types supported by secret key object.
* This function is called internally with mode = SOFT_CREATE_OBJ_INT.
*
*/
CK_RV
soft_build_secret_key_object(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
soft_object_t *new_object, CK_ULONG mode, CK_ULONG key_len,
CK_KEY_TYPE key_type)
{
ulong_t i;
CK_KEY_TYPE keytype = (CK_KEY_TYPE)~0UL;
uint64_t attr_mask = SECRET_KEY_DEFAULT;
CK_RV rv = CKR_OK;
int isLabel = 0;
/* Must set flags if mode != SOFT_UNWRAP_KEY, else must not set */
int isValue = 0;
/* Must not set flags if mode != SOFT_UNWRAP_KEY, else optional */
int isValueLen = 0;
CK_ATTRIBUTE string_tmp;
secret_key_obj_t *sck;
uchar_t object_type = 0;
string_tmp.pValue = NULL;
/* Allocate storage for Secret Key Object. */
sck = calloc(1, sizeof (secret_key_obj_t));
if (sck == NULL) {
rv = CKR_HOST_MEMORY;
goto fail_cleanup;
}
new_object->object_class_u.secret_key = sck;
new_object->class = CKO_SECRET_KEY;
for (i = 0; i < ulAttrNum; i++) {
/* Secret Key Object Attributes */
switch (template[i].type) {
/* common key attributes */
case CKA_KEY_TYPE:
keytype = *((CK_KEY_TYPE*)template[i].pValue);
break;
case CKA_ID:
case CKA_START_DATE:
case CKA_END_DATE:
/*
* Allocate storage to hold the attribute
* value with byte array type, and add it to
* the extra attribute list of the object.
*/
rv = soft_add_extra_attr(&template[i],
new_object);
if (rv != CKR_OK) {
goto fail_cleanup;
}
break;
/*
* The following key related attribute types must
* not be specified by C_CreateObject and C_GenerateKey.
*/
case CKA_LOCAL:
case CKA_KEY_GEN_MECHANISM:
case CKA_ALWAYS_SENSITIVE:
case CKA_NEVER_EXTRACTABLE:
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
/* Key related boolean attributes */
case CKA_DERIVE:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= DERIVE_BOOL_ON;
break;
case CKA_SENSITIVE:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= SENSITIVE_BOOL_ON;
break;
case CKA_ENCRYPT:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= ENCRYPT_BOOL_ON;
else
attr_mask &= ~ENCRYPT_BOOL_ON;
break;
case CKA_DECRYPT:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= DECRYPT_BOOL_ON;
else
attr_mask &= ~DECRYPT_BOOL_ON;
break;
case CKA_SIGN:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= SIGN_BOOL_ON;
else
attr_mask &= ~SIGN_BOOL_ON;
break;
case CKA_VERIFY:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= VERIFY_BOOL_ON;
else
attr_mask &= ~VERIFY_BOOL_ON;
break;
case CKA_WRAP:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= WRAP_BOOL_ON;
else
attr_mask &= ~WRAP_BOOL_ON;
break;
case CKA_UNWRAP:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= UNWRAP_BOOL_ON;
else
attr_mask &= ~UNWRAP_BOOL_ON;
break;
case CKA_EXTRACTABLE:
if (*(CK_BBOOL *)template[i].pValue)
attr_mask |= EXTRACTABLE_BOOL_ON;
else
attr_mask &= ~EXTRACTABLE_BOOL_ON;
break;
case CKA_MODIFIABLE:
if ((*(CK_BBOOL *)template[i].pValue) == B_FALSE)
attr_mask |= NOT_MODIFIABLE_BOOL_ON;
break;
case CKA_VALUE:
isValue = 1;
if (mode == SOFT_CREATE_OBJ) {
if ((template[i].ulValueLen == 0) ||
(template[i].pValue == NULL)) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
}
/*
* Copyin attribute from template
* to a local variable.
*/
rv = get_bigint_attr_from_template((biginteger_t *)sck,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_VALUE_LEN:
isValueLen = 1;
get_ulong_attr_from_template(&sck->sk_value_len,
&template[i]);
break;
case CKA_LABEL:
isLabel = 1;
rv = get_string_from_template(&string_tmp,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
default:
rv = soft_parse_common_attrs(&template[i],
&object_type);
if (rv != CKR_OK)
goto fail_cleanup;
break;
}
} /* For */
switch (mode) {
case SOFT_CREATE_OBJ:
case SOFT_CREATE_OBJ_INT:
case SOFT_DERIVE_KEY_DH:
/*
* The key type must be specified in the application's
* template. Otherwise, returns error.
*/
if (keytype == (CK_KEY_TYPE)~0UL) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
break;
case SOFT_GEN_KEY:
if (keytype == (CK_KEY_TYPE)~0UL) {
/*
* The key type is not specified in the application's
* template, so we use the implied key type based on
* the mechanism.
*/
keytype = key_type;
} else {
if (keytype != key_type) {
/*
* The key type specified in the template
* does not match the implied key type based
* on the mechanism.
*/
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
}
/*
* If a key_len is passed as a parameter, it has to
* match the one found in the template.
*/
if (key_len > 0) {
if (isValueLen && sck->sk_value_len != key_len) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
isValueLen = 1;
sck->sk_value_len = key_len;
}
break;
case SOFT_UNWRAP_KEY:
/*
* Note that, for mode SOFT_UNWRAP_KEY, key type is not
* implied by the mechanism (key_type), so if it is not
* specified from the attribute template (keytype), it is
* incomplete.
*/
if (keytype == (CK_KEY_TYPE)~0UL) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
break;
case SOFT_DERIVE_KEY_OTHER:
/*
* For CKM_MD5_KEY_DERIVATION & CKM_SHA1_KEY_DERIVATION, the
* key type is optional.
*/
if (keytype == (CK_KEY_TYPE)~0UL) {
keytype = key_type;
}
break;
}
switch (mode) {
case SOFT_CREATE_OBJ:
case SOFT_CREATE_OBJ_INT:
switch (keytype) {
case CKK_RC4:
if (!isValue) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
if ((sck->sk_value_len < ARCFOUR_MIN_KEY_BYTES) ||
(sck->sk_value_len > ARCFOUR_MAX_KEY_BYTES)) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
break;
case CKK_GENERIC_SECRET:
if (!isValue) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
break;
case CKK_AES:
if (!isValue) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
#ifdef CRYPTO_UNLIMITED
if ((sck->sk_value_len != AES_MIN_KEY_BYTES) &&
(sck->sk_value_len != AES_192_KEY_BYTES) &&
(sck->sk_value_len != AES_MAX_KEY_BYTES)) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
#else
if (sck->sk_value_len != AES_MIN_KEY_BYTES) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
#endif /* CRYPTO_UNLIMITED */
break;
case CKK_BLOWFISH:
if (!isValue) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
if ((sck->sk_value_len < BLOWFISH_MINBYTES) ||
(sck->sk_value_len > BLOWFISH_MAXBYTES)) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
break;
case CKK_DES:
if (!isValue) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
if (sck->sk_value_len != DES_KEYSIZE) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
break;
case CKK_DES2:
if (!isValue) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
if (sck->sk_value_len != DES2_KEYSIZE) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
break;
case CKK_DES3:
if (!isValue) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
if (sck->sk_value_len != DES3_KEYSIZE) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
break;
default:
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
if (isValueLen) {
/*
* Templates for internal object creation come from
* applications calls to C_DeriveKey(), for which it
* is OKey to pass a CKA_VALUE_LEN attribute, as
* long as it does not conflict with the length of the
* CKA_VALUE attribute.
*/
if ((mode != SOFT_CREATE_OBJ_INT) ||
((key_len > 0) && sck->sk_value_len != key_len)) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
}
break;
case SOFT_GEN_KEY:
/* CKA_VALUE must not be specified */
if (isValue) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
switch (keytype) {
/*
* CKA_VALUE_LEN must be specified by C_GenerateKey
* if mech is CKK_RC4, CKK_AES, CKK_GENERIC_SECRET.
*/
case CKK_RC4:
if (!isValueLen) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
if ((sck->sk_value_len < ARCFOUR_MIN_KEY_BYTES) ||
(sck->sk_value_len > ARCFOUR_MAX_KEY_BYTES)) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
break;
case CKK_GENERIC_SECRET:
/* arbitrary key length - no length checking */
if (!isValueLen) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
break;
case CKK_AES:
if (!isValueLen) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
#ifdef CRYPTO_UNLIMITED
if ((sck->sk_value_len != AES_MIN_KEY_BYTES) &&
(sck->sk_value_len != AES_192_KEY_BYTES) &&
(sck->sk_value_len != AES_MAX_KEY_BYTES)) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
#else
if (sck->sk_value_len != AES_MIN_KEY_BYTES) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
#endif /* CRYPTO_UNLIMITED */
break;
case CKK_BLOWFISH:
if (!isValueLen) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
if ((sck->sk_value_len < BLOWFISH_MINBYTES) ||
(sck->sk_value_len > BLOWFISH_MAXBYTES)) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
break;
case CKK_DES:
case CKK_DES2:
case CKK_DES3:
/* CKA_VALUE_LEN attribute does not apply to DES<n> */
if (isValueLen) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
break;
default:
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
break;
case SOFT_UNWRAP_KEY:
/*
* According to v2.11 of PKCS#11 spec, neither CKA_VALUE nor
* CKA_VALUE_LEN can be be specified; however v2.20 has this
* restriction removed, perhaps because it makes it hard to
* determine variable-length key sizes. This case statement
* complied with v2.20.
*/
if (isValue) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
switch (keytype) {
/*
* CKA_VALUE_LEN is optional
* if key is CKK_RC4, CKK_AES, CKK_GENERIC_SECRET
* and the unwrapping mech is *_CBC_PAD.
*
* CKA_VALUE_LEN is required
* if key is CKK_RC4, CKK_AES, CKK_GENERIC_SECRET
* and the unwrapping mech is *_ECB or *_CBC.
*
* since mech is not known at this point, CKA_VALUE_LEN is
* treated as optional and the caller needs to enforce it.
*/
case CKK_RC4:
if (isValueLen) {
if ((sck->sk_value_len <
ARCFOUR_MIN_KEY_BYTES) ||
(sck->sk_value_len >
ARCFOUR_MAX_KEY_BYTES)) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
}
break;
case CKK_GENERIC_SECRET:
/* arbitrary key length - no length checking */
break;
case CKK_AES:
if (isValueLen) {
#ifdef CRYPTO_UNLIMITED
if ((sck->sk_value_len != AES_MIN_KEY_BYTES) &&
(sck->sk_value_len != AES_192_KEY_BYTES) &&
(sck->sk_value_len != AES_MAX_KEY_BYTES)) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
#else
if (sck->sk_value_len != AES_MIN_KEY_BYTES) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
#endif /* CRYPTO_UNLIMITED */
}
break;
case CKK_BLOWFISH:
if (isValueLen &&
((sck->sk_value_len < BLOWFISH_MINBYTES) ||
(sck->sk_value_len > BLOWFISH_MAXBYTES))) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
break;
case CKK_DES:
case CKK_DES2:
case CKK_DES3:
/* CKA_VALUE_LEN attribute does not apply to DES<n> */
if (isValueLen) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
break;
default:
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
break;
case SOFT_DERIVE_KEY_DH:
/* CKA_VALUE must not be specified */
if (isValue) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
switch (keytype) {
/*
* CKA_VALUE_LEN is optional
* if mech is CKK_RC4, CKK_AES, CKK_GENERIC_SECRET.
*/
case CKK_RC4:
if (isValueLen) {
if ((sck->sk_value_len <
ARCFOUR_MIN_KEY_BYTES) ||
(sck->sk_value_len >
ARCFOUR_MAX_KEY_BYTES)) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
}
break;
case CKK_GENERIC_SECRET:
/* arbitrary key length - no length checking */
break;
case CKK_AES:
if (isValueLen) {
#ifdef CRYPTO_UNLIMITED
if ((sck->sk_value_len != AES_MIN_KEY_BYTES) &&
(sck->sk_value_len != AES_192_KEY_BYTES) &&
(sck->sk_value_len != AES_MAX_KEY_BYTES)) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
#else
if (sck->sk_value_len != AES_MIN_KEY_BYTES) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
#endif /* CRYPTO_UNLIMITED */
}
break;
case CKK_BLOWFISH:
if (isValueLen &&
((sck->sk_value_len < BLOWFISH_MINBYTES) ||
(sck->sk_value_len > BLOWFISH_MAXBYTES))) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto fail_cleanup;
}
break;
case CKK_DES:
case CKK_DES2:
case CKK_DES3:
/* CKA_VALUE_LEN attribute does not apply to DES<n> */
if (isValueLen) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
break;
default:
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
break;
case SOFT_DERIVE_KEY_OTHER:
/* CKA_VALUE must not be specified */
if (isValue) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
switch (keytype) {
/*
* CKA_VALUE_LEN is an optional attribute for
* CKM_SHA1_KEY_DERIVATION and CKM_MD5_KEY_DERIVATION
* if mech is CKK_RC4, CKK_AES, CKK_GENERIC_SECRET.
*/
case CKK_RC4:
case CKK_GENERIC_SECRET:
case CKK_AES:
case CKK_BLOWFISH:
/*
* No need to check key length value here, it will be
* validated later in soft_key_derive_check_length().
*/
break;
case CKK_DES:
case CKK_DES2:
case CKK_DES3:
/* CKA_VALUE_LEN attribute does not apply to DES<n> */
if (isValueLen) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
break;
default:
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
break;
}
/* Set up object. */
new_object->key_type = keytype;
new_object->object_type = object_type;
new_object->bool_attr_mask = attr_mask;
if (isLabel) {
rv = soft_add_extra_attr(&string_tmp, new_object);
if (rv != CKR_OK)
goto fail_cleanup;
string_attr_cleanup(&string_tmp);
}
return (rv);
fail_cleanup:
/*
* cleanup the storage allocated to the local variables.
*/
bigint_attr_cleanup((biginteger_t *)sck);
string_attr_cleanup(&string_tmp);
/*
* cleanup the storage allocated inside the object itself.
*/
soft_cleanup_object(new_object);
return (rv);
}
/*
* Build a Domain Parameter Object.
*
* - Parse the object's template, and when an error is detected such as
* invalid attribute type, invalid attribute value, etc., return
* with appropriate return value.
* - Allocate storage for the Domain Parameter object.
* - Build the Domain Parameter object according to the key type. Allocate
* storage to hold the big integer value for the supplied attributes
* that are required for a certain key type.
*
*/
CK_RV
soft_build_domain_parameters_object(CK_ATTRIBUTE_PTR template,
CK_ULONG ulAttrNum, soft_object_t *new_object)
{
ulong_t i;
CK_KEY_TYPE keytype = (CK_KEY_TYPE)~0UL;
CK_RV rv = CKR_OK;
int isLabel = 0;
/* Must set flags */
int isPrime = 0;
int isSubprime = 0;
int isBase = 0;
/* Must not set flags */
int isPrimeBits = 0;
int isSubPrimeBits = 0;
biginteger_t prime;
biginteger_t subprime;
biginteger_t base;
CK_ATTRIBUTE string_tmp;
domain_obj_t *dom;
uchar_t object_type = 0;
/* prevent bigint_attr_cleanup from freeing invalid attr value */
(void) memset(&prime, 0x0, sizeof (biginteger_t));
(void) memset(&subprime, 0x0, sizeof (biginteger_t));
(void) memset(&base, 0x0, sizeof (biginteger_t));
string_tmp.pValue = NULL;
for (i = 0; i < ulAttrNum; i++) {
/* Domain Parameters Object Attributes */
switch (template[i].type) {
/* common domain parameter attribute */
case CKA_KEY_TYPE:
keytype = *((CK_KEY_TYPE*)template[i].pValue);
break;
/*
* The following common domain parameter attribute
* must not be specified by C_CreateObject.
*/
case CKA_LOCAL:
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
/*
* The following domain parameter attributes must be
* specified according to the key type by
* C_CreateObject.
*/
case CKA_PRIME:
isPrime = 1;
/*
* Copyin big integer attribute from template
* to a local variable.
*/
rv = get_bigint_attr_from_template(&prime,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_SUBPRIME:
isSubprime = 1;
rv = get_bigint_attr_from_template(&subprime,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_BASE:
isBase = 1;
rv = get_bigint_attr_from_template(&base,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_PRIME_BITS:
isPrimeBits = 1;
break;
case CKA_SUB_PRIME_BITS:
isSubPrimeBits = 1;
break;
case CKA_LABEL:
isLabel = 1;
rv = get_string_from_template(&string_tmp,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
default:
rv = soft_parse_common_attrs(&template[i],
&object_type);
if (rv != CKR_OK)
goto fail_cleanup;
break;
}
} /* For */
/* Allocate storage for Domain Parameters Object. */
dom = calloc(1, sizeof (domain_obj_t));
if (dom == NULL) {
rv = CKR_HOST_MEMORY;
goto fail_cleanup;
}
new_object->object_class_u.domain = dom;
new_object->class = CKO_DOMAIN_PARAMETERS;
if (keytype == (CK_KEY_TYPE)~0UL) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
new_object->key_type = keytype;
/* Supported key types of the Domain Parameters Object */
switch (keytype) {
case CKK_DSA:
if (isPrimeBits || isSubPrimeBits) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
if (isPrime && isSubprime && isBase) {
/*
* Copy big integer attribute value to the
* designated place in the domain parameter
* object.
*/
copy_bigint_attr(&prime, KEY_DOM_DSA_PRIME(dom));
copy_bigint_attr(&subprime, KEY_DOM_DSA_SUBPRIME(dom));
copy_bigint_attr(&base, KEY_DOM_DSA_BASE(dom));
} else {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
break;
case CKK_DH:
if (isPrimeBits || isSubprime || isSubPrimeBits) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
if (isPrime && isBase) {
copy_bigint_attr(&prime, KEY_DOM_DH_PRIME(dom));
copy_bigint_attr(&base, KEY_DOM_DH_BASE(dom));
} else {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
break;
case CKK_X9_42_DH:
if (isPrimeBits || isSubPrimeBits) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
if (isPrime && isSubprime && isBase) {
copy_bigint_attr(&prime, KEY_DOM_DH942_PRIME(dom));
copy_bigint_attr(&base, KEY_DOM_DH942_BASE(dom));
copy_bigint_attr(&subprime,
KEY_DOM_DH942_SUBPRIME(dom));
} else {
rv = CKR_TEMPLATE_INCOMPLETE;
goto fail_cleanup;
}
break;
default:
rv = CKR_TEMPLATE_INCONSISTENT;
goto fail_cleanup;
}
new_object->object_type = object_type;
if (isLabel) {
rv = soft_add_extra_attr(&string_tmp, new_object);
if (rv != CKR_OK)
goto fail_cleanup;
string_attr_cleanup(&string_tmp);
}
return (rv);
fail_cleanup:
/*
* cleanup the storage allocated to the local variables.
*/
bigint_attr_cleanup(&prime);
bigint_attr_cleanup(&subprime);
bigint_attr_cleanup(&base);
string_attr_cleanup(&string_tmp);
/*
* cleanup the storage allocated inside the object itself.
*/
soft_cleanup_object(new_object);
return (rv);
}
/*
* Build a Certificate Object
*
* - Parse the object's template, and when an error is detected such as
* invalid attribute type, invalid attribute value, etc., return
* with appropriate return value.
* - Allocate storage for the Certificate object
*/
static CK_RV
soft_build_certificate_object(CK_ATTRIBUTE_PTR template,
CK_ULONG ulAttrNum, soft_object_t *new_object,
CK_CERTIFICATE_TYPE cert_type)
{
uint64_t attr_mask = 0;
CK_RV rv = CKR_OK;
CK_ULONG i;
int owner_set = 0;
int value_set = 0;
int subject_set = 0;
certificate_obj_t *cert;
/* certificate type defaults to the value given as a parameter */
CK_CERTIFICATE_TYPE certtype = cert_type;
CK_ATTRIBUTE string_tmp;
int isLabel = 0;
uchar_t object_type = 0;
/*
* Look for the certificate type attribute and do some
* sanity checking before creating the structures.
*/
for (i = 0; i < ulAttrNum; i++) {
/* Certificate Object Attributes */
switch (template[i].type) {
case CKA_CERTIFICATE_TYPE:
certtype =
*((CK_CERTIFICATE_TYPE*)template[i].pValue);
break;
case CKA_SUBJECT:
subject_set = 1;
break;
case CKA_OWNER:
owner_set = 1;
break;
case CKA_VALUE:
value_set = 1;
break;
}
}
/* The certificate type MUST be specified */
if (certtype != CKC_X_509 && certtype != CKC_X_509_ATTR_CERT)
return (CKR_TEMPLATE_INCOMPLETE);
/*
* For X.509 certs, the CKA_SUBJECT and CKA_VALUE
* must be present at creation time.
*/
if (certtype == CKC_X_509 &&
(!subject_set || !value_set))
return (CKR_TEMPLATE_INCOMPLETE);
/*
* For X.509 Attribute certs, the CKA_OWNER and CKA_VALUE
* must be present at creation time.
*/
if (certtype == CKC_X_509_ATTR_CERT &&
(!owner_set || !value_set))
return (CKR_TEMPLATE_INCOMPLETE);
string_tmp.pValue = NULL;
cert = calloc(1, sizeof (certificate_obj_t));
if (cert == NULL) {
return (CKR_HOST_MEMORY);
}
cert->certificate_type = certtype;
for (i = 0; i < ulAttrNum; i++) {
/* Certificate Object Attributes */
switch (certtype) {
case CKC_X_509:
switch (template[i].type) {
case CKA_SUBJECT:
rv = get_cert_attr_from_template(
&cert->cert_type_u.x509.subject,
&template[i]);
break;
case CKA_VALUE:
rv = get_cert_attr_from_template(
&cert->cert_type_u.x509.value,
&template[i]);
break;
case CKA_LABEL:
isLabel = 1;
rv = get_string_from_template(
&string_tmp,
&template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_ID:
case CKA_ISSUER:
case CKA_SERIAL_NUMBER:
rv = soft_add_extra_attr(&template[i],
new_object);
break;
case CKA_MODIFIABLE:
if ((*(CK_BBOOL *)template[i].pValue) ==
B_FALSE)
attr_mask |=
NOT_MODIFIABLE_BOOL_ON;
break;
case CKA_CERTIFICATE_TYPE:
break;
default:
rv = soft_parse_common_attrs(
&template[i], &object_type);
if (rv != CKR_OK)
goto fail_cleanup;
}
break;
case CKC_X_509_ATTR_CERT:
switch (template[i].type) {
case CKA_OWNER:
rv = get_cert_attr_from_template(
&cert->cert_type_u.x509_attr.owner,
&template[i]);
break;
case CKA_VALUE:
rv = get_cert_attr_from_template(
&cert->cert_type_u.x509_attr.value,
&template[i]);
break;
case CKA_LABEL:
isLabel = 1;
rv = get_string_from_template(
&string_tmp, &template[i]);
if (rv != CKR_OK)
goto fail_cleanup;
break;
case CKA_SERIAL_NUMBER:
case CKA_AC_ISSUER:
case CKA_ATTR_TYPES:
rv = soft_add_extra_attr(&template[i],
new_object);
break;
case CKA_MODIFIABLE:
if ((*(CK_BBOOL *)template[i].pValue) ==
B_FALSE)
attr_mask |=
NOT_MODIFIABLE_BOOL_ON;
break;
case CKA_CERTIFICATE_TYPE:
break;
default:
rv = soft_parse_common_attrs(
&template[i], &object_type);
if (rv != CKR_OK)
goto fail_cleanup;
break;
}
break;
default:
rv = CKR_TEMPLATE_INCOMPLETE;
break;
}
}
if (rv == CKR_OK) {
new_object->object_class_u.certificate = cert;
new_object->class = CKO_CERTIFICATE;
new_object->object_type = object_type;
new_object->cert_type = certtype;
new_object->bool_attr_mask = attr_mask;
if (isLabel) {
rv = soft_add_extra_attr(&string_tmp, new_object);
if (rv != CKR_OK)
goto fail_cleanup;
string_attr_cleanup(&string_tmp);
}
}
fail_cleanup:
if (rv != CKR_OK) {
soft_cleanup_cert_object(new_object);
}
return (rv);
}
/*
* Validate the attribute types in the object's template. Then,
* call the appropriate build function according to the class of
* the object specified in the template.
*
* Note: The following classes of objects are supported:
* - CKO_PUBLIC_KEY
* - CKO_PRIVATE_KEY
* - CKO_SECRET_KEY
* - CKO_DOMAIN_PARAMETERS
* - CKO_CERTIFICATE
*
*/
CK_RV
soft_build_object(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
soft_object_t *new_object)
{
CK_OBJECT_CLASS class = (CK_OBJECT_CLASS)~0UL;
CK_RV rv = CKR_OK;
if (template == NULL) {
return (CKR_ARGUMENTS_BAD);
}
/* Validate the attribute type in the template. */
rv = soft_validate_attr(template, ulAttrNum, &class);
if (rv != CKR_OK)
return (rv);
/*
* CKA_CLASS is a mandatory attribute for C_CreateObject
*/
if (class == (CK_OBJECT_CLASS)~0UL)
return (CKR_TEMPLATE_INCOMPLETE);
/*
* Call the appropriate function based on the supported class
* of the object.
*/
switch (class) {
case CKO_PUBLIC_KEY:
rv = soft_build_public_key_object(template, ulAttrNum,
new_object, SOFT_CREATE_OBJ, (CK_KEY_TYPE)~0UL);
break;
case CKO_PRIVATE_KEY:
rv = soft_build_private_key_object(template, ulAttrNum,
new_object, SOFT_CREATE_OBJ, (CK_KEY_TYPE)~0UL);
break;
case CKO_SECRET_KEY:
rv = soft_build_secret_key_object(template, ulAttrNum,
new_object, SOFT_CREATE_OBJ, 0, (CK_KEY_TYPE)~0UL);
break;
case CKO_DOMAIN_PARAMETERS:
rv = soft_build_domain_parameters_object(template, ulAttrNum,
new_object);
break;
case CKO_CERTIFICATE:
rv = soft_build_certificate_object(template, ulAttrNum,
new_object, (CK_CERTIFICATE_TYPE)~0UL);
break;
case CKO_DATA:
case CKO_HW_FEATURE:
case CKO_VENDOR_DEFINED:
default:
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
return (rv);
}
/*
* Validate the attribute types in the object's template. Then,
* call the appropriate build function according to the class of
* the object specified in the template.
*
*/
CK_RV
soft_build_key(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
soft_object_t *new_object, CK_OBJECT_CLASS class, CK_KEY_TYPE key_type,
CK_ULONG key_len, CK_ULONG mode)
{
CK_RV rv = CKR_OK;
CK_OBJECT_CLASS temp_class = (CK_OBJECT_CLASS)~0UL;
/* Validate the attribute type in the template. */
if ((template != NULL) && (ulAttrNum != 0)) {
rv = soft_validate_attr(template, ulAttrNum, &temp_class);
if (rv != CKR_OK)
return (rv);
}
/*
* If either the class from the parameter list ("class") or
* the class from the template ("temp_class") is not specified,
* try to use the other one.
*/
if (temp_class == (CK_OBJECT_CLASS)~0UL) {
temp_class = class;
} else if (class == (CK_OBJECT_CLASS)~0UL) {
class = temp_class;
}
/* If object class is still not specified, template is incomplete. */
if (class == (CK_OBJECT_CLASS)~0UL)
return (CKR_TEMPLATE_INCOMPLETE);
/* Class should match if specified in both parameters and template. */
if (class != temp_class)
return (CKR_TEMPLATE_INCONSISTENT);
/*
* Call the appropriate function based on the supported class
* of the object.
*/
switch (class) {
case CKO_PUBLIC_KEY:
/* Unwrapping public keys is not supported. */
if (mode == SOFT_UNWRAP_KEY) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
break;
}
rv = soft_build_public_key_object(template, ulAttrNum,
new_object, mode, key_type);
break;
case CKO_PRIVATE_KEY:
rv = soft_build_private_key_object(template, ulAttrNum,
new_object, mode, key_type);
break;
case CKO_SECRET_KEY:
rv = soft_build_secret_key_object(template, ulAttrNum,
new_object, mode, key_len, key_type);
break;
case CKO_DOMAIN_PARAMETERS:
/* Unwrapping domain parameters is not supported. */
if (mode == SOFT_UNWRAP_KEY) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
break;
}
rv = soft_build_domain_parameters_object(template, ulAttrNum,
new_object);
break;
case CKO_DATA:
case CKO_CERTIFICATE:
case CKO_HW_FEATURE:
case CKO_VENDOR_DEFINED:
default:
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
return (rv);
}
/*
* Get the value of a requested attribute that is common to all supported
* classes (i.e. public key, private key, secret key, domain parameters,
* and certificate classes).
*/
CK_RV
soft_get_common_attrs(soft_object_t *object_p, CK_ATTRIBUTE_PTR template,
uchar_t object_type)
{
CK_RV rv = CKR_OK;
switch (template->type) {
case CKA_CLASS:
return (get_ulong_attr_from_object(object_p->class,
template));
/* default boolean attributes */
case CKA_TOKEN:
template->ulValueLen = sizeof (CK_BBOOL);
if (template->pValue == NULL) {
return (CKR_OK);
}
if (object_type & TOKEN_OBJECT)
*((CK_BBOOL *)template->pValue) = B_TRUE;
else
*((CK_BBOOL *)template->pValue) = B_FALSE;
break;
case CKA_PRIVATE:
template->ulValueLen = sizeof (CK_BBOOL);
if (template->pValue == NULL) {
return (CKR_OK);
}
if (object_type & PRIVATE_OBJECT)
*((CK_BBOOL *)template->pValue) = B_TRUE;
else
*((CK_BBOOL *)template->pValue) = B_FALSE;
break;
case CKA_MODIFIABLE:
template->ulValueLen = sizeof (CK_BBOOL);
if (template->pValue == NULL) {
return (CKR_OK);
}
if ((object_p->bool_attr_mask) & NOT_MODIFIABLE_BOOL_ON)
*((CK_BBOOL *)template->pValue) = B_FALSE;
else
*((CK_BBOOL *)template->pValue) = B_TRUE;
break;
case CKA_LABEL:
return (get_extra_attr_from_object(object_p,
template));
default:
/*
* The specified attribute for the object is invalid.
* (the object does not possess such an attribute.)
*/
template->ulValueLen = (CK_ULONG)-1;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
return (rv);
}
/*
* Get the value of a requested attribute that is common to all key objects
* (i.e. public key, private key and secret key).
*/
CK_RV
soft_get_common_key_attrs(soft_object_t *object_p, CK_ATTRIBUTE_PTR template)
{
switch (template->type) {
case CKA_KEY_TYPE:
return (get_ulong_attr_from_object(object_p->key_type,
template));
case CKA_ID:
case CKA_START_DATE:
case CKA_END_DATE:
/*
* The above extra attributes have byte array type.
*/
return (get_extra_attr_from_object(object_p,
template));
/* Key related boolean attributes */
case CKA_LOCAL:
return (get_bool_attr_from_object(object_p,
LOCAL_BOOL_ON, template));
case CKA_DERIVE:
return (get_bool_attr_from_object(object_p,
DERIVE_BOOL_ON, template));
case CKA_KEY_GEN_MECHANISM:
return (get_ulong_attr_from_object(object_p->mechanism,
template));
default:
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
}
/*
* Get the value of a requested attribute of a Public Key Object.
*
* Rule: All the attributes in the public key object can be revealed.
*/
CK_RV
soft_get_public_key_attribute(soft_object_t *object_p,
CK_ATTRIBUTE_PTR template)
{
CK_RV rv = CKR_OK;
CK_KEY_TYPE keytype = object_p->key_type;
switch (template->type) {
case CKA_SUBJECT:
case CKA_EC_PARAMS:
/*
* The above extra attributes have byte array type.
*/
return (get_extra_attr_from_object(object_p,
template));
/* Key related boolean attributes */
case CKA_ENCRYPT:
return (get_bool_attr_from_object(object_p,
ENCRYPT_BOOL_ON, template));
case CKA_VERIFY:
return (get_bool_attr_from_object(object_p,
VERIFY_BOOL_ON, template));
case CKA_VERIFY_RECOVER:
return (get_bool_attr_from_object(object_p,
VERIFY_RECOVER_BOOL_ON, template));
case CKA_WRAP:
return (get_bool_attr_from_object(object_p,
WRAP_BOOL_ON, template));
case CKA_TRUSTED:
return (get_bool_attr_from_object(object_p,
TRUSTED_BOOL_ON, template));
case CKA_MODULUS:
/*
* This attribute is valid only for RSA public key
* object.
*/
if (keytype == CKK_RSA) {
return (get_bigint_attr_from_object(
OBJ_PUB_RSA_MOD(object_p), template));
} else {
template->ulValueLen = (CK_ULONG)-1;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
case CKA_PUBLIC_EXPONENT:
if (keytype == CKK_RSA) {
return (get_bigint_attr_from_object(
OBJ_PUB_RSA_PUBEXPO(object_p), template));
} else {
template->ulValueLen = (CK_ULONG)-1;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
case CKA_MODULUS_BITS:
if (keytype == CKK_RSA) {
return (get_ulong_attr_from_object(
OBJ_PUB_RSA_MOD_BITS(object_p), template));
} else {
template->ulValueLen = (CK_ULONG)-1;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
case CKA_PRIME:
switch (keytype) {
case CKK_DSA:
return (get_bigint_attr_from_object(
OBJ_PUB_DSA_PRIME(object_p), template));
case CKK_DH:
return (get_bigint_attr_from_object(
OBJ_PUB_DH_PRIME(object_p), template));
case CKK_X9_42_DH:
return (get_bigint_attr_from_object(
OBJ_PUB_DH942_PRIME(object_p), template));
default:
template->ulValueLen = (CK_ULONG)-1;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
case CKA_SUBPRIME:
switch (keytype) {
case CKK_DSA:
return (get_bigint_attr_from_object(
OBJ_PUB_DSA_SUBPRIME(object_p), template));
case CKK_X9_42_DH:
return (get_bigint_attr_from_object(
OBJ_PUB_DH942_SUBPRIME(object_p), template));
default:
template->ulValueLen = (CK_ULONG)-1;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
case CKA_BASE:
switch (keytype) {
case CKK_DSA:
return (get_bigint_attr_from_object(
OBJ_PUB_DSA_BASE(object_p), template));
case CKK_DH:
return (get_bigint_attr_from_object(
OBJ_PUB_DH_BASE(object_p), template));
case CKK_X9_42_DH:
return (get_bigint_attr_from_object(
OBJ_PUB_DH942_BASE(object_p), template));
default:
template->ulValueLen = (CK_ULONG)-1;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
case CKA_EC_POINT:
return (get_bigint_attr_from_object(
OBJ_PUB_EC_POINT(object_p), template));
case CKA_VALUE:
switch (keytype) {
case CKK_DSA:
return (get_bigint_attr_from_object(
OBJ_PUB_DSA_VALUE(object_p), template));
case CKK_DH:
return (get_bigint_attr_from_object(
OBJ_PUB_DH_VALUE(object_p), template));
case CKK_X9_42_DH:
return (get_bigint_attr_from_object(
OBJ_PUB_DH942_VALUE(object_p), template));
default:
template->ulValueLen = (CK_ULONG)-1;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
default:
/*
* First, get the value of the request attribute defined
* in the list of common key attributes. If the request
* attribute is not found in that list, then get the
* attribute from the list of common attributes.
*/
rv = soft_get_common_key_attrs(object_p, template);
if (rv == CKR_ATTRIBUTE_TYPE_INVALID) {
rv = soft_get_common_attrs(object_p, template,
object_p->object_type);
}
break;
}
return (rv);
}
/*
* Get the value of a requested attribute of a Private Key Object.
*
* Rule: All the attributes in the private key object can be revealed
* except those marked with footnote number "7" when the object
* has its CKA_SENSITIVE attribute set to TRUE or its
* CKA_EXTRACTABLE attribute set to FALSE (p.88 in PKCS11 spec.).
*/
CK_RV
soft_get_private_key_attribute(soft_object_t *object_p,
CK_ATTRIBUTE_PTR template)
{
CK_RV rv = CKR_OK;
CK_KEY_TYPE keytype = object_p->key_type;
/*
* If the following specified attributes for the private key
* object cannot be revealed because the object is sensitive
* or unextractable, then the ulValueLen is set to -1.
*/
if ((object_p->bool_attr_mask & SENSITIVE_BOOL_ON) ||
!(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) {
switch (template->type) {
case CKA_PRIVATE_EXPONENT:
case CKA_PRIME_1:
case CKA_PRIME_2:
case CKA_EXPONENT_1:
case CKA_EXPONENT_2:
case CKA_COEFFICIENT:
case CKA_VALUE:
template->ulValueLen = (CK_ULONG)-1;
return (CKR_ATTRIBUTE_SENSITIVE);
}
}
switch (template->type) {
case CKA_SUBJECT:
case CKA_EC_PARAMS:
/*
* The above extra attributes have byte array type.
*/
return (get_extra_attr_from_object(object_p,
template));
/* Key related boolean attributes */
case CKA_SENSITIVE:
return (get_bool_attr_from_object(object_p,
SENSITIVE_BOOL_ON, template));
case CKA_SECONDARY_AUTH:
return (get_bool_attr_from_object(object_p,
SECONDARY_AUTH_BOOL_ON, template));
case CKA_DECRYPT:
return (get_bool_attr_from_object(object_p,
DECRYPT_BOOL_ON, template));
case CKA_SIGN:
return (get_bool_attr_from_object(object_p,
SIGN_BOOL_ON, template));
case CKA_SIGN_RECOVER:
return (get_bool_attr_from_object(object_p,
SIGN_RECOVER_BOOL_ON, template));
case CKA_UNWRAP:
return (get_bool_attr_from_object(object_p,
UNWRAP_BOOL_ON, template));
case CKA_EXTRACTABLE:
return (get_bool_attr_from_object(object_p,
EXTRACTABLE_BOOL_ON, template));
case CKA_ALWAYS_SENSITIVE:
return (get_bool_attr_from_object(object_p,
ALWAYS_SENSITIVE_BOOL_ON, template));
case CKA_NEVER_EXTRACTABLE:
return (get_bool_attr_from_object(object_p,
NEVER_EXTRACTABLE_BOOL_ON, template));
case CKA_MODULUS:
if (keytype == CKK_RSA) {
return (get_bigint_attr_from_object(
OBJ_PRI_RSA_MOD(object_p), template));
} else {
template->ulValueLen = (CK_ULONG)-1;
rv = CKR_ATTRIBUTE_TYPE_INVALID;
break;
}
case CKA_PUBLIC_EXPONENT:
if (keytype == CKK_RSA) {
return (get_bigint_attr_from_object(
OBJ_PRI_RSA_PUBEXPO(object_p), template));
} else {
template->ulValueLen = (CK_ULONG)-1;
rv = CKR_ATTRIBUTE_TYPE_INVALID;
break;
}
case CKA_PRIVATE_EXPONENT:
if (keytype == CKK_RSA) {
return (get_bigint_attr_from_object(
OBJ_PRI_RSA_PRIEXPO(object_p), template));
} else {
template->ulValueLen = (CK_ULONG)-1;
rv = CKR_ATTRIBUTE_TYPE_INVALID;
break;
}
case CKA_PRIME_1:
if (keytype == CKK_RSA) {
return (get_bigint_attr_from_object(
OBJ_PRI_RSA_PRIME1(object_p), template));
} else {
template->ulValueLen = (CK_ULONG)-1;
rv = CKR_ATTRIBUTE_TYPE_INVALID;
break;
}
case CKA_PRIME_2:
if (keytype == CKK_RSA) {
return (get_bigint_attr_from_object(
OBJ_PRI_RSA_PRIME2(object_p), template));
} else {
template->ulValueLen = (CK_ULONG)-1;
rv = CKR_ATTRIBUTE_TYPE_INVALID;
break;
}
case CKA_EXPONENT_1:
if (keytype == CKK_RSA) {
return (get_bigint_attr_from_object(
OBJ_PRI_RSA_EXPO1(object_p), template));
} else {
template->ulValueLen = (CK_ULONG)-1;
rv = CKR_ATTRIBUTE_TYPE_INVALID;
break;
}
case CKA_EXPONENT_2:
if (keytype == CKK_RSA) {
return (get_bigint_attr_from_object(
OBJ_PRI_RSA_EXPO2(object_p), template));
} else {
template->ulValueLen = (CK_ULONG)-1;
rv = CKR_ATTRIBUTE_TYPE_INVALID;
break;
}
case CKA_COEFFICIENT:
if (keytype == CKK_RSA) {
return (get_bigint_attr_from_object(
OBJ_PRI_RSA_COEF(object_p), template));
} else {
template->ulValueLen = (CK_ULONG)-1;
rv = CKR_ATTRIBUTE_TYPE_INVALID;
break;
}
case CKA_VALUE_BITS:
if (keytype == CKK_DH) {
return (get_ulong_attr_from_object(
OBJ_PRI_DH_VAL_BITS(object_p), template));
} else {
template->ulValueLen = (CK_ULONG)-1;
rv = CKR_ATTRIBUTE_TYPE_INVALID;
break;
}
case CKA_PRIME:
switch (keytype) {
case CKK_DSA:
return (get_bigint_attr_from_object(
OBJ_PRI_DSA_PRIME(object_p), template));
case CKK_DH:
return (get_bigint_attr_from_object(
OBJ_PRI_DH_PRIME(object_p), template));
case CKK_X9_42_DH:
return (get_bigint_attr_from_object(
OBJ_PRI_DH942_PRIME(object_p), template));
default:
template->ulValueLen = (CK_ULONG)-1;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
case CKA_SUBPRIME:
switch (keytype) {
case CKK_DSA:
return (get_bigint_attr_from_object(
OBJ_PRI_DSA_SUBPRIME(object_p), template));
case CKK_X9_42_DH:
return (get_bigint_attr_from_object(
OBJ_PRI_DH942_SUBPRIME(object_p), template));
default:
template->ulValueLen = (CK_ULONG)-1;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
case CKA_BASE:
switch (keytype) {
case CKK_DSA:
return (get_bigint_attr_from_object(
OBJ_PRI_DSA_BASE(object_p), template));
case CKK_DH:
return (get_bigint_attr_from_object(
OBJ_PRI_DH_BASE(object_p), template));
case CKK_X9_42_DH:
return (get_bigint_attr_from_object(
OBJ_PRI_DH942_BASE(object_p), template));
default:
template->ulValueLen = (CK_ULONG)-1;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
case CKA_VALUE:
switch (keytype) {
case CKK_DSA:
return (get_bigint_attr_from_object(
OBJ_PRI_DSA_VALUE(object_p), template));
case CKK_DH:
return (get_bigint_attr_from_object(
OBJ_PRI_DH_VALUE(object_p), template));
case CKK_X9_42_DH:
return (get_bigint_attr_from_object(
OBJ_PRI_DH942_VALUE(object_p), template));
case CKK_EC:
return (get_bigint_attr_from_object(
OBJ_PRI_EC_VALUE(object_p), template));
default:
template->ulValueLen = (CK_ULONG)-1;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
default:
/*
* First, get the value of the request attribute defined
* in the list of common key attributes. If the request
* attribute is not found in that list, then get the
* attribute from the list of common attributes.
*/
rv = soft_get_common_key_attrs(object_p, template);
if (rv == CKR_ATTRIBUTE_TYPE_INVALID) {
rv = soft_get_common_attrs(object_p, template,
object_p->object_type);
}
break;
}
return (rv);
}
/*
* Get the value of a requested attribute of a Secret Key Object.
*
* Rule: All the attributes in the secret key object can be revealed
* except those marked with footnote number "7" when the object
* has its CKA_SENSITIVE attribute set to TRUE or its
* CKA_EXTRACTABLE attribute set to FALSE (p.88 in PKCS11 spec.).
*/
CK_RV
soft_get_secret_key_attribute(soft_object_t *object_p,
CK_ATTRIBUTE_PTR template)
{
CK_RV rv = CKR_OK;
CK_KEY_TYPE keytype = object_p->key_type;
switch (template->type) {
/* Key related boolean attributes */
case CKA_SENSITIVE:
return (get_bool_attr_from_object(object_p,
SENSITIVE_BOOL_ON, template));
case CKA_ENCRYPT:
return (get_bool_attr_from_object(object_p,
ENCRYPT_BOOL_ON, template));
case CKA_DECRYPT:
return (get_bool_attr_from_object(object_p,
DECRYPT_BOOL_ON, template));
case CKA_SIGN:
return (get_bool_attr_from_object(object_p,
SIGN_BOOL_ON, template));
case CKA_VERIFY:
return (get_bool_attr_from_object(object_p,
VERIFY_BOOL_ON, template));
case CKA_WRAP:
return (get_bool_attr_from_object(object_p,
WRAP_BOOL_ON, template));
case CKA_UNWRAP:
return (get_bool_attr_from_object(object_p,
UNWRAP_BOOL_ON, template));
case CKA_EXTRACTABLE:
return (get_bool_attr_from_object(object_p,
EXTRACTABLE_BOOL_ON, template));
case CKA_ALWAYS_SENSITIVE:
return (get_bool_attr_from_object(object_p,
ALWAYS_SENSITIVE_BOOL_ON, template));
case CKA_NEVER_EXTRACTABLE:
return (get_bool_attr_from_object(object_p,
NEVER_EXTRACTABLE_BOOL_ON, template));
case CKA_VALUE:
case CKA_VALUE_LEN:
/*
* If the specified attribute for the secret key object
* cannot be revealed because the object is sensitive
* or unextractable, then the ulValueLen is set to -1.
*/
if ((object_p->bool_attr_mask & SENSITIVE_BOOL_ON) ||
!(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) {
template->ulValueLen = (CK_ULONG)-1;
return (CKR_ATTRIBUTE_SENSITIVE);
}
switch (keytype) {
case CKK_RC4:
case CKK_GENERIC_SECRET:
case CKK_RC5:
case CKK_DES:
case CKK_DES2:
case CKK_DES3:
case CKK_CDMF:
case CKK_AES:
case CKK_BLOWFISH:
if (template->type == CKA_VALUE_LEN) {
return (get_ulong_attr_from_object(
OBJ_SEC_VALUE_LEN(object_p),
template));
} else {
return (get_bigint_attr_from_object(
(biginteger_t *)OBJ_SEC(object_p),
template));
}
default:
template->ulValueLen = (CK_ULONG)-1;
rv = CKR_ATTRIBUTE_TYPE_INVALID;
break;
}
break;
default:
/*
* First, get the value of the request attribute defined
* in the list of common key attributes. If the request
* attribute is not found in that list, then get the
* attribute from the list of common attributes.
*/
rv = soft_get_common_key_attrs(object_p, template);
if (rv == CKR_ATTRIBUTE_TYPE_INVALID) {
rv = soft_get_common_attrs(object_p, template,
object_p->object_type);
}
break;
}
return (rv);
}
/*
* Get the value of a requested attribute of a Domain Parameters Object.
*
* Rule: All the attributes in the domain parameters object can be revealed.
*/
CK_RV
soft_get_domain_parameters_attribute(soft_object_t *object_p,
CK_ATTRIBUTE_PTR template)
{
CK_RV rv = CKR_OK;
CK_KEY_TYPE keytype = object_p->key_type;
switch (template->type) {
case CKA_KEY_TYPE:
return (get_ulong_attr_from_object(keytype,
template));
case CKA_LOCAL:
return (get_bool_attr_from_object(object_p,
LOCAL_BOOL_ON, template));
case CKA_PRIME:
switch (keytype) {
case CKK_DSA:
return (get_bigint_attr_from_object(
OBJ_DOM_DSA_PRIME(object_p), template));
case CKK_DH:
return (get_bigint_attr_from_object(
OBJ_DOM_DH_PRIME(object_p), template));
case CKK_X9_42_DH:
return (get_bigint_attr_from_object(
OBJ_DOM_DH942_PRIME(object_p), template));
default:
template->ulValueLen = (CK_ULONG)-1;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
case CKA_SUBPRIME:
switch (keytype) {
case CKK_DSA:
return (get_bigint_attr_from_object(
OBJ_DOM_DSA_SUBPRIME(object_p), template));
case CKK_X9_42_DH:
return (get_bigint_attr_from_object(
OBJ_DOM_DH942_SUBPRIME(object_p), template));
default:
template->ulValueLen = (CK_ULONG)-1;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
case CKA_BASE:
switch (keytype) {
case CKK_DSA:
return (get_bigint_attr_from_object(
OBJ_DOM_DSA_BASE(object_p), template));
case CKK_DH:
return (get_bigint_attr_from_object(
OBJ_DOM_DH_BASE(object_p), template));
case CKK_X9_42_DH:
return (get_bigint_attr_from_object(
OBJ_DOM_DH942_BASE(object_p), template));
default:
template->ulValueLen = (CK_ULONG)-1;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
case CKA_PRIME_BITS:
switch (keytype) {
case CKK_DSA:
return (get_ulong_attr_from_object(
OBJ_DOM_DSA_PRIME_BITS(object_p), template));
case CKK_DH:
return (get_ulong_attr_from_object(
OBJ_DOM_DH_PRIME_BITS(object_p), template));
case CKK_X9_42_DH:
return (get_ulong_attr_from_object(
OBJ_DOM_DH942_PRIME_BITS(object_p), template));
default:
template->ulValueLen = (CK_ULONG)-1;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
case CKA_SUB_PRIME_BITS:
switch (keytype) {
case CKK_X9_42_DH:
return (get_ulong_attr_from_object(
OBJ_DOM_DH942_SUBPRIME_BITS(object_p), template));
default:
template->ulValueLen = (CK_ULONG)-1;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
default:
/*
* Get the value of a common attribute.
*/
rv = soft_get_common_attrs(object_p, template,
object_p->object_type);
break;
}
return (rv);
}
/*
* Get certificate attributes from an object.
* return CKR_ATTRIBUTE_TYPE_INVALID if the requested type
* does not exist in the certificate.
*/
CK_RV
soft_get_certificate_attribute(soft_object_t *object_p,
CK_ATTRIBUTE_PTR template)
{
CK_CERTIFICATE_TYPE certtype = object_p->cert_type;
cert_attr_t src;
switch (template->type) {
case CKA_SUBJECT:
if (certtype == CKC_X_509) {
return (get_cert_attr_from_object(
X509_CERT_SUBJECT(object_p), template));
}
break;
case CKA_VALUE:
if (certtype == CKC_X_509) {
return (get_cert_attr_from_object(
X509_CERT_VALUE(object_p), template));
} else if (certtype == CKC_X_509_ATTR_CERT) {
return (get_cert_attr_from_object(
X509_ATTR_CERT_VALUE(object_p), template));
}
break;
case CKA_OWNER:
if (certtype == CKC_X_509_ATTR_CERT) {
return (get_cert_attr_from_object(
X509_ATTR_CERT_OWNER(object_p), template));
}
break;
case CKA_CERTIFICATE_TYPE:
src.value = (CK_BYTE *)&certtype;
src.length = sizeof (certtype);
return (get_cert_attr_from_object(&src, template));
break;
case CKA_TRUSTED:
return (get_bool_attr_from_object(object_p,
TRUSTED_BOOL_ON, template));
case CKA_ID:
case CKA_ISSUER:
case CKA_SERIAL_NUMBER:
case CKA_AC_ISSUER:
case CKA_ATTR_TYPES:
return (get_extra_attr_from_object(object_p,
template));
break;
default:
return (soft_get_common_attrs(object_p, template,
object_p->object_type));
break;
}
/*
* If we got this far, then the combination of certificate type
* and requested attribute is invalid.
*/
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
CK_RV
soft_set_certificate_attribute(soft_object_t *object_p,
CK_ATTRIBUTE_PTR template, boolean_t copy)
{
CK_CERTIFICATE_TYPE certtype = object_p->cert_type;
switch (template->type) {
case CKA_SUBJECT:
if (certtype == CKC_X_509) {
/* SUBJECT attr cannot be modified. */
return (CKR_ATTRIBUTE_READ_ONLY);
}
break;
case CKA_OWNER:
if (certtype == CKC_X_509_ATTR_CERT) {
/* OWNER attr cannot be modified. */
return (CKR_ATTRIBUTE_READ_ONLY);
}
break;
case CKA_VALUE:
/* VALUE attr cannot be modified. */
return (CKR_ATTRIBUTE_READ_ONLY);
break;
case CKA_ID:
case CKA_ISSUER:
if (certtype == CKC_X_509) {
return (set_extra_attr_to_object(object_p,
template->type, template));
}
break;
case CKA_AC_ISSUER:
case CKA_ATTR_TYPES:
if (certtype == CKC_X_509_ATTR_CERT) {
return (set_extra_attr_to_object(object_p,
template->type, template));
}
break;
case CKA_SERIAL_NUMBER:
case CKA_LABEL:
return (set_extra_attr_to_object(object_p,
template->type, template));
break;
default:
return (soft_set_common_storage_attribute(
object_p, template, copy));
break;
}
/*
* If we got this far, then the combination of certificate type
* and requested attribute is invalid.
*/
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
/*
* Call the appropriate get attribute function according to the class
* of object.
*
* The caller of this function holds the lock on the object.
*/
CK_RV
soft_get_attribute(soft_object_t *object_p, CK_ATTRIBUTE_PTR template)
{
CK_RV rv = CKR_OK;
CK_OBJECT_CLASS class = object_p->class;
switch (class) {
case CKO_PUBLIC_KEY:
rv = soft_get_public_key_attribute(object_p, template);
break;
case CKO_PRIVATE_KEY:
rv = soft_get_private_key_attribute(object_p, template);
break;
case CKO_SECRET_KEY:
rv = soft_get_secret_key_attribute(object_p, template);
break;
case CKO_DOMAIN_PARAMETERS:
rv = soft_get_domain_parameters_attribute(object_p, template);
break;
case CKO_CERTIFICATE:
rv = soft_get_certificate_attribute(object_p, template);
break;
default:
/*
* If the specified attribute for the object is invalid
* (the object does not possess such as attribute), then
* the ulValueLen is modified to hold the value -1.
*/
template->ulValueLen = (CK_ULONG)-1;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
return (rv);
}
CK_RV
soft_set_common_storage_attribute(soft_object_t *object_p,
CK_ATTRIBUTE_PTR template, boolean_t copy)
{
CK_RV rv = CKR_OK;
switch (template->type) {
case CKA_TOKEN:
if (copy) {
if ((*(CK_BBOOL *)template->pValue) == B_TRUE) {
if (!soft_keystore_status(KEYSTORE_INITIALIZED))
return (CKR_DEVICE_REMOVED);
object_p->object_type |= TOKEN_OBJECT;
}
} else {
rv = CKR_ATTRIBUTE_READ_ONLY;
}
break;
case CKA_PRIVATE:
if (copy) {
if ((*(CK_BBOOL *)template->pValue) == B_TRUE) {
(void) pthread_mutex_lock(&soft_giant_mutex);
if (!soft_slot.authenticated) {
/*
* Check if this is the special case
* when the PIN is never initialized
* in the keystore. If true, we will
* let it pass here and let it fail
* with CKR_PIN_EXPIRED later on.
*/
if (!soft_slot.userpin_change_needed) {
(void) pthread_mutex_unlock(
&soft_giant_mutex);
return (CKR_USER_NOT_LOGGED_IN);
}
}
(void) pthread_mutex_unlock(&soft_giant_mutex);
object_p->object_type |= PRIVATE_OBJECT;
}
} else {
rv = CKR_ATTRIBUTE_READ_ONLY;
}
break;
case CKA_MODIFIABLE:
if (copy) {
if ((*(CK_BBOOL *)template->pValue) == TRUE)
object_p->bool_attr_mask &=
~NOT_MODIFIABLE_BOOL_ON;
else
object_p->bool_attr_mask |=
NOT_MODIFIABLE_BOOL_ON;
} else {
rv = CKR_ATTRIBUTE_READ_ONLY;
}
break;
case CKA_CLASS:
rv = CKR_ATTRIBUTE_READ_ONLY;
break;
default:
rv = CKR_TEMPLATE_INCONSISTENT;
}
return (rv);
}
/*
* Set the value of an attribute that is common to all key objects
* (i.e. public key, private key and secret key).
*/
CK_RV
soft_set_common_key_attribute(soft_object_t *object_p,
CK_ATTRIBUTE_PTR template, boolean_t copy)
{
switch (template->type) {
case CKA_LABEL:
/*
* Only the LABEL can be modified in the common storage
* object attributes after the object is created.
*/
return (set_extra_attr_to_object(object_p,
CKA_LABEL, template));
case CKA_ID:
return (set_extra_attr_to_object(object_p,
CKA_ID, template));
case CKA_START_DATE:
return (set_extra_attr_to_object(object_p,
CKA_START_DATE, template));
case CKA_END_DATE:
return (set_extra_attr_to_object(object_p,
CKA_END_DATE, template));
case CKA_DERIVE:
return (set_bool_attr_to_object(object_p,
DERIVE_BOOL_ON, template));
case CKA_KEY_TYPE:
case CKA_LOCAL:
case CKA_KEY_GEN_MECHANISM:
return (CKR_ATTRIBUTE_READ_ONLY);
default:
return (soft_set_common_storage_attribute(object_p,
template, copy));
}
}
/*
* Set the value of an attribute of a Public Key Object.
*
* Rule: The attributes marked with footnote number "8" in the PKCS11
* spec may be modified (p.88 in PKCS11 spec.).
*/
CK_RV
soft_set_public_key_attribute(soft_object_t *object_p,
CK_ATTRIBUTE_PTR template, boolean_t copy)
{
CK_KEY_TYPE keytype = object_p->key_type;
switch (template->type) {
case CKA_SUBJECT:
return (set_extra_attr_to_object(object_p,
CKA_SUBJECT, template));
case CKA_ENCRYPT:
return (set_bool_attr_to_object(object_p,
ENCRYPT_BOOL_ON, template));
case CKA_VERIFY:
return (set_bool_attr_to_object(object_p,
VERIFY_BOOL_ON, template));
case CKA_VERIFY_RECOVER:
return (set_bool_attr_to_object(object_p,
VERIFY_RECOVER_BOOL_ON, template));
case CKA_WRAP:
return (set_bool_attr_to_object(object_p,
WRAP_BOOL_ON, template));
case CKA_MODULUS:
case CKA_MODULUS_BITS:
case CKA_PUBLIC_EXPONENT:
if (keytype == CKK_RSA)
return (CKR_ATTRIBUTE_READ_ONLY);
break;
case CKA_SUBPRIME:
if ((keytype == CKK_DSA) ||
(keytype == CKK_X9_42_DH))
return (CKR_ATTRIBUTE_READ_ONLY);
break;
case CKA_PRIME:
case CKA_BASE:
case CKA_VALUE:
if ((keytype == CKK_DSA) ||
(keytype == CKK_DH) ||
(keytype == CKK_X9_42_DH))
return (CKR_ATTRIBUTE_READ_ONLY);
break;
default:
/*
* Set the value of a common key attribute.
*/
return (soft_set_common_key_attribute(object_p,
template, copy));
}
/*
* If we got this far, then the combination of key type
* and requested attribute is invalid.
*/
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
/*
* Set the value of an attribute of a Private Key Object.
*
* Rule: The attributes marked with footnote number "8" in the PKCS11
* spec may be modified (p.88 in PKCS11 spec.).
*/
CK_RV
soft_set_private_key_attribute(soft_object_t *object_p,
CK_ATTRIBUTE_PTR template, boolean_t copy)
{
CK_KEY_TYPE keytype = object_p->key_type;
switch (template->type) {
case CKA_SUBJECT:
return (set_extra_attr_to_object(object_p,
CKA_SUBJECT, template));
case CKA_SENSITIVE:
/*
* Cannot set SENSITIVE to FALSE if it is already ON.
*/
if (((*(CK_BBOOL *)template->pValue) == B_FALSE) &&
(object_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
return (CKR_ATTRIBUTE_READ_ONLY);
}
if (*(CK_BBOOL *)template->pValue)
object_p->bool_attr_mask |= SENSITIVE_BOOL_ON;
return (CKR_OK);
case CKA_DECRYPT:
return (set_bool_attr_to_object(object_p,
DECRYPT_BOOL_ON, template));
case CKA_SIGN:
return (set_bool_attr_to_object(object_p,
SIGN_BOOL_ON, template));
case CKA_SIGN_RECOVER:
return (set_bool_attr_to_object(object_p,
SIGN_RECOVER_BOOL_ON, template));
case CKA_UNWRAP:
return (set_bool_attr_to_object(object_p,
UNWRAP_BOOL_ON, template));
case CKA_EXTRACTABLE:
/*
* Cannot set EXTRACTABLE to TRUE if it is already OFF.
*/
if ((*(CK_BBOOL *)template->pValue) &&
!(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) {
return (CKR_ATTRIBUTE_READ_ONLY);
}
if ((*(CK_BBOOL *)template->pValue) == B_FALSE)
object_p->bool_attr_mask &= ~EXTRACTABLE_BOOL_ON;
return (CKR_OK);
case CKA_MODULUS:
case CKA_PUBLIC_EXPONENT:
case CKA_PRIVATE_EXPONENT:
case CKA_PRIME_1:
case CKA_PRIME_2:
case CKA_EXPONENT_1:
case CKA_EXPONENT_2:
case CKA_COEFFICIENT:
if (keytype == CKK_RSA) {
return (CKR_ATTRIBUTE_READ_ONLY);
}
break;
case CKA_SUBPRIME:
if ((keytype == CKK_DSA) ||
(keytype == CKK_X9_42_DH))
return (CKR_ATTRIBUTE_READ_ONLY);
break;
case CKA_PRIME:
case CKA_BASE:
case CKA_VALUE:
if ((keytype == CKK_DSA) ||
(keytype == CKK_DH) ||
(keytype == CKK_X9_42_DH))
return (CKR_ATTRIBUTE_READ_ONLY);
break;
case CKA_VALUE_BITS:
if (keytype == CKK_DH)
return (CKR_ATTRIBUTE_READ_ONLY);
break;
default:
/*
* Set the value of a common key attribute.
*/
return (soft_set_common_key_attribute(object_p,
template, copy));
}
/*
* If we got this far, then the combination of key type
* and requested attribute is invalid.
*/
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
/*
* Set the value of an attribute of a Secret Key Object.
*
* Rule: The attributes marked with footnote number "8" in the PKCS11
* spec may be modified (p.88 in PKCS11 spec.).
*/
CK_RV
soft_set_secret_key_attribute(soft_object_t *object_p,
CK_ATTRIBUTE_PTR template, boolean_t copy)
{
CK_KEY_TYPE keytype = object_p->key_type;
switch (template->type) {
case CKA_SENSITIVE:
/*
* Cannot set SENSITIVE to FALSE if it is already ON.
*/
if (((*(CK_BBOOL *)template->pValue) == B_FALSE) &&
(object_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
return (CKR_ATTRIBUTE_READ_ONLY);
}
if (*(CK_BBOOL *)template->pValue)
object_p->bool_attr_mask |= SENSITIVE_BOOL_ON;
return (CKR_OK);
case CKA_ENCRYPT:
return (set_bool_attr_to_object(object_p,
ENCRYPT_BOOL_ON, template));
case CKA_DECRYPT:
return (set_bool_attr_to_object(object_p,
DECRYPT_BOOL_ON, template));
case CKA_SIGN:
return (set_bool_attr_to_object(object_p,
SIGN_BOOL_ON, template));
case CKA_VERIFY:
return (set_bool_attr_to_object(object_p,
VERIFY_BOOL_ON, template));
case CKA_WRAP:
return (set_bool_attr_to_object(object_p,
WRAP_BOOL_ON, template));
case CKA_UNWRAP:
return (set_bool_attr_to_object(object_p,
UNWRAP_BOOL_ON, template));
case CKA_EXTRACTABLE:
/*
* Cannot set EXTRACTABLE to TRUE if it is already OFF.
*/
if ((*(CK_BBOOL *)template->pValue) &&
!(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) {
return (CKR_ATTRIBUTE_READ_ONLY);
}
if ((*(CK_BBOOL *)template->pValue) == B_FALSE)
object_p->bool_attr_mask &= ~EXTRACTABLE_BOOL_ON;
return (CKR_OK);
case CKA_VALUE:
return (CKR_ATTRIBUTE_READ_ONLY);
case CKA_VALUE_LEN:
if ((keytype == CKK_RC4) ||
(keytype == CKK_GENERIC_SECRET) ||
(keytype == CKK_AES) ||
(keytype == CKK_BLOWFISH))
return (CKR_ATTRIBUTE_READ_ONLY);
break;
default:
/*
* Set the value of a common key attribute.
*/
return (soft_set_common_key_attribute(object_p,
template, copy));
}
/*
* If we got this far, then the combination of key type
* and requested attribute is invalid.
*/
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
/*
* Call the appropriate set attribute function according to the class
* of object.
*
* The caller of this function does not hold the lock on the original
* object, since this function is setting the attribute on the new object
* that is being modified.
*
* Argument copy: TRUE when called by C_CopyObject,
* FALSE when called by C_SetAttributeValue.
*/
CK_RV
soft_set_attribute(soft_object_t *object_p, CK_ATTRIBUTE_PTR template,
boolean_t copy)
{
CK_RV rv = CKR_OK;
CK_OBJECT_CLASS class = object_p->class;
switch (class) {
case CKO_PUBLIC_KEY:
rv = soft_set_public_key_attribute(object_p, template, copy);
break;
case CKO_PRIVATE_KEY:
rv = soft_set_private_key_attribute(object_p, template, copy);
break;
case CKO_SECRET_KEY:
rv = soft_set_secret_key_attribute(object_p, template, copy);
break;
case CKO_DOMAIN_PARAMETERS:
switch (template->type) {
case CKA_LABEL:
/*
* Only the LABEL can be modified in the common
* storage object attributes after the object is
* created.
*/
return (set_extra_attr_to_object(object_p,
CKA_LABEL, template));
default:
return (CKR_TEMPLATE_INCONSISTENT);
}
case CKO_CERTIFICATE:
rv = soft_set_certificate_attribute(object_p, template, copy);
break;
default:
/*
* If the template specifies a value of an attribute
* which is incompatible with other existing attributes
* of the object, then fails with return code
* CKR_TEMPLATE_INCONSISTENT.
*/
rv = CKR_TEMPLATE_INCONSISTENT;
break;
}
return (rv);
}
CK_RV
soft_get_public_attr(soft_object_t *key, CK_ATTRIBUTE_TYPE type,
uchar_t *value, uint32_t *value_len)
{
uint32_t len = 0;
switch (type) {
/* The following attributes belong to RSA */
case CKA_MODULUS:
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PUB_RSA_MOD(key))->big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PUB_RSA_MOD(key))->big_value_len;
#endif /* __sparcv9 */
/* This attribute MUST BE set */
if (len == 0 || len > *value_len) {
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
*value_len = len;
(void) memcpy(value,
((biginteger_t *)OBJ_PUB_RSA_MOD(key))->big_value,
*value_len);
break;
case CKA_PUBLIC_EXPONENT:
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PUB_RSA_PUBEXPO(key))->big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PUB_RSA_PUBEXPO(key))->big_value_len;
#endif /* __sparcv9 */
/* This attribute MUST BE set */
if (len == 0 || len > *value_len) {
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
*value_len = len;
(void) memcpy(value,
((biginteger_t *)OBJ_PUB_RSA_PUBEXPO(key))->big_value,
*value_len);
break;
/* The following attributes belong to DSA and DH */
case CKA_PRIME:
if (key->key_type == CKK_DSA)
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PUB_DSA_PRIME(key))->
big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PUB_DSA_PRIME(key))->
big_value_len;
#endif /* __sparcv9 */
else
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PUB_DH_PRIME(key))->
big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PUB_DH_PRIME(key))->
big_value_len;
#endif /* __sparcv9 */
/* This attribute MUST BE set */
if (len == 0 || len > *value_len) {
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
*value_len = len;
if (key->key_type == CKK_DSA)
(void) memcpy(value,
((biginteger_t *)OBJ_PUB_DSA_PRIME(key))->big_value,
*value_len);
else
(void) memcpy(value,
((biginteger_t *)OBJ_PUB_DH_PRIME(key))->big_value,
*value_len);
break;
case CKA_SUBPRIME:
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PUB_DSA_SUBPRIME(key))->big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PUB_DSA_SUBPRIME(key))->big_value_len;
#endif /* __sparcv9 */
/* This attribute MUST BE set */
if (len == 0 || len > *value_len) {
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
*value_len = len;
(void) memcpy(value,
((biginteger_t *)OBJ_PUB_DSA_SUBPRIME(key))->big_value,
*value_len);
break;
case CKA_BASE:
if (key->key_type == CKK_DSA)
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PUB_DSA_BASE(key))->
big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PUB_DSA_BASE(key))->
big_value_len;
#endif /* __sparcv9 */
else
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PUB_DH_BASE(key))->
big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PUB_DH_BASE(key))->
big_value_len;
#endif /* __sparcv9 */
/* This attribute MUST BE set */
if (len == 0 || len > *value_len) {
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
*value_len = len;
if (key->key_type == CKK_DSA)
(void) memcpy(value,
((biginteger_t *)OBJ_PUB_DSA_BASE(key))->big_value,
*value_len);
else
(void) memcpy(value,
((biginteger_t *)OBJ_PUB_DH_BASE(key))->big_value,
*value_len);
break;
case CKA_VALUE:
if (key->key_type == CKK_DSA)
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PUB_DSA_VALUE(key))->
big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PUB_DSA_VALUE(key))->
big_value_len;
#endif /* __sparcv9 */
else
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PUB_DH_VALUE(key))->
big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PUB_DH_VALUE(key))->
big_value_len;
#endif /* __sparcv9 */
/* This attribute MUST BE set */
if (len == 0 || len > *value_len) {
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
*value_len = len;
if (key->key_type == CKK_DSA)
(void) memcpy(value,
((biginteger_t *)OBJ_PUB_DSA_VALUE(key))->big_value,
*value_len);
else
(void) memcpy(value,
((biginteger_t *)OBJ_PUB_DH_VALUE(key))->big_value,
*value_len);
break;
}
return (CKR_OK);
}
CK_RV
soft_get_private_attr(soft_object_t *key, CK_ATTRIBUTE_TYPE type,
uchar_t *value, uint32_t *value_len)
{
uint32_t len = 0;
switch (type) {
/* The following attributes belong to RSA */
case CKA_MODULUS:
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PRI_RSA_MOD(key))->big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PRI_RSA_MOD(key))->big_value_len;
#endif /* __sparcv9 */
/* This attribute MUST BE set */
if (len == 0 || len > *value_len) {
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
*value_len = len;
(void) memcpy(value,
((biginteger_t *)OBJ_PRI_RSA_MOD(key))->big_value,
*value_len);
break;
case CKA_PRIVATE_EXPONENT:
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PRI_RSA_PRIEXPO(key))->big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PRI_RSA_PRIEXPO(key))->big_value_len;
#endif /* __sparcv9 */
/* This attribute MUST BE set */
if (len == 0 || len > *value_len) {
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
*value_len = len;
(void) memcpy(value,
((biginteger_t *)OBJ_PRI_RSA_PRIEXPO(key))->big_value,
*value_len);
break;
case CKA_PRIME_1:
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PRI_RSA_PRIME1(key))->big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PRI_RSA_PRIME1(key))->big_value_len;
#endif /* __sparcv9 */
if (len > *value_len) {
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
*value_len = len;
if (*value_len == 0) {
return (CKR_OK);
}
(void) memcpy(value,
((biginteger_t *)OBJ_PRI_RSA_PRIME1(key))->big_value,
*value_len);
break;
case CKA_PRIME_2:
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PRI_RSA_PRIME2(key))->big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PRI_RSA_PRIME2(key))->big_value_len;
#endif /* __sparcv9 */
if (len > *value_len) {
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
*value_len = len;
if (*value_len == 0) {
return (CKR_OK);
}
(void) memcpy(value,
((biginteger_t *)OBJ_PRI_RSA_PRIME2(key))->big_value,
*value_len);
break;
case CKA_EXPONENT_1:
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PRI_RSA_EXPO1(key))->big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PRI_RSA_EXPO1(key))->big_value_len;
#endif /* __sparcv9 */
if (len > *value_len) {
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
*value_len = len;
if (*value_len == 0) {
return (CKR_OK);
}
(void) memcpy(value,
((biginteger_t *)OBJ_PRI_RSA_EXPO1(key))->big_value,
*value_len);
break;
case CKA_EXPONENT_2:
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PRI_RSA_EXPO2(key))->big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PRI_RSA_EXPO2(key))->big_value_len;
#endif /* __sparcv9 */
if (len > *value_len) {
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
*value_len = len;
if (*value_len == 0) {
return (CKR_OK);
}
(void) memcpy(value,
((biginteger_t *)OBJ_PRI_RSA_EXPO2(key))->big_value,
*value_len);
break;
case CKA_COEFFICIENT:
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PRI_RSA_COEF(key))->big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PRI_RSA_COEF(key))->big_value_len;
#endif /* __sparcv9 */
if (len > *value_len) {
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
*value_len = len;
if (*value_len == 0) {
return (CKR_OK);
}
(void) memcpy(value,
((biginteger_t *)OBJ_PRI_RSA_COEF(key))->big_value,
*value_len);
break;
/* The following attributes belong to DSA and DH */
case CKA_PRIME:
if (key->key_type == CKK_DSA)
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PRI_DSA_PRIME(key))->
big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PRI_DSA_PRIME(key))->
big_value_len;
#endif /* __sparcv9 */
else
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PRI_DH_PRIME(key))->
big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PRI_DH_PRIME(key))->
big_value_len;
#endif /* __sparcv9 */
/* This attribute MUST BE set */
if (len == 0 || len > *value_len) {
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
*value_len = len;
if (key->key_type == CKK_DSA)
(void) memcpy(value,
((biginteger_t *)OBJ_PRI_DSA_PRIME(key))->big_value,
*value_len);
else
(void) memcpy(value,
((biginteger_t *)OBJ_PRI_DH_PRIME(key))->big_value,
*value_len);
break;
case CKA_SUBPRIME:
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PRI_DSA_SUBPRIME(key))->big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PRI_DSA_SUBPRIME(key))->big_value_len;
#endif /* __sparcv9 */
/* This attribute MUST BE set */
if (len == 0 || len > *value_len) {
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
*value_len = len;
(void) memcpy(value,
((biginteger_t *)OBJ_PRI_DSA_SUBPRIME(key))->big_value,
*value_len);
break;
case CKA_BASE:
if (key->key_type == CKK_DSA)
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PRI_DSA_BASE(key))->
big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PRI_DSA_BASE(key))->
big_value_len;
#endif /* __sparcv9 */
else
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PRI_DH_BASE(key))->
big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PRI_DH_BASE(key))->
big_value_len;
#endif /* __sparcv9 */
/* This attribute MUST BE set */
if (len == 0 || len > *value_len) {
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
*value_len = len;
if (key->key_type == CKK_DSA)
(void) memcpy(value,
((biginteger_t *)OBJ_PRI_DSA_BASE(key))->big_value,
*value_len);
else
(void) memcpy(value,
((biginteger_t *)OBJ_PRI_DH_BASE(key))->big_value,
*value_len);
break;
case CKA_VALUE:
if (key->key_type == CKK_DSA)
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PRI_DSA_VALUE(key))->
big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PRI_DSA_VALUE(key))->
big_value_len;
#endif /* __sparcv9 */
else
#ifdef __sparcv9
len =
/* LINTED */
(uint32_t)
((biginteger_t *)OBJ_PRI_DH_VALUE(key))->
big_value_len;
#else /* !__sparcv9 */
len =
((biginteger_t *)OBJ_PRI_DH_VALUE(key))->
big_value_len;
#endif /* __sparcv9 */
/* This attribute MUST BE set */
if (len == 0 || len > *value_len) {
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
*value_len = len;
if (key->key_type == CKK_DSA)
(void) memcpy(value,
((biginteger_t *)OBJ_PRI_DSA_VALUE(key))->big_value,
*value_len);
else
(void) memcpy(value,
((biginteger_t *)OBJ_PRI_DH_VALUE(key))->big_value,
*value_len);
break;
}
return (CKR_OK);
}
static CK_RV
copy_bigint(biginteger_t *new_bigint, biginteger_t *old_bigint)
{
new_bigint->big_value =
malloc((sizeof (CK_BYTE) * new_bigint->big_value_len));
if (new_bigint->big_value == NULL) {
return (CKR_HOST_MEMORY);
}
(void) memcpy(new_bigint->big_value, old_bigint->big_value,
(sizeof (CK_BYTE) * new_bigint->big_value_len));
return (CKR_OK);
}
static void
free_public_key_attr(public_key_obj_t *pbk, CK_KEY_TYPE key_type)
{
if (pbk == NULL) {
return;
}
switch (key_type) {
case CKK_RSA:
bigint_attr_cleanup(KEY_PUB_RSA_MOD(pbk));
bigint_attr_cleanup(KEY_PUB_RSA_PUBEXPO(pbk));
break;
case CKK_DSA:
bigint_attr_cleanup(KEY_PUB_DSA_PRIME(pbk));
bigint_attr_cleanup(KEY_PUB_DSA_SUBPRIME(pbk));
bigint_attr_cleanup(KEY_PUB_DSA_BASE(pbk));
bigint_attr_cleanup(KEY_PUB_DSA_VALUE(pbk));
break;
case CKK_DH:
bigint_attr_cleanup(KEY_PUB_DH_PRIME(pbk));
bigint_attr_cleanup(KEY_PUB_DH_BASE(pbk));
bigint_attr_cleanup(KEY_PUB_DH_VALUE(pbk));
break;
case CKK_EC:
bigint_attr_cleanup(KEY_PUB_EC_POINT(pbk));
break;
case CKK_X9_42_DH:
bigint_attr_cleanup(KEY_PUB_DH942_PRIME(pbk));
bigint_attr_cleanup(KEY_PUB_DH942_SUBPRIME(pbk));
bigint_attr_cleanup(KEY_PUB_DH942_BASE(pbk));
bigint_attr_cleanup(KEY_PUB_DH942_VALUE(pbk));
break;
default:
break;
}
free(pbk);
}
CK_RV
soft_copy_public_key_attr(public_key_obj_t *old_pub_key_obj_p,
public_key_obj_t **new_pub_key_obj_p, CK_KEY_TYPE key_type)
{
public_key_obj_t *pbk;
CK_RV rv = CKR_OK;
pbk = calloc(1, sizeof (public_key_obj_t));
if (pbk == NULL) {
return (CKR_HOST_MEMORY);
}
switch (key_type) {
case CKK_RSA:
(void) memcpy(KEY_PUB_RSA(pbk),
KEY_PUB_RSA(old_pub_key_obj_p),
sizeof (rsa_pub_key_t));
/* copy modulus */
rv = copy_bigint(KEY_PUB_RSA_MOD(pbk),
KEY_PUB_RSA_MOD(old_pub_key_obj_p));
if (rv != CKR_OK) {
free_public_key_attr(pbk, key_type);
return (rv);
}
/* copy public exponent */
rv = copy_bigint(KEY_PUB_RSA_PUBEXPO(pbk),
KEY_PUB_RSA_PUBEXPO(old_pub_key_obj_p));
if (rv != CKR_OK) {
free_public_key_attr(pbk, key_type);
return (rv);
}
break;
case CKK_DSA:
(void) memcpy(KEY_PUB_DSA(pbk),
KEY_PUB_DSA(old_pub_key_obj_p),
sizeof (dsa_pub_key_t));
/* copy prime */
rv = copy_bigint(KEY_PUB_DSA_PRIME(pbk),
KEY_PUB_DSA_PRIME(old_pub_key_obj_p));
if (rv != CKR_OK) {
free_public_key_attr(pbk, key_type);
return (rv);
}
/* copy subprime */
rv = copy_bigint(KEY_PUB_DSA_SUBPRIME(pbk),
KEY_PUB_DSA_SUBPRIME(old_pub_key_obj_p));
if (rv != CKR_OK) {
free_public_key_attr(pbk, key_type);
return (rv);
}
/* copy base */
rv = copy_bigint(KEY_PUB_DSA_BASE(pbk),
KEY_PUB_DSA_BASE(old_pub_key_obj_p));
if (rv != CKR_OK) {
free_public_key_attr(pbk, key_type);
return (rv);
}
/* copy value */
rv = copy_bigint(KEY_PUB_DSA_VALUE(pbk),
KEY_PUB_DSA_VALUE(old_pub_key_obj_p));
if (rv != CKR_OK) {
free_public_key_attr(pbk, key_type);
return (rv);
}
break;
case CKK_DH:
(void) memcpy(KEY_PUB_DH(pbk),
KEY_PUB_DH(old_pub_key_obj_p),
sizeof (dh_pub_key_t));
/* copy prime */
rv = copy_bigint(KEY_PUB_DH_PRIME(pbk),
KEY_PUB_DH_PRIME(old_pub_key_obj_p));
if (rv != CKR_OK) {
free_public_key_attr(pbk, key_type);
return (rv);
}
/* copy base */
rv = copy_bigint(KEY_PUB_DH_BASE(pbk),
KEY_PUB_DH_BASE(old_pub_key_obj_p));
if (rv != CKR_OK) {
free_public_key_attr(pbk, key_type);
return (rv);
}
/* copy value */
rv = copy_bigint(KEY_PUB_DH_VALUE(pbk),
KEY_PUB_DH_VALUE(old_pub_key_obj_p));
if (rv != CKR_OK) {
free_public_key_attr(pbk, key_type);
return (rv);
}
break;
case CKK_EC:
(void) memcpy(KEY_PUB_EC(pbk),
KEY_PUB_EC(old_pub_key_obj_p),
sizeof (ec_pub_key_t));
/* copy point */
rv = copy_bigint(KEY_PUB_EC_POINT(pbk),
KEY_PUB_EC_POINT(old_pub_key_obj_p));
if (rv != CKR_OK) {
free_public_key_attr(pbk, key_type);
return (rv);
}
break;
case CKK_X9_42_DH:
(void) memcpy(KEY_PUB_DH942(pbk),
KEY_PUB_DH942(old_pub_key_obj_p),
sizeof (dh942_pub_key_t));
/* copy prime */
rv = copy_bigint(KEY_PUB_DH942_PRIME(pbk),
KEY_PUB_DH942_PRIME(old_pub_key_obj_p));
if (rv != CKR_OK) {
free_public_key_attr(pbk, key_type);
return (rv);
}
/* copy subprime */
rv = copy_bigint(KEY_PUB_DH942_SUBPRIME(pbk),
KEY_PUB_DH942_SUBPRIME(old_pub_key_obj_p));
if (rv != CKR_OK) {
free_public_key_attr(pbk, key_type);
return (rv);
}
/* copy base */
rv = copy_bigint(KEY_PUB_DH942_BASE(pbk),
KEY_PUB_DH942_BASE(old_pub_key_obj_p));
if (rv != CKR_OK) {
free_public_key_attr(pbk, key_type);
return (rv);
}
/* copy value */
rv = copy_bigint(KEY_PUB_DH942_VALUE(pbk),
KEY_PUB_DH942_VALUE(old_pub_key_obj_p));
if (rv != CKR_OK) {
free_public_key_attr(pbk, key_type);
return (rv);
}
break;
default:
break;
}
*new_pub_key_obj_p = pbk;
return (rv);
}
static void
free_private_key_attr(private_key_obj_t *pbk, CK_KEY_TYPE key_type)
{
if (pbk == NULL) {
return;
}
switch (key_type) {
case CKK_RSA:
bigint_attr_cleanup(KEY_PRI_RSA_MOD(pbk));
bigint_attr_cleanup(KEY_PRI_RSA_PUBEXPO(pbk));
bigint_attr_cleanup(KEY_PRI_RSA_PRIEXPO(pbk));
bigint_attr_cleanup(KEY_PRI_RSA_PRIME1(pbk));
bigint_attr_cleanup(KEY_PRI_RSA_PRIME2(pbk));
bigint_attr_cleanup(KEY_PRI_RSA_EXPO1(pbk));
bigint_attr_cleanup(KEY_PRI_RSA_EXPO2(pbk));
bigint_attr_cleanup(KEY_PRI_RSA_COEF(pbk));
break;
case CKK_DSA:
bigint_attr_cleanup(KEY_PRI_DSA_PRIME(pbk));
bigint_attr_cleanup(KEY_PRI_DSA_SUBPRIME(pbk));
bigint_attr_cleanup(KEY_PRI_DSA_BASE(pbk));
bigint_attr_cleanup(KEY_PRI_DSA_VALUE(pbk));
break;
case CKK_DH:
bigint_attr_cleanup(KEY_PRI_DH_PRIME(pbk));
bigint_attr_cleanup(KEY_PRI_DH_BASE(pbk));
bigint_attr_cleanup(KEY_PRI_DH_VALUE(pbk));
break;
case CKK_EC:
bigint_attr_cleanup(KEY_PRI_EC_VALUE(pbk));
break;
case CKK_X9_42_DH:
bigint_attr_cleanup(KEY_PRI_DH942_PRIME(pbk));
bigint_attr_cleanup(KEY_PRI_DH942_SUBPRIME(pbk));
bigint_attr_cleanup(KEY_PRI_DH942_BASE(pbk));
bigint_attr_cleanup(KEY_PRI_DH942_VALUE(pbk));
break;
default:
break;
}
free(pbk);
}
CK_RV
soft_copy_private_key_attr(private_key_obj_t *old_pri_key_obj_p,
private_key_obj_t **new_pri_key_obj_p, CK_KEY_TYPE key_type)
{
CK_RV rv = CKR_OK;
private_key_obj_t *pbk;
pbk = calloc(1, sizeof (private_key_obj_t));
if (pbk == NULL) {
return (CKR_HOST_MEMORY);
}
switch (key_type) {
case CKK_RSA:
(void) memcpy(KEY_PRI_RSA(pbk),
KEY_PRI_RSA(old_pri_key_obj_p),
sizeof (rsa_pri_key_t));
/* copy modulus */
rv = copy_bigint(KEY_PRI_RSA_MOD(pbk),
KEY_PRI_RSA_MOD(old_pri_key_obj_p));
if (rv != CKR_OK) {
free_private_key_attr(pbk, key_type);
return (rv);
}
/* copy public exponent */
rv = copy_bigint(KEY_PRI_RSA_PUBEXPO(pbk),
KEY_PRI_RSA_PUBEXPO(old_pri_key_obj_p));
if (rv != CKR_OK) {
free_private_key_attr(pbk, key_type);
return (rv);
}
/* copy private exponent */
rv = copy_bigint(KEY_PRI_RSA_PRIEXPO(pbk),
KEY_PRI_RSA_PRIEXPO(old_pri_key_obj_p));
if (rv != CKR_OK) {
free_private_key_attr(pbk, key_type);
return (rv);
}
/* copy prime_1 */
rv = copy_bigint(KEY_PRI_RSA_PRIME1(pbk),
KEY_PRI_RSA_PRIME1(old_pri_key_obj_p));
if (rv != CKR_OK) {
free_private_key_attr(pbk, key_type);
return (rv);
}
/* copy prime_2 */
rv = copy_bigint(KEY_PRI_RSA_PRIME2(pbk),
KEY_PRI_RSA_PRIME2(old_pri_key_obj_p));
if (rv != CKR_OK) {
free_private_key_attr(pbk, key_type);
return (rv);
}
/* copy exponent_1 */
rv = copy_bigint(KEY_PRI_RSA_EXPO1(pbk),
KEY_PRI_RSA_EXPO1(old_pri_key_obj_p));
if (rv != CKR_OK) {
free_private_key_attr(pbk, key_type);
return (rv);
}
/* copy exponent_2 */
rv = copy_bigint(KEY_PRI_RSA_EXPO2(pbk),
KEY_PRI_RSA_EXPO2(old_pri_key_obj_p));
if (rv != CKR_OK) {
free_private_key_attr(pbk, key_type);
return (rv);
}
/* copy coefficient */
rv = copy_bigint(KEY_PRI_RSA_COEF(pbk),
KEY_PRI_RSA_COEF(old_pri_key_obj_p));
if (rv != CKR_OK) {
free_private_key_attr(pbk, key_type);
return (rv);
}
break;
case CKK_DSA:
(void) memcpy(KEY_PRI_DSA(pbk),
KEY_PRI_DSA(old_pri_key_obj_p),
sizeof (dsa_pri_key_t));
/* copy prime */
rv = copy_bigint(KEY_PRI_DSA_PRIME(pbk),
KEY_PRI_DSA_PRIME(old_pri_key_obj_p));
if (rv != CKR_OK) {
free_private_key_attr(pbk, key_type);
return (rv);
}
/* copy subprime */
rv = copy_bigint(KEY_PRI_DSA_SUBPRIME(pbk),
KEY_PRI_DSA_SUBPRIME(old_pri_key_obj_p));
if (rv != CKR_OK) {
free_private_key_attr(pbk, key_type);
return (rv);
}
/* copy base */
rv = copy_bigint(KEY_PRI_DSA_BASE(pbk),
KEY_PRI_DSA_BASE(old_pri_key_obj_p));
if (rv != CKR_OK) {
free_private_key_attr(pbk, key_type);
return (rv);
}
/* copy value */
rv = copy_bigint(KEY_PRI_DSA_VALUE(pbk),
KEY_PRI_DSA_VALUE(old_pri_key_obj_p));
if (rv != CKR_OK) {
free_private_key_attr(pbk, key_type);
return (rv);
}
break;
case CKK_DH:
(void) memcpy(KEY_PRI_DH(pbk),
KEY_PRI_DH(old_pri_key_obj_p),
sizeof (dh_pri_key_t));
/* copy prime */
rv = copy_bigint(KEY_PRI_DH_PRIME(pbk),
KEY_PRI_DH_PRIME(old_pri_key_obj_p));
if (rv != CKR_OK) {
free_private_key_attr(pbk, key_type);
return (rv);
}
/* copy base */
rv = copy_bigint(KEY_PRI_DH_BASE(pbk),
KEY_PRI_DH_BASE(old_pri_key_obj_p));
if (rv != CKR_OK) {
free_private_key_attr(pbk, key_type);
return (rv);
}
/* copy value */
rv = copy_bigint(KEY_PRI_DH_VALUE(pbk),
KEY_PRI_DH_VALUE(old_pri_key_obj_p));
if (rv != CKR_OK) {
free_private_key_attr(pbk, key_type);
return (rv);
}
break;
case CKK_EC:
(void) memcpy(KEY_PRI_EC(pbk),
KEY_PRI_EC(old_pri_key_obj_p),
sizeof (ec_pri_key_t));
/* copy value */
rv = copy_bigint(KEY_PRI_EC_VALUE(pbk),
KEY_PRI_EC_VALUE(old_pri_key_obj_p));
if (rv != CKR_OK) {
free_private_key_attr(pbk, key_type);
return (rv);
}
break;
case CKK_X9_42_DH:
(void) memcpy(KEY_PRI_DH942(pbk),
KEY_PRI_DH942(old_pri_key_obj_p),
sizeof (dh942_pri_key_t));
/* copy prime */
rv = copy_bigint(KEY_PRI_DH942_PRIME(pbk),
KEY_PRI_DH942_PRIME(old_pri_key_obj_p));
if (rv != CKR_OK) {
free_private_key_attr(pbk, key_type);
return (rv);
}
/* copy subprime */
rv = copy_bigint(KEY_PRI_DH942_SUBPRIME(pbk),
KEY_PRI_DH942_SUBPRIME(old_pri_key_obj_p));
if (rv != CKR_OK) {
free_private_key_attr(pbk, key_type);
return (rv);
}
/* copy base */
rv = copy_bigint(KEY_PRI_DH942_BASE(pbk),
KEY_PRI_DH942_BASE(old_pri_key_obj_p));
if (rv != CKR_OK) {
free_private_key_attr(pbk, key_type);
return (rv);
}
/* copy value */
rv = copy_bigint(KEY_PRI_DH942_VALUE(pbk),
KEY_PRI_DH942_VALUE(old_pri_key_obj_p));
if (rv != CKR_OK) {
free_private_key_attr(pbk, key_type);
return (rv);
}
break;
default:
break;
}
*new_pri_key_obj_p = pbk;
return (rv);
}
static void
free_domain_attr(domain_obj_t *domain, CK_KEY_TYPE key_type)
{
if (domain == NULL) {
return;
}
switch (key_type) {
case CKK_DSA:
bigint_attr_cleanup(KEY_DOM_DSA_PRIME(domain));
bigint_attr_cleanup(KEY_DOM_DSA_SUBPRIME(domain));
bigint_attr_cleanup(KEY_DOM_DSA_BASE(domain));
break;
case CKK_DH:
bigint_attr_cleanup(KEY_DOM_DH_PRIME(domain));
bigint_attr_cleanup(KEY_DOM_DH_BASE(domain));
break;
case CKK_X9_42_DH:
bigint_attr_cleanup(KEY_DOM_DH942_PRIME(domain));
bigint_attr_cleanup(KEY_DOM_DH942_SUBPRIME(domain));
bigint_attr_cleanup(KEY_DOM_DH942_BASE(domain));
break;
default:
break;
}
free(domain);
}
CK_RV
soft_copy_domain_attr(domain_obj_t *old_domain_obj_p,
domain_obj_t **new_domain_obj_p, CK_KEY_TYPE key_type)
{
CK_RV rv = CKR_OK;
domain_obj_t *domain;
domain = calloc(1, sizeof (domain_obj_t));
if (domain == NULL) {
return (CKR_HOST_MEMORY);
}
switch (key_type) {
case CKK_DSA:
(void) memcpy(KEY_DOM_DSA(domain),
KEY_DOM_DSA(old_domain_obj_p),
sizeof (dsa_dom_key_t));
/* copy prime */
rv = copy_bigint(KEY_DOM_DSA_PRIME(domain),
KEY_DOM_DSA_PRIME(old_domain_obj_p));
if (rv != CKR_OK) {
free_domain_attr(domain, key_type);
return (rv);
}
/* copy subprime */
rv = copy_bigint(KEY_DOM_DSA_SUBPRIME(domain),
KEY_DOM_DSA_SUBPRIME(old_domain_obj_p));
if (rv != CKR_OK) {
free_domain_attr(domain, key_type);
return (rv);
}
/* copy base */
rv = copy_bigint(KEY_DOM_DSA_BASE(domain),
KEY_DOM_DSA_BASE(old_domain_obj_p));
if (rv != CKR_OK) {
free_domain_attr(domain, key_type);
return (rv);
}
break;
case CKK_DH:
(void) memcpy(KEY_DOM_DH(domain),
KEY_DOM_DH(old_domain_obj_p),
sizeof (dh_dom_key_t));
/* copy prime */
rv = copy_bigint(KEY_DOM_DH_PRIME(domain),
KEY_DOM_DH_PRIME(old_domain_obj_p));
if (rv != CKR_OK) {
free_domain_attr(domain, key_type);
return (rv);
}
/* copy base */
rv = copy_bigint(KEY_DOM_DH_BASE(domain),
KEY_DOM_DH_BASE(old_domain_obj_p));
if (rv != CKR_OK) {
free_domain_attr(domain, key_type);
return (rv);
}
break;
case CKK_X9_42_DH:
(void) memcpy(KEY_DOM_DH942(domain),
KEY_DOM_DH942(old_domain_obj_p),
sizeof (dh942_dom_key_t));
/* copy prime */
rv = copy_bigint(KEY_DOM_DH942_PRIME(domain),
KEY_DOM_DH942_PRIME(old_domain_obj_p));
if (rv != CKR_OK) {
free_domain_attr(domain, key_type);
return (rv);
}
/* copy subprime */
rv = copy_bigint(KEY_DOM_DH942_SUBPRIME(domain),
KEY_DOM_DH942_SUBPRIME(old_domain_obj_p));
if (rv != CKR_OK) {
free_domain_attr(domain, key_type);
return (rv);
}
/* copy base */
rv = copy_bigint(KEY_DOM_DH942_BASE(domain),
KEY_DOM_DH942_BASE(old_domain_obj_p));
if (rv != CKR_OK) {
free_domain_attr(domain, key_type);
return (rv);
}
break;
default:
break;
}
*new_domain_obj_p = domain;
return (rv);
}
CK_RV
soft_copy_secret_key_attr(secret_key_obj_t *old_secret_key_obj_p,
secret_key_obj_t **new_secret_key_obj_p)
{
secret_key_obj_t *sk;
sk = malloc(sizeof (secret_key_obj_t));
if (sk == NULL) {
return (CKR_HOST_MEMORY);
}
(void) memcpy(sk, old_secret_key_obj_p, sizeof (secret_key_obj_t));
/* copy the secret key value */
sk->sk_value = malloc((sizeof (CK_BYTE) * sk->sk_value_len));
if (sk->sk_value == NULL) {
free(sk);
return (CKR_HOST_MEMORY);
}
(void) memcpy(sk->sk_value, old_secret_key_obj_p->sk_value,
(sizeof (CK_BYTE) * sk->sk_value_len));
/*
* Copy the pre-expanded key schedule.
*/
if (old_secret_key_obj_p->key_sched != NULL &&
old_secret_key_obj_p->keysched_len > 0) {
sk->key_sched = malloc(old_secret_key_obj_p->keysched_len);
if (sk->key_sched == NULL) {
free(sk);
return (CKR_HOST_MEMORY);
}
sk->keysched_len = old_secret_key_obj_p->keysched_len;
(void) memcpy(sk->key_sched, old_secret_key_obj_p->key_sched,
sk->keysched_len);
}
*new_secret_key_obj_p = sk;
return (CKR_OK);
}
/*
* If CKA_CLASS not given, guess CKA_CLASS using
* attributes on template .
*
* Some attributes are specific to an object class. If one or more
* of these attributes are in the template, make a list of classes
* that can have these attributes. This would speed up the search later,
* because we can immediately skip an object if the class of that
* object can not possiblely contain one of the attributes.
*
*/
void
soft_process_find_attr(CK_OBJECT_CLASS *pclasses,
CK_ULONG *num_result_pclasses, CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount)
{
ulong_t i;
int j;
boolean_t pub_found = B_FALSE,
priv_found = B_FALSE,
secret_found = B_FALSE,
domain_found = B_FALSE,
hardware_found = B_FALSE,
cert_found = B_FALSE;
int num_pub_key_attrs, num_priv_key_attrs,
num_secret_key_attrs, num_domain_attrs,
num_hardware_attrs, num_cert_attrs;
int num_pclasses = 0;
for (i = 0; i < ulCount; i++) {
if (pTemplate[i].type == CKA_CLASS) {
/*
* don't need to guess the class, it is specified.
* Just record the class, and return.
*/
pclasses[0] =
(*((CK_OBJECT_CLASS *)pTemplate[i].pValue));
*num_result_pclasses = 1;
return;
}
}
num_pub_key_attrs =
sizeof (PUB_KEY_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
num_priv_key_attrs =
sizeof (PRIV_KEY_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
num_secret_key_attrs =
sizeof (SECRET_KEY_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
num_domain_attrs =
sizeof (DOMAIN_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
num_hardware_attrs =
sizeof (HARDWARE_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
num_cert_attrs =
sizeof (CERT_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
/*
* Get the list of objects class that might contain
* some attributes.
*/
for (i = 0; i < ulCount; i++) {
/*
* only check if this attribute can belong to public key object
* class if public key object isn't already in the list
*/
if (!pub_found) {
for (j = 0; j < num_pub_key_attrs; j++) {
if (pTemplate[i].type == PUB_KEY_ATTRS[j]) {
pub_found = B_TRUE;
pclasses[num_pclasses++] =
CKO_PUBLIC_KEY;
break;
}
}
}
if (!priv_found) {
for (j = 0; j < num_priv_key_attrs; j++) {
if (pTemplate[i].type == PRIV_KEY_ATTRS[j]) {
priv_found = B_TRUE;
pclasses[num_pclasses++] =
CKO_PRIVATE_KEY;
break;
}
}
}
if (!secret_found) {
for (j = 0; j < num_secret_key_attrs; j++) {
if (pTemplate[i].type == SECRET_KEY_ATTRS[j]) {
secret_found = B_TRUE;
pclasses[num_pclasses++] =
CKO_SECRET_KEY;
break;
}
}
}
if (!domain_found) {
for (j = 0; j < num_domain_attrs; j++) {
if (pTemplate[i].type == DOMAIN_ATTRS[j]) {
domain_found = B_TRUE;
pclasses[num_pclasses++] =
CKO_DOMAIN_PARAMETERS;
break;
}
}
}
if (!hardware_found) {
for (j = 0; j < num_hardware_attrs; j++) {
if (pTemplate[i].type == HARDWARE_ATTRS[j]) {
hardware_found = B_TRUE;
pclasses[num_pclasses++] =
CKO_HW_FEATURE;
break;
}
}
}
if (!cert_found) {
for (j = 0; j < num_cert_attrs; j++) {
if (pTemplate[i].type == CERT_ATTRS[j]) {
cert_found = B_TRUE;
pclasses[num_pclasses++] =
CKO_CERTIFICATE;
break;
}
}
}
}
*num_result_pclasses = num_pclasses;
}
boolean_t
soft_find_match_attrs(soft_object_t *obj, CK_OBJECT_CLASS *pclasses,
CK_ULONG num_pclasses, CK_ATTRIBUTE *template, CK_ULONG num_attr)
{
ulong_t i;
CK_ATTRIBUTE *tmpl_attr, *obj_attr;
cert_attr_t *cert_attr;
uint64_t attr_mask;
biginteger_t *bigint;
boolean_t compare_attr, compare_bigint, compare_boolean;
boolean_t compare_cert_val, compare_cert_type;
/*
* Check if the class of this object match with any
* of object classes that can possiblely contain the
* requested attributes.
*/
if (num_pclasses > 0) {
for (i = 0; i < num_pclasses; i++) {
if (obj->class == pclasses[i]) {
break;
}
}
if (i == num_pclasses) {
/*
* this object can't possiblely contain one or
* more attributes, don't need to check this object
*/
return (B_FALSE);
}
}
/* need to examine everything */
for (i = 0; i < num_attr; i++) {
tmpl_attr = &(template[i]);
compare_attr = B_FALSE;
compare_bigint = B_FALSE;
compare_boolean = B_FALSE;
compare_cert_val = B_FALSE;
compare_cert_type = B_FALSE;
switch (tmpl_attr->type) {
/* First, check the most common attributes */
case CKA_CLASS:
if (*((CK_OBJECT_CLASS *)tmpl_attr->pValue) !=
obj->class) {
return (B_FALSE);
}
break;
case CKA_KEY_TYPE:
if (*((CK_KEY_TYPE *)tmpl_attr->pValue) !=
obj->key_type) {
return (B_FALSE);
}
break;
case CKA_ENCRYPT:
attr_mask = (obj->bool_attr_mask) & ENCRYPT_BOOL_ON;
compare_boolean = B_TRUE;
break;
case CKA_DECRYPT:
attr_mask = (obj->bool_attr_mask) & DECRYPT_BOOL_ON;
compare_boolean = B_TRUE;
break;
case CKA_WRAP:
attr_mask = (obj->bool_attr_mask) & WRAP_BOOL_ON;
compare_boolean = B_TRUE;
break;
case CKA_UNWRAP:
attr_mask = (obj->bool_attr_mask) & UNWRAP_BOOL_ON;
compare_boolean = B_TRUE;
break;
case CKA_SIGN:
attr_mask = (obj->bool_attr_mask) & SIGN_BOOL_ON;
compare_boolean = B_TRUE;
break;
case CKA_SIGN_RECOVER:
attr_mask = (obj->bool_attr_mask) &
SIGN_RECOVER_BOOL_ON;
compare_boolean = B_TRUE;
break;
case CKA_VERIFY:
attr_mask = (obj->bool_attr_mask) & VERIFY_BOOL_ON;
compare_boolean = B_TRUE;
break;
case CKA_VERIFY_RECOVER:
attr_mask = (obj->bool_attr_mask) &
VERIFY_RECOVER_BOOL_ON;
compare_boolean = B_TRUE;
break;
case CKA_DERIVE:
attr_mask = (obj->bool_attr_mask) & DERIVE_BOOL_ON;
compare_boolean = B_TRUE;
break;
case CKA_LOCAL:
attr_mask = (obj->bool_attr_mask) & LOCAL_BOOL_ON;
compare_boolean = B_TRUE;
break;
case CKA_SENSITIVE:
attr_mask = (obj->bool_attr_mask) & SENSITIVE_BOOL_ON;
compare_boolean = B_TRUE;
break;
case CKA_SECONDARY_AUTH:
attr_mask = (obj->bool_attr_mask) &
SECONDARY_AUTH_BOOL_ON;
compare_boolean = B_TRUE;
break;
case CKA_TRUSTED:
attr_mask = (obj->bool_attr_mask) & TRUSTED_BOOL_ON;
compare_boolean = B_TRUE;
break;
case CKA_EXTRACTABLE:
attr_mask = (obj->bool_attr_mask) &
EXTRACTABLE_BOOL_ON;
compare_boolean = B_TRUE;
break;
case CKA_ALWAYS_SENSITIVE:
attr_mask = (obj->bool_attr_mask) &
ALWAYS_SENSITIVE_BOOL_ON;
compare_boolean = B_TRUE;
break;
case CKA_NEVER_EXTRACTABLE:
attr_mask = (obj->bool_attr_mask) &
NEVER_EXTRACTABLE_BOOL_ON;
compare_boolean = B_TRUE;
break;
case CKA_TOKEN:
attr_mask = (obj->object_type) & TOKEN_OBJECT;
compare_boolean = B_TRUE;
break;
case CKA_PRIVATE:
attr_mask = (obj->object_type) & PRIVATE_OBJECT;
compare_boolean = B_TRUE;
break;
case CKA_MODIFIABLE:
{
CK_BBOOL bval;
attr_mask = (obj->bool_attr_mask) &
NOT_MODIFIABLE_BOOL_ON;
if (attr_mask) {
bval = FALSE;
} else {
bval = TRUE;
}
if (bval != *((CK_BBOOL *)tmpl_attr->pValue)) {
return (B_FALSE);
}
break;
}
case CKA_OWNER:
/*
* For X.509 attribute certificate object, get its
* CKA_OWNER attribute from the x509_attr_cert_t struct.
*/
if ((obj->class == CKO_CERTIFICATE) &&
(obj->cert_type == CKC_X_509_ATTR_CERT)) {
cert_attr = X509_ATTR_CERT_OWNER(obj);
compare_cert_val = B_TRUE;
}
break;
case CKA_SUBJECT:
/*
* For X.509 certificate object, get its CKA_SUBJECT
* attribute from the x509_cert_t struct (not from
* the extra_attrlistp).
*/
if ((obj->class == CKO_CERTIFICATE) &&
(obj->cert_type == CKC_X_509)) {
cert_attr = X509_CERT_SUBJECT(obj);
compare_cert_val = B_TRUE;
break;
}
/*FALLTHRU*/
case CKA_ID:
case CKA_START_DATE:
case CKA_END_DATE:
case CKA_KEY_GEN_MECHANISM:
case CKA_LABEL:
case CKA_ISSUER:
case CKA_SERIAL_NUMBER:
case CKA_AC_ISSUER:
case CKA_ATTR_TYPES:
/* find these attributes from extra_attrlistp */
obj_attr = get_extra_attr(tmpl_attr->type, obj);
compare_attr = B_TRUE;
break;
case CKA_CERTIFICATE_TYPE:
compare_cert_type = B_TRUE;
break;
case CKA_VALUE_LEN:
/* only secret key has this attribute */
if (obj->class == CKO_SECRET_KEY) {
if (*((CK_ULONG *)tmpl_attr->pValue) !=
OBJ_SEC_VALUE_LEN(obj)) {
return (B_FALSE);
}
} else {
return (B_FALSE);
}
break;
case CKA_VALUE:
switch (obj->class) {
case CKO_SECRET_KEY:
/*
* secret_key_obj_t is the same as
* biginteger_t
*/
bigint = (biginteger_t *)OBJ_SEC(obj);
compare_bigint = B_TRUE;
break;
case CKO_PRIVATE_KEY:
if (obj->key_type == CKK_DSA) {
bigint = OBJ_PRI_DSA_VALUE(obj);
} else if (obj->key_type == CKK_DH) {
bigint = OBJ_PRI_DH_VALUE(obj);
} else if (obj->key_type == CKK_X9_42_DH) {
bigint = OBJ_PRI_DH942_VALUE(obj);
} else {
return (B_FALSE);
}
compare_bigint = B_TRUE;
break;
case CKO_PUBLIC_KEY:
if (obj->key_type == CKK_DSA) {
bigint = OBJ_PUB_DSA_VALUE(obj);
} else if (obj->key_type == CKK_DH) {
bigint = OBJ_PUB_DH_VALUE(obj);
} else if (obj->key_type == CKK_X9_42_DH) {
bigint = OBJ_PUB_DH942_VALUE(obj);
} else {
return (B_FALSE);
}
compare_bigint = B_TRUE;
break;
case CKO_CERTIFICATE:
if (obj->cert_type == CKC_X_509) {
cert_attr = X509_CERT_VALUE(obj);
} else if (obj->cert_type ==
CKC_X_509_ATTR_CERT) {
cert_attr = X509_ATTR_CERT_VALUE(obj);
}
compare_cert_val = B_TRUE;
break;
default:
return (B_FALSE);
}
break;
case CKA_MODULUS:
/* only RSA public and private key have this attr */
if (obj->key_type == CKK_RSA) {
if (obj->class == CKO_PUBLIC_KEY) {
bigint = OBJ_PUB_RSA_MOD(obj);
} else if (obj->class == CKO_PRIVATE_KEY) {
bigint = OBJ_PRI_RSA_MOD(obj);
} else {
return (B_FALSE);
}
compare_bigint = B_TRUE;
} else {
return (B_FALSE);
}
break;
case CKA_MODULUS_BITS:
/* only RSA public key has this attribute */
if ((obj->key_type == CKK_RSA) &&
(obj->class == CKO_PUBLIC_KEY)) {
CK_ULONG mod_bits = OBJ_PUB_RSA_MOD_BITS(obj);
if (mod_bits !=
*((CK_ULONG *)tmpl_attr->pValue)) {
return (B_FALSE);
}
} else {
return (B_FALSE);
}
break;
case CKA_PUBLIC_EXPONENT:
/* only RSA public and private key have this attr */
if (obj->key_type == CKK_RSA) {
if (obj->class == CKO_PUBLIC_KEY) {
bigint = OBJ_PUB_RSA_PUBEXPO(obj);
} else if (obj->class == CKO_PRIVATE_KEY) {
bigint = OBJ_PRI_RSA_PUBEXPO(obj);
} else {
return (B_FALSE);
}
compare_bigint = B_TRUE;
} else {
return (B_FALSE);
}
break;
case CKA_PRIVATE_EXPONENT:
/* only RSA private key has this attribute */
if ((obj->key_type == CKK_RSA) &&
(obj->class == CKO_PRIVATE_KEY)) {
bigint = OBJ_PRI_RSA_PRIEXPO(obj);
compare_bigint = B_TRUE;
} else {
return (B_FALSE);
}
break;
case CKA_PRIME_1:
/* only RSA private key has this attribute */
if ((obj->key_type == CKK_RSA) &&
(obj->class == CKO_PRIVATE_KEY)) {
bigint = OBJ_PRI_RSA_PRIME1(obj);
compare_bigint = B_TRUE;
} else {
return (B_FALSE);
}
break;
case CKA_PRIME_2:
/* only RSA private key has this attribute */
if ((obj->key_type == CKK_RSA) &&
(obj->class == CKO_PRIVATE_KEY)) {
bigint = OBJ_PRI_RSA_PRIME2(obj);
compare_bigint = B_TRUE;
} else {
return (B_FALSE);
}
break;
case CKA_EXPONENT_1:
/* only RSA private key has this attribute */
if ((obj->key_type == CKK_RSA) &&
(obj->class == CKO_PRIVATE_KEY)) {
bigint = OBJ_PRI_RSA_EXPO1(obj);
compare_bigint = B_TRUE;
} else {
return (B_FALSE);
}
break;
case CKA_EXPONENT_2:
/* only RSA private key has this attribute */
if ((obj->key_type == CKK_RSA) &&
(obj->class == CKO_PRIVATE_KEY)) {
bigint = OBJ_PRI_RSA_EXPO2(obj);
compare_bigint = B_TRUE;
} else {
return (B_FALSE);
}
break;
case CKA_COEFFICIENT:
/* only RSA private key has this attribute */
if ((obj->key_type == CKK_RSA) &&
(obj->class == CKO_PRIVATE_KEY)) {
bigint = OBJ_PRI_RSA_COEF(obj);
compare_bigint = B_TRUE;
} else {
return (B_FALSE);
}
break;
case CKA_VALUE_BITS:
/* only Diffie-Hellman private key has this attr */
if ((obj->key_type == CKK_DH) &&
(obj->class == CKO_PRIVATE_KEY)) {
CK_ULONG val_bits = OBJ_PRI_DH_VAL_BITS(obj);
if (val_bits !=
*((CK_ULONG *)tmpl_attr->pValue)) {
return (B_FALSE);
}
} else {
return (B_FALSE);
}
break;
case CKA_PRIME:
if (obj->class == CKO_PUBLIC_KEY) {
switch (obj->key_type) {
case CKK_DSA:
bigint = OBJ_PUB_DSA_PRIME(obj);
break;
case CKK_DH:
bigint = OBJ_PUB_DH_PRIME(obj);
break;
case CKK_X9_42_DH:
bigint = OBJ_PUB_DH942_PRIME(obj);
break;
default:
return (B_FALSE);
}
} else if (obj->class == CKO_PRIVATE_KEY) {
switch (obj->key_type) {
case CKK_DSA:
bigint = OBJ_PRI_DSA_PRIME(obj);
break;
case CKK_DH:
bigint = OBJ_PRI_DH_PRIME(obj);
break;
case CKK_X9_42_DH:
bigint = OBJ_PRI_DH942_PRIME(obj);
break;
default:
return (B_FALSE);
}
} else if (obj->class == CKO_DOMAIN_PARAMETERS) {
switch (obj->key_type) {
case CKK_DSA:
bigint = OBJ_DOM_DSA_PRIME(obj);
break;
case CKK_DH:
bigint = OBJ_DOM_DH_PRIME(obj);
break;
case CKK_X9_42_DH:
bigint = OBJ_DOM_DH942_PRIME(obj);
break;
default:
return (B_FALSE);
}
} else {
return (B_FALSE);
}
compare_bigint = B_TRUE;
break;
case CKA_SUBPRIME:
if (obj->class == CKO_PUBLIC_KEY) {
switch (obj->key_type) {
case CKK_DSA:
bigint = OBJ_PUB_DSA_SUBPRIME(obj);
break;
case CKK_X9_42_DH:
bigint = OBJ_PUB_DH942_SUBPRIME(obj);
break;
default:
return (B_FALSE);
}
} else if (obj->class == CKO_PRIVATE_KEY) {
switch (obj->key_type) {
case CKK_DSA:
bigint = OBJ_PRI_DSA_SUBPRIME(obj);
break;
case CKK_X9_42_DH:
bigint = OBJ_PRI_DH942_SUBPRIME(obj);
break;
default:
return (B_FALSE);
}
} else if (obj->class == CKO_DOMAIN_PARAMETERS) {
switch (obj->key_type) {
case CKK_DSA:
bigint = OBJ_DOM_DSA_SUBPRIME(obj);
break;
case CKK_X9_42_DH:
bigint = OBJ_DOM_DH942_SUBPRIME(obj);
break;
default:
return (B_FALSE);
}
} else {
return (B_FALSE);
}
compare_bigint = B_TRUE;
break;
case CKA_BASE:
if (obj->class == CKO_PUBLIC_KEY) {
switch (obj->key_type) {
case CKK_DSA:
bigint = OBJ_PUB_DSA_BASE(obj);
break;
case CKK_DH:
bigint = OBJ_PUB_DH_BASE(obj);
break;
case CKK_X9_42_DH:
bigint = OBJ_PUB_DH942_BASE(obj);
break;
default:
return (B_FALSE);
}
} else if (obj->class == CKO_PRIVATE_KEY) {
switch (obj->key_type) {
case CKK_DSA:
bigint = OBJ_PRI_DSA_BASE(obj);
break;
case CKK_DH:
bigint = OBJ_PRI_DH_BASE(obj);
break;
case CKK_X9_42_DH:
bigint = OBJ_PRI_DH942_BASE(obj);
break;
default:
return (B_FALSE);
}
} else if (obj->class == CKO_DOMAIN_PARAMETERS) {
switch (obj->key_type) {
case CKK_DSA:
bigint = OBJ_DOM_DSA_BASE(obj);
break;
case CKK_DH:
bigint = OBJ_DOM_DH_BASE(obj);
break;
case CKK_X9_42_DH:
bigint = OBJ_DOM_DH942_BASE(obj);
break;
default:
return (B_FALSE);
}
} else {
return (B_FALSE);
}
compare_bigint = B_TRUE;
break;
case CKA_PRIME_BITS:
if (obj->class == CKO_DOMAIN_PARAMETERS) {
CK_ULONG prime_bits;
if (obj->key_type == CKK_DSA) {
prime_bits =
OBJ_DOM_DSA_PRIME_BITS(obj);
} else if (obj->key_type == CKK_DH) {
prime_bits =
OBJ_DOM_DH_PRIME_BITS(obj);
} else if (obj->key_type == CKK_X9_42_DH) {
prime_bits =
OBJ_DOM_DH942_PRIME_BITS(obj);
} else {
return (B_FALSE);
}
if (prime_bits !=
*((CK_ULONG *)tmpl_attr->pValue)) {
return (B_FALSE);
}
} else {
return (B_FALSE);
}
break;
case CKA_SUBPRIME_BITS:
if ((obj->class == CKO_DOMAIN_PARAMETERS) &&
(obj->key_type == CKK_X9_42_DH)) {
CK_ULONG subprime_bits =
OBJ_DOM_DH942_SUBPRIME_BITS(obj);
if (subprime_bits !=
*((CK_ULONG *)tmpl_attr->pValue)) {
return (B_FALSE);
}
} else {
return (B_FALSE);
}
break;
default:
/*
* any other attributes are currently not supported.
* so, it's not possible for them to be in the
* object
*/
return (B_FALSE);
}
if (compare_boolean) {
CK_BBOOL bval;
if (attr_mask) {
bval = TRUE;
} else {
bval = FALSE;
}
if (bval != *((CK_BBOOL *)tmpl_attr->pValue)) {
return (B_FALSE);
}
} else if (compare_bigint) {
if (bigint == NULL) {
return (B_FALSE);
}
if (tmpl_attr->ulValueLen != bigint->big_value_len) {
return (B_FALSE);
}
if (memcmp(tmpl_attr->pValue, bigint->big_value,
tmpl_attr->ulValueLen) != 0) {
return (B_FALSE);
}
} else if (compare_attr) {
if (obj_attr == NULL) {
/*
* The attribute type is valid, and its value
* has not been initialized in the object. In
* this case, it only matches the template's
* attribute if the template's value length
* is 0.
*/
if (tmpl_attr->ulValueLen != 0)
return (B_FALSE);
} else {
if (tmpl_attr->ulValueLen !=
obj_attr->ulValueLen) {
return (B_FALSE);
}
if (memcmp(tmpl_attr->pValue, obj_attr->pValue,
tmpl_attr->ulValueLen) != 0) {
return (B_FALSE);
}
}
} else if (compare_cert_val) {
if (cert_attr == NULL) {
/* specific attribute not found */
return (B_FALSE);
}
if (tmpl_attr->ulValueLen != cert_attr->length) {
return (B_FALSE);
}
if (memcmp(tmpl_attr->pValue, cert_attr->value,
tmpl_attr->ulValueLen) != 0) {
return (B_FALSE);
}
} else if (compare_cert_type) {
if (memcmp(tmpl_attr->pValue, &(obj->cert_type),
tmpl_attr->ulValueLen) != 0) {
return (B_FALSE);
}
}
}
return (B_TRUE);
}
CK_ATTRIBUTE_PTR
get_extra_attr(CK_ATTRIBUTE_TYPE type, soft_object_t *obj)
{
CK_ATTRIBUTE_INFO_PTR tmp;
tmp = obj->extra_attrlistp;
while (tmp != NULL) {
if (tmp->attr.type == type) {
return (&(tmp->attr));
}
tmp = tmp->next;
}
/* if get there, the specified attribute is not found */
return (NULL);
}