/*
* 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
* 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
*/
/*
*/
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <cryptoutil.h>
#include <errno.h>
#include <security/cryptoki.h>
#include "kernelGlobal.h"
#include "kernelObject.h"
#include "kernelSlot.h"
cur_attr++; \
}
/*
* In order to fit everything on one line, the 'CRYPTO_' prefix
* has been dropped from the KCF #defines, e.g.
* CRYPTO_SUCCESS becomes SUCCESS.
*/
CKR_OK, /* SUCCESS */
CKR_CANCEL, /* CANCEL */
CKR_HOST_MEMORY, /* HOST_MEMORY */
CKR_GENERAL_ERROR, /* GENERAL_ERROR */
CKR_FUNCTION_FAILED, /* FAILED */
CKR_ARGUMENTS_BAD, /* ARGUMENTS_BAD */
CKR_ATTRIBUTE_READ_ONLY, /* ATTRIBUTE_READ_ONLY */
CKR_ATTRIBUTE_SENSITIVE, /* ATTRIBUTE_SENSITIVE */
CKR_ATTRIBUTE_TYPE_INVALID, /* ATTRIBUTE_TYPE_INVALID */
CKR_ATTRIBUTE_VALUE_INVALID, /* ATTRIBUTE_VALUE_INVALID */
CKR_FUNCTION_FAILED, /* CANCELED */
CKR_DATA_INVALID, /* DATA_INVALID */
CKR_DATA_LEN_RANGE, /* DATA_LEN_RANGE */
CKR_DEVICE_ERROR, /* DEVICE_ERROR */
CKR_DEVICE_MEMORY, /* DEVICE_MEMORY */
CKR_DEVICE_REMOVED, /* DEVICE_REMOVED */
CKR_ENCRYPTED_DATA_INVALID, /* ENCRYPTED_DATA_INVALID */
CKR_ENCRYPTED_DATA_LEN_RANGE, /* ENCRYPTED_DATA_LEN_RANGE */
CKR_KEY_HANDLE_INVALID, /* KEY_HANDLE_INVALID */
CKR_KEY_SIZE_RANGE, /* KEY_SIZE_RANGE */
CKR_KEY_TYPE_INCONSISTENT, /* KEY_TYPE_INCONSISTENT */
CKR_KEY_NOT_NEEDED, /* KEY_NOT_NEEDED */
CKR_KEY_CHANGED, /* KEY_CHANGED */
CKR_KEY_NEEDED, /* KEY_NEEDED */
CKR_KEY_INDIGESTIBLE, /* KEY_INDIGESTIBLE */
CKR_KEY_FUNCTION_NOT_PERMITTED, /* KEY_FUNCTION_NOT_PERMITTED */
CKR_KEY_NOT_WRAPPABLE, /* KEY_NOT_WRAPPABLE */
CKR_KEY_UNEXTRACTABLE, /* KEY_UNEXTRACTABLE */
CKR_MECHANISM_INVALID, /* MECHANISM_INVALID */
CKR_MECHANISM_PARAM_INVALID, /* MECHANISM_PARAM_INVALID */
CKR_OBJECT_HANDLE_INVALID, /* OBJECT_HANDLE_INVALID */
CKR_OPERATION_ACTIVE, /* OPERATION_ACTIVE */
CKR_OPERATION_NOT_INITIALIZED, /* OPERATION_NOT_INITIALIZED */
CKR_PIN_INCORRECT, /* PIN_INCORRECT */
CKR_PIN_INVALID, /* PIN_INVALID */
CKR_PIN_LEN_RANGE, /* PIN_LEN_RANGE */
CKR_PIN_EXPIRED, /* PIN_EXPIRED */
CKR_PIN_LOCKED, /* PIN_LOCKED */
CKR_SESSION_CLOSED, /* SESSION_CLOSED */
CKR_SESSION_COUNT, /* SESSION_COUNT */
CKR_SESSION_HANDLE_INVALID, /* SESSION_HANDLE_INVALID */
CKR_SESSION_READ_ONLY, /* SESSION_READ_ONLY */
CKR_SESSION_EXISTS, /* SESSION_EXISTS */
CKR_SESSION_READ_ONLY_EXISTS, /* SESSION_READ_ONLY_EXISTS */
CKR_SESSION_READ_WRITE_SO_EXISTS, /* SESSION_READ_WRITE_SO_EXISTS */
CKR_SIGNATURE_INVALID, /* SIGNATURE_INVALID */
CKR_SIGNATURE_LEN_RANGE, /* SIGNATURE_LEN_RANGE */
CKR_TEMPLATE_INCOMPLETE, /* TEMPLATE_INCOMPLETE */
CKR_TEMPLATE_INCONSISTENT, /* TEMPLATE_INCONSISTENT */
CKR_UNWRAPPING_KEY_HANDLE_INVALID, /* UNWRAPPING_KEY_HANDLE_INVALID */
CKR_UNWRAPPING_KEY_SIZE_RANGE, /* UNWRAPPING_KEY_SIZE_RANGE */
CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, /* UNWRAPPING_KEY_TYPE_INCONSISTENT */
CKR_USER_ALREADY_LOGGED_IN, /* USER_ALREADY_LOGGED_IN */
CKR_USER_NOT_LOGGED_IN, /* USER_NOT_LOGGED_IN */
CKR_USER_PIN_NOT_INITIALIZED, /* USER_PIN_NOT_INITIALIZED */
CKR_USER_TYPE_INVALID, /* USER_TYPE_INVALID */
CKR_USER_ANOTHER_ALREADY_LOGGED_IN, /* USER_ANOTHER_ALREADY_LOGGED_IN */
CKR_USER_TOO_MANY_TYPES, /* USER_TOO_MANY_TYPES */
CKR_WRAPPED_KEY_INVALID, /* WRAPPED_KEY_INVALID */
CKR_WRAPPED_KEY_LEN_RANGE, /* WRAPPED_KEY_LEN_RANGE */
CKR_WRAPPING_KEY_HANDLE_INVALID, /* WRAPPING_KEY_HANDLE_INVALID */
CKR_WRAPPING_KEY_SIZE_RANGE, /* WRAPPING_KEY_SIZE_RANGE */
CKR_WRAPPING_KEY_TYPE_INCONSISTENT, /* WRAPPING_KEY_TYPE_INCONSISTENT */
CKR_RANDOM_SEED_NOT_SUPPORTED, /* RANDOM_SEED_NOT_SUPPORTED */
CKR_RANDOM_NO_RNG, /* RANDOM_NO_RNG */
CKR_DOMAIN_PARAMS_INVALID, /* DOMAIN_PARAMS_INVALID */
CKR_BUFFER_TOO_SMALL, /* BUFFER_TOO_SMALL */
CKR_INFORMATION_SENSITIVE, /* INFORMATION_SENSITIVE */
CKR_FUNCTION_NOT_SUPPORTED, /* NOT_SUPPORTED */
CKR_GENERAL_ERROR, /* QUEUED */
CKR_GENERAL_ERROR, /* BUFFER_TOO_BIG */
CKR_OPERATION_NOT_INITIALIZED, /* INVALID_CONTEXT */
CKR_GENERAL_ERROR, /* INVALID_MAC */
CKR_GENERAL_ERROR, /* MECH_NOT_SUPPORTED */
CKR_GENERAL_ERROR, /* INCONSISTENT_ATTRIBUTE */
CKR_GENERAL_ERROR, /* NO_PERMISSION */
CKR_SLOT_ID_INVALID, /* INVALID_PROVIDER_ID */
CKR_GENERAL_ERROR, /* VERSION_MISMATCH */
CKR_GENERAL_ERROR, /* BUSY */
CKR_GENERAL_ERROR, /* UNKNOWN_PROVIDER */
CKR_GENERAL_ERROR, /* MODVERIFICATION_FAILED */
CKR_GENERAL_ERROR, /* OLD_CTX_TEMPLATE */
CKR_GENERAL_ERROR, /* WEAK_KEY */
CKR_GENERAL_ERROR /* FIPS140_ERROR */
};
#error "Crypto to PKCS11 error mapping table needs to be updated!"
#endif
/*
* Map KCF error codes into PKCS11 error codes.
*/
{
if (n >= sizeof (error_number_table) / sizeof (error_number_table[0]))
return (CKR_GENERAL_ERROR);
return (error_number_table[n]);
}
/*
* Serialize writes to the hash table. We don't need a per bucket lock as
* there are only a few writes and we don't need the lock for reads.
*/
static CK_RV
{
uint_t h;
return (CKR_HOST_MEMORY);
(void) pthread_mutex_lock(&mechhash_mutex);
/* Some other thread beat us to it. */
(void) pthread_mutex_unlock(&mechhash_mutex);
return (CKR_OK);
}
}
kernel_mechhash[h] = elem;
(void) pthread_mutex_unlock(&mechhash_mutex);
return (CKR_OK);
}
{
const char *string;
int r;
uint_t h;
/*
* Search for an existing entry. No need to lock since we are
* just a reader and we never free the entries in the hash table.
*/
return (CKR_OK);
}
}
if (type >= CKM_VENDOR_DEFINED) {
} else {
}
return (CKR_MECHANISM_INVALID);
&get_number)) < 0) {
break;
}
if (r < 0) {
} else {
} else {
}
}
/* Add this to the hash table */
}
return (rv);
}
/*
* Return the value of a secret key object.
* This routine allocates memory for the value.
* A null pointer is returned on error.
*/
unsigned char *
{
case CKO_SECRET_KEY:
return (NULL);
return (cipherKey);
default:
return (NULL);
}
}
/*
* Convert a RSA private key object into a crypto_key structure.
* Memory is allocated for each attribute stored in the crypto_key
* structure. Memory for the crypto_key structure is not
* allocated. Attributes can be freed by free_key_attributes().
*/
{
char *ptr;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
RSA_PRI_ATTR_COUNT * sizeof (crypto_object_attribute_t));
return (CKR_HOST_MEMORY);
}
/*
* Allocate memory for each key attribute and set up the value
* value length.
*/
/* CKA_MODULUS is required. */
goto fail_cleanup;
} else {
goto fail_cleanup;
}
}
/* CKA_PRIVATE_EXPONENT is required. */
goto fail_cleanup;
} else {
goto fail_cleanup;
}
big->big_value_len);
}
/* CKA_PRIME_1 is optional. */
goto fail_cleanup;
}
}
/* CKA_PRIME_2 is optional. */
goto fail_cleanup;
}
}
/* CKA_EXPONENT_1 is optional. */
goto fail_cleanup;
}
big->big_value_len);
}
/* CKA_EXPONENT_2 is optional. */
goto fail_cleanup;
}
big->big_value_len);
}
/* CKA_COEFFICIENT is optional. */
goto fail_cleanup;
}
big->big_value_len);
}
return (CKR_OK);
return (rv);
}
/*
* Convert a RSA public key object into a crypto_key structure.
* Memory is allocated for each attribute stored in the crypto_key
* structure. Memory for the crypto_key structure is not
* allocated. Attributes can be freed by free_key_attributes().
*/
{
char *ptr;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
RSA_PUB_ATTR_COUNT * sizeof (crypto_object_attribute_t));
return (CKR_HOST_MEMORY);
}
goto mem_failure;
goto mem_failure;
goto mem_failure;
sizeof (CK_ULONG));
return (CKR_OK);
return (CKR_HOST_MEMORY);
}
/*
* Free attribute storage in a crypto_key structure.
*/
void
{
int i;
}
}
}
}
/*
* Convert a DSA private key object into a crypto_key structure.
* Memory is allocated for each attribute stored in the crypto_key
* structure. Memory for the crypto_key structure is not
* allocated. Attributes can be freed by free_dsa_key_attributes().
*/
{
char *ptr;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
DSA_ATTR_COUNT * sizeof (crypto_object_attribute_t));
return (CKR_HOST_MEMORY);
}
goto mem_failure;
goto mem_failure;
goto mem_failure;
goto mem_failure;
return (CKR_OK);
return (CKR_HOST_MEMORY);
}
/*
* Convert a DSA public key object into a crypto_key structure.
* Memory is allocated for each attribute stored in the crypto_key
* structure. Memory for the crypto_key structure is not
* allocated. Attributes can be freed by free_dsa_key_attributes().
*/
{
char *ptr;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
DSA_ATTR_COUNT * sizeof (crypto_object_attribute_t));
return (CKR_HOST_MEMORY);
}
goto mem_failure;
goto mem_failure;
goto mem_failure;
goto mem_failure;
return (CKR_OK);
return (CKR_HOST_MEMORY);
}
/*
* Convert a EC private key object into a crypto_key structure.
* Memory is allocated for each attribute stored in the crypto_key
* structure. Memory for the crypto_key structure is not
* allocated. Attributes can be freed by free_ec_key_attributes().
*/
{
char *ptr;
int rv;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
return (CKR_HOST_MEMORY);
}
goto fail;
}
goto fail;
}
goto fail;
}
goto fail;
}
return (CKR_OK);
fail:
return (rv);
}
/*
* Convert an EC public key object into a crypto_key structure.
* Memory is allocated for each attribute stored in the crypto_key
* structure. Memory for the crypto_key structure is not
* allocated. Attributes can be freed by free_ec_key_attributes().
*/
{
char *ptr;
int rv;
return (CKR_ATTRIBUTE_TYPE_INVALID);
}
return (CKR_HOST_MEMORY);
}
goto fail;
}
goto fail;
}
goto fail;
}
goto fail;
}
return (CKR_OK);
fail:
return (rv);
}
/*
* Convert an attribute template into an obj_attrs array.
* Memory is allocated for each attribute stored in the obj_attrs.
* The memory can be freed by free_object_attributes().
*
* If the boolean pointer is_token_obj is not NULL, the caller wants to
* retrieve the value of the CKA_TOKEN attribute if it is specified in the
* template.
* - When this routine is called thru C_CreateObject(), C_CopyObject(), or
* any key management function, is_token_obj should NOT be NULL.
* - When this routine is called thru C_GetAttributeValue() or
* C_SetAttributeValue(), "is_token_obj" should be NULL.
*/
{
int i, cur_i;
char *ptr;
if (ulCount == 0) {
return (CKR_OK);
}
return (CKR_HOST_MEMORY);
}
for (i = 0; i < ulCount; i++) {
/*
* The length of long attributes must be set correctly
* so providers can determine whether they came from 32
* or 64-bit applications.
*/
case CKA_CLASS:
case CKA_CERTIFICATE_TYPE:
case CKA_KEY_TYPE:
case CKA_MODULUS_BITS:
case CKA_HW_FEATURE_TYPE:
cur_i = i;
goto fail_cleanup;
}
break;
default:
}
(pTemplate[i].ulValueLen > 0)) {
cur_i = i;
goto fail_cleanup;
} else {
pTemplate[i].ulValueLen);
}
}
if ((is_token_obj != NULL) &&
/* Get the CKA_TOKEN attribute value. */
cur_i = i;
goto fail_cleanup;
} else {
*is_token_obj =
}
}
cur_attr++;
}
return (CKR_OK);
for (i = 0; i < cur_i; i++) {
}
cur_attr++;
}
return (rv);
}
/*
* Copy the attribute values from obj_attrs to pTemplate.
* The obj_attrs is an image of the Template and is expected to have the
* same attributes in the same order and each one of the attribute pValue
* in obj_attr has enough space allocated for the corresponding valueLen
* in pTemplate.
*/
{
int i;
/* LINTED */
for (i = 0; i < ulCount; i++) {
/* The attribute type doesn't match, this is bad. */
return (rv);
}
pTemplate[i].ulValueLen);
}
cur_attr++;
}
return (rv);
}
/*
* Free the attribute storage in a crypto_object_attribute_t structure.
*/
void
{
int i;
return;
}
/* LINTED */
for (i = 0; i < ulCount; i++) {
/* XXX check that oa_value > 0 */
}
cur_attr++;
}
}
/*
* This function is called by process_found_objects(). It will check the
* CKA_PRIVATE and CKA_TOKEN attributes for the kernel object "oid", then
* initialize all the necessary fields in the object wrapper "objp".
*/
static CK_RV
{
int r;
/*
* Make a CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE ioctl call to get this
* kernel object's attribute values for CKA_PRIVATE and CKA_TOKEN.
*/
NULL);
return (rv);
}
&obj_ga)) < 0) {
break;
}
if (r < 0) {
} else {
}
}
}
return (rv);
}
/* Make sure it is a token object. */
if (!is_token_obj) {
return (rv);
}
/* If it is a private object, make sure the user has logged in. */
return (rv);
}
if (is_pri_obj) {
} else {
}
return (CKR_OK);
}
/*
* This function processes the kernel object handles returned from the
* CRYPTO_OBJECT_FIND_UPDATE ioctl and returns an object handle list
* and the number of object handles to the caller - C_FindObjects().
* The caller acquires the slot lock and the session lock.
*/
{
int i;
*found_obj_count = 0;
return (CKR_OK);
}
/* LINTED */
/*
* Check if this oid has an object wrapper in the library
* already. First, search the slot's token object list.
*/
} else {
}
}
/*
* If it is not in the slot's token object list,
* search it in all the sessions.
*/
if (!is_in_lib) {
} else {
}
}
}
}
/*
* If this object is in the library already, add its object
* wrapper to the returned find object list.
*/
if (is_in_lib) {
}
/*
* If we still do not find it in the library. This object
* must be a token object pre-existed in the HW provider.
* We need to create an object wrapper for it in the library.
*/
if (!is_in_lib) {
goto failed_exit;
}
*oid_p);
/* Save the new object to the new_tobj_list. */
if (new_tobj_list == NULL) {
} else {
}
} else {
/*
* If create_new_tobj_in_lib() doesn't fail
* with CKR_HOST_MEMORY, the failure should be
* caused by the attributes' checking. We will
* just ignore this object and continue on.
*/
if (rv == CKR_HOST_MEMORY) {
goto failed_exit;
}
}
}
/* Process next one */
oid_p++;
}
/*
* Add the newly created token object wrappers to the found object
* list and to the slot's token object list.
*/
if (new_tobj_list != NULL) {
/* Add to the obj_found array. */
while (objp) {
break;
}
}
/* Add to the beginning of the slot's token object list. */
}
}
return (CKR_OK);
/* Free the newly created token object wrappers. */
while (objp) {
}
return (rv);
}
/*
* Get the value of the CKA_PRIVATE attribute for the object just returned
* from the HW provider. This function will be called by any function
* that creates a new object, because the CKA_PRIVATE value of an object is
* token specific. The CKA_PRIVATE attribute value of the new object will be
* stored in the object structure in the library, which will be used later at
* C_Logout to clean up all private objects.
*/
{
int r;
&obj_ga)) < 0) {
break;
}
if (r < 0) {
} else {
}
}
return (rv);
}
{
const char *string;
int r;
if (type >= CKM_VENDOR_DEFINED) {
} else {
}
return (CKR_MECHANISM_INVALID);
&mechanism_info)) < 0) {
break;
}
if (r < 0) {
} else {
}
return (rv);
}
/*
* Atomic flags are not part of PKCS#11 so we filter
* them out here.
*/
if (mi_flags == 0) {
return (CKR_MECHANISM_INVALID);
}
/* set the value of k_mi_flags first */
*k_mi_flags = mi_flags;
/* convert KEF flags into pkcs11 flags */
if (mi_flags & CRYPTO_FG_ENCRYPT)
flags |= CKF_ENCRYPT;
if (mi_flags & CRYPTO_FG_DECRYPT) {
flags |= CKF_DECRYPT;
/*
* Since we'll be emulating C_UnwrapKey() for some
* cases, we can go ahead and claim CKF_UNWRAP
*/
flags |= CKF_UNWRAP;
}
if (mi_flags & CRYPTO_FG_DIGEST)
flags |= CKF_DIGEST;
if (mi_flags & CRYPTO_FG_SIGN)
if (mi_flags & CRYPTO_FG_SIGN_RECOVER)
if (mi_flags & CRYPTO_FG_VERIFY)
flags |= CKF_VERIFY;
if (mi_flags & CRYPTO_FG_VERIFY_RECOVER)
if (mi_flags & CRYPTO_FG_GENERATE)
flags |= CKF_GENERATE;
if (mi_flags & CRYPTO_FG_WRAP)
if (mi_flags & CRYPTO_FG_UNWRAP)
flags |= CKF_UNWRAP;
if (mi_flags & CRYPTO_FG_DERIVE)
flags |= CKF_DERIVE;
}
return (rv);
}