/* * 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 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2012 Milan Jurik. All rights reserved. * Copyright (c) 2018, Joyent, Inc. */ #include #include #include #include #include #include #include #include #include #include #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 != NULL) { freezero(attr->value, attr->length); 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) { cleanup_cert_attr(*dest_attr); } 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 != NULL) { /* * 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. */ freezero(extra_attr->attr.pValue, extra_attr->attr.ulValueLen); } /* 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. */ freezero(extra_attr->attr.pValue, extra_attr->attr.ulValueLen); } /* 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. */ static CK_RV get_ulong_attr_from_template(CK_ULONG *value, CK_ATTRIBUTE_PTR template) { if (template->ulValueLen < sizeof (CK_ULONG)) return (CKR_ATTRIBUTE_VALUE_INVALID); if (template->pValue != NULL) { *value = *(CK_ULONG_PTR)template->pValue; } else { *value = 0; } return (CKR_OK); } /* * 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) { cleanup_cert_attr(*dest); } 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) { freezero(template->pValue, template->ulValueLen); 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; freezero(big->big_value, big->big_value_len); 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) { freezero(OBJ_SEC_VALUE(object_p), OBJ_SEC_VALUE_LEN(object_p)); } /* cleanup key schedule data area */ if (OBJ_KEY_SCHED(object_p) != NULL && OBJ_KEY_SCHED_LEN(object_p) > 0) { freezero(OBJ_KEY_SCHED(object_p), OBJ_KEY_SCHED_LEN(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; CK_ATTRIBUTE defpubexpo = { CKA_PUBLIC_EXPONENT, (CK_BYTE_PTR)DEFAULT_PUB_EXPO, DEFAULT_PUB_EXPO_Len }; BIGNUM n; /* 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; rv = get_ulong_attr_from_template(&modulus_bits, &template[i]); if (rv != CKR_OK) goto fail_cleanup; 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(¶m_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) { /* * Derive modulus_bits attribute from modulus. * Save modulus_bits integer value to the * designated place in the public key object. */ n.malloced = 0; #ifdef __sparcv9 if (big_init(&n, (int)CHARLEN2BIGNUMLEN( modulus.big_value_len)) != BIG_OK) { #else /* !__sparcv9 */ if (big_init(&n, CHARLEN2BIGNUMLEN( modulus.big_value_len)) != BIG_OK) { #endif /* __sparcv9 */ rv = CKR_HOST_MEMORY; big_finish(&n); goto fail_cleanup; } bytestring2bignum(&n, modulus.big_value, modulus.big_value_len); modulus_bits = big_bitlength(&n); KEY_PUB_RSA_MOD_BITS(pbk) = modulus_bits; big_finish(&n); /* * After modulus_bits has been computed, * it is safe to move modulus and pubexpo * 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 { /* mode is SOFT_GEN_KEY */ if (isModulus || isPrime || isSubprime || isBase || isValue) { rv = CKR_TEMPLATE_INCONSISTENT; goto fail_cleanup; } if (isModulusBits) { /* * Copy big integer attribute value to the * designated place in the public key object. */ KEY_PUB_RSA_MOD_BITS(pbk) = modulus_bits; } else { rv = CKR_TEMPLATE_INCOMPLETE; goto fail_cleanup; } /* * Use PKCS#11 default 0x010001 for public exponent * if not not specified in attribute template. */ if (!isPubExpo) { isPubExpo = 1; rv = get_bigint_attr_from_template(&pubexpo, &defpubexpo); if (rv != CKR_OK) goto fail_cleanup; } /* * Copy big integer attribute value to the * designated place in the public key object. */ copy_bigint_attr(&pubexpo, KEY_PUB_RSA_PUBEXPO(pbk)); } 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(¶m_tmp, new_object); if (rv != CKR_OK) goto fail_cleanup; string_attr_cleanup(¶m_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(¶m_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; rv = get_ulong_attr_from_template(&value_bits, &template[i]); if (rv != CKR_OK) goto fail_cleanup; 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(¶m_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 BIG_CHUNK_TYPE words. */ #ifdef __sparcv9 if (big_init(&x, (int)CHARLEN2BIGNUMLEN(value.big_value_len)) != BIG_OK) { #else /* !__sparcv9 */ if (big_init(&x, CHARLEN2BIGNUMLEN(value.big_value_len)) != BIG_OK) { #endif /* __sparcv9 */ rv = CKR_HOST_MEMORY; goto fail_cleanup; } #ifdef __sparcv9 if (big_init(&q, (int)CHARLEN2BIGNUMLEN(subprime.big_value_len)) != BIG_OK) { #else /* !__sparcv9 */ if (big_init(&q, CHARLEN2BIGNUMLEN(subprime.big_value_len)) != 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(¶m_tmp, new_object); if (rv != CKR_OK) goto fail_cleanup; string_attr_cleanup(¶m_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(¶m_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; rv = get_ulong_attr_from_template(&sck->sk_value_len, &template[i]); if (rv != CKR_OK) goto fail_cleanup; 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; } 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; } 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_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: /* arbitrary key length - no length checking */ if (!isValueLen) { rv = CKR_TEMPLATE_INCOMPLETE; goto fail_cleanup; } break; case CKK_AES: if (!isValueLen) { rv = CKR_TEMPLATE_INCOMPLETE; goto fail_cleanup; } 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; } break; case CKK_BLOWFISH: if (!isValueLen) { 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: case CKK_DES2: case CKK_DES3: /* CKA_VALUE_LEN attribute does not apply to DES */ 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) { 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; } } 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 */ 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) { 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; } } 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 */ 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 */ 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)); 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)); default: return (soft_get_common_attrs(object_p, template, object_p->object_type)); } /* * 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); 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)); default: return (soft_set_common_storage_attribute( object_p, template, copy)); } /* * 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_value(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_value(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 if (key->key_type == CKK_DH) { #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 */ } else { #ifdef __sparcv9 len = /* LINTED */ (uint32_t) ((biginteger_t *)OBJ_PRI_EC_VALUE(key))-> big_value_len; #else /* !__sparcv9 */ len = ((biginteger_t *)OBJ_PRI_EC_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 if (key->key_type == CKK_DH) { (void) memcpy(value, ((biginteger_t *)OBJ_PRI_DH_VALUE(key))->big_value, *value_len); } else { (void) memcpy(value, ((biginteger_t *)OBJ_PRI_EC_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(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) { freezero(sk->sk_value, sk->sk_value_len); 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 possibly 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 possibly 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 possibly 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); }