dprov.c revision 5151fb1220e0ceafdc172203863c73da4285c170
/*
* 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
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Dummy Cryptographic Provider:
*
* This file implements a "dummy" cryptographic provider. It is implemented
* as a pseudo device driver.
*
*/
/*
* This driver implements a KEF provider with the following capabilities:
*
* - registration/unregistration with KEF
* - digest entry points
* - mac entry points
* - ctx management
* - support for async requests
* - cipher entry points
* - dual entry points
* - sign entry points
* - verify entry points
* - dual operations entry points
* - session management
* - object management
* - key management
* - provider management
*
* In order to avoid duplicating the implementation of algorithms
* provided by software providers, this pseudo driver acts as
* a consumer of the framework. When invoking one of the framework's
* entry points, the driver specifies the software provider to
* be used for the operation.
*
* User management: we implement a PKCS#11 style provider which supports:
* - one normal user with a PIN, and
* - one SO user with a PIN.
* These values are kept in the per-instance structure, and are initialized
* with the provider management entry points.
*
*/
#include <sys/byteorder.h>
#include <sys/sysmacros.h>
#include <aes/aes_cbc_crypt.h>
#include <des/des_impl.h>
#include <blowfish/blowfish_impl.h>
/*
* Debugging macros.
*/
#ifdef DEBUG
static uint32_t dprov_debug = 0;
#define DPROV_CALL(f, r, x) if (dprov_debug & (f)) { (void) r x; }
#else /* DEBUG */
#define DPROV_DEBUG(f, x)
#define DPROV_CALL(f, r, x)
#endif /* DEBUG */
/*
* DDI entry points.
*/
/*
* Module linkage.
*/
nodev, /* cb_open */
nodev, /* cb_close */
nodev, /* cb_strategy */
nodev, /* cb_print */
nodev, /* cb_dump */
nodev, /* cb_read */
nodev, /* cb_write */
nodev, /* 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 */
dprov_getinfo, /* devo_getinfo */
nulldev, /* devo_identify */
nulldev, /* devo_probe */
dprov_attach, /* devo_attach */
dprov_detach, /* devo_detach */
nodev, /* devo_reset */
&cbops, /* devo_cb_ops */
NULL, /* devo_bus_ops */
NULL, /* devo_power */
};
"Pseudo KCF Prov (drv) %I%",
};
static struct modlcrypto modlcrypto = {
"Pseudo KCF Prov (crypto) %I%"
};
static struct modlinkage modlinkage = {
&modldrv,
};
/*
* CSPI information (entry points, provider info, etc.)
*/
typedef enum dprov_mech_type {
MD4_MECH_INFO_TYPE, /* SUN_CKM_MD4 */
MD5_MECH_INFO_TYPE, /* SUN_CKM_MD5 */
MD5_HMAC_MECH_INFO_TYPE, /* SUN_CKM_MD5_HMAC */
MD5_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_MD5_HMAC_GENERAL */
SHA1_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA1_HMAC */
SHA1_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA1_HMAC_GENERAL */
SHA1_MECH_INFO_TYPE, /* SUN_CKM_SHA1 */
SHA256_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA256_HMAC */
SHA256_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA256_HMAC_GENERAL */
SHA256_MECH_INFO_TYPE, /* SUN_CKM_SHA256 */
SHA384_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA384_HMAC */
SHA384_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA384_HMAC_GENERAL */
SHA384_MECH_INFO_TYPE, /* SUN_CKM_SHA384 */
SHA512_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA512_HMAC */
SHA512_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA512_HMAC_GENERAL */
SHA512_MECH_INFO_TYPE, /* SUN_CKM_SHA512 */
DES_CBC_MECH_INFO_TYPE, /* SUN_CKM_DES_CBC */
DES3_CBC_MECH_INFO_TYPE, /* SUN_CKM_DES3_CBC */
DES_ECB_MECH_INFO_TYPE, /* SUN_CKM_DES_ECB */
DES3_ECB_MECH_INFO_TYPE, /* SUN_CKM_DES3_ECB */
BLOWFISH_CBC_MECH_INFO_TYPE, /* SUN_CKM_BLOWFISH_CBC */
BLOWFISH_ECB_MECH_INFO_TYPE, /* SUN_CKM_BLOWFISH_ECB */
AES_CBC_MECH_INFO_TYPE, /* SUN_CKM_AES_CBC */
AES_ECB_MECH_INFO_TYPE, /* SUN_CKM_AES_ECB */
AES_CTR_MECH_INFO_TYPE, /* SUN_CKM_AES_CTR */
RC4_MECH_INFO_TYPE, /* SUN_CKM_RC4 */
RSA_PKCS_MECH_INFO_TYPE, /* SUN_CKM_RSA_PKCS */
RSA_X_509_MECH_INFO_TYPE, /* SUN_CKM_RSA_X_509 */
MD5_RSA_PKCS_MECH_INFO_TYPE, /* SUN_CKM_MD5_RSA_PKCS */
SHA1_RSA_PKCS_MECH_INFO_TYPE, /* SUN_CKM_SHA1_RSA_PKCS */
SHA256_RSA_PKCS_MECH_INFO_TYPE, /* SUN_CKM_SHA256_RSA_PKCS */
SHA384_RSA_PKCS_MECH_INFO_TYPE, /* SUN_CKM_SHA384_RSA_PKCS */
SHA512_RSA_PKCS_MECH_INFO_TYPE, /* SUN_CKM_SHA512_RSA_PKCS */
MD5_KEY_DERIVATION_MECH_INFO_TYPE, /* SUN_CKM_MD5_KEY_DERIVATION */
SHA1_KEY_DERIVATION_MECH_INFO_TYPE, /* SUN_CKM_SHA1_KEY_DERIVATION */
/* SUN_CKM_SHA256_KEY_DERIVATION */
/* SUN_CKM_SHA384_KEY_DERIVATION */
/* SUN_CKM_SHA512_KEY_DERIVATION */
DES_KEY_GEN_MECH_INFO_TYPE, /* SUN_CKM_DES_KEY_GEN */
DES3_KEY_GEN_MECH_INFO_TYPE, /* SUN_CKM_DES3_KEY_GEN */
AES_KEY_GEN_MECH_INFO_TYPE, /* SUN_CKM_AES_KEY_GEN */
BLOWFISH_KEY_GEN_MECH_INFO_TYPE, /* SUN_CKM_BLOWFISH_KEY_GEN */
RC4_KEY_GEN_MECH_INFO_TYPE, /* SUN_CKM_RC4_KEY_GEN */
RSA_PKCS_KEY_PAIR_GEN_MECH_INFO_TYPE /* SUN_CKM_RSA_PKCS_KEY_PAIR_GEN */
/*
* Mechanism info structure passed to KCF during registration.
*/
#define DPROV_CKM_MD5_KEY_DERIVATION "CKM_MD5_KEY_DERIVATION"
#define DPROV_CKM_SHA1_KEY_DERIVATION "CKM_SHA1_KEY_DERIVATION"
#define DPROV_CKM_SHA256_KEY_DERIVATION "CKM_SHA256_KEY_DERIVATION"
#define DPROV_CKM_SHA384_KEY_DERIVATION "CKM_SHA384_KEY_DERIVATION"
#define DPROV_CKM_SHA512_KEY_DERIVATION "CKM_SHA512_KEY_DERIVATION"
#define DPROV_CKM_DES_KEY_GEN "CKM_DES_KEY_GEN"
#define DPROV_CKM_DES3_KEY_GEN "CKM_DES3_KEY_GEN"
#define DPROV_CKM_AES_KEY_GEN "CKM_AES_KEY_GEN"
#define DPROV_CKM_BLOWFISH_KEY_GEN "CKM_BLOWFISH_KEY_GEN"
#define DPROV_CKM_RC4_KEY_GEN "CKM_RC4_KEY_GEN"
#define DPROV_CKM_RSA_PKCS_KEY_PAIR_GEN "CKM_RSA_PKCS_KEY_PAIR_GEN"
static crypto_mech_info_t dprov_mech_info_tab[] = {
/* MD4 */
CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 0, 0,
/* MD5 */
CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 0, 0,
/* MD5-HMAC */
/* MD5-HMAC GENERAL */
/* SHA1 */
CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 0, 0,
/* SHA1-HMAC */
/* SHA1-HMAC GENERAL */
/* SHA256 */
CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 0, 0,
/* SHA256-HMAC */
/* SHA256-HMAC GENERAL */
/* SHA384 */
CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 0, 0,
/* SHA384-HMAC */
/* SHA384-HMAC GENERAL */
/* SHA512 */
CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 0, 0,
/* SHA512-HMAC */
/* SHA512-HMAC GENERAL */
/* DES-CBC */
/* DES3-CBC */
/* DES-ECB */
/* DES3-ECB */
/* BLOWFISH-CBC */
/* BLOWFISH-ECB */
/* AES-CBC */
/* AES-ECB */
/* AES-CTR */
/* RC4 */
/* RSA_PKCS */
/* RSA_X_509 */
/* MD5_RSA_PKCS */
/* SHA1_RSA_PKCS */
/* SHA256_RSA_PKCS */
/* SHA384_RSA_PKCS */
/* SHA512_RSA_PKCS */
/* MD5_KEY_DERIVATION */
/* SHA1_KEY_DERIVATION */
/* SHA256_KEY_DERIVATION */
/* SHA384_KEY_DERIVATION */
/* SHA512_KEY_DERIVATION */
/* DES_KEY_GENERATION */
/* DES3_KEY_GENERATION */
/* AES_KEY_GENERATION */
/* BLOWFISH_KEY_GENERATION */
/* RC4_KEY_GENERATION */
/* RSA_PKCS_KEY_PAIR_GEN */
};
static crypto_control_ops_t dprov_control_ops = {
};
#define DPROV_MANUFACTURER "SUNW "
#define DPROV_MODEL "dprov "
#define DPROV_ALLSPACES " "
static crypto_digest_ops_t dprov_digest_ops = {
};
static int dprov_mac_verify_atomic(crypto_provider_handle_t,
static crypto_mac_ops_t dprov_mac_ops = {
};
static crypto_cipher_ops_t dprov_cipher_ops = {
};
static int dprov_sign_recover_atomic(crypto_provider_handle_t,
static crypto_sign_ops_t dprov_sign_ops = {
};
static int dprov_verify_recover_atomic(crypto_provider_handle_t,
static crypto_verify_ops_t dprov_verify_ops = {
};
static crypto_dual_ops_t dprov_dual_ops = {
};
static int dprov_encrypt_mac_init(crypto_ctx_t *,
static int dprov_encrypt_mac(crypto_ctx_t *,
static int dprov_encrypt_mac_update(crypto_ctx_t *,
static int dprov_encrypt_mac_final(crypto_ctx_t *,
static int dprov_encrypt_mac_atomic(crypto_provider_handle_t,
static int dprov_mac_decrypt_init(crypto_ctx_t *,
static int dprov_mac_decrypt(crypto_ctx_t *,
static int dprov_mac_decrypt_update(crypto_ctx_t *,
static int dprov_mac_decrypt_final(crypto_ctx_t *,
static int dprov_mac_decrypt_atomic(crypto_provider_handle_t,
static crypto_dual_cipher_mac_ops_t dprov_cipher_mac_ops = {
};
};
static crypto_session_ops_t dprov_session_ops = {
};
crypto_object_attribute_t *, uint_t, void **,
static int dprov_object_find(crypto_provider_handle_t, void *,
static int dprov_object_find_final(crypto_provider_handle_t, void *,
static crypto_object_ops_t dprov_object_ops = {
};
static int dprov_key_generate_pair(crypto_provider_handle_t,
static crypto_key_ops_t dprov_key_ops = {
};
static int dprov_ext_info(crypto_provider_handle_t,
char *, crypto_req_handle_t);
char *, size_t, crypto_req_handle_t);
};
static int dprov_free_context(crypto_ctx_t *);
static int dprov_copyin_mechanism(crypto_provider_handle_t,
static int dprov_copyout_mechanism(crypto_provider_handle_t,
static int dprov_free_mechanism(crypto_provider_handle_t,
static crypto_ctx_ops_t dprov_ctx_ops = {
NULL,
};
static crypto_mech_ops_t dprov_mech_ops = {
};
static crypto_ops_t dprov_crypto_ops = {
};
/* maximum SO and user PIN lengths */
#define DPROV_MAX_PIN_LEN 128
/*
* Objects: each session is associated with an array of objects.
* Unlike PKCS#11, the objects cannot be shared between sessions.
* The ioctl driver multiplexes PKCS#11 sessions to providers
* sessions in order to support this semantic. This simplifies
* the CSPI greatly since the provider does not have to associate
* sessions with a user space process.
* There is also a per-instance array of objects, which correspond
* to PKCS#11 token objects. These objects can be shared by multiple
* sesions.
*
* Token objects are identified by having a CKA_TOKEN attribute B_TRUE.
* Private objects are identified by having a CKA_PRIVATE attribute
* set to B_TRUE.
*/
/* object description */
typedef struct dprov_object {
/* for token objects. */
/* keep object around until all */
/* sessions that refer to it */
/* are closed, but mark it */
/* destroyed so that references */
/* to the object fail. */
/* used for token objects only */
/*
* If a session has a reference to a dprov_object_t,
* it REFHOLD()s.
*/
#define DPROV_OBJECT_REFHOLD(object) { \
}
/*
* Releases a reference to an object. When the last
* reference is released, the object is freed.
*/
#define DPROV_OBJECT_REFRELE(object) { \
membar_exit(); \
}
/*
* Object attributes are passed to the provider using crypto_object_attribute
* structures, which contain the type of the attribute, a pointer to
* it's value, and the length of its value. The attribute types values
* are defined by the PKCS#11 specification. This provider only cares
* about a subset of these attributes. In order to avoid having to
* include the PKCS#11 header files, we define here the attributes values
* which are used by the provider.
*/
#define DPROV_CKA_CLASS 0x00000000
#define DPROV_CKA_TOKEN 0x00000001
#define DPROV_CKA_PRIVATE 0x00000002
#define DPROV_CKA_VALUE 0x00000011
#define DPROV_CKA_CERTIFICATE_TYPE 0x00000080
#define DPROV_CKA_KEY_TYPE 0x00000100
#define DPROV_CKA_ENCRYPT 0x00000104
#define DPROV_CKA_DECRYPT 0x00000105
#define DPROV_CKA_WRAP 0x00000106
#define DPROV_CKA_UNWRAP 0x00000107
#define DPROV_CKA_SIGN 0x00000108
#define DPROV_CKA_SIGN_RECOVER 0x00000109
#define DPROV_CKA_VERIFY 0x0000010A
#define DPROV_CKA_VERIFY_RECOVER 0x0000010B
#define DPROV_CKA_DERIVE 0x0000010C
#define DPROV_CKA_MODULUS 0x00000120
#define DPROV_CKA_MODULUS_BITS 0x00000121
#define DPROV_CKA_PUBLIC_EXPONENT 0x00000122
#define DPROV_CKA_PRIVATE_EXPONENT 0x00000123
#define DPROV_CKA_VALUE_BITS 0x00000160
#define DPROV_CKA_VALUE_LEN 0x00000161
#define DPROV_CKA_EXTRACTABLE 0x00000162
#define DPROV_HW_FEATURE_TYPE 0x00000300
/*
* Object classes from PKCS#11
*/
#define DPROV_CKO_DATA 0x00000000
#define DPROV_CKO_CERTIFICATE 0x00000001
#define DPROV_CKO_PUBLIC_KEY 0x00000002
#define DPROV_CKO_PRIVATE_KEY 0x00000003
#define DPROV_CKO_SECRET_KEY 0x00000004
#define DPROV_CKO_HW_FEATURE 0x00000005
#define DPROV_CKO_DOMAIN_PARAMETERS 0x00000006
#define DPROV_CKO_VENDOR_DEFINED 0x80000000
/*
* A few key types from PKCS#11
*/
#define DPROV_CKK_RSA 0x00000000
#define DPROV_CKK_GENERIC_SECRET 0x00000010
#define DPROV_CKK_RC4 0x00000012
#define DPROV_CKK_DES 0x00000013
#define DPROV_CKK_DES3 0x00000015
#define DPROV_CKK_AES 0x0000001F
#define DPROV_CKK_BLOWFISH 0x00000020
/*
* to store data persistent across calls.
*/
typedef struct dprov_find_ctx {
/*
* Session management: each instance is associated with an array
* of sessions. KEF providers sessions are always R/W the library and
* the ioctl maintain the PKCS#11 R/W attributes for the session.
*/
typedef enum dprov_session_state {
DPROV_SESSION_STATE_PUBLIC, /* public (default) */
DPROV_SESSION_STATE_SO, /* SO logged in */
DPROV_SESSION_STATE_USER /* user logged in */
/* session description */
typedef struct dprov_session {
static crypto_provider_info_t dprov_prov_info = {
"Dummy Pseudo HW Provider",
NULL, /* pi_provider_dev */
NULL, /* pi_provider_handle */
sizeof (dprov_mech_info_tab)/sizeof (crypto_mech_info_t),
0, /* pi_logical_provider_count */
NULL /* pi_logical_providers */
};
/*
* Per-instance info.
*/
typedef struct dprov_state {
/*
* A taskq is associated with each instance of the pseudo driver in order
* to simulate the asynchronous execution of requests.
* The following defines the taskq request structures.
*/
/* request types */
typedef enum dprov_req_type {
/* digest requests */
/* cipher requests */
/* mac requests */
/* sign requests */
/* verify requests */
/* dual ops requests */
/* random number ops */
/* session management requests */
/* object management requests */
/* key management requests */
/* provider management requests */
/* for DPROV_REQ_DIGEST requests */
typedef struct dprov_digest_req {
/* for DPROV_REQ_MAC requests */
typedef struct dprov_mac_req {
/* for DPROV_REQ_ENCRYPT and DPROV_REQ_DECRYPT requests */
typedef struct dprov_cipher_req {
/* for DPROV_REQ_SIGN requests */
typedef struct dprov_sign_req {
/* for DPROV_REQ_VERIFY requests */
typedef struct dprov_verify_req {
/* for dual ops requests */
typedef struct dprov_dual_req {
typedef struct dprov_cipher_mac_req {
/* for DPROV_REQ_RANDOM requests */
typedef struct dprov_random_req {
/* for DPROV_REQ_SESSION requests */
typedef struct dprov_session_req {
char *sr_pin;
/* for DPROV_REQ_OBJECT requests */
typedef struct dprov_object_req {
void **or_find_pp;
void *or_find_p;
/* for DPROV_REQ_KEY requests */
typedef struct dprov_key_req {
/* for DPROV_REQ_MGMT requests */
typedef struct dprov_mgmt_req {
char *mr_pin;
char *mr_old_pin;
char *mr_label;
/* request, as queued on taskq */
typedef struct dprov_req {
union {
} dr_req;
} dprov_req_t;
/* shortcuts for union fields */
/* prototypes for the tasq dispatcher functions */
static void dprov_digest_task(dprov_req_t *);
static void dprov_mac_task(dprov_req_t *);
static void dprov_sign_task(dprov_req_t *);
static void dprov_verify_task(dprov_req_t *);
static void dprov_dual_task(dprov_req_t *);
static void dprov_cipher_task(dprov_req_t *);
static void dprov_cipher_mac_task(dprov_req_t *);
static void dprov_random_task(dprov_req_t *);
static void dprov_session_task(dprov_req_t *);
static void dprov_object_task(dprov_req_t *);
static void dprov_key_task(dprov_req_t *);
static void dprov_mgmt_task(dprov_req_t *);
/* helper functions */
crypto_data_t *, crypto_ctx_t *, int);
crypto_data_t *);
uint32_t);
crypto_user_type_t, char *, size_t);
char *, crypto_provider_ext_info_t *);
/* object management helper functions */
static void dprov_free_object(dprov_object_t *);
static void dprov_release_session_objects(dprov_session_t *);
boolean_t *);
size_t *);
size_t *);
static int dprov_get_template_attr_boolean(crypto_object_attribute_t *,
uint64_t);
/* retrieve the softc and instance number from a SPI crypto context */
}
/* retrieve the softc and instance number from a taskq request */
}
/*
* The dprov private context most of the time contains a pointer to the
* crypto_context_t that was allocated when calling a KCF function.
* to maintain the contexts associated with the separate cipher
* and mac operations. These two types of dprov contexts are
* defined below.
*/
typedef enum dprov_ctx_type {
/*
* When the context refers to a single KCF context, the
* cc_provider field of a crypto_ctx_t points to a structure of
* type dprov_ctx_single.
*/
typedef struct dprov_ctx_single {
/*
* pointers to to KCF contexts, one for the cipher operation, the
* other for the mac operation.
*/
typedef struct dprov_ctx_dual {
/*
* Helper macros for context accessors. These macros return the
* k-API context corresponding to the given SPI context for
*/
#define DPROV_CTX_SINGLE(_ctx) \
#define DPROV_CTX_DUAL_CIPHER(_ctx) \
#define DPROV_CTX_DUAL_MAC(_ctx) \
static void *statep; /* state pointer */
/*
* DDI entry points.
*/
int
_init(void)
{
int error;
0)) != 0)
return (error);
return (mod_install(&modlinkage));
}
int
_fini(void)
{
int error;
return (error);
return (0);
}
int
{
}
/* ARGSUSED */
static int
{
instance));
switch (cmd) {
case DDI_INFO_DEVT2DEVINFO:
return (DDI_SUCCESS);
case DDI_INFO_DEVT2INSTANCE:
return (DDI_SUCCESS);
}
return (DDI_FAILURE);
}
static int
{
char devname[256];
int ret;
instance));
if (cmd != DDI_ATTACH) {
return (DDI_FAILURE);
}
/* get new softc and initialize it */
return (DDI_FAILURE);
/* create minor node */
DDI_PSEUDO, 0) != DDI_SUCCESS) {
return (DDI_FAILURE);
}
/* create taskq */
/* initialize table of sessions */
sizeof (dprov_session_t *), KM_SLEEP);
softc->ds_sessions_count = 0;
/* initialized done by init_token entry point */
/* register with the crypto framework */
"dprov crypto_register_provider() failed (0x%x)", ret);
sizeof (dprov_session_t *));
return (DDI_FAILURE);
}
/*
* This call is for testing only; it is not required by the SPI.
*/
return (DDI_SUCCESS);
}
static int
{
int i, ret;
instance));
if (cmd != DDI_DETACH)
return (DDI_FAILURE);
/* unregister from the crypto framework */
if ((ret = crypto_unregister_provider(
"crypto_unregister_provider() "
"failed (0x%x)", ret);
return (DDI_FAILURE);
}
for (i = 0; i < softc->ds_sessions_slots; i++) {
continue;
}
sizeof (dprov_session_t *));
/* free token objects */
for (i = 0; i < DPROV_MAX_OBJECTS; i++)
return (DDI_SUCCESS);
}
/*
* Control entry points.
*/
static void
{
}
/*
* Digest entry points.
*/
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
/* check mechanism */
return (CRYPTO_MECHANISM_INVALID);
}
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
/* submit request to the taskq */
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
/* check mechanism */
return (CRYPTO_MECHANISM_INVALID);
}
/* submit request to the taskq */
return (error);
}
/*
* MAC entry points.
*/
/*
* Checks whether the specified mech_type is supported by mac
* entry points.
*/
static boolean_t
{
return (mech_type == MD5_HMAC_MECH_INFO_TYPE ||
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
/* check mechanism */
return (CRYPTO_MECHANISM_INVALID);
}
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
/* submit request to the taskq */
error));
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* check mechanism */
return (CRYPTO_MECHANISM_INVALID);
}
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* check mechanism */
return (CRYPTO_MECHANISM_INVALID);
}
/* submit request to the taskq */
return (error);
}
/*
*/
/*
* Checks whether the specified mech_type is supported by cipher entry
* points.
*/
static boolean_t
{
return (mech_type == DES_CBC_MECH_INFO_TYPE ||
mech_type == RC4_MECH_INFO_TYPE ||
}
static boolean_t
{
return (mech_type == RSA_PKCS_MECH_INFO_TYPE ||
}
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
/* check mechanism */
return (CRYPTO_MECHANISM_INVALID);
}
/* submit request to the taskq */
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
/* submit request to the taskq */
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
/* submit request to the taskq */
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* check mechanism */
return (CRYPTO_MECHANISM_INVALID);
}
KM_SLEEP);
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
/* check mechanism */
return (CRYPTO_MECHANISM_INVALID);
}
/* submit request to the taskq */
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
/* submit request to the taskq */
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
/* submit request to the taskq */
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* check mechanism */
return (CRYPTO_MECHANISM_INVALID);
}
KM_SLEEP);
return (error);
}
/*
* Sign entry points.
*/
/*
* entry points.
*/
static boolean_t
{
return (mech_type == MD5_HMAC_MECH_INFO_TYPE ||
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
/* check mechanism */
return (CRYPTO_MECHANISM_INVALID);
}
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* check mechanism */
return (CRYPTO_MECHANISM_INVALID);
}
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* submit request to the taskq */
return (error);
}
/*
* Verify entry points.
*/
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
/* check mechanism */
return (CRYPTO_MECHANISM_INVALID);
}
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
/* check mechanism */
return (CRYPTO_MECHANISM_INVALID);
}
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* submit request to the taskq */
return (error);
}
/*
* Dual operations entry points.
*/
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
return (CRYPTO_INVALID_CONTEXT);
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
return (CRYPTO_INVALID_CONTEXT);
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
return (CRYPTO_INVALID_CONTEXT);
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
return (CRYPTO_INVALID_CONTEXT);
/* submit request to the taskq */
return (error);
}
/*
* Dual cipher-mac entry points.
*/
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
/* check mechanisms */
"mech type 0x%llx\n",
(unsigned long long)encrypt_mech->cm_type);
return (CRYPTO_MECHANISM_INVALID);
}
"mech type 0x%llx\n",
return (CRYPTO_MECHANISM_INVALID);
}
return (CRYPTO_ARGUMENTS_BAD);
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
/*
* submit request to the taskq
*/
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
/* check mechanisms */
"mech type 0x%llx\n",
(unsigned long long)encrypt_mech->cm_type);
return (CRYPTO_MECHANISM_INVALID);
}
"mech type 0x%llx\n",
return (CRYPTO_MECHANISM_INVALID);
}
return (CRYPTO_ARGUMENTS_BAD);
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
/* check mechanisms */
"mech type 0x%llx\n",
(unsigned long long)decrypt_mech->cm_type);
return (CRYPTO_MECHANISM_INVALID);
}
"mech type 0x%llx\n",
return (CRYPTO_MECHANISM_INVALID);
}
return (CRYPTO_ARGUMENTS_BAD);
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
/* check mechanisms */
"mech type 0x%llx\n",
(unsigned long long)decrypt_mech->cm_type);
return (CRYPTO_MECHANISM_INVALID);
}
"mech type 0x%llx\n",
return (CRYPTO_MECHANISM_INVALID);
}
return (CRYPTO_ARGUMENTS_BAD);
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
"started\n", instance));
/* check mechanisms */
"unexpected encrypt mech type 0x%llx\n",
(unsigned long long)decrypt_mech->cm_type);
return (CRYPTO_MECHANISM_INVALID);
}
"unexpected mac mech type 0x%llx\n",
return (CRYPTO_MECHANISM_INVALID);
}
return (CRYPTO_ARGUMENTS_BAD);
/* submit request to the taskq */
return (error);
}
/*
* Random number entry points.
*/
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
return (error);
}
/*
* Session Management entry points.
*/
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
return (error);
}
/*
* Object management entry points.
*/
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
"started\n", instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
"started\n", instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
/* submit request to the taskq */
0, NULL, KM_NOSLEEP);
return (error);
}
/*
* Key management entry points.
*/
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
/* submit request to the taskq */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
/* submit request to the taskq */
return (error);
}
/*
* Provider management entry points.
*/
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
instance));
return (error);
}
/*
* Context management entry points.
*/
/*
* Allocate a dprov-private context based on the specified dprov request.
* contain a structure dprov_ctx_dual_t, for other request types,
* it will contain a dprov_ctx_single.
* Returns one of the CRYPTO_ status codes.
*/
static int
{
switch (req_type) {
if (dprov_private == NULL)
return (CRYPTO_HOST_MEMORY);
break;
default:
if (dprov_private == NULL)
return (CRYPTO_HOST_MEMORY);
break;
}
return (CRYPTO_SUCCESS);
}
static int
{
return (CRYPTO_SUCCESS);
{
/*
* The dprov private context could contain either
* a dprov_ctx_single_t or a dprov_ctx_dual_t. Free
* the context based on its type. The k-API contexts
* that were attached to the dprov private context
* are freed by the framework.
*/
/*
* This case happens for the crypto_cancel_ctx() case.
* We have to cancel the SW provider context also.
*/
} else {
/* See comments above. */
if (cipher_context != NULL)
if (mac_context != NULL)
}
}
return (CRYPTO_SUCCESS);
}
/*
* Resource control checks don't need to be done. Why? Because this routine
* knows the size of the structure, and it can't be overridden by a user.
* This is different from the crypto module, which has no knowledge of
* specific mechanisms, and therefore has to trust specified size of the
* parameter. This trust, or lack of trust, is why the size of the
* parameter has to be charged against the project resource control.
*/
static int
{
int error = 0;
int rv = 0;
goto out;
}
out_mech->cm_param_len = 0;
goto out;
}
/* allocate param structure and counter block */
if (aes_ctr_params == NULL) {
goto out;
}
sizeof (CK_AES_CTR_PARAMS);
sizeof (CK_AES_CTR_PARAMS) + 16);
goto out;
}
}
out:
return (rv);
}
/* ARGSUSED */
static int
{
int error = 0;
int rv = 0;
goto out;
}
goto out;
}
/* for testing, overwrite the iv with 16 X 'A' */
goto out;
}
}
out:
return (rv);
}
/* ARGSUSED */
static int
{
char *param;
int rv;
int error = 0;
kmech->cm_param_len = 0;
case DES_CBC_MECH_INFO_TYPE:
case DES3_CBC_MECH_INFO_TYPE:
break;
break;
case AES_CBC_MECH_INFO_TYPE:
break;
case AES_CTR_MECH_INFO_TYPE:
case SHA1_KEY_DERIVATION_MECH_INFO_TYPE: /* for testing only */
goto out;
default:
/* nothing to do - mechanism has no parameters */
rv = CRYPTO_SUCCESS;
goto out;
}
if (param_len != expected_param_len) {
goto out;
}
goto out;
}
goto out;
}
rv = CRYPTO_FAILED;
goto out;
}
rv = CRYPTO_SUCCESS;
out:
return (rv);
}
/* ARGSUSED */
static int
{
case AES_CTR_MECH_INFO_TYPE:
case SHA1_KEY_DERIVATION_MECH_INFO_TYPE: /* for testing only */
default:
return (CRYPTO_MECHANISM_INVALID);
}
}
/*
* Free mechanism parameter that was allocated by the provider.
*/
/* ARGSUSED */
static int
{
return (CRYPTO_SUCCESS);
} else {
}
return (CRYPTO_SUCCESS);
}
/*
* Allocate a dprov taskq request and initialize the common fields.
* Return NULL if the memory allocation failed.
*/
static dprov_req_t *
{
return (NULL);
return (taskq_req);
}
/*
* Dispatch a dprov request on the taskq associated with a softc.
* Returns CRYPTO_HOST_MEMORY if the request cannot be queued,
* CRYPTO_QUEUED on success.
*/
static int
{
return (CRYPTO_HOST_MEMORY);
} else
return (CRYPTO_QUEUED);
}
/*
* Helper function to submit digest operations to the taskq.
* Returns one of the CRYPTO_ errors.
*/
static int
{
return (CRYPTO_HOST_MEMORY);
}
/*
* Helper function to submit mac operations to the taskq.
* Returns one of the CRYPTO_ errors.
*/
static int
{
return (CRYPTO_HOST_MEMORY);
}
/*
* Helper function to submit sign operations to the taskq.
* Returns one of the CRYPTO_ errors.
*/
static int
int kmflag)
{
return (CRYPTO_HOST_MEMORY);
}
/*
* Helper function to submit verify operations to the taskq.
* Returns one of the CRYPTO_ errors.
*/
static int
int kmflag)
{
return (CRYPTO_HOST_MEMORY);
}
/*
* Helper function to submit dual operations to the taskq.
* Returns one of the CRYPTO_ errors.
*/
static int
{
KM_NOSLEEP)) == NULL)
return (CRYPTO_HOST_MEMORY);
}
/*
* Returns one of the CRYPTO_ errors.
*/
static int
{
return (CRYPTO_HOST_MEMORY);
}
/*
* Helper function to submit cipher operations to the taskq.
* Returns one of the CRYPTO_ errors.
*/
static int
int kmflag)
{
return (CRYPTO_HOST_MEMORY);
}
/*
* Helper function to submit random number operations to the taskq.
* Returns one of the CRYPTO_ errors.
*/
static int
{
KM_NOSLEEP)) == NULL)
return (CRYPTO_HOST_MEMORY);
}
/*
* Helper function to submit session management operations to the taskq.
* Returns one of the CRYPTO_ errors.
*/
static int
{
KM_NOSLEEP)) == NULL)
return (CRYPTO_HOST_MEMORY);
}
/*
* Helper function to submit object management operations to the taskq.
* Returns one of the CRYPTO_ errors.
*/
static int
{
return (CRYPTO_HOST_MEMORY);
}
/*
* Helper function to submit key management operations to the taskq.
* Returns one of the CRYPTO_ errors.
*/
static int
{
KM_NOSLEEP)) == NULL)
return (CRYPTO_HOST_MEMORY);
}
/*
* Helper function to submit provider management operations to the taskq.
* Returns one of the CRYPTO_ errors.
*/
static int
{
KM_NOSLEEP)) == NULL)
return (CRYPTO_HOST_MEMORY);
}
/*
* Helper function for taskq dispatcher routines. Notify the framework
* that the operation corresponding to the specified request is done,
* and pass it the error code. Finally, free the taskq_req.
*/
static void
{
/* notify framework that request is completed */
/* free taskq request structure */
}
/*
* taskq dispatcher function for digest operations.
*/
static void
{
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
int error = CRYPTO_NOT_SUPPORTED;
case DPROV_REQ_DIGEST_INIT:
/* allocate a dprov-private context */
break;
/* structure assignment */
/* get the software provider for this mechanism */
if ((error = dprov_get_sw_prov(
break;
/* Use a session id of zero since we use a software provider */
/* release provider reference */
break;
case DPROV_REQ_DIGEST:
if (error != CRYPTO_BUFFER_TOO_SMALL) {
(void) dprov_free_context(ctx);
}
break;
case DPROV_REQ_DIGEST_UPDATE:
break;
case DPROV_REQ_DIGEST_KEY: {
if (error != CRYPTO_SUCCESS)
break;
/* key lengths are specified in bits */
break;
}
case DPROV_REQ_DIGEST_FINAL:
if (error != CRYPTO_BUFFER_TOO_SMALL) {
(void) dprov_free_context(ctx);
}
break;
case DPROV_REQ_DIGEST_ATOMIC:
/* structure assignment */
/* get the software provider for this mechanism */
if ((error = dprov_get_sw_prov(
break;
/* use a session id of zero since we use a software provider */
/* release provider reference */
break;
}
}
/*
* taskq dispatcher function for mac operations.
*/
static void
{
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
int error = CRYPTO_NOT_SUPPORTED;
case DPROV_REQ_MAC_INIT:
/* allocate a dprov-private context */
break;
/* get key value */
if (error != CRYPTO_SUCCESS)
break;
/* structure assignment */
/* get the software provider for this mechanism */
if ((error = dprov_get_sw_prov(
break;
/* Use a session id of zero since we use a software provider */
/* release provider reference */
break;
case DPROV_REQ_MAC:
if (error != CRYPTO_BUFFER_TOO_SMALL) {
(void) dprov_free_context(ctx);
}
break;
case DPROV_REQ_MAC_UPDATE:
break;
case DPROV_REQ_MAC_FINAL:
if (error != CRYPTO_BUFFER_TOO_SMALL) {
(void) dprov_free_context(ctx);
}
break;
case DPROV_REQ_MAC_ATOMIC:
/* get key value */
if (error != CRYPTO_SUCCESS)
break;
/* structure assignment */
/* get the software provider for this mechanism */
if ((error = dprov_get_sw_prov(
break;
/* use a session id of zero since we use a software provider */
else
/* release provider reference */
break;
}
}
/*
* taskq dispatcher function for sign operations.
*/
static void
{
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
int error = CRYPTO_NOT_SUPPORTED;
case DPROV_REQ_SIGN_INIT:
/* allocate a dprov-private context */
break;
/* structure assignment */
/* get key value for secret key algorithms */
!= CRYPTO_SUCCESS) {
break;
}
} else {
!= CRYPTO_SUCCESS) {
break;
}
}
/* get the software provider for this mechanism */
if ((error = dprov_get_sw_prov(
break;
/* Use a session id of zero since we use a software provider */
else
/* release provider reference */
break;
case DPROV_REQ_SIGN:
if (error != CRYPTO_BUFFER_TOO_SMALL) {
(void) dprov_free_context(ctx);
}
break;
case DPROV_REQ_SIGN_UPDATE:
break;
case DPROV_REQ_SIGN_FINAL:
if (error != CRYPTO_BUFFER_TOO_SMALL) {
(void) dprov_free_context(ctx);
}
break;
case DPROV_REQ_SIGN_ATOMIC:
/* structure assignment */
/* get key value for secret key algorithms */
!= CRYPTO_SUCCESS) {
break;
}
} else {
!= CRYPTO_SUCCESS) {
break;
}
}
/* get the software provider for this mechanism */
if ((error = dprov_get_sw_prov(
break;
/* Use a session id of zero since we use a software provider */
else
/* release provider reference */
break;
case DPROV_REQ_SIGN_RECOVER:
if (error != CRYPTO_BUFFER_TOO_SMALL) {
(void) dprov_free_context(ctx);
}
break;
}
}
/*
* taskq dispatcher function for verify operations.
*/
static void
{
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
int error = CRYPTO_NOT_SUPPORTED;
case DPROV_REQ_VERIFY_INIT:
/* allocate a dprov-private context */
break;
/* structure assignment */
/* get key value for secret key algorithms */
!= CRYPTO_SUCCESS) {
break;
}
} else {
!= CRYPTO_SUCCESS) {
break;
}
}
/* get the software provider for this mechanism */
if ((error = dprov_get_sw_prov(
break;
/* Use a session id of zero since we use a software provider */
else
/* release provider reference */
break;
case DPROV_REQ_VERIFY:
(void) dprov_free_context(ctx);
break;
case DPROV_REQ_VERIFY_UPDATE:
break;
case DPROV_REQ_VERIFY_FINAL:
(void) dprov_free_context(ctx);
break;
case DPROV_REQ_VERIFY_ATOMIC:
/* structure assignment */
/* get key value for secret key algorithms */
!= CRYPTO_SUCCESS) {
break;
}
} else {
!= CRYPTO_SUCCESS) {
break;
}
}
/* get the software provider for this mechanism */
if ((error = dprov_get_sw_prov(
break;
/* Use a session id of zero since we use a software provider */
else
/*
* crypto_verify_recover_prov() has different argument
* order than crypto_verify_prov().
*/
/* release provider reference */
break;
case DPROV_REQ_VERIFY_RECOVER:
/*
* crypto_verify_recover_single() has different argument
* order than crypto_verify_single().
*/
if (error != CRYPTO_BUFFER_TOO_SMALL) {
(void) dprov_free_context(ctx);
}
break;
}
}
/*
* taskq dispatcher function for dual operations.
*/
static void
{
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
int error = CRYPTO_NOT_SUPPORTED;
break;
break;
break;
break;
}
}
/*
* taskq dispatcher function for cipher operations.
*/
static void
{
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
int error = CRYPTO_NOT_SUPPORTED;
case DPROV_REQ_ENCRYPT_INIT:
case DPROV_REQ_DECRYPT_INIT:
/* allocate a dprov-private context */
break;
/* structure assignment */
/* get key value for secret key algorithms */
!= CRYPTO_SUCCESS) {
break;
}
} else {
!= CRYPTO_SUCCESS) {
break;
}
}
/* get the software provider for this mechanism */
if ((error = dprov_get_sw_prov(
break;
/* Use a session id of zero since we use a software provider */
else
crypto_ctx_t *lctx =
}
/* release provider reference */
break;
case DPROV_REQ_ENCRYPT:
if (error != CRYPTO_BUFFER_TOO_SMALL) {
(void) dprov_free_context(ctx);
}
break;
case DPROV_REQ_DECRYPT:
if (error != CRYPTO_BUFFER_TOO_SMALL) {
(void) dprov_free_context(ctx);
}
break;
case DPROV_REQ_ENCRYPT_UPDATE:
break;
case DPROV_REQ_DECRYPT_UPDATE:
break;
case DPROV_REQ_ENCRYPT_FINAL:
if (error != CRYPTO_BUFFER_TOO_SMALL) {
(void) dprov_free_context(ctx);
}
break;
case DPROV_REQ_DECRYPT_FINAL:
if (error != CRYPTO_BUFFER_TOO_SMALL) {
(void) dprov_free_context(ctx);
}
break;
case DPROV_REQ_ENCRYPT_ATOMIC:
case DPROV_REQ_DECRYPT_ATOMIC:
/* structure assignment */
/* get key value for secret key algorithms */
&key)) != CRYPTO_SUCCESS) {
break;
}
} else {
&key))
!= CRYPTO_SUCCESS) {
break;
}
}
/* get the software provider for this mechanism */
if ((error = dprov_get_sw_prov(
break;
/* use a session id of zero since we use a software provider */
else
/* release provider reference */
break;
}
}
/*
* function. Initialize the cipher and mac key values and find the
* providers that can process the request for the specified mechanisms.
*/
static int
{
int error;
/* get the cipher key value */
if (error != CRYPTO_SUCCESS) {
return (error);
}
/* get the mac key value */
if (error != CRYPTO_SUCCESS)
return (error);
/* get the SW provider to perform the cipher operation */
if ((error = dprov_get_sw_prov(
return (error);
/* get the SW provider to perform the mac operation */
return (error);
}
/*
*/
static void
{
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
int error = CRYPTO_NOT_SUPPORTED;
instance));
/* structure assignment */
/* get the keys values and providers to use for operations */
break;
/* allocate a dprov-private context */
break;
/* do the encryption initialization */
else
/* do the decryption initialization */
if (error != CRYPTO_SUCCESS)
break;
/* do the mac initialization */
NULL)) != CRYPTO_SUCCESS)
break;
/* release references to providers */
break;
case DPROV_REQ_ENCRYPT_MAC: {
/* do an encrypt update */
if (inplace) {
} else {
}
break;
/* do an encrypt final */
break;
/*
* Do a mac update on the resulting ciphertext, but with no
* more bytes than specified by dual_data, and starting at
* offset specified by dual_data. For in-place operations,
* we use the length specified by the dual_data.
*/
break;
/* do a mac final */
/* Set the total size of the ciphertext, when successful */
if (error == CRYPTO_SUCCESS)
if (error != CRYPTO_BUFFER_TOO_SMALL) {
(void) dprov_free_context(ctx);
}
break;
}
case DPROV_REQ_ENCRYPT_MAC_UPDATE: {
/* do an encrypt update */
if (inplace) {
} else {
}
break;
/*
* Do a mac update on the resulting ciphertext, but with no
* more bytes than specified by dual_data, and starting at
* offset specified by dual_data. For in-place operations,
* we use the length specified by the dual_data.
* There is an edge case, when the encryption step produced
* zero bytes in the ciphertext. Only the portion between
* offset2 and offset1 is then thrown in the MAC mix.
*/
if (maclen > 0) {
break;
}
/* Set the total size of the ciphertext, when successful */
if (error == CRYPTO_SUCCESS)
break;
}
/* do an encrypt final */
NULL)) != CRYPTO_SUCCESS)
break;
/*
* If ciphertext length is different from zero, do a mac
* update on it. This does not apply to in-place since we
* do not allow partial updates, hence no final residual.
*/
break;
/* do a mac final */
if (error != CRYPTO_BUFFER_TOO_SMALL) {
(void) dprov_free_context(ctx);
}
break;
case DPROV_REQ_ENCRYPT_MAC_ATOMIC: {
/* do an encrypt atomic */
if (inplace) {
} else {
}
/* structure assignment */
/* get the keys values and providers to use for operations */
break;
/* do the atomic encrypt */
break;
/* do the atomic mac */
break;
}
case DPROV_REQ_MAC_DECRYPT: {
/* do a mac update and final on the ciphertext */
break;
/* do a mac final */
break;
/* do an decrypt update */
/* in-place */
else
NULL)) != CRYPTO_SUCCESS)
break;
/* do an decrypt final */
/* in-place, everything must have been decrypted */
else
&plaintext_tmp, NULL);
if (error != CRYPTO_BUFFER_TOO_SMALL) {
(void) dprov_free_context(ctx);
}
break;
}
/* do mac update */
break;
/* do a decrypt update */
break;
/* do a mac final */
break;
/* do a decrypt final */
if (error != CRYPTO_BUFFER_TOO_SMALL) {
(void) dprov_free_context(ctx);
}
break;
/* structure assignment */
/* get the keys values and providers to use for operations */
break;
/* do the atomic mac */
else
/* DPROV_REQ_MAC_VERIFY_DECRYPT_ATOMIC */
if (error != CRYPTO_SUCCESS)
break;
/* do the atomic decrypt */
break;
}
instance));
}
/*
* taskq dispatcher function for random number generation.
*/
static void
{
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
int error = CRYPTO_SUCCESS;
/*
* Since we don't really generate random numbers
* nothing to do.
*/
break;
case DPROV_REQ_RANDOM_GENERATE: {
uint_t i;
uchar_t c = 0;
/*
* We don't generate random numbers so that the result
* of the operation can be checked during testing.
*/
break;
}
}
}
/*
* taskq dispatcher function for session management operations.
*/
static void
{
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
int error = CRYPTO_NOT_SUPPORTED;
int i;
instance));
/* validate session id and get ptr to session */
return;
}
case DPROV_REQ_SESSION_OPEN: {
break;
}
/* search for available session slot */
for (i = 0; i < softc->ds_sessions_slots; i++)
break;
if (i == softc->ds_sessions_slots) {
/* ran out of slots, grow sessions array */
if (new_sessions == NULL) {
break;
}
sizeof (dprov_session_t *));
}
/* allocate and initialize new session */
sizeof (dprov_session_t), KM_NOSLEEP);
break;
}
/* initialize session state */
/* return new session id to caller */
break;
}
case DPROV_REQ_SESSION_CLOSE:
break;
}
/* free session state and corresponding slot */
break;
case DPROV_REQ_SESSION_LOGIN: {
/* check user type */
break;
}
/* check pin length */
if (pin_len > DPROV_MAX_PIN_LEN) {
break;
}
/* check pin */
break;
}
/* validate PIN state */
break;
}
(user_type == CRYPTO_USER &&
/* SO or user already logged in */
break;
}
/* another user already logged in */
break;
}
/* everything's fine, update session */
break;
}
case DPROV_REQ_SESSION_LOGOUT:
/* fail if not logged in */
break;
}
/*
* Destroy all private session objects.
* Invalidate handles to all private objects.
*/
for (i = 0; i < DPROV_MAX_OBJECTS; i++) {
if (!dprov_object_is_token(object))
/* It's a session object, free it */
NULL;
}
}
/* update session state */
break;
}
}
/* return true if attribute is defined to be a PKCS#11 long */
static boolean_t
{
return (type == DPROV_CKA_CLASS ||
type == DPROV_CKA_KEY_TYPE ||
}
/*
* Attributes defined to be a PKCS#11 long causes problems for dprov
* because 32-bit applications set the size to 4 and 64-bit applications
* set the size to 8. dprov always stores these fixed-size attributes
* as uint32_t.
*/
static ssize_t
{
if (fixed_size_attribute(type))
return (sizeof (uint32_t));
return (len);
}
/*
* taskq dispatcher function for object management operations.
*/
static void
{
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
int error = CRYPTO_NOT_SUPPORTED;
/* validate session id and get ptr to session */
return;
}
case DPROV_REQ_OBJECT_CREATE:
/* create the object from the specified template */
B_FALSE)) != CRYPTO_SUCCESS)
break;
break;
case DPROV_REQ_OBJECT_COPY:
/* check object id */
if (object_id >= DPROV_MAX_OBJECTS ||
break;
}
/*
* Create a new object from the object passed as
* argument.
*/
B_FALSE)) != CRYPTO_SUCCESS)
break;
/*
* Add the attributes specified by the template to the
* newly created object, replacing existing ones if needed.
*/
break;
case DPROV_REQ_OBJECT_DESTROY:
/* destroy the object */
break;
/* get ptr to object */
if (object_id >= DPROV_MAX_OBJECTS ||
break;
}
/*
* The PKCS11 specification does not specifies what
* the object size really is, here we just return
* the number of possible attributes of the object.
*/
break;
int tmpl_idx;
int object_idx;
/* get ptr to object */
if (object_id >= DPROV_MAX_OBJECTS ||
break;
}
(void) dprov_get_object_attr_boolean(object,
(void) dprov_get_object_attr_ulong(object,
DPROV_CKA_CLASS, &class);
/* return the specified attributes, when possible */
/*
* Attribute can't be revealed if the CKA_EXTRACTABLE
* attribute is set to false.
*/
if (type == DPROV_CKA_VALUE) {
continue;
}
}
if (type == DPROV_CKA_PRIVATE_EXPONENT) {
continue;
}
}
if (object_idx == -1) {
/* attribute not found in object */
continue;
}
/* return attribute length */
/*
* The size of the attribute is set by the
* library according to the data model of the
* application, so don't overwrite it with
* dprov's size.
*/
if (!fixed_size_attribute(type))
continue;
}
continue;
}
/* copy attribute value */
offset = 0;
#ifdef _BIG_ENDIAN
if (fixed_size_attribute(type)) {
}
#endif
/* don't update length for fixed-size attributes */
if (!fixed_size_attribute(type))
}
break;
}
/*
* Add the attributes specified by the template to the
* newly created object, replacing existing ones if needed.
*/
break;
case DPROV_REQ_OBJECT_FIND_INIT: {
int so_idx; /* session object index */
int to_idx; /* token object index */
/* allocate find context */
/* first go through the existing session objects */
continue;
/* setting count to zero means find all objects */
if (attr_count > 0) {
continue;
}
/* session object attributes matches template */
}
/*
* Go through the token object. For each token object
* that can be accessed:
* If there was already an session object id assigned
* to that token object, skip it, since it was returned
* during the check of session objects, else,
* assign a new object id for that token object and
* add it to the array of matching objects.
*/
continue;
/* setting count to zero means find all objects */
if (attr_count > 0) {
continue;
}
/* if the the object has been destroyed, skip it */
if (object->do_destroyed)
continue;
/* skip object if it cannot be accessed from session */
if (dprov_object_is_private(object) &&
continue;
/*
* Is there already a session object id for this
* token object?
*/
break;
if (so_idx < DPROV_MAX_OBJECTS)
/* object found in session table, skip it */
continue;
/* find free session slot for this object */
break;
if (so_idx == DPROV_MAX_OBJECTS) {
/* ran out of session objects slots */
break;
}
/* add object to session objects table */
/* add object to list of objects to return */
}
break;
}
case DPROV_REQ_OBJECT_FIND: {
/* return the desired number of object ids */
break;
}
sizeof (dprov_find_ctx_t));
break;
}
}
/*
* taskq dispatcher function for key management operations.
*/
static void
{
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
int error = CRYPTO_NOT_SUPPORTED;
/* validate session id and get ptr to session */
return;
}
case DPROV_REQ_KEY_GENERATE: {
/* optional */
DPROV_CKA_CLASS, &class);
/* optional */
break;
}
break;
}
break;
break;
}
break;
break;
}
&value_len) != CRYPTO_SUCCESS) {
break;
}
if (value_len >= AES_MAX_KEY_LEN) {
break;
}
break;
key_type != DPROV_CKK_BLOWFISH) {
break;
}
&value_len) != CRYPTO_SUCCESS) {
break;
}
if (value_len >= BLOWFISH_MAX_KEY_LEN) {
break;
}
break;
break;
}
&value_len) != CRYPTO_SUCCESS) {
break;
}
if (value_len >=
break;
}
break;
default:
}
if (error != CRYPTO_SUCCESS)
break;
if (error != CRYPTO_SUCCESS)
break;
/* make sure class is set */
if (error != CRYPTO_SUCCESS) {
goto destroy_object;
}
/* make sure key_type is set */
if (error != CRYPTO_SUCCESS) {
goto destroy_object;
}
key_len) != 0) {
goto destroy_object;
}
if (error != CRYPTO_SUCCESS) {
goto destroy_object;
}
break;
break;
}
case DPROV_REQ_KEY_GENERATE_PAIR: {
char public_exponent[3] = {
0x01, 0x00, 0x01
};
0x4a, 0xef, 0xb9, 0x30, 0xa1, 0x44, 0x0a, 0xe0,
0x30, 0xdd, 0xd3, 0x57, 0xc2, 0xb6, 0x6a, 0xba,
0x5f, 0x81, 0xb0, 0x72, 0x55, 0x5b, 0x5b, 0xf3,
0x07, 0xd2, 0x5f, 0x15, 0x87, 0xc0, 0x78, 0x7d,
0x4f, 0x95, 0x09, 0x59, 0xd2, 0x9a, 0x95, 0xc3,
0xcc, 0xdc, 0xf1, 0xa4, 0x60, 0x76, 0xd7, 0xa7,
0xf8, 0x01, 0x13, 0xf8, 0x54, 0xd4, 0xf8, 0x2f,
0xcf, 0x0c, 0x8b, 0x6e, 0xee, 0x34, 0x53, 0x19,
0x14, 0xa6, 0x15, 0x14, 0xaf, 0xb2, 0x28, 0xa1,
0x78, 0x1b, 0x2d, 0x9b, 0x28, 0x52, 0x14, 0xfa,
0x72, 0x2b, 0x81, 0x11, 0xd0, 0x59, 0xde, 0xc6,
0x52, 0x90, 0xa4, 0xae, 0xc9, 0xf1, 0x97, 0xd4,
0x57, 0xbc, 0xe3, 0x90, 0x30, 0xc7, 0xff, 0xe8,
0xd7, 0x2d, 0xd8, 0xef, 0x14, 0x2d, 0x2d, 0x60,
0x54, 0x22, 0x9d, 0x32, 0x36, 0xcf, 0x4f, 0xf7,
0x37, 0xcc, 0x8e, 0x00, 0x85, 0xb1, 0x00, 0x01
};
0x87, 0xb2, 0x2a, 0x54, 0x63, 0x83, 0x5e, 0x30,
0xdc, 0x73, 0x03, 0xc6, 0x35, 0xf8, 0xa0, 0x25,
0xa5, 0x6e, 0xcc, 0x14, 0xdd, 0x77, 0x2e, 0x80,
0xd1, 0xa3, 0x05, 0x09, 0x1a, 0x2f, 0x88, 0xec,
0xd1, 0x46, 0x92, 0x19, 0x8c, 0x7a, 0xf7, 0x63,
0x28, 0xbf, 0x7a, 0xea, 0x9f, 0xfe, 0x96, 0x0f,
0x80, 0xa1, 0x3e, 0xa6, 0xe1, 0x89, 0x7c, 0x4c,
0x8e, 0x92, 0xdc, 0x6e, 0x69, 0xba, 0x4b, 0x3f,
0x93, 0xc0, 0xaf, 0xbd, 0xbc, 0x81, 0xf2, 0x1e,
0xc0, 0x7d, 0xc3, 0x4c, 0x8f, 0x5f, 0xfe, 0xdc,
0xdb, 0xdb, 0x52, 0x03, 0x94, 0x78, 0x04, 0xa6,
0x78, 0x1f, 0xdd, 0x5e, 0xd8, 0x85, 0x3e, 0x19,
0x54, 0x7c, 0xd5, 0x81, 0xfb, 0x70, 0x69, 0x5d,
0xbf, 0x23, 0x7a, 0xb1, 0xf9, 0x85, 0x6e, 0xc2,
0x0a, 0x4d, 0x81, 0x21, 0xf8, 0xad, 0x71, 0x65,
0xaf, 0xb6, 0x8f, 0xa1, 0xac, 0x46, 0x8a, 0x4d
};
/* optional */
/* optional */
/* optional */
/* optional */
break;
}
break;
}
if (pub_key_type != ~0UL &&
pub_key_type != DPROV_CKK_RSA) {
break;
}
if (pri_key_type != ~0UL &&
pri_key_type != DPROV_CKK_RSA) {
break;
}
break;
}
break;
}
break;
default:
}
if (error != CRYPTO_SUCCESS)
break;
if (error != CRYPTO_SUCCESS)
break;
/* make sure class is set */
if (error != CRYPTO_SUCCESS) {
goto destroy_public_object;
}
/* make sure key_type is set */
if (error != CRYPTO_SUCCESS) {
goto destroy_public_object;
}
if (error != CRYPTO_SUCCESS) {
goto destroy_public_object;
}
if (error != CRYPTO_SUCCESS) {
goto destroy_public_object;
}
if (error != CRYPTO_SUCCESS)
break;
/* make sure class is set */
if (error != CRYPTO_SUCCESS) {
goto destroy_private_object;
}
/* make sure key_type is set */
if (error != CRYPTO_SUCCESS) {
goto destroy_private_object;
}
if (error != CRYPTO_SUCCESS) {
goto destroy_private_object;
}
if (error != CRYPTO_SUCCESS) {
goto destroy_private_object;
}
break;
break;
}
case DPROV_REQ_KEY_WRAP: {
int object_idx;
char *plaintext_key;
/* structure assignment */
/* get wrapping key value */
&key)) != CRYPTO_SUCCESS)
break;
} else {
&key)) != CRYPTO_SUCCESS)
break;
}
/* get the software provider for this mechanism */
break;
if (object_id >= DPROV_MAX_OBJECTS) {
break;
}
/* get ptr to object */
break;
}
(void) dprov_get_object_attr_boolean(object,
if (!extractable) {
break;
}
(void) dprov_get_object_attr_ulong(object,
DPROV_CKA_CLASS, &class);
switch (class) {
case DPROV_CKO_SECRET_KEY:
if (object_idx == -1) {
break;
}
break;
case DPROV_CKO_PRIVATE_KEY:
/*
* PKCS#11 says that ASN.1 should be used to encode
* specific attributes before encrypting the blob.
* We only encrypt the private exponent for the
* purpose of testing.
*/
if (object_idx == -1) {
break;
}
break;
default:
break;
}
if (error != CRYPTO_SUCCESS)
break;
/* session id is 0 for software provider */
ciphertext.cd_offset = 0;
if (error == CRYPTO_SUCCESS ||
error == CRYPTO_BUFFER_TOO_SMALL) {
}
break;
}
case DPROV_REQ_KEY_UNWRAP: {
char *plaintext_buf;
/* all objects must have an object class attribute */
break;
}
/* structure assignment */
/* get unwrapping key value */
&key)) != CRYPTO_SUCCESS)
break;
} else {
&key)) != CRYPTO_SUCCESS)
break;
}
/* get the software provider for this mechanism */
break;
ciphertext.cd_offset = 0;
/*
* Plaintext length is less than or equal to
* the length of the ciphertext.
*/
if (error != CRYPTO_SUCCESS)
goto free_unwrapped_key;
if (error != CRYPTO_SUCCESS)
goto free_unwrapped_key;
switch (class) {
case DPROV_CKO_SECRET_KEY:
break;
case DPROV_CKO_PRIVATE_KEY:
/*
* PKCS#11 says that ASN.1 should be used to encode
* specific attributes before encrypting the blob.
* We only encrypt the private exponent for the
* purpose of testing.
*/
break;
default:
goto free_unwrapped_key;
}
break; /* don't free the unwrapped key */
/* failure */
break;
break;
}
case DPROV_REQ_KEY_DERIVE: {
char *digest_buf;
void *value;
/* required */
break;
}
/* structure assignment */
digest_mech = *mechp;
switch (digest_mech.cm_type) {
break;
break;
break;
break;
break;
default:
}
if (error != CRYPTO_SUCCESS)
break;
/* CKA_VALUE is optional */
/* check for inconsistent value length */
switch (key_type) {
case DPROV_CKK_GENERIC_SECRET:
if (value_len > 0) {
} else {
}
break;
case DPROV_CKK_RC4:
case DPROV_CKK_AES:
if (value_len == 0 ||
}
break;
case DPROV_CKK_DES:
if (value_len > 0 &&
value_len != DES_KEY_LEN) {
}
break;
case DPROV_CKK_DES3:
if (value_len > 0 &&
value_len != DES3_KEY_LEN) {
}
break;
default:
break;
}
if (error != CRYPTO_SUCCESS)
break;
/* get the software provider for this mechanism */
break;
/* get the base key */
if (error != CRYPTO_SUCCESS)
break;
if (error != CRYPTO_SUCCESS)
goto free_derived_key;
if (error != CRYPTO_SUCCESS)
goto free_derived_key;
if (error != CRYPTO_SUCCESS) {
}
}
}
}
/*
* taskq dispatcher function for provider management operations.
*/
static void
{
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
int error = CRYPTO_NOT_SUPPORTED;
case DPROV_REQ_MGMT_EXTINFO: {
if (!softc->ds_token_initialized) {
strlen("(not initialized)"));
} else {
}
/* PKCS#11 blank padding */
if (softc->ds_user_pin_set)
if (softc->ds_token_initialized)
break;
}
case DPROV_REQ_MGMT_INITTOKEN: {
/* cannot initialize token when a session is open */
if (softc->ds_sessions_count > 0) {
break;
}
/* check PIN length */
if (pin_len > DPROV_MAX_PIN_LEN) {
break;
}
/* check PIN */
break;
}
/*
* If the token has already been initialized, need
* to validate supplied PIN.
*/
if (softc->ds_token_initialized &&
/* invalid SO PIN */
break;
}
/* set label */
/* set new SO PIN, update state */
break;
}
case DPROV_REQ_MGMT_INITPIN: {
/* check session id */
break;
}
/* fail if not logged in as SO */
break;
}
/* check PIN length */
if (pin_len > DPROV_MAX_PIN_LEN) {
break;
}
/* check PIN */
break;
}
/* set new normal user PIN */
break;
}
case DPROV_REQ_MGMT_SETPIN: {
/* check session id */
break;
}
/* check PIN length */
if (old_pin_len > DPROV_MAX_PIN_LEN ||
break;
}
/* check PIN */
break;
}
/* check user PIN state */
if (!softc->ds_user_pin_set) {
break;
}
/*
* If the token has already been initialized, need
* to validate supplied PIN.
*/
/* invalid SO PIN */
break;
}
/* set new PIN */
break;
}
}
}
/*
* Returns in the location pointed to by pd a pointer to the descriptor
* for the software provider for the specified mechanism.
* The provider descriptor is returned held. Returns one of the CRYPTO_
* error codes on failure, CRYPTO_SUCCESS on success.
*/
static int
{
int i, rv;
/* lookup the KCF mech type associated with our mech type */
for (i = 0; i < sizeof (dprov_mech_info_tab)/
sizeof (crypto_mech_info_t); i++) {
}
}
if (rv == CRYPTO_SUCCESS)
return (rv);
}
/*
* Object management helper functions.
*/
/*
* Given a crypto_key_t, return whether the key can be used or not
* for the specified request. The attributes used here are defined
* in table 42 of the PKCS#11 spec (Common secret key attributes).
*/
static int
{
int rv = CRYPTO_SUCCESS;
/* check if object is allowed for specified operation */
switch (req_type) {
case DPROV_REQ_ENCRYPT_INIT:
case DPROV_REQ_ENCRYPT_ATOMIC:
DPROV_CKA_ENCRYPT, &ret);
break;
case DPROV_REQ_DECRYPT_INIT:
case DPROV_REQ_DECRYPT_ATOMIC:
DPROV_CKA_DECRYPT, &ret);
break;
case DPROV_REQ_SIGN_INIT:
case DPROV_REQ_SIGN_ATOMIC:
case DPROV_REQ_MAC_INIT:
case DPROV_REQ_MAC_ATOMIC:
DPROV_CKA_SIGN, &ret);
break;
break;
case DPROV_REQ_VERIFY_INIT:
case DPROV_REQ_VERIFY_ATOMIC:
DPROV_CKA_VERIFY, &ret);
break;
break;
case DPROV_REQ_KEY_WRAP:
DPROV_CKA_WRAP, &ret);
break;
case DPROV_REQ_KEY_UNWRAP:
DPROV_CKA_UNWRAP, &ret);
break;
case DPROV_REQ_DIGEST_KEY:
/*
* There is no attribute to check for; therefore,
* any secret key can be used.
*/
rv = CRYPTO_SUCCESS;
break;
case DPROV_REQ_KEY_DERIVE:
DPROV_CKA_DERIVE, &ret);
break;
}
return (CRYPTO_KEY_FUNCTION_NOT_PERMITTED);
return (CRYPTO_SUCCESS);
}
/*
* Given a crypto_key_t corresponding to a secret key (i.e. for
* use with symmetric crypto algorithms) specified in raw format, by
* attribute, or by reference, initialize the ck_data and ck_length
* fields of the ret_key argument so that they specify the key value
* and length.
*
* For a key by value, this function uess the ck_data and ck_length,
* for a key by reference, it looks up the corresponding object and
* returns the appropriate attribute. For a key by attribute, it returns
* the appropriate attribute. The attributes used are CKA_VALUE to retrieve
* the value of the key, and CKA_VALUE_LEN to retrieve its length in bytes.
*/
static int
{
int ret = CRYPTO_SUCCESS;
case CRYPTO_KEY_RAW:
break;
case CRYPTO_KEY_ATTR_LIST: {
void *value;
&key_type)) != CRYPTO_SUCCESS)
break;
break;
/*
* The length of the array is expressed in bytes.
* Convert to bits now since that's how keys are measured.
*/
/* optional */
&value_len)) == CRYPTO_SUCCESS) {
}
break;
}
case CRYPTO_KEY_REFERENCE: {
void *value;
/* check session id */
break;
}
goto bail;
}
/* check if object id specified by key is valid */
goto bail;
}
/* check if object can be used for operation */
goto bail;
goto bail;
goto bail;
/* optional */
&value_len)) == CRYPTO_SUCCESS) {
}
/*
* The length of attributes are in bytes.
* Convert to bits now since that's how keys are measured.
*/
bail:
break;
}
default:
break;
}
return (ret);
}
/*
* Get the attribute list for the specified asymmetric key.
*/
static int
{
int ret = CRYPTO_SUCCESS;
case CRYPTO_KEY_ATTR_LIST:
break;
case CRYPTO_KEY_REFERENCE: {
/* check session id */
break;
}
/* check if object id specified by key is valid */
break;
}
/* check if object can be used for operation */
break;
break;
}
default:
}
return (ret);
}
/*
* Return the index of an attribute of specified type found in
* the specified array of attributes. If the attribute cannot
* found, return -1.
*/
static int
{
int i;
for (i = 0; i < nattr; i++)
return (i);
return (-1);
}
/*
* Given the given object template and session, return whether
* an object can be created from that template according to the
* following rules:
* - private objects can be created only by a logged-in user
*/
static int
{
int error;
/* check CKA_PRIVATE attribute value */
/* it's a private object */
/*
* Cannot create private object with SO or public
* sessions.
*/
return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
}
}
/* all objects must have an object class attribute */
&class) != CRYPTO_SUCCESS) {
return (CRYPTO_TEMPLATE_INCOMPLETE);
}
/* key objects must have a key type attribute */
if (class == DPROV_CKO_SECRET_KEY ||
class == DPROV_CKO_PUBLIC_KEY ||
class == DPROV_CKO_PRIVATE_KEY) {
return (CRYPTO_TEMPLATE_INCOMPLETE);
}
}
/* check for RSA public key attributes that must be present */
if (class == DPROV_CKO_PUBLIC_KEY) {
if (key_type == DPROV_CKK_RSA) {
nattr, DPROV_CKA_MODULUS) ||
return (CRYPTO_TEMPLATE_INCOMPLETE);
}
/* these attributes should not be present */
return (CRYPTO_TEMPLATE_INCONSISTENT);
}
}
}
}
/* check for RSA private key attributes that must be present */
if (class == DPROV_CKO_PRIVATE_KEY) {
if (key_type == DPROV_CKK_RSA) {
return (CRYPTO_TEMPLATE_INCOMPLETE);
if (check_for_secret) {
return (
}
}
}
}
/* check for secret key attributes that must be present */
if (class == DPROV_CKO_SECRET_KEY) {
if (check_for_secret) {
DPROV_CKA_VALUE)) {
return (CRYPTO_TEMPLATE_INCOMPLETE);
}
}
/* these attributes should not be present */
return (CRYPTO_TEMPLATE_INCONSISTENT);
}
}
return (CRYPTO_SUCCESS);
}
/*
* Create an object from the specified template. Checks whether the
* object can be created according to its attributes and the state
* of the session. The new session object id is returned. If the
* object is a token object, it is added to the per-instance object
* table as well.
*/
static int
{
uint_t i;
int error;
if (nattr > DPROV_MAX_ATTR)
return (CRYPTO_HOST_MEMORY);
if (!force) {
/* verify that object can be created */
return (error);
}
/* allocate new object */
return (CRYPTO_HOST_MEMORY);
/* is it a token object? */
/* check CKA_TOKEN attribute value */
/* token object, add it to the per-instance object table */
for (i = 0; i < DPROV_MAX_OBJECTS; i++)
break;
if (i == DPROV_MAX_OBJECTS)
/* no free slot */
return (CRYPTO_HOST_MEMORY);
object->do_token_idx = i;
}
/* add object to session object table */
for (i = 0; i < DPROV_MAX_OBJECTS; i++)
break;
if (i == DPROV_MAX_OBJECTS) {
/* no more session object slots */
return (CRYPTO_HOST_MEMORY);
}
*object_id = i;
/* initialize object from template */
continue;
if (type == DPROV_CKA_EXTRACTABLE) {
} else if (type == DPROV_CKA_PRIVATE) {
}
KM_SLEEP);
offset = 0;
#ifdef _BIG_ENDIAN
if (fixed_size_attribute(type)) {
}
#endif
oattr++;
}
/* add boolean attributes that must be present */
if (extractable_attribute_present == B_FALSE) {
oattr++;
}
if (private_attribute_present == B_FALSE) {
oattr++;
}
return (CRYPTO_SUCCESS);
}
/*
* Checks whether or not the object matches the specified attributes.
*
* PKCS#11 attributes which are longs are stored in uint32_t containers
* so they can be matched by both 32 and 64-bit applications.
*/
static boolean_t
{
int ta_idx; /* template attribute index */
int oa_idx; /* object attribute index */
/* no value for template attribute */
continue;
/* find attribute in object */
if (oa_idx == -1)
/* attribute not found in object */
return (B_FALSE);
return (B_FALSE);
diff = 0;
#ifdef _BIG_ENDIAN
/* application may think attribute is 8 bytes */
if (fixed_size_attribute(type))
#endif
/* value mismatch */
return (B_FALSE);
}
return (B_TRUE);
}
/*
* Destroy the object specified by its session and object id.
*/
static int
{
return (CRYPTO_OBJECT_HANDLE_INVALID);
/* remove from session table */
if (dprov_object_is_token(object)) {
if (!object->do_destroyed) {
/* remove from per-instance token table */
} else {
"object %p already destroyed\n", (void *)object));
}
}
return (CRYPTO_SUCCESS);
}
static int
{
/* all objects should have an object class attribute */
&object_class) != CRYPTO_SUCCESS) {
return (CRYPTO_SUCCESS);
}
if (object_class == DPROV_CKO_SECRET_KEY ||
DPROV_CKA_CLASS) ||
return (CRYPTO_TEMPLATE_INCONSISTENT);
}
switch (object_class) {
case DPROV_CKO_SECRET_KEY:
return (CRYPTO_TEMPLATE_INCONSISTENT);
break;
case DPROV_CKO_PUBLIC_KEY:
return (CRYPTO_TEMPLATE_INCONSISTENT);
break;
case DPROV_CKO_PRIVATE_KEY:
return (CRYPTO_TEMPLATE_INCONSISTENT);
break;
default:
return (CRYPTO_SUCCESS);
}
return (CRYPTO_SUCCESS);
}
/*
* Set the attributes specified by the template in the specified object,
* replacing existing ones if needed.
*/
static int
{
uint_t i, j;
int error;
return (CRYPTO_OBJECT_HANDLE_INVALID);
if (check_attributes) {
/* verify that attributes in the template can be modified */
!= CRYPTO_SUCCESS)
return (error);
}
/* go through the attributes specified in the template */
for (i = 0; i < nattr; i++) {
continue;
/* find attribute in object */
if (j != -1) {
/* attribute already exists, free old value */
} else {
/* attribute does not exist, create it */
for (j = 0; j < DPROV_MAX_ATTR; j++)
break;
if (j == DPROV_MAX_ATTR)
/* ran out of attribute slots */
return (CRYPTO_HOST_MEMORY);
}
/* set object attribute value */
/* and the type */
}
return (CRYPTO_SUCCESS);
}
/*
* Free the specified object.
*/
static void
{
int i;
/* free the object attributes values */
for (i = 0; i < DPROV_MAX_ATTR; i++)
/* free the object */
}
/*
* Checks whether the specified object is a private or public object.
*/
static boolean_t
{
int err;
if (err != CRYPTO_SUCCESS)
/* by default, CKA_PRIVATE is false */
return (ret);
}
/*
* Checks whether the specified object is a token or session object.
*/
static boolean_t
{
int err;
if (err != CRYPTO_SUCCESS)
/* by default, CKA_TOKEN is false */
return (ret);
}
/*
* Common function used by the dprov_get_object_attr_*() family of
* functions. Returns the value of the specified attribute of specified
* length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID
* if the length of the attribute does not match the specified length,
* or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found.
*/
static int
{
int attr_idx;
attr_type)) == -1)
return (CRYPTO_ARGUMENTS_BAD);
if (oa_value_len != value_len) {
/*
* For some attributes, it's okay to copy the value
* into a larger container, e.g. copy an unsigned
* 32-bit integer into a 64-bit container.
*/
if (attr_type == DPROV_CKA_VALUE_LEN ||
attr_type == DPROV_CKA_KEY_TYPE ||
attr_type == DPROV_CKA_CLASS) {
if (oa_value_len < value_len) {
#ifdef _BIG_ENDIAN
#endif
goto do_copy;
}
}
/* incorrect attribute value length */
return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
}
return (CRYPTO_SUCCESS);
}
/*
* Get the value of the a boolean attribute from the specified object.
*/
static int
{
int ret;
/* PKCS#11 defines a boolean as one byte */
if (ret == CRYPTO_SUCCESS) {
}
return (ret);
}
/*
* Get the value of a ulong_t attribute from the specified object.
*/
static int
{
attr_value, sizeof (ulong_t)));
}
/*
* Find the specified byte array attribute of specified type in
* the specified object. Returns CRYPTO_SUCCESS
* on success or CRYPTO_ARGUMENTS_BAD if the specified
* attribute cannot be found.
*/
static int
{
int attr_idx;
attr_type)) == -1)
return (CRYPTO_ARGUMENTS_BAD);
return (CRYPTO_SUCCESS);
}
/*
* Common function used by the dprov_get_template_attr_*() family of
* functions. Returns the value of the specified attribute of specified
* length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID
* if the length of the attribute does not match the specified length,
* or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found.
*/
static int
{
int attr_idx;
return (CRYPTO_ARGUMENTS_BAD);
if (oa_value_len != value_len) {
/*
* For some attributes, it's okay to copy the value
* into a larger container, e.g. copy an unsigned
* 32-bit integer into a 64-bit container.
*/
if (attr_type == DPROV_CKA_VALUE_LEN ||
attr_type == DPROV_CKA_KEY_TYPE ||
attr_type == DPROV_CKA_CLASS) {
if (oa_value_len < value_len) {
#ifdef _BIG_ENDIAN
#endif
goto do_copy;
}
}
/* incorrect attribute value length */
return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
}
return (CRYPTO_SUCCESS);
}
/*
* Get the value of the a boolean attribute from the specified template
*/
static int
{
int ret;
/* PKCS#11 defines a boolean as one byte */
if (ret == CRYPTO_SUCCESS) {
}
return (ret);
}
/*
* Get the value of a ulong_t attribute from the specified template.
*/
static int
{
}
static int
{
}
/*
* Find the specified byte array attribute of specified type in
* the specified template. Returns CRYPTO_SUCCESS on success or
* CRYPTO_ARGUMENTS_BAD if the specified attribute cannot be found.
*/
static int
{
int attr_idx;
return (CRYPTO_ARGUMENTS_BAD);
return (CRYPTO_SUCCESS);
}
/*
* Common function used by the dprov_get_key_attr_*() family of
* functions. Returns the value of the specified attribute of specified
* length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID
* if the length of the attribute does not match the specified length,
* or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found.
*/
static int
{
int attr_idx;
attr_type)) == -1)
return (CRYPTO_ARGUMENTS_BAD);
/* incorrect attribute value length */
return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
return (CRYPTO_SUCCESS);
}
/*
* Get the value of a ulong_t attribute from the specified key.
*/
static int
{
attr_value, sizeof (ulong_t)));
}
/*
* Find the specified byte array attribute of specified type in
* the specified key by attributes. Returns CRYPTO_SUCCESS
* on success or CRYPTO_ARGUMENTS_BAD if the specified
* attribute cannot be found.
*/
static int
{
int attr_idx;
attr_type)) == -1)
return (CRYPTO_ARGUMENTS_BAD);
return (CRYPTO_SUCCESS);
}
static void
{
int i;
for (i = 0; i < DPROV_MAX_OBJECTS; i++) {
}
}
}