/*
* 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
*/
/*
*/
/*
* The ioctl interface for cryptographic commands.
*/
#include <sys/sysmacros.h>
extern int kcf_des3_threshold;
extern int kcf_aes_threshold;
extern int kcf_rc4_threshold;
extern int kcf_md5_threshold;
extern int kcf_sha1_threshold;
/*
* Locking notes:
*
* crypto_locks protects the global array of minor structures.
* crypto_locks is an array of locks indexed by the cpuid. A reader needs
* to hold a single lock while a writer needs to hold all locks.
* krwlock_t is not an option here because the hold time
* is very small for these locks.
*
* The fields in the minor structure are protected by the cm_lock member
* of the minor structure. The cm_cv is used to signal decrements
* in the cm_refcnt, and is used with the cm_lock.
*
* The locking order is crypto_locks followed by cm_lock.
*/
/*
* DDI entry points.
*/
crypto_data_t *, crypto_call_req_t *));
static void crypto_release_provider_session(crypto_minor_t *,
static int crypto_buffer_check(size_t);
static int crypto_free_find_ctx(crypto_session_data_t *);
/* number of minor numbers to allocate at a time */
/*
* There are two limits associated with kernel memory. The first,
* CRYPTO_MAX_BUFFER_LEN, is the maximum number of bytes that can be
* the total number of bytes that can be allocated by a process
* project.max-crypto-memory resource control.
*/
/*
* We preapprove some bytes for each session to avoid making the costly
* crypto_buffer_check() calls. The preapproval is done when a new session
* is created and that cost is amortized over later crypto calls.
* Most applications create a session and then do a bunch of crypto calls
* in that session. So, they benefit from this optimization.
*
* Note that we may hit the project.max-crypto-memory limit a bit sooner
* because of this preapproval. But it is acceptable since the preapproved
* amount is insignificant compared to the default max-crypto-memory limit
* which is quarter of the machine's memory. The preapproved amount is
* roughly 2 * 16K(maximum SSL record size).
*/
/* The session table grows by CRYPTO_SESSION_CHUNK increments */
/*
* Minors are started from 1 because vmem_alloc()
* returns 0 in case of failure.
*/
#define CRYPTO_ENTER_ALL_LOCKS() \
for (i = 0; i < max_ncpus; i++) \
#define CRYPTO_EXIT_ALL_LOCKS() \
for (i = 0; i < max_ncpus; i++) \
#define CRYPTO_PROVIDER_OFFSET(f) \
crypto_cancel_ctx(*(spp)); \
}
} \
} \
} \
} \
} \
} \
} \
}
kproject_t *projp; \
}
/*
* We do not need to hold sd_lock in the macros below
* as they are called after doing a get_session_ptr() which
* sets the CRYPTO_SESSION_IS_BUSY flag.
*/
if (rctl_chk) { \
} else { \
} \
}
/*
* Module linkage.
*/
crypto_open, /* cb_open */
crypto_close, /* cb_close */
nodev, /* cb_strategy */
nodev, /* cb_print */
nodev, /* cb_dump */
nodev, /* cb_read */
nodev, /* cb_write */
crypto_ioctl, /* cb_ioctl */
nodev, /* cb_devmap */
nodev, /* cb_mmap */
nodev, /* cb_segmap */
nochpoll, /* cb_chpoll */
ddi_prop_op, /* cb_prop_op */
NULL, /* cb_streamtab */
D_MP, /* cb_flag */
CB_REV, /* cb_rev */
nodev, /* cb_aread */
nodev, /* cb_awrite */
};
DEVO_REV, /* devo_rev */
0, /* devo_refcnt */
crypto_getinfo, /* devo_getinfo */
nulldev, /* devo_identify */
nulldev, /* devo_probe */
crypto_attach, /* devo_attach */
crypto_detach, /* devo_detach */
nodev, /* devo_reset */
&cbops, /* devo_cb_ops */
NULL, /* devo_bus_ops */
NULL, /* devo_power */
ddi_quiesce_not_needed, /* devo_quiesce */
};
&mod_driverops, /* drv_modops */
"Cryptographic Library Interface", /* drv_linkinfo */
&devops,
};
MODREV_1, /* ml_rev */
&modldrv, /* ml_linkage */
};
/*
* DDI entry points.
*/
int
_init(void)
{
return (mod_install(&modlinkage));
}
int
_fini(void)
{
return (mod_remove(&modlinkage));
}
int
{
}
/* ARGSUSED */
static int
{
switch (cmd) {
case DDI_INFO_DEVT2DEVINFO:
*result = crypto_dip;
return (DDI_SUCCESS);
case DDI_INFO_DEVT2INSTANCE:
*result = (void *)0;
return (DDI_SUCCESS);
}
return (DDI_FAILURE);
}
static int
{
int i;
if (cmd != DDI_ATTACH) {
return (DDI_FAILURE);
}
if (ddi_get_instance(dip) != 0) {
/* we only allow instance 0 to attach */
return (DDI_FAILURE);
}
if (crypto_session_cache == NULL)
return (DDI_FAILURE);
/* create the minor node */
DDI_PSEUDO, 0) != DDI_SUCCESS) {
return (DDI_FAILURE);
}
KM_SLEEP);
for (i = 0; i < max_ncpus; i++)
crypto_dip = dip;
/* allocate integer space for minor numbers */
return (DDI_SUCCESS);
}
static int
{
minor_t i;
if (cmd != DDI_DETACH)
return (DDI_FAILURE);
/* check if device is open */
for (i = 0; i < crypto_minors_table_count; i++) {
if (crypto_minors[i] != NULL) {
return (DDI_FAILURE);
}
}
crypto_dip = NULL;
sizeof (crypto_minor_t *) * crypto_minors_table_count);
for (i = 0; i < max_ncpus; i++)
crypto_locks = NULL;
crypto_arena = NULL;
return (DDI_SUCCESS);
}
/* ARGSUSED3 */
static int
{
int i;
return (ENXIO);
if (crypto_dip == NULL)
return (ENXIO);
/* exclusive opens are not supported */
return (ENOTSUP);
/* grow the minors table if needed */
if (crypto_minors_count >= crypto_minors_table_count) {
return (ENOMEM);
}
new_size = sizeof (crypto_minor_t *) *
/*
* Check if table grew while we were sleeping.
* The minors table never shrinks.
*/
if (crypto_minors_table_count > saved_count) {
goto again;
}
/* we assume that bcopy() will return if count is 0 */
sizeof (crypto_minor_t *) * crypto_minors_table_count);
sizeof (crypto_minor_t *) * crypto_minors_table_count);
/* grow the minors number space */
if (crypto_minors_table_count != 0) {
(void) vmem_add(crypto_arena,
}
} else {
}
/* allocate a new minor number starting with 1 */
return (0);
}
/* ARGSUSED1 */
static int
{
uint_t i;
if (mn > crypto_minors_table_count) {
return (ENODEV);
}
return (ENODEV);
}
/*
* We free the minor number, mn, from the crypto_arena
* only later. This ensures that we won't race with another
* thread in crypto_open with the same minor number.
*/
}
/* free all session table entries starting with 1 */
continue;
(void) crypto_free_find_ctx(sp);
}
}
/* free the session table */
sizeof (void *));
return (0);
}
static crypto_minor_t *
{
if (minor > crypto_minors_table_count)
return (NULL);
}
return (cm);
}
static void
{
}
}
/*
* Build a list of functions and other information for the provider, pd.
*/
static void
{
return;
}
}
}
}
}
}
}
}
}
}
}
if (fl->prov_is_hash_limited) {
}
if (fl->prov_is_hmac_limited) {
}
/*
* mechanism. For now, we use the same value for all
* is fine.
*/
}
}
/* ARGSUSED */
static int
{
int rv;
return (ENXIO);
}
return (EFAULT);
}
/* initialize provider_array */
if (rv != CRYPTO_SUCCESS) {
goto release_minor;
}
}
/* index must be less than count of providers */
goto release_minor;
}
} else {
}
}
rv = CRYPTO_SUCCESS;
return (EFAULT);
}
return (0);
}
/*
* This ioctl maps a PKCS#11 mechanism string into an internal number
* that is used by the kernel. pn_internal_number is set to the
* internal number.
*/
/* ARGSUSED */
static int
{
char *mechanism_name;
int rv;
return (EFAULT);
goto out;
}
mechanism_name, len) != 0) {
return (EFAULT);
}
/*
* Get mechanism number from kcf. We set the load_module
* flag to false since we use only hardware providers.
*/
if (number == CRYPTO_MECH_INVALID) {
goto out;
}
pn_internal_number), sizeof (number));
rv = CRYPTO_SUCCESS;
out:
STRUCT_SIZE(get_number)) != 0) {
return (EFAULT);
}
return (0);
}
/*
* This ioctl returns an array of crypto_mech_name_t entries.
* It lists all the PKCS#11 mechanisms available in the kernel.
*/
/* ARGSUSED */
static int
{
int error = 0;
return (EFAULT);
}
/* Number of entries caller thinks we have */
/* check if buffer is too small */
}
/* copyout the first stuff */
}
/*
* If only requesting number of entries or buffer too small or an
* error occurred, stop here
*/
goto out;
}
/* copyout entries */
}
out:
return (error);
}
/*
* Copyout kernel array of mech_infos to user space.
*/
/* ARGSUSED */
static int
{
caddr_t p;
int i;
if (count == 0)
return (0);
p = u_minfos;
for (i = 0; i < count; i++) {
p += STRUCT_SIZE(mi);
}
return (EFAULT);
return (0);
}
/*
* This ioctl returns information for the specified mechanism.
*/
/* ARGSUSED */
static int
{
#ifdef _LP64
#else
/* LINTED E_FUNC_SET_NOT_USED */
#endif
int error = 0;
int rv;
STRUCT_SIZE(get_all_mech)) != 0) {
return (EFAULT);
}
if (mech_type == CRYPTO_MECH_INVALID) {
goto out1;
}
KM_SLEEP);
if (rv != CRYPTO_SUCCESS) {
goto out1;
}
/* rv is CRYPTO_SUCCESS at this point */
/* Number of entries caller thinks we have */
/* check if buffer is too small */
if (num_mech_infos > req_count) {
}
out1:
/* copy the first part */
STRUCT_SIZE(get_all_mech)) != 0) {
}
/*
* If only requesting number of entries, or there are no entries,
* or rv is not CRYPTO_SUCCESS due to buffer too small or some other
* crypto error, or an error occurred with copyout, stop here
*/
error != 0) {
goto out2;
}
/* copyout mech_infos */
out2:
if (mech_infos != NULL)
return (error);
}
/*
* Side-effects:
* 1. This routine stores provider descriptor pointers in an array
* and increments each descriptor's reference count. The array
* is stored in per-minor number storage.
* 2. Destroys the old array and creates a new one every time
* this routine is called.
*/
int
{
crypto_provider_entry_t *p = NULL;
int rval;
int i;
/*
* Take snapshot of provider table returning only HW entries
* that are in a usable state. Also returns logical provider entries.
*/
if (rval != CRYPTO_SUCCESS)
return (rval);
/* allocate memory before taking cm->cm_lock */
if (return_slot_list) {
if (provider_count != 0) {
p = kmem_alloc(provider_count *
sizeof (crypto_provider_entry_t), KM_SLEEP);
for (i = 0; i < provider_count; i++) {
p[i].pe_provider_id = i;
p[i].pe_mechanism_count =
}
}
*array = p;
*count = provider_count;
}
/*
* Free existing array of providers and replace with new list.
*/
}
return (CRYPTO_SUCCESS);
}
/*
* This ioctl returns an array of crypto_provider_entry_t entries.
* This is how consumers learn which hardware providers are available.
*/
/* ARGSUSED */
static int
{
int rv;
return (ENXIO);
}
return (EFAULT);
}
if (rv != CRYPTO_SUCCESS) {
STRUCT_SIZE(get_list)) != 0) {
return (EFAULT);
}
return (0);
}
/* Number of slots caller thinks we have */
/* Check if only requesting number of slots */
if (req_count == 0) {
STRUCT_SIZE(get_list)) != 0) {
return (EFAULT);
}
return (0);
}
/* check if buffer is too small */
STRUCT_SIZE(get_list)) != 0) {
return (EFAULT);
}
return (0);
}
/* copyout the first stuff */
return (EFAULT);
}
if (count == 0) {
return (0);
}
/* copyout entries */
return (EFAULT);
}
return (0);
}
static void
{
/*
* We do not support ioctls for dual-function crypto operations yet.
* So, we clear this flag as it might have been set by a provider.
*/
}
/*
* Utility routine to construct a crypto_provider_ext_info structure. Some
* of the fields are constructed from information in the provider structure.
* The rest of the fields have default values. We need to do this for
* providers which do not support crypto_provider_management_ops routines.
*/
static void
{
/* empty label */
ei->ei_max_pin_len = 0;
ei->ei_min_pin_len = 0;
}
/* ARGSUSED */
static int
{
int error = 0;
int rv;
return (ENXIO);
}
return (EFAULT);
}
need = sizeof (crypto_provider_ext_info_t);
need = 0;
goto release_minor;
}
/* initialize provider_array */
if (rv != CRYPTO_SUCCESS) {
goto release_minor;
}
}
/* index must be less than count of providers */
goto release_minor;
}
(void) kcf_get_hardware_provider_nomech(
if (real_provider != NULL) {
B_FALSE);
} else {
/* do the best we can */
rv = CRYPTO_SUCCESS;
}
if (rv == CRYPTO_SUCCESS) {
}
if (error != 0)
return (error);
return (EFAULT);
}
return (0);
}
/*
* This ioctl returns an array of crypto_mech_name_t entries.
* This is how consumers learn which mechanisms are permitted
* by a provider.
*/
/* ARGSUSED */
static int
{
int err;
"get_provider_mechanisms: failed holding minor");
return (ENXIO);
}
STRUCT_SIZE(get_mechanisms)) != 0) {
return (EFAULT);
}
/* get array of mechanisms from the core module */
STRUCT_SIZE(get_mechanisms)) != 0) {
return (EFAULT);
}
return (0);
}
/* Number of mechs caller thinks we have */
/* Check if caller is just requesting a count of mechanisms */
if (req_count == 0) {
STRUCT_SIZE(get_mechanisms)) != 0) {
return (EFAULT);
}
return (0);
}
/* check if buffer is too small */
STRUCT_SIZE(get_mechanisms)) != 0) {
return (EFAULT);
}
return (0);
}
/* copyout the first stuff */
STRUCT_SIZE(get_mechanisms)) != 0) {
return (EFAULT);
}
if (count == 0) {
return (0);
}
/* copyout entries */
return (EFAULT);
}
return (0);
}
/*
* This ioctl returns information about a provider's mechanism.
*/
/* ARGSUSED */
static int
{
int i;
"get_provider_mechanism_info: failed holding minor");
return (ENXIO);
}
return (EFAULT);
}
/* initialize provider table */
if (rv != CRYPTO_SUCCESS) {
goto fail;
}
}
/*
* Provider ID must be less than the count of providers
* obtained by calling get_provider_list().
*/
goto fail;
}
/* First check if the provider supports the mechanism. */
for (i = 0; i < pd->pd_mech_list_count; i++) {
CRYPTO_MAX_MECH_NAME) == 0) {
break;
}
}
goto fail;
}
/* Now check if the mechanism is enabled for the provider. */
goto fail;
}
fail:
return (EFAULT);
}
return (0);
}
/*
* a single session to each provider. Calls to open and close session
* are not made to providers that do not support sessions. For these
* providers, a session number of 0 is passed during subsequent operations,
* and it is ignored by the provider.
*/
static int
{
int rv;
/* pd may be a logical provider */
/*
* Check if there is already a session to the provider.
* Sessions may be to a logical provider or a real provider.
*/
break;
}
/* found existing session */
return (CRYPTO_SUCCESS);
}
/* find a hardware provider that supports session ops */
if (real_provider != NULL) {
/* open session to provider */
B_FALSE);
if (rv != CRYPTO_SUCCESS) {
return (rv);
}
}
/* allocate crypto_provider_session structure */
/*
* Check if someone opened a session to the provider
* while we dropped the lock.
*/
if (real_provider != NULL) {
pd);
}
goto again;
}
}
/* increment refcnt and attach to crypto_minor structure */
if (real_provider != NULL) {
}
return (CRYPTO_SUCCESS);
}
/*
* Release a provider session.
* If the reference count goes to zero, then close the session
* to the provider.
*/
static void
{
/* verify that provider_session is valid */
if (ps == provider_session) {
break;
}
}
return;
return;
/* close session with provider */
}
}
static int
{
int rv;
current_allocation = session_table_count * sizeof (void *);
new_allocation = need * sizeof (void *);
/*
* Memory needed to grow the session table is checked
* against the project.max-crypto-memory resource control.
*/
return (rv);
}
/* drop lock while we allocate memory */
/* check if another thread increased the table size */
return (CRYPTO_SUCCESS);
}
return (CRYPTO_SUCCESS);
}
/*
* Find unused entry in session table and return it's index.
* Initialize session table entry.
*/
/* ARGSUSED */
static int
{
uint_t i;
int rv;
return (CRYPTO_FAILED);
}
/* initialize provider_array */
if (rv != 0) {
return (rv);
}
}
/* index must be less than count of providers */
return (CRYPTO_INVALID_PROVIDER_ID);
}
if (rv != CRYPTO_SUCCESS) {
return (rv);
}
/* session handles start with 1 */
for (i = 1; i < session_table_count; i++) {
if (session_table[i] == NULL)
break;
}
if (i == session_table_count || session_table_count == 0) {
return (rv);
}
goto again;
}
/* See the comment for CRYPTO_PRE_APPROVED_LIMIT. */
sp->sd_pre_approved_amount = 0;
} else {
}
*session_index = i;
return (CRYPTO_SUCCESS);
}
/*
* Close a session.
*/
static int
{
return (CRYPTO_FAILED);
}
if ((session_index) == 0 ||
return (CRYPTO_SESSION_HANDLE_INVALID);
}
return (CRYPTO_SESSION_HANDLE_INVALID);
}
/*
* If session is in use, free it when the thread
* finishes with the session.
*/
} else {
(void) crypto_free_find_ctx(sp);
}
}
return (CRYPTO_SUCCESS);
}
/*
* This ioctl opens a session and returns the session ID in os_session.
*/
/* ARGSUSED */
static int
{
int rv;
return (EFAULT);
if (rv != CRYPTO_SUCCESS) {
return (EFAULT);
}
return (0);
}
return (EFAULT);
}
return (0);
}
/*
* This ioctl closes a session.
*/
/* ARGSUSED */
static int
{
int rv;
return (EFAULT);
return (EFAULT);
}
return (0);
}
/*
* Copy data model dependent mechanism structure into a kernel mechanism
* structure. Allocate param storage if necessary.
*/
static boolean_t
{
int error = 0;
int rv = 0;
out_mech->cm_param_len = 0;
if (param_len > crypto_max_buffer_len) {
"%ld bytes, pid = %d", crypto_max_buffer_len,
goto out;
}
if (rv != CRYPTO_SUCCESS) {
goto out;
}
goto out;
}
}
out:
}
/*
* Free key attributes when key type is CRYPTO_KEY_ATTR_LIST.
* The crypto_key structure is not freed.
*/
static void
{
int i;
return;
/* compute the size of the container */
/* total up the size of all attributes in the container */
if (attrs->oa_value_len != 0 &&
}
}
}
/*
* Frees allocated storage in the key structure, but doesn't free
* the key structure.
*/
static void
{
case CRYPTO_KEY_RAW: {
break;
break;
}
case CRYPTO_KEY_ATTR_LIST:
break;
default:
break;
}
}
/*
* Copy in an array of crypto_object_attribute structures from user-space.
* Kernel memory is allocated for the array and the value of each attribute
* in the array. Since unprivileged users can specify the size of attributes,
* the amount of memory needed is charged against the
* project.max-crypto-memory resource control.
*
* Attribute values are copied in from user-space if copyin_value is set to
* B_TRUE. This routine returns B_TRUE if the copyin was successful.
*/
static boolean_t
{
int error = 0;
int rv = 0;
int i;
if (count == 0) {
rv = CRYPTO_SUCCESS;
goto out;
}
if (count > CRYPTO_MAX_ATTRIBUTE_COUNT) {
goto out;
}
/* compute size of crypto_object_attribute array */
/* this allocation is not charged against the user's resource limit */
goto out;
}
/* figure out how much memory to allocate for all of the attributes */
for (i = 0; i < count; i++) {
sizeof (caddr_t));
if (tmp_len > crypto_max_buffer_len) {
"than %ld bytes, pid = %d", crypto_max_buffer_len,
goto out;
}
}
if (rv != CRYPTO_SUCCESS) {
goto out;
}
/* one big allocation for everything */
p = k_attrs_buf;
for (i = 0; i < count; i++) {
goto out;
}
}
} else {
}
}
out:
/*
* Free the array if there is a failure or the caller
* doesn't want the array to be returned.
*/
}
}
if (u_attrs_out != NULL)
*u_attrs_out = attrs;
if (k_attrs_size_out != NULL)
*k_attrs_out = k_attrs;
}
/*
* Copy data model dependent raw key into a kernel key
* structure. Checks key length or attribute lengths against
* resource controls before allocating memory. Returns B_TRUE
* if both error and rv are set to 0.
*/
static boolean_t
{
int count;
int error = 0;
case CRYPTO_KEY_RAW:
if (key_bits != 0) {
if (key_bits >
"than %ld bytes, pid = %d",
goto out;
}
*out_rctl_chk);
if (rv != CRYPTO_SUCCESS) {
goto out;
}
goto out;
}
}
break;
case CRYPTO_KEY_ATTR_LIST:
} else {
}
break;
case CRYPTO_KEY_REFERENCE:
break;
default:
}
out:
}
/*
* This routine does two things:
* 1. Given a crypto_minor structure and a session ID, it returns
* a valid session pointer.
* 2. It checks that the provider, to which the session has been opened,
* has not been removed.
*/
static boolean_t
{
int error = 0;
if ((i < cm->cm_session_table_count) &&
goto out;
}
}
goto out;
}
goto out;
}
rv = CRYPTO_SUCCESS;
} else {
}
out:
*session_ptr = sp;
}
mutex_enter(&((s)->sd_lock)); \
(s)->sd_flags &= ~CRYPTO_SESSION_IS_BUSY; \
cv_broadcast(&(s)->sd_cv); \
mutex_exit(&((s)->sd_lock)); \
}
/* ARGSUSED */
static int
{
}
/* ARGSUSED */
static int
{
}
/*
* umech is a mechanism structure that has been copied from user address
* space into kernel address space. Only one copyin has been done.
* The mechanism parameter, if non-null, still points to user address space.
* If the mechanism parameter contains pointers, they are pointers into
* user address space.
*
* kmech is a umech with all pointers and structures in kernel address space.
*
* This routine calls the provider's entry point to copy a umech parameter
* into kernel address space. Kernel memory is allocated by the provider.
*/
static int
{
int rv;
/* get the provider's mech number */
kmech->cm_param_len = 0;
return (rv);
}
/*
* umech is a mechanism structure that has been copied from user address
* space into kernel address space. Only one copyin has been done.
* The mechanism parameter, if non-null, still points to user address space.
* If the mechanism parameter contains pointers, they are pointers into
* user address space.
*
* kmech is a umech with all pointers and structures in kernel address space.
*
* This routine calls the provider's entry point to copy a kmech parameter
* into user address space using umech as a template containing
* user address pointers.
*/
static int
{
int rv;
/* get the provider's mech number */
return (rv);
}
/*
* Call the provider's entry point to free kernel memory that has been
* allocated for the mechanism's parameter.
*/
static void
{
if (allocated_by_crypto_module) {
} else {
/* get the provider's mech number */
}
}
}
/*
* ASSUMPTION: crypto_encrypt_init and crypto_decrypt_init
* structures are identical except for field names.
*/
static int
{
int error = 0;
int rv;
return (ENXIO);
}
STRUCT_SIZE(encrypt_init)) != 0) {
return (EFAULT);
}
goto out;
}
sizeof (crypto_mech_type_t));
if (init == crypto_encrypt_init_prov) {
} else {
}
/* We need the key length for provider selection so copy it in now. */
goto out;
}
!= CRYPTO_SUCCESS) {
goto out;
}
if (rv == CRYPTO_NOT_SUPPORTED) {
goto out;
}
} else {
if (rv != CRYPTO_SUCCESS)
goto out;
}
/*
* Check if a context already exists. If so, it means it is being
* abandoned. So, cancel it to avoid leaking it.
*/
out:
if (real_provider != NULL) {
}
if (error != 0)
/* XXX free context */
return (error);
STRUCT_SIZE(encrypt_init)) != 0) {
/* XXX free context */
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
}
/* ARGSUSED */
static int
{
}
/*
* ASSUMPTION: crypto_encrypt and crypto_decrypt structures
* are identical except for field names.
*/
static int
{
char *encrbuf;
int error = 0;
int rv;
return (ENXIO);
}
return (EFAULT);
}
/*
* Don't allocate output buffer unless both buffer pointer and
* buffer length are not NULL or 0 (length).
*/
encrlen = 0;
}
if (datalen > crypto_max_buffer_len ||
goto release_minor;
}
goto release_minor;
}
CRYPTO_INPLACE_OPERATION) != 0;
need = 0;
goto release_minor;
}
goto release_minor;
}
if (do_inplace) {
/* set out = in for in-place */
} else {
}
if (do_inplace)
/* specify in-place buffers with output = NULL */
else
if (KCF_CONTEXT_DONE(rv))
if (rv == CRYPTO_SUCCESS) {
goto release_minor;
}
}
if (rv == CRYPTO_BUFFER_TOO_SMALL) {
/*
* The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
* of section 11.2 of the pkcs11 spec. We catch it here and
* provide the correct pkcs11 return value.
*/
rv = CRYPTO_SUCCESS;
}
if (error != 0)
return (error);
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
}
/* ARGSUSED */
static int
{
}
/*
* ASSUMPTION: crypto_encrypt_update and crypto_decrypt_update
* structures are identical except for field names.
*/
static int
{
char *encrbuf;
int error = 0;
int rv;
return (ENXIO);
}
STRUCT_SIZE(encrypt_update)) != 0) {
return (EFAULT);
}
/*
* Don't allocate output buffer unless both buffer pointer and
* buffer length are not NULL or 0 (length).
*/
encrlen = 0;
}
if (datalen > crypto_max_buffer_len ||
goto out;
}
goto out;
}
CRYPTO_INPLACE_OPERATION) != 0;
need = 0;
goto out;
}
goto out;
}
if (do_inplace) {
/* specify in-place buffers with output = input */
} else {
}
if (do_inplace)
/* specify in-place buffers with output = NULL */
else
if (rv == CRYPTO_SUCCESS) {
goto out;
}
} else {
/*
* The providers return CRYPTO_BUFFER_TOO_SMALL even
* for case 1 of section 11.2 of the pkcs11 spec.
* We catch it here and provide the correct pkcs11
* return value.
*/
rv = CRYPTO_SUCCESS;
}
} else {
}
out:
if (error != 0)
return (error);
STRUCT_SIZE(encrypt_update)) != 0) {
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
}
/* ARGSUSED */
static int
{
}
/*
* ASSUMPTION: crypto_encrypt_final, crypto_decrypt_final, crypto_sign_final,
* and crypto_digest_final structures are identical except for field names.
*/
static int
{
char *encrbuf;
int error = 0;
int rv;
return (ENXIO);
}
STRUCT_SIZE(encrypt_final)) != 0) {
return (EFAULT);
}
/*
* Don't allocate output buffer unless both buffer pointer and
* buffer length are not NULL or 0 (length).
*/
encrlen = 0;
}
if (encrlen > crypto_max_buffer_len) {
goto release_minor;
}
goto release_minor;
}
goto release_minor;
}
final == crypto_digest_final);
if (final == crypto_encrypt_final) {
} else if (final == crypto_decrypt_final) {
} else if (final == crypto_sign_final) {
} else {
}
if (KCF_CONTEXT_DONE(rv))
if (rv == CRYPTO_SUCCESS) {
goto release_minor;
}
}
if (rv == CRYPTO_BUFFER_TOO_SMALL) {
/*
* The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
* of section 11.2 of the pkcs11 spec. We catch it here and
* provide the correct pkcs11 return value.
*/
rv = CRYPTO_SUCCESS;
}
if (error != 0)
return (error);
STRUCT_SIZE(encrypt_final)) != 0) {
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
int error = 0;
int rv;
return (ENXIO);
}
STRUCT_SIZE(digest_init)) != 0) {
return (EFAULT);
}
goto out;
}
goto out;
}
CRYPTO_FG_DIGEST)) != CRYPTO_SUCCESS) {
goto out;
}
/*
* Check if a context already exists. If so, it means it is being
* abandoned. So, cancel it to avoid leaking it.
*/
out:
if (real_provider != NULL)
if (error != 0)
return (error);
STRUCT_SIZE(digest_init)) != 0) {
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
int error = 0;
int rv;
return (ENXIO);
}
STRUCT_SIZE(digest_update)) != 0) {
return (EFAULT);
}
if (datalen > crypto_max_buffer_len) {
goto release_minor;
}
goto release_minor;
}
goto release_minor;
}
goto release_minor;
}
if (rv != CRYPTO_SUCCESS)
if (error != 0)
return (error);
STRUCT_SIZE(digest_update)) != 0) {
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
int error = 0;
int rv;
return (ENXIO);
}
return (EFAULT);
}
goto out;
}
goto out;
}
if (rv != CRYPTO_SUCCESS)
out:
if (error != 0)
return (error);
STRUCT_SIZE(digest_key)) != 0) {
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
}
/* ARGSUSED */
static int
{
}
/*
* ASSUMPTION: crypto_digest, crypto_sign, crypto_sign_recover,
* and crypto_verify_recover are identical except for field names.
*/
static int
{
char *digestbuf;
int error = 0;
int rv;
return (ENXIO);
}
STRUCT_SIZE(crypto_digest)) != 0) {
return (EFAULT);
}
/*
* Don't allocate output buffer unless both buffer pointer and
* buffer length are not NULL or 0 (length).
*/
digestlen = 0;
}
if (datalen > crypto_max_buffer_len ||
goto release_minor;
}
goto release_minor;
}
need = 0;
goto release_minor;
}
goto release_minor;
}
single == crypto_sign_single ||
if (single == crypto_digest_single) {
} else if (single == crypto_sign_single) {
} else if (single == crypto_verify_recover_single) {
} else {
}
if (KCF_CONTEXT_DONE(rv))
if (rv == CRYPTO_SUCCESS) {
goto release_minor;
}
}
if (rv == CRYPTO_BUFFER_TOO_SMALL) {
/*
* The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
* of section 11.2 of the pkcs11 spec. We catch it here and
* provide the correct pkcs11 return value.
*/
rv = CRYPTO_SUCCESS;
}
if (error != 0)
return (error);
STRUCT_SIZE(crypto_digest)) != 0) {
return (EFAULT);
}
return (0);
}
/*
* A helper function that does what the name suggests.
* Returns 0 on success and non-zero otherwise.
* On failure, out_pin is set to 0.
*/
int
{
if (pin_len > KCF_MAX_PIN_LEN) {
goto out;
}
goto out;
}
out:
}
/* ARGSUSED */
static int
{
int error = 0;
int rv;
return (ENXIO);
}
STRUCT_SIZE(set_pin)) != 0) {
return (EFAULT);
}
goto release_minor;
if (new_pin_len > KCF_MAX_PIN_LEN) {
goto out;
}
new_pin, new_pin_len) != 0) {
goto out;
}
if ((rv = kcf_get_hardware_provider_nomech(
goto out;
}
out:
}
}
if (error != 0)
return (error);
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
char *pin;
int error = 0;
int rv;
return (ENXIO);
}
return (EFAULT);
}
if (rv == CRYPTO_PIN_LEN_RANGE)
goto release_minor;
}
if ((rv = kcf_get_hardware_provider_nomech(
&real_provider)) != CRYPTO_SUCCESS) {
goto out;
}
out:
}
if (error != 0)
return (error);
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
int error = 0;
int rv;
return (ENXIO);
}
return (EFAULT);
}
goto release_minor;
}
if ((rv = kcf_get_hardware_provider_nomech(
&real_provider)) != CRYPTO_SUCCESS) {
goto out;
}
out:
if (error != 0)
return (error);
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
}
/* ARGSUSED */
static int
{
}
/* ARGSUSED */
static int
{
}
/* ARGSUSED */
static int
{
}
/*
* ASSUMPTION: crypto_sign_init, crypto_verify_init, crypto_sign_recover_init,
* and crypto_verify_recover_init structures are identical
* except for field names.
*/
static int
{
int error = 0;
int rv;
return (ENXIO);
}
return (EFAULT);
}
goto out;
}
sizeof (crypto_mech_type_t));
init == crypto_verify_init_prov ||
if (init == crypto_sign_init_prov) {
fg = CRYPTO_FG_SIGN;
} else if (init == crypto_verify_init_prov) {
} else if (init == crypto_sign_recover_init_prov) {
} else {
}
/* We need the key length for provider selection so copy it in now. */
goto out;
}
fg)) != CRYPTO_SUCCESS) {
goto out;
}
if (rv == CRYPTO_NOT_SUPPORTED) {
goto out;
}
} else {
if (rv != CRYPTO_SUCCESS)
goto out;
}
/*
* Check if a context already exists. If so, it means it is being
* abandoned. So, cancel it to avoid leaking it.
*/
out:
if (real_provider != NULL) {
}
if (error != 0)
return (error);
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
}
/* ARGSUSED */
static int
{
}
/* ARGSUSED */
static int
{
int error = 0;
int rv;
return (ENXIO);
}
return (EFAULT);
}
if (datalen > crypto_max_buffer_len ||
goto release_minor;
}
goto release_minor;
}
need = 0;
goto release_minor;
}
goto release_minor;
}
goto release_minor;
}
if (KCF_CONTEXT_DONE(rv))
if (error != 0)
return (error);
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
}
/* ARGSUSED */
static int
{
}
/* ARGSUSED */
static int
{
}
/*
* ASSUMPTION: crypto_sign_update and crypto_verify_update structures
* are identical except for field names.
*/
static int
{
int error = 0;
int rv;
return (ENXIO);
}
STRUCT_SIZE(sign_update)) != 0) {
return (EFAULT);
}
if (datalen > crypto_max_buffer_len) {
goto release_minor;
}
goto release_minor;
}
goto release_minor;
}
goto release_minor;
}
if (rv != CRYPTO_SUCCESS)
if (error != 0)
return (error);
STRUCT_SIZE(sign_update)) != 0) {
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
}
/*
* Can't use the common final because it does a copyout of
* the final part.
*/
/* ARGSUSED */
static int
{
int error = 0;
int rv;
return (ENXIO);
}
STRUCT_SIZE(verify_final)) != 0) {
return (EFAULT);
}
if (signlen > crypto_max_buffer_len) {
goto release_minor;
}
goto release_minor;
}
goto release_minor;
}
goto release_minor;
}
if (KCF_CONTEXT_DONE(rv))
if (error != 0)
return (error);
STRUCT_SIZE(verify_final)) != 0) {
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
int error = 0;
int rv;
return (ENXIO);
}
STRUCT_SIZE(seed_random)) != 0) {
return (EFAULT);
}
if (seed_len > crypto_max_buffer_len) {
goto release_minor;
}
goto release_minor;
}
goto release_minor;
}
seed_buffer, seed_len) != 0) {
goto release_minor;
}
if ((rv = kcf_get_hardware_provider_nomech(
goto release_minor;
}
if (real_provider != NULL)
if (seed_buffer != NULL)
if (error != 0)
return (error);
STRUCT_SIZE(seed_random)) != 0) {
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
int error = 0;
int rv;
return (ENXIO);
}
STRUCT_SIZE(generate_random)) != 0) {
return (EFAULT);
}
if (len > crypto_max_buffer_len) {
goto release_minor;
}
goto release_minor;
}
goto release_minor;
}
if ((rv = kcf_get_hardware_provider_nomech(
&real_provider)) != CRYPTO_SUCCESS) {
goto release_minor;
}
if (rv == CRYPTO_SUCCESS) {
}
}
if (real_provider != NULL)
/* random numbers are often used to create keys */
}
if (error != 0)
return (error);
STRUCT_SIZE(generate_random)) != 0) {
return (EFAULT);
}
return (0);
}
/*
* Copyout a kernel array of attributes to user space.
* u_attrs is the corresponding user space array containing
* user space pointers necessary for the copyout.
*/
/* ARGSUSED */
static int
{
int i;
int error = 0;
if (count == 0)
return (0);
p = u_attrs;
for (i = 0; i < count; i++) {
/* can this bcopy be eliminated? */
goto out;
}
}
p += STRUCT_SIZE(oa);
}
}
out:
return (error);
}
/* ARGSUSED */
static int
{
int error = 0;
int rv;
return (ENXIO);
}
STRUCT_SIZE(object_create)) != 0) {
return (EFAULT);
}
goto release_minor;
}
goto release_minor;
}
if ((rv = kcf_get_hardware_provider_nomech(
&real_provider)) != CRYPTO_SUCCESS) {
goto release_minor;
}
if (rv == CRYPTO_SUCCESS)
if (error != 0)
goto out;
STRUCT_SIZE(object_create)) != 0) {
if (rv == CRYPTO_SUCCESS) {
}
}
out:
if (real_provider != NULL)
return (error);
}
/* ARGSUSED */
static int
{
int error = 0;
int rv;
return (ENXIO);
}
STRUCT_SIZE(object_copy)) != 0) {
return (EFAULT);
}
goto release_minor;
}
goto release_minor;
}
if ((rv = kcf_get_hardware_provider_nomech(
&real_provider)) != CRYPTO_SUCCESS) {
goto release_minor;
}
if (rv == CRYPTO_SUCCESS)
if (error != 0)
goto out;
STRUCT_SIZE(object_copy)) != 0) {
if (rv == CRYPTO_SUCCESS) {
}
}
out:
if (real_provider != NULL)
return (error);
}
/* ARGSUSED */
static int
{
int error = 0;
int rv;
return (ENXIO);
}
STRUCT_SIZE(object_destroy)) != 0) {
return (EFAULT);
}
goto release_minor;
}
if ((rv = kcf_get_hardware_provider_nomech(
&real_provider)) != CRYPTO_SUCCESS) {
goto out;
}
out:
if (error != 0)
return (error);
STRUCT_SIZE(object_destroy)) != 0) {
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
#ifdef _LP64
#else
/* LINTED E_FUNC_SET_NOT_USED */
#endif
int error = 0;
int rv;
"object_get_attribute_value: failed holding minor");
return (ENXIO);
}
STRUCT_SIZE(get_attribute_value)) != 0) {
return (EFAULT);
}
goto release_minor;
}
goto release_minor;
}
if ((rv = kcf_get_hardware_provider_nomech(
goto out;
}
out:
rv == CRYPTO_BUFFER_TOO_SMALL) {
}
if (error != 0)
return (error);
STRUCT_SIZE(get_attribute_value)) != 0) {
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
int error = 0;
int rv;
return (ENXIO);
}
STRUCT_SIZE(object_get_size)) != 0) {
return (EFAULT);
}
goto release_minor;
}
if ((rv = kcf_get_hardware_provider_nomech(
goto release_minor;
}
if (rv == CRYPTO_SUCCESS) {
}
if (error != 0)
return (error);
STRUCT_SIZE(object_get_size)) != 0) {
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
int error = 0;
int rv;
"object_set_attribute_value: failed holding minor");
return (ENXIO);
}
STRUCT_SIZE(set_attribute_value)) != 0) {
return (EFAULT);
}
goto release_minor;
}
goto release_minor;
}
if ((rv = kcf_get_hardware_provider_nomech(
goto release_minor;
}
if (error != 0)
return (error);
STRUCT_SIZE(set_attribute_value)) != 0) {
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
int error = 0;
int rv;
void *cookie;
return (ENXIO);
}
return (EFAULT);
}
goto release_minor;
}
goto release_minor;
}
if ((rv = kcf_get_hardware_provider_nomech(
goto release_minor;
}
/* check for an active find */
goto release_minor;
}
if (rv == CRYPTO_SUCCESS) {
/*
* The cookie is allocated by a provider at the start of an
* object search. It is freed when the search is terminated
* by a final operation, or when the session is closed.
* It contains state information about which object handles
* have been returned to the caller.
*/
}
if (real_provider != NULL)
if (error != 0)
return (error);
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
return (ENXIO);
}
STRUCT_SIZE(find_update)) != 0) {
return (EFAULT);
}
if (max_count > CRYPTO_MAX_FIND_COUNT) {
goto release_minor;
}
goto release_minor;
}
goto release_minor;
}
rctl_bytes = len;
if ((rv = kcf_get_hardware_provider_nomech(
&real_provider)) != CRYPTO_SUCCESS) {
goto release_minor;
}
if (rv == CRYPTO_SUCCESS) {
/* bad bad provider */
rv = CRYPTO_FAILED;
goto release_minor;
}
if (count != 0) {
/* copyout handles */
count * sizeof (crypto_object_id_t)) != 0) {
}
}
}
if (error != 0)
return (error);
STRUCT_SIZE(find_update)) != 0) {
return (EFAULT);
}
return (0);
}
/*
* Free provider-allocated storage used for find object searches.
*/
static int
{
int rv;
if ((rv = kcf_get_hardware_provider_nomech(
return (rv);
}
return (rv);
}
/* ARGSUSED */
static int
{
int error = 0;
int rv;
return (ENXIO);
}
STRUCT_SIZE(object_find_final)) != 0) {
return (EFAULT);
}
goto release_minor;
}
}
if (error != 0)
return (error);
STRUCT_SIZE(object_find_final)) != 0) {
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
int error = 0;
int rv;
return (ENXIO);
}
STRUCT_SIZE(generate_key)) != 0) {
return (EFAULT);
}
goto release_minor;
}
sizeof (crypto_mech_type_t));
goto release_minor;
}
if (rv == CRYPTO_NOT_SUPPORTED) {
goto release_minor;
}
} else {
if (rv != CRYPTO_SUCCESS)
goto release_minor;
}
&key_rctl_chk, B_TRUE)) {
goto release_minor;
}
if (rv == CRYPTO_SUCCESS)
if (error != 0)
goto out;
STRUCT_SIZE(generate_key)) != 0) {
if (rv == CRYPTO_SUCCESS) {
}
}
out:
if (real_provider != NULL) {
}
return (error);
}
/* ARGSUSED */
static int
{
#ifdef _LP64
#else
/* LINTED E_FUNC_SET_NOT_USED */
#endif
int error = 0;
int rv;
return (ENXIO);
}
STRUCT_SIZE(generate_key)) != 0) {
return (EFAULT);
}
goto release_minor;
}
sizeof (crypto_mech_type_t));
goto release_minor;
}
if (rv == CRYPTO_NOT_SUPPORTED) {
goto release_minor;
}
} else {
if (rv != CRYPTO_SUCCESS)
goto release_minor;
}
&in_key_rctl_chk, B_TRUE)) {
goto release_minor;
}
&out_key_rctl_chk, B_FALSE)) {
goto release_minor;
}
if (rv == CRYPTO_SUCCESS) {
}
if (k_in_attrs != NULL)
if (k_out_attrs != NULL) {
}
if (error != 0)
goto out;
STRUCT_SIZE(generate_key)) != 0) {
}
out:
if (real_provider != NULL) {
}
return (error);
}
/* ARGSUSED */
static int
{
int error = 0;
int rv;
"object_generate_key_pair: failed holding minor");
return (ENXIO);
}
STRUCT_SIZE(generate_key_pair)) != 0) {
return (EFAULT);
}
goto release_minor;
}
sizeof (crypto_mech_type_t));
goto release_minor;
}
if (rv == CRYPTO_NOT_SUPPORTED) {
goto release_minor;
}
} else {
if (rv != CRYPTO_SUCCESS)
goto release_minor;
}
&pub_rctl_chk, B_TRUE)) {
goto release_minor;
}
goto release_minor;
}
if (rv == CRYPTO_SUCCESS) {
}
if (k_pub_attrs != NULL)
if (k_pri_attrs != NULL)
if (error != 0)
goto out;
STRUCT_SIZE(generate_key_pair)) != 0) {
if (rv == CRYPTO_SUCCESS) {
}
}
out:
if (real_provider != NULL) {
}
return (error);
}
/* ARGSUSED */
static int
{
#ifdef _LP64
#else
/* LINTED E_FUNC_SET_NOT_USED */
#endif
int error = 0;
int rv;
"nostore_generate_key_pair: failed holding minor");
return (ENXIO);
}
STRUCT_SIZE(generate_key_pair)) != 0) {
return (EFAULT);
}
goto release_minor;
}
sizeof (crypto_mech_type_t));
goto release_minor;
}
&error);
if (rv == CRYPTO_NOT_SUPPORTED) {
goto release_minor;
}
} else {
if (rv != CRYPTO_SUCCESS)
goto release_minor;
}
goto release_minor;
}
goto release_minor;
}
goto release_minor;
}
goto release_minor;
}
if (rv == CRYPTO_SUCCESS) {
if (error != CRYPTO_SUCCESS)
goto release_minor;
}
if (k_in_pub_attrs != NULL)
if (k_in_pri_attrs != NULL)
if (k_out_pub_attrs != NULL)
if (k_out_pri_attrs != NULL) {
}
if (u_pub_attrs != NULL)
if (u_pri_attrs != NULL)
if (error != 0)
goto out;
STRUCT_SIZE(generate_key_pair)) != 0) {
}
out:
if (real_provider != NULL) {
}
return (error);
}
/* ARGSUSED */
static int
{
char *wrapped_key_buffer;
int error = 0;
int rv;
return (ENXIO);
}
return (EFAULT);
}
goto out;
}
sizeof (crypto_mech_type_t));
/* We need the key length for provider selection so copy it in now. */
goto out;
}
goto out;
}
if (rv == CRYPTO_NOT_SUPPORTED) {
goto out;
}
} else {
if (rv != CRYPTO_SUCCESS)
goto out;
}
/*
* Don't allocate output buffer unless both buffer pointer and
* buffer length are not NULL or 0 (length).
*/
wrapped_key_len = 0;
}
if (wrapped_key_len > crypto_max_buffer_len) {
goto out;
}
wrapped_key_rctl_chk)) != CRYPTO_SUCCESS) {
goto out;
}
/* new_wrapped_key_len can be modified by the provider */
if (rv == CRYPTO_SUCCESS) {
wrapped_key_buffer, new_wrapped_key_len) != 0) {
}
}
if (rv == CRYPTO_BUFFER_TOO_SMALL) {
/*
* The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
* of section 11.2 of the pkcs11 spec. We catch it here and
* provide the correct pkcs11 return value.
*/
rv = CRYPTO_SUCCESS;
}
out:
if (real_provider != NULL) {
}
if (wrapped_key != NULL)
if (error != 0)
return (error);
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
int error = 0;
int rv;
return (ENXIO);
}
return (EFAULT);
}
goto release_minor;
}
sizeof (crypto_mech_type_t));
/* We need the key length for provider selection so copy it in now. */
goto release_minor;
}
goto release_minor;
}
if (rv == CRYPTO_NOT_SUPPORTED) {
goto release_minor;
}
} else {
if (rv != CRYPTO_SUCCESS)
goto release_minor;
}
&k_attrs_rctl_chk, B_TRUE)) {
goto release_minor;
}
if (wrapped_key_len > crypto_max_buffer_len) {
goto release_minor;
}
wrapped_key_rctl_chk)) != CRYPTO_SUCCESS) {
goto release_minor;
}
goto release_minor;
}
/* wrapped_key_len is not modified by the unwrap operation */
if (rv == CRYPTO_SUCCESS)
if (wrapped_key != NULL)
if (error != 0)
goto out;
STRUCT_SIZE(unwrap_key)) != 0) {
if (rv == CRYPTO_SUCCESS) {
}
}
out:
if (real_provider != NULL) {
}
return (error);
}
/* ARGSUSED */
static int
{
int error = 0;
int rv;
return (ENXIO);
}
return (EFAULT);
}
goto release_minor;
}
sizeof (crypto_mech_type_t));
/* We need the key length for provider selection so copy it in now. */
goto release_minor;
}
goto release_minor;
}
if (rv == CRYPTO_NOT_SUPPORTED) {
goto release_minor;
}
} else {
if (rv != CRYPTO_SUCCESS)
goto release_minor;
}
goto release_minor;
}
if (rv == CRYPTO_SUCCESS) {
if (rv == CRYPTO_NOT_SUPPORTED) {
rv = CRYPTO_SUCCESS;
goto release_minor;
}
if (rv != CRYPTO_SUCCESS)
}
if (error != 0)
goto out;
STRUCT_SIZE(derive_key)) != 0) {
if (rv == CRYPTO_SUCCESS) {
}
}
out:
if (please_destroy_object) {
}
if (real_provider != NULL) {
}
return (error);
}
/* ARGSUSED */
static int
{
#ifdef _LP64
#else
/* LINTED E_FUNC_SET_NOT_USED */
#endif
int error = 0;
int rv;
return (ENXIO);
}
return (EFAULT);
}
goto release_minor;
}
sizeof (crypto_mech_type_t));
/* We need the key length for provider selection so copy it in now. */
goto release_minor;
}
goto release_minor;
}
if (rv == CRYPTO_NOT_SUPPORTED) {
goto release_minor;
}
} else {
if (rv != CRYPTO_SUCCESS)
goto release_minor;
}
&in_attributes_rctl_chk, B_TRUE)) {
goto release_minor;
}
goto release_minor;
}
if (rv == CRYPTO_SUCCESS) {
if (rv == CRYPTO_NOT_SUPPORTED) {
rv = CRYPTO_SUCCESS;
}
/* copyout the derived secret */
k_out_attrs, u_attrs) != 0)
}
if (k_in_attrs != NULL)
if (k_out_attrs != NULL) {
}
if (error != 0)
goto out;
STRUCT_SIZE(derive_key)) != 0) {
}
out:
if (real_provider != NULL) {
}
return (error);
}
/* ARGSUSED */
static int
int *rval)
{
switch (cmd) {
case CRYPTO_GET_FUNCTION_LIST:
case CRYPTO_GET_PROVIDER_LIST:
case CRYPTO_GET_PROVIDER_INFO:
case CRYPTO_OPEN_SESSION:
case CRYPTO_CLOSE_SESSION:
case CRYPTO_ENCRYPT_INIT:
case CRYPTO_DECRYPT_INIT:
case CRYPTO_ENCRYPT:
case CRYPTO_DECRYPT:
case CRYPTO_ENCRYPT_UPDATE:
case CRYPTO_DECRYPT_UPDATE:
case CRYPTO_ENCRYPT_FINAL:
case CRYPTO_DECRYPT_FINAL:
case CRYPTO_DIGEST_INIT:
case CRYPTO_DIGEST:
case CRYPTO_DIGEST_UPDATE:
case CRYPTO_DIGEST_KEY:
case CRYPTO_DIGEST_FINAL:
case CRYPTO_SIGN_INIT:
case CRYPTO_SIGN:
case CRYPTO_SIGN_UPDATE:
case CRYPTO_SIGN_FINAL:
case CRYPTO_SIGN_RECOVER_INIT:
case CRYPTO_SIGN_RECOVER:
case CRYPTO_VERIFY_INIT:
case CRYPTO_VERIFY:
case CRYPTO_VERIFY_UPDATE:
case CRYPTO_VERIFY_FINAL:
case CRYPTO_VERIFY_RECOVER:
case CRYPTO_SET_PIN:
case CRYPTO_LOGIN:
case CRYPTO_LOGOUT:
case CRYPTO_SEED_RANDOM:
case CRYPTO_GENERATE_RANDOM:
case CRYPTO_OBJECT_CREATE:
case CRYPTO_OBJECT_COPY:
case CRYPTO_OBJECT_DESTROY:
case CRYPTO_OBJECT_GET_SIZE:
case CRYPTO_OBJECT_FIND_INIT:
case CRYPTO_OBJECT_FIND_FINAL:
case CRYPTO_GENERATE_KEY:
case CRYPTO_GENERATE_KEY_PAIR:
case CRYPTO_WRAP_KEY:
case CRYPTO_UNWRAP_KEY:
case CRYPTO_DERIVE_KEY:
}
return (EINVAL);
}
/*
* Check for the project.max-crypto-memory resource control.
*/
static int
{
if (need == 0)
return (CRYPTO_SUCCESS);
return (CRYPTO_HOST_MEMORY);
}
}
return (CRYPTO_SUCCESS);
}