1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 
  27 /*
  28  * Dummy Cryptographic Provider:
  29  *
  30  * This file implements a "dummy" cryptographic provider. It is implemented
  31  * as a pseudo device driver.
  32  *
  33  */
  34 
  35 /*
  36  * This driver implements a KEF provider with the following capabilities:
  37  *
  38  * - registration/unregistration with KEF
  39  * - digest entry points
  40  * - mac entry points
  41  * - ctx management
  42  * - support for async requests
  43  * - cipher entry points
  44  * - dual entry points
  45  * - sign entry points
  46  * - verify entry points
  47  * - dual operations entry points
  48  * - dual cipher/mac operation entry points
  49  * - session management
  50  * - object management
  51  * - key management
  52  * - provider management
  53  *
  54  * In order to avoid duplicating the implementation of algorithms
  55  * provided by software providers, this pseudo driver acts as
  56  * a consumer of the framework. When invoking one of the framework's
  57  * entry points, the driver specifies the software provider to
  58  * be used for the operation.
  59  *
  60  * User management: we implement a PKCS#11 style provider which supports:
  61  * - one normal user with a PIN, and
  62  * - one SO user with a PIN.
  63  * These values are kept in the per-instance structure, and are initialized
  64  * with the provider management entry points.
  65  *
  66  */
  67 
  68 
  69 #include <sys/types.h>
  70 #include <sys/modctl.h>
  71 #include <sys/conf.h>
  72 #include <sys/stat.h>
  73 #include <sys/ddi.h>
  74 #include <sys/sunddi.h>
  75 #include <sys/kmem.h>
  76 #include <sys/errno.h>
  77 #include <sys/ksynch.h>
  78 #include <sys/file.h>
  79 #include <sys/open.h>
  80 #include <sys/cred.h>
  81 #include <sys/model.h>
  82 #include <sys/note.h>
  83 #include <sys/random.h>
  84 #include <sys/byteorder.h>
  85 #include <sys/crypto/common.h>
  86 #include <sys/crypto/spi.h>
  87 
  88 #include <sys/taskq.h>
  89 #include <sys/disp.h>
  90 #include <sys/sysmacros.h>
  91 #include <sys/crypto/impl.h>
  92 #include <sys/crypto/sched_impl.h>
  93 
  94 #include <sys/sha2.h>
  95 #include <modes/modes.h>
  96 #include <aes/aes_impl.h>
  97 #include <des/des_impl.h>
  98 #include <ecc/ecc_impl.h>
  99 #include <blowfish/blowfish_impl.h>
 100 
 101 /*
 102  * Debugging macros.
 103  */
 104 #ifdef DEBUG
 105 #define D_INIT          0x00000001      /* _init/_fini/_info */
 106 #define D_ATTACH        0x00000002      /* attach/detach */
 107 #define D_DIGEST        0x00000010      /* digest entry points */
 108 #define D_MAC           0x00000020      /* mac entry points */
 109 #define D_CONTEXT       0x00000040      /* context entry points */
 110 #define D_CIPHER        0x00000080      /* cipher entry points */
 111 #define D_SIGN          0x00000100      /* sign entry points */
 112 #define D_VERIFY        0x00000200      /* verify entry points */
 113 #define D_SESSION       0x00000400      /* session management entry points */
 114 #define D_MGMT          0x00000800      /* provider management entry points */
 115 #define D_DUAL          0x00001000      /* dual ops */
 116 #define D_CIPHER_MAC    0x00002000      /* cipher/mac dual ops */
 117 #define D_OBJECT        0x00004000      /* object management */
 118 #define D_RANDOM        0x00008000      /* random number generation */
 119 #define D_KEY           0x00010000      /* key management */
 120 
 121 static uint32_t dprov_debug = 0;
 122 
 123 #define DPROV_DEBUG(f, x)       if (dprov_debug & (f)) { (void) printf x; }
 124 #define DPROV_CALL(f, r, x)     if (dprov_debug & (f)) { (void) r x; }
 125 #else /* DEBUG */
 126 #define DPROV_DEBUG(f, x)
 127 #define DPROV_CALL(f, r, x)
 128 #endif /* DEBUG */
 129 
 130 static int nostore_key_gen;
 131 static boolean_t dprov_no_multipart = B_FALSE;
 132 static int dprov_max_digestsz = INT_MAX;
 133 
 134 /*
 135  * DDI entry points.
 136  */
 137 static int dprov_attach(dev_info_t *, ddi_attach_cmd_t);
 138 static int dprov_detach(dev_info_t *, ddi_detach_cmd_t);
 139 static int dprov_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
 140 
 141 /*
 142  * Module linkage.
 143  */
 144 static struct cb_ops cbops = {
 145         nodev,                  /* cb_open */
 146         nodev,                  /* cb_close */
 147         nodev,                  /* cb_strategy */
 148         nodev,                  /* cb_print */
 149         nodev,                  /* cb_dump */
 150         nodev,                  /* cb_read */
 151         nodev,                  /* cb_write */
 152         nodev,                  /* cb_ioctl */
 153         nodev,                  /* cb_devmap */
 154         nodev,                  /* cb_mmap */
 155         nodev,                  /* cb_segmap */
 156         nochpoll,               /* cb_chpoll */
 157         ddi_prop_op,            /* cb_prop_op */
 158         NULL,                   /* cb_streamtab */
 159         D_MP,                   /* cb_flag */
 160         CB_REV,                 /* cb_rev */
 161         nodev,                  /* cb_aread */
 162         nodev,                  /* cb_awrite */
 163 };
 164 
 165 static struct dev_ops devops = {
 166         DEVO_REV,               /* devo_rev */
 167         0,                      /* devo_refcnt */
 168         dprov_getinfo,          /* devo_getinfo */
 169         nulldev,                /* devo_identify */
 170         nulldev,                /* devo_probe */
 171         dprov_attach,           /* devo_attach */
 172         dprov_detach,           /* devo_detach */
 173         nodev,                  /* devo_reset */
 174         &cbops,                     /* devo_cb_ops */
 175         NULL,                   /* devo_bus_ops */
 176         NULL,                   /* devo_power */
 177         ddi_quiesce_not_needed,         /* devo_quiesce */
 178 };
 179 
 180 static struct modldrv modldrv = {
 181         &mod_driverops,
 182         "Pseudo KCF Prov (drv)",
 183         &devops
 184 };
 185 
 186 static struct modlcrypto modlcrypto = {
 187         &mod_cryptoops,
 188         "Pseudo KCF Prov (crypto)"
 189 };
 190 
 191 static struct modlinkage modlinkage = {
 192         MODREV_1,
 193         &modldrv,
 194         &modlcrypto,
 195         NULL
 196 };
 197 
 198 /*
 199  * CSPI information (entry points, provider info, etc.)
 200  */
 201 
 202 typedef enum dprov_mech_type {
 203         MD4_MECH_INFO_TYPE,             /* SUN_CKM_MD4 */
 204 
 205         MD5_MECH_INFO_TYPE,             /* SUN_CKM_MD5 */
 206         MD5_HMAC_MECH_INFO_TYPE,        /* SUN_CKM_MD5_HMAC */
 207         MD5_HMAC_GEN_MECH_INFO_TYPE,    /* SUN_CKM_MD5_HMAC_GENERAL */
 208 
 209         SHA1_HMAC_MECH_INFO_TYPE,       /* SUN_CKM_SHA1_HMAC */
 210         SHA1_HMAC_GEN_MECH_INFO_TYPE,   /* SUN_CKM_SHA1_HMAC_GENERAL */
 211         SHA1_MECH_INFO_TYPE,            /* SUN_CKM_SHA1 */
 212 
 213         SHA256_HMAC_MECH_INFO_TYPE,     /* SUN_CKM_SHA256_HMAC */
 214         SHA256_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA256_HMAC_GENERAL */
 215         SHA256_MECH_INFO_TYPE,          /* SUN_CKM_SHA256 */
 216         SHA384_HMAC_MECH_INFO_TYPE,     /* SUN_CKM_SHA384_HMAC */
 217         SHA384_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA384_HMAC_GENERAL */
 218         SHA384_MECH_INFO_TYPE,          /* SUN_CKM_SHA384 */
 219         SHA512_HMAC_MECH_INFO_TYPE,     /* SUN_CKM_SHA512_HMAC */
 220         SHA512_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA512_HMAC_GENERAL */
 221         SHA512_MECH_INFO_TYPE,          /* SUN_CKM_SHA512 */
 222 
 223         DES_CBC_MECH_INFO_TYPE,         /* SUN_CKM_DES_CBC */
 224         DES3_CBC_MECH_INFO_TYPE,        /* SUN_CKM_DES3_CBC */
 225         DES_ECB_MECH_INFO_TYPE,         /* SUN_CKM_DES_ECB */
 226         DES3_ECB_MECH_INFO_TYPE,        /* SUN_CKM_DES3_ECB */
 227 
 228         BLOWFISH_CBC_MECH_INFO_TYPE,    /* SUN_CKM_BLOWFISH_CBC */
 229         BLOWFISH_ECB_MECH_INFO_TYPE,    /* SUN_CKM_BLOWFISH_ECB */
 230         AES_CBC_MECH_INFO_TYPE,         /* SUN_CKM_AES_CBC */
 231         AES_ECB_MECH_INFO_TYPE,         /* SUN_CKM_AES_ECB */
 232         AES_CTR_MECH_INFO_TYPE,         /* SUN_CKM_AES_CTR */
 233         AES_CCM_MECH_INFO_TYPE,         /* SUN_CKM_AES_CCM */
 234         AES_GCM_MECH_INFO_TYPE,         /* SUN_CKM_AES_GCM */
 235         AES_GMAC_MECH_INFO_TYPE,        /* SUN_CKM_AES_GMAC */
 236         RC4_MECH_INFO_TYPE,             /* SUN_CKM_RC4 */
 237         RSA_PKCS_MECH_INFO_TYPE,        /* SUN_CKM_RSA_PKCS */
 238         RSA_X_509_MECH_INFO_TYPE,       /* SUN_CKM_RSA_X_509 */
 239         MD5_RSA_PKCS_MECH_INFO_TYPE,    /* SUN_CKM_MD5_RSA_PKCS */
 240         SHA1_RSA_PKCS_MECH_INFO_TYPE,   /* SUN_CKM_SHA1_RSA_PKCS */
 241         SHA256_RSA_PKCS_MECH_INFO_TYPE, /* SUN_CKM_SHA256_RSA_PKCS */
 242         SHA384_RSA_PKCS_MECH_INFO_TYPE, /* SUN_CKM_SHA384_RSA_PKCS */
 243         SHA512_RSA_PKCS_MECH_INFO_TYPE, /* SUN_CKM_SHA512_RSA_PKCS */
 244         MD5_KEY_DERIVATION_MECH_INFO_TYPE, /* SUN_CKM_MD5_KEY_DERIVATION */
 245         SHA1_KEY_DERIVATION_MECH_INFO_TYPE, /* SUN_CKM_SHA1_KEY_DERIVATION */
 246         /* SUN_CKM_SHA256_KEY_DERIVATION */
 247         SHA256_KEY_DERIVATION_MECH_INFO_TYPE,
 248         /* SUN_CKM_SHA384_KEY_DERIVATION */
 249         SHA384_KEY_DERIVATION_MECH_INFO_TYPE,
 250         /* SUN_CKM_SHA512_KEY_DERIVATION */
 251         SHA512_KEY_DERIVATION_MECH_INFO_TYPE,
 252         DES_KEY_GEN_MECH_INFO_TYPE,     /* SUN_CKM_DES_KEY_GEN */
 253         DES3_KEY_GEN_MECH_INFO_TYPE,    /* SUN_CKM_DES3_KEY_GEN */
 254         AES_KEY_GEN_MECH_INFO_TYPE,     /* SUN_CKM_AES_KEY_GEN */
 255         BLOWFISH_KEY_GEN_MECH_INFO_TYPE,        /* SUN_CKM_BLOWFISH_KEY_GEN */
 256         RC4_KEY_GEN_MECH_INFO_TYPE,     /* SUN_CKM_RC4_KEY_GEN */
 257         EC_KEY_PAIR_GEN_MECH_INFO_TYPE, /* SUN_CKM_EC_KEY_PAIR_GEN */
 258         ECDSA_MECH_INFO_TYPE,           /* SUN_CKM_ECDSA */
 259         ECDSA_SHA1_MECH_INFO_TYPE,      /* SUN_CKM_ECDSA_SHA1 */
 260         ECDH1_DERIVE_MECH_INFO_TYPE,    /* SUN_CKM_ECDH1_DERIVE */
 261         DH_PKCS_KEY_PAIR_GEN_MECH_INFO_TYPE, /* SUN_CKM_DH_PKCS_KEY_PAIR_GEN */
 262         DH_PKCS_DERIVE_MECH_INFO_TYPE,  /* SUN_CKM_DH_PKCS_DERIVE */
 263         RSA_PKCS_KEY_PAIR_GEN_MECH_INFO_TYPE /* SUN_CKM_RSA_PKCS_KEY_PAIR_GEN */
 264 } dprov_mech_type_t;
 265 
 266 /*
 267  * Mechanism info structure passed to KCF during registration.
 268  */
 269 #define MD5_DIGEST_LEN          16      /* MD5 digest size */
 270 #define MD5_HMAC_BLOCK_SIZE     64      /* MD5-HMAC block size */
 271 #define MD5_HMAC_MIN_KEY_LEN    1       /* MD5-HMAC min key length in bytes */
 272 #define MD5_HMAC_MAX_KEY_LEN    INT_MAX /* MD5-HMAC max key length in bytes */
 273 
 274 #define SHA1_DIGEST_LEN         20      /* SHA1 digest size */
 275 #define SHA1_HMAC_BLOCK_SIZE    64      /* SHA1-HMAC block size */
 276 #define SHA1_HMAC_MIN_KEY_LEN   1       /* SHA1-HMAC min key length in bytes */
 277 #define SHA1_HMAC_MAX_KEY_LEN   INT_MAX /* SHA1-HMAC max key length in bytes */
 278 
 279 #define DES_KEY_LEN             8       /* DES key length in bytes */
 280 #define DES3_KEY_LEN            24      /* DES3 key length in bytes */
 281 
 282 #define BLOWFISH_MIN_KEY_LEN    32      /* Blowfish min key length in bits */
 283 #define BLOWFISH_MAX_KEY_LEN    448     /* Blowfish max key length in bits */
 284 
 285 #define AES_MIN_KEY_LEN         16      /* AES min key length in bytes */
 286 #define AES_MAX_KEY_LEN         32      /* AES max key length in bytes */
 287 
 288 #define ARCFOUR_MIN_KEY_BITS    40      /* RC4 min supported key size */
 289 #define ARCFOUR_MAX_KEY_BITS    2048    /* RC4 max supported key size */
 290 
 291 #define RSA_MIN_KEY_LEN         256     /* RSA min key length in bits */
 292 #define RSA_MAX_KEY_LEN         4096    /* RSA max key length in bits */
 293 
 294 #define DH_MIN_KEY_LEN          64      /* DH min key length in bits */
 295 #define DH_MAX_KEY_LEN          4096    /* DH max key length in bits */
 296 
 297 #define DPROV_CKM_MD5_KEY_DERIVATION    "CKM_MD5_KEY_DERIVATION"
 298 #define DPROV_CKM_SHA1_KEY_DERIVATION   "CKM_SHA1_KEY_DERIVATION"
 299 #define DPROV_CKM_SHA256_KEY_DERIVATION "CKM_SHA256_KEY_DERIVATION"
 300 #define DPROV_CKM_SHA384_KEY_DERIVATION "CKM_SHA384_KEY_DERIVATION"
 301 #define DPROV_CKM_SHA512_KEY_DERIVATION "CKM_SHA512_KEY_DERIVATION"
 302 #define DPROV_CKM_DES_KEY_GEN           "CKM_DES_KEY_GEN"
 303 #define DPROV_CKM_DES3_KEY_GEN          "CKM_DES3_KEY_GEN"
 304 #define DPROV_CKM_AES_KEY_GEN           "CKM_AES_KEY_GEN"
 305 #define DPROV_CKM_BLOWFISH_KEY_GEN      "CKM_BLOWFISH_KEY_GEN"
 306 #define DPROV_CKM_RC4_KEY_GEN           "CKM_RC4_KEY_GEN"
 307 #define DPROV_CKM_RSA_PKCS_KEY_PAIR_GEN "CKM_RSA_PKCS_KEY_PAIR_GEN"
 308 #define DPROV_CKM_EC_KEY_PAIR_GEN       "CKM_EC_KEY_PAIR_GEN"
 309 #define DPROV_CKM_ECDSA                 "CKM_ECDSA"
 310 #define DPROV_CKM_ECDSA_SHA1            "CKM_ECDSA_SHA1"
 311 #define DPROV_CKM_ECDH1_DERIVE          "CKM_ECDH1_DERIVE"
 312 #define DPROV_CKM_DH_PKCS_KEY_PAIR_GEN  "CKM_DH_PKCS_KEY_PAIR_GEN"
 313 #define DPROV_CKM_DH_PKCS_DERIVE        "CKM_DH_PKCS_DERIVE"
 314 
 315 static crypto_mech_info_t dprov_mech_info_tab[] = {
 316         /* MD4 */
 317         {SUN_CKM_MD4, MD4_MECH_INFO_TYPE,
 318             CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 0, 0,
 319             CRYPTO_KEYSIZE_UNIT_IN_BITS},
 320         /* MD5 */
 321         {SUN_CKM_MD5, MD5_MECH_INFO_TYPE,
 322             CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 0, 0,
 323             CRYPTO_KEYSIZE_UNIT_IN_BITS},
 324         /* MD5-HMAC */
 325         {SUN_CKM_MD5_HMAC, MD5_HMAC_MECH_INFO_TYPE,
 326             CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
 327             CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
 328             CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
 329             CRYPTO_FG_ENCRYPT_MAC | CRYPTO_FG_MAC_DECRYPT |
 330             CRYPTO_FG_ENCRYPT_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
 331             MD5_HMAC_MIN_KEY_LEN, MD5_HMAC_MAX_KEY_LEN,
 332             CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 333         /* MD5-HMAC GENERAL */
 334         {SUN_CKM_MD5_HMAC_GENERAL, MD5_HMAC_GEN_MECH_INFO_TYPE,
 335             CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
 336             CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
 337             CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
 338             CRYPTO_FG_ENCRYPT_MAC | CRYPTO_FG_MAC_DECRYPT |
 339             CRYPTO_FG_ENCRYPT_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
 340             MD5_HMAC_MIN_KEY_LEN, MD5_HMAC_MAX_KEY_LEN,
 341             CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 342         /* SHA1 */
 343         {SUN_CKM_SHA1, SHA1_MECH_INFO_TYPE,
 344             CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 0, 0,
 345             CRYPTO_KEYSIZE_UNIT_IN_BITS},
 346         /* SHA1-HMAC */
 347         {SUN_CKM_SHA1_HMAC, SHA1_HMAC_MECH_INFO_TYPE,
 348             CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
 349             CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
 350             CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
 351             CRYPTO_FG_ENCRYPT_MAC | CRYPTO_FG_MAC_DECRYPT |
 352             CRYPTO_FG_ENCRYPT_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
 353             SHA1_HMAC_MIN_KEY_LEN, SHA1_HMAC_MAX_KEY_LEN,
 354             CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 355         /* SHA1-HMAC GENERAL */
 356         {SUN_CKM_SHA1_HMAC_GENERAL, SHA1_HMAC_GEN_MECH_INFO_TYPE,
 357             CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
 358             CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
 359             CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
 360             CRYPTO_FG_ENCRYPT_MAC | CRYPTO_FG_MAC_DECRYPT |
 361             CRYPTO_FG_ENCRYPT_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
 362             SHA1_HMAC_MIN_KEY_LEN, SHA1_HMAC_MAX_KEY_LEN,
 363             CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 364         /* SHA256 */
 365         {SUN_CKM_SHA256, SHA256_MECH_INFO_TYPE,
 366             CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 0, 0,
 367             CRYPTO_KEYSIZE_UNIT_IN_BITS},
 368         /* SHA256-HMAC */
 369         {SUN_CKM_SHA256_HMAC, SHA256_HMAC_MECH_INFO_TYPE,
 370             CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
 371             CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
 372             CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
 373             CRYPTO_FG_ENCRYPT_MAC | CRYPTO_FG_MAC_DECRYPT |
 374             CRYPTO_FG_ENCRYPT_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
 375             SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
 376             CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 377         /* SHA256-HMAC GENERAL */
 378         {SUN_CKM_SHA256_HMAC_GENERAL, SHA256_HMAC_GEN_MECH_INFO_TYPE,
 379             CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
 380             CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
 381             CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
 382             CRYPTO_FG_ENCRYPT_MAC | CRYPTO_FG_MAC_DECRYPT |
 383             CRYPTO_FG_ENCRYPT_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
 384             SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
 385             CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 386         /* SHA384 */
 387         {SUN_CKM_SHA384, SHA384_MECH_INFO_TYPE,
 388             CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 0, 0,
 389             CRYPTO_KEYSIZE_UNIT_IN_BITS},
 390         /* SHA384-HMAC */
 391         {SUN_CKM_SHA384_HMAC, SHA384_HMAC_MECH_INFO_TYPE,
 392             CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
 393             CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
 394             CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
 395             CRYPTO_FG_ENCRYPT_MAC | CRYPTO_FG_MAC_DECRYPT |
 396             CRYPTO_FG_ENCRYPT_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
 397             SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
 398             CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 399         /* SHA384-HMAC GENERAL */
 400         {SUN_CKM_SHA384_HMAC_GENERAL, SHA384_HMAC_GEN_MECH_INFO_TYPE,
 401             CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
 402             CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
 403             CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
 404             CRYPTO_FG_ENCRYPT_MAC | CRYPTO_FG_MAC_DECRYPT |
 405             CRYPTO_FG_ENCRYPT_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
 406             SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
 407             CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 408         /* SHA512 */
 409         {SUN_CKM_SHA512, SHA512_MECH_INFO_TYPE,
 410             CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 0, 0,
 411             CRYPTO_KEYSIZE_UNIT_IN_BITS},
 412         /* SHA512-HMAC */
 413         {SUN_CKM_SHA512_HMAC, SHA512_HMAC_MECH_INFO_TYPE,
 414             CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
 415             CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
 416             CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
 417             CRYPTO_FG_ENCRYPT_MAC | CRYPTO_FG_MAC_DECRYPT |
 418             CRYPTO_FG_ENCRYPT_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
 419             SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
 420             CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 421         /* SHA512-HMAC GENERAL */
 422         {SUN_CKM_SHA512_HMAC_GENERAL, SHA512_HMAC_GEN_MECH_INFO_TYPE,
 423             CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
 424             CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
 425             CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
 426             CRYPTO_FG_ENCRYPT_MAC | CRYPTO_FG_MAC_DECRYPT |
 427             CRYPTO_FG_ENCRYPT_MAC_ATOMIC | CRYPTO_FG_MAC_DECRYPT_ATOMIC,
 428             SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
 429             CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 430         /* DES-CBC */
 431         {SUN_CKM_DES_CBC, DES_CBC_MECH_INFO_TYPE,
 432             CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_ENCRYPT_MAC |
 433             CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
 434             CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
 435             CRYPTO_FG_MAC_DECRYPT_ATOMIC,
 436             DES_KEY_LEN, DES_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 437         /* DES3-CBC */
 438         {SUN_CKM_DES3_CBC, DES3_CBC_MECH_INFO_TYPE,
 439             CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_ENCRYPT_MAC |
 440             CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
 441             CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
 442             CRYPTO_FG_MAC_DECRYPT_ATOMIC,
 443             DES3_KEY_LEN, DES3_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 444         /* DES-ECB */
 445         {SUN_CKM_DES_ECB, DES_ECB_MECH_INFO_TYPE,
 446             CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_ENCRYPT_MAC |
 447             CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
 448             CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
 449             CRYPTO_FG_MAC_DECRYPT_ATOMIC,
 450             DES_KEY_LEN, DES_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 451         /* DES3-ECB */
 452         {SUN_CKM_DES3_ECB, DES3_ECB_MECH_INFO_TYPE,
 453             CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_ENCRYPT_MAC |
 454             CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
 455             CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
 456             CRYPTO_FG_MAC_DECRYPT_ATOMIC,
 457             DES3_KEY_LEN, DES3_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 458         /* BLOWFISH-CBC */
 459         {SUN_CKM_BLOWFISH_CBC, BLOWFISH_CBC_MECH_INFO_TYPE,
 460             CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_ENCRYPT_MAC |
 461             CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
 462             CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
 463             CRYPTO_FG_MAC_DECRYPT_ATOMIC, BLOWFISH_MIN_KEY_LEN,
 464             BLOWFISH_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
 465         /* BLOWFISH-ECB */
 466         {SUN_CKM_BLOWFISH_ECB, BLOWFISH_ECB_MECH_INFO_TYPE,
 467             CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_ENCRYPT_MAC |
 468             CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
 469             CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
 470             CRYPTO_FG_MAC_DECRYPT_ATOMIC, BLOWFISH_MIN_KEY_LEN,
 471             BLOWFISH_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
 472         /* AES-CBC */
 473         {SUN_CKM_AES_CBC, AES_CBC_MECH_INFO_TYPE,
 474             CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_ENCRYPT_MAC |
 475             CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
 476             CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
 477             CRYPTO_FG_MAC_DECRYPT_ATOMIC,
 478             AES_MIN_KEY_LEN, AES_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 479         /* AES-ECB */
 480         {SUN_CKM_AES_ECB, AES_ECB_MECH_INFO_TYPE,
 481             CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_ENCRYPT_MAC |
 482             CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
 483             CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
 484             CRYPTO_FG_MAC_DECRYPT_ATOMIC,
 485             AES_MIN_KEY_LEN, AES_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 486         /* AES-CTR */
 487         {SUN_CKM_AES_CTR, AES_CTR_MECH_INFO_TYPE,
 488             CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_ENCRYPT_MAC |
 489             CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
 490             CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
 491             CRYPTO_FG_MAC_DECRYPT_ATOMIC,
 492             AES_MIN_KEY_LEN, AES_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 493         /* AES-CCM */
 494         {SUN_CKM_AES_CCM, AES_CCM_MECH_INFO_TYPE,
 495             CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_ENCRYPT_MAC |
 496             CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
 497             CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
 498             CRYPTO_FG_MAC_DECRYPT_ATOMIC,
 499             AES_MIN_KEY_LEN, AES_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 500         /* AES-GCM */
 501         {SUN_CKM_AES_GCM, AES_GCM_MECH_INFO_TYPE,
 502             CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_ENCRYPT_MAC |
 503             CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
 504             CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
 505             CRYPTO_FG_MAC_DECRYPT_ATOMIC,
 506             AES_MIN_KEY_LEN, AES_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 507         /* AES-GMAC */
 508         {SUN_CKM_AES_GMAC, AES_GMAC_MECH_INFO_TYPE,
 509             CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_ENCRYPT_MAC |
 510             CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
 511             CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
 512             CRYPTO_FG_MAC_DECRYPT_ATOMIC |
 513             CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
 514             CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
 515             AES_MIN_KEY_LEN, AES_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 516         /* RC4 */
 517         {SUN_CKM_RC4, RC4_MECH_INFO_TYPE,
 518             CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
 519             CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC,
 520             ARCFOUR_MIN_KEY_BITS, ARCFOUR_MAX_KEY_BITS,
 521             CRYPTO_KEYSIZE_UNIT_IN_BITS | CRYPTO_CAN_SHARE_OPSTATE},
 522         /* RSA_PKCS */
 523         {SUN_CKM_RSA_PKCS, RSA_PKCS_MECH_INFO_TYPE,
 524             CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
 525             CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC |
 526             CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
 527             CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
 528             CRYPTO_FG_SIGN_RECOVER | CRYPTO_FG_SIGN_RECOVER_ATOMIC |
 529             CRYPTO_FG_VERIFY_RECOVER | CRYPTO_FG_VERIFY_RECOVER_ATOMIC,
 530             RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
 531         /* RSA_X_509 */
 532         {SUN_CKM_RSA_X_509, RSA_X_509_MECH_INFO_TYPE,
 533             CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
 534             CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC |
 535             CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
 536             CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC |
 537             CRYPTO_FG_SIGN_RECOVER | CRYPTO_FG_SIGN_RECOVER_ATOMIC |
 538             CRYPTO_FG_VERIFY_RECOVER | CRYPTO_FG_VERIFY_RECOVER_ATOMIC,
 539             RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
 540         /* MD5_RSA_PKCS */
 541         {SUN_CKM_MD5_RSA_PKCS, MD5_RSA_PKCS_MECH_INFO_TYPE,
 542             CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
 543             CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
 544             RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
 545         /* SHA1_RSA_PKCS */
 546         {SUN_CKM_SHA1_RSA_PKCS, SHA1_RSA_PKCS_MECH_INFO_TYPE,
 547             CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
 548             CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
 549             RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
 550         /* SHA256_RSA_PKCS */
 551         {SUN_CKM_SHA256_RSA_PKCS, SHA256_RSA_PKCS_MECH_INFO_TYPE,
 552             CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
 553             CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
 554             RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
 555         /* SHA384_RSA_PKCS */
 556         {SUN_CKM_SHA384_RSA_PKCS, SHA384_RSA_PKCS_MECH_INFO_TYPE,
 557             CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
 558             CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
 559             RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
 560         /* SHA512_RSA_PKCS */
 561         {SUN_CKM_SHA512_RSA_PKCS, SHA512_RSA_PKCS_MECH_INFO_TYPE,
 562             CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
 563             CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
 564             RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
 565         /* MD5_KEY_DERIVATION */
 566         {DPROV_CKM_MD5_KEY_DERIVATION, MD5_KEY_DERIVATION_MECH_INFO_TYPE,
 567             CRYPTO_FG_DERIVE, 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS},
 568         /* SHA1_KEY_DERIVATION */
 569         {DPROV_CKM_SHA1_KEY_DERIVATION, SHA1_KEY_DERIVATION_MECH_INFO_TYPE,
 570             CRYPTO_FG_DERIVE, 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS},
 571         /* SHA256_KEY_DERIVATION */
 572         {DPROV_CKM_SHA256_KEY_DERIVATION, SHA256_KEY_DERIVATION_MECH_INFO_TYPE,
 573             CRYPTO_FG_DERIVE, 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS},
 574         /* SHA384_KEY_DERIVATION */
 575         {DPROV_CKM_SHA384_KEY_DERIVATION, SHA384_KEY_DERIVATION_MECH_INFO_TYPE,
 576             CRYPTO_FG_DERIVE, 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS},
 577         /* SHA512_KEY_DERIVATION */
 578         {DPROV_CKM_SHA512_KEY_DERIVATION, SHA512_KEY_DERIVATION_MECH_INFO_TYPE,
 579             CRYPTO_FG_DERIVE, 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS},
 580         /* DES_KEY_GENERATION */
 581         {DPROV_CKM_DES_KEY_GEN, DES_KEY_GEN_MECH_INFO_TYPE,
 582             CRYPTO_FG_GENERATE, DES_KEY_LEN, DES_KEY_LEN,
 583             CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 584         /* DES3_KEY_GENERATION */
 585         {DPROV_CKM_DES3_KEY_GEN, DES3_KEY_GEN_MECH_INFO_TYPE,
 586             CRYPTO_FG_GENERATE, DES3_KEY_LEN, DES3_KEY_LEN,
 587             CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 588         /* AES_KEY_GENERATION */
 589         {DPROV_CKM_AES_KEY_GEN, AES_KEY_GEN_MECH_INFO_TYPE,
 590             CRYPTO_FG_GENERATE, AES_MIN_KEY_LEN, AES_MAX_KEY_LEN,
 591             CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 592         /* BLOWFISH_KEY_GENERATION */
 593         {DPROV_CKM_BLOWFISH_KEY_GEN, BLOWFISH_KEY_GEN_MECH_INFO_TYPE,
 594             CRYPTO_FG_GENERATE, BLOWFISH_MIN_KEY_LEN, BLOWFISH_MAX_KEY_LEN,
 595             CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 596         /* RC4_KEY_GENERATION */
 597         {DPROV_CKM_RC4_KEY_GEN, RC4_KEY_GEN_MECH_INFO_TYPE,
 598             CRYPTO_FG_GENERATE, ARCFOUR_MIN_KEY_BITS, ARCFOUR_MAX_KEY_BITS,
 599             CRYPTO_KEYSIZE_UNIT_IN_BITS},
 600         /* DH_PKCS_KEY_PAIR_GEN */
 601         {DPROV_CKM_DH_PKCS_KEY_PAIR_GEN, DH_PKCS_KEY_PAIR_GEN_MECH_INFO_TYPE,
 602             CRYPTO_FG_GENERATE_KEY_PAIR, DH_MIN_KEY_LEN, DH_MAX_KEY_LEN,
 603             CRYPTO_KEYSIZE_UNIT_IN_BITS},
 604         /* DH_PKCS_DERIVE */
 605         {DPROV_CKM_DH_PKCS_DERIVE, DH_PKCS_DERIVE_MECH_INFO_TYPE,
 606             CRYPTO_FG_DERIVE, 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS},
 607         /* RSA_PKCS_KEY_PAIR_GEN */
 608         {DPROV_CKM_RSA_PKCS_KEY_PAIR_GEN, RSA_PKCS_KEY_PAIR_GEN_MECH_INFO_TYPE,
 609             CRYPTO_FG_GENERATE_KEY_PAIR, RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN,
 610             CRYPTO_KEYSIZE_UNIT_IN_BITS},
 611         /* EC_KEY_PAIR_GEN */
 612         {DPROV_CKM_EC_KEY_PAIR_GEN, EC_KEY_PAIR_GEN_MECH_INFO_TYPE,
 613             CRYPTO_FG_GENERATE_KEY_PAIR, EC_MIN_KEY_LEN, EC_MAX_KEY_LEN,
 614             CRYPTO_KEYSIZE_UNIT_IN_BITS},
 615         /* ECDSA */
 616         {DPROV_CKM_ECDSA, ECDSA_MECH_INFO_TYPE,
 617             CRYPTO_FG_SIGN | CRYPTO_FG_VERIFY |
 618             CRYPTO_FG_SIGN_ATOMIC | CRYPTO_FG_VERIFY_ATOMIC |
 619             EC_MIN_KEY_LEN, EC_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
 620         /* ECDSA_SHA1 */
 621         {DPROV_CKM_ECDSA_SHA1, ECDSA_SHA1_MECH_INFO_TYPE,
 622             CRYPTO_FG_SIGN | CRYPTO_FG_VERIFY |
 623             CRYPTO_FG_SIGN_ATOMIC | CRYPTO_FG_VERIFY_ATOMIC |
 624             EC_MIN_KEY_LEN, EC_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
 625         /* ECDH1_DERIVE */
 626         {DPROV_CKM_ECDH1_DERIVE, ECDH1_DERIVE_MECH_INFO_TYPE,
 627             CRYPTO_FG_DERIVE, 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS}
 628 };
 629 
 630 /*
 631  * Crypto Values
 632  *
 633  * These values are the used in the STC ef test suite.  If they are changed
 634  * the test suite needs to be changed.
 635  */
 636 static uchar_t dh_value[8] = { 'd', 'h', 'd', 'h', 'd', 'h', 'd', '\0' };
 637 char public_exponent[3] = { 0x01, 0x00, 0x01 };
 638 static uchar_t private_exponent[128] = {
 639         0x8e, 0xc9, 0x70, 0x57, 0x6b, 0xcd, 0xfb, 0xa9,
 640         0x19, 0xad, 0xcd, 0x91, 0x69, 0xd5, 0x52, 0xec,
 641         0x72, 0x1e, 0x45, 0x15, 0x06, 0xdc, 0x65, 0x2d,
 642         0x98, 0xc4, 0xce, 0x33, 0x54, 0x15, 0x70, 0x8d,
 643         0xfa, 0x65, 0xea, 0x53, 0x44, 0xf3, 0x3e, 0x3f,
 644         0xb4, 0x4c, 0x60, 0xd5, 0x01, 0x2d, 0xa4, 0x12,
 645         0x99, 0xbf, 0x3f, 0x0b, 0xcd, 0xbb, 0x24, 0x10,
 646         0x60, 0x30, 0x5e, 0x58, 0xf8, 0x59, 0xaa, 0xd1,
 647         0x63, 0x3b, 0xbc, 0xcb, 0x94, 0x58, 0x38, 0x24,
 648         0xfc, 0x65, 0x25, 0xc5, 0xa6, 0x51, 0xa2, 0x2e,
 649         0xf1, 0x5e, 0xf5, 0xc1, 0xf5, 0x46, 0xf7, 0xbd,
 650         0xc7, 0x62, 0xa8, 0xe2, 0x27, 0xd6, 0x94, 0x5b,
 651         0xd3, 0xa2, 0xb5, 0x76, 0x42, 0x67, 0x6b, 0x86,
 652         0x91, 0x97, 0x4d, 0x07, 0x92, 0x00, 0x4a, 0xdf,
 653         0x0b, 0x65, 0x64, 0x05, 0x03, 0x48, 0x27, 0xeb,
 654         0xce, 0x9a, 0x49, 0x7f, 0x3e, 0x10, 0xe0, 0x01
 655 };
 656 
 657 static uchar_t modulus[128] = {
 658         0x94, 0x32, 0xb9, 0x12, 0x1d, 0x68, 0x2c, 0xda,
 659         0x2b, 0xe0, 0xe4, 0x97, 0x1b, 0x4d, 0xdc, 0x43,
 660         0xdf, 0x38, 0x6e, 0x7b, 0x9f, 0x07, 0x58, 0xae,
 661         0x9d, 0x82, 0x1e, 0xc7, 0xbc, 0x92, 0xbf, 0xd3,
 662         0xce, 0x00, 0xbb, 0x91, 0xc9, 0x79, 0x06, 0x03,
 663         0x1f, 0xbc, 0x9f, 0x94, 0x75, 0x29, 0x5f, 0xd7,
 664         0xc5, 0xf3, 0x73, 0x8a, 0xa4, 0x35, 0x43, 0x7a,
 665         0x00, 0x32, 0x97, 0x3e, 0x86, 0xef, 0x70, 0x6f,
 666         0x18, 0x56, 0x15, 0xaa, 0x6a, 0x87, 0xe7, 0x8d,
 667         0x7d, 0xdd, 0x1f, 0xa4, 0xe4, 0x31, 0xd4, 0x7a,
 668         0x8c, 0x0e, 0x20, 0xd2, 0x23, 0xf5, 0x57, 0x3c,
 669         0x1b, 0xa8, 0x44, 0xa4, 0x57, 0x8f, 0x33, 0x52,
 670         0xad, 0x83, 0xae, 0x4a, 0x97, 0xa6, 0x1e, 0xa6,
 671         0x2b, 0xfa, 0xea, 0xeb, 0x6e, 0x71, 0xb8, 0xb6,
 672         0x0a, 0x36, 0xed, 0x83, 0xce, 0xb0, 0xdf, 0xc1,
 673         0xd4, 0x3a, 0xe9, 0x99, 0x6f, 0xf3, 0x96, 0xb7
 674 };
 675 
 676 
 677 static void dprov_provider_status(crypto_provider_handle_t, uint_t *);
 678 
 679 static crypto_control_ops_t dprov_control_ops = {
 680         dprov_provider_status
 681 };
 682 
 683 #define DPROV_MANUFACTURER      "SUNW                            "
 684 #define DPROV_MODEL             "dprov           "
 685 #define DPROV_ALLSPACES         "                "
 686 
 687 static int dprov_digest_init(crypto_ctx_t *, crypto_mechanism_t *,
 688     crypto_req_handle_t);
 689 static int dprov_digest(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
 690     crypto_req_handle_t);
 691 static int dprov_digest_update(crypto_ctx_t *, crypto_data_t *,
 692     crypto_req_handle_t);
 693 static int dprov_digest_key(crypto_ctx_t *, crypto_key_t *,
 694     crypto_req_handle_t);
 695 static int dprov_digest_final(crypto_ctx_t *, crypto_data_t *,
 696     crypto_req_handle_t);
 697 static int dprov_digest_atomic(crypto_provider_handle_t, crypto_session_id_t,
 698     crypto_mechanism_t *, crypto_data_t *, crypto_data_t *,
 699     crypto_req_handle_t);
 700 
 701 static crypto_digest_ops_t dprov_digest_ops = {
 702         dprov_digest_init,
 703         dprov_digest,
 704         dprov_digest_update,
 705         dprov_digest_key,
 706         dprov_digest_final,
 707         dprov_digest_atomic
 708 };
 709 
 710 static int dprov_mac_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *,
 711     crypto_spi_ctx_template_t, crypto_req_handle_t);
 712 static int dprov_mac(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
 713     crypto_req_handle_t);
 714 static int dprov_mac_update(crypto_ctx_t *, crypto_data_t *,
 715     crypto_req_handle_t);
 716 static int dprov_mac_final(crypto_ctx_t *, crypto_data_t *,
 717     crypto_req_handle_t);
 718 static int dprov_mac_atomic(crypto_provider_handle_t, crypto_session_id_t,
 719     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
 720     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
 721 static int dprov_mac_verify_atomic(crypto_provider_handle_t,
 722     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
 723     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
 724 
 725 static crypto_mac_ops_t dprov_mac_ops = {
 726         dprov_mac_init,
 727         dprov_mac,
 728         dprov_mac_update,
 729         dprov_mac_final,
 730         dprov_mac_atomic,
 731         dprov_mac_verify_atomic
 732 };
 733 
 734 static int dprov_encrypt_init(crypto_ctx_t *, crypto_mechanism_t *,
 735     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
 736 static int dprov_encrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
 737     crypto_req_handle_t);
 738 static int dprov_encrypt_update(crypto_ctx_t *, crypto_data_t *,
 739     crypto_data_t *, crypto_req_handle_t);
 740 static int dprov_encrypt_final(crypto_ctx_t *, crypto_data_t *,
 741     crypto_req_handle_t);
 742 static int dprov_encrypt_atomic(crypto_provider_handle_t, crypto_session_id_t,
 743     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
 744     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
 745 
 746 static int dprov_decrypt_init(crypto_ctx_t *, crypto_mechanism_t *,
 747     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
 748 static int dprov_decrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
 749     crypto_req_handle_t);
 750 static int dprov_decrypt_update(crypto_ctx_t *, crypto_data_t *,
 751     crypto_data_t *, crypto_req_handle_t);
 752 static int dprov_decrypt_final(crypto_ctx_t *, crypto_data_t *,
 753     crypto_req_handle_t);
 754 static int dprov_decrypt_atomic(crypto_provider_handle_t, crypto_session_id_t,
 755     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
 756     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
 757 
 758 static crypto_cipher_ops_t dprov_cipher_ops = {
 759         dprov_encrypt_init,
 760         dprov_encrypt,
 761         dprov_encrypt_update,
 762         dprov_encrypt_final,
 763         dprov_encrypt_atomic,
 764         dprov_decrypt_init,
 765         dprov_decrypt,
 766         dprov_decrypt_update,
 767         dprov_decrypt_final,
 768         dprov_decrypt_atomic
 769 };
 770 
 771 static int dprov_sign_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *,
 772     crypto_spi_ctx_template_t, crypto_req_handle_t);
 773 static int dprov_sign(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
 774     crypto_req_handle_t);
 775 static int dprov_sign_update(crypto_ctx_t *, crypto_data_t *,
 776     crypto_req_handle_t);
 777 static int dprov_sign_final(crypto_ctx_t *, crypto_data_t *,
 778     crypto_req_handle_t);
 779 static int dprov_sign_atomic(crypto_provider_handle_t, crypto_session_id_t,
 780     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
 781     crypto_spi_ctx_template_t, crypto_req_handle_t);
 782 static int dprov_sign_recover_init(crypto_ctx_t *, crypto_mechanism_t *,
 783     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
 784 static int dprov_sign_recover(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
 785     crypto_req_handle_t);
 786 static int dprov_sign_recover_atomic(crypto_provider_handle_t,
 787     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
 788     crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t,
 789     crypto_req_handle_t);
 790 
 791 static crypto_sign_ops_t dprov_sign_ops = {
 792         dprov_sign_init,
 793         dprov_sign,
 794         dprov_sign_update,
 795         dprov_sign_final,
 796         dprov_sign_atomic,
 797         dprov_sign_recover_init,
 798         dprov_sign_recover,
 799         dprov_sign_recover_atomic
 800 };
 801 
 802 static int dprov_verify_init(crypto_ctx_t *, crypto_mechanism_t *,
 803     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
 804 static int dprov_verify(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
 805     crypto_req_handle_t);
 806 static int dprov_verify_update(crypto_ctx_t *, crypto_data_t *,
 807     crypto_req_handle_t);
 808 static int dprov_verify_final(crypto_ctx_t *, crypto_data_t *,
 809     crypto_req_handle_t);
 810 static int dprov_verify_atomic(crypto_provider_handle_t, crypto_session_id_t,
 811     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
 812     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
 813 static int dprov_verify_recover_init(crypto_ctx_t *, crypto_mechanism_t *,
 814     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
 815 static int dprov_verify_recover(crypto_ctx_t *, crypto_data_t *,
 816     crypto_data_t *, crypto_req_handle_t);
 817 static int dprov_verify_recover_atomic(crypto_provider_handle_t,
 818     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
 819     crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t,
 820     crypto_req_handle_t);
 821 
 822 static crypto_verify_ops_t dprov_verify_ops = {
 823         dprov_verify_init,
 824         dprov_verify,
 825         dprov_verify_update,
 826         dprov_verify_final,
 827         dprov_verify_atomic,
 828         dprov_verify_recover_init,
 829         dprov_verify_recover,
 830         dprov_verify_recover_atomic
 831 };
 832 
 833 static int dprov_digest_encrypt_update(crypto_ctx_t *, crypto_ctx_t *,
 834     crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
 835 static int dprov_decrypt_digest_update(crypto_ctx_t *, crypto_ctx_t *,
 836     crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
 837 static int dprov_sign_encrypt_update(crypto_ctx_t *, crypto_ctx_t *,
 838     crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
 839 static int dprov_decrypt_verify_update(crypto_ctx_t *, crypto_ctx_t *,
 840     crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
 841 
 842 static crypto_dual_ops_t dprov_dual_ops = {
 843         dprov_digest_encrypt_update,
 844         dprov_decrypt_digest_update,
 845         dprov_sign_encrypt_update,
 846         dprov_decrypt_verify_update
 847 };
 848 
 849 static int dprov_encrypt_mac_init(crypto_ctx_t *,
 850     crypto_mechanism_t *, crypto_key_t *, crypto_mechanism_t *,
 851     crypto_key_t *, crypto_spi_ctx_template_t,
 852     crypto_spi_ctx_template_t, crypto_req_handle_t);
 853 static int dprov_encrypt_mac(crypto_ctx_t *,
 854     crypto_data_t *, crypto_dual_data_t *, crypto_data_t *,
 855     crypto_req_handle_t);
 856 static int dprov_encrypt_mac_update(crypto_ctx_t *,
 857     crypto_data_t *, crypto_dual_data_t *, crypto_req_handle_t);
 858 static int dprov_encrypt_mac_final(crypto_ctx_t *,
 859     crypto_dual_data_t *, crypto_data_t *, crypto_req_handle_t);
 860 static int dprov_encrypt_mac_atomic(crypto_provider_handle_t,
 861     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
 862     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
 863     crypto_dual_data_t *, crypto_data_t *, crypto_spi_ctx_template_t,
 864     crypto_spi_ctx_template_t, crypto_req_handle_t);
 865 
 866 static int dprov_mac_decrypt_init(crypto_ctx_t *,
 867     crypto_mechanism_t *, crypto_key_t *, crypto_mechanism_t *,
 868     crypto_key_t *, crypto_spi_ctx_template_t,
 869     crypto_spi_ctx_template_t, crypto_req_handle_t);
 870 static int dprov_mac_decrypt(crypto_ctx_t *,
 871     crypto_dual_data_t *, crypto_data_t *, crypto_data_t *,
 872     crypto_req_handle_t);
 873 static int dprov_mac_decrypt_update(crypto_ctx_t *,
 874     crypto_dual_data_t *, crypto_data_t *, crypto_req_handle_t);
 875 static int dprov_mac_decrypt_final(crypto_ctx_t *,
 876     crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
 877 static int dprov_mac_decrypt_atomic(crypto_provider_handle_t,
 878     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
 879     crypto_mechanism_t *, crypto_key_t *, crypto_dual_data_t *,
 880     crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t,
 881     crypto_spi_ctx_template_t, crypto_req_handle_t);
 882 static int dprov_mac_verify_decrypt_atomic(crypto_provider_handle_t,
 883     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
 884     crypto_mechanism_t *, crypto_key_t *, crypto_dual_data_t *,
 885     crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t,
 886     crypto_spi_ctx_template_t, crypto_req_handle_t);
 887 
 888 static crypto_dual_cipher_mac_ops_t dprov_cipher_mac_ops = {
 889         dprov_encrypt_mac_init,
 890         dprov_encrypt_mac,
 891         dprov_encrypt_mac_update,
 892         dprov_encrypt_mac_final,
 893         dprov_encrypt_mac_atomic,
 894         dprov_mac_decrypt_init,
 895         dprov_mac_decrypt,
 896         dprov_mac_decrypt_update,
 897         dprov_mac_decrypt_final,
 898         dprov_mac_decrypt_atomic,
 899         dprov_mac_verify_decrypt_atomic
 900 };
 901 
 902 static int dprov_seed_random(crypto_provider_handle_t, crypto_session_id_t,
 903     uchar_t *, size_t, uint_t, uint32_t, crypto_req_handle_t);
 904 static int dprov_generate_random(crypto_provider_handle_t, crypto_session_id_t,
 905     uchar_t *, size_t, crypto_req_handle_t);
 906 
 907 static crypto_random_number_ops_t dprov_random_number_ops = {
 908         dprov_seed_random,
 909         dprov_generate_random
 910 };
 911 
 912 static int dprov_session_open(crypto_provider_handle_t, crypto_session_id_t *,
 913     crypto_req_handle_t);
 914 static int dprov_session_close(crypto_provider_handle_t, crypto_session_id_t,
 915     crypto_req_handle_t);
 916 static int dprov_session_login(crypto_provider_handle_t, crypto_session_id_t,
 917     crypto_user_type_t, char *, size_t, crypto_req_handle_t);
 918 static int dprov_session_logout(crypto_provider_handle_t, crypto_session_id_t,
 919     crypto_req_handle_t);
 920 
 921 static crypto_session_ops_t dprov_session_ops = {
 922         dprov_session_open,
 923         dprov_session_close,
 924         dprov_session_login,
 925         dprov_session_logout
 926 };
 927 
 928 static int dprov_object_create(crypto_provider_handle_t, crypto_session_id_t,
 929     crypto_object_attribute_t *, uint_t, crypto_object_id_t *,
 930     crypto_req_handle_t);
 931 static int dprov_object_copy(crypto_provider_handle_t, crypto_session_id_t,
 932     crypto_object_id_t, crypto_object_attribute_t *, uint_t,
 933     crypto_object_id_t *, crypto_req_handle_t);
 934 static int dprov_object_destroy(crypto_provider_handle_t, crypto_session_id_t,
 935     crypto_object_id_t, crypto_req_handle_t);
 936 static int dprov_object_get_size(crypto_provider_handle_t, crypto_session_id_t,
 937     crypto_object_id_t, size_t *, crypto_req_handle_t);
 938 static int dprov_object_get_attribute_value(crypto_provider_handle_t,
 939     crypto_session_id_t, crypto_object_id_t,
 940     crypto_object_attribute_t *, uint_t, crypto_req_handle_t);
 941 static int dprov_object_set_attribute_value(crypto_provider_handle_t,
 942     crypto_session_id_t, crypto_object_id_t,
 943     crypto_object_attribute_t *,  uint_t, crypto_req_handle_t);
 944 static int dprov_object_find_init(crypto_provider_handle_t, crypto_session_id_t,
 945     crypto_object_attribute_t *, uint_t, void **,
 946     crypto_req_handle_t);
 947 static int dprov_object_find(crypto_provider_handle_t, void *,
 948     crypto_object_id_t *, uint_t, uint_t *, crypto_req_handle_t);
 949 static int dprov_object_find_final(crypto_provider_handle_t, void *,
 950     crypto_req_handle_t);
 951 
 952 static crypto_object_ops_t dprov_object_ops = {
 953         dprov_object_create,
 954         dprov_object_copy,
 955         dprov_object_destroy,
 956         dprov_object_get_size,
 957         dprov_object_get_attribute_value,
 958         dprov_object_set_attribute_value,
 959         dprov_object_find_init,
 960         dprov_object_find,
 961         dprov_object_find_final
 962 };
 963 
 964 static int dprov_key_generate(crypto_provider_handle_t, crypto_session_id_t,
 965     crypto_mechanism_t *, crypto_object_attribute_t *, uint_t,
 966     crypto_object_id_t *, crypto_req_handle_t);
 967 static int dprov_key_generate_pair(crypto_provider_handle_t,
 968     crypto_session_id_t, crypto_mechanism_t *, crypto_object_attribute_t *,
 969     uint_t, crypto_object_attribute_t *, uint_t, crypto_object_id_t *,
 970     crypto_object_id_t *, crypto_req_handle_t);
 971 static int dprov_key_wrap(crypto_provider_handle_t, crypto_session_id_t,
 972     crypto_mechanism_t *, crypto_key_t *, crypto_object_id_t *,
 973     uchar_t *, size_t *, crypto_req_handle_t);
 974 static int dprov_key_unwrap(crypto_provider_handle_t, crypto_session_id_t,
 975     crypto_mechanism_t *, crypto_key_t *, uchar_t *, size_t *,
 976     crypto_object_attribute_t *, uint_t,
 977     crypto_object_id_t *, crypto_req_handle_t);
 978 static int dprov_key_derive(crypto_provider_handle_t, crypto_session_id_t,
 979     crypto_mechanism_t *, crypto_key_t *, crypto_object_attribute_t *,
 980     uint_t, crypto_object_id_t *, crypto_req_handle_t);
 981 
 982 static crypto_key_ops_t dprov_key_ops = {
 983         dprov_key_generate,
 984         dprov_key_generate_pair,
 985         dprov_key_wrap,
 986         dprov_key_unwrap,
 987         dprov_key_derive
 988 };
 989 
 990 static int dprov_ext_info(crypto_provider_handle_t,
 991     crypto_provider_ext_info_t *, crypto_req_handle_t);
 992 static int dprov_init_token(crypto_provider_handle_t, char *, size_t,
 993     char *, crypto_req_handle_t);
 994 static int dprov_init_pin(crypto_provider_handle_t, crypto_session_id_t,
 995     char *, size_t, crypto_req_handle_t);
 996 static int dprov_set_pin(crypto_provider_handle_t, crypto_session_id_t,
 997     char *, size_t, char *, size_t, crypto_req_handle_t);
 998 
 999 static crypto_provider_management_ops_t dprov_management_ops = {
1000         dprov_ext_info,
1001         dprov_init_token,
1002         dprov_init_pin,
1003         dprov_set_pin
1004 };
1005 
1006 static int dprov_free_context(crypto_ctx_t *);
1007 static int dprov_copyin_mechanism(crypto_provider_handle_t,
1008     crypto_mechanism_t *, crypto_mechanism_t *, int *error, int);
1009 static int dprov_copyout_mechanism(crypto_provider_handle_t,
1010     crypto_mechanism_t *, crypto_mechanism_t *, int *error, int);
1011 static int dprov_free_mechanism(crypto_provider_handle_t,
1012     crypto_mechanism_t *);
1013 
1014 static crypto_ctx_ops_t dprov_ctx_ops = {
1015         NULL,
1016         dprov_free_context
1017 };
1018 
1019 static crypto_mech_ops_t dprov_mech_ops = {
1020         dprov_copyin_mechanism,
1021         dprov_copyout_mechanism,
1022         dprov_free_mechanism
1023 };
1024 
1025 static int dprov_nostore_key_generate(crypto_provider_handle_t,
1026     crypto_session_id_t, crypto_mechanism_t *, crypto_object_attribute_t *,
1027     uint_t, crypto_object_attribute_t *, uint_t, crypto_req_handle_t);
1028 static int dprov_nostore_key_generate_pair(crypto_provider_handle_t,
1029     crypto_session_id_t, crypto_mechanism_t *, crypto_object_attribute_t *,
1030     uint_t, crypto_object_attribute_t *, uint_t, crypto_object_attribute_t *,
1031     uint_t, crypto_object_attribute_t *, uint_t, crypto_req_handle_t);
1032 static int dprov_nostore_key_derive(crypto_provider_handle_t,
1033     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
1034     crypto_object_attribute_t *, uint_t, crypto_object_attribute_t *,
1035     uint_t, crypto_req_handle_t);
1036 
1037 static crypto_nostore_key_ops_t dprov_nostore_key_ops = {
1038         dprov_nostore_key_generate,
1039         dprov_nostore_key_generate_pair,
1040         dprov_nostore_key_derive
1041 };
1042 
1043 static crypto_ops_t dprov_crypto_ops = {
1044         &dprov_control_ops,
1045         &dprov_digest_ops,
1046         &dprov_cipher_ops,
1047         &dprov_mac_ops,
1048         &dprov_sign_ops,
1049         &dprov_verify_ops,
1050         &dprov_dual_ops,
1051         &dprov_cipher_mac_ops,
1052         &dprov_random_number_ops,
1053         &dprov_session_ops,
1054         &dprov_object_ops,
1055         &dprov_key_ops,
1056         &dprov_management_ops,
1057         &dprov_ctx_ops,
1058         &dprov_mech_ops
1059 };
1060 
1061 
1062 /* maximum SO and user PIN lengths */
1063 #define DPROV_MAX_PIN_LEN       128
1064 
1065 /*
1066  * Objects: each session is associated with an array of objects.
1067  * Unlike PKCS#11, the objects cannot be shared between sessions.
1068  * The ioctl driver multiplexes PKCS#11 sessions to providers
1069  * sessions in order to support this semantic. This simplifies
1070  * the CSPI greatly since the provider does not have to associate
1071  * sessions with a user space process.
1072  * There is also a per-instance array of objects, which correspond
1073  * to PKCS#11 token objects. These objects can be shared by multiple
1074  * sesions.
1075  *
1076  * Token objects are identified by having a CKA_TOKEN attribute B_TRUE.
1077  * Private objects are identified by having a CKA_PRIVATE attribute
1078  * set to B_TRUE.
1079  */
1080 
1081 #define DPROV_MAX_OBJECTS       128     /* max # of objects */
1082 #define DPROV_MAX_ATTR          64      /* max # of attributes per object */
1083 
1084 /* object description */
1085 typedef struct dprov_object {
1086         crypto_object_attribute_t do_attr[DPROV_MAX_ATTR]; /* attributes */
1087         uint_t do_token_idx;            /* index in per-instance table */
1088                                         /* for token objects. */
1089         boolean_t do_destroyed;         /* object has been destroyed. */
1090                                         /* keep object around until all */
1091                                         /* sessions that refer to it */
1092                                         /* are closed, but mark it */
1093                                         /* destroyed so that references */
1094                                         /* to the object fail. */
1095                                         /* used for token objects only */
1096         uint_t do_refcnt;
1097 } dprov_object_t;
1098 
1099 /*
1100  * If a session has a reference to a dprov_object_t,
1101  * it REFHOLD()s.
1102  */
1103 #define DPROV_OBJECT_REFHOLD(object) {          \
1104         atomic_inc_32(&(object)->do_refcnt);     \
1105         ASSERT((object)->do_refcnt != 0);            \
1106 }
1107 
1108 /*
1109  * Releases a reference to an object. When the last
1110  * reference is released, the object is freed.
1111  */
1112 #define DPROV_OBJECT_REFRELE(object) {                          \
1113         ASSERT((object)->do_refcnt != 0);                    \
1114         membar_exit();                                          \
1115         if (atomic_dec_32_nv(&(object)->do_refcnt) == 0) \
1116                 dprov_free_object(object);                      \
1117 }
1118 
1119 /*
1120  * Object attributes are passed to the provider using crypto_object_attribute
1121  * structures, which contain the type of the attribute, a pointer to
1122  * it's value, and the length of its value. The attribute types values
1123  * are defined by the PKCS#11 specification. This provider only cares
1124  * about a subset of these attributes. In order to avoid having to
1125  * include the PKCS#11 header files, we define here the attributes values
1126  * which are used by the provider.
1127  */
1128 
1129 #define DPROV_CKA_CLASS                 0x00000000
1130 #define DPROV_CKA_TOKEN                 0x00000001
1131 #define DPROV_CKA_PRIVATE               0x00000002
1132 #define DPROV_CKA_VALUE                 0x00000011
1133 #define DPROV_CKA_CERTIFICATE_TYPE      0x00000080
1134 #define DPROV_CKA_KEY_TYPE              0x00000100
1135 #define DPROV_CKA_SENSITIVE             0x00000103
1136 #define DPROV_CKA_ENCRYPT               0x00000104
1137 #define DPROV_CKA_DECRYPT               0x00000105
1138 #define DPROV_CKA_WRAP                  0x00000106
1139 #define DPROV_CKA_UNWRAP                0x00000107
1140 #define DPROV_CKA_SIGN                  0x00000108
1141 #define DPROV_CKA_SIGN_RECOVER          0x00000109
1142 #define DPROV_CKA_VERIFY                0x0000010A
1143 #define DPROV_CKA_VERIFY_RECOVER        0x0000010B
1144 #define DPROV_CKA_DERIVE                0x0000010C
1145 #define DPROV_CKA_MODULUS               0x00000120
1146 #define DPROV_CKA_MODULUS_BITS          0x00000121
1147 #define DPROV_CKA_PUBLIC_EXPONENT       0x00000122
1148 #define DPROV_CKA_PRIVATE_EXPONENT      0x00000123
1149 #define DPROV_CKA_PRIME                 0x00000130
1150 #define DPROV_CKA_BASE                  0x00000132
1151 #define DPROV_CKA_VALUE_BITS            0x00000160
1152 #define DPROV_CKA_VALUE_LEN             0x00000161
1153 #define DPROV_CKA_EXTRACTABLE           0x00000162
1154 #define DPROV_CKA_EC_PARAMS             0x00000180
1155 #define DPROV_CKA_EC_POINT              0x00000181
1156 #define DPROV_HW_FEATURE_TYPE           0x00000300
1157 
1158 /*
1159  * Object classes from PKCS#11
1160  */
1161 #define DPROV_CKO_DATA                  0x00000000
1162 #define DPROV_CKO_CERTIFICATE           0x00000001
1163 #define DPROV_CKO_PUBLIC_KEY            0x00000002
1164 #define DPROV_CKO_PRIVATE_KEY           0x00000003
1165 #define DPROV_CKO_SECRET_KEY            0x00000004
1166 #define DPROV_CKO_HW_FEATURE            0x00000005
1167 #define DPROV_CKO_DOMAIN_PARAMETERS     0x00000006
1168 #define DPROV_CKO_VENDOR_DEFINED        0x80000000
1169 
1170 /*
1171  * A few key types from PKCS#11
1172  */
1173 #define DPROV_CKK_RSA                   0x00000000
1174 #define DPROV_CKK_GENERIC_SECRET        0x00000010
1175 #define DPROV_CKK_RC4                   0x00000012
1176 #define DPROV_CKK_DES                   0x00000013
1177 #define DPROV_CKK_DES3                  0x00000015
1178 #define DPROV_CKK_AES                   0x0000001F
1179 #define DPROV_CKK_BLOWFISH              0x00000020
1180 
1181 /*
1182  * Find object context. Allows the find object init/find/final
1183  * to store data persistent across calls.
1184  */
1185 typedef struct dprov_find_ctx {
1186         crypto_object_id_t fc_ids[DPROV_MAX_OBJECTS];   /* object ids */
1187         uint_t fc_nids;                 /* number of ids in fc_ids */
1188         uint_t fc_next;                 /* next id to return */
1189 } dprov_find_ctx_t;
1190 
1191 /*
1192  * Session management: each instance is associated with an array
1193  * of sessions. KEF providers sessions are always R/W the library and
1194  * the ioctl maintain the PKCS#11 R/W attributes for the session.
1195  */
1196 
1197 #define DPROV_MIN_SESSIONS      32      /* # of sessions to start with */
1198 
1199 typedef enum dprov_session_state {
1200         DPROV_SESSION_STATE_PUBLIC,     /* public (default) */
1201         DPROV_SESSION_STATE_SO,         /* SO logged in */
1202         DPROV_SESSION_STATE_USER        /* user logged in */
1203 } dprov_session_state_t;
1204 
1205 /* session description */
1206 typedef struct dprov_session {
1207         dprov_session_state_t ds_state; /* session state */
1208         dprov_object_t *ds_objects[DPROV_MAX_OBJECTS];  /* session objects */
1209 } dprov_session_t;
1210 
1211 
1212 static crypto_provider_info_t dprov_prov_info = {
1213         CRYPTO_SPI_VERSION_2,
1214         "Dummy Pseudo HW Provider",
1215         CRYPTO_HW_PROVIDER,
1216         NULL,                           /* pi_provider_dev */
1217         NULL,                           /* pi_provider_handle */
1218         &dprov_crypto_ops,
1219         sizeof (dprov_mech_info_tab)/sizeof (crypto_mech_info_t),
1220         dprov_mech_info_tab,
1221         0,                              /* pi_logical_provider_count */
1222         NULL,                           /* pi_logical_providers */
1223         0                               /* pi_flags */
1224 };
1225 
1226 /*
1227  * Per-instance info.
1228  */
1229 typedef struct dprov_state {
1230         kmutex_t ds_lock;               /* per-instance lock */
1231         dev_info_t *ds_dip;             /* device info */
1232         crypto_kcf_provider_handle_t ds_prov_handle;    /* framework handle */
1233         taskq_t *ds_taskq;              /* taskq for async behavior */
1234         char ds_user_pin[DPROV_MAX_PIN_LEN];    /* normal user PIN */
1235         uint_t ds_user_pin_len;
1236         char ds_so_pin[DPROV_MAX_PIN_LEN];      /* SO PIN */
1237         uint_t ds_so_pin_len;
1238         dprov_session_t **ds_sessions;  /* sessions for this instance */
1239         uint_t ds_sessions_slots;       /* number of session slots */
1240         uint_t ds_sessions_count;       /* number of open sessions */
1241         boolean_t ds_token_initialized; /* provider initialized? */
1242         boolean_t ds_user_pin_set;      /* user pin set? */
1243         char ds_label[CRYPTO_EXT_SIZE_LABEL];           /* "token" label */
1244         dprov_object_t *ds_objects[DPROV_MAX_OBJECTS];  /* "token" objects */
1245 } dprov_state_t;
1246 
1247 
1248 /*
1249  * A taskq is associated with each instance of the pseudo driver in order
1250  * to simulate the asynchronous execution of requests.
1251  * The following defines the taskq request structures.
1252  */
1253 
1254 /* request types */
1255 typedef enum dprov_req_type {
1256         /* digest requests */
1257         DPROV_REQ_DIGEST_INIT = 1,
1258         DPROV_REQ_DIGEST,
1259         DPROV_REQ_DIGEST_UPDATE,
1260         DPROV_REQ_DIGEST_KEY,
1261         DPROV_REQ_DIGEST_FINAL,
1262         DPROV_REQ_DIGEST_ATOMIC,
1263         /* cipher requests */
1264         DPROV_REQ_ENCRYPT_INIT,
1265         DPROV_REQ_ENCRYPT,
1266         DPROV_REQ_ENCRYPT_UPDATE,
1267         DPROV_REQ_ENCRYPT_FINAL,
1268         DPROV_REQ_ENCRYPT_ATOMIC,
1269         DPROV_REQ_DECRYPT_INIT,
1270         DPROV_REQ_DECRYPT,
1271         DPROV_REQ_DECRYPT_UPDATE,
1272         DPROV_REQ_DECRYPT_FINAL,
1273         DPROV_REQ_DECRYPT_ATOMIC,
1274         /* mac requests */
1275         DPROV_REQ_MAC_INIT,
1276         DPROV_REQ_MAC,
1277         DPROV_REQ_MAC_UPDATE,
1278         DPROV_REQ_MAC_FINAL,
1279         DPROV_REQ_MAC_ATOMIC,
1280         DPROV_REQ_MAC_VERIFY_ATOMIC,
1281         /* sign requests */
1282         DPROV_REQ_SIGN_INIT,
1283         DPROV_REQ_SIGN,
1284         DPROV_REQ_SIGN_UPDATE,
1285         DPROV_REQ_SIGN_FINAL,
1286         DPROV_REQ_SIGN_ATOMIC,
1287         DPROV_REQ_SIGN_RECOVER_INIT,
1288         DPROV_REQ_SIGN_RECOVER,
1289         DPROV_REQ_SIGN_RECOVER_ATOMIC,
1290         /* verify requests */
1291         DPROV_REQ_VERIFY_INIT,
1292         DPROV_REQ_VERIFY,
1293         DPROV_REQ_VERIFY_UPDATE,
1294         DPROV_REQ_VERIFY_FINAL,
1295         DPROV_REQ_VERIFY_ATOMIC,
1296         DPROV_REQ_VERIFY_RECOVER_INIT,
1297         DPROV_REQ_VERIFY_RECOVER,
1298         DPROV_REQ_VERIFY_RECOVER_ATOMIC,
1299         /* dual ops requests */
1300         DPROV_REQ_DIGEST_ENCRYPT_UPDATE,
1301         DPROV_REQ_DECRYPT_DIGEST_UPDATE,
1302         DPROV_REQ_SIGN_ENCRYPT_UPDATE,
1303         DPROV_REQ_DECRYPT_VERIFY_UPDATE,
1304         /* dual cipher/mac requests */
1305         DPROV_REQ_ENCRYPT_MAC_INIT,
1306         DPROV_REQ_ENCRYPT_MAC,
1307         DPROV_REQ_ENCRYPT_MAC_UPDATE,
1308         DPROV_REQ_ENCRYPT_MAC_FINAL,
1309         DPROV_REQ_ENCRYPT_MAC_ATOMIC,
1310         DPROV_REQ_MAC_DECRYPT_INIT,
1311         DPROV_REQ_MAC_DECRYPT,
1312         DPROV_REQ_MAC_DECRYPT_UPDATE,
1313         DPROV_REQ_MAC_DECRYPT_FINAL,
1314         DPROV_REQ_MAC_DECRYPT_ATOMIC,
1315         DPROV_REQ_MAC_VERIFY_DECRYPT_ATOMIC,
1316         /* random number ops */
1317         DPROV_REQ_RANDOM_SEED,
1318         DPROV_REQ_RANDOM_GENERATE,
1319         /* session management requests */
1320         DPROV_REQ_SESSION_OPEN,
1321         DPROV_REQ_SESSION_CLOSE,
1322         DPROV_REQ_SESSION_LOGIN,
1323         DPROV_REQ_SESSION_LOGOUT,
1324         /* object management requests */
1325         DPROV_REQ_OBJECT_CREATE,
1326         DPROV_REQ_OBJECT_COPY,
1327         DPROV_REQ_OBJECT_DESTROY,
1328         DPROV_REQ_OBJECT_GET_SIZE,
1329         DPROV_REQ_OBJECT_GET_ATTRIBUTE_VALUE,
1330         DPROV_REQ_OBJECT_SET_ATTRIBUTE_VALUE,
1331         DPROV_REQ_OBJECT_FIND_INIT,
1332         DPROV_REQ_OBJECT_FIND,
1333         DPROV_REQ_OBJECT_FIND_FINAL,
1334         /* key management requests */
1335         DPROV_REQ_KEY_GENERATE,
1336         DPROV_REQ_KEY_GENERATE_PAIR,
1337         DPROV_REQ_KEY_WRAP,
1338         DPROV_REQ_KEY_UNWRAP,
1339         DPROV_REQ_KEY_DERIVE,
1340         /* provider management requests */
1341         DPROV_REQ_MGMT_EXTINFO,
1342         DPROV_REQ_MGMT_INITTOKEN,
1343         DPROV_REQ_MGMT_INITPIN,
1344         DPROV_REQ_MGMT_SETPIN,
1345         /* no (key)store key management requests */
1346         DPROV_REQ_NOSTORE_KEY_GENERATE,
1347         DPROV_REQ_NOSTORE_KEY_GENERATE_PAIR,
1348         DPROV_REQ_NOSTORE_KEY_DERIVE
1349 } dprov_req_type_t;
1350 
1351 /* for DPROV_REQ_DIGEST requests */
1352 typedef struct dprov_digest_req {
1353         crypto_mechanism_t *dr_mechanism;
1354         crypto_ctx_t *dr_ctx;
1355         crypto_data_t *dr_data;
1356         crypto_key_t *dr_key;
1357         crypto_data_t *dr_digest;
1358 } dprov_digest_req_t;
1359 
1360 /* for DPROV_REQ_MAC requests */
1361 typedef struct dprov_mac_req {
1362         crypto_mechanism_t *dr_mechanism;
1363         crypto_ctx_t *dr_ctx;
1364         crypto_key_t *dr_key;
1365         crypto_data_t *dr_data;
1366         crypto_data_t *dr_mac;
1367         crypto_session_id_t dr_session_id;
1368 } dprov_mac_req_t;
1369 
1370 /* for DPROV_REQ_ENCRYPT and DPROV_REQ_DECRYPT requests */
1371 typedef struct dprov_cipher_req {
1372         crypto_mechanism_t *dr_mechanism;
1373         crypto_ctx_t *dr_ctx;
1374         crypto_key_t *dr_key;
1375         crypto_data_t *dr_plaintext;
1376         crypto_data_t *dr_ciphertext;
1377         crypto_session_id_t dr_session_id;
1378 } dprov_cipher_req_t;
1379 
1380 /* for DPROV_REQ_SIGN requests */
1381 typedef struct dprov_sign_req {
1382         crypto_mechanism_t *sr_mechanism;
1383         crypto_ctx_t *sr_ctx;
1384         crypto_key_t *sr_key;
1385         crypto_data_t *sr_data;
1386         crypto_data_t *sr_signature;
1387         crypto_session_id_t sr_session_id;
1388 } dprov_sign_req_t;
1389 
1390 /* for DPROV_REQ_VERIFY requests */
1391 typedef struct dprov_verify_req {
1392         crypto_mechanism_t *vr_mechanism;
1393         crypto_ctx_t *vr_ctx;
1394         crypto_key_t *vr_key;
1395         crypto_data_t *vr_data;
1396         crypto_data_t *vr_signature;
1397         crypto_session_id_t vr_session_id;
1398 } dprov_verify_req_t;
1399 
1400 /* for dual ops requests */
1401 typedef struct dprov_dual_req {
1402         crypto_ctx_t *dr_signverify_ctx;
1403         crypto_ctx_t *dr_cipher_ctx;
1404         crypto_data_t *dr_plaintext;
1405         crypto_data_t *dr_ciphertext;
1406 } dprov_dual_req_t;
1407 
1408 /* for cipher/mac dual ops requests */
1409 typedef struct dprov_cipher_mac_req {
1410         crypto_session_id_t mr_session_id;
1411         crypto_ctx_t *mr_ctx;
1412         crypto_mechanism_t *mr_cipher_mech;
1413         crypto_key_t *mr_cipher_key;
1414         crypto_mechanism_t *mr_mac_mech;
1415         crypto_key_t *mr_mac_key;
1416         crypto_dual_data_t *mr_dual_data;
1417         crypto_data_t *mr_data;
1418         crypto_data_t *mr_mac;
1419 } dprov_cipher_mac_req_t;
1420 
1421 /* for DPROV_REQ_RANDOM requests */
1422 typedef struct dprov_random_req {
1423         uchar_t *rr_buf;
1424         size_t rr_len;
1425         crypto_session_id_t rr_session_id;
1426         uint_t rr_entropy_est;
1427         uint32_t rr_flags;
1428 } dprov_random_req_t;
1429 
1430 /* for DPROV_REQ_SESSION requests */
1431 typedef struct dprov_session_req {
1432         crypto_session_id_t *sr_session_id_ptr;
1433         crypto_session_id_t sr_session_id;
1434         crypto_user_type_t sr_user_type;
1435         char *sr_pin;
1436         size_t sr_pin_len;
1437 } dprov_session_req_t;
1438 
1439 /* for DPROV_REQ_OBJECT requests */
1440 typedef struct dprov_object_req {
1441         crypto_session_id_t or_session_id;
1442         crypto_object_id_t or_object_id;
1443         crypto_object_attribute_t *or_template;
1444         uint_t or_attribute_count;
1445         crypto_object_id_t *or_object_id_ptr;
1446         size_t *or_object_size;
1447         void **or_find_pp;
1448         void *or_find_p;
1449         uint_t or_max_object_count;
1450         uint_t *or_object_count_ptr;
1451 } dprov_object_req_t;
1452 
1453 /* for DPROV_REQ_KEY requests */
1454 typedef struct dprov_key_req {
1455         crypto_session_id_t kr_session_id;
1456         crypto_mechanism_t *kr_mechanism;
1457         crypto_object_attribute_t *kr_template;
1458         uint_t kr_attribute_count;
1459         crypto_object_id_t *kr_object_id_ptr;
1460         crypto_object_attribute_t *kr_private_key_template;
1461         uint_t kr_private_key_attribute_count;
1462         crypto_object_id_t *kr_private_key_object_id_ptr;
1463         crypto_key_t *kr_key;
1464         uchar_t *kr_wrapped_key;
1465         size_t *kr_wrapped_key_len_ptr;
1466         crypto_object_attribute_t *kr_out_template1;
1467         crypto_object_attribute_t *kr_out_template2;
1468         uint_t kr_out_attribute_count1;
1469         uint_t kr_out_attribute_count2;
1470 } dprov_key_req_t;
1471 
1472 /* for DPROV_REQ_MGMT requests */
1473 typedef struct dprov_mgmt_req {
1474         crypto_session_id_t mr_session_id;
1475         char *mr_pin;
1476         size_t mr_pin_len;
1477         char *mr_old_pin;
1478         size_t mr_old_pin_len;
1479         char *mr_label;
1480         crypto_provider_ext_info_t *mr_ext_info;
1481 } dprov_mgmt_req_t;
1482 
1483 /* request, as queued on taskq */
1484 typedef struct dprov_req {
1485         dprov_req_type_t dr_type;
1486         dprov_state_t *dr_softc;
1487         crypto_req_handle_t dr_kcf_req;
1488         union {
1489                 dprov_digest_req_t dru_digest_req;
1490                 dprov_mac_req_t dru_mac_req;
1491                 dprov_cipher_req_t dru_cipher_req;
1492                 dprov_sign_req_t dru_sign_req;
1493                 dprov_verify_req_t dru_verify_req;
1494                 dprov_dual_req_t dru_dual_req;
1495                 dprov_cipher_mac_req_t dru_cipher_mac_req;
1496                 dprov_random_req_t dru_random_req;
1497                 dprov_session_req_t dru_session_req;
1498                 dprov_object_req_t dru_object_req;
1499                 dprov_key_req_t dru_key_req;
1500                 dprov_mgmt_req_t dru_mgmt_req;
1501         } dr_req;
1502 } dprov_req_t;
1503 
1504 /* shortcuts for union fields */
1505 #define dr_digest_req           dr_req.dru_digest_req
1506 #define dr_mac_req              dr_req.dru_mac_req
1507 #define dr_cipher_req           dr_req.dru_cipher_req
1508 #define dr_sign_req             dr_req.dru_sign_req
1509 #define dr_verify_req           dr_req.dru_verify_req
1510 #define dr_dual_req             dr_req.dru_dual_req
1511 #define dr_cipher_mac_req       dr_req.dru_cipher_mac_req
1512 #define dr_random_req           dr_req.dru_random_req
1513 #define dr_session_req          dr_req.dru_session_req
1514 #define dr_object_req           dr_req.dru_object_req
1515 #define dr_key_req              dr_req.dru_key_req
1516 #define dr_mgmt_req             dr_req.dru_mgmt_req
1517 
1518 /* prototypes for the tasq dispatcher functions */
1519 static void dprov_digest_task(dprov_req_t *);
1520 static void dprov_mac_task(dprov_req_t *);
1521 static void dprov_sign_task(dprov_req_t *);
1522 static void dprov_verify_task(dprov_req_t *);
1523 static void dprov_dual_task(dprov_req_t *);
1524 static void dprov_cipher_task(dprov_req_t *);
1525 static void dprov_cipher_mac_task(dprov_req_t *);
1526 static void dprov_random_task(dprov_req_t *);
1527 static void dprov_session_task(dprov_req_t *);
1528 static void dprov_object_task(dprov_req_t *);
1529 static void dprov_key_task(dprov_req_t *);
1530 static void dprov_mgmt_task(dprov_req_t *);
1531 
1532 /* helper functions */
1533 static int dprov_digest_submit_req(dprov_req_type_t, dprov_state_t *,
1534     crypto_req_handle_t, crypto_mechanism_t *, crypto_data_t *, crypto_key_t *,
1535     crypto_data_t *, crypto_ctx_t *, int);
1536 static int dprov_cipher_submit_req(dprov_req_type_t, dprov_state_t *,
1537     crypto_req_handle_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
1538     crypto_data_t *, crypto_ctx_t *, crypto_session_id_t, int);
1539 static int dprov_mac_submit_req(dprov_req_type_t, dprov_state_t *,
1540     crypto_req_handle_t, crypto_mechanism_t *, crypto_data_t *,
1541     crypto_key_t *, crypto_data_t *, crypto_ctx_t *, crypto_session_id_t, int);
1542 static int dprov_sign_submit_req(dprov_req_type_t, dprov_state_t *,
1543     crypto_req_handle_t, crypto_mechanism_t *, crypto_key_t *,
1544     crypto_data_t *, crypto_data_t *, crypto_ctx_t *, crypto_session_id_t, int);
1545 static int dprov_verify_submit_req(dprov_req_type_t, dprov_state_t *,
1546     crypto_req_handle_t, crypto_mechanism_t *, crypto_key_t *,
1547     crypto_data_t *, crypto_data_t *, crypto_ctx_t *, crypto_session_id_t, int);
1548 static int dprov_dual_submit_req(dprov_req_type_t, dprov_state_t *,
1549     crypto_req_handle_t, crypto_ctx_t *, crypto_ctx_t *, crypto_data_t *,
1550     crypto_data_t *);
1551 static int dprov_cipher_mac_submit_req(dprov_req_type_t, dprov_state_t *,
1552     crypto_req_handle_t, crypto_ctx_t *, crypto_session_id_t,
1553     crypto_mechanism_t *, crypto_key_t *, crypto_mechanism_t *, crypto_key_t *,
1554     crypto_dual_data_t *, crypto_data_t *, crypto_data_t *, int);
1555 static int dprov_random_submit_req(dprov_req_type_t, dprov_state_t *,
1556     crypto_req_handle_t, uchar_t *, size_t, crypto_session_id_t, uint_t,
1557     uint32_t);
1558 static int dprov_session_submit_req(dprov_req_type_t, dprov_state_t *,
1559     crypto_req_handle_t, crypto_session_id_t *, crypto_session_id_t,
1560     crypto_user_type_t, char *, size_t);
1561 static int dprov_object_submit_req(dprov_req_type_t, dprov_state_t *,
1562     crypto_req_handle_t, crypto_session_id_t, crypto_object_id_t,
1563     crypto_object_attribute_t *, uint_t, crypto_object_id_t *, size_t *,
1564     void **, void *, uint_t, uint_t *, int);
1565 static int dprov_key_submit_req(dprov_req_type_t, dprov_state_t *,
1566     crypto_req_handle_t, crypto_session_id_t, crypto_mechanism_t *,
1567     crypto_object_attribute_t *, uint_t, crypto_object_id_t *,
1568     crypto_object_attribute_t *, uint_t, crypto_object_id_t *,
1569     crypto_key_t *, uchar_t *, size_t *, crypto_object_attribute_t *,
1570     uint_t, crypto_object_attribute_t *, uint_t);
1571 static int dprov_mgmt_submit_req(dprov_req_type_t, dprov_state_t *,
1572     crypto_req_handle_t, crypto_session_id_t, char *, size_t, char *, size_t,
1573     char *, crypto_provider_ext_info_t *);
1574 static int dprov_get_sw_prov(crypto_mechanism_t *, kcf_provider_desc_t **,
1575     crypto_mech_type_t *);
1576 
1577 /* object management helper functions */
1578 static void dprov_free_object(dprov_object_t *);
1579 static void dprov_release_session_objects(dprov_session_t *);
1580 static void dprov_adjust_attrs(crypto_object_attribute_t *, int);
1581 static boolean_t dprov_object_is_private(dprov_object_t *);
1582 static boolean_t dprov_object_is_token(dprov_object_t *);
1583 static int dprov_key_value_secret(dprov_state_t *, crypto_session_id_t,
1584     dprov_req_type_t, crypto_key_t *, crypto_key_t *);
1585 static int dprov_key_attr_asymmetric(dprov_state_t *, crypto_session_id_t,
1586     dprov_req_type_t, crypto_key_t *, crypto_key_t *);
1587 static int dprov_get_object_attr_boolean(dprov_object_t *, uint64_t,
1588         boolean_t *);
1589 static int dprov_get_object_attr_ulong(dprov_object_t *, uint64_t, ulong_t *);
1590 static int dprov_get_object_attr_array(dprov_object_t *, uint64_t, void **,
1591     size_t *);
1592 static int dprov_get_key_attr_ulong(crypto_key_t *, uint64_t, ulong_t *);
1593 static int dprov_get_key_attr_array(crypto_key_t *, uint64_t, void **,
1594     size_t *);
1595 static int dprov_create_object_from_template(dprov_state_t *, dprov_session_t *,
1596     crypto_object_attribute_t *, uint_t, crypto_object_id_t *, boolean_t,
1597     boolean_t);
1598 static int dprov_get_template_attr_scalar_common(crypto_object_attribute_t *,
1599     uint_t, uint64_t, void *, size_t);
1600 static int dprov_get_template_attr_boolean(crypto_object_attribute_t *,
1601     uint_t, uint64_t, boolean_t *);
1602 static int dprov_get_template_attr_ulong(crypto_object_attribute_t *, uint_t,
1603     uint64_t, ulong_t *);
1604 static int dprov_template_attr_present(crypto_object_attribute_t *, uint_t,
1605     uint64_t);
1606 static int dprov_get_template_attr_array(crypto_object_attribute_t *, uint_t,
1607     uint64_t, void **, size_t *);
1608 static int dprov_destroy_object(dprov_state_t *, dprov_session_t *,
1609     crypto_object_id_t);
1610 static int dprov_object_set_attr(dprov_session_t *, crypto_object_id_t,
1611     crypto_object_attribute_t *, uint_t, boolean_t);
1612 static int dprov_find_attr(crypto_object_attribute_t *, uint_t, uint64_t);
1613 static boolean_t dprov_attributes_match(dprov_object_t *,
1614     crypto_object_attribute_t *, uint_t);
1615 
1616 /* retrieve the softc and instance number from a SPI crypto context */
1617 #define DPROV_SOFTC_FROM_CTX(ctx, softc, instance) {    \
1618         (softc) = (dprov_state_t *)(ctx)->cc_provider;       \
1619         (instance) = ddi_get_instance((softc)->ds_dip);      \
1620 }
1621 
1622 /* retrieve the softc and instance number from a taskq request */
1623 #define DPROV_SOFTC_FROM_REQ(req, softc, instance) {    \
1624         (softc) = (req)->dr_softc;                   \
1625         (instance) = ddi_get_instance((softc)->ds_dip);      \
1626 }
1627 
1628 /*
1629  * The dprov private context most of the time contains a pointer to the
1630  * crypto_context_t that was allocated when calling a KCF function.
1631  * Dual cipher/mac operations however require the dprov driver
1632  * to maintain the contexts associated with the separate cipher
1633  * and mac operations. These two types of dprov contexts are
1634  * defined below.
1635  */
1636 typedef enum dprov_ctx_type {
1637         DPROV_CTX_SINGLE,
1638         DPROV_CTX_DUAL
1639 } dprov_ctx_type_t;
1640 
1641 /*
1642  * When the context refers to a single KCF context, the
1643  * cc_provider field of a crypto_ctx_t points to a structure of
1644  * type dprov_ctx_single.
1645  */
1646 typedef struct dprov_ctx_single {
1647         dprov_ctx_type_t dc_type;
1648         crypto_context_t dc_ctx;
1649         boolean_t dc_svrfy_to_mac;
1650 } dprov_ctx_single_t;
1651 
1652 /*
1653  * When the context is used for cipher/mac operations, it contains
1654  * pointers to to KCF contexts, one for the cipher operation, the
1655  * other for the mac operation.
1656  */
1657 typedef struct dprov_ctx_dual {
1658         dprov_ctx_type_t cd_type;
1659         crypto_context_t cd_cipher_ctx;
1660         crypto_context_t cd_mac_ctx;
1661 } dprov_ctx_dual_t;
1662 
1663 /*
1664  * Helper macros for context accessors. These macros return the
1665  * k-API context corresponding to the given SPI context for
1666  * single and dual cipher/mac operations.
1667  */
1668 
1669 #define DPROV_CTX_P(_ctx) \
1670         ((dprov_ctx_single_t *)(_ctx)->cc_provider_private)
1671 
1672 #define DPROV_CTX_SINGLE(_ctx)  ((DPROV_CTX_P(_ctx))->dc_ctx)
1673 
1674 #define DPROV_CTX_DUAL_CIPHER(_ctx) \
1675         (((dprov_ctx_dual_t *)(_ctx)->cc_provider_private)->cd_cipher_ctx)
1676 
1677 #define DPROV_CTX_DUAL_MAC(_ctx) \
1678         (((dprov_ctx_dual_t *)(_ctx)->cc_provider_private)->cd_mac_ctx)
1679 
1680 static int dprov_alloc_context(dprov_req_type_t, crypto_ctx_t *);
1681 
1682 
1683 
1684 static void *statep;    /* state pointer */
1685 
1686 /*
1687  * DDI entry points.
1688  */
1689 int
1690 _init(void)
1691 {
1692         int error;
1693 
1694         DPROV_DEBUG(D_INIT, ("dprov: in _init\n"));
1695 
1696         if ((error = ddi_soft_state_init(&statep, sizeof (dprov_state_t),
1697             0)) != 0)
1698                 return (error);
1699 
1700         return (mod_install(&modlinkage));
1701 }
1702 
1703 int
1704 _fini(void)
1705 {
1706         int error;
1707 
1708         DPROV_DEBUG(D_INIT, ("dprov: in _fini\n"));
1709 
1710         if ((error = mod_remove(&modlinkage)) != 0)
1711                 return (error);
1712 
1713         ddi_soft_state_fini(&statep);
1714 
1715         return (0);
1716 }
1717 
1718 int
1719 _info(struct modinfo *modinfop)
1720 {
1721         DPROV_DEBUG(D_INIT, ("dprov: in _info\n"));
1722 
1723         return (mod_info(&modlinkage, modinfop));
1724 }
1725 
1726 /* ARGSUSED */
1727 static int
1728 dprov_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
1729 {
1730         int instance = getminor((dev_t)arg);
1731         dprov_state_t *softc;
1732 
1733         DPROV_DEBUG(D_ATTACH, ("dprov: in dprov_getinfo() for %d\n",
1734             instance));
1735 
1736         switch (cmd) {
1737         case DDI_INFO_DEVT2DEVINFO:
1738                 softc = ddi_get_soft_state(statep, instance);
1739                 *result = softc->ds_dip;
1740                 return (DDI_SUCCESS);
1741 
1742         case DDI_INFO_DEVT2INSTANCE:
1743                 *result = (void *)(uintptr_t)instance;
1744                 return (DDI_SUCCESS);
1745         }
1746         return (DDI_FAILURE);
1747 }
1748 
1749 static int
1750 dprov_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1751 {
1752         int instance = ddi_get_instance(dip);
1753         dprov_state_t *softc;
1754         char devname[256];
1755         int ret;
1756 
1757         DPROV_DEBUG(D_ATTACH, ("dprov: in dprov_attach() for %d\n",
1758             instance));
1759 
1760         if (cmd != DDI_ATTACH) {
1761                 return (DDI_FAILURE);
1762         }
1763 
1764         /* get new softc and initialize it */
1765         if (ddi_soft_state_zalloc(statep, instance) != DDI_SUCCESS)
1766                 return (DDI_FAILURE);
1767 
1768         softc = ddi_get_soft_state(statep, instance);
1769         mutex_init(&softc->ds_lock, NULL, MUTEX_DRIVER, NULL);
1770         softc->ds_dip = dip;
1771         softc->ds_prov_handle = NULL;
1772 
1773         /* create minor node */
1774         (void) sprintf(devname, "dprov%d", instance);
1775         if (ddi_create_minor_node(dip, devname, S_IFCHR, instance,
1776             DDI_PSEUDO, 0) != DDI_SUCCESS) {
1777                 cmn_err(CE_WARN, "attach: failed creating minor node");
1778                 mutex_destroy(&softc->ds_lock);
1779                 ddi_soft_state_free(statep, instance);
1780                 return (DDI_FAILURE);
1781         }
1782 
1783         nostore_key_gen = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1784             DDI_PROP_DONTPASS, "nostore_key_gen", 0);
1785         if (nostore_key_gen != 0) {
1786                 dprov_prov_info.pi_interface_version = CRYPTO_SPI_VERSION_3;
1787                 dprov_crypto_ops.co_object_ops = NULL;
1788                 dprov_crypto_ops.co_nostore_key_ops = &dprov_nostore_key_ops;
1789         }
1790 
1791         dprov_max_digestsz = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1792             DDI_PROP_DONTPASS, "max_digest_sz", INT_MAX);
1793         if (dprov_max_digestsz != INT_MAX && dprov_max_digestsz != 0 &&
1794             dprov_max_digestsz != DDI_PROP_NOT_FOUND) {
1795                 dprov_no_multipart = B_TRUE;
1796                 dprov_prov_info.pi_flags |=
1797                     (CRYPTO_HASH_NO_UPDATE | CRYPTO_HMAC_NO_UPDATE);
1798         }
1799 
1800         /* create taskq */
1801         softc->ds_taskq = taskq_create(devname, 1, minclsyspri,
1802             crypto_taskq_minalloc, crypto_taskq_maxalloc, TASKQ_PREPOPULATE);
1803 
1804         /* initialize table of sessions */
1805         softc->ds_sessions = kmem_zalloc(DPROV_MIN_SESSIONS *
1806             sizeof (dprov_session_t *), KM_SLEEP);
1807         softc->ds_sessions_slots = DPROV_MIN_SESSIONS;
1808         softc->ds_sessions_count = 0;
1809 
1810         /* initialized done by init_token entry point */
1811         softc->ds_token_initialized = B_TRUE;
1812 
1813         (void) memset(softc->ds_label, ' ', CRYPTO_EXT_SIZE_LABEL);
1814         bcopy("Dummy Pseudo HW Provider", softc->ds_label, 24);
1815 
1816         bcopy("changeme", softc->ds_user_pin, 8);
1817         softc->ds_user_pin_len = 8;
1818         softc->ds_user_pin_set = B_TRUE;
1819 
1820         /* register with the crypto framework */
1821         dprov_prov_info.pi_provider_dev.pd_hw = dip;
1822         dprov_prov_info.pi_provider_handle = softc;
1823 
1824         if (dprov_no_multipart) { /* Export only single part */
1825                 dprov_digest_ops.digest_update = NULL;
1826                 dprov_digest_ops.digest_key = NULL;
1827                 dprov_digest_ops.digest_final = NULL;
1828                 dprov_object_ops.object_create = NULL;
1829         }
1830 
1831         if ((ret = crypto_register_provider(&dprov_prov_info,
1832             &softc->ds_prov_handle)) != CRYPTO_SUCCESS) {
1833                 cmn_err(CE_WARN,
1834                     "dprov crypto_register_provider() failed (0x%x)", ret);
1835                 taskq_destroy(softc->ds_taskq);
1836                 kmem_free(softc->ds_sessions, softc->ds_sessions_slots *
1837                     sizeof (dprov_session_t *));
1838                 mutex_destroy(&softc->ds_lock);
1839                 ddi_soft_state_free(statep, instance);
1840                 ddi_remove_minor_node(dip, NULL);
1841                 return (DDI_FAILURE);
1842         }
1843 
1844         /*
1845          * This call is for testing only; it is not required by the SPI.
1846          */
1847         crypto_provider_notification(softc->ds_prov_handle,
1848             CRYPTO_PROVIDER_READY);
1849 
1850         return (DDI_SUCCESS);
1851 }
1852 
1853 static int
1854 dprov_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1855 {
1856         int instance = ddi_get_instance(dip);
1857         dprov_state_t *softc = ddi_get_soft_state(statep, instance);
1858         dprov_session_t *session;
1859         int i, ret;
1860 
1861         DPROV_DEBUG(D_ATTACH, ("dprov: in dprov_detach() for %d\n",
1862             instance));
1863 
1864         if (cmd != DDI_DETACH)
1865                 return (DDI_FAILURE);
1866 
1867         /* unregister from the crypto framework */
1868         if (softc->ds_prov_handle != NULL)
1869                 if ((ret = crypto_unregister_provider(
1870                     softc->ds_prov_handle)) != CRYPTO_SUCCESS) {
1871                         cmn_err(CE_WARN, "dprov_detach: "
1872                             "crypto_unregister_provider() "
1873                             "failed (0x%x)", ret);
1874                         return (DDI_FAILURE);
1875                 }
1876 
1877 
1878         taskq_destroy(softc->ds_taskq);
1879 
1880         for (i = 0; i < softc->ds_sessions_slots; i++) {
1881                 if ((session = softc->ds_sessions[i]) == NULL)
1882                         continue;
1883 
1884                 dprov_release_session_objects(session);
1885 
1886                 kmem_free(session, sizeof (dprov_session_t));
1887                 softc->ds_sessions_count--;
1888 
1889         }
1890 
1891         kmem_free(softc->ds_sessions, softc->ds_sessions_slots *
1892             sizeof (dprov_session_t *));
1893         /* free token objects */
1894         for (i = 0; i < DPROV_MAX_OBJECTS; i++)
1895                 if (softc->ds_objects[i] != NULL)
1896                         dprov_free_object(softc->ds_objects[i]);
1897 
1898         mutex_destroy(&softc->ds_lock);
1899         ddi_soft_state_free(statep, instance);
1900 
1901         ddi_remove_minor_node(dip, NULL);
1902 
1903         return (DDI_SUCCESS);
1904 }
1905 
1906 /*
1907  * Control entry points.
1908  */
1909 static void
1910 dprov_provider_status(crypto_provider_handle_t provider, uint_t *status)
1911 {
1912         _NOTE(ARGUNUSED(provider))
1913 
1914         *status = CRYPTO_PROVIDER_READY;
1915 }
1916 
1917 /*
1918  * Digest entry points.
1919  */
1920 
1921 static int
1922 dprov_digest_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
1923     crypto_req_handle_t req)
1924 {
1925         int error = CRYPTO_FAILED;
1926         dprov_state_t *softc;
1927         /* LINTED E_FUNC_SET_NOT_USED */
1928         int instance;
1929 
1930         /* extract softc and instance number from context */
1931         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
1932         DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_init: started\n", instance));
1933 
1934         /* check mechanism */
1935         if (mechanism->cm_type != MD4_MECH_INFO_TYPE &&
1936             mechanism->cm_type != MD5_MECH_INFO_TYPE &&
1937             mechanism->cm_type != SHA1_MECH_INFO_TYPE &&
1938             mechanism->cm_type != SHA256_MECH_INFO_TYPE &&
1939             mechanism->cm_type != SHA384_MECH_INFO_TYPE &&
1940             mechanism->cm_type != SHA512_MECH_INFO_TYPE) {
1941                 cmn_err(CE_WARN, "dprov_digest_init: unexpected mech type "
1942                     "0x%llx\n", (unsigned long long)mechanism->cm_type);
1943                 return (CRYPTO_MECHANISM_INVALID);
1944         }
1945 
1946         /* submit request to the taskq */
1947         error = dprov_digest_submit_req(DPROV_REQ_DIGEST_INIT, softc, req,
1948             mechanism, NULL, NULL, NULL, ctx, KM_SLEEP);
1949 
1950         DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_init: done err = 0x%x\n",
1951             instance, error));
1952 
1953         return (error);
1954 }
1955 
1956 static int
1957 dprov_digest(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *digest,
1958     crypto_req_handle_t req)
1959 {
1960         int error = CRYPTO_FAILED;
1961         dprov_state_t *softc;
1962         /* LINTED E_FUNC_SET_NOT_USED */
1963         int instance;
1964 
1965         if (dprov_no_multipart && data->cd_length > dprov_max_digestsz)
1966                 return (CRYPTO_BUFFER_TOO_BIG);
1967 
1968         /* extract softc and instance number from context */
1969         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
1970         DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest: started\n", instance));
1971 
1972         /* submit request to the taskq */
1973         error = dprov_digest_submit_req(DPROV_REQ_DIGEST, softc, req,
1974             NULL, data, NULL, digest, ctx, KM_NOSLEEP);
1975 
1976         DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest: done, err = 0x%x\n",
1977             instance, error));
1978 
1979         return (error);
1980 }
1981 
1982 static int
1983 dprov_digest_update(crypto_ctx_t *ctx, crypto_data_t *data,
1984     crypto_req_handle_t req)
1985 {
1986         int error = CRYPTO_FAILED;
1987         dprov_state_t *softc;
1988         /* LINTED E_FUNC_SET_NOT_USED */
1989         int instance;
1990 
1991         /* extract softc and instance number from context */
1992         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
1993         DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_update: started\n",
1994             instance));
1995 
1996         /* submit request to the taskq */
1997         error = dprov_digest_submit_req(DPROV_REQ_DIGEST_UPDATE, softc,
1998             req, NULL, data, NULL, NULL, ctx, KM_NOSLEEP);
1999 
2000         DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_update: done err = 0x0%x\n",
2001             instance, error));
2002 
2003         return (error);
2004 }
2005 
2006 static int
2007 dprov_digest_key(crypto_ctx_t *ctx, crypto_key_t *key, crypto_req_handle_t req)
2008 {
2009         int error = CRYPTO_FAILED;
2010         dprov_state_t *softc;
2011         /* LINTED E_FUNC_SET_NOT_USED */
2012         int instance;
2013 
2014         /* extract softc and instance number from context */
2015         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2016         DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_key: started\n", instance));
2017 
2018         /* submit request to the taskq */
2019         error = dprov_digest_submit_req(DPROV_REQ_DIGEST_KEY, softc, req, NULL,
2020             NULL, key, NULL, ctx, KM_NOSLEEP);
2021 
2022         DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_key: done err = 0x0%x\n",
2023             instance, error));
2024 
2025         return (error);
2026 }
2027 
2028 static int
2029 dprov_digest_final(crypto_ctx_t *ctx, crypto_data_t *digest,
2030     crypto_req_handle_t req)
2031 {
2032         int error = CRYPTO_FAILED;
2033         dprov_state_t *softc;
2034         /* LINTED E_FUNC_SET_NOT_USED */
2035         int instance;
2036 
2037         /* extract softc and instance number from context */
2038         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2039         DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_final: started\n", instance));
2040 
2041         /* submit request to the taskq */
2042         error = dprov_digest_submit_req(DPROV_REQ_DIGEST_FINAL, softc, req,
2043             NULL, NULL, NULL, digest, ctx, KM_NOSLEEP);
2044 
2045         DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_final: done err = 0x0%x\n",
2046             instance, error));
2047 
2048         return (error);
2049 }
2050 
2051 /* ARGSUSED */
2052 static int
2053 dprov_digest_atomic(crypto_provider_handle_t provider,
2054     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2055     crypto_data_t *data, crypto_data_t *digest,
2056     crypto_req_handle_t req)
2057 {
2058         int error = CRYPTO_FAILED;
2059         dprov_state_t *softc = (dprov_state_t *)provider;
2060         /* LINTED E_FUNC_SET_NOT_USED */
2061         int instance;
2062 
2063         if (dprov_no_multipart && data->cd_length > dprov_max_digestsz)
2064                 return (CRYPTO_BUFFER_TOO_BIG);
2065 
2066         instance = ddi_get_instance(softc->ds_dip);
2067         DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_atomic: started\n",
2068             instance));
2069 
2070         /* check mechanism */
2071         if (mechanism->cm_type != MD4_MECH_INFO_TYPE &&
2072             mechanism->cm_type != MD5_MECH_INFO_TYPE &&
2073             mechanism->cm_type != SHA1_MECH_INFO_TYPE &&
2074             mechanism->cm_type != SHA256_MECH_INFO_TYPE &&
2075             mechanism->cm_type != SHA384_MECH_INFO_TYPE &&
2076             mechanism->cm_type != SHA512_MECH_INFO_TYPE) {
2077                 cmn_err(CE_WARN, "dprov_digest_atomic: unexpected mech type "
2078                     "0x%llx\n", (unsigned long long)mechanism->cm_type);
2079                 return (CRYPTO_MECHANISM_INVALID);
2080         }
2081 
2082         /* submit request to the taskq */
2083         error = dprov_digest_submit_req(DPROV_REQ_DIGEST_ATOMIC, softc, req,
2084             mechanism, data, NULL, digest, NULL, KM_SLEEP);
2085 
2086         DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_atomic: done err = 0x0%x\n",
2087             instance, error));
2088 
2089         return (error);
2090 }
2091 
2092 /*
2093  * MAC entry points.
2094  */
2095 
2096 /*
2097  * Checks whether the specified mech_type is supported by mac
2098  * entry points.
2099  */
2100 static boolean_t
2101 dprov_valid_mac_mech(crypto_mech_type_t mech_type)
2102 {
2103         return (mech_type == MD5_HMAC_MECH_INFO_TYPE ||
2104             mech_type == MD5_HMAC_GEN_MECH_INFO_TYPE ||
2105             mech_type == SHA1_HMAC_MECH_INFO_TYPE ||
2106             mech_type == SHA1_HMAC_GEN_MECH_INFO_TYPE ||
2107             mech_type == SHA256_HMAC_MECH_INFO_TYPE ||
2108             mech_type == SHA256_HMAC_GEN_MECH_INFO_TYPE ||
2109             mech_type == SHA384_HMAC_MECH_INFO_TYPE ||
2110             mech_type == SHA384_HMAC_GEN_MECH_INFO_TYPE ||
2111             mech_type == SHA512_HMAC_MECH_INFO_TYPE ||
2112             mech_type == SHA512_HMAC_GEN_MECH_INFO_TYPE ||
2113             mech_type == AES_GMAC_MECH_INFO_TYPE);
2114 }
2115 
2116 static int
2117 dprov_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
2118     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
2119     crypto_req_handle_t req)
2120 {
2121         int error = CRYPTO_FAILED;
2122         dprov_state_t *softc;
2123         /* LINTED E_FUNC_SET_NOT_USED */
2124         int instance;
2125 
2126         /* extract softc and instance number from context */
2127         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2128         DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_init: started\n", instance));
2129 
2130         /* check mechanism */
2131         if (!dprov_valid_mac_mech(mechanism->cm_type)) {
2132                 cmn_err(CE_WARN, "dprov_mac_init: unexpected mech type "
2133                     "0x%llx\n", (unsigned long long)mechanism->cm_type);
2134                 return (CRYPTO_MECHANISM_INVALID);
2135         }
2136 
2137         if (ctx_template != NULL)
2138                 return (CRYPTO_ARGUMENTS_BAD);
2139 
2140         /* submit request to the taskq */
2141         error = dprov_mac_submit_req(DPROV_REQ_MAC_INIT, softc, req,
2142             mechanism, NULL, key, NULL, ctx, 0, KM_SLEEP);
2143 
2144         DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_init: done err = 0x%x\n",
2145             instance, error));
2146 
2147         return (error);
2148 }
2149 
2150 static int
2151 dprov_mac(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *mac,
2152     crypto_req_handle_t req)
2153 {
2154         int error = CRYPTO_FAILED;
2155         dprov_state_t *softc;
2156         /* LINTED E_FUNC_SET_NOT_USED */
2157         int instance;
2158 
2159         /* extract softc and instance number from context */
2160         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2161         DPROV_DEBUG(D_MAC, ("(%d) dprov_mac: started\n", instance));
2162 
2163         /* submit request to the taskq */
2164         error = dprov_mac_submit_req(DPROV_REQ_MAC, softc, req,
2165             NULL, data, NULL, mac, ctx, 0, KM_NOSLEEP);
2166 
2167         DPROV_DEBUG(D_MAC, ("(%d) dprov_mac: done, err = 0x%x\n", instance,
2168             error));
2169 
2170         return (error);
2171 }
2172 
2173 static int
2174 dprov_mac_update(crypto_ctx_t *ctx, crypto_data_t *data,
2175     crypto_req_handle_t req)
2176 {
2177         int error = CRYPTO_FAILED;
2178         dprov_state_t *softc;
2179         /* LINTED E_FUNC_SET_NOT_USED */
2180         int instance;
2181 
2182         /* extract softc and instance number from context */
2183         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2184         DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_update: started\n", instance));
2185 
2186         /* submit request to the taskq */
2187         error = dprov_mac_submit_req(DPROV_REQ_MAC_UPDATE, softc,
2188             req, NULL, data, NULL, NULL, ctx, 0, KM_NOSLEEP);
2189 
2190         DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_update: done err = 0x0%x\n",
2191             instance, error));
2192 
2193         return (error);
2194 }
2195 
2196 static int
2197 dprov_mac_final(crypto_ctx_t *ctx, crypto_data_t *mac, crypto_req_handle_t req)
2198 {
2199         int error = CRYPTO_FAILED;
2200         dprov_state_t *softc;
2201         /* LINTED E_FUNC_SET_NOT_USED */
2202         int instance;
2203 
2204         /* extract softc and instance number from context */
2205         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2206         DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_final: started\n", instance));
2207 
2208         /* submit request to the taskq */
2209         error = dprov_mac_submit_req(DPROV_REQ_MAC_FINAL, softc, req,
2210             NULL, NULL, NULL, mac, ctx, 0, KM_NOSLEEP);
2211 
2212         DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_final: done err = 0x0%x\n",
2213             instance, error));
2214 
2215         return (error);
2216 }
2217 
2218 static int
2219 dprov_mac_atomic(crypto_provider_handle_t provider,
2220     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2221     crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
2222     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
2223 {
2224         int error = CRYPTO_FAILED;
2225         dprov_state_t *softc = (dprov_state_t *)provider;
2226         /* LINTED E_FUNC_SET_NOT_USED */
2227         int instance;
2228 
2229         instance = ddi_get_instance(softc->ds_dip);
2230         DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_atomic: started\n", instance));
2231 
2232         if (ctx_template != NULL)
2233                 return (CRYPTO_ARGUMENTS_BAD);
2234 
2235         /* check mechanism */
2236         if (!dprov_valid_mac_mech(mechanism->cm_type)) {
2237                 cmn_err(CE_WARN, "dprov_mac_atomic: unexpected mech type "
2238                     "0x%llx\n", (unsigned long long)mechanism->cm_type);
2239                 return (CRYPTO_MECHANISM_INVALID);
2240         }
2241 
2242         /* submit request to the taskq */
2243         error = dprov_mac_submit_req(DPROV_REQ_MAC_ATOMIC, softc, req,
2244             mechanism, data, key, mac, NULL, session_id, KM_SLEEP);
2245 
2246         DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_atomic: done err = 0x0%x\n",
2247             instance, error));
2248 
2249         return (error);
2250 }
2251 
2252 static int
2253 dprov_mac_verify_atomic(crypto_provider_handle_t provider,
2254     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2255     crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
2256     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
2257 {
2258         int error = CRYPTO_FAILED;
2259         dprov_state_t *softc = (dprov_state_t *)provider;
2260         /* LINTED E_FUNC_SET_NOT_USED */
2261         int instance;
2262 
2263         instance = ddi_get_instance(softc->ds_dip);
2264         DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_verify_atomic: started\n",
2265             instance));
2266 
2267         if (ctx_template != NULL)
2268                 return (CRYPTO_ARGUMENTS_BAD);
2269 
2270         /* check mechanism */
2271         if (!dprov_valid_mac_mech(mechanism->cm_type)) {
2272                 cmn_err(CE_WARN, "dprov_mac_verify_atomic: unexpected mech "
2273                     "type 0x%llx\n", (unsigned long long)mechanism->cm_type);
2274                 return (CRYPTO_MECHANISM_INVALID);
2275         }
2276 
2277         /* submit request to the taskq */
2278         error = dprov_mac_submit_req(DPROV_REQ_MAC_VERIFY_ATOMIC, softc, req,
2279             mechanism, data, key, mac, NULL, session_id, KM_SLEEP);
2280 
2281         DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_verify_atomic: done err = 0x0%x\n",
2282             instance, error));
2283 
2284         return (error);
2285 }
2286 
2287 /*
2288  * Cipher (encrypt/decrypt) entry points.
2289  */
2290 
2291 /*
2292  * Checks whether the specified mech_type is supported by cipher entry
2293  * points.
2294  */
2295 static boolean_t
2296 dprov_valid_cipher_mech(crypto_mech_type_t mech_type)
2297 {
2298         return (mech_type == DES_CBC_MECH_INFO_TYPE ||
2299             mech_type == DES3_CBC_MECH_INFO_TYPE ||
2300             mech_type == DES_ECB_MECH_INFO_TYPE ||
2301             mech_type == DES3_ECB_MECH_INFO_TYPE ||
2302             mech_type == BLOWFISH_CBC_MECH_INFO_TYPE ||
2303             mech_type == BLOWFISH_ECB_MECH_INFO_TYPE ||
2304             mech_type == AES_CBC_MECH_INFO_TYPE ||
2305             mech_type == AES_ECB_MECH_INFO_TYPE ||
2306             mech_type == AES_CTR_MECH_INFO_TYPE ||
2307             mech_type == AES_CCM_MECH_INFO_TYPE ||
2308             mech_type == AES_GCM_MECH_INFO_TYPE ||
2309             mech_type == AES_GMAC_MECH_INFO_TYPE ||
2310             mech_type == RC4_MECH_INFO_TYPE ||
2311             mech_type == RSA_PKCS_MECH_INFO_TYPE ||
2312             mech_type == RSA_X_509_MECH_INFO_TYPE ||
2313             mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE ||
2314             mech_type == SHA1_RSA_PKCS_MECH_INFO_TYPE ||
2315             mech_type == SHA256_RSA_PKCS_MECH_INFO_TYPE ||
2316             mech_type == SHA384_RSA_PKCS_MECH_INFO_TYPE ||
2317             mech_type == SHA512_RSA_PKCS_MECH_INFO_TYPE);
2318 }
2319 
2320 static boolean_t
2321 is_publickey_mech(crypto_mech_type_t mech_type)
2322 {
2323         return (mech_type == RSA_PKCS_MECH_INFO_TYPE ||
2324             mech_type == RSA_X_509_MECH_INFO_TYPE ||
2325             mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE ||
2326             mech_type == SHA1_RSA_PKCS_MECH_INFO_TYPE ||
2327             mech_type == SHA256_RSA_PKCS_MECH_INFO_TYPE ||
2328             mech_type == SHA384_RSA_PKCS_MECH_INFO_TYPE ||
2329             mech_type == SHA512_RSA_PKCS_MECH_INFO_TYPE ||
2330             mech_type == ECDSA_SHA1_MECH_INFO_TYPE ||
2331             mech_type == ECDSA_MECH_INFO_TYPE);
2332 }
2333 
2334 
2335 /* ARGSUSED */
2336 static int
2337 dprov_encrypt_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
2338     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
2339     crypto_req_handle_t req)
2340 {
2341         int error = CRYPTO_FAILED;
2342         dprov_state_t *softc;
2343         /* LINTED E_FUNC_SET_NOT_USED */
2344         int instance;
2345 
2346         /* extract softc and instance number from context */
2347         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2348         DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt_init: started\n",
2349             instance));
2350 
2351         /* check mechanism */
2352         if (!dprov_valid_cipher_mech(mechanism->cm_type)) {
2353                 cmn_err(CE_WARN, "dprov_encrypt_init: unexpected mech type "
2354                     "0x%llx\n", (unsigned long long)mechanism->cm_type);
2355                 return (CRYPTO_MECHANISM_INVALID);
2356         }
2357 
2358         /* submit request to the taskq */
2359         error = dprov_cipher_submit_req(DPROV_REQ_ENCRYPT_INIT, softc,
2360             req, mechanism, key, NULL, NULL, ctx, 0, KM_SLEEP);
2361 
2362         DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt_init: done err = 0x0%x\n",
2363             instance, error));
2364 
2365         return (error);
2366 }
2367 
2368 /* ARGSUSED */
2369 static int
2370 dprov_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
2371     crypto_data_t *ciphertext, crypto_req_handle_t req)
2372 {
2373         int error = CRYPTO_FAILED;
2374         dprov_state_t *softc;
2375         /* LINTED E_FUNC_SET_NOT_USED */
2376         int instance;
2377 
2378         /* extract softc and instance number from context */
2379         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2380         DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt: started\n", instance));
2381 
2382         /* submit request to the taskq */
2383         error = dprov_cipher_submit_req(DPROV_REQ_ENCRYPT, softc,
2384             req, NULL, NULL, plaintext, ciphertext, ctx, 0, KM_NOSLEEP);
2385 
2386         DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt: done err = 0x0%x\n",
2387             instance, error));
2388 
2389         return (error);
2390 }
2391 
2392 /* ARGSUSED */
2393 static int
2394 dprov_encrypt_update(crypto_ctx_t *ctx, crypto_data_t *plaintext,
2395     crypto_data_t *ciphertext, crypto_req_handle_t req)
2396 {
2397         int error = CRYPTO_FAILED;
2398         dprov_state_t *softc;
2399         /* LINTED E_FUNC_SET_NOT_USED */
2400         int instance;
2401 
2402         /* extract softc and instance number from context */
2403         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2404         DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt_update: started\n",
2405             instance));
2406 
2407         /* submit request to the taskq */
2408         error = dprov_cipher_submit_req(DPROV_REQ_ENCRYPT_UPDATE, softc,
2409             req, NULL, NULL, plaintext, ciphertext, ctx, 0, KM_NOSLEEP);
2410 
2411         DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt_update: done err = 0x0%x\n",
2412             instance, error));
2413 
2414         return (error);
2415 }
2416 
2417 /* ARGSUSED */
2418 static int
2419 dprov_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
2420     crypto_req_handle_t req)
2421 {
2422         int error = CRYPTO_FAILED;
2423         dprov_state_t *softc;
2424         /* LINTED E_FUNC_SET_NOT_USED */
2425         int instance;
2426 
2427         /* extract softc and instance number from context */
2428         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2429         DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt_final: started\n",
2430             instance));
2431 
2432         /* submit request to the taskq */
2433         error = dprov_cipher_submit_req(DPROV_REQ_ENCRYPT_FINAL, softc,
2434             req, NULL, NULL, NULL, ciphertext, ctx, 0, KM_NOSLEEP);
2435 
2436         DPROV_DEBUG(D_CIPHER, ("(%d) dprov_encrypt_final: done err = 0x0%x\n",
2437             instance, error));
2438 
2439         return (error);
2440 }
2441 
2442 static int
2443 dprov_encrypt_atomic(crypto_provider_handle_t provider,
2444     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2445     crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext,
2446     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
2447 {
2448         int error = CRYPTO_FAILED;
2449         dprov_state_t *softc = (dprov_state_t *)provider;
2450         /* LINTED E_FUNC_SET_NOT_USED */
2451         int instance;
2452 
2453         instance = ddi_get_instance(softc->ds_dip);
2454         DPROV_DEBUG(D_MAC, ("(%d) dprov_encrypt_atomic: started\n", instance));
2455 
2456         if (ctx_template != NULL)
2457                 return (CRYPTO_ARGUMENTS_BAD);
2458 
2459         /* check mechanism */
2460         if (!dprov_valid_cipher_mech(mechanism->cm_type)) {
2461                 cmn_err(CE_WARN, "dprov_encrypt_atomic: unexpected mech type "
2462                     "0x%llx\n", (unsigned long long)mechanism->cm_type);
2463                 return (CRYPTO_MECHANISM_INVALID);
2464         }
2465 
2466         error = dprov_cipher_submit_req(DPROV_REQ_ENCRYPT_ATOMIC, softc,
2467             req, mechanism, key, plaintext, ciphertext, NULL, session_id,
2468             KM_SLEEP);
2469 
2470         DPROV_DEBUG(D_MAC, ("(%d) dprov_encrypt_atomic: done err = 0x0%x\n",
2471             instance, error));
2472 
2473         return (error);
2474 }
2475 
2476 /* ARGSUSED */
2477 static int
2478 dprov_decrypt_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
2479     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
2480     crypto_req_handle_t req)
2481 {
2482         int error = CRYPTO_FAILED;
2483         dprov_state_t *softc;
2484         /* LINTED E_FUNC_SET_NOT_USED */
2485         int instance;
2486 
2487         /* extract softc and instance number from context */
2488         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2489         DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt_init: started\n",
2490             instance));
2491 
2492         /* check mechanism */
2493         if (!dprov_valid_cipher_mech(mechanism->cm_type)) {
2494                 cmn_err(CE_WARN, "dprov_decrypt_init: unexpected mech type "
2495                     "0x%llx\n", (unsigned long long)mechanism->cm_type);
2496                 return (CRYPTO_MECHANISM_INVALID);
2497         }
2498 
2499         /* submit request to the taskq */
2500         error = dprov_cipher_submit_req(DPROV_REQ_DECRYPT_INIT, softc,
2501             req, mechanism, key, NULL, NULL, ctx, 0, KM_SLEEP);
2502 
2503         DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt_init: done err = 0x0%x\n",
2504             instance, error));
2505 
2506         return (error);
2507 }
2508 
2509 /* ARGSUSED */
2510 static int
2511 dprov_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
2512     crypto_data_t *plaintext, crypto_req_handle_t req)
2513 {
2514         int error = CRYPTO_FAILED;
2515 
2516         dprov_state_t *softc;
2517         /* LINTED E_FUNC_SET_NOT_USED */
2518         int instance;
2519 
2520         /* extract softc and instance number from context */
2521         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2522         DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt: started\n", instance));
2523 
2524         /* submit request to the taskq */
2525         error = dprov_cipher_submit_req(DPROV_REQ_DECRYPT, softc,
2526             req, NULL, NULL, plaintext, ciphertext, ctx, 0, KM_NOSLEEP);
2527 
2528         DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt: done err = 0x0%x\n",
2529             instance, error));
2530 
2531         return (error);
2532 }
2533 
2534 /* ARGSUSED */
2535 static int
2536 dprov_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
2537     crypto_data_t *plaintext, crypto_req_handle_t req)
2538 {
2539         int error = CRYPTO_FAILED;
2540         dprov_state_t *softc;
2541         /* LINTED E_FUNC_SET_NOT_USED */
2542         int instance;
2543 
2544         /* extract softc and instance number from context */
2545         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2546         DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt_update: started\n",
2547             instance));
2548 
2549         /* submit request to the taskq */
2550         error = dprov_cipher_submit_req(DPROV_REQ_DECRYPT_UPDATE, softc,
2551             req, NULL, NULL, plaintext, ciphertext, ctx, 0, KM_NOSLEEP);
2552 
2553         DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt_update: done err = 0x0%x\n",
2554             instance, error));
2555 
2556         return (error);
2557 }
2558 
2559 /* ARGSUSED */
2560 static int
2561 dprov_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *plaintext,
2562     crypto_req_handle_t req)
2563 {
2564         int error = CRYPTO_FAILED;
2565         dprov_state_t *softc;
2566         /* LINTED E_FUNC_SET_NOT_USED */
2567         int instance;
2568 
2569         /* extract softc and instance number from context */
2570         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2571         DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt_final: started\n",
2572             instance));
2573 
2574         /* submit request to the taskq */
2575         error = dprov_cipher_submit_req(DPROV_REQ_DECRYPT_FINAL, softc,
2576             req, NULL, NULL, plaintext, NULL, ctx, 0, KM_NOSLEEP);
2577 
2578         DPROV_DEBUG(D_CIPHER, ("(%d) dprov_decrypt_final: done err = 0x0%x\n",
2579             instance, error));
2580 
2581         return (error);
2582 }
2583 
2584 static int
2585 dprov_decrypt_atomic(crypto_provider_handle_t provider,
2586     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2587     crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext,
2588     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
2589 {
2590         int error = CRYPTO_FAILED;
2591         dprov_state_t *softc = (dprov_state_t *)provider;
2592         /* LINTED E_FUNC_SET_NOT_USED */
2593         int instance;
2594 
2595         instance = ddi_get_instance(softc->ds_dip);
2596         DPROV_DEBUG(D_MAC, ("(%d) dprov_decrypt_atomic: started\n", instance));
2597 
2598         if (ctx_template != NULL)
2599                 return (CRYPTO_ARGUMENTS_BAD);
2600 
2601         /* check mechanism */
2602         if (!dprov_valid_cipher_mech(mechanism->cm_type)) {
2603                 cmn_err(CE_WARN, "dprov_atomic_init: unexpected mech type "
2604                     "0x%llx\n", (unsigned long long)mechanism->cm_type);
2605                 return (CRYPTO_MECHANISM_INVALID);
2606         }
2607 
2608         error = dprov_cipher_submit_req(DPROV_REQ_DECRYPT_ATOMIC, softc,
2609             req, mechanism, key, plaintext, ciphertext, NULL, session_id,
2610             KM_SLEEP);
2611 
2612         DPROV_DEBUG(D_MAC, ("(%d) dprov_decrypt_atomic: done err = 0x0%x\n",
2613             instance, error));
2614 
2615         return (error);
2616 }
2617 
2618 /*
2619  * Sign entry points.
2620  */
2621 
2622 /*
2623  * Checks whether the specified mech_type is supported by sign/verify
2624  * entry points.
2625  */
2626 static boolean_t
2627 dprov_valid_sign_verif_mech(crypto_mech_type_t mech_type)
2628 {
2629         return (mech_type == MD5_HMAC_MECH_INFO_TYPE ||
2630             mech_type == MD5_HMAC_GEN_MECH_INFO_TYPE ||
2631             mech_type == SHA1_HMAC_MECH_INFO_TYPE ||
2632             mech_type == SHA1_HMAC_GEN_MECH_INFO_TYPE ||
2633             mech_type == SHA256_HMAC_MECH_INFO_TYPE ||
2634             mech_type == SHA256_HMAC_GEN_MECH_INFO_TYPE ||
2635             mech_type == SHA384_HMAC_MECH_INFO_TYPE ||
2636             mech_type == SHA384_HMAC_GEN_MECH_INFO_TYPE ||
2637             mech_type == SHA512_HMAC_MECH_INFO_TYPE ||
2638             mech_type == SHA512_HMAC_GEN_MECH_INFO_TYPE ||
2639             mech_type == RSA_PKCS_MECH_INFO_TYPE ||
2640             mech_type == RSA_X_509_MECH_INFO_TYPE ||
2641             mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE ||
2642             mech_type == SHA1_RSA_PKCS_MECH_INFO_TYPE ||
2643             mech_type == SHA256_RSA_PKCS_MECH_INFO_TYPE ||
2644             mech_type == SHA384_RSA_PKCS_MECH_INFO_TYPE ||
2645             mech_type == SHA512_RSA_PKCS_MECH_INFO_TYPE ||
2646             mech_type == ECDSA_SHA1_MECH_INFO_TYPE ||
2647             mech_type == ECDSA_MECH_INFO_TYPE);
2648 }
2649 
2650 static int
2651 dprov_sign_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
2652     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
2653     crypto_req_handle_t req)
2654 {
2655         int error = CRYPTO_FAILED;
2656         dprov_state_t *softc;
2657         /* LINTED E_FUNC_SET_NOT_USED */
2658         int instance;
2659 
2660         /* extract softc and instance number from context */
2661         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2662         DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_init: started\n", instance));
2663 
2664         /* check mechanism */
2665         if (!dprov_valid_sign_verif_mech(mechanism->cm_type)) {
2666                 cmn_err(CE_WARN, "dprov_sign_init: unexpected mech type "
2667                     "0x%llx\n", (unsigned long long)mechanism->cm_type);
2668                 return (CRYPTO_MECHANISM_INVALID);
2669         }
2670 
2671         if (ctx_template != NULL)
2672                 return (CRYPTO_ARGUMENTS_BAD);
2673 
2674         /* submit request to the taskq */
2675         error = dprov_sign_submit_req(DPROV_REQ_SIGN_INIT, softc, req,
2676             mechanism, key, NULL, NULL, ctx, 0, KM_SLEEP);
2677 
2678         DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_init: done err = 0x%x\n",
2679             instance, error));
2680 
2681         return (error);
2682 }
2683 
2684 static int
2685 dprov_sign(crypto_ctx_t *ctx, crypto_data_t *data,
2686     crypto_data_t *signature, crypto_req_handle_t req)
2687 {
2688         int error = CRYPTO_FAILED;
2689         dprov_state_t *softc;
2690         /* LINTED E_FUNC_SET_NOT_USED */
2691         int instance;
2692 
2693         /* extract softc and instance number from context */
2694         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2695         DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign: started\n", instance));
2696 
2697         /* submit request to the taskq */
2698         error = dprov_sign_submit_req(DPROV_REQ_SIGN, softc, req,
2699             NULL, NULL, data, signature, ctx, 0, KM_NOSLEEP);
2700 
2701         DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign: done err = 0x%x\n",
2702             instance, error));
2703 
2704         return (error);
2705 }
2706 
2707 static int
2708 dprov_sign_update(crypto_ctx_t *ctx, crypto_data_t *data,
2709     crypto_req_handle_t req)
2710 {
2711         int error = CRYPTO_FAILED;
2712         dprov_state_t *softc;
2713         /* LINTED E_FUNC_SET_NOT_USED */
2714         int instance;
2715 
2716         /* extract softc and instance number from context */
2717         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2718         DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_update: started\n", instance));
2719 
2720         /* submit request to the taskq */
2721         error = dprov_sign_submit_req(DPROV_REQ_SIGN_UPDATE, softc, req,
2722             NULL, NULL, data, NULL, ctx, 0, KM_NOSLEEP);
2723 
2724         DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_update: done err = 0x%x\n",
2725             instance, error));
2726 
2727         return (error);
2728 }
2729 
2730 static int
2731 dprov_sign_final(crypto_ctx_t *ctx, crypto_data_t *signature,
2732     crypto_req_handle_t req)
2733 {
2734         int error = CRYPTO_FAILED;
2735         dprov_state_t *softc;
2736         /* LINTED E_FUNC_SET_NOT_USED */
2737         int instance;
2738 
2739         /* extract softc and instance number from context */
2740         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2741         DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_final: started\n", instance));
2742 
2743         /* submit request to the taskq */
2744         error = dprov_sign_submit_req(DPROV_REQ_SIGN_FINAL, softc, req,
2745             NULL, NULL, NULL, signature, ctx, 0, KM_NOSLEEP);
2746 
2747         DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_final: done err = 0x%x\n",
2748             instance, error));
2749 
2750         return (error);
2751 }
2752 
2753 static int
2754 dprov_sign_atomic(crypto_provider_handle_t provider,
2755     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2756     crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
2757     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
2758 {
2759         int error = CRYPTO_FAILED;
2760         dprov_state_t *softc = (dprov_state_t *)provider;
2761         /* LINTED E_FUNC_SET_NOT_USED */
2762         int instance;
2763 
2764         instance = ddi_get_instance(softc->ds_dip);
2765         DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_atomic: started\n", instance));
2766 
2767         /* check mechanism */
2768         if (!dprov_valid_sign_verif_mech(mechanism->cm_type)) {
2769                 cmn_err(CE_WARN, "dprov_sign_atomic: unexpected mech type "
2770                     "0x%llx\n", (unsigned long long)mechanism->cm_type);
2771                 return (CRYPTO_MECHANISM_INVALID);
2772         }
2773 
2774         if (ctx_template != NULL)
2775                 return (CRYPTO_ARGUMENTS_BAD);
2776 
2777         /* submit request to the taskq */
2778         error = dprov_sign_submit_req(DPROV_REQ_SIGN_ATOMIC, softc, req,
2779             mechanism, key, data, signature, NULL, session_id, KM_SLEEP);
2780 
2781         DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_atomic: done err = 0x%x\n",
2782             instance, error));
2783 
2784         return (error);
2785 }
2786 
2787 static int
2788 dprov_sign_recover_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
2789     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
2790     crypto_req_handle_t req)
2791 {
2792         int error = CRYPTO_FAILED;
2793         dprov_state_t *softc;
2794         /* LINTED E_FUNC_SET_NOT_USED */
2795         int instance;
2796 
2797         /* extract softc and instance number from context */
2798         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2799         DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_recover_init: started\n",
2800             instance));
2801 
2802         if (ctx_template != NULL)
2803                 return (CRYPTO_ARGUMENTS_BAD);
2804 
2805         /* submit request to the taskq */
2806         error = dprov_sign_submit_req(DPROV_REQ_SIGN_RECOVER_INIT, softc, req,
2807             mechanism, key, NULL, NULL, ctx, 0, KM_SLEEP);
2808 
2809         DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_recover_init: done err = 0x%x\n",
2810             instance, error));
2811 
2812         return (error);
2813 }
2814 
2815 static int
2816 dprov_sign_recover(crypto_ctx_t *ctx, crypto_data_t *data,
2817     crypto_data_t *signature, crypto_req_handle_t req)
2818 {
2819         int error = CRYPTO_FAILED;
2820         dprov_state_t *softc;
2821         /* LINTED E_FUNC_SET_NOT_USED */
2822         int instance;
2823 
2824         /* extract softc and instance number from context */
2825         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2826         DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_recover: started\n", instance));
2827 
2828         /* submit request to the taskq */
2829         error = dprov_sign_submit_req(DPROV_REQ_SIGN_RECOVER, softc, req,
2830             NULL, NULL, data, signature, ctx, 0, KM_NOSLEEP);
2831 
2832         DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_recover: done err = 0x%x\n",
2833             instance, error));
2834 
2835         return (error);
2836 }
2837 
2838 static int
2839 dprov_sign_recover_atomic(crypto_provider_handle_t provider,
2840     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2841     crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
2842     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
2843 {
2844         int error = CRYPTO_FAILED;
2845         dprov_state_t *softc = (dprov_state_t *)provider;
2846         /* LINTED E_FUNC_SET_NOT_USED */
2847         int instance;
2848 
2849         instance = ddi_get_instance(softc->ds_dip);
2850         DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_recover_atomic: started\n",
2851             instance));
2852 
2853         if (ctx_template != NULL)
2854                 return (CRYPTO_ARGUMENTS_BAD);
2855 
2856         /* submit request to the taskq */
2857         error = dprov_sign_submit_req(DPROV_REQ_SIGN_RECOVER_ATOMIC, softc, req,
2858             mechanism, key, data, signature, NULL, session_id, KM_SLEEP);
2859 
2860         DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_recover_atomic: done "
2861             "err = 0x%x\n", instance, error));
2862 
2863         return (error);
2864 }
2865 
2866 /*
2867  * Verify entry points.
2868  */
2869 
2870 static int
2871 dprov_verify_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
2872     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
2873     crypto_req_handle_t req)
2874 {
2875         int error = CRYPTO_FAILED;
2876         dprov_state_t *softc;
2877         /* LINTED E_FUNC_SET_NOT_USED */
2878         int instance;
2879 
2880         /* extract softc and instance number from context */
2881         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2882         DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_init: started\n", instance));
2883 
2884         /* check mechanism */
2885         if (!dprov_valid_sign_verif_mech(mechanism->cm_type)) {
2886                 cmn_err(CE_WARN, "dprov_verify_init: unexpected mech type "
2887                     "0x%llx\n", (unsigned long long)mechanism->cm_type);
2888                 return (CRYPTO_MECHANISM_INVALID);
2889         }
2890 
2891         if (ctx_template != NULL)
2892                 return (CRYPTO_ARGUMENTS_BAD);
2893 
2894         error = dprov_verify_submit_req(DPROV_REQ_VERIFY_INIT, softc, req,
2895             mechanism, key, NULL, NULL, ctx, 0, KM_SLEEP);
2896 
2897         DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_init: done err = 0x%x\n",
2898             instance, error));
2899 
2900         return (error);
2901 }
2902 
2903 static int
2904 dprov_verify(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
2905     crypto_req_handle_t req)
2906 {
2907         int error = CRYPTO_FAILED;
2908         dprov_state_t *softc;
2909         /* LINTED E_FUNC_SET_NOT_USED */
2910         int instance;
2911 
2912         /* extract softc and instance number from context */
2913         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2914         DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify: started\n", instance));
2915 
2916         /* submit request to the taskq */
2917         error = dprov_verify_submit_req(DPROV_REQ_VERIFY, softc, req,
2918             NULL, NULL, data, signature, ctx, 0, KM_NOSLEEP);
2919 
2920         DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify: done err = 0x%x\n",
2921             instance, error));
2922 
2923         return (error);
2924 }
2925 
2926 static int
2927 dprov_verify_update(crypto_ctx_t *ctx, crypto_data_t *data,
2928     crypto_req_handle_t req)
2929 {
2930         int error = CRYPTO_FAILED;
2931         dprov_state_t *softc;
2932         /* LINTED E_FUNC_SET_NOT_USED */
2933         int instance;
2934 
2935         /* extract softc and instance number from context */
2936         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2937         DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_update: started\n",
2938             instance));
2939 
2940         /* submit request to the taskq */
2941         error = dprov_verify_submit_req(DPROV_REQ_VERIFY_UPDATE, softc, req,
2942             NULL, NULL, data, NULL, ctx, 0, KM_NOSLEEP);
2943 
2944         DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_update: done err = 0x%x\n",
2945             instance, error));
2946 
2947         return (error);
2948 }
2949 
2950 static int
2951 dprov_verify_final(crypto_ctx_t *ctx, crypto_data_t *signature,
2952     crypto_req_handle_t req)
2953 {
2954         int error = CRYPTO_FAILED;
2955         dprov_state_t *softc;
2956         /* LINTED E_FUNC_SET_NOT_USED */
2957         int instance;
2958 
2959         /* extract softc and instance number from context */
2960         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
2961         DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_final: started\n", instance));
2962 
2963         /* submit request to the taskq */
2964         error = dprov_verify_submit_req(DPROV_REQ_VERIFY_FINAL, softc, req,
2965             NULL, NULL, NULL, signature, ctx, 0, KM_NOSLEEP);
2966 
2967         DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_final: done err = 0x%x\n",
2968             instance, error));
2969 
2970         return (error);
2971 }
2972 
2973 static int
2974 dprov_verify_atomic(crypto_provider_handle_t provider,
2975     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
2976     crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
2977     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
2978 {
2979         int error = CRYPTO_FAILED;
2980         dprov_state_t *softc = (dprov_state_t *)provider;
2981         /* LINTED E_FUNC_SET_NOT_USED */
2982         int instance;
2983 
2984         instance = ddi_get_instance(softc->ds_dip);
2985         DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_atomic: started\n",
2986             instance));
2987 
2988         /* check mechanism */
2989         if (!dprov_valid_sign_verif_mech(mechanism->cm_type)) {
2990                 cmn_err(CE_WARN, "dprov_verify_atomic: unexpected mech type "
2991                     "0x%llx\n", (unsigned long long)mechanism->cm_type);
2992                 return (CRYPTO_MECHANISM_INVALID);
2993         }
2994 
2995         if (ctx_template != NULL)
2996                 return (CRYPTO_ARGUMENTS_BAD);
2997 
2998         /* submit request to the taskq */
2999         error = dprov_verify_submit_req(DPROV_REQ_VERIFY_ATOMIC, softc, req,
3000             mechanism, key, data, signature, NULL, session_id, KM_SLEEP);
3001 
3002         DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_atomic: done err = 0x%x\n",
3003             instance, error));
3004 
3005         return (error);
3006 }
3007 
3008 static int
3009 dprov_verify_recover_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
3010     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
3011     crypto_req_handle_t req)
3012 {
3013         int error = CRYPTO_FAILED;
3014         dprov_state_t *softc;
3015         /* LINTED E_FUNC_SET_NOT_USED */
3016         int instance;
3017 
3018         /* extract softc and instance number from context */
3019         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3020         DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_recover_init: started\n",
3021             instance));
3022 
3023         if (ctx_template != NULL)
3024                 return (CRYPTO_ARGUMENTS_BAD);
3025 
3026         /* submit request to the taskq */
3027         error = dprov_verify_submit_req(DPROV_REQ_VERIFY_RECOVER_INIT, softc,
3028             req, mechanism, key, NULL, NULL, ctx, 0, KM_SLEEP);
3029 
3030         DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_recover_init: done "
3031             "err = 0x%x\n", instance, error));
3032 
3033         return (error);
3034 }
3035 
3036 static int
3037 dprov_verify_recover(crypto_ctx_t *ctx, crypto_data_t *signature,
3038     crypto_data_t *data, crypto_req_handle_t req)
3039 {
3040         int error = CRYPTO_FAILED;
3041         dprov_state_t *softc;
3042         /* LINTED E_FUNC_SET_NOT_USED */
3043         int instance;
3044 
3045         /* extract softc and instance number from context */
3046         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3047         DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_recover: started\n",
3048             instance));
3049 
3050         /* submit request to the taskq */
3051         error = dprov_verify_submit_req(DPROV_REQ_VERIFY_RECOVER, softc, req,
3052             NULL, NULL, data, signature, ctx, 0, KM_NOSLEEP);
3053 
3054         DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_recover: done err = 0x%x\n",
3055             instance, error));
3056 
3057         return (error);
3058 }
3059 
3060 static int
3061 dprov_verify_recover_atomic(crypto_provider_handle_t provider,
3062     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
3063     crypto_key_t *key, crypto_data_t *signature, crypto_data_t *data,
3064     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
3065 {
3066         int error = CRYPTO_FAILED;
3067         dprov_state_t *softc = (dprov_state_t *)provider;
3068         /* LINTED E_FUNC_SET_NOT_USED */
3069         int instance;
3070 
3071         instance = ddi_get_instance(softc->ds_dip);
3072         DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_recover_atomic: started\n",
3073             instance));
3074 
3075         if (ctx_template != NULL)
3076                 return (CRYPTO_ARGUMENTS_BAD);
3077 
3078         /* submit request to the taskq */
3079         error = dprov_verify_submit_req(DPROV_REQ_VERIFY_RECOVER_ATOMIC, softc,
3080             req, mechanism, key, data, signature, NULL, session_id, KM_SLEEP);
3081 
3082         DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_recover_atomic: done "
3083             "err = 0x%x\n", instance, error));
3084 
3085         return (error);
3086 }
3087 
3088 /*
3089  * Dual operations entry points.
3090  */
3091 
3092 static int
3093 dprov_digest_encrypt_update(crypto_ctx_t *digest_ctx,
3094     crypto_ctx_t *encrypt_ctx, crypto_data_t *plaintext,
3095     crypto_data_t *ciphertext, crypto_req_handle_t req)
3096 {
3097         int error = CRYPTO_FAILED;
3098         dprov_state_t *softc;
3099         /* LINTED E_FUNC_SET_NOT_USED */
3100         int instance;
3101 
3102         /* extract softc and instance number from context */
3103         DPROV_SOFTC_FROM_CTX(digest_ctx, softc, instance);
3104         DPROV_DEBUG(D_DUAL, ("(%d) dprov_digest_encrypt_update: started\n",
3105             instance));
3106 
3107         if (digest_ctx->cc_provider != encrypt_ctx->cc_provider)
3108                 return (CRYPTO_INVALID_CONTEXT);
3109 
3110         /* submit request to the taskq */
3111         error = dprov_dual_submit_req(DPROV_REQ_DIGEST_ENCRYPT_UPDATE,
3112             softc, req, digest_ctx, encrypt_ctx, plaintext, ciphertext);
3113 
3114         DPROV_DEBUG(D_DUAL, ("(%d) dprov_digest_encrypt_update: done "
3115             "err = 0x%x\n", instance, error));
3116 
3117         return (error);
3118 }
3119 
3120 static int
3121 dprov_decrypt_digest_update(crypto_ctx_t *decrypt_ctx, crypto_ctx_t *digest_ctx,
3122     crypto_data_t *ciphertext, crypto_data_t *plaintext,
3123     crypto_req_handle_t req)
3124 {
3125         int error = CRYPTO_FAILED;
3126         dprov_state_t *softc;
3127         /* LINTED E_FUNC_SET_NOT_USED */
3128         int instance;
3129 
3130         /* extract softc and instance number from context */
3131         DPROV_SOFTC_FROM_CTX(decrypt_ctx, softc, instance);
3132         DPROV_DEBUG(D_DUAL, ("(%d) dprov_decrypt_digest_update: started\n",
3133             instance));
3134 
3135         if (decrypt_ctx->cc_provider != digest_ctx->cc_provider)
3136                 return (CRYPTO_INVALID_CONTEXT);
3137 
3138         /* submit request to the taskq */
3139         error = dprov_dual_submit_req(DPROV_REQ_DECRYPT_DIGEST_UPDATE,
3140             softc, req, digest_ctx, decrypt_ctx, plaintext, ciphertext);
3141 
3142         DPROV_DEBUG(D_DUAL, ("(%d) dprov_decrypt_digest_update: done "
3143             "err = 0x%x\n", instance, error));
3144 
3145         return (error);
3146 }
3147 
3148 static int
3149 dprov_sign_encrypt_update(crypto_ctx_t *sign_ctx, crypto_ctx_t *encrypt_ctx,
3150     crypto_data_t *plaintext, crypto_data_t *ciphertext,
3151     crypto_req_handle_t req)
3152 {
3153         int error = CRYPTO_FAILED;
3154         dprov_state_t *softc;
3155         /* LINTED E_FUNC_SET_NOT_USED */
3156         int instance;
3157 
3158         /* extract softc and instance number from context */
3159         DPROV_SOFTC_FROM_CTX(sign_ctx, softc, instance);
3160         DPROV_DEBUG(D_DUAL, ("(%d) dprov_sign_encrypt_update: started\n",
3161             instance));
3162 
3163         if (sign_ctx->cc_provider != encrypt_ctx->cc_provider)
3164                 return (CRYPTO_INVALID_CONTEXT);
3165 
3166         /* submit request to the taskq */
3167         error = dprov_dual_submit_req(DPROV_REQ_SIGN_ENCRYPT_UPDATE,
3168             softc, req, sign_ctx, encrypt_ctx, plaintext, ciphertext);
3169 
3170         DPROV_DEBUG(D_DUAL, ("(%d) dprov_sign_encrypt_update: done "
3171             "err = 0x%x\n", instance, error));
3172 
3173         return (error);
3174 }
3175 
3176 static int
3177 dprov_decrypt_verify_update(crypto_ctx_t *decrypt_ctx, crypto_ctx_t *verify_ctx,
3178     crypto_data_t *ciphertext, crypto_data_t *plaintext,
3179     crypto_req_handle_t req)
3180 {
3181         int error = CRYPTO_FAILED;
3182         dprov_state_t *softc;
3183         /* LINTED E_FUNC_SET_NOT_USED */
3184         int instance;
3185 
3186         /* extract softc and instance number from context */
3187         DPROV_SOFTC_FROM_CTX(decrypt_ctx, softc, instance);
3188         DPROV_DEBUG(D_DUAL, ("(%d) dprov_decrypt_verify_update: started\n",
3189             instance));
3190 
3191         if (decrypt_ctx->cc_provider != verify_ctx->cc_provider)
3192                 return (CRYPTO_INVALID_CONTEXT);
3193 
3194         /* submit request to the taskq */
3195         error = dprov_dual_submit_req(DPROV_REQ_DECRYPT_VERIFY_UPDATE,
3196             softc, req, verify_ctx, decrypt_ctx, plaintext, ciphertext);
3197 
3198         DPROV_DEBUG(D_DUAL, ("(%d) dprov_decrypt_verify_update: done "
3199             "err = 0x%x\n", instance, error));
3200 
3201         return (error);
3202 }
3203 
3204 /*
3205  * Dual cipher-mac entry points.
3206  */
3207 
3208 static int
3209 dprov_encrypt_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *encrypt_mech,
3210     crypto_key_t *encrypt_key, crypto_mechanism_t *mac_mech,
3211     crypto_key_t *mac_key, crypto_spi_ctx_template_t encr_ctx_template,
3212     crypto_spi_ctx_template_t mac_ctx_template,
3213     crypto_req_handle_t req)
3214 {
3215         int error = CRYPTO_FAILED;
3216         dprov_state_t *softc;
3217         /* LINTED E_FUNC_SET_NOT_USED */
3218         int instance;
3219 
3220         /* extract softc and instance number from context */
3221         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3222         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_init: started\n",
3223             instance));
3224 
3225         /* check mechanisms */
3226         if (!dprov_valid_cipher_mech(encrypt_mech->cm_type)) {
3227                 cmn_err(CE_WARN, "dprov_encrypt_mac_init: unexpected encrypt "
3228                     "mech type 0x%llx\n",
3229                     (unsigned long long)encrypt_mech->cm_type);
3230                 return (CRYPTO_MECHANISM_INVALID);
3231         }
3232         if (!dprov_valid_mac_mech(mac_mech->cm_type)) {
3233                 cmn_err(CE_WARN, "dprov_encrypt_mac_init: unexpected mac "
3234                     "mech type 0x%llx\n",
3235                     (unsigned long long)mac_mech->cm_type);
3236                 return (CRYPTO_MECHANISM_INVALID);
3237         }
3238 
3239         if (encr_ctx_template != NULL || mac_ctx_template != NULL)
3240                 return (CRYPTO_ARGUMENTS_BAD);
3241 
3242         /* submit request to the taskq */
3243         error = dprov_cipher_mac_submit_req(DPROV_REQ_ENCRYPT_MAC_INIT,
3244             softc, req, ctx, 0, encrypt_mech, encrypt_key, mac_mech, mac_key,
3245             NULL, NULL, NULL, KM_SLEEP);
3246 
3247         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_init: done "
3248             "err = 0x%x\n", instance, error));
3249 
3250         return (error);
3251 }
3252 
3253 static int
3254 dprov_encrypt_mac(crypto_ctx_t *ctx, crypto_data_t *plaintext,
3255     crypto_dual_data_t *ciphertext, crypto_data_t *mac, crypto_req_handle_t req)
3256 {
3257         int error = CRYPTO_FAILED;
3258         dprov_state_t *softc;
3259         /* LINTED E_FUNC_SET_NOT_USED */
3260         int instance;
3261 
3262         /* extract softc and instance number from context */
3263         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3264         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac: started\n",
3265             instance));
3266 
3267         /*
3268          * submit request to the taskq
3269          * Careful! cihertext/plaintext order inversion
3270          */
3271         error = dprov_cipher_mac_submit_req(DPROV_REQ_ENCRYPT_MAC,
3272             softc, req, ctx, 0, NULL, NULL, NULL, NULL,
3273             ciphertext, plaintext, mac, KM_NOSLEEP);
3274 
3275         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac: done "
3276             "err = 0x%x\n", instance, error));
3277 
3278         return (error);
3279 }
3280 
3281 static int
3282 dprov_encrypt_mac_update(crypto_ctx_t *ctx, crypto_data_t *plaintext,
3283     crypto_dual_data_t *ciphertext, crypto_req_handle_t req)
3284 {
3285         int error = CRYPTO_FAILED;
3286         dprov_state_t *softc;
3287         /* LINTED E_FUNC_SET_NOT_USED */
3288         int instance;
3289 
3290         /* extract softc and instance number from context */
3291         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3292         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_update: started\n",
3293             instance));
3294 
3295         /* submit request to the taskq */
3296         error = dprov_cipher_mac_submit_req(DPROV_REQ_ENCRYPT_MAC_UPDATE,
3297             softc, req, ctx, 0, NULL, NULL, NULL, NULL,
3298             ciphertext, plaintext, NULL, KM_NOSLEEP);
3299 
3300         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_update: done "
3301             "err = 0x%x\n", instance, error));
3302 
3303         return (error);
3304 }
3305 
3306 static int
3307 dprov_encrypt_mac_final(crypto_ctx_t *ctx,
3308     crypto_dual_data_t *ciphertext, crypto_data_t *mac,
3309     crypto_req_handle_t req)
3310 {
3311         int error = CRYPTO_FAILED;
3312         dprov_state_t *softc;
3313         /* LINTED E_FUNC_SET_NOT_USED */
3314         int instance;
3315 
3316         /* extract softc and instance number from context */
3317         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3318         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_final: started\n",
3319             instance));
3320 
3321         /* submit request to the taskq */
3322         error = dprov_cipher_mac_submit_req(DPROV_REQ_ENCRYPT_MAC_FINAL,
3323             softc, req, ctx, 0, NULL, NULL, NULL, NULL,
3324             ciphertext, NULL, mac, KM_NOSLEEP);
3325 
3326         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_final: done "
3327             "err = 0x%x\n", instance, error));
3328 
3329         return (error);
3330 }
3331 
3332 static int
3333 dprov_encrypt_mac_atomic(crypto_provider_handle_t provider,
3334     crypto_session_id_t session_id, crypto_mechanism_t *encrypt_mech,
3335     crypto_key_t *encrypt_key, crypto_mechanism_t *mac_mech,
3336     crypto_key_t *mac_key, crypto_data_t *plaintext,
3337     crypto_dual_data_t *ciphertext, crypto_data_t *mac,
3338     crypto_spi_ctx_template_t encr_ctx_template,
3339     crypto_spi_ctx_template_t mac_ctx_template,
3340     crypto_req_handle_t req)
3341 {
3342         int error = CRYPTO_FAILED;
3343         dprov_state_t *softc = (dprov_state_t *)provider;
3344         /* LINTED E_FUNC_SET_NOT_USED */
3345         int instance;
3346 
3347         instance = ddi_get_instance(softc->ds_dip);
3348         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_atomic: started\n",
3349             instance));
3350 
3351         /* check mechanisms */
3352         if (!dprov_valid_cipher_mech(encrypt_mech->cm_type)) {
3353                 cmn_err(CE_WARN, "dprov_encrypt_mac_atomic: unexpected encrypt "
3354                     "mech type 0x%llx\n",
3355                     (unsigned long long)encrypt_mech->cm_type);
3356                 return (CRYPTO_MECHANISM_INVALID);
3357         }
3358         if (!dprov_valid_mac_mech(mac_mech->cm_type)) {
3359                 cmn_err(CE_WARN, "dprov_encrypt_mac_atomic: unexpected mac "
3360                     "mech type 0x%llx\n",
3361                     (unsigned long long)mac_mech->cm_type);
3362                 return (CRYPTO_MECHANISM_INVALID);
3363         }
3364 
3365         if (encr_ctx_template != NULL || mac_ctx_template != NULL)
3366                 return (CRYPTO_ARGUMENTS_BAD);
3367 
3368         /* submit request to the taskq */
3369         error = dprov_cipher_mac_submit_req(DPROV_REQ_ENCRYPT_MAC_ATOMIC,
3370             softc, req, NULL, session_id, encrypt_mech, encrypt_key, mac_mech,
3371             mac_key, ciphertext, plaintext, mac, KM_SLEEP);
3372 
3373         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_encrypt_mac_atomic: done "
3374             "err = 0x%x\n", instance, error));
3375 
3376         return (error);
3377 }
3378 
3379 static int
3380 dprov_mac_decrypt_init(crypto_ctx_t *ctx, crypto_mechanism_t *mac_mech,
3381     crypto_key_t *mac_key, crypto_mechanism_t *decrypt_mech,
3382     crypto_key_t *decrypt_key, crypto_spi_ctx_template_t mac_ctx_template,
3383     crypto_spi_ctx_template_t decr_ctx_template,
3384     crypto_req_handle_t req)
3385 {
3386         int error = CRYPTO_FAILED;
3387         dprov_state_t *softc;
3388         /* LINTED E_FUNC_SET_NOT_USED */
3389         int instance;
3390 
3391         /* extract softc and instance number from context */
3392         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3393         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_init: started\n",
3394             instance));
3395 
3396         /* check mechanisms */
3397         if (!dprov_valid_cipher_mech(decrypt_mech->cm_type)) {
3398                 cmn_err(CE_WARN, "dprov_mac_decrypt_init: unexpected decrypt "
3399                     "mech type 0x%llx\n",
3400                     (unsigned long long)decrypt_mech->cm_type);
3401                 return (CRYPTO_MECHANISM_INVALID);
3402         }
3403         if (!dprov_valid_mac_mech(mac_mech->cm_type)) {
3404                 cmn_err(CE_WARN, "dprov_mac_decrypt_init: unexpected mac "
3405                     "mech type 0x%llx\n",
3406                     (unsigned long long)mac_mech->cm_type);
3407                 return (CRYPTO_MECHANISM_INVALID);
3408         }
3409 
3410         if (decr_ctx_template != NULL || mac_ctx_template != NULL)
3411                 return (CRYPTO_ARGUMENTS_BAD);
3412 
3413         /* submit request to the taskq */
3414         error = dprov_cipher_mac_submit_req(DPROV_REQ_MAC_DECRYPT_INIT,
3415             softc, req, ctx, 0, decrypt_mech, decrypt_key, mac_mech, mac_key,
3416             NULL, NULL, NULL, KM_SLEEP);
3417 
3418         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_init: done "
3419             "err = 0x%x\n", instance, error));
3420 
3421         return (error);
3422 }
3423 
3424 static int
3425 dprov_mac_decrypt(crypto_ctx_t *ctx, crypto_dual_data_t *ciphertext,
3426     crypto_data_t *mac, crypto_data_t *plaintext, crypto_req_handle_t req)
3427 {
3428         int error = CRYPTO_FAILED;
3429         dprov_state_t *softc;
3430         /* LINTED E_FUNC_SET_NOT_USED */
3431         int instance;
3432 
3433         /* extract softc and instance number from context */
3434         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3435         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt: started\n",
3436             instance));
3437 
3438         /* submit request to the taskq */
3439         error = dprov_cipher_mac_submit_req(DPROV_REQ_MAC_DECRYPT,
3440             softc, req, ctx, 0, NULL, NULL, NULL, NULL,
3441             ciphertext, plaintext, mac, KM_NOSLEEP);
3442 
3443         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt: done "
3444             "err = 0x%x\n", instance, error));
3445 
3446         return (error);
3447 }
3448 
3449 static int
3450 dprov_mac_decrypt_update(crypto_ctx_t *ctx, crypto_dual_data_t *ciphertext,
3451     crypto_data_t *plaintext, crypto_req_handle_t req)
3452 {
3453         int error = CRYPTO_FAILED;
3454         dprov_state_t *softc;
3455         /* LINTED E_FUNC_SET_NOT_USED */
3456         int instance;
3457 
3458         /* extract softc and instance number from context */
3459         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3460         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_update: started\n",
3461             instance));
3462 
3463         /* submit request to the taskq */
3464         error = dprov_cipher_mac_submit_req(DPROV_REQ_MAC_DECRYPT_UPDATE,
3465             softc, req, ctx, 0, NULL, NULL, NULL, NULL,
3466             ciphertext, plaintext, NULL, KM_NOSLEEP);
3467 
3468         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_update: done "
3469             "err = 0x%x\n", instance, error));
3470 
3471         return (error);
3472 }
3473 
3474 static int
3475 dprov_mac_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *mac,
3476     crypto_data_t *plaintext, crypto_req_handle_t req)
3477 {
3478         int error = CRYPTO_FAILED;
3479         dprov_state_t *softc;
3480         /* LINTED E_FUNC_SET_NOT_USED */
3481         int instance;
3482 
3483         /* extract softc and instance number from context */
3484         DPROV_SOFTC_FROM_CTX(ctx, softc, instance);
3485         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_final: started\n",
3486             instance));
3487 
3488         /* submit request to the taskq */
3489         error = dprov_cipher_mac_submit_req(DPROV_REQ_MAC_DECRYPT_FINAL,
3490             softc, req, ctx, 0, NULL, NULL, NULL, NULL,
3491             NULL, plaintext, mac, KM_NOSLEEP);
3492 
3493         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_final: done "
3494             "err = 0x%x\n", instance, error));
3495 
3496         return (error);
3497 }
3498 
3499 static int
3500 dprov_mac_decrypt_atomic(crypto_provider_handle_t provider,
3501     crypto_session_id_t session_id, crypto_mechanism_t *mac_mech,
3502     crypto_key_t *mac_key, crypto_mechanism_t *decrypt_mech,
3503     crypto_key_t *decrypt_key, crypto_dual_data_t *ciphertext,
3504     crypto_data_t *mac, crypto_data_t *plaintext,
3505     crypto_spi_ctx_template_t mac_ctx_template,
3506     crypto_spi_ctx_template_t decr_ctx_template,
3507     crypto_req_handle_t req)
3508 {
3509         int error = CRYPTO_FAILED;
3510         dprov_state_t *softc = (dprov_state_t *)provider;
3511         /* LINTED E_FUNC_SET_NOT_USED */
3512         int instance;
3513 
3514         instance = ddi_get_instance(softc->ds_dip);
3515         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_atomic: started\n",
3516             instance));
3517 
3518         /* check mechanisms */
3519         if (!dprov_valid_cipher_mech(decrypt_mech->cm_type)) {
3520                 cmn_err(CE_WARN, "dprov_mac_decrypt_atomic: unexpected encrypt "
3521                     "mech type 0x%llx\n",
3522                     (unsigned long long)decrypt_mech->cm_type);
3523                 return (CRYPTO_MECHANISM_INVALID);
3524         }
3525         if (!dprov_valid_mac_mech(mac_mech->cm_type)) {
3526                 cmn_err(CE_WARN, "dprov_mac_decrypt_atomic: unexpected mac "
3527                     "mech type 0x%llx\n",
3528                     (unsigned long long)mac_mech->cm_type);
3529                 return (CRYPTO_MECHANISM_INVALID);
3530         }
3531 
3532         if (decr_ctx_template != NULL || mac_ctx_template != NULL)
3533                 return (CRYPTO_ARGUMENTS_BAD);
3534 
3535         /* submit request to the taskq */
3536         error = dprov_cipher_mac_submit_req(DPROV_REQ_MAC_DECRYPT_ATOMIC,
3537             softc, req, NULL, session_id, decrypt_mech, decrypt_key, mac_mech,
3538             mac_key, ciphertext, plaintext, mac, KM_SLEEP);
3539 
3540         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_decrypt_atomic: done "
3541             "err = 0x%x\n", instance, error));
3542 
3543         return (error);
3544 }
3545 
3546 static int
3547 dprov_mac_verify_decrypt_atomic(crypto_provider_handle_t provider,
3548     crypto_session_id_t session_id, crypto_mechanism_t *mac_mech,
3549     crypto_key_t *mac_key, crypto_mechanism_t *decrypt_mech,
3550     crypto_key_t *decrypt_key, crypto_dual_data_t *ciphertext,
3551     crypto_data_t *mac, crypto_data_t *plaintext,
3552     crypto_spi_ctx_template_t mac_ctx_template,
3553     crypto_spi_ctx_template_t decr_ctx_template,
3554     crypto_req_handle_t req)
3555 {
3556         int error = CRYPTO_FAILED;
3557         dprov_state_t *softc = (dprov_state_t *)provider;
3558         /* LINTED E_FUNC_SET_NOT_USED */
3559         int instance;
3560 
3561         instance = ddi_get_instance(softc->ds_dip);
3562         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_verify_decrypt_atomic:"
3563             "started\n", instance));
3564 
3565         /* check mechanisms */
3566         if (!dprov_valid_cipher_mech(decrypt_mech->cm_type)) {
3567                 cmn_err(CE_WARN, "dprov_mac_verify_decrypt_atomic: "
3568                     "unexpected encrypt mech type 0x%llx\n",
3569                     (unsigned long long)decrypt_mech->cm_type);
3570                 return (CRYPTO_MECHANISM_INVALID);
3571         }
3572         if (!dprov_valid_mac_mech(mac_mech->cm_type)) {
3573                 cmn_err(CE_WARN, "dprov_mac_verify_decrypt_atomic: "
3574                     "unexpected mac mech type 0x%llx\n",
3575                     (unsigned long long)mac_mech->cm_type);
3576                 return (CRYPTO_MECHANISM_INVALID);
3577         }
3578 
3579         if (decr_ctx_template != NULL || mac_ctx_template != NULL)
3580                 return (CRYPTO_ARGUMENTS_BAD);
3581 
3582         /* submit request to the taskq */
3583         error = dprov_cipher_mac_submit_req(DPROV_REQ_MAC_VERIFY_DECRYPT_ATOMIC,
3584             softc, req, NULL, session_id, decrypt_mech, decrypt_key, mac_mech,
3585             mac_key, ciphertext, plaintext, mac, KM_SLEEP);
3586 
3587         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_mac_verify_decrypt_atomic: done "
3588             "err = 0x%x\n", instance, error));
3589 
3590         return (error);
3591 }
3592 
3593 /*
3594  * Random number entry points.
3595  */
3596 
3597 static int
3598 dprov_seed_random(crypto_provider_handle_t provider,  crypto_session_id_t sid,
3599     uchar_t *buf, size_t len, uint_t entropy_est, uint32_t flags,
3600     crypto_req_handle_t req)
3601 {
3602         int error = CRYPTO_FAILED;
3603         dprov_state_t *softc = (dprov_state_t *)provider;
3604         /* LINTED E_FUNC_SET_NOT_USED */
3605         int instance;
3606 
3607         instance = ddi_get_instance(softc->ds_dip);
3608         DPROV_DEBUG(D_RANDOM, ("(%d) dprov_seed_random: started\n",
3609             instance));
3610 
3611         error = dprov_random_submit_req(DPROV_REQ_RANDOM_SEED, softc,
3612             req, buf, len, sid, entropy_est, flags);
3613 
3614         DPROV_DEBUG(D_RANDOM, ("(%d) dprov_seed_random: done err = 0x0%x\n",
3615             instance, error));
3616 
3617         return (error);
3618 }
3619 
3620 static int
3621 dprov_generate_random(crypto_provider_handle_t provider,
3622     crypto_session_id_t sid, uchar_t *buf, size_t len, crypto_req_handle_t req)
3623 {
3624         int error = CRYPTO_FAILED;
3625         dprov_state_t *softc = (dprov_state_t *)provider;
3626         /* LINTED E_FUNC_SET_NOT_USED */
3627         int instance;
3628 
3629         instance = ddi_get_instance(softc->ds_dip);
3630         DPROV_DEBUG(D_RANDOM, ("(%d) dprov_generate_random: started\n",
3631             instance));
3632 
3633         error = dprov_random_submit_req(DPROV_REQ_RANDOM_GENERATE, softc,
3634             req, buf, len, sid, 0, 0);
3635 
3636         DPROV_DEBUG(D_RANDOM, ("(%d) dprov_generate_random: done "
3637             "err = 0x0%x\n", instance, error));
3638 
3639         return (error);
3640 }
3641 
3642 /*
3643  * Session Management entry points.
3644  */
3645 
3646 static int
3647 dprov_session_open(crypto_provider_handle_t provider,
3648     crypto_session_id_t *session_id, crypto_req_handle_t req)
3649 {
3650         int error = CRYPTO_FAILED;
3651         dprov_state_t *softc = (dprov_state_t *)provider;
3652         /* LINTED E_FUNC_SET_NOT_USED */
3653         int instance;
3654 
3655         instance = ddi_get_instance(softc->ds_dip);
3656         DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_open: started\n",
3657             instance));
3658 
3659         error = dprov_session_submit_req(DPROV_REQ_SESSION_OPEN, softc,
3660             req, session_id, 0, 0, NULL, 0);
3661 
3662         DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_open: done err = 0x0%x\n",
3663             instance, error));
3664 
3665         return (error);
3666 }
3667 
3668 static int
3669 dprov_session_close(crypto_provider_handle_t provider,
3670     crypto_session_id_t session_id, crypto_req_handle_t req)
3671 {
3672         int error = CRYPTO_FAILED;
3673         dprov_state_t *softc = (dprov_state_t *)provider;
3674         /* LINTED E_FUNC_SET_NOT_USED */
3675         int instance;
3676 
3677         instance = ddi_get_instance(softc->ds_dip);
3678         DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_close: started\n",
3679             instance));
3680 
3681         error = dprov_session_submit_req(DPROV_REQ_SESSION_CLOSE, softc,
3682             req, 0, session_id, 0, NULL, 0);
3683 
3684         DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_close: done err = 0x0%x\n",
3685             instance, error));
3686 
3687         return (error);
3688 }
3689 
3690 static int
3691 dprov_session_login(crypto_provider_handle_t provider,
3692     crypto_session_id_t session_id, crypto_user_type_t user_type,
3693     char *pin, size_t pin_len, crypto_req_handle_t req)
3694 {
3695         int error = CRYPTO_FAILED;
3696         dprov_state_t *softc = (dprov_state_t *)provider;
3697         /* LINTED E_FUNC_SET_NOT_USED */
3698         int instance;
3699 
3700         instance = ddi_get_instance(softc->ds_dip);
3701         DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_login: started\n",
3702             instance));
3703 
3704         error = dprov_session_submit_req(DPROV_REQ_SESSION_LOGIN, softc,
3705             req, 0, session_id, user_type, pin, pin_len);
3706 
3707         DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_login: done err = 0x0%x\n",
3708             instance, error));
3709 
3710         return (error);
3711 }
3712 
3713 static int
3714 dprov_session_logout(crypto_provider_handle_t provider,
3715     crypto_session_id_t session_id, crypto_req_handle_t req)
3716 {
3717         int error = CRYPTO_FAILED;
3718         dprov_state_t *softc = (dprov_state_t *)provider;
3719         /* LINTED E_FUNC_SET_NOT_USED */
3720         int instance;
3721 
3722         instance = ddi_get_instance(softc->ds_dip);
3723         DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_logout: started\n",
3724             instance));
3725 
3726         error = dprov_session_submit_req(DPROV_REQ_SESSION_LOGOUT, softc,
3727             req, 0, session_id, 0, NULL, 0);
3728 
3729         DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_logout: done err = 0x0%x\n",
3730             instance, error));
3731 
3732         return (error);
3733 }
3734 
3735 /*
3736  * Object management entry points.
3737  */
3738 
3739 static int
3740 dprov_object_create(crypto_provider_handle_t provider,
3741     crypto_session_id_t session_id, crypto_object_attribute_t *template,
3742     uint_t attribute_count, crypto_object_id_t *object,
3743     crypto_req_handle_t req)
3744 {
3745         int error = CRYPTO_FAILED;
3746         dprov_state_t *softc = (dprov_state_t *)provider;
3747         /* LINTED E_FUNC_SET_NOT_USED */
3748         int instance;
3749 
3750         instance = ddi_get_instance(softc->ds_dip);
3751         DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_create: started\n",
3752             instance));
3753 
3754         /* submit request to the taskq */
3755         error = dprov_object_submit_req(DPROV_REQ_OBJECT_CREATE, softc, req,
3756             session_id, 0, template, attribute_count, object, NULL, NULL,
3757             NULL, 0, NULL, KM_NOSLEEP);
3758 
3759         DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_create: done err = 0x0%x\n",
3760             instance, error));
3761 
3762         return (error);
3763 }
3764 
3765 static int
3766 dprov_object_copy(crypto_provider_handle_t provider,
3767     crypto_session_id_t session_id, crypto_object_id_t object,
3768     crypto_object_attribute_t *template, uint_t attribute_count,
3769     crypto_object_id_t *new_object, crypto_req_handle_t req)
3770 {
3771         int error = CRYPTO_FAILED;
3772         dprov_state_t *softc = (dprov_state_t *)provider;
3773         /* LINTED E_FUNC_SET_NOT_USED */
3774         int instance;
3775 
3776         instance = ddi_get_instance(softc->ds_dip);
3777         DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_copy: started\n",
3778             instance));
3779 
3780         /* submit request to the taskq */
3781         error = dprov_object_submit_req(DPROV_REQ_OBJECT_COPY, softc, req,
3782             session_id, object, template, attribute_count, new_object,
3783             NULL, NULL, NULL, 0, NULL, KM_NOSLEEP);
3784 
3785         DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_copy: done err = 0x0%x\n",
3786             instance, error));
3787 
3788         return (error);
3789 }
3790 
3791 static int
3792 dprov_object_destroy(crypto_provider_handle_t provider,
3793     crypto_session_id_t session_id, crypto_object_id_t object,
3794     crypto_req_handle_t req)
3795 {
3796         int error = CRYPTO_FAILED;
3797         dprov_state_t *softc = (dprov_state_t *)provider;
3798         /* LINTED E_FUNC_SET_NOT_USED */
3799         int instance;
3800 
3801         instance = ddi_get_instance(softc->ds_dip);
3802         DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_destroy: started\n",
3803             instance));
3804 
3805         /* submit request to the taskq */
3806         error = dprov_object_submit_req(DPROV_REQ_OBJECT_DESTROY, softc, req,
3807             session_id, object, NULL, 0, NULL, NULL, NULL, NULL, 0, NULL,
3808             KM_NOSLEEP);
3809 
3810         DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_destroy: done err = 0x0%x\n",
3811             instance, error));
3812 
3813         return (error);
3814 }
3815 
3816 static int
3817 dprov_object_get_size(crypto_provider_handle_t provider,
3818     crypto_session_id_t session_id, crypto_object_id_t object,
3819     size_t *size, crypto_req_handle_t req)
3820 {
3821         int error = CRYPTO_FAILED;
3822         dprov_state_t *softc = (dprov_state_t *)provider;
3823         /* LINTED E_FUNC_SET_NOT_USED */
3824         int instance;
3825 
3826         instance = ddi_get_instance(softc->ds_dip);
3827         DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_get_size: started\n",
3828             instance));
3829 
3830         /* submit request to the taskq */
3831         error = dprov_object_submit_req(DPROV_REQ_OBJECT_GET_SIZE, softc, req,
3832             session_id, object, NULL, 0, NULL, size, NULL, NULL, 0, NULL,
3833             KM_NOSLEEP);
3834 
3835         DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_get_size: done err = 0x0%x\n",
3836             instance, error));
3837 
3838         return (error);
3839 }
3840 
3841 static int
3842 dprov_object_get_attribute_value(crypto_provider_handle_t provider,
3843     crypto_session_id_t session_id, crypto_object_id_t object,
3844     crypto_object_attribute_t *template, uint_t attribute_count,
3845     crypto_req_handle_t req)
3846 {
3847         int error = CRYPTO_FAILED;
3848         dprov_state_t *softc = (dprov_state_t *)provider;
3849         /* LINTED E_FUNC_SET_NOT_USED */
3850         int instance;
3851 
3852         instance = ddi_get_instance(softc->ds_dip);
3853         DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_get_attribute_value: "
3854             "started\n", instance));
3855 
3856         /* submit request to the taskq */
3857         error = dprov_object_submit_req(DPROV_REQ_OBJECT_GET_ATTRIBUTE_VALUE,
3858             softc, req, session_id, object, template, attribute_count,
3859             NULL, NULL, NULL, NULL, 0, NULL, KM_NOSLEEP);
3860 
3861         DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_get_attribute_value: "
3862             "done err = 0x0%x\n", instance, error));
3863 
3864         return (error);
3865 }
3866 
3867 static int
3868 dprov_object_set_attribute_value(crypto_provider_handle_t provider,
3869     crypto_session_id_t session_id, crypto_object_id_t object,
3870     crypto_object_attribute_t *template, uint_t attribute_count,
3871     crypto_req_handle_t req)
3872 {
3873         int error = CRYPTO_FAILED;
3874         dprov_state_t *softc = (dprov_state_t *)provider;
3875         /* LINTED E_FUNC_SET_NOT_USED */
3876         int instance;
3877 
3878         instance = ddi_get_instance(softc->ds_dip);
3879         DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_set_attribute_value: "
3880             "started\n", instance));
3881 
3882         /* submit request to the taskq */
3883         error = dprov_object_submit_req(DPROV_REQ_OBJECT_SET_ATTRIBUTE_VALUE,
3884             softc, req, session_id, object, template, attribute_count,
3885             NULL, NULL, NULL, NULL, 0, NULL, KM_NOSLEEP);
3886 
3887         DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_set_attribute_value: "
3888             "done err = 0x0%x\n", instance, error));
3889 
3890         return (error);
3891 }
3892 
3893 static int
3894 dprov_object_find_init(crypto_provider_handle_t provider,
3895     crypto_session_id_t session_id, crypto_object_attribute_t *template,
3896     uint_t attribute_count, void **provider_private,
3897     crypto_req_handle_t req)
3898 {
3899         int error = CRYPTO_FAILED;
3900         dprov_state_t *softc = (dprov_state_t *)provider;
3901         /* LINTED E_FUNC_SET_NOT_USED */
3902         int instance;
3903 
3904         instance = ddi_get_instance(softc->ds_dip);
3905         DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_find_init: started\n",
3906             instance));
3907 
3908         /* submit request to the taskq */
3909         error = dprov_object_submit_req(DPROV_REQ_OBJECT_FIND_INIT, softc, req,
3910             session_id, 0, template, attribute_count, NULL, NULL,
3911             provider_private, NULL, 0, NULL, KM_SLEEP);
3912 
3913         DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_find_init: done "
3914             "err = 0x0%x\n", instance, error));
3915 
3916         return (error);
3917 }
3918 
3919 static int
3920 dprov_object_find(crypto_provider_handle_t provider, void *provider_private,
3921     crypto_object_id_t *objects, uint_t max_object_count,
3922     uint_t *object_count, crypto_req_handle_t req)
3923 {
3924         int error = CRYPTO_FAILED;
3925         dprov_state_t *softc = (dprov_state_t *)provider;
3926         /* LINTED E_FUNC_SET_NOT_USED */
3927         int instance;
3928 
3929         instance = ddi_get_instance(softc->ds_dip);
3930         DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_find: started\n",
3931             instance));
3932 
3933         /* submit request to the taskq */
3934         error = dprov_object_submit_req(DPROV_REQ_OBJECT_FIND, softc, req,
3935             0, 0, NULL, 0, objects, NULL, NULL, provider_private,
3936             max_object_count, object_count, KM_NOSLEEP);
3937 
3938 
3939         DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_find: done err = 0x0%x\n",
3940             instance, error));
3941 
3942         return (error);
3943 }
3944 
3945 static int
3946 dprov_object_find_final(crypto_provider_handle_t provider,
3947     void *provider_private, crypto_req_handle_t req)
3948 {
3949         int error = CRYPTO_FAILED;
3950         dprov_state_t *softc = (dprov_state_t *)provider;
3951         /* LINTED E_FUNC_SET_NOT_USED */
3952         int instance;
3953 
3954         instance = ddi_get_instance(softc->ds_dip);
3955         DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_find_final: started\n",
3956             instance));
3957 
3958         /* submit request to the taskq */
3959         error = dprov_object_submit_req(DPROV_REQ_OBJECT_FIND_FINAL, softc, req,
3960             0, 0, NULL, 0, NULL, NULL, NULL, provider_private,
3961             0, NULL, KM_NOSLEEP);
3962 
3963         DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_find_final: done "
3964             "err = 0x0%x\n", instance, error));
3965 
3966         return (error);
3967 }
3968 
3969 /*
3970  * Key management entry points.
3971  */
3972 
3973 static int
3974 dprov_key_generate(crypto_provider_handle_t provider,
3975     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
3976     crypto_object_attribute_t *template, uint_t attribute_count,
3977     crypto_object_id_t *object, crypto_req_handle_t req)
3978 {
3979         int error = CRYPTO_FAILED;
3980         dprov_state_t *softc = (dprov_state_t *)provider;
3981         /* LINTED E_FUNC_SET_NOT_USED */
3982         int instance;
3983 
3984         instance = ddi_get_instance(softc->ds_dip);
3985         DPROV_DEBUG(D_KEY, ("(%d) dprov_key_generate: started\n",
3986             instance));
3987 
3988         /* submit request to the taskq */
3989         error = dprov_key_submit_req(DPROV_REQ_KEY_GENERATE, softc, req,
3990             session_id, mechanism, template, attribute_count, object, NULL,
3991             0, NULL, NULL, NULL, 0, NULL, 0, NULL, 0);
3992 
3993         DPROV_DEBUG(D_KEY, ("(%d) dprov_key_generate: done err = 0x0%x\n",
3994             instance, error));
3995 
3996         return (error);
3997 }
3998 
3999 static int
4000 dprov_key_generate_pair(crypto_provider_handle_t provider,
4001     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
4002     crypto_object_attribute_t *public_key_template,
4003     uint_t public_key_attribute_count,
4004     crypto_object_attribute_t *private_key_template,
4005     uint_t private_key_attribute_count,
4006     crypto_object_id_t *public_key, crypto_object_id_t *private_key,
4007     crypto_req_handle_t req)
4008 {
4009         int error = CRYPTO_FAILED;
4010         dprov_state_t *softc = (dprov_state_t *)provider;
4011         /* LINTED E_FUNC_SET_NOT_USED */
4012         int instance;
4013 
4014         instance = ddi_get_instance(softc->ds_dip);
4015         DPROV_DEBUG(D_KEY, ("(%d) dprov_key_generate_pair: started\n",
4016             instance));
4017 
4018         /* submit request to the taskq */
4019         error = dprov_key_submit_req(DPROV_REQ_KEY_GENERATE_PAIR, softc, req,
4020             session_id, mechanism, public_key_template,
4021             public_key_attribute_count, public_key, private_key_template,
4022             private_key_attribute_count, private_key, NULL, NULL, 0, NULL, 0,
4023             NULL, 0);
4024 
4025         DPROV_DEBUG(D_KEY, ("(%d) dprov_key_generate_pair: done err = 0x0%x\n",
4026             instance, error));
4027 
4028         return (error);
4029 }
4030 
4031 static int
4032 dprov_key_wrap(crypto_provider_handle_t provider,
4033     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
4034     crypto_key_t *wrapping_key, crypto_object_id_t *key,
4035     uchar_t *wrapped_key, size_t *wrapped_key_len_ptr, crypto_req_handle_t req)
4036 {
4037         int error = CRYPTO_FAILED;
4038         dprov_state_t *softc = (dprov_state_t *)provider;
4039         /* LINTED E_FUNC_SET_NOT_USED */
4040         int instance;
4041 
4042         instance = ddi_get_instance(softc->ds_dip);
4043         DPROV_DEBUG(D_KEY, ("(%d) dprov_key_wrap: started\n",
4044             instance));
4045 
4046         /* submit request to the taskq */
4047         error = dprov_key_submit_req(DPROV_REQ_KEY_WRAP, softc, req,
4048             session_id, mechanism, NULL, 0, key, NULL,
4049             0, NULL, wrapping_key, wrapped_key, wrapped_key_len_ptr,
4050             NULL, 0, NULL, 0);
4051 
4052         DPROV_DEBUG(D_KEY, ("(%d) dprov_key_wrap: done err = 0x0%x\n",
4053             instance, error));
4054 
4055         return (error);
4056 }
4057 
4058 static int
4059 dprov_key_unwrap(crypto_provider_handle_t provider,
4060     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
4061     crypto_key_t *unwrapping_key, uchar_t *wrapped_key,
4062     size_t *wrapped_key_len_ptr, crypto_object_attribute_t *template,
4063     uint_t attribute_count, crypto_object_id_t *key, crypto_req_handle_t req)
4064 {
4065         int error = CRYPTO_FAILED;
4066         dprov_state_t *softc = (dprov_state_t *)provider;
4067         /* LINTED E_FUNC_SET_NOT_USED */
4068         int instance;
4069 
4070         instance = ddi_get_instance(softc->ds_dip);
4071         DPROV_DEBUG(D_KEY, ("(%d) dprov_key_unwrap: started\n",
4072             instance));
4073 
4074         /* submit request to the taskq */
4075         error = dprov_key_submit_req(DPROV_REQ_KEY_UNWRAP, softc, req,
4076             session_id, mechanism, template, attribute_count, key, NULL,
4077             0, NULL, unwrapping_key, wrapped_key, wrapped_key_len_ptr,
4078             NULL, 0, NULL, 0);
4079 
4080         DPROV_DEBUG(D_KEY, ("(%d) dprov_key_unwrap: done err = 0x0%x\n",
4081             instance, error));
4082 
4083         return (error);
4084 }
4085 
4086 static int
4087 dprov_key_derive(crypto_provider_handle_t provider,
4088     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
4089     crypto_key_t *base_key, crypto_object_attribute_t *template,
4090     uint_t attribute_count, crypto_object_id_t *key, crypto_req_handle_t req)
4091 {
4092         int error = CRYPTO_FAILED;
4093         dprov_state_t *softc = (dprov_state_t *)provider;
4094         /* LINTED E_FUNC_SET_NOT_USED */
4095         int instance;
4096 
4097         instance = ddi_get_instance(softc->ds_dip);
4098         DPROV_DEBUG(D_KEY, ("(%d) dprov_key_derive: started\n",
4099             instance));
4100 
4101         /* submit request to the taskq */
4102         error = dprov_key_submit_req(DPROV_REQ_KEY_DERIVE, softc, req,
4103             session_id, mechanism, template, attribute_count, key, NULL,
4104             0, NULL, base_key, NULL, 0, NULL, 0, NULL, 0);
4105 
4106         DPROV_DEBUG(D_KEY, ("(%d) dprov_key_derive: done err = 0x0%x\n",
4107             instance, error));
4108 
4109         return (error);
4110 }
4111 
4112 /*
4113  * Provider management entry points.
4114  */
4115 
4116 static int
4117 dprov_ext_info(crypto_provider_handle_t provider,
4118     crypto_provider_ext_info_t *ext_info, crypto_req_handle_t req)
4119 {
4120         int error = CRYPTO_FAILED;
4121         dprov_state_t *softc = (dprov_state_t *)provider;
4122         /* LINTED E_FUNC_SET_NOT_USED */
4123         int instance;
4124 
4125         instance = ddi_get_instance(softc->ds_dip);
4126         DPROV_DEBUG(D_MGMT, ("(%d) dprov_ext_info: started\n",
4127             instance));
4128 
4129         error = dprov_mgmt_submit_req(DPROV_REQ_MGMT_EXTINFO, softc, req,
4130             0, NULL, 0, NULL, 0, NULL, ext_info);
4131 
4132         DPROV_DEBUG(D_MGMT, ("(%d) dprov_ext_info: done err = 0x0%x\n",
4133             instance, error));
4134 
4135         return (error);
4136 }
4137 
4138 static int
4139 dprov_init_token(crypto_provider_handle_t provider, char *pin, size_t pin_len,
4140     char *label, crypto_req_handle_t req)
4141 {
4142         int error = CRYPTO_FAILED;
4143         dprov_state_t *softc = (dprov_state_t *)provider;
4144         /* LINTED E_FUNC_SET_NOT_USED */
4145         int instance;
4146 
4147         instance = ddi_get_instance(softc->ds_dip);
4148         DPROV_DEBUG(D_MGMT, ("(%d) dprov_init_token: started\n",
4149             instance));
4150 
4151         error = dprov_mgmt_submit_req(DPROV_REQ_MGMT_INITTOKEN, softc, req,
4152             0, pin, pin_len, NULL, 0, label, NULL);
4153 
4154         DPROV_DEBUG(D_MGMT, ("(%d) dprov_init_token: done err = 0x0%x\n",
4155             instance, error));
4156 
4157         return (error);
4158 }
4159 
4160 static int
4161 dprov_init_pin(crypto_provider_handle_t provider,
4162     crypto_session_id_t session_id, char *pin, size_t pin_len,
4163     crypto_req_handle_t req)
4164 {
4165         int error = CRYPTO_FAILED;
4166         dprov_state_t *softc = (dprov_state_t *)provider;
4167         /* LINTED E_FUNC_SET_NOT_USED */
4168         int instance;
4169 
4170         instance = ddi_get_instance(softc->ds_dip);
4171         DPROV_DEBUG(D_MGMT, ("(%d) dprov_init_pin: started\n",
4172             instance));
4173 
4174         error = dprov_mgmt_submit_req(DPROV_REQ_MGMT_INITPIN, softc, req,
4175             session_id, pin, pin_len, NULL, 0, NULL, NULL);
4176 
4177         DPROV_DEBUG(D_MGMT, ("(%d) dprov_init_pin: done err = 0x0%x\n",
4178             instance, error));
4179 
4180         return (error);
4181 }
4182 
4183 static int
4184 dprov_set_pin(crypto_provider_handle_t provider, crypto_session_id_t session_id,
4185     char *old_pin, size_t old_pin_len, char *new_pin, size_t new_pin_len,
4186     crypto_req_handle_t req)
4187 {
4188         int error = CRYPTO_FAILED;
4189         dprov_state_t *softc = (dprov_state_t *)provider;
4190         /* LINTED E_FUNC_SET_NOT_USED */
4191         int instance;
4192 
4193         instance = ddi_get_instance(softc->ds_dip);
4194         DPROV_DEBUG(D_MGMT, ("(%d) dprov_set_pin: started\n",
4195             instance));
4196 
4197         error = dprov_mgmt_submit_req(DPROV_REQ_MGMT_SETPIN, softc, req,
4198             session_id, new_pin, new_pin_len, old_pin, old_pin_len, NULL, NULL);
4199 
4200         DPROV_DEBUG(D_MGMT, ("(%d) dprov_set_pin: done err = 0x0%x\n",
4201             instance, error));
4202 
4203         return (error);
4204 }
4205 
4206 
4207 /*
4208  * Context management entry points.
4209  */
4210 
4211 /*
4212  * Allocate a dprov-private context based on the specified dprov request.
4213  * For dual cipher/mac requests, the allocated context will
4214  * contain a structure dprov_ctx_dual_t, for other request types,
4215  * it will contain a dprov_ctx_single.
4216  * Returns one of the CRYPTO_ status codes.
4217  */
4218 static int
4219 dprov_alloc_context(dprov_req_type_t req_type, crypto_ctx_t *spi_ctx)
4220 {
4221         dprov_ctx_single_t *dprov_private;
4222 
4223         switch (req_type) {
4224         case DPROV_REQ_ENCRYPT_MAC_INIT:
4225         case DPROV_REQ_MAC_DECRYPT_INIT:
4226                 dprov_private = kmem_zalloc(sizeof (dprov_ctx_dual_t),
4227                     KM_NOSLEEP);
4228                 if (dprov_private == NULL)
4229                         return (CRYPTO_HOST_MEMORY);
4230                 dprov_private->dc_type = DPROV_CTX_DUAL;
4231                 break;
4232         default:
4233                 dprov_private = kmem_zalloc(sizeof (dprov_ctx_single_t),
4234                     KM_NOSLEEP);
4235                 if (dprov_private == NULL)
4236                         return (CRYPTO_HOST_MEMORY);
4237                 dprov_private->dc_type = DPROV_CTX_SINGLE;
4238                 dprov_private->dc_svrfy_to_mac = B_FALSE;
4239                 break;
4240         }
4241 
4242         spi_ctx->cc_provider_private = (void *)dprov_private;
4243 
4244         return (CRYPTO_SUCCESS);
4245 }
4246 
4247 static int
4248 dprov_free_context(crypto_ctx_t *ctx)
4249 {
4250         if (ctx->cc_provider_private == NULL)
4251                 return (CRYPTO_SUCCESS);
4252 
4253         DPROV_DEBUG(D_CONTEXT, ("dprov_free_context\n"));
4254 
4255         {
4256                 /*
4257                  * The dprov private context could contain either
4258                  * a dprov_ctx_single_t or a dprov_ctx_dual_t. Free
4259                  * the context based on its type. The k-API contexts
4260                  * that were attached to the dprov private context
4261                  * are freed by the framework.
4262                  */
4263                 dprov_ctx_single_t *ctx_single =
4264                     (dprov_ctx_single_t *)(ctx->cc_provider_private);
4265 
4266                 if (ctx_single->dc_type == DPROV_CTX_SINGLE) {
4267                         crypto_context_t context = DPROV_CTX_SINGLE(ctx);
4268 
4269                         /*
4270                          * This case happens for the crypto_cancel_ctx() case.
4271                          * We have to cancel the SW provider context also.
4272                          */
4273                         if (context != NULL)
4274                                 crypto_cancel_ctx(context);
4275 
4276                         kmem_free(ctx_single, sizeof (dprov_ctx_single_t));
4277                 } else {
4278                         crypto_context_t cipher_context =
4279                             DPROV_CTX_DUAL_CIPHER(ctx);
4280                         crypto_context_t mac_context = DPROV_CTX_DUAL_MAC(ctx);
4281 
4282                         /* See comments above. */
4283                         if (cipher_context != NULL)
4284                                 crypto_cancel_ctx(cipher_context);
4285                         if (mac_context != NULL)
4286                                 crypto_cancel_ctx(mac_context);
4287 
4288                         ASSERT(ctx_single->dc_type == DPROV_CTX_DUAL);
4289                         kmem_free(ctx_single, sizeof (dprov_ctx_dual_t));
4290                 }
4291                 ctx->cc_provider_private = NULL;
4292         }
4293 
4294         return (CRYPTO_SUCCESS);
4295 }
4296 
4297 /*
4298  * Resource control checks don't need to be done. Why? Because this routine
4299  * knows the size of the structure, and it can't be overridden by a user.
4300  * This is different from the crypto module, which has no knowledge of
4301  * specific mechanisms, and therefore has to trust specified size of the
4302  * parameter.  This trust, or lack of trust, is why the size of the
4303  * parameter has to be charged against the project resource control.
4304  */
4305 static int
4306 copyin_aes_ccm_mech(crypto_mechanism_t *in_mech, crypto_mechanism_t *out_mech,
4307     int *out_error, int mode)
4308 {
4309         STRUCT_DECL(crypto_mechanism, mech);
4310         STRUCT_DECL(CK_AES_CCM_PARAMS, params);
4311         CK_AES_CCM_PARAMS *aes_ccm_params;
4312         caddr_t pp;
4313         size_t param_len;
4314         int error = 0;
4315         int rv = 0;
4316 
4317         STRUCT_INIT(mech, mode);
4318         STRUCT_INIT(params, mode);
4319         bcopy(in_mech, STRUCT_BUF(mech), STRUCT_SIZE(mech));
4320         pp = STRUCT_FGETP(mech, cm_param);
4321         param_len = STRUCT_FGET(mech, cm_param_len);
4322 
4323         if (param_len != STRUCT_SIZE(params)) {
4324                 rv = CRYPTO_ARGUMENTS_BAD;
4325                 goto out;
4326         }
4327 
4328         out_mech->cm_type = STRUCT_FGET(mech, cm_type);
4329         out_mech->cm_param = NULL;
4330         out_mech->cm_param_len = 0;
4331         if (pp != NULL) {
4332                 size_t nonce_len, auth_data_len, total_param_len;
4333 
4334                 if (copyin((char *)pp, STRUCT_BUF(params), param_len) != 0) {
4335                         out_mech->cm_param = NULL;
4336                         error = EFAULT;
4337                         goto out;
4338                 }
4339 
4340                 nonce_len = STRUCT_FGET(params, ulNonceSize);
4341                 auth_data_len = STRUCT_FGET(params, ulAuthDataSize);
4342 
4343                 /* allocate param structure */
4344                 total_param_len =
4345                     sizeof (CK_AES_CCM_PARAMS) + nonce_len + auth_data_len;
4346                 aes_ccm_params = kmem_alloc(total_param_len, KM_NOSLEEP);
4347                 if (aes_ccm_params == NULL) {
4348                         rv = CRYPTO_HOST_MEMORY;
4349                         goto out;
4350                 }
4351                 aes_ccm_params->ulMACSize = STRUCT_FGET(params, ulMACSize);
4352                 aes_ccm_params->ulNonceSize = nonce_len;
4353                 aes_ccm_params->ulAuthDataSize = auth_data_len;
4354                 aes_ccm_params->ulDataSize
4355                     = STRUCT_FGET(params, ulDataSize);
4356                 aes_ccm_params->nonce
4357                     = (uchar_t *)aes_ccm_params + sizeof (CK_AES_CCM_PARAMS);
4358                 aes_ccm_params->authData
4359                     = aes_ccm_params->nonce + nonce_len;
4360 
4361                 if (copyin((char *)STRUCT_FGETP(params, nonce),
4362                     aes_ccm_params->nonce, nonce_len) != 0) {
4363                         kmem_free(aes_ccm_params, total_param_len);
4364                         out_mech->cm_param = NULL;
4365                         error = EFAULT;
4366                         goto out;
4367                 }
4368                 if (copyin((char *)STRUCT_FGETP(params, authData),
4369                     aes_ccm_params->authData, auth_data_len) != 0) {
4370                         kmem_free(aes_ccm_params, total_param_len);
4371                         out_mech->cm_param = NULL;
4372                         error = EFAULT;
4373                         goto out;
4374                 }
4375                 out_mech->cm_param = (char *)aes_ccm_params;
4376                 out_mech->cm_param_len = sizeof (CK_AES_CCM_PARAMS);
4377         }
4378 out:
4379         *out_error = error;
4380         return (rv);
4381 }
4382 
4383 /*
4384  * Resource control checks don't need to be done. Why? Because this routine
4385  * knows the size of the structure, and it can't be overridden by a user.
4386  * This is different from the crypto module, which has no knowledge of
4387  * specific mechanisms, and therefore has to trust specified size of the
4388  * parameter.  This trust, or lack of trust, is why the size of the
4389  * parameter has to be charged against the project resource control.
4390  */
4391 static int
4392 copyin_aes_gcm_mech(crypto_mechanism_t *in_mech, crypto_mechanism_t *out_mech,
4393     int *out_error, int mode)
4394 {
4395         STRUCT_DECL(crypto_mechanism, mech);
4396         STRUCT_DECL(CK_AES_GCM_PARAMS, params);
4397         CK_AES_GCM_PARAMS *aes_gcm_params;
4398         caddr_t pp;
4399         size_t param_len;
4400         int error = 0;
4401         int rv = 0;
4402 
4403         STRUCT_INIT(mech, mode);
4404         STRUCT_INIT(params, mode);
4405         bcopy(in_mech, STRUCT_BUF(mech), STRUCT_SIZE(mech));
4406         pp = STRUCT_FGETP(mech, cm_param);
4407         param_len = STRUCT_FGET(mech, cm_param_len);
4408 
4409         if (param_len != STRUCT_SIZE(params)) {
4410                 rv = CRYPTO_ARGUMENTS_BAD;
4411                 goto out;
4412         }
4413 
4414         out_mech->cm_type = STRUCT_FGET(mech, cm_type);
4415         out_mech->cm_param = NULL;
4416         out_mech->cm_param_len = 0;
4417         if (pp != NULL) {
4418                 size_t nonce_len, auth_data_len, total_param_len;
4419 
4420                 if (copyin((char *)pp, STRUCT_BUF(params), param_len) != 0) {
4421                         out_mech->cm_param = NULL;
4422                         error = EFAULT;
4423                         goto out;
4424                 }
4425 
4426                 nonce_len = STRUCT_FGET(params, ulIvLen);
4427                 auth_data_len = STRUCT_FGET(params, ulAADLen);
4428 
4429                 /* allocate param structure */
4430                 total_param_len =
4431                     sizeof (CK_AES_GCM_PARAMS) + nonce_len + auth_data_len;
4432                 aes_gcm_params = kmem_alloc(total_param_len, KM_NOSLEEP);
4433                 if (aes_gcm_params == NULL) {
4434                         rv = CRYPTO_HOST_MEMORY;
4435                         goto out;
4436                 }
4437                 aes_gcm_params->ulTagBits = STRUCT_FGET(params, ulTagBits);
4438                 aes_gcm_params->ulIvLen = nonce_len;
4439                 aes_gcm_params->ulAADLen = auth_data_len;
4440                 aes_gcm_params->pIv
4441                     = (uchar_t *)aes_gcm_params + sizeof (CK_AES_GCM_PARAMS);
4442                 aes_gcm_params->pAAD = aes_gcm_params->pIv + nonce_len;
4443 
4444                 if (copyin((char *)STRUCT_FGETP(params, pIv),
4445                     aes_gcm_params->pIv, nonce_len) != 0) {
4446                         kmem_free(aes_gcm_params, total_param_len);
4447                         out_mech->cm_param = NULL;
4448                         error = EFAULT;
4449                         goto out;
4450                 }
4451                 if (copyin((char *)STRUCT_FGETP(params, pAAD),
4452                     aes_gcm_params->pAAD, auth_data_len) != 0) {
4453                         kmem_free(aes_gcm_params, total_param_len);
4454                         out_mech->cm_param = NULL;
4455                         error = EFAULT;
4456                         goto out;
4457                 }
4458                 out_mech->cm_param = (char *)aes_gcm_params;
4459                 out_mech->cm_param_len = sizeof (CK_AES_GCM_PARAMS);
4460         }
4461 out:
4462         *out_error = error;
4463         return (rv);
4464 }
4465 
4466 static int
4467 copyin_aes_gmac_mech(crypto_mechanism_t *in_mech, crypto_mechanism_t *out_mech,
4468     int *out_error, int mode)
4469 {
4470         STRUCT_DECL(crypto_mechanism, mech);
4471         STRUCT_DECL(CK_AES_GMAC_PARAMS, params);
4472         CK_AES_GMAC_PARAMS *aes_gmac_params;
4473         caddr_t pp;
4474         size_t param_len;
4475         int error = 0;
4476         int rv = 0;
4477 
4478         STRUCT_INIT(mech, mode);
4479         STRUCT_INIT(params, mode);
4480         bcopy(in_mech, STRUCT_BUF(mech), STRUCT_SIZE(mech));
4481         pp = STRUCT_FGETP(mech, cm_param);
4482         param_len = STRUCT_FGET(mech, cm_param_len);
4483 
4484         if (param_len != STRUCT_SIZE(params)) {
4485                 rv = CRYPTO_ARGUMENTS_BAD;
4486                 goto out;
4487         }
4488 
4489         out_mech->cm_type = STRUCT_FGET(mech, cm_type);
4490         out_mech->cm_param = NULL;
4491         out_mech->cm_param_len = 0;
4492         if (pp != NULL) {
4493                 size_t auth_data_len, total_param_len;
4494 
4495                 if (copyin((char *)pp, STRUCT_BUF(params), param_len) != 0) {
4496                         out_mech->cm_param = NULL;
4497                         error = EFAULT;
4498                         goto out;
4499                 }
4500 
4501                 auth_data_len = STRUCT_FGET(params, ulAADLen);
4502 
4503                 /* allocate param structure */
4504                 total_param_len = sizeof (CK_AES_GMAC_PARAMS) +
4505                     AES_GMAC_IV_LEN + auth_data_len;
4506                 aes_gmac_params = kmem_alloc(total_param_len, KM_NOSLEEP);
4507                 if (aes_gmac_params == NULL) {
4508                         rv = CRYPTO_HOST_MEMORY;
4509                         goto out;
4510                 }
4511                 aes_gmac_params->ulAADLen = auth_data_len;
4512                 aes_gmac_params->pIv
4513                     = (uchar_t *)aes_gmac_params + sizeof (CK_AES_GMAC_PARAMS);
4514                 aes_gmac_params->pAAD = aes_gmac_params->pIv + AES_GMAC_IV_LEN;
4515 
4516                 if (copyin((char *)STRUCT_FGETP(params, pIv),
4517                     aes_gmac_params->pIv, AES_GMAC_IV_LEN) != 0) {
4518                         kmem_free(aes_gmac_params, total_param_len);
4519                         out_mech->cm_param = NULL;
4520                         error = EFAULT;
4521                         goto out;
4522                 }
4523                 if (copyin((char *)STRUCT_FGETP(params, pAAD),
4524                     aes_gmac_params->pAAD, auth_data_len) != 0) {
4525                         kmem_free(aes_gmac_params, total_param_len);
4526                         out_mech->cm_param = NULL;
4527                         error = EFAULT;
4528                         goto out;
4529                 }
4530                 out_mech->cm_param = (char *)aes_gmac_params;
4531                 out_mech->cm_param_len = sizeof (CK_AES_GMAC_PARAMS);
4532         }
4533 out:
4534         *out_error = error;
4535         return (rv);
4536 }
4537 
4538 /*
4539  * Resource control checks don't need to be done. Why? Because this routine
4540  * knows the size of the structure, and it can't be overridden by a user.
4541  * This is different from the crypto module, which has no knowledge of
4542  * specific mechanisms, and therefore has to trust specified size of the
4543  * parameter.  This trust, or lack of trust, is why the size of the
4544  * parameter has to be charged against the project resource control.
4545  */
4546 static int
4547 copyin_aes_ctr_mech(crypto_mechanism_t *in_mech, crypto_mechanism_t *out_mech,
4548     int *out_error, int mode)
4549 {
4550         STRUCT_DECL(crypto_mechanism, mech);
4551         STRUCT_DECL(CK_AES_CTR_PARAMS, params);
4552         CK_AES_CTR_PARAMS *aes_ctr_params;
4553         caddr_t pp;
4554         size_t param_len;
4555         int error = 0;
4556         int rv = 0;
4557 
4558         STRUCT_INIT(mech, mode);
4559         STRUCT_INIT(params, mode);
4560         bcopy(in_mech, STRUCT_BUF(mech), STRUCT_SIZE(mech));
4561         pp = STRUCT_FGETP(mech, cm_param);
4562         param_len = STRUCT_FGET(mech, cm_param_len);
4563 
4564         if (param_len != STRUCT_SIZE(params)) {
4565                 rv = CRYPTO_ARGUMENTS_BAD;
4566                 goto out;
4567         }
4568 
4569         out_mech->cm_type = STRUCT_FGET(mech, cm_type);
4570         out_mech->cm_param = NULL;
4571         out_mech->cm_param_len = 0;
4572         if (pp != NULL) {
4573                 if (copyin((char *)pp, STRUCT_BUF(params), param_len) != 0) {
4574                         out_mech->cm_param = NULL;
4575                         error = EFAULT;
4576                         goto out;
4577                 }
4578                 /* allocate param structure and counter block */
4579                 aes_ctr_params = kmem_alloc(sizeof (CK_AES_CTR_PARAMS),
4580                     KM_NOSLEEP);
4581                 if (aes_ctr_params == NULL) {
4582                         rv = CRYPTO_HOST_MEMORY;
4583                         goto out;
4584                 }
4585                 aes_ctr_params->ulCounterBits = STRUCT_FGET(params,
4586                     ulCounterBits);
4587                 bcopy(STRUCT_FGETP(params, cb), aes_ctr_params->cb, 16);
4588                 out_mech->cm_param = (char *)aes_ctr_params;
4589                 out_mech->cm_param_len = sizeof (CK_AES_CTR_PARAMS);
4590         }
4591 out:
4592         *out_error = error;
4593         return (rv);
4594 }
4595 
4596 static int
4597 copyin_ecc_mech(crypto_mechanism_t *in_mech, crypto_mechanism_t *out_mech,
4598     int *out_error, int mode)
4599 {
4600         STRUCT_DECL(crypto_mechanism, mech);
4601         STRUCT_DECL(CK_ECDH1_DERIVE_PARAMS, params);
4602         CK_ECDH1_DERIVE_PARAMS *ecc_params;
4603         caddr_t pp;
4604         size_t param_len, shared_data_len, public_data_len;
4605         int error = 0;
4606         int rv = 0;
4607 
4608         STRUCT_INIT(mech, mode);
4609         STRUCT_INIT(params, mode);
4610         bcopy(in_mech, STRUCT_BUF(mech), STRUCT_SIZE(mech));
4611         pp = STRUCT_FGETP(mech, cm_param);
4612         param_len = STRUCT_FGET(mech, cm_param_len);
4613 
4614         if (param_len != STRUCT_SIZE(params)) {
4615                 rv = CRYPTO_ARGUMENTS_BAD;
4616                 goto out;
4617         }
4618 
4619         out_mech->cm_type = STRUCT_FGET(mech, cm_type);
4620         out_mech->cm_param = NULL;
4621         out_mech->cm_param_len = 0;
4622         if (pp != NULL) {
4623                 if (copyin((char *)pp, STRUCT_BUF(params), param_len) != 0) {
4624                         out_mech->cm_param = NULL;
4625                         error = EFAULT;
4626                         goto out;
4627                 }
4628                 shared_data_len = STRUCT_FGET(params, ulSharedDataLen);
4629                 public_data_len = STRUCT_FGET(params, ulPublicDataLen);
4630                 /* allocate param structure and buffers */
4631                 ecc_params = kmem_alloc(sizeof (CK_ECDH1_DERIVE_PARAMS) +
4632                     roundup(shared_data_len, sizeof (caddr_t)) +
4633                     roundup(public_data_len, sizeof (caddr_t)), KM_NOSLEEP);
4634                 if (ecc_params == NULL) {
4635                         rv = CRYPTO_HOST_MEMORY;
4636                         goto out;
4637                 }
4638                 ecc_params->pSharedData = (uchar_t *)ecc_params +
4639                     sizeof (CK_ECDH1_DERIVE_PARAMS);
4640                 ecc_params->pPublicData = (uchar_t *)ecc_params->pSharedData +
4641                     roundup(shared_data_len, sizeof (caddr_t));
4642                 if (copyin((char *)STRUCT_FGETP(params, pSharedData),
4643                     ecc_params->pSharedData, shared_data_len) != 0) {
4644                         kmem_free(ecc_params, sizeof (CK_ECDH1_DERIVE_PARAMS) +
4645                             roundup(shared_data_len, sizeof (caddr_t)) +
4646                             roundup(public_data_len, sizeof (caddr_t)));
4647                         out_mech->cm_param = NULL;
4648                         error = EFAULT;
4649                         goto out;
4650                 }
4651                 ecc_params->ulSharedDataLen = shared_data_len;
4652 
4653                 if (copyin((char *)STRUCT_FGETP(params, pPublicData),
4654                     ecc_params->pPublicData, public_data_len) != 0) {
4655                         kmem_free(ecc_params, sizeof (CK_ECDH1_DERIVE_PARAMS) +
4656                             roundup(shared_data_len, sizeof (caddr_t)) +
4657                             roundup(public_data_len, sizeof (caddr_t)));
4658                         out_mech->cm_param = NULL;
4659                         error = EFAULT;
4660                         goto out;
4661                 }
4662                 ecc_params->ulPublicDataLen = public_data_len;
4663                 ecc_params->kdf = STRUCT_FGET(params, kdf);
4664                 out_mech->cm_param = (char *)ecc_params;
4665                 out_mech->cm_param_len = sizeof (CK_ECDH1_DERIVE_PARAMS);
4666         }
4667 out:
4668         *out_error = error;
4669         return (rv);
4670 }
4671 
4672 /* ARGSUSED */
4673 static int
4674 copyout_aes_ctr_mech(crypto_mechanism_t *in_mech, crypto_mechanism_t *out_mech,
4675     int *out_error, int mode)
4676 {
4677         STRUCT_DECL(crypto_mechanism, mech);
4678         STRUCT_DECL(CK_AES_CTR_PARAMS, params);
4679         caddr_t pp;
4680         size_t param_len;
4681         int error = 0;
4682         int rv = 0;
4683 
4684         STRUCT_INIT(mech, mode);
4685         STRUCT_INIT(params, mode);
4686         bcopy(out_mech, STRUCT_BUF(mech), STRUCT_SIZE(mech));
4687         pp = STRUCT_FGETP(mech, cm_param);
4688         param_len = STRUCT_FGET(mech, cm_param_len);
4689         if (param_len != STRUCT_SIZE(params)) {
4690                 rv = CRYPTO_ARGUMENTS_BAD;
4691                 goto out;
4692         }
4693 
4694         if (copyin((char *)pp, STRUCT_BUF(params), param_len) != 0) {
4695                 error = EFAULT;
4696                 goto out;
4697         }
4698 
4699         /* for testing, overwrite the iv with 16 X 'A' */
4700         (void) memset(STRUCT_FGETP(params, cb), 'A', 16);
4701         if (copyout((char *)pp, STRUCT_BUF(params),  param_len) != 0) {
4702                 error = EFAULT;
4703                 goto out;
4704         }
4705 out:
4706         *out_error = error;
4707         return (rv);
4708 }
4709 
4710 /* ARGSUSED */
4711 static int
4712 dprov_copyin_mechanism(crypto_provider_handle_t provider,
4713     crypto_mechanism_t *umech, crypto_mechanism_t *kmech,
4714     int *out_error, int mode)
4715 {
4716         STRUCT_DECL(crypto_mechanism, mech);
4717         size_t param_len, expected_param_len;
4718         caddr_t pp;
4719         char *param;
4720         int rv;
4721         int error = 0;
4722 
4723         ASSERT(!servicing_interrupt());
4724 
4725         STRUCT_INIT(mech, mode);
4726         bcopy(umech, STRUCT_BUF(mech), STRUCT_SIZE(mech));
4727         pp = STRUCT_FGETP(mech, cm_param);
4728         param_len = STRUCT_FGET(mech, cm_param_len);
4729 
4730         kmech->cm_param = NULL;
4731         kmech->cm_param_len = 0;
4732 
4733         switch (kmech->cm_type) {
4734         case DES_CBC_MECH_INFO_TYPE:
4735         case DES3_CBC_MECH_INFO_TYPE:
4736                 expected_param_len = DES_BLOCK_LEN;
4737                 break;
4738 
4739         case BLOWFISH_CBC_MECH_INFO_TYPE:
4740                 expected_param_len = BLOWFISH_BLOCK_LEN;
4741                 break;
4742 
4743         case AES_CBC_MECH_INFO_TYPE:
4744                 expected_param_len = AES_BLOCK_LEN;
4745                 break;
4746 
4747         case AES_CTR_MECH_INFO_TYPE:
4748         case SHA1_KEY_DERIVATION_MECH_INFO_TYPE:        /* for testing only */
4749                 rv = copyin_aes_ctr_mech(umech, kmech, &error, mode);
4750                 goto out;
4751 
4752         case ECDH1_DERIVE_MECH_INFO_TYPE:
4753                 rv = copyin_ecc_mech(umech, kmech, &error, mode);
4754                 goto out;
4755 
4756         case AES_CCM_MECH_INFO_TYPE:
4757                 rv = copyin_aes_ccm_mech(umech, kmech, &error, mode);
4758                 goto out;
4759 
4760         case AES_GCM_MECH_INFO_TYPE:
4761                 rv = copyin_aes_gcm_mech(umech, kmech, &error, mode);
4762                 goto out;
4763 
4764         case AES_GMAC_MECH_INFO_TYPE:
4765                 rv = copyin_aes_gmac_mech(umech, kmech, &error, mode);
4766                 goto out;
4767 
4768         case DH_PKCS_DERIVE_MECH_INFO_TYPE:
4769                 expected_param_len = param_len;
4770                 break;
4771 
4772         default:
4773                 /* nothing to do - mechanism has no parameters */
4774                 rv = CRYPTO_SUCCESS;
4775                 goto out;
4776         }
4777 
4778         if (param_len != expected_param_len) {
4779                 rv = CRYPTO_MECHANISM_PARAM_INVALID;
4780                 goto out;
4781         }
4782         if (pp == NULL) {
4783                 rv = CRYPTO_MECHANISM_PARAM_INVALID;
4784                 goto out;
4785         }
4786         if ((param = kmem_alloc(param_len, KM_NOSLEEP)) == NULL) {
4787                 rv = CRYPTO_HOST_MEMORY;
4788                 goto out;
4789         }
4790         if (copyin((char *)pp, param, param_len) != 0) {
4791                 kmem_free(param, param_len);
4792                 error = EFAULT;
4793                 rv = CRYPTO_FAILED;
4794                 goto out;
4795         }
4796         kmech->cm_param = (char *)param;
4797         kmech->cm_param_len = param_len;
4798         rv = CRYPTO_SUCCESS;
4799 out:
4800         *out_error = error;
4801         return (rv);
4802 }
4803 
4804 /* ARGSUSED */
4805 static int
4806 dprov_copyout_mechanism(crypto_provider_handle_t provider,
4807     crypto_mechanism_t *kmech, crypto_mechanism_t *umech,
4808     int *out_error, int mode)
4809 {
4810         ASSERT(!servicing_interrupt());
4811 
4812         switch (kmech->cm_type) {
4813         case AES_CTR_MECH_INFO_TYPE:
4814         case SHA1_KEY_DERIVATION_MECH_INFO_TYPE:        /* for testing only */
4815                 return (copyout_aes_ctr_mech(kmech, umech, out_error, mode));
4816         case ECDH1_DERIVE_MECH_INFO_TYPE:
4817                 return (CRYPTO_SUCCESS);
4818         default:
4819                 return (CRYPTO_MECHANISM_INVALID);
4820         }
4821 }
4822 
4823 /*
4824  * Free mechanism parameter that was allocated by the provider.
4825  */
4826 /* ARGSUSED */
4827 static int
4828 dprov_free_mechanism(crypto_provider_handle_t provider,
4829     crypto_mechanism_t *mech)
4830 {
4831         size_t len;
4832 
4833         if (mech->cm_param == NULL || mech->cm_param_len == 0)
4834                 return (CRYPTO_SUCCESS);
4835 
4836         switch (mech->cm_type) {
4837         case AES_CTR_MECH_INFO_TYPE:
4838         case SHA1_KEY_DERIVATION_MECH_INFO_TYPE:
4839                 len = sizeof (CK_AES_CTR_PARAMS);
4840                 break;
4841         case ECDH1_DERIVE_MECH_INFO_TYPE: {
4842                 CK_ECDH1_DERIVE_PARAMS *ecc_params;
4843 
4844                 /* LINTED: pointer alignment */
4845                 ecc_params = (CK_ECDH1_DERIVE_PARAMS *)mech->cm_param;
4846                 kmem_free(ecc_params, sizeof (CK_ECDH1_DERIVE_PARAMS) +
4847                     roundup(ecc_params->ulSharedDataLen, sizeof (caddr_t)) +
4848                     roundup(ecc_params->ulPublicDataLen, sizeof (caddr_t)));
4849                 return (CRYPTO_SUCCESS);
4850         }
4851         case AES_CCM_MECH_INFO_TYPE: {
4852                 CK_AES_CCM_PARAMS *params;
4853                 size_t total_param_len;
4854 
4855                 if ((mech->cm_param != NULL) && (mech->cm_param_len != 0)) {
4856                         /* LINTED: pointer alignment */
4857                         params = (CK_AES_CCM_PARAMS *)mech->cm_param;
4858                         total_param_len = mech->cm_param_len +
4859                             params->ulNonceSize + params->ulAuthDataSize;
4860                         kmem_free(params, total_param_len);
4861                         mech->cm_param = NULL;
4862                         mech->cm_param_len = 0;
4863                 }
4864                 return (CRYPTO_SUCCESS);
4865         }
4866         case AES_GMAC_MECH_INFO_TYPE: {
4867                 CK_AES_GMAC_PARAMS *params;
4868                 size_t total_param_len;
4869 
4870                 if ((mech->cm_param != NULL) && (mech->cm_param_len != 0)) {
4871                         /* LINTED: pointer alignment */
4872                         params = (CK_AES_GMAC_PARAMS *)mech->cm_param;
4873                         total_param_len = mech->cm_param_len +
4874                             AES_GMAC_IV_LEN + params->ulAADLen;
4875                         kmem_free(params, total_param_len);
4876                         mech->cm_param = NULL;
4877                         mech->cm_param_len = 0;
4878                 }
4879                 return (CRYPTO_SUCCESS);
4880         }
4881         case AES_GCM_MECH_INFO_TYPE: {
4882                 CK_AES_GCM_PARAMS *params;
4883                 size_t total_param_len;
4884 
4885                 if ((mech->cm_param != NULL) && (mech->cm_param_len != 0)) {
4886                         /* LINTED: pointer alignment */
4887                         params = (CK_AES_GCM_PARAMS *)mech->cm_param;
4888                         total_param_len = mech->cm_param_len +
4889                             params->ulIvLen + params->ulAADLen;
4890                         kmem_free(params, total_param_len);
4891                         mech->cm_param = NULL;
4892                         mech->cm_param_len = 0;
4893                 }
4894                 return (CRYPTO_SUCCESS);
4895         }
4896 
4897         default:
4898                 len = mech->cm_param_len;
4899         }
4900         kmem_free(mech->cm_param, len);
4901         return (CRYPTO_SUCCESS);
4902 }
4903 
4904 /*
4905  * No (Key)Store Key management entry point.
4906  */
4907 static int
4908 dprov_nostore_key_generate(crypto_provider_handle_t provider,
4909     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
4910     crypto_object_attribute_t *template, uint_t attribute_count,
4911     crypto_object_attribute_t *out_template, uint_t out_attribute_count,
4912     crypto_req_handle_t req)
4913 {
4914         int error = CRYPTO_FAILED;
4915         dprov_state_t *softc = (dprov_state_t *)provider;
4916         /* LINTED E_FUNC_SET_NOT_USED */
4917         int instance;
4918 
4919         instance = ddi_get_instance(softc->ds_dip);
4920         DPROV_DEBUG(D_KEY, ("(%d) dprov_nostore_key_generate: started\n",
4921             instance));
4922 
4923         /* submit request to the taskq */
4924         error = dprov_key_submit_req(DPROV_REQ_NOSTORE_KEY_GENERATE,
4925             softc, req, session_id, mechanism, template, attribute_count,
4926             NULL, NULL, 0, NULL, NULL, NULL, 0, out_template,
4927             out_attribute_count, NULL, 0);
4928 
4929         DPROV_DEBUG(D_KEY, ("(%d) dprov_nostore_key_generate: "
4930             "done err = 0x0%x\n", instance, error));
4931 
4932         return (error);
4933 }
4934 
4935 static int
4936 dprov_nostore_key_generate_pair(crypto_provider_handle_t provider,
4937     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
4938     crypto_object_attribute_t *public_key_template,
4939     uint_t public_key_attribute_count,
4940     crypto_object_attribute_t *private_key_template,
4941     uint_t private_key_attribute_count,
4942     crypto_object_attribute_t *out_public_key_template,
4943     uint_t out_public_key_attribute_count,
4944     crypto_object_attribute_t *out_private_key_template,
4945     uint_t out_private_key_attribute_count,
4946     crypto_req_handle_t req)
4947 {
4948         int error = CRYPTO_FAILED;
4949         dprov_state_t *softc = (dprov_state_t *)provider;
4950         /* LINTED E_FUNC_SET_NOT_USED */
4951         int instance;
4952 
4953         instance = ddi_get_instance(softc->ds_dip);
4954         DPROV_DEBUG(D_KEY, ("(%d) dprov_nostore_key_generate_pair: started\n",
4955             instance));
4956 
4957         /* submit request to the taskq */
4958         error = dprov_key_submit_req(DPROV_REQ_NOSTORE_KEY_GENERATE_PAIR,
4959             softc, req, session_id, mechanism, public_key_template,
4960             public_key_attribute_count, NULL, private_key_template,
4961             private_key_attribute_count, NULL, NULL, NULL, 0,
4962             out_public_key_template, out_public_key_attribute_count,
4963             out_private_key_template, out_private_key_attribute_count);
4964 
4965         DPROV_DEBUG(D_KEY, ("(%d) dprov_nostore_key_generate_pair: "
4966             "done err = 0x0%x\n", instance, error));
4967 
4968         return (error);
4969 }
4970 
4971 static int
4972 dprov_nostore_key_derive(crypto_provider_handle_t provider,
4973     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
4974     crypto_key_t *base_key, crypto_object_attribute_t *template,
4975     uint_t attribute_count, crypto_object_attribute_t *out_template,
4976     uint_t out_attribute_count, crypto_req_handle_t req)
4977 {
4978         int error = CRYPTO_FAILED;
4979         dprov_state_t *softc = (dprov_state_t *)provider;
4980         /* LINTED E_FUNC_SET_NOT_USED */
4981         int instance;
4982 
4983         instance = ddi_get_instance(softc->ds_dip);
4984         DPROV_DEBUG(D_KEY, ("(%d) dprov_nostore_key_derive: started\n",
4985             instance));
4986 
4987         /* submit request to the taskq */
4988         error = dprov_key_submit_req(DPROV_REQ_NOSTORE_KEY_DERIVE, softc, req,
4989             session_id, mechanism, template, attribute_count, NULL, NULL,
4990             0, NULL, base_key, NULL, 0, out_template, out_attribute_count,
4991             NULL, 0);
4992 
4993         DPROV_DEBUG(D_KEY, ("(%d) dprov_nostore_key_derive: "
4994             "done err = 0x0%x\n", instance, error));
4995 
4996         return (error);
4997 }
4998 
4999 /*
5000  * Allocate a dprov taskq request and initialize the common fields.
5001  * Return NULL if the memory allocation failed.
5002  */
5003 static dprov_req_t *
5004 dprov_alloc_req(dprov_req_type_t req_type, dprov_state_t *softc,
5005     crypto_req_handle_t kcf_req, int kmflag)
5006 {
5007         dprov_req_t *taskq_req;
5008 
5009         if ((taskq_req = kmem_alloc(sizeof (dprov_req_t), kmflag)) == NULL)
5010                 return (NULL);
5011 
5012         taskq_req->dr_type = req_type;
5013         taskq_req->dr_softc = softc;
5014         taskq_req->dr_kcf_req = kcf_req;
5015 
5016         return (taskq_req);
5017 }
5018 
5019 /*
5020  * Dispatch a dprov request on the taskq associated with a softc.
5021  * Returns CRYPTO_HOST_MEMORY if the request cannot be queued,
5022  * CRYPTO_QUEUED on success.
5023  */
5024 static int
5025 dprov_taskq_dispatch(dprov_state_t *softc, dprov_req_t *taskq_req,
5026     task_func_t *func, int kmflag)
5027 {
5028         if (taskq_dispatch(softc->ds_taskq, func, taskq_req,
5029             kmflag == KM_NOSLEEP ? TQ_NOSLEEP : TQ_SLEEP) == (taskqid_t)0) {
5030                 kmem_free(taskq_req, sizeof (dprov_req_t));
5031                 return (CRYPTO_HOST_MEMORY);
5032         } else
5033                 return (CRYPTO_QUEUED);
5034 }
5035 
5036 /*
5037  * Helper function to submit digest operations to the taskq.
5038  * Returns one of the CRYPTO_ errors.
5039  */
5040 static int
5041 dprov_digest_submit_req(dprov_req_type_t req_type,
5042     dprov_state_t *softc, crypto_req_handle_t req,
5043     crypto_mechanism_t *mechanism, crypto_data_t *data, crypto_key_t *key,
5044     crypto_data_t *digest, crypto_ctx_t *ctx, int kmflag)
5045 {
5046         dprov_req_t *taskq_req;
5047 
5048         if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
5049                 return (CRYPTO_HOST_MEMORY);
5050 
5051         taskq_req->dr_digest_req.dr_mechanism = mechanism;
5052         taskq_req->dr_digest_req.dr_ctx = ctx;
5053         taskq_req->dr_digest_req.dr_data = data;
5054         taskq_req->dr_digest_req.dr_key = key;
5055         taskq_req->dr_digest_req.dr_digest = digest;
5056 
5057         return (dprov_taskq_dispatch(softc, taskq_req,
5058             (task_func_t *)dprov_digest_task, kmflag));
5059 }
5060 
5061 /*
5062  * Helper function to submit mac operations to the taskq.
5063  * Returns one of the CRYPTO_ errors.
5064  */
5065 static int
5066 dprov_mac_submit_req(dprov_req_type_t req_type,
5067     dprov_state_t *softc, crypto_req_handle_t req,
5068     crypto_mechanism_t *mechanism, crypto_data_t *data, crypto_key_t *key,
5069     crypto_data_t *mac, crypto_ctx_t *ctx, crypto_session_id_t sid, int kmflag)
5070 {
5071         dprov_req_t *taskq_req;
5072 
5073         if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
5074                 return (CRYPTO_HOST_MEMORY);
5075 
5076         taskq_req->dr_mac_req.dr_mechanism = mechanism;
5077         taskq_req->dr_mac_req.dr_ctx = ctx;
5078         taskq_req->dr_mac_req.dr_data = data;
5079         taskq_req->dr_mac_req.dr_key = key;
5080         taskq_req->dr_mac_req.dr_mac = mac;
5081         taskq_req->dr_mac_req.dr_session_id = sid;
5082 
5083         return (dprov_taskq_dispatch(softc, taskq_req,
5084             (task_func_t *)dprov_mac_task, kmflag));
5085 }
5086 
5087 /*
5088  * Helper function to submit sign operations to the taskq.
5089  * Returns one of the CRYPTO_ errors.
5090  */
5091 static int
5092 dprov_sign_submit_req(dprov_req_type_t req_type,
5093     dprov_state_t *softc, crypto_req_handle_t req,
5094     crypto_mechanism_t *mechanism, crypto_key_t *key, crypto_data_t *data,
5095     crypto_data_t *signature, crypto_ctx_t *ctx, crypto_session_id_t sid,
5096     int kmflag)
5097 {
5098         dprov_req_t *taskq_req;
5099 
5100         if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
5101                 return (CRYPTO_HOST_MEMORY);
5102 
5103         taskq_req->dr_sign_req.sr_mechanism = mechanism;
5104         taskq_req->dr_sign_req.sr_ctx = ctx;
5105         taskq_req->dr_sign_req.sr_key = key;
5106         taskq_req->dr_sign_req.sr_data = data;
5107         taskq_req->dr_sign_req.sr_signature = signature;
5108         taskq_req->dr_sign_req.sr_session_id = sid;
5109 
5110         return (dprov_taskq_dispatch(softc, taskq_req,
5111             (task_func_t *)dprov_sign_task, kmflag));
5112 }
5113 
5114 /*
5115  * Helper function to submit verify operations to the taskq.
5116  * Returns one of the CRYPTO_ errors.
5117  */
5118 static int
5119 dprov_verify_submit_req(dprov_req_type_t req_type,
5120     dprov_state_t *softc, crypto_req_handle_t req,
5121     crypto_mechanism_t *mechanism, crypto_key_t *key, crypto_data_t *data,
5122     crypto_data_t *signature, crypto_ctx_t *ctx, crypto_session_id_t sid,
5123     int kmflag)
5124 {
5125         dprov_req_t *taskq_req;
5126 
5127         if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
5128                 return (CRYPTO_HOST_MEMORY);
5129 
5130         taskq_req->dr_verify_req.vr_mechanism = mechanism;
5131         taskq_req->dr_verify_req.vr_ctx = ctx;
5132         taskq_req->dr_verify_req.vr_key = key;
5133         taskq_req->dr_verify_req.vr_data = data;
5134         taskq_req->dr_verify_req.vr_signature = signature;
5135         taskq_req->dr_verify_req.vr_session_id = sid;
5136 
5137         return (dprov_taskq_dispatch(softc, taskq_req,
5138             (task_func_t *)dprov_verify_task, kmflag));
5139 }
5140 
5141 /*
5142  * Helper function to submit dual operations to the taskq.
5143  * Returns one of the CRYPTO_ errors.
5144  */
5145 static int
5146 dprov_dual_submit_req(dprov_req_type_t req_type, dprov_state_t *softc,
5147     crypto_req_handle_t req, crypto_ctx_t *signverify_ctx,
5148     crypto_ctx_t *cipher_ctx, crypto_data_t *plaintext,
5149     crypto_data_t *ciphertext)
5150 {
5151         dprov_req_t *taskq_req;
5152 
5153         if ((taskq_req = dprov_alloc_req(req_type, softc, req,
5154             KM_NOSLEEP)) == NULL)
5155                 return (CRYPTO_HOST_MEMORY);
5156 
5157         taskq_req->dr_dual_req.dr_signverify_ctx = signverify_ctx;
5158         taskq_req->dr_dual_req.dr_cipher_ctx = cipher_ctx;
5159         taskq_req->dr_dual_req.dr_plaintext = plaintext;
5160         taskq_req->dr_dual_req.dr_ciphertext = ciphertext;
5161 
5162         return (dprov_taskq_dispatch(softc, taskq_req,
5163             (task_func_t *)dprov_dual_task, KM_NOSLEEP));
5164 }
5165 
5166 /*
5167  * Helper function to submit dual cipher/mac operations to the taskq.
5168  * Returns one of the CRYPTO_ errors.
5169  */
5170 static int
5171 dprov_cipher_mac_submit_req(dprov_req_type_t req_type,
5172     dprov_state_t *softc, crypto_req_handle_t req, crypto_ctx_t *ctx,
5173     crypto_session_id_t sid, crypto_mechanism_t *cipher_mech,
5174     crypto_key_t *cipher_key, crypto_mechanism_t *mac_mech,
5175     crypto_key_t *mac_key, crypto_dual_data_t *dual_data,
5176     crypto_data_t *data, crypto_data_t *mac, int kmflag)
5177 {
5178         dprov_req_t *taskq_req;
5179 
5180         if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
5181                 return (CRYPTO_HOST_MEMORY);
5182 
5183         taskq_req->dr_cipher_mac_req.mr_session_id = sid;
5184         taskq_req->dr_cipher_mac_req.mr_ctx = ctx;
5185         taskq_req->dr_cipher_mac_req.mr_cipher_mech = cipher_mech;
5186         taskq_req->dr_cipher_mac_req.mr_cipher_key = cipher_key;
5187         taskq_req->dr_cipher_mac_req.mr_mac_mech = mac_mech;
5188         taskq_req->dr_cipher_mac_req.mr_mac_key = mac_key;
5189         taskq_req->dr_cipher_mac_req.mr_dual_data = dual_data;
5190         taskq_req->dr_cipher_mac_req.mr_data = data;
5191         taskq_req->dr_cipher_mac_req.mr_mac = mac;
5192 
5193         return (dprov_taskq_dispatch(softc, taskq_req,
5194             (task_func_t *)dprov_cipher_mac_task, kmflag));
5195 }
5196 
5197 /*
5198  * Helper function to submit cipher operations to the taskq.
5199  * Returns one of the CRYPTO_ errors.
5200  */
5201 static int
5202 dprov_cipher_submit_req(dprov_req_type_t req_type,
5203     dprov_state_t *softc, crypto_req_handle_t req,
5204     crypto_mechanism_t *mechanism, crypto_key_t *key, crypto_data_t *plaintext,
5205     crypto_data_t *ciphertext, crypto_ctx_t *ctx, crypto_session_id_t sid,
5206     int kmflag)
5207 {
5208         dprov_req_t *taskq_req;
5209 
5210         if ((taskq_req = dprov_alloc_req(req_type, softc, req, kmflag)) == NULL)
5211                 return (CRYPTO_HOST_MEMORY);
5212 
5213         taskq_req->dr_cipher_req.dr_mechanism = mechanism;
5214         taskq_req->dr_cipher_req.dr_ctx = ctx;
5215         taskq_req->dr_cipher_req.dr_key = key;
5216         taskq_req->dr_cipher_req.dr_plaintext = plaintext;
5217         taskq_req->dr_cipher_req.dr_ciphertext = ciphertext;
5218         taskq_req->dr_cipher_req.dr_session_id = sid;
5219 
5220         return (dprov_taskq_dispatch(softc, taskq_req,
5221             (task_func_t *)dprov_cipher_task, kmflag));
5222 }
5223 
5224 /*
5225  * Helper function to submit random number operations to the taskq.
5226  * Returns one of the CRYPTO_ errors.
5227  */
5228 static int
5229 dprov_random_submit_req(dprov_req_type_t req_type,
5230     dprov_state_t *softc, crypto_req_handle_t req, uchar_t *buf, size_t len,
5231     crypto_session_id_t sid, uint_t entropy_est, uint32_t flags)
5232 {
5233         dprov_req_t *taskq_req;
5234 
5235         if ((taskq_req = dprov_alloc_req(req_type, softc, req,
5236             KM_NOSLEEP)) == NULL)
5237                 return (CRYPTO_HOST_MEMORY);
5238 
5239         taskq_req->dr_random_req.rr_buf = buf;
5240         taskq_req->dr_random_req.rr_len = len;
5241         taskq_req->dr_random_req.rr_session_id = sid;
5242         taskq_req->dr_random_req.rr_entropy_est = entropy_est;
5243         taskq_req->dr_random_req.rr_flags = flags;
5244 
5245         return (dprov_taskq_dispatch(softc, taskq_req,
5246             (task_func_t *)dprov_random_task, KM_NOSLEEP));
5247 }
5248 
5249 
5250 /*
5251  * Helper function to submit session management operations to the taskq.
5252  * Returns one of the CRYPTO_ errors.
5253  */
5254 static int
5255 dprov_session_submit_req(dprov_req_type_t req_type,
5256     dprov_state_t *softc, crypto_req_handle_t req,
5257     crypto_session_id_t *session_id_ptr, crypto_session_id_t session_id,
5258     crypto_user_type_t user_type, char *pin, size_t pin_len)
5259 {
5260         dprov_req_t *taskq_req;
5261 
5262         if ((taskq_req = dprov_alloc_req(req_type, softc, req,
5263             KM_NOSLEEP)) == NULL)
5264                 return (CRYPTO_HOST_MEMORY);
5265 
5266         taskq_req->dr_session_req.sr_session_id_ptr = session_id_ptr;
5267         taskq_req->dr_session_req.sr_session_id = session_id;
5268         taskq_req->dr_session_req.sr_user_type = user_type;
5269         taskq_req->dr_session_req.sr_pin = pin;
5270         taskq_req->dr_session_req.sr_pin_len = pin_len;
5271 
5272         return (dprov_taskq_dispatch(softc, taskq_req,
5273             (task_func_t *)dprov_session_task, KM_NOSLEEP));
5274 }
5275 
5276 /*
5277  * Helper function to submit object management operations to the taskq.
5278  * Returns one of the CRYPTO_ errors.
5279  */
5280 static int
5281 dprov_object_submit_req(dprov_req_type_t req_type,
5282     dprov_state_t *softc, crypto_req_handle_t req,
5283     crypto_session_id_t session_id, crypto_object_id_t object_id,
5284     crypto_object_attribute_t *template, uint_t attribute_count,
5285     crypto_object_id_t *object_id_ptr, size_t *object_size,
5286     void **find_pp, void *find_p, uint_t max_object_count,
5287     uint_t *object_count_ptr, int kmflag)
5288 {
5289         dprov_req_t *taskq_req;
5290 
5291         if ((taskq_req = dprov_alloc_req(req_type, softc, req,
5292             kmflag)) == NULL)
5293                 return (CRYPTO_HOST_MEMORY);
5294 
5295         taskq_req->dr_object_req.or_session_id = session_id;
5296         taskq_req->dr_object_req.or_object_id = object_id;
5297         taskq_req->dr_object_req.or_template = template;
5298         taskq_req->dr_object_req.or_attribute_count = attribute_count;
5299         taskq_req->dr_object_req.or_object_id_ptr = object_id_ptr;
5300         taskq_req->dr_object_req.or_object_size = object_size;
5301         taskq_req->dr_object_req.or_find_pp = find_pp;
5302         taskq_req->dr_object_req.or_find_p = find_p;
5303         taskq_req->dr_object_req.or_max_object_count = max_object_count;
5304         taskq_req->dr_object_req.or_object_count_ptr = object_count_ptr;
5305 
5306         return (dprov_taskq_dispatch(softc, taskq_req,
5307             (task_func_t *)dprov_object_task, KM_NOSLEEP));
5308 }
5309 
5310 /*
5311  * Helper function to submit key management operations to the taskq.
5312  * Returns one of the CRYPTO_ errors.
5313  */
5314 static int
5315 dprov_key_submit_req(dprov_req_type_t req_type,
5316     dprov_state_t *softc, crypto_req_handle_t req,
5317     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
5318     crypto_object_attribute_t *template, uint_t attribute_count,
5319     crypto_object_id_t *object_id_ptr,
5320     crypto_object_attribute_t *private_key_template,
5321     uint_t private_key_attribute_count,
5322     crypto_object_id_t *private_key_object_id_ptr, crypto_key_t *key,
5323     uchar_t *wrapped_key, size_t *wrapped_key_len_ptr,
5324     crypto_object_attribute_t *out_template1, uint_t out_attribute_count1,
5325     crypto_object_attribute_t *out_template2, uint_t out_attribute_count2)
5326 {
5327         dprov_req_t *taskq_req;
5328 
5329         if ((taskq_req = dprov_alloc_req(req_type, softc, req,
5330             KM_NOSLEEP)) == NULL)
5331                 return (CRYPTO_HOST_MEMORY);
5332 
5333         taskq_req->dr_key_req.kr_session_id = session_id;
5334         taskq_req->dr_key_req.kr_mechanism = mechanism;
5335         taskq_req->dr_key_req.kr_template = template;
5336         taskq_req->dr_key_req.kr_attribute_count = attribute_count;
5337         taskq_req->dr_key_req.kr_object_id_ptr = object_id_ptr;
5338         taskq_req->dr_key_req.kr_private_key_template = private_key_template;
5339         taskq_req->dr_key_req.kr_private_key_attribute_count =
5340             private_key_attribute_count;
5341         taskq_req->dr_key_req.kr_private_key_object_id_ptr =
5342             private_key_object_id_ptr;
5343         taskq_req->dr_key_req.kr_key = key;
5344         taskq_req->dr_key_req.kr_wrapped_key = wrapped_key;
5345         taskq_req->dr_key_req.kr_wrapped_key_len_ptr = wrapped_key_len_ptr;
5346         taskq_req->dr_key_req.kr_out_template1 = out_template1;
5347         taskq_req->dr_key_req.kr_out_attribute_count1 = out_attribute_count1;
5348         taskq_req->dr_key_req.kr_out_template2 = out_template2;
5349         taskq_req->dr_key_req.kr_out_attribute_count2 = out_attribute_count2;
5350 
5351         return (dprov_taskq_dispatch(softc, taskq_req,
5352             (task_func_t *)dprov_key_task, KM_NOSLEEP));
5353 }
5354 
5355 /*
5356  * Helper function to submit provider management operations to the taskq.
5357  * Returns one of the CRYPTO_ errors.
5358  */
5359 static int
5360 dprov_mgmt_submit_req(dprov_req_type_t req_type,
5361     dprov_state_t *softc, crypto_req_handle_t req,
5362     crypto_session_id_t session_id, char *pin, size_t pin_len,
5363     char *old_pin, size_t old_pin_len, char *label,
5364     crypto_provider_ext_info_t *ext_info)
5365 {
5366         dprov_req_t *taskq_req;
5367 
5368         if ((taskq_req = dprov_alloc_req(req_type, softc, req,
5369             KM_NOSLEEP)) == NULL)
5370                 return (CRYPTO_HOST_MEMORY);
5371 
5372         taskq_req->dr_mgmt_req.mr_session_id = session_id;
5373         taskq_req->dr_mgmt_req.mr_pin = pin;
5374         taskq_req->dr_mgmt_req.mr_pin_len = pin_len;
5375         taskq_req->dr_mgmt_req.mr_old_pin = old_pin;
5376         taskq_req->dr_mgmt_req.mr_old_pin_len = old_pin_len;
5377         taskq_req->dr_mgmt_req.mr_label = label;
5378         taskq_req->dr_mgmt_req.mr_ext_info = ext_info;
5379 
5380         return (dprov_taskq_dispatch(softc, taskq_req,
5381             (task_func_t *)dprov_mgmt_task, KM_NOSLEEP));
5382 }
5383 
5384 /*
5385  * Helper function for taskq dispatcher routines. Notify the framework
5386  * that the operation corresponding to the specified request is done,
5387  * and pass it the error code. Finally, free the taskq_req.
5388  */
5389 static void
5390 dprov_op_done(dprov_req_t *taskq_req, int error)
5391 {
5392         /* notify framework that request is completed */
5393         crypto_op_notification(taskq_req->dr_kcf_req, error);
5394 
5395         /* free taskq request structure */
5396         kmem_free(taskq_req, sizeof (dprov_req_t));
5397 }
5398 
5399 /*
5400  * taskq dispatcher function for digest operations.
5401  */
5402 static void
5403 dprov_digest_task(dprov_req_t *taskq_req)
5404 {
5405         kcf_provider_desc_t *pd;
5406         dprov_state_t *softc;
5407         /* LINTED E_FUNC_SET_NOT_USED */
5408         int instance;
5409         int error = CRYPTO_NOT_SUPPORTED;
5410         crypto_ctx_t *ctx = taskq_req->dr_digest_req.dr_ctx;
5411         crypto_mechanism_t mech;
5412 
5413         DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
5414         DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_task: started\n", instance));
5415 
5416         switch (taskq_req->dr_type) {
5417 
5418         case DPROV_REQ_DIGEST_INIT:
5419                 /* allocate a dprov-private context */
5420                 if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
5421                     CRYPTO_SUCCESS)
5422                         break;
5423 
5424                 /* structure assignment */
5425                 mech = *taskq_req->dr_digest_req.dr_mechanism;
5426 
5427                 /* get the software provider for this mechanism */
5428                 if ((error = dprov_get_sw_prov(
5429                     taskq_req->dr_digest_req.dr_mechanism, &pd,
5430                     &mech.cm_type)) != CRYPTO_SUCCESS)
5431                         break;
5432 
5433                 /* Use a session id of zero since we use a software provider */
5434                 error = crypto_digest_init_prov(pd, 0, &mech,
5435                     &DPROV_CTX_SINGLE(ctx), NULL);
5436 
5437                 /* release provider reference */
5438                 KCF_PROV_REFRELE(pd);
5439                 break;
5440 
5441         case DPROV_REQ_DIGEST:
5442                 error = crypto_digest_single(DPROV_CTX_SINGLE(ctx),
5443                     taskq_req->dr_digest_req.dr_data,
5444                     taskq_req->dr_digest_req.dr_digest, NULL);
5445 
5446                 if (error != CRYPTO_BUFFER_TOO_SMALL) {
5447                         DPROV_CTX_SINGLE(ctx) = NULL;
5448                         (void) dprov_free_context(ctx);
5449                 }
5450                 break;
5451 
5452         case DPROV_REQ_DIGEST_UPDATE:
5453                 error = crypto_digest_update(DPROV_CTX_SINGLE(ctx),
5454                     taskq_req->dr_digest_req.dr_data, NULL);
5455                 break;
5456 
5457         case DPROV_REQ_DIGEST_KEY: {
5458                 crypto_data_t data;
5459                 crypto_key_t key;
5460                 size_t len;
5461 
5462                 mutex_enter(&softc->ds_lock);
5463                 error = dprov_key_value_secret(softc, ctx->cc_session,
5464                     taskq_req->dr_type, taskq_req->dr_digest_req.dr_key, &key);
5465                 mutex_exit(&softc->ds_lock);
5466                 if (error != CRYPTO_SUCCESS)
5467                         break;
5468 
5469                 /* key lengths are specified in bits */
5470                 len = CRYPTO_BITS2BYTES(key.ck_length);
5471                 data.cd_format = CRYPTO_DATA_RAW;
5472                 data.cd_offset = 0;
5473                 data.cd_length = len;
5474                 data.cd_raw.iov_base = key.ck_data;
5475                 data.cd_raw.iov_len = len;
5476                 error = crypto_digest_update(DPROV_CTX_SINGLE(ctx),
5477                     &data, NULL);
5478                 break;
5479         }
5480 
5481         case DPROV_REQ_DIGEST_FINAL:
5482                 error = crypto_digest_final(DPROV_CTX_SINGLE(ctx),
5483                     taskq_req->dr_digest_req.dr_digest, NULL);
5484                 if (error != CRYPTO_BUFFER_TOO_SMALL) {
5485                         DPROV_CTX_SINGLE(ctx) = NULL;
5486                         (void) dprov_free_context(ctx);
5487                 }
5488                 break;
5489 
5490         case DPROV_REQ_DIGEST_ATOMIC:
5491                 /* structure assignment */
5492                 mech = *taskq_req->dr_digest_req.dr_mechanism;
5493 
5494                 /* get the software provider for this mechanism */
5495                 if ((error = dprov_get_sw_prov(
5496                     taskq_req->dr_digest_req.dr_mechanism, &pd,
5497                     &mech.cm_type)) != CRYPTO_SUCCESS)
5498                         break;
5499 
5500                 /* use a session id of zero since we use a software provider */
5501                 error = crypto_digest_prov(pd, 0, &mech,
5502                     taskq_req->dr_digest_req.dr_data,
5503                     taskq_req->dr_digest_req.dr_digest, NULL);
5504 
5505                 /* release provider reference */
5506                 KCF_PROV_REFRELE(pd);
5507 
5508                 break;
5509         }
5510 
5511         dprov_op_done(taskq_req, error);
5512         DPROV_DEBUG(D_DIGEST, ("(%d) dprov_digest_task: end\n", instance));
5513 }
5514 
5515 /*
5516  * taskq dispatcher function for mac operations.
5517  */
5518 static void
5519 dprov_mac_task(dprov_req_t *taskq_req)
5520 {
5521         kcf_provider_desc_t *pd;
5522         dprov_state_t *softc;
5523         /* LINTED E_FUNC_SET_NOT_USED */
5524         int instance;
5525         int error = CRYPTO_NOT_SUPPORTED;
5526         crypto_ctx_t *ctx = taskq_req->dr_mac_req.dr_ctx;
5527         crypto_key_t key;
5528         crypto_mechanism_t mech;
5529 
5530         DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
5531         DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_task: started\n", instance));
5532 
5533         switch (taskq_req->dr_type) {
5534 
5535         case DPROV_REQ_MAC_INIT:
5536                 /* allocate a dprov-private context */
5537                 if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
5538                     CRYPTO_SUCCESS)
5539                         break;
5540 
5541                 /* get key value */
5542                 mutex_enter(&softc->ds_lock);
5543                 error = dprov_key_value_secret(softc, ctx->cc_session,
5544                     taskq_req->dr_type, taskq_req->dr_mac_req.dr_key, &key);
5545                 mutex_exit(&softc->ds_lock);
5546                 if (error != CRYPTO_SUCCESS)
5547                         break;
5548 
5549                 /* structure assignment */
5550                 mech = *taskq_req->dr_mac_req.dr_mechanism;
5551 
5552                 /* get the software provider for this mechanism */
5553                 if ((error = dprov_get_sw_prov(
5554                     taskq_req->dr_mac_req.dr_mechanism, &pd,
5555                     &mech.cm_type)) != CRYPTO_SUCCESS)
5556                         break;
5557 
5558                 /* Use a session id of zero since we use a software provider */
5559                 error = crypto_mac_init_prov(pd, 0, &mech, &key, NULL,
5560                     &DPROV_CTX_SINGLE(ctx), NULL);
5561 
5562                 /* release provider reference */
5563                 KCF_PROV_REFRELE(pd);
5564                 break;
5565 
5566         case DPROV_REQ_MAC:
5567                 error = crypto_mac_single(DPROV_CTX_SINGLE(ctx),
5568                     taskq_req->dr_mac_req.dr_data,
5569                     taskq_req->dr_mac_req.dr_mac, NULL);
5570 
5571                 if (error != CRYPTO_BUFFER_TOO_SMALL) {
5572                         DPROV_CTX_SINGLE(ctx) = NULL;
5573                         (void) dprov_free_context(ctx);
5574                 }
5575                 break;
5576 
5577         case DPROV_REQ_MAC_UPDATE:
5578                 error = crypto_mac_update(DPROV_CTX_SINGLE(ctx),
5579                     taskq_req->dr_mac_req.dr_data, NULL);
5580                 break;
5581 
5582         case DPROV_REQ_MAC_FINAL:
5583                 error = crypto_mac_final(DPROV_CTX_SINGLE(ctx),
5584                     taskq_req->dr_mac_req.dr_mac, NULL);
5585                 if (error != CRYPTO_BUFFER_TOO_SMALL) {
5586                         DPROV_CTX_SINGLE(ctx) = NULL;
5587                         (void) dprov_free_context(ctx);
5588                 }
5589                 break;
5590 
5591         case DPROV_REQ_MAC_ATOMIC:
5592         case DPROV_REQ_MAC_VERIFY_ATOMIC:
5593                 /* get key value */
5594                 mutex_enter(&softc->ds_lock);
5595                 error = dprov_key_value_secret(softc,
5596                     taskq_req->dr_mac_req.dr_session_id,
5597                     taskq_req->dr_type, taskq_req->dr_mac_req.dr_key, &key);
5598                 mutex_exit(&softc->ds_lock);
5599                 if (error != CRYPTO_SUCCESS)
5600                         break;
5601 
5602                 /* structure assignment */
5603                 mech = *taskq_req->dr_mac_req.dr_mechanism;
5604 
5605                 /* get the software provider for this mechanism */
5606                 if ((error = dprov_get_sw_prov(
5607                     taskq_req->dr_mac_req.dr_mechanism, &pd,
5608                     &mech.cm_type)) != CRYPTO_SUCCESS)
5609                         break;
5610 
5611                 /* use a session id of zero since we use a software provider */
5612                 if (taskq_req->dr_type == DPROV_REQ_MAC_ATOMIC)
5613                         error = crypto_mac_prov(pd, 0, &mech,
5614                             taskq_req->dr_mac_req.dr_data,
5615                             &key, NULL, taskq_req->dr_mac_req.dr_mac, NULL);
5616                 else
5617                         error = crypto_mac_verify_prov(pd, 0, &mech,
5618                             taskq_req->dr_mac_req.dr_data,
5619                             &key, NULL, taskq_req->dr_mac_req.dr_mac, NULL);
5620 
5621                 /* release provider reference */
5622                 KCF_PROV_REFRELE(pd);
5623 
5624                 break;
5625         }
5626 
5627         dprov_op_done(taskq_req, error);
5628         DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_task: end\n", instance));
5629 }
5630 
5631 /*
5632  * taskq dispatcher function for sign operations.
5633  */
5634 static void
5635 dprov_sign_task(dprov_req_t *taskq_req)
5636 {
5637         kcf_provider_desc_t *pd;
5638         dprov_state_t *softc;
5639         /* LINTED E_FUNC_SET_NOT_USED */
5640         int instance;
5641         int error = CRYPTO_NOT_SUPPORTED;
5642         crypto_ctx_t *ctx = taskq_req->dr_sign_req.sr_ctx;
5643         crypto_key_t key, *keyp;
5644         crypto_mechanism_t mech;
5645 
5646         DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
5647         DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_task: started\n", instance));
5648 
5649         switch (taskq_req->dr_type) {
5650 
5651         case DPROV_REQ_SIGN_INIT:
5652         case DPROV_REQ_SIGN_RECOVER_INIT:
5653                 /* allocate a dprov-private context */
5654                 if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
5655                     CRYPTO_SUCCESS)
5656                         break;
5657 
5658                 /* structure assignment */
5659                 mech = *taskq_req->dr_sign_req.sr_mechanism;
5660                 if (dprov_valid_mac_mech(mech.cm_type)) {
5661                         DPROV_CTX_P(ctx)->dc_svrfy_to_mac = B_TRUE;
5662                 }
5663 
5664                 mutex_enter(&softc->ds_lock);
5665                 if (is_publickey_mech(mech.cm_type)) {
5666                         if ((error = dprov_key_attr_asymmetric(softc,
5667                             ctx->cc_session, taskq_req->dr_type,
5668                             taskq_req->dr_sign_req.sr_key, &key))
5669                             != CRYPTO_SUCCESS) {
5670                                 mutex_exit(&softc->ds_lock);
5671                                 break;
5672                         }
5673                         keyp = &key;
5674                 } else {
5675                         if ((error = dprov_key_value_secret(softc,
5676                             ctx->cc_session, taskq_req->dr_type,
5677                             taskq_req->dr_sign_req.sr_key, &key))
5678                             != CRYPTO_SUCCESS) {
5679                                 mutex_exit(&softc->ds_lock);
5680                                 break;
5681                         }
5682                         keyp = &key;
5683                 }
5684                 mutex_exit(&softc->ds_lock);
5685 
5686                 /* get the software provider for this mechanism */
5687                 if ((error = dprov_get_sw_prov(
5688                     taskq_req->dr_sign_req.sr_mechanism, &pd,
5689                     &mech.cm_type)) != CRYPTO_SUCCESS)
5690                         break;
5691 
5692                 if (DPROV_CTX_P(ctx)->dc_svrfy_to_mac) {
5693                         error = crypto_mac_init_prov(pd, 0, &mech, keyp, NULL,
5694                             &DPROV_CTX_SINGLE(ctx), NULL);
5695 
5696                         /* release provider reference */
5697                         KCF_PROV_REFRELE(pd);
5698                         break;
5699                 }
5700 
5701                 /* Use a session id of zero since we use a software provider */
5702                 if (taskq_req->dr_type == DPROV_REQ_SIGN_INIT)
5703                         error = crypto_sign_init_prov(pd, 0, &mech, keyp,
5704                             NULL, &DPROV_CTX_SINGLE(ctx), NULL);
5705                 else
5706                         error = crypto_sign_recover_init_prov(pd, 0, &mech,
5707                             keyp, NULL, &DPROV_CTX_SINGLE(ctx), NULL);
5708 
5709                 /* release provider reference */
5710                 KCF_PROV_REFRELE(pd);
5711 
5712                 break;
5713 
5714         case DPROV_REQ_SIGN:
5715                 if (DPROV_CTX_P(ctx)->dc_svrfy_to_mac) {
5716                         /* Emulate using update and final */
5717                         error = crypto_mac_update(DPROV_CTX_SINGLE(ctx),
5718                             taskq_req->dr_mac_req.dr_data, NULL);
5719                         if (error == CRYPTO_SUCCESS) {
5720                                 error = crypto_mac_final(DPROV_CTX_SINGLE(ctx),
5721                                     taskq_req->dr_mac_req.dr_mac, NULL);
5722                         }
5723                 } else {
5724                         error = crypto_sign_single(DPROV_CTX_SINGLE(ctx),
5725                             taskq_req->dr_sign_req.sr_data,
5726                             taskq_req->dr_sign_req.sr_signature, NULL);
5727                 }
5728 
5729                 if (error != CRYPTO_BUFFER_TOO_SMALL) {
5730                         DPROV_CTX_SINGLE(ctx) = NULL;
5731                         (void) dprov_free_context(ctx);
5732                 }
5733                 break;
5734 
5735         case DPROV_REQ_SIGN_UPDATE:
5736                 if (DPROV_CTX_P(ctx)->dc_svrfy_to_mac) {
5737                         error = crypto_mac_update(DPROV_CTX_SINGLE(ctx),
5738                             taskq_req->dr_mac_req.dr_data, NULL);
5739                 } else {
5740                         error = crypto_sign_update(DPROV_CTX_SINGLE(ctx),
5741                             taskq_req->dr_sign_req.sr_data, NULL);
5742                 }
5743                 break;
5744 
5745         case DPROV_REQ_SIGN_FINAL:
5746                 if (DPROV_CTX_P(ctx)->dc_svrfy_to_mac) {
5747                         error = crypto_mac_final(DPROV_CTX_SINGLE(ctx),
5748                             taskq_req->dr_mac_req.dr_mac, NULL);
5749                 } else {
5750                         error = crypto_sign_final(DPROV_CTX_SINGLE(ctx),
5751                             taskq_req->dr_sign_req.sr_signature, NULL);
5752                 }
5753 
5754                 if (error != CRYPTO_BUFFER_TOO_SMALL) {
5755                         DPROV_CTX_SINGLE(ctx) = NULL;
5756                         (void) dprov_free_context(ctx);
5757                 }
5758                 break;
5759 
5760         case DPROV_REQ_SIGN_ATOMIC:
5761         case DPROV_REQ_SIGN_RECOVER_ATOMIC:
5762                 /* structure assignment */
5763                 mech = *taskq_req->dr_sign_req.sr_mechanism;
5764 
5765                 mutex_enter(&softc->ds_lock);
5766                 /* get key value for secret key algorithms */
5767                 if (is_publickey_mech(mech.cm_type)) {
5768                         if ((error = dprov_key_attr_asymmetric(softc,
5769                             taskq_req->dr_sign_req.sr_session_id,
5770                             taskq_req->dr_type,
5771                             taskq_req->dr_sign_req.sr_key, &key))
5772                             != CRYPTO_SUCCESS) {
5773                                 mutex_exit(&softc->ds_lock);
5774                                 break;
5775                         }
5776                         keyp = &key;
5777                 } else {
5778                         if ((error = dprov_key_value_secret(softc,
5779                             taskq_req->dr_sign_req.sr_session_id,
5780                             taskq_req->dr_type,
5781                             taskq_req->dr_sign_req.sr_key, &key))
5782                             != CRYPTO_SUCCESS) {
5783                                 mutex_exit(&softc->ds_lock);
5784                                 break;
5785                         }
5786                         keyp = &key;
5787                 }
5788                 mutex_exit(&softc->ds_lock);
5789 
5790                 /* get the software provider for this mechanism */
5791                 if ((error = dprov_get_sw_prov(
5792                     taskq_req->dr_sign_req.sr_mechanism, &pd,
5793                     &mech.cm_type)) != CRYPTO_SUCCESS)
5794                         break;
5795 
5796                 /* Use a session id of zero since we use a software provider */
5797                 if (taskq_req->dr_type == DPROV_REQ_SIGN_ATOMIC)
5798                         error = crypto_sign_prov(pd, 0, &mech, keyp,
5799                             taskq_req->dr_sign_req.sr_data,
5800                             NULL, taskq_req->dr_sign_req.sr_signature, NULL);
5801                 else
5802                         error = crypto_sign_recover_prov(pd, 0, &mech, keyp,
5803                             taskq_req->dr_sign_req.sr_data,
5804                             NULL, taskq_req->dr_sign_req.sr_signature, NULL);
5805 
5806                 /* release provider reference */
5807                 KCF_PROV_REFRELE(pd);
5808                 break;
5809 
5810         case DPROV_REQ_SIGN_RECOVER:
5811                 error = crypto_sign_recover_single(DPROV_CTX_SINGLE(ctx),
5812                     taskq_req->dr_sign_req.sr_data,
5813                     taskq_req->dr_sign_req.sr_signature, NULL);
5814 
5815                 if (error != CRYPTO_BUFFER_TOO_SMALL) {
5816                         DPROV_CTX_SINGLE(ctx) = NULL;
5817                         (void) dprov_free_context(ctx);
5818                 }
5819                 break;
5820         }
5821 
5822         dprov_op_done(taskq_req, error);
5823         DPROV_DEBUG(D_SIGN, ("(%d) dprov_sign_task: end\n", instance));
5824 }
5825 
5826 static int
5827 emulate_verify_with_mac(crypto_ctx_t *ctx, crypto_data_t *in_mac)
5828 {
5829         int error;
5830         crypto_data_t tmpd;
5831         crypto_data_t *out_mac;
5832         char digest[SHA512_DIGEST_LENGTH];
5833 
5834         bzero(&tmpd, sizeof (crypto_data_t));
5835         tmpd.cd_format = CRYPTO_DATA_RAW;
5836         tmpd.cd_length = SHA512_DIGEST_LENGTH;
5837         tmpd.cd_raw.iov_base = digest;
5838         tmpd.cd_raw.iov_len = SHA512_DIGEST_LENGTH;
5839         out_mac = &tmpd;
5840 
5841         error = crypto_mac_final(DPROV_CTX_SINGLE(ctx), out_mac, NULL);
5842         if (in_mac->cd_length != out_mac->cd_length ||
5843             (bcmp(digest, (unsigned char *)in_mac->cd_raw.iov_base +
5844             in_mac->cd_offset, out_mac->cd_length) != 0)) {
5845                 error = CRYPTO_INVALID_MAC;
5846         }
5847 
5848         return (error);
5849 }
5850 
5851 /*
5852  * taskq dispatcher function for verify operations.
5853  */
5854 static void
5855 dprov_verify_task(dprov_req_t *taskq_req)
5856 {
5857         kcf_provider_desc_t *pd;
5858         dprov_state_t *softc;
5859         /* LINTED E_FUNC_SET_NOT_USED */
5860         int instance;
5861         int error = CRYPTO_NOT_SUPPORTED;
5862         crypto_ctx_t *ctx = taskq_req->dr_verify_req.vr_ctx;
5863         crypto_key_t key, *keyp;
5864         crypto_mechanism_t mech;
5865 
5866         DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
5867         DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_task: started\n", instance));
5868 
5869         switch (taskq_req->dr_type) {
5870 
5871         case DPROV_REQ_VERIFY_INIT:
5872         case DPROV_REQ_VERIFY_RECOVER_INIT:
5873                 /* allocate a dprov-private context */
5874                 if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
5875                     CRYPTO_SUCCESS)
5876                         break;
5877 
5878                 /* structure assignment */
5879                 mech = *taskq_req->dr_verify_req.vr_mechanism;
5880                 if (dprov_valid_mac_mech(mech.cm_type)) {
5881                         DPROV_CTX_P(ctx)->dc_svrfy_to_mac = B_TRUE;
5882                 }
5883 
5884                 mutex_enter(&softc->ds_lock);
5885                 /* get key value for secret key algorithms */
5886                 if (is_publickey_mech(mech.cm_type)) {
5887                         if ((error = dprov_key_attr_asymmetric(softc,
5888                             ctx->cc_session, taskq_req->dr_type,
5889                             taskq_req->dr_verify_req.vr_key, &key))
5890                             != CRYPTO_SUCCESS) {
5891                                 mutex_exit(&softc->ds_lock);
5892                                 break;
5893                         }
5894                         keyp = &key;
5895                 } else {
5896                         if ((error = dprov_key_value_secret(softc,
5897                             ctx->cc_session, taskq_req->dr_type,
5898                             taskq_req->dr_verify_req.vr_key, &key))
5899                             != CRYPTO_SUCCESS) {
5900                                 mutex_exit(&softc->ds_lock);
5901                                 break;
5902                         }
5903                         keyp = &key;
5904                 }
5905                 mutex_exit(&softc->ds_lock);
5906 
5907                 /* get the software provider for this mechanism */
5908                 if ((error = dprov_get_sw_prov(
5909                     taskq_req->dr_verify_req.vr_mechanism, &pd,
5910                     &mech.cm_type)) != CRYPTO_SUCCESS)
5911                         break;
5912 
5913 
5914                 if (DPROV_CTX_P(ctx)->dc_svrfy_to_mac) {
5915                         error = crypto_mac_init_prov(pd, 0, &mech, keyp, NULL,
5916                             &DPROV_CTX_SINGLE(ctx), NULL);
5917 
5918                         /* release provider reference */
5919                         KCF_PROV_REFRELE(pd);
5920                         break;
5921                 }
5922 
5923                 /* Use a session id of zero since we use a software provider */
5924                 if (taskq_req->dr_type == DPROV_REQ_VERIFY_INIT)
5925                         error = crypto_verify_init_prov(pd, 0, &mech, keyp,
5926                             NULL, &DPROV_CTX_SINGLE(ctx), NULL);
5927                 else
5928                         error = crypto_verify_recover_init_prov(pd, 0, &mech,
5929                             keyp, NULL, &DPROV_CTX_SINGLE(ctx), NULL);
5930 
5931                 /* release provider reference */
5932                 KCF_PROV_REFRELE(pd);
5933 
5934                 break;
5935 
5936         case DPROV_REQ_VERIFY:
5937                 if (DPROV_CTX_P(ctx)->dc_svrfy_to_mac) {
5938                         /* Emulate using update and final */
5939                         error = crypto_mac_update(DPROV_CTX_SINGLE(ctx),
5940                             taskq_req->dr_mac_req.dr_data, NULL);
5941                         if (error == CRYPTO_SUCCESS) {
5942                                 error = emulate_verify_with_mac(ctx,
5943                                     taskq_req->dr_mac_req.dr_mac);
5944                         }
5945                 } else {
5946                         error = crypto_verify_single(DPROV_CTX_SINGLE(ctx),
5947                             taskq_req->dr_verify_req.vr_data,
5948                             taskq_req->dr_verify_req.vr_signature, NULL);
5949                 }
5950 
5951                 ASSERT(error != CRYPTO_BUFFER_TOO_SMALL);
5952                 DPROV_CTX_SINGLE(ctx) = NULL;
5953                 (void) dprov_free_context(ctx);
5954                 break;
5955 
5956         case DPROV_REQ_VERIFY_UPDATE:
5957                 if (DPROV_CTX_P(ctx)->dc_svrfy_to_mac) {
5958                         error = crypto_mac_update(DPROV_CTX_SINGLE(ctx),
5959                             taskq_req->dr_mac_req.dr_data, NULL);
5960                 } else {
5961                         error = crypto_verify_update(DPROV_CTX_SINGLE(ctx),
5962                             taskq_req->dr_verify_req.vr_data, NULL);
5963                 }
5964                 break;
5965 
5966         case DPROV_REQ_VERIFY_FINAL:
5967                 if (DPROV_CTX_P(ctx)->dc_svrfy_to_mac) {
5968                         error = emulate_verify_with_mac(ctx,
5969                             taskq_req->dr_mac_req.dr_mac);
5970                 } else {
5971                         error = crypto_verify_final(DPROV_CTX_SINGLE(ctx),
5972                             taskq_req->dr_verify_req.vr_signature, NULL);
5973                 }
5974 
5975                 ASSERT(error != CRYPTO_BUFFER_TOO_SMALL);
5976                 DPROV_CTX_SINGLE(ctx) = NULL;
5977                 (void) dprov_free_context(ctx);
5978                 break;
5979 
5980         case DPROV_REQ_VERIFY_ATOMIC:
5981         case DPROV_REQ_VERIFY_RECOVER_ATOMIC:
5982                 /* structure assignment */
5983                 mech = *taskq_req->dr_verify_req.vr_mechanism;
5984 
5985                 mutex_enter(&softc->ds_lock);
5986                 /* get key value for secret key algorithms */
5987                 if (is_publickey_mech(mech.cm_type)) {
5988                         if ((error = dprov_key_attr_asymmetric(softc,
5989                             taskq_req->dr_verify_req.vr_session_id,
5990                             taskq_req->dr_type,
5991                             taskq_req->dr_verify_req.vr_key, &key))
5992                             != CRYPTO_SUCCESS) {
5993                                 mutex_exit(&softc->ds_lock);
5994                                 break;
5995                         }
5996                         keyp = &key;
5997                 } else {
5998                         if ((error = dprov_key_value_secret(softc,
5999                             taskq_req->dr_verify_req.vr_session_id,
6000                             taskq_req->dr_type,
6001                             taskq_req->dr_verify_req.vr_key, &key))
6002                             != CRYPTO_SUCCESS) {
6003                                 mutex_exit(&softc->ds_lock);
6004                                 break;
6005                         }
6006                         keyp = &key;
6007                 }
6008                 mutex_exit(&softc->ds_lock);
6009 
6010                 /* get the software provider for this mechanism */
6011                 if ((error = dprov_get_sw_prov(
6012                     taskq_req->dr_verify_req.vr_mechanism, &pd,
6013                     &mech.cm_type)) != CRYPTO_SUCCESS)
6014                         break;
6015 
6016                 /* Use a session id of zero since we use a software provider */
6017                 if (taskq_req->dr_type == DPROV_REQ_VERIFY_ATOMIC)
6018                         error = crypto_verify_prov(pd, 0, &mech, keyp,
6019                             taskq_req->dr_verify_req.vr_data,
6020                             NULL, taskq_req->dr_verify_req.vr_signature, NULL);
6021                 else
6022                         /*
6023                          * crypto_verify_recover_prov() has different argument
6024                          * order than crypto_verify_prov().
6025                          */
6026                         error = crypto_verify_recover_prov(pd, 0, &mech, keyp,
6027                             taskq_req->dr_verify_req.vr_signature,
6028                             NULL, taskq_req->dr_verify_req.vr_data, NULL);
6029 
6030                 /* release provider reference */
6031                 KCF_PROV_REFRELE(pd);
6032                 break;
6033 
6034         case DPROV_REQ_VERIFY_RECOVER:
6035                 /*
6036                  * crypto_verify_recover_single() has different argument
6037                  * order than crypto_verify_single().
6038                  */
6039                 error = crypto_verify_recover_single(DPROV_CTX_SINGLE(ctx),
6040                     taskq_req->dr_verify_req.vr_signature,
6041                     taskq_req->dr_verify_req.vr_data, NULL);
6042 
6043                 if (error != CRYPTO_BUFFER_TOO_SMALL) {
6044                         DPROV_CTX_SINGLE(ctx) = NULL;
6045                         (void) dprov_free_context(ctx);
6046                 }
6047                 break;
6048         }
6049 
6050         dprov_op_done(taskq_req, error);
6051         DPROV_DEBUG(D_VERIFY, ("(%d) dprov_verify_task: end\n", instance));
6052 }
6053 
6054 /*
6055  * taskq dispatcher function for dual operations.
6056  */
6057 static void
6058 dprov_dual_task(dprov_req_t *taskq_req)
6059 {
6060         dprov_state_t *softc;
6061         /* LINTED E_FUNC_SET_NOT_USED */
6062         int instance;
6063         int error = CRYPTO_NOT_SUPPORTED;
6064         crypto_ctx_t *signverify_ctx = taskq_req->dr_dual_req.dr_signverify_ctx;
6065         crypto_ctx_t *cipher_ctx = taskq_req->dr_dual_req.dr_cipher_ctx;
6066 
6067         DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
6068         DPROV_DEBUG(D_DUAL, ("(%d) dprov_dual_task: started\n", instance));
6069 
6070         switch (taskq_req->dr_type) {
6071 
6072         case DPROV_REQ_DIGEST_ENCRYPT_UPDATE:
6073                 error = crypto_digest_encrypt_update(
6074                     DPROV_CTX_SINGLE(signverify_ctx),
6075                     DPROV_CTX_SINGLE(cipher_ctx),
6076                     taskq_req->dr_dual_req.dr_plaintext,
6077                     taskq_req->dr_dual_req.dr_ciphertext, NULL);
6078                 break;
6079 
6080         case DPROV_REQ_DECRYPT_DIGEST_UPDATE:
6081                 error = crypto_decrypt_digest_update(
6082                     DPROV_CTX_SINGLE(cipher_ctx),
6083                     DPROV_CTX_SINGLE(signverify_ctx),
6084                     taskq_req->dr_dual_req.dr_ciphertext,
6085                     taskq_req->dr_dual_req.dr_plaintext, NULL);
6086                 break;
6087 
6088         case DPROV_REQ_SIGN_ENCRYPT_UPDATE:
6089                 error = crypto_sign_encrypt_update(
6090                     DPROV_CTX_SINGLE(signverify_ctx),
6091                     DPROV_CTX_SINGLE(cipher_ctx),
6092                     taskq_req->dr_dual_req.dr_plaintext,
6093                     taskq_req->dr_dual_req.dr_ciphertext, NULL);
6094                 break;
6095 
6096         case DPROV_REQ_DECRYPT_VERIFY_UPDATE:
6097                 error = crypto_decrypt_verify_update(
6098                     DPROV_CTX_SINGLE(cipher_ctx),
6099                     DPROV_CTX_SINGLE(signverify_ctx),
6100                     taskq_req->dr_dual_req.dr_ciphertext,
6101                     taskq_req->dr_dual_req.dr_plaintext, NULL);
6102                 break;
6103         }
6104 
6105         dprov_op_done(taskq_req, error);
6106         DPROV_DEBUG(D_DUAL, ("(%d) dprov_dual_task: end\n", instance));
6107 }
6108 
6109 /*
6110  * taskq dispatcher function for cipher operations.
6111  */
6112 static void
6113 dprov_cipher_task(dprov_req_t *taskq_req)
6114 {
6115         kcf_provider_desc_t *pd;
6116         dprov_state_t *softc;
6117         /* LINTED E_FUNC_SET_NOT_USED */
6118         int instance;
6119         int error = CRYPTO_NOT_SUPPORTED;
6120         crypto_ctx_t *ctx = taskq_req->dr_cipher_req.dr_ctx;
6121         crypto_key_t key, *keyp;
6122         crypto_mechanism_t mech;
6123 
6124         DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
6125         DPROV_DEBUG(D_CIPHER, ("(%d) dprov_cipher_task: started\n", instance));
6126 
6127         switch (taskq_req->dr_type) {
6128 
6129         case DPROV_REQ_ENCRYPT_INIT:
6130         case DPROV_REQ_DECRYPT_INIT:
6131                 /* allocate a dprov-private context */
6132                 if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
6133                     CRYPTO_SUCCESS)
6134                         break;
6135 
6136                 /* structure assignment */
6137                 mech = *taskq_req->dr_cipher_req.dr_mechanism;
6138 
6139                 mutex_enter(&softc->ds_lock);
6140                 /* get key value for secret key algorithms */
6141                 if (is_publickey_mech(mech.cm_type)) {
6142                         if ((error = dprov_key_attr_asymmetric(softc,
6143                             ctx->cc_session, taskq_req->dr_type,
6144                             taskq_req->dr_cipher_req.dr_key, &key))
6145                             != CRYPTO_SUCCESS) {
6146                                 mutex_exit(&softc->ds_lock);
6147                                 break;
6148                         }
6149                         keyp = &key;
6150                 } else {
6151                         if ((error = dprov_key_value_secret(softc,
6152                             ctx->cc_session, taskq_req->dr_type,
6153                             taskq_req->dr_cipher_req.dr_key, &key))
6154                             != CRYPTO_SUCCESS) {
6155                                 mutex_exit(&softc->ds_lock);
6156                                 break;
6157                         }
6158                         keyp = &key;
6159                 }
6160                 mutex_exit(&softc->ds_lock);
6161 
6162                 /* get the software provider for this mechanism */
6163                 if ((error = dprov_get_sw_prov(
6164                     taskq_req->dr_cipher_req.dr_mechanism, &pd,
6165                     &mech.cm_type)) != CRYPTO_SUCCESS)
6166                         break;
6167 
6168                 /* Use a session id of zero since we use a software provider */
6169                 if (taskq_req->dr_type == DPROV_REQ_ENCRYPT_INIT)
6170                         error = crypto_encrypt_init_prov(pd, 0, &mech, keyp,
6171                             NULL, &DPROV_CTX_SINGLE(ctx), NULL);
6172                 else
6173                         error = crypto_decrypt_init_prov(pd, 0, &mech, keyp,
6174                             NULL, &DPROV_CTX_SINGLE(ctx), NULL);
6175 
6176                 if (ctx->cc_flags & CRYPTO_INIT_OPSTATE) {
6177                         crypto_ctx_t *lctx =
6178                             (crypto_ctx_t *)(DPROV_CTX_SINGLE(ctx));
6179 
6180                         ctx->cc_opstate = lctx->cc_provider_private;
6181                         ctx->cc_flags |= CRYPTO_USE_OPSTATE;
6182                 }
6183 
6184                 /* release provider reference */
6185                 KCF_PROV_REFRELE(pd);
6186                 break;
6187 
6188         case DPROV_REQ_ENCRYPT:
6189                 error = crypto_encrypt_single(DPROV_CTX_SINGLE(ctx),
6190                     taskq_req->dr_cipher_req.dr_plaintext,
6191                     taskq_req->dr_cipher_req.dr_ciphertext, NULL);
6192 
6193                 if (error != CRYPTO_BUFFER_TOO_SMALL) {
6194                         DPROV_CTX_SINGLE(ctx) = NULL;
6195                         (void) dprov_free_context(ctx);
6196                 }
6197                 break;
6198 
6199         case DPROV_REQ_DECRYPT:
6200                 error = crypto_decrypt_single(DPROV_CTX_SINGLE(ctx),
6201                     taskq_req->dr_cipher_req.dr_ciphertext,
6202                     taskq_req->dr_cipher_req.dr_plaintext, NULL);
6203 
6204                 if (error != CRYPTO_BUFFER_TOO_SMALL) {
6205                         DPROV_CTX_SINGLE(ctx) = NULL;
6206                         (void) dprov_free_context(ctx);
6207                 }
6208                 break;
6209 
6210         case DPROV_REQ_ENCRYPT_UPDATE:
6211                 ASSERT(!(ctx->cc_flags & CRYPTO_INIT_OPSTATE) ||
6212                     (ctx->cc_flags & CRYPTO_USE_OPSTATE));
6213                 error = crypto_encrypt_update(DPROV_CTX_SINGLE(ctx),
6214                     taskq_req->dr_cipher_req.dr_plaintext,
6215                     taskq_req->dr_cipher_req.dr_ciphertext, NULL);
6216                 break;
6217 
6218         case DPROV_REQ_DECRYPT_UPDATE:
6219                 ASSERT(!(ctx->cc_flags & CRYPTO_INIT_OPSTATE) ||
6220                     (ctx->cc_flags & CRYPTO_USE_OPSTATE));
6221                 error = crypto_decrypt_update(DPROV_CTX_SINGLE(ctx),
6222                     taskq_req->dr_cipher_req.dr_ciphertext,
6223                     taskq_req->dr_cipher_req.dr_plaintext, NULL);
6224                 break;
6225 
6226         case DPROV_REQ_ENCRYPT_FINAL:
6227                 error = crypto_encrypt_final(DPROV_CTX_SINGLE(ctx),
6228                     taskq_req->dr_cipher_req.dr_ciphertext, NULL);
6229                 if (error != CRYPTO_BUFFER_TOO_SMALL) {
6230                         DPROV_CTX_SINGLE(ctx) = NULL;
6231                         (void) dprov_free_context(ctx);
6232                 }
6233                 break;
6234 
6235         case DPROV_REQ_DECRYPT_FINAL:
6236                 error = crypto_decrypt_final(DPROV_CTX_SINGLE(ctx),
6237                     taskq_req->dr_cipher_req.dr_plaintext, NULL);
6238                 if (error != CRYPTO_BUFFER_TOO_SMALL) {
6239                         DPROV_CTX_SINGLE(ctx) = NULL;
6240                         (void) dprov_free_context(ctx);
6241                 }
6242                 break;
6243 
6244         case DPROV_REQ_ENCRYPT_ATOMIC:
6245         case DPROV_REQ_DECRYPT_ATOMIC:
6246                 /* structure assignment */
6247                 mech = *taskq_req->dr_cipher_req.dr_mechanism;
6248 
6249                 mutex_enter(&softc->ds_lock);
6250                 /* get key value for secret key algorithms */
6251                 if (is_publickey_mech(mech.cm_type)) {
6252                         if ((error = dprov_key_attr_asymmetric(softc,
6253                             taskq_req->dr_cipher_req.dr_session_id,
6254                             taskq_req->dr_type,
6255                             taskq_req->dr_cipher_req.dr_key,
6256                             &key)) != CRYPTO_SUCCESS) {
6257                                 mutex_exit(&softc->ds_lock);
6258                                 break;
6259                         }
6260                         keyp = &key;
6261                 } else {
6262                         if ((error = dprov_key_value_secret(softc,
6263                             taskq_req->dr_cipher_req.dr_session_id,
6264                             taskq_req->dr_type, taskq_req->dr_cipher_req.dr_key,
6265                             &key))
6266                             != CRYPTO_SUCCESS) {
6267                                 mutex_exit(&softc->ds_lock);
6268                                 break;
6269                         }
6270                         keyp = &key;
6271                 }
6272                 mutex_exit(&softc->ds_lock);
6273 
6274                 /* get the software provider for this mechanism */
6275                 if ((error = dprov_get_sw_prov(
6276                     taskq_req->dr_cipher_req.dr_mechanism, &pd,
6277                     &mech.cm_type)) != CRYPTO_SUCCESS)
6278                         break;
6279 
6280                 /* use a session id of zero since we use a software provider */
6281                 if (taskq_req->dr_type == DPROV_REQ_ENCRYPT_ATOMIC)
6282                         error = crypto_encrypt_prov(pd, 0, &mech,
6283                             taskq_req->dr_cipher_req.dr_plaintext,
6284                             keyp, NULL,
6285                             taskq_req->dr_cipher_req.dr_ciphertext, NULL);
6286                 else
6287                         error = crypto_decrypt_prov(pd, 0, &mech,
6288                             taskq_req->dr_cipher_req.dr_ciphertext,
6289                             keyp, NULL,
6290                             taskq_req->dr_cipher_req.dr_plaintext, NULL);
6291 
6292                 /* release provider reference */
6293                 KCF_PROV_REFRELE(pd);
6294 
6295                 break;
6296         }
6297 
6298         dprov_op_done(taskq_req, error);
6299         DPROV_DEBUG(D_MAC, ("(%d) dprov_mac_task: end\n", instance));
6300 }
6301 
6302 /*
6303  * Helper function for the cipher/mac dual operation taskq dispatch
6304  * function. Initialize the cipher and mac key values and find the
6305  * providers that can process the request for the specified mechanisms.
6306  */
6307 static int
6308 dprov_cipher_mac_key_pd(dprov_state_t *softc, crypto_session_id_t sid,
6309     dprov_req_t *taskq_req, crypto_key_t *cipher_key, crypto_key_t *mac_key,
6310     kcf_provider_desc_t **cipher_pd, kcf_provider_desc_t **mac_pd,
6311     crypto_mech_type_t *cipher_mech_type, crypto_mech_type_t *mac_mech_type)
6312 {
6313         int error;
6314 
6315         /* get the cipher key value */
6316         mutex_enter(&softc->ds_lock);
6317         error = dprov_key_value_secret(softc, sid, DPROV_REQ_ENCRYPT_ATOMIC,
6318             taskq_req->dr_cipher_mac_req.mr_cipher_key, cipher_key);
6319         if (error != CRYPTO_SUCCESS) {
6320                 mutex_exit(&softc->ds_lock);
6321                 return (error);
6322         }
6323 
6324         /* get the mac key value */
6325         error = dprov_key_value_secret(softc, sid, DPROV_REQ_MAC_ATOMIC,
6326             taskq_req->dr_cipher_mac_req.mr_mac_key, mac_key);
6327         mutex_exit(&softc->ds_lock);
6328         if (error != CRYPTO_SUCCESS)
6329                 return (error);
6330 
6331         /* get the SW provider to perform the cipher operation */
6332         if ((error = dprov_get_sw_prov(
6333             taskq_req->dr_cipher_mac_req.mr_cipher_mech, cipher_pd,
6334             cipher_mech_type)) != CRYPTO_SUCCESS)
6335                 return (error);
6336 
6337         /* get the SW provider to perform the mac operation */
6338         error = dprov_get_sw_prov(taskq_req->dr_cipher_mac_req.mr_mac_mech,
6339             mac_pd, mac_mech_type);
6340 
6341         return (error);
6342 }
6343 
6344 /*
6345  * taskq dispatcher function for cipher/mac dual operations.
6346  */
6347 static void
6348 dprov_cipher_mac_task(dprov_req_t *taskq_req)
6349 {
6350         dprov_state_t *softc;
6351         /* LINTED E_FUNC_SET_NOT_USED */
6352         int instance;
6353         int error = CRYPTO_NOT_SUPPORTED;
6354         crypto_ctx_t *ctx = taskq_req->dr_cipher_mac_req.mr_ctx;
6355         kcf_provider_desc_t *cipher_pd;
6356         kcf_provider_desc_t *mac_pd;
6357         crypto_key_t cipher_key;
6358         crypto_key_t mac_key;
6359         crypto_dual_data_t *dual_data =
6360             taskq_req->dr_cipher_mac_req.mr_dual_data;
6361         crypto_data_t cipher_data;
6362         crypto_data_t mac_data;
6363         crypto_mechanism_t cipher_mech, mac_mech;
6364         crypto_session_id_t session_id;
6365 
6366         DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
6367         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_cipher_mac_task: started\n",
6368             instance));
6369 
6370         switch (taskq_req->dr_type) {
6371         case DPROV_REQ_ENCRYPT_MAC_INIT:
6372         case DPROV_REQ_MAC_DECRYPT_INIT:
6373                 /* structure assignment */
6374                 cipher_mech = *taskq_req->dr_cipher_mac_req.mr_cipher_mech;
6375                 mac_mech = *taskq_req->dr_cipher_mac_req.mr_mac_mech;
6376 
6377                 /* get the keys values and providers to use for operations */
6378                 if ((error = dprov_cipher_mac_key_pd(softc, ctx->cc_session,
6379                     taskq_req, &cipher_key, &mac_key, &cipher_pd, &mac_pd,
6380                     &cipher_mech.cm_type, &mac_mech.cm_type)) != CRYPTO_SUCCESS)
6381                         break;
6382 
6383                 /* allocate a dprov-private context */
6384                 if ((error = dprov_alloc_context(taskq_req->dr_type, ctx)) !=
6385                     CRYPTO_SUCCESS)
6386                         break;
6387 
6388                 if (taskq_req->dr_type == DPROV_REQ_ENCRYPT_MAC_INIT)
6389                         /* do the encryption initialization */
6390                         error = crypto_encrypt_init_prov(cipher_pd, 0,
6391                             &cipher_mech, &cipher_key, NULL,
6392                             &DPROV_CTX_DUAL_CIPHER(ctx), NULL);
6393                 else
6394                         /* do the decryption initialization */
6395                         error = crypto_decrypt_init_prov(cipher_pd, 0,
6396                             &cipher_mech, &cipher_key, NULL,
6397                             &DPROV_CTX_DUAL_CIPHER(ctx), NULL);
6398                 if (error != CRYPTO_SUCCESS)
6399                         break;
6400 
6401                 /* do the mac initialization */
6402                 if ((error = crypto_mac_init_prov(mac_pd, 0,
6403                     &mac_mech, &mac_key, NULL, &DPROV_CTX_DUAL_MAC(ctx),
6404                     NULL)) != CRYPTO_SUCCESS)
6405                         break;
6406 
6407                 /* release references to providers */
6408                 KCF_PROV_REFRELE(cipher_pd);
6409                 KCF_PROV_REFRELE(mac_pd);
6410 
6411                 break;
6412 
6413         case DPROV_REQ_ENCRYPT_MAC: {
6414                 size_t encrypted;
6415                 boolean_t inplace;
6416 
6417                 crypto_data_t *plaintext_tmp, *ciphertext_tmp;
6418 
6419                 cipher_data = *((crypto_data_t *)dual_data);
6420 
6421                 /* do an encrypt update */
6422                 inplace = (taskq_req->dr_cipher_mac_req.mr_data == NULL);
6423                 if (inplace) {
6424                         plaintext_tmp = &cipher_data;
6425                         ciphertext_tmp = NULL;
6426                 } else {
6427                         plaintext_tmp = taskq_req->dr_cipher_mac_req.mr_data;
6428                         ciphertext_tmp = &cipher_data;
6429                 }
6430                 if ((error = crypto_encrypt_update(DPROV_CTX_DUAL_CIPHER(ctx),
6431                     plaintext_tmp, ciphertext_tmp, NULL)) != CRYPTO_SUCCESS)
6432                         break;
6433 
6434                 /* do an encrypt final */
6435                 encrypted = cipher_data.cd_length;
6436 
6437                 cipher_data.cd_offset += encrypted;
6438                 cipher_data.cd_length = dual_data->dd_len1 - encrypted;
6439 
6440                 if ((error = crypto_encrypt_final(DPROV_CTX_DUAL_CIPHER(ctx),
6441                     &cipher_data, NULL)) != CRYPTO_SUCCESS)
6442                         break;
6443 
6444                 /*
6445                  * Do a mac update on the resulting ciphertext, but with no
6446                  * more bytes than specified by dual_data, and starting at
6447                  * offset specified by dual_data. For in-place operations,
6448                  * we use the length specified by the dual_data.
6449                  */
6450                 mac_data = cipher_data;
6451                 mac_data.cd_offset = dual_data->dd_offset2;
6452                 mac_data.cd_length = dual_data->dd_len2;
6453                 if ((error = crypto_mac_update(DPROV_CTX_DUAL_MAC(ctx),
6454                     &mac_data, NULL)) != CRYPTO_SUCCESS)
6455                         break;
6456 
6457                 /* do a mac final */
6458                 error = crypto_mac_final(DPROV_CTX_DUAL_MAC(ctx),
6459                     taskq_req->dr_cipher_mac_req.mr_mac, NULL);
6460 
6461                 /* Set the total size of the ciphertext, when successful */
6462                 if (error == CRYPTO_SUCCESS)
6463                         dual_data->dd_len1 = encrypted + cipher_data.cd_length;
6464 
6465                 if (error != CRYPTO_BUFFER_TOO_SMALL) {
6466                         DPROV_CTX_DUAL_CIPHER(ctx) = NULL;
6467                         DPROV_CTX_DUAL_MAC(ctx) = NULL;
6468                         (void) dprov_free_context(ctx);
6469                 }
6470                 break;
6471         }
6472 
6473         case DPROV_REQ_ENCRYPT_MAC_UPDATE: {
6474                 crypto_data_t *plaintext_tmp, *ciphertext_tmp;
6475                 size_t encrypted;
6476                 ssize_t maclen;
6477                 boolean_t inplace;
6478 
6479                 cipher_data = *((crypto_data_t *)dual_data);
6480 
6481                 /* do an encrypt update */
6482                 inplace = (taskq_req->dr_cipher_mac_req.mr_data == NULL);
6483                 if (inplace) {
6484                         plaintext_tmp = &cipher_data;
6485                         ciphertext_tmp = NULL;
6486                 } else {
6487                         plaintext_tmp = taskq_req->dr_cipher_mac_req.mr_data;
6488                         ciphertext_tmp = &cipher_data;
6489                 }
6490                 if ((error = crypto_encrypt_update(DPROV_CTX_DUAL_CIPHER(ctx),
6491                     plaintext_tmp, ciphertext_tmp, NULL)) != CRYPTO_SUCCESS)
6492                         break;
6493 
6494                 encrypted = cipher_data.cd_length;
6495 
6496                 /*
6497                  * Do a mac update on the resulting ciphertext, but with no
6498                  * more bytes than specified by dual_data, and starting at
6499                  * offset specified by dual_data. For in-place operations,
6500                  * we use the length specified by the dual_data.
6501                  * There is an edge case, when the encryption step produced
6502                  * zero bytes in the ciphertext. Only the portion between
6503                  * offset2 and offset1 is then thrown in the MAC mix.
6504                  */
6505                 maclen = dual_data->dd_offset1 - dual_data->dd_offset2 +
6506                     encrypted;
6507                 if (maclen > 0) {
6508                         mac_data = cipher_data;
6509                         mac_data.cd_offset = dual_data->dd_offset2;
6510                         mac_data.cd_length = min(dual_data->dd_len2, maclen);
6511                         if ((error = crypto_mac_update(DPROV_CTX_DUAL_MAC(ctx),
6512                             &mac_data, NULL)) != CRYPTO_SUCCESS)
6513                                 break;
6514                 }
6515                 /* Set the total size of the ciphertext, when successful */
6516                 if (error == CRYPTO_SUCCESS)
6517                         dual_data->dd_len1 = encrypted;
6518 
6519                 break;
6520         }
6521 
6522         case DPROV_REQ_ENCRYPT_MAC_FINAL:
6523                 cipher_data = *((crypto_data_t *)dual_data);
6524 
6525                 /* do an encrypt final */
6526                 if ((error = crypto_encrypt_final(DPROV_CTX_DUAL_CIPHER(ctx),
6527                     taskq_req->dr_cipher_mac_req.mr_data == NULL ?
6528                     &cipher_data : taskq_req->dr_cipher_mac_req.mr_data,
6529                     NULL)) != CRYPTO_SUCCESS)
6530                         break;
6531 
6532                 /*
6533                  * If ciphertext length is different from zero, do a mac
6534                  * update on it. This does not apply to in-place since we
6535                  * do not allow partial updates, hence no final residual.
6536                  */
6537                 if (taskq_req->dr_cipher_mac_req.mr_data != NULL &&
6538                     taskq_req->dr_cipher_mac_req.mr_data->cd_length > 0)
6539                         if ((error = crypto_mac_update(DPROV_CTX_DUAL_MAC(ctx),
6540                             taskq_req->dr_cipher_mac_req.mr_data, NULL)) !=
6541                             CRYPTO_SUCCESS)
6542                                 break;
6543 
6544                 /* do a mac final */
6545                 error = crypto_mac_final(DPROV_CTX_DUAL_MAC(ctx),
6546                     taskq_req->dr_cipher_mac_req.mr_mac, NULL);
6547 
6548                 if (error != CRYPTO_BUFFER_TOO_SMALL) {
6549                         DPROV_CTX_DUAL_CIPHER(ctx) = NULL;
6550                         DPROV_CTX_DUAL_MAC(ctx) = NULL;
6551                         (void) dprov_free_context(ctx);
6552                 }
6553                 break;
6554 
6555         case DPROV_REQ_ENCRYPT_MAC_ATOMIC: {
6556                 crypto_data_t *plaintext_tmp, *ciphertext_tmp;
6557                 boolean_t inplace;
6558 
6559                 cipher_data = *((crypto_data_t *)dual_data);
6560 
6561                 /* do an encrypt atomic */
6562                 inplace = (taskq_req->dr_cipher_mac_req.mr_data == NULL);
6563                 if (inplace) {
6564                         plaintext_tmp = &cipher_data;
6565                         ciphertext_tmp = NULL;
6566                 } else {
6567                         plaintext_tmp = taskq_req->dr_cipher_mac_req.mr_data;
6568                         ciphertext_tmp = &cipher_data;
6569                 }
6570 
6571                 /* structure assignment */
6572                 cipher_mech = *taskq_req->dr_cipher_mac_req.mr_cipher_mech;
6573                 mac_mech = *taskq_req->dr_cipher_mac_req.mr_mac_mech;
6574                 session_id = taskq_req->dr_cipher_mac_req.mr_session_id;
6575 
6576                 /* get the keys values and providers to use for operations */
6577                 if ((error = dprov_cipher_mac_key_pd(softc, session_id,
6578                     taskq_req, &cipher_key, &mac_key, &cipher_pd, &mac_pd,
6579                     &cipher_mech.cm_type, &mac_mech.cm_type)) !=
6580                     CRYPTO_SUCCESS)
6581                         break;
6582 
6583                 /* do the atomic encrypt */
6584                 if ((error = crypto_encrypt_prov(cipher_pd, 0,
6585                     &cipher_mech, plaintext_tmp, &cipher_key, NULL,
6586                     ciphertext_tmp, NULL)) != CRYPTO_SUCCESS)
6587                         break;
6588 
6589                 /* do the atomic mac */
6590                 mac_data = cipher_data;
6591                 mac_data.cd_length = dual_data->dd_len2;
6592                 mac_data.cd_offset = dual_data->dd_offset2;
6593                 error = crypto_mac_prov(mac_pd, 0, &mac_mech, &mac_data,
6594                     &mac_key, NULL, taskq_req->dr_cipher_mac_req.mr_mac, NULL);
6595 
6596                 dual_data->dd_len1 = cipher_data.cd_length;
6597 
6598                 break;
6599         }
6600 
6601         case DPROV_REQ_MAC_DECRYPT: {
6602                 uint_t decrypted;
6603                 crypto_data_t plaintext_tmp;
6604 
6605                 cipher_data = *((crypto_data_t *)dual_data);
6606 
6607                 /* do a mac update and final on the ciphertext */
6608                 if ((error = crypto_mac_update(DPROV_CTX_DUAL_MAC(ctx),
6609                     &mac_data, NULL)) != CRYPTO_SUCCESS)
6610                         break;
6611 
6612                 /* do a mac final */
6613                 if ((error = crypto_mac_final(DPROV_CTX_DUAL_MAC(ctx),
6614                     taskq_req->dr_cipher_mac_req.mr_mac, NULL)) !=
6615                     CRYPTO_SUCCESS)
6616                         break;
6617 
6618                 /* do an decrypt update */
6619                 cipher_data = mac_data;
6620                 cipher_data.cd_length = dual_data->dd_len2;
6621                 cipher_data.cd_offset = dual_data->dd_offset2;
6622                 if (taskq_req->dr_cipher_mac_req.mr_data == NULL)
6623                         /* in-place */
6624                         plaintext_tmp = cipher_data;
6625                 else
6626                         plaintext_tmp = *taskq_req->dr_cipher_mac_req.mr_data;
6627 
6628                 if ((error = crypto_decrypt_update(DPROV_CTX_DUAL_CIPHER(ctx),
6629                     &cipher_data, taskq_req->dr_cipher_mac_req.mr_data,
6630                     NULL)) != CRYPTO_SUCCESS)
6631                         break;
6632 
6633                 /* do an decrypt final */
6634                 if (taskq_req->dr_cipher_mac_req.mr_data == NULL)
6635                         /* in-place, everything must have been decrypted */
6636                         decrypted = cipher_data.cd_length;
6637                 else
6638                         decrypted =
6639                             taskq_req->dr_cipher_mac_req.mr_data->cd_length;
6640                 plaintext_tmp.cd_offset += decrypted;
6641                 plaintext_tmp.cd_length -= decrypted;
6642 
6643                 error = crypto_decrypt_final(DPROV_CTX_DUAL_CIPHER(ctx),
6644                     &plaintext_tmp, NULL);
6645                 if (taskq_req->dr_cipher_mac_req.mr_data != NULL)
6646                         taskq_req->dr_cipher_mac_req.mr_data->cd_length +=
6647                             plaintext_tmp.cd_length;
6648 
6649                 if (error != CRYPTO_BUFFER_TOO_SMALL) {
6650                         DPROV_CTX_DUAL_MAC(ctx) = NULL;
6651                         DPROV_CTX_DUAL_CIPHER(ctx) = NULL;
6652                         (void) dprov_free_context(ctx);
6653                 }
6654                 break;
6655         }
6656 
6657         case DPROV_REQ_MAC_DECRYPT_UPDATE:
6658                 cipher_data = *((crypto_data_t *)dual_data);
6659 
6660                 /* do mac update */
6661                 if ((error = crypto_mac_update(DPROV_CTX_DUAL_MAC(ctx),
6662                     &cipher_data, NULL)) != CRYPTO_SUCCESS)
6663                         break;
6664 
6665                 /* do a decrypt update */
6666                 cipher_data.cd_length = dual_data->dd_len2;
6667                 cipher_data.cd_offset = dual_data->dd_offset2;
6668                 error = crypto_decrypt_update(DPROV_CTX_DUAL_CIPHER(ctx),
6669                     &cipher_data, taskq_req->dr_cipher_mac_req.mr_data, NULL);
6670 
6671                 break;
6672 
6673         case DPROV_REQ_MAC_DECRYPT_FINAL:
6674                 /* do a mac final */
6675                 if ((error = crypto_mac_final(DPROV_CTX_DUAL_MAC(ctx),
6676                     taskq_req->dr_cipher_mac_req.mr_mac, NULL)) !=
6677                     CRYPTO_SUCCESS)
6678                         break;
6679 
6680                 /* do a decrypt final */
6681                 error = crypto_decrypt_final(DPROV_CTX_DUAL_CIPHER(ctx),
6682                     taskq_req->dr_cipher_mac_req.mr_data, NULL);
6683 
6684                 if (error != CRYPTO_BUFFER_TOO_SMALL) {
6685                         DPROV_CTX_DUAL_MAC(ctx) = NULL;
6686                         DPROV_CTX_DUAL_CIPHER(ctx) = NULL;
6687                         (void) dprov_free_context(ctx);
6688                 }
6689                 break;
6690 
6691         case DPROV_REQ_MAC_DECRYPT_ATOMIC:
6692         case DPROV_REQ_MAC_VERIFY_DECRYPT_ATOMIC:
6693                 cipher_data = *((crypto_data_t *)dual_data);
6694 
6695                 /* structure assignment */
6696                 cipher_mech = *taskq_req->dr_cipher_mac_req.mr_cipher_mech;
6697                 mac_mech = *taskq_req->dr_cipher_mac_req.mr_mac_mech;
6698                 session_id = taskq_req->dr_cipher_mac_req.mr_session_id;
6699 
6700                 /* get the keys values and providers to use for operations */
6701                 if ((error = dprov_cipher_mac_key_pd(softc, session_id,
6702                     taskq_req, &cipher_key, &mac_key, &cipher_pd, &mac_pd,
6703                     &cipher_mech.cm_type, &mac_mech.cm_type)) != CRYPTO_SUCCESS)
6704                         break;
6705 
6706                 /* do the atomic mac */
6707                 if (taskq_req->dr_type == DPROV_REQ_MAC_DECRYPT_ATOMIC)
6708                         error = crypto_mac_prov(mac_pd, 0, &mac_mech,
6709                             &cipher_data, &mac_key, NULL,
6710                             taskq_req->dr_cipher_mac_req.mr_mac, NULL);
6711                 else
6712                         /* DPROV_REQ_MAC_VERIFY_DECRYPT_ATOMIC */
6713                         error = crypto_mac_verify_prov(mac_pd, 0, &mac_mech,
6714                             &cipher_data, &mac_key, NULL,
6715                             taskq_req->dr_cipher_mac_req.mr_mac, NULL);
6716 
6717                 if (error != CRYPTO_SUCCESS)
6718                         break;
6719 
6720                 /* do the atomic decrypt */
6721                 cipher_data.cd_length = dual_data->dd_len2;
6722                 cipher_data.cd_offset = dual_data->dd_offset2;
6723                 error = crypto_decrypt_prov(cipher_pd, 0, &cipher_mech,
6724                     &cipher_data, &cipher_key, NULL,
6725                     taskq_req->dr_cipher_mac_req.mr_data, NULL);
6726 
6727                 break;
6728         }
6729 
6730         dprov_op_done(taskq_req, error);
6731         DPROV_DEBUG(D_CIPHER_MAC, ("(%d) dprov_cipher_mac_task: end\n",
6732             instance));
6733 }
6734 
6735 /*
6736  * taskq dispatcher function for random number generation.
6737  */
6738 static void
6739 dprov_random_task(dprov_req_t *taskq_req)
6740 {
6741         dprov_state_t *softc;
6742         /* LINTED E_FUNC_SET_NOT_USED */
6743         int instance;
6744         int error = CRYPTO_SUCCESS;
6745 
6746         DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
6747         DPROV_DEBUG(D_RANDOM, ("(%d) dprov_random_task: started\n", instance));
6748 
6749         mutex_enter(&softc->ds_lock);
6750 
6751         switch (taskq_req->dr_type) {
6752 
6753         DPROV_REQ_RANDOM_SEED:
6754                 /*
6755                  * Since we don't really generate random numbers
6756                  * nothing to do.
6757                  */
6758                 break;
6759 
6760         case DPROV_REQ_RANDOM_GENERATE: {
6761                 uint_t i;
6762                 uchar_t c = 0;
6763 
6764                 /*
6765                  * We don't generate random numbers so that the result
6766                  * of the operation can be checked during testing.
6767                  */
6768 
6769                 for (i = 0; i < taskq_req->dr_random_req.rr_len; i++)
6770                         taskq_req->dr_random_req.rr_buf[i] = c++;
6771 
6772                 break;
6773         }
6774         }
6775 
6776         mutex_exit(&softc->ds_lock);
6777         dprov_op_done(taskq_req, error);
6778         DPROV_DEBUG(D_RANDOM, ("(%d) dprov_random_task: end\n", instance));
6779 }
6780 
6781 
6782 /*
6783  * taskq dispatcher function for session management operations.
6784  */
6785 static void
6786 dprov_session_task(dprov_req_t *taskq_req)
6787 {
6788         dprov_state_t *softc;
6789         /* LINTED E_FUNC_SET_NOT_USED */
6790         int instance;
6791         int error = CRYPTO_NOT_SUPPORTED;
6792         crypto_session_id_t session_id =
6793             taskq_req->dr_session_req.sr_session_id;
6794         dprov_session_t *session;
6795         dprov_object_t *object;
6796         int i;
6797 
6798         DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
6799         DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_task: started\n",
6800             instance));
6801 
6802         mutex_enter(&softc->ds_lock);
6803 
6804         if (taskq_req->dr_type != DPROV_REQ_SESSION_OPEN)
6805                 /* validate session id and get ptr to session */
6806                 if ((session = softc->ds_sessions[session_id]) == NULL) {
6807                         mutex_exit(&softc->ds_lock);
6808                         dprov_op_done(taskq_req, CRYPTO_SESSION_HANDLE_INVALID);
6809                         return;
6810                 }
6811 
6812         switch (taskq_req->dr_type) {
6813 
6814         case DPROV_REQ_SESSION_OPEN: {
6815                 dprov_session_t **new_sessions;
6816 
6817                 if (softc->ds_token_initialized == B_FALSE) {
6818                         error = CRYPTO_OPERATION_NOT_INITIALIZED;
6819                         break;
6820                 }
6821 
6822                 /* search for available session slot */
6823                 for (i = 0; i < softc->ds_sessions_slots; i++)
6824                         if (softc->ds_sessions[i] == NULL)
6825                                 break;
6826 
6827                 if (i == softc->ds_sessions_slots) {
6828                         /* ran out of slots, grow sessions array */
6829                         new_sessions = kmem_zalloc(
6830                             2 * softc->ds_sessions_slots *
6831                             sizeof (dprov_session_t *), KM_NOSLEEP);
6832                         if (new_sessions == NULL) {
6833                                 error = CRYPTO_SESSION_COUNT;
6834                                 break;
6835                         }
6836                         bcopy(softc->ds_sessions, new_sessions,
6837                             softc->ds_sessions_slots *
6838                             sizeof (dprov_session_t *));
6839                         kmem_free(softc->ds_sessions, softc->ds_sessions_slots *
6840                             sizeof (dprov_session_t *));
6841                         softc->ds_sessions = new_sessions;
6842                         softc->ds_sessions_slots *= 2;
6843                 }
6844 
6845                 /* allocate and initialize new session */
6846                 softc->ds_sessions[i] = kmem_zalloc(
6847                     sizeof (dprov_session_t), KM_NOSLEEP);
6848                 if (softc->ds_sessions[i] == NULL) {
6849                         error = CRYPTO_HOST_MEMORY;
6850                         break;
6851                 }
6852                 softc->ds_sessions_count++;
6853 
6854                 /* initialize session state */
6855                 softc->ds_sessions[i]->ds_state = DPROV_SESSION_STATE_PUBLIC;
6856 
6857                 /* return new session id to caller */
6858                 *(taskq_req->dr_session_req.sr_session_id_ptr) = i;
6859 
6860                 error = CRYPTO_SUCCESS;
6861                 break;
6862         }
6863 
6864         case DPROV_REQ_SESSION_CLOSE:
6865                 softc->ds_sessions[session_id] = NULL;
6866 
6867                 if (softc->ds_token_initialized == B_FALSE) {
6868                         error = CRYPTO_OPERATION_NOT_INITIALIZED;
6869                         break;
6870                 }
6871 
6872                 dprov_release_session_objects(session);
6873 
6874                 /* free session state and corresponding slot */
6875                 kmem_free(session, sizeof (dprov_session_t));
6876                 softc->ds_sessions_count--;
6877 
6878                 error = CRYPTO_SUCCESS;
6879                 break;
6880 
6881         case DPROV_REQ_SESSION_LOGIN: {
6882                 char *pin = taskq_req->dr_session_req.sr_pin;
6883                 size_t pin_len = taskq_req->dr_session_req.sr_pin_len;
6884                 crypto_user_type_t user_type =
6885                     taskq_req->dr_session_req.sr_user_type;
6886 
6887                 /* check user type */
6888                 if (user_type != CRYPTO_SO && user_type != CRYPTO_USER) {
6889                         error = CRYPTO_USER_TYPE_INVALID;
6890                         break;
6891                 }
6892 
6893                 /* check pin length */
6894                 if (pin_len > DPROV_MAX_PIN_LEN) {
6895                         error = CRYPTO_PIN_LEN_RANGE;
6896                         break;
6897                 }
6898 
6899                 /* check pin */
6900                 if (pin == NULL) {
6901                         error = CRYPTO_PIN_INVALID;
6902                         break;
6903                 }
6904 
6905                 /* validate PIN state */
6906                 if ((user_type == CRYPTO_SO) && !softc->ds_token_initialized ||
6907                     (user_type == CRYPTO_USER) && !softc->ds_user_pin_set) {
6908                         error = CRYPTO_USER_PIN_NOT_INITIALIZED;
6909                         break;
6910                 }
6911 
6912                 if ((user_type == CRYPTO_SO &&
6913                     softc->ds_sessions[session_id]->ds_state ==
6914                     DPROV_SESSION_STATE_SO) ||
6915                     (user_type == CRYPTO_USER &&
6916                     softc->ds_sessions[session_id]->ds_state ==
6917                     DPROV_SESSION_STATE_USER)) {
6918                         /* SO or user already logged in */
6919                         error = CRYPTO_USER_ALREADY_LOGGED_IN;
6920                         break;
6921                 }
6922 
6923                 if (softc->ds_sessions[session_id]->ds_state !=
6924                     DPROV_SESSION_STATE_PUBLIC) {
6925                         /* another user already logged in */
6926                         error = CRYPTO_USER_ANOTHER_ALREADY_LOGGED_IN;
6927                         break;
6928                 }
6929 
6930                 /* everything's fine, update session */
6931                 softc->ds_sessions[session_id]->ds_state =
6932                     user_type == CRYPTO_SO ?
6933                     DPROV_SESSION_STATE_SO : DPROV_SESSION_STATE_USER;
6934 
6935                 error = CRYPTO_SUCCESS;
6936                 break;
6937         }
6938 
6939         case DPROV_REQ_SESSION_LOGOUT:
6940                 /* fail if not logged in */
6941                 if (softc->ds_sessions[session_id]->ds_state ==
6942                     DPROV_SESSION_STATE_PUBLIC) {
6943                         error = CRYPTO_USER_NOT_LOGGED_IN;
6944                         break;
6945                 }
6946 
6947                 /*
6948                  * Destroy all private session objects.
6949                  * Invalidate handles to all private objects.
6950                  */
6951                 for (i = 0; i < DPROV_MAX_OBJECTS; i++) {
6952                         object = softc->ds_sessions[session_id]->ds_objects[i];
6953                         if (object != NULL && dprov_object_is_private(object)) {
6954                                 if (!dprov_object_is_token(object))
6955                                         /* It's a session object, free it */
6956                                         DPROV_OBJECT_REFRELE(object);
6957                                 softc->ds_sessions[session_id]->ds_objects[i] =
6958                                     NULL;
6959                         }
6960                 }
6961 
6962                 /* update session state */
6963                 softc->ds_sessions[session_id]->ds_state =
6964                     DPROV_SESSION_STATE_PUBLIC;
6965 
6966                 error = CRYPTO_SUCCESS;
6967                 break;
6968         }
6969 
6970         mutex_exit(&softc->ds_lock);
6971         dprov_op_done(taskq_req, error);
6972         DPROV_DEBUG(D_SESSION, ("(%d) dprov_session_task: end\n", instance));
6973 }
6974 
6975 /* return true if attribute is defined to be a PKCS#11 long */
6976 static boolean_t
6977 fixed_size_attribute(crypto_attr_type_t type)
6978 {
6979         return (type == DPROV_CKA_CLASS ||
6980             type == DPROV_CKA_CERTIFICATE_TYPE ||
6981             type == DPROV_CKA_KEY_TYPE ||
6982             type == DPROV_HW_FEATURE_TYPE);
6983 }
6984 
6985 /*
6986  * Attributes defined to be a PKCS#11 long causes problems for dprov
6987  * because 32-bit applications set the size to 4 and 64-bit applications
6988  * set the size to 8. dprov always stores these fixed-size attributes
6989  * as uint32_t.
6990  */
6991 static ssize_t
6992 attribute_size(crypto_attr_type_t type, ssize_t len)
6993 {
6994         if (fixed_size_attribute(type))
6995                 return (sizeof (uint32_t));
6996 
6997         return (len);
6998 }
6999 
7000 /*
7001  * taskq dispatcher function for object management operations.
7002  */
7003 static void
7004 dprov_object_task(dprov_req_t *taskq_req)
7005 {
7006         dprov_state_t *softc;
7007         /* LINTED E_FUNC_SET_NOT_USED */
7008         int instance;
7009         int error = CRYPTO_NOT_SUPPORTED;
7010         crypto_object_id_t object_id = taskq_req->dr_object_req.or_object_id;
7011         crypto_session_id_t session_id = taskq_req->dr_object_req.or_session_id;
7012         crypto_object_attribute_t *template =
7013             taskq_req->dr_object_req.or_template;
7014         uint_t attr_count = taskq_req->dr_object_req.or_attribute_count;
7015         dprov_object_t *object;
7016         dprov_session_t *session;
7017 
7018         DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
7019         DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_task: started\n", instance));
7020 
7021         mutex_enter(&softc->ds_lock);
7022 
7023         /* validate session id and get ptr to session */
7024         if ((session = softc->ds_sessions[session_id]) == NULL) {
7025                 mutex_exit(&softc->ds_lock);
7026                 dprov_op_done(taskq_req, CRYPTO_SESSION_HANDLE_INVALID);
7027                 return;
7028         }
7029 
7030         switch (taskq_req->dr_type) {
7031 
7032         case DPROV_REQ_OBJECT_CREATE:
7033                 /* create the object from the specified template */
7034                 if ((error = dprov_create_object_from_template(softc, session,
7035                     template, attr_count,
7036                     taskq_req->dr_object_req.or_object_id_ptr, B_TRUE,
7037                     B_FALSE)) != CRYPTO_SUCCESS)
7038                         break;
7039 
7040                 break;
7041 
7042         case DPROV_REQ_OBJECT_COPY:
7043                 /* check object id */
7044                 if (object_id >= DPROV_MAX_OBJECTS ||
7045                     (object = session->ds_objects[object_id]) == NULL) {
7046                         error = CRYPTO_OBJECT_HANDLE_INVALID;
7047                         break;
7048                 }
7049 
7050                 /*
7051                  * Create a new object from the object passed as
7052                  * argument.
7053                  */
7054                 if ((error = dprov_create_object_from_template(softc, session,
7055                     object->do_attr, DPROV_MAX_ATTR,
7056                     taskq_req->dr_object_req.or_object_id_ptr, B_TRUE,
7057                     B_FALSE)) != CRYPTO_SUCCESS)
7058                         break;
7059 
7060                 /*
7061                  * Add the attributes specified by the template to the
7062                  * newly created object, replacing existing ones if needed.
7063                  */
7064                 error = dprov_object_set_attr(session,
7065                     *taskq_req->dr_object_req.or_object_id_ptr,
7066                     taskq_req->dr_object_req.or_template,
7067                     taskq_req->dr_object_req.or_attribute_count, B_TRUE);
7068 
7069                 break;
7070 
7071         case DPROV_REQ_OBJECT_DESTROY:
7072                 /* destroy the object */
7073                 error = dprov_destroy_object(softc, session,
7074                     taskq_req->dr_object_req.or_object_id);
7075 
7076                 break;
7077 
7078         case DPROV_REQ_OBJECT_GET_SIZE:
7079                 /* get ptr to object */
7080                 if (object_id >= DPROV_MAX_OBJECTS ||
7081                     session->ds_objects[object_id] == NULL) {
7082                         error = CRYPTO_OBJECT_HANDLE_INVALID;
7083                         break;
7084                 }
7085 
7086                 /*
7087                  * The PKCS11 specification does not specifies what
7088                  * the object size really is, here we just return
7089                  * the number of possible attributes of the object.
7090                  */
7091                 *taskq_req->dr_object_req.or_object_size = DPROV_MAX_ATTR;
7092 
7093                 error = CRYPTO_SUCCESS;
7094                 break;
7095 
7096         case DPROV_REQ_OBJECT_GET_ATTRIBUTE_VALUE: {
7097                 crypto_attr_type_t type;
7098                 size_t olen, tlen;
7099                 offset_t offset;
7100                 int tmpl_idx;
7101                 int object_idx;
7102                 ulong_t class = DPROV_CKO_DATA;
7103                 boolean_t extractable = B_TRUE;
7104 
7105                 error = CRYPTO_SUCCESS;
7106 
7107                 /* get ptr to object */
7108                 if (object_id >= DPROV_MAX_OBJECTS ||
7109                     (object = session->ds_objects[object_id]) == NULL) {
7110                         error = CRYPTO_OBJECT_HANDLE_INVALID;
7111                         break;
7112                 }
7113 
7114                 (void) dprov_get_object_attr_boolean(object,
7115                     DPROV_CKA_EXTRACTABLE, &extractable);
7116 
7117                 (void) dprov_get_object_attr_ulong(object,
7118                     DPROV_CKA_CLASS, &class);
7119 
7120                 /* return the specified attributes, when possible */
7121                 for (tmpl_idx = 0; tmpl_idx < attr_count; tmpl_idx++) {
7122                         /*
7123                          * Attribute can't be revealed if the CKA_EXTRACTABLE
7124                          * attribute is set to false.
7125                          */
7126                         type = template[tmpl_idx].oa_type;
7127                         if (!extractable && class == DPROV_CKO_SECRET_KEY) {
7128                                 if (type == DPROV_CKA_VALUE) {
7129                                         template[tmpl_idx].oa_value_len = -1;
7130                                         error = CRYPTO_ATTRIBUTE_SENSITIVE;
7131                                         continue;
7132                                 }
7133                         }
7134                         if (!extractable && class == DPROV_CKO_PRIVATE_KEY) {
7135                                 if (type == DPROV_CKA_PRIVATE_EXPONENT) {
7136                                         template[tmpl_idx].oa_value_len = -1;
7137                                         error = CRYPTO_ATTRIBUTE_SENSITIVE;
7138                                         continue;
7139                                 }
7140                         }
7141 
7142                         object_idx = dprov_find_attr(object->do_attr,
7143                             DPROV_MAX_ATTR, type);
7144                         if (object_idx == -1) {
7145                                 /* attribute not found in object */
7146                                 template[tmpl_idx].oa_value_len = -1;
7147                                 error = CRYPTO_ATTRIBUTE_TYPE_INVALID;
7148                                 continue;
7149                         }
7150 
7151                         tlen = template[tmpl_idx].oa_value_len;
7152                         olen = object->do_attr[object_idx].oa_value_len;
7153                         /* return attribute length */
7154                         if (template[tmpl_idx].oa_value == NULL) {
7155                                 /*
7156                                  * The size of the attribute is set by the
7157                                  * library according to the data model of the
7158                                  * application, so don't overwrite it with
7159                                  * dprov's size.
7160                                  */
7161                                 if (!fixed_size_attribute(type))
7162                                         template[tmpl_idx].oa_value_len = olen;
7163                                 continue;
7164                         }
7165 
7166                         if (tlen < olen) {
7167                                 template[tmpl_idx].oa_value_len = -1;
7168                                 error = CRYPTO_BUFFER_TOO_SMALL;
7169                                 continue;
7170                         }
7171 
7172                         /* copy attribute value */
7173                         bzero(template[tmpl_idx].oa_value, tlen);
7174 
7175                         offset = 0;
7176 #ifdef _BIG_ENDIAN
7177                         if (fixed_size_attribute(type)) {
7178                                 offset = tlen - olen;
7179                         }
7180 #endif
7181                         bcopy(object->do_attr[object_idx].oa_value,
7182                             &template[tmpl_idx].oa_value[offset], olen);
7183 
7184                         /* don't update length for fixed-size attributes */
7185                         if (!fixed_size_attribute(type))
7186                                 template[tmpl_idx].oa_value_len = olen;
7187                 }
7188 
7189                 break;
7190         }
7191 
7192         case DPROV_REQ_OBJECT_SET_ATTRIBUTE_VALUE:
7193                 /*
7194                  * Add the attributes specified by the template to the
7195                  * newly created object, replacing existing ones if needed.
7196                  */
7197                 error = dprov_object_set_attr(session,
7198                     taskq_req->dr_object_req.or_object_id,
7199                     taskq_req->dr_object_req.or_template,
7200                     taskq_req->dr_object_req.or_attribute_count, B_TRUE);
7201 
7202                 break;
7203 
7204         case DPROV_REQ_OBJECT_FIND_INIT: {
7205                 dprov_find_ctx_t *find_ctx;
7206                 int so_idx;             /* session object index */
7207                 int to_idx;             /* token object index */
7208 
7209                 error = CRYPTO_SUCCESS;
7210                 /* allocate find context */
7211                 find_ctx = kmem_zalloc(sizeof (dprov_find_ctx_t), KM_SLEEP);
7212                 *taskq_req->dr_object_req.or_find_pp = find_ctx;
7213 
7214                 /* first go through the existing session objects */
7215                 for (so_idx = 0; so_idx < DPROV_MAX_OBJECTS; so_idx++) {
7216                         if ((object = session->ds_objects[so_idx]) == NULL)
7217                                 continue;
7218 
7219                         /* setting count to zero means find all objects */
7220                         if (attr_count > 0) {
7221                                 if (!dprov_attributes_match(object, template,
7222                                     attr_count))
7223                                         continue;
7224                         }
7225 
7226                         /* session object attributes matches template */
7227                         find_ctx->fc_ids[find_ctx->fc_nids] = so_idx;
7228                         find_ctx->fc_nids++;
7229                 }
7230 
7231                 /*
7232                  * Go through the token object. For each token object
7233                  * that can be accessed:
7234                  * If there was already an session object id assigned
7235                  * to that token object, skip it, since it was returned
7236                  * during the check of session objects, else,
7237                  * assign a new object id for that token object and
7238                  * add it to the array of matching objects.
7239                  */
7240                 for (to_idx = 0; to_idx < DPROV_MAX_OBJECTS &&
7241                     error == CRYPTO_SUCCESS; to_idx++) {
7242                         if ((object = softc->ds_objects[to_idx]) == NULL)
7243                                 continue;
7244 
7245                         /* setting count to zero means find all objects */
7246                         if (attr_count > 0) {
7247                                 if (!dprov_attributes_match(object, template,
7248                                     attr_count))
7249                                         continue;
7250                         }
7251 
7252                         /* if the the object has been destroyed, skip it */
7253                         if (object->do_destroyed)
7254                                 continue;
7255 
7256                         /* skip object if it cannot be accessed from session */
7257                         if (dprov_object_is_private(object) &&
7258                             session->ds_state != DPROV_SESSION_STATE_USER)
7259                                 continue;
7260 
7261                         /*
7262                          * Is there already a session object id for this
7263                          * token object?
7264                          */
7265                         for (so_idx = 0; so_idx < DPROV_MAX_OBJECTS; so_idx++)
7266                                 if (session->ds_objects[so_idx] != NULL &&
7267                                     session->ds_objects[so_idx]->do_token_idx ==
7268                                     to_idx)
7269                                         break;
7270                         if (so_idx < DPROV_MAX_OBJECTS)
7271                                 /* object found in session table, skip it */
7272                                 continue;
7273 
7274                         /* find free session slot for this object */
7275                         for (so_idx = 0; so_idx < DPROV_MAX_OBJECTS; so_idx++)
7276                                 if (session->ds_objects[so_idx] == NULL)
7277                                         break;
7278                         if (so_idx == DPROV_MAX_OBJECTS) {
7279                                 /* ran out of session objects slots */
7280                                 kmem_free(find_ctx, sizeof (dprov_find_ctx_t));
7281                                 error = CRYPTO_HOST_MEMORY;
7282                                 break;
7283                         }
7284 
7285                         /* add object to session objects table */
7286                         session->ds_objects[so_idx] = object;
7287                         DPROV_OBJECT_REFHOLD(object);
7288 
7289                         /* add object to list of objects to return */
7290                         find_ctx->fc_ids[find_ctx->fc_nids] = so_idx;
7291                         find_ctx->fc_nids++;
7292                 }
7293 
7294                 break;
7295         }
7296 
7297         case DPROV_REQ_OBJECT_FIND: {
7298                 crypto_object_id_t *object_ids =
7299                     taskq_req->dr_object_req.or_object_id_ptr;
7300                 uint_t max_object_count =
7301                     taskq_req->dr_object_req.or_max_object_count;
7302                 dprov_find_ctx_t *find_ctx =
7303                     taskq_req->dr_object_req.or_find_p;
7304                 uint_t ret_oid_idx;
7305 
7306                 /* return the desired number of object ids */
7307                 for (ret_oid_idx = 0; ret_oid_idx < max_object_count &&
7308                     find_ctx->fc_next < find_ctx->fc_nids; ret_oid_idx++)
7309                         object_ids[ret_oid_idx] =
7310                             find_ctx->fc_ids[find_ctx->fc_next++];
7311 
7312                 *taskq_req->dr_object_req.or_object_count_ptr = ret_oid_idx;
7313 
7314                 error = CRYPTO_SUCCESS;
7315                 break;
7316         }
7317 
7318         case DPROV_REQ_OBJECT_FIND_FINAL:
7319                 kmem_free(taskq_req->dr_object_req.or_find_p,
7320                     sizeof (dprov_find_ctx_t));
7321 
7322                 error = CRYPTO_SUCCESS;
7323                 break;
7324         }
7325 
7326         mutex_exit(&softc->ds_lock);
7327         dprov_op_done(taskq_req, error);
7328         DPROV_DEBUG(D_OBJECT, ("(%d) dprov_object_task: end\n", instance));
7329 }
7330 
7331 /*
7332  * Copy attribute values into a template. RSA values are precomputed.
7333  */
7334 static int
7335 nostore_copy_attribute(crypto_object_attribute_t *template, uint_t count,
7336     uint64_t attr_type)
7337 {
7338         void *value, *dprov_attribute_value;
7339         size_t dprov_attribute_size;
7340         size_t value_len = 0;
7341         int error;
7342 
7343         switch (attr_type) {
7344         case DPROV_CKA_VALUE:
7345                 dprov_attribute_size = sizeof (dh_value);
7346                 dprov_attribute_value = dh_value;
7347                 break;
7348 
7349         case DPROV_CKA_MODULUS:
7350                 dprov_attribute_size = sizeof (modulus);
7351                 dprov_attribute_value = modulus;
7352                 break;
7353 
7354         case DPROV_CKA_PUBLIC_EXPONENT:
7355                 dprov_attribute_size = sizeof (public_exponent);
7356                 dprov_attribute_value = public_exponent;
7357                 break;
7358 
7359         case DPROV_CKA_PRIVATE_EXPONENT:
7360                 dprov_attribute_size = sizeof (private_exponent);
7361                 dprov_attribute_value = private_exponent;
7362                 break;
7363 
7364         default:
7365                 return (CRYPTO_ATTRIBUTE_TYPE_INVALID);
7366         }
7367 
7368         error = dprov_get_template_attr_array(template, count, attr_type,
7369             &value, &value_len);
7370         if (error != CRYPTO_SUCCESS)
7371                 return (error);
7372 
7373         if (value_len < dprov_attribute_size)
7374                 return (CRYPTO_BUFFER_TOO_SMALL);
7375 
7376         /*
7377          * The updated template will be returned to libpkcs11.
7378          */
7379         bcopy(dprov_attribute_value, value, dprov_attribute_size);
7380 
7381         return (CRYPTO_SUCCESS);
7382 }
7383 
7384 static void
7385 fill_dh(void *value, size_t len)
7386 {
7387         int i = 0;
7388         char *p = value;
7389         while (i < len) {
7390                 p[i++] = 'D';
7391                 if (i >= len)
7392                         break;
7393                 p[i++] = 'H';
7394         }
7395 }
7396 
7397 /*
7398  * taskq dispatcher function for key management operations.
7399  */
7400 static void
7401 dprov_key_task(dprov_req_t *taskq_req)
7402 {
7403         dprov_state_t *softc;
7404         /* LINTED E_FUNC_SET_NOT_USED */
7405         int instance;
7406         int error = CRYPTO_NOT_SUPPORTED;
7407         kcf_provider_desc_t *pd;
7408         crypto_session_id_t session_id = taskq_req->dr_key_req.kr_session_id;
7409         dprov_session_t *session;
7410 
7411         DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
7412         DPROV_DEBUG(D_KEY, ("(%d) dprov_key_task: started\n", instance));
7413 
7414         mutex_enter(&softc->ds_lock);
7415 
7416         /* validate session id and get ptr to session */
7417         if ((session = softc->ds_sessions[session_id]) == NULL) {
7418                 mutex_exit(&softc->ds_lock);
7419                 dprov_op_done(taskq_req, CRYPTO_SESSION_HANDLE_INVALID);
7420                 return;
7421         }
7422 
7423         switch (taskq_req->dr_type) {
7424         case DPROV_REQ_KEY_GENERATE: {
7425                 crypto_mechanism_t *mechp;
7426                 crypto_object_id_t *object_id_ptr;
7427                 crypto_object_attribute_t *template;
7428                 crypto_object_attribute_t attribute;
7429                 uint_t attribute_count;
7430                 ulong_t key_type = ~0UL, class = ~0UL;
7431                 ulong_t value_len;
7432                 size_t key_len = 0;
7433 
7434                 error = CRYPTO_SUCCESS;
7435 
7436                 template = taskq_req->dr_key_req.kr_template;
7437                 attribute_count = taskq_req->dr_key_req.kr_attribute_count;
7438                 object_id_ptr = taskq_req->dr_key_req.kr_object_id_ptr;
7439                 mechp = taskq_req->dr_key_req.kr_mechanism;
7440 
7441                 /* optional */
7442                 (void) dprov_get_template_attr_ulong(template, attribute_count,
7443                     DPROV_CKA_CLASS, &class);
7444 
7445                 /* optional */
7446                 (void) dprov_get_template_attr_ulong(template, attribute_count,
7447                     DPROV_CKA_KEY_TYPE, &key_type);
7448 
7449                 if (class != ~0UL && class != DPROV_CKO_SECRET_KEY) {
7450                         error = CRYPTO_TEMPLATE_INCONSISTENT;
7451                         break;
7452                 }
7453 
7454                 switch (mechp->cm_type) {
7455                 case DES_KEY_GEN_MECH_INFO_TYPE:
7456                         if (key_type != ~0UL && key_type != DPROV_CKK_DES) {
7457                                 error = CRYPTO_TEMPLATE_INCONSISTENT;
7458                                 break;
7459                         }
7460                         key_len = DES_KEY_LEN;
7461                         key_type = DPROV_CKK_DES;
7462                         break;
7463 
7464                 case DES3_KEY_GEN_MECH_INFO_TYPE:
7465                         if (key_type != ~0UL && key_type != DPROV_CKK_DES3) {
7466                                 error = CRYPTO_TEMPLATE_INCONSISTENT;
7467                                 break;
7468                         }
7469                         key_len = DES3_KEY_LEN;
7470                         key_type = DPROV_CKK_DES3;
7471                         break;
7472 
7473                 case AES_KEY_GEN_MECH_INFO_TYPE:
7474                         if (key_type != ~0UL && key_type != DPROV_CKK_AES) {
7475                                 error = CRYPTO_TEMPLATE_INCONSISTENT;
7476                                 break;
7477                         }
7478                         if (dprov_get_template_attr_ulong(template,
7479                             attribute_count, DPROV_CKA_VALUE_LEN,
7480                             &value_len) != CRYPTO_SUCCESS) {
7481                                 error = CRYPTO_TEMPLATE_INCOMPLETE;
7482                                 break;
7483                         }
7484                         if (value_len >= AES_MAX_KEY_LEN) {
7485                                 error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7486                                 break;
7487                         }
7488                         key_len = value_len;
7489                         key_type = DPROV_CKK_AES;
7490                         break;
7491 
7492                 case BLOWFISH_KEY_GEN_MECH_INFO_TYPE:
7493                         if (key_type != ~0UL &&
7494                             key_type != DPROV_CKK_BLOWFISH) {
7495                                 error = CRYPTO_TEMPLATE_INCONSISTENT;
7496                                 break;
7497                         }
7498                         if (dprov_get_template_attr_ulong(template,
7499                             attribute_count, DPROV_CKA_VALUE_LEN,
7500                             &value_len) != CRYPTO_SUCCESS) {
7501                                 error = CRYPTO_TEMPLATE_INCOMPLETE;
7502                                 break;
7503                         }
7504                         if (value_len >= BLOWFISH_MAX_KEY_LEN) {
7505                                 error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7506                                 break;
7507                         }
7508                         key_len = value_len;
7509                         key_type = DPROV_CKK_BLOWFISH;
7510                         break;
7511 
7512                 case RC4_KEY_GEN_MECH_INFO_TYPE:
7513                         if (key_type != ~0UL && key_type != DPROV_CKK_RC4) {
7514                                 error = CRYPTO_TEMPLATE_INCONSISTENT;
7515                                 break;
7516                         }
7517                         if (dprov_get_template_attr_ulong(template,
7518                             attribute_count, DPROV_CKA_VALUE_LEN,
7519                             &value_len) != CRYPTO_SUCCESS) {
7520                                 error = CRYPTO_TEMPLATE_INCOMPLETE;
7521                                 break;
7522                         }
7523                         if (value_len >=
7524                             CRYPTO_BITS2BYTES(ARCFOUR_MAX_KEY_BITS)) {
7525                                 error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
7526                                 break;
7527                         }
7528                         key_len = value_len;
7529                         key_type = DPROV_CKK_RC4;
7530                         break;
7531 
7532                 default:
7533                         error = CRYPTO_MECHANISM_INVALID;
7534                 }
7535 
7536                 if (error != CRYPTO_SUCCESS)
7537                         break;
7538 
7539                 error = dprov_create_object_from_template(softc, session,
7540                     template, attribute_count, object_id_ptr, B_FALSE, B_TRUE);
7541 
7542                 if (error != CRYPTO_SUCCESS)
7543                         break;
7544 
7545                 /* make sure class is set */
7546                 attribute.oa_type = DPROV_CKA_CLASS;
7547                 attribute.oa_value = (char *)&class;
7548                 attribute.oa_value_len = sizeof (ulong_t);
7549                 error = dprov_object_set_attr(session, *object_id_ptr,
7550                     &attribute, 1, B_FALSE);
7551 
7552                 if (error != CRYPTO_SUCCESS) {
7553                         goto destroy_object;
7554                 }
7555 
7556                 /* make sure key_type is set */
7557                 attribute.oa_type = DPROV_CKA_KEY_TYPE;
7558                 attribute.oa_value = (char *)&key_type;
7559                 attribute.oa_value_len = sizeof (ulong_t);
7560                 error = dprov_object_set_attr(session, *object_id_ptr,
7561                     &attribute, 1, B_FALSE);
7562 
7563                 if (error != CRYPTO_SUCCESS) {
7564                         goto destroy_object;
7565                 }
7566 
7567                 attribute.oa_type = DPROV_CKA_VALUE;
7568                 attribute.oa_value = kmem_alloc(key_len, KM_SLEEP);
7569                 attribute.oa_value_len = key_len;
7570 
7571                 if (random_get_pseudo_bytes((uchar_t *)attribute.oa_value,
7572                     key_len) != 0) {
7573                         bzero(attribute.oa_value, key_len);
7574                         kmem_free(attribute.oa_value, key_len);
7575                         goto destroy_object;
7576                 }
7577                 error = dprov_object_set_attr(session, *object_id_ptr,
7578                     &attribute, 1, B_FALSE);
7579 
7580                 bzero(attribute.oa_value, key_len);
7581                 kmem_free(attribute.oa_value, key_len);
7582 
7583                 if (error != CRYPTO_SUCCESS) {
7584                         goto destroy_object;
7585                 }
7586                 break;
7587 
7588 destroy_object:
7589                 (void) dprov_destroy_object(softc, session, *object_id_ptr);
7590                 break;
7591         }
7592 
7593         case DPROV_REQ_KEY_GENERATE_PAIR: {
7594                 crypto_mechanism_t *mechp;
7595                 crypto_object_id_t *pub_object_id_ptr;
7596                 crypto_object_id_t *pri_object_id_ptr;
7597                 crypto_object_attribute_t *pub_template;
7598                 crypto_object_attribute_t *pri_template;
7599                 crypto_object_attribute_t attribute;
7600                 uint_t pub_attribute_count;
7601                 uint_t pri_attribute_count;
7602                 ulong_t pub_key_type = ~0UL, pub_class = ~0UL;
7603                 ulong_t pri_key_type = ~0UL, pri_class = ~0UL;
7604 
7605                 pub_template = taskq_req->dr_key_req.kr_template;
7606                 pub_attribute_count = taskq_req->dr_key_req.kr_attribute_count;
7607                 pub_object_id_ptr = taskq_req->dr_key_req.kr_object_id_ptr;
7608                 pri_template = taskq_req->dr_key_req.kr_private_key_template;
7609                 pri_attribute_count =
7610                     taskq_req->dr_key_req.kr_private_key_attribute_count;
7611                 pri_object_id_ptr =
7612                     taskq_req->dr_key_req.kr_private_key_object_id_ptr;
7613                 mechp = taskq_req->dr_key_req.kr_mechanism;
7614 
7615                 error = CRYPTO_SUCCESS;
7616 
7617                 /* optional */
7618                 (void) dprov_get_template_attr_ulong(pub_template,
7619                     pub_attribute_count, DPROV_CKA_CLASS, &pub_class);
7620 
7621                 /* optional */
7622                 (void) dprov_get_template_attr_ulong(pri_template,
7623                     pri_attribute_count, DPROV_CKA_CLASS, &pri_class);
7624 
7625                 /* optional */
7626                 (void) dprov_get_template_attr_ulong(pub_template,
7627                     pub_attribute_count, DPROV_CKA_KEY_TYPE, &pub_key_type);
7628 
7629                 /* optional */
7630                 (void) dprov_get_template_attr_ulong(pri_template,
7631                     pri_attribute_count, DPROV_CKA_KEY_TYPE, &pri_key_type);
7632 
7633                 if (pub_class != ~0UL && pub_class != DPROV_CKO_PUBLIC_KEY) {
7634                         error = CRYPTO_TEMPLATE_INCONSISTENT;
7635                         break;
7636                 }
7637 
7638                 if (pri_class != ~0UL && pri_class != DPROV_CKO_PRIVATE_KEY) {
7639                         error = CRYPTO_TEMPLATE_INCONSISTENT;
7640                         break;
7641                 }
7642 
7643                 switch (mechp->cm_type) {
7644                 case RSA_PKCS_KEY_PAIR_GEN_MECH_INFO_TYPE:
7645                         if (pub_key_type != ~0UL &&
7646                             pub_key_type != DPROV_CKK_RSA) {
7647                                 error = CRYPTO_TEMPLATE_INCONSISTENT;
7648                                 break;
7649                         }
7650                         pub_key_type = DPROV_CKK_RSA;
7651 
7652                         if (pri_key_type != ~0UL &&
7653                             pri_key_type != DPROV_CKK_RSA) {
7654                                 error = CRYPTO_TEMPLATE_INCONSISTENT;
7655                                 break;
7656                         }
7657                         pri_key_type = DPROV_CKK_RSA;
7658 
7659                         if (pub_class != ~0UL &&
7660                             pub_class != DPROV_CKO_PUBLIC_KEY) {
7661                                 error = CRYPTO_TEMPLATE_INCONSISTENT;
7662                                 break;
7663                         }
7664                         pub_class = DPROV_CKO_PUBLIC_KEY;
7665 
7666                         if (pri_class != ~0UL &&
7667                             pri_class != DPROV_CKO_PRIVATE_KEY) {
7668                                 error = CRYPTO_TEMPLATE_INCONSISTENT;
7669                                 break;
7670                         }
7671                         pri_class = DPROV_CKO_PRIVATE_KEY;
7672                         break;
7673 
7674                 default:
7675                         error = CRYPTO_MECHANISM_INVALID;
7676                 }
7677 
7678                 if (error != CRYPTO_SUCCESS)
7679                         break;
7680 
7681                 error = dprov_create_object_from_template(softc, session,
7682                     pub_template, pub_attribute_count, pub_object_id_ptr,
7683                     B_FALSE, B_TRUE);
7684 
7685                 if (error != CRYPTO_SUCCESS)
7686                         break;
7687 
7688                 /* make sure class is set */
7689                 attribute.oa_type = DPROV_CKA_CLASS;
7690                 attribute.oa_value = (char *)&pub_class;
7691                 attribute.oa_value_len = sizeof (ulong_t);
7692                 error = dprov_object_set_attr(session, *pub_object_id_ptr,
7693                     &attribute, 1, B_FALSE);
7694 
7695                 if (error != CRYPTO_SUCCESS) {
7696                         goto destroy_public_object;
7697                 }
7698 
7699                 /* make sure key_type is set */
7700                 attribute.oa_type = DPROV_CKA_KEY_TYPE;
7701                 attribute.oa_value = (char *)&pub_key_type;
7702                 attribute.oa_value_len = sizeof (ulong_t);
7703                 error = dprov_object_set_attr(session, *pub_object_id_ptr,
7704                     &attribute, 1, B_FALSE);
7705 
7706                 if (error != CRYPTO_SUCCESS) {
7707                         goto destroy_public_object;
7708                 }
7709 
7710                 attribute.oa_type = DPROV_CKA_MODULUS;
7711                 attribute.oa_value = (char *)modulus;
7712                 attribute.oa_value_len = sizeof (modulus);
7713                 error = dprov_object_set_attr(session, *pub_object_id_ptr,
7714                     &attribute, 1, B_FALSE);
7715 
7716                 if (error != CRYPTO_SUCCESS) {
7717                         goto destroy_public_object;
7718                 }
7719 
7720                 attribute.oa_type = DPROV_CKA_PUBLIC_EXPONENT;
7721                 attribute.oa_value = public_exponent;
7722                 attribute.oa_value_len = sizeof (public_exponent);
7723                 error = dprov_object_set_attr(session, *pub_object_id_ptr,
7724                     &attribute, 1, B_FALSE);
7725 
7726                 if (error != CRYPTO_SUCCESS) {
7727                         goto destroy_public_object;
7728                 }
7729 
7730                 error = dprov_create_object_from_template(softc, session,
7731                     pri_template, pri_attribute_count, pri_object_id_ptr,
7732                     B_FALSE, B_TRUE);
7733 
7734                 if (error != CRYPTO_SUCCESS)
7735                         break;
7736 
7737                 /* make sure class is set */
7738                 attribute.oa_type = DPROV_CKA_CLASS;
7739                 attribute.oa_value = (char *)&pri_class;
7740                 attribute.oa_value_len = sizeof (ulong_t);
7741                 error = dprov_object_set_attr(session, *pri_object_id_ptr,
7742                     &attribute, 1, B_FALSE);
7743 
7744                 if (error != CRYPTO_SUCCESS) {
7745                         goto destroy_private_object;
7746                 }
7747 
7748                 /* make sure key_type is set */
7749                 attribute.oa_type = DPROV_CKA_KEY_TYPE;
7750                 attribute.oa_value = (char *)&pri_key_type;
7751                 attribute.oa_value_len = sizeof (ulong_t);
7752                 error = dprov_object_set_attr(session, *pri_object_id_ptr,
7753                     &attribute, 1, B_FALSE);
7754 
7755                 if (error != CRYPTO_SUCCESS) {
7756                         goto destroy_private_object;
7757                 }
7758 
7759                 attribute.oa_type = DPROV_CKA_MODULUS;
7760                 attribute.oa_value = (char *)modulus;
7761                 attribute.oa_value_len = sizeof (modulus);
7762                 error = dprov_object_set_attr(session, *pri_object_id_ptr,
7763                     &attribute, 1, B_FALSE);
7764 
7765                 if (error != CRYPTO_SUCCESS) {
7766                         goto destroy_private_object;
7767                 }
7768 
7769                 attribute.oa_type = DPROV_CKA_PRIVATE_EXPONENT;
7770                 attribute.oa_value = (char *)private_exponent;
7771                 attribute.oa_value_len = sizeof (private_exponent);
7772                 error = dprov_object_set_attr(session, *pri_object_id_ptr,
7773                     &attribute, 1, B_FALSE);
7774 
7775                 if (error != CRYPTO_SUCCESS) {
7776                         goto destroy_private_object;
7777                 }
7778                 break;
7779 
7780 destroy_private_object:
7781                 (void) dprov_destroy_object(softc, session,
7782                     *pri_object_id_ptr);
7783 destroy_public_object:
7784                 (void) dprov_destroy_object(softc, session,
7785                     *pub_object_id_ptr);
7786 
7787                 break;
7788         }
7789 
7790         case DPROV_REQ_KEY_WRAP: {
7791                 crypto_mechanism_t mech, *mechp;
7792                 crypto_key_t key, *keyp;
7793                 crypto_object_id_t object_id;
7794                 ulong_t class = DPROV_CKO_DATA;
7795                 boolean_t extractable = B_TRUE;
7796                 dprov_object_t *object;
7797                 int object_idx;
7798                 char *plaintext_key;
7799                 size_t plaintext_key_len;
7800                 crypto_data_t plaintext;
7801                 crypto_data_t ciphertext;
7802                 size_t *lenp;
7803 
7804                 mechp = taskq_req->dr_key_req.kr_mechanism;
7805                 /* structure assignment */
7806                 mech = *mechp;
7807 
7808                 /* get wrapping key value */
7809                 if (is_publickey_mech(mech.cm_type)) {
7810                         if ((error = dprov_key_attr_asymmetric(softc,
7811                             session_id, taskq_req->dr_type,
7812                             taskq_req->dr_key_req.kr_key,
7813                             &key)) != CRYPTO_SUCCESS)
7814                                 break;
7815                         keyp = &key;
7816                 } else {
7817                         if ((error = dprov_key_value_secret(softc,
7818                             session_id, taskq_req->dr_type,
7819                             taskq_req->dr_key_req.kr_key,
7820                             &key)) != CRYPTO_SUCCESS)
7821                                 break;
7822                         keyp = &key;
7823                 }
7824 
7825                 /* get the software provider for this mechanism */
7826                 if ((error = dprov_get_sw_prov(mechp, &pd,
7827                     &mech.cm_type)) != CRYPTO_SUCCESS)
7828                         break;
7829 
7830                 object_id = *taskq_req->dr_key_req.kr_object_id_ptr;
7831                 if (object_id >= DPROV_MAX_OBJECTS) {
7832                         error = CRYPTO_KEY_HANDLE_INVALID;
7833                         break;
7834                 }
7835 
7836                 /* get ptr to object */
7837                 if ((object = session->ds_objects[object_id]) == NULL) {
7838                         error = CRYPTO_OBJECT_HANDLE_INVALID;
7839                         break;
7840                 }
7841 
7842                 (void) dprov_get_object_attr_boolean(object,
7843                     DPROV_CKA_EXTRACTABLE, &extractable);
7844 
7845                 if (!extractable) {
7846                         error = CRYPTO_ATTRIBUTE_SENSITIVE;
7847                         break;
7848                 }
7849 
7850                 (void) dprov_get_object_attr_ulong(object,
7851                     DPROV_CKA_CLASS, &class);
7852 
7853                 switch (class) {
7854                 case DPROV_CKO_SECRET_KEY:
7855                         object_idx = dprov_find_attr(object->do_attr,
7856                             DPROV_MAX_ATTR, DPROV_CKA_VALUE);
7857                         if (object_idx == -1) {
7858                                 error = CRYPTO_ATTRIBUTE_TYPE_INVALID;
7859                                 break;
7860                         }
7861                         break;
7862 
7863                         case DPROV_CKO_PRIVATE_KEY:
7864                         /*
7865                          * PKCS#11 says that ASN.1 should be used to encode
7866                          * specific attributes before encrypting the blob.
7867                          * We only encrypt the private exponent for the
7868                          * purpose of testing.
7869                          */
7870                         object_idx = dprov_find_attr(object->do_attr,
7871                             DPROV_MAX_ATTR, DPROV_CKA_PRIVATE_EXPONENT);
7872                         if (object_idx == -1) {
7873                                 error = CRYPTO_ATTRIBUTE_TYPE_INVALID;
7874                                 break;
7875                         }
7876                         break;
7877                 default:
7878                         error = CRYPTO_KEY_NOT_WRAPPABLE;
7879                         break;
7880                 }
7881                 if (error != CRYPTO_SUCCESS)
7882                         break;
7883 
7884                 plaintext_key = object->do_attr[object_idx].oa_value;
7885                 plaintext_key_len = object->do_attr[object_idx].oa_value_len;
7886                 lenp = taskq_req->dr_key_req.kr_wrapped_key_len_ptr;
7887 
7888                 /* session id is 0 for software provider */
7889                 plaintext.cd_format = CRYPTO_DATA_RAW;
7890                 plaintext.cd_offset = 0;
7891                 plaintext.cd_length = plaintext_key_len;
7892                 plaintext.cd_raw.iov_base = plaintext_key;
7893                 plaintext.cd_raw.iov_len = plaintext_key_len;
7894                 plaintext.cd_miscdata = NULL;
7895 
7896                 ciphertext.cd_format = CRYPTO_DATA_RAW;
7897                 ciphertext.cd_offset = 0;
7898                 ciphertext.cd_length = *lenp;
7899                 ciphertext.cd_raw.iov_base =
7900                     (char *)taskq_req->dr_key_req.kr_wrapped_key;
7901                 ciphertext.cd_raw.iov_len = ciphertext.cd_length;
7902                 ciphertext.cd_miscdata = NULL;
7903 
7904                 error = crypto_encrypt_prov(pd, 0, &mech, &plaintext, keyp,
7905                     NULL, &ciphertext, NULL);
7906 
7907                 KCF_PROV_REFRELE(pd);
7908                 if (error == CRYPTO_SUCCESS ||
7909                     error == CRYPTO_BUFFER_TOO_SMALL) {
7910                         *lenp = ciphertext.cd_length;
7911                 }
7912                 break;
7913         }
7914 
7915         case DPROV_REQ_KEY_UNWRAP: {
7916                 crypto_mechanism_t mech, *mechp;
7917                 crypto_key_t key, *keyp;
7918                 crypto_object_id_t *object_id_ptr;
7919                 ulong_t class = DPROV_CKO_DATA;
7920                 uchar_t *wrapped_key;
7921                 char *plaintext_buf;
7922                 size_t wrapped_key_len;
7923                 crypto_data_t plaintext;
7924                 crypto_data_t ciphertext;
7925                 crypto_object_attribute_t unwrapped_key;
7926                 crypto_object_attribute_t *template;
7927                 uint_t attribute_count;
7928 
7929                 template = taskq_req->dr_key_req.kr_template;
7930                 attribute_count = taskq_req->dr_key_req.kr_attribute_count;
7931                 object_id_ptr = taskq_req->dr_key_req.kr_object_id_ptr;
7932 
7933                 /* all objects must have an object class attribute */
7934                 if (dprov_get_template_attr_ulong(template, attribute_count,
7935                     DPROV_CKA_CLASS, &class) != CRYPTO_SUCCESS) {
7936                         error = CRYPTO_TEMPLATE_INCOMPLETE;
7937                         break;
7938                 }
7939 
7940                 mechp = taskq_req->dr_key_req.kr_mechanism;
7941                 /* structure assignment */
7942                 mech = *mechp;
7943 
7944                 /* get unwrapping key value */
7945                 if (is_publickey_mech(mech.cm_type)) {
7946                         if ((error = dprov_key_attr_asymmetric(softc,
7947                             session_id, taskq_req->dr_type,
7948                             taskq_req->dr_key_req.kr_key,
7949                             &key)) != CRYPTO_SUCCESS)
7950                                 break;
7951                         keyp = &key;
7952                 } else {
7953                         if ((error = dprov_key_value_secret(softc,
7954                             session_id, taskq_req->dr_type,
7955                             taskq_req->dr_key_req.kr_key,
7956                             &key)) != CRYPTO_SUCCESS)
7957                                 break;
7958                         keyp = &key;
7959                 }
7960 
7961                 /* get the software provider for this mechanism */
7962                 if ((error = dprov_get_sw_prov(mechp, &pd,
7963                     &mech.cm_type)) != CRYPTO_SUCCESS)
7964                         break;
7965 
7966                 wrapped_key = taskq_req->dr_key_req.kr_wrapped_key;
7967                 wrapped_key_len = *taskq_req->dr_key_req.kr_wrapped_key_len_ptr;
7968                 ciphertext.cd_format = CRYPTO_DATA_RAW;
7969                 ciphertext.cd_offset = 0;
7970                 ciphertext.cd_length = wrapped_key_len;
7971                 ciphertext.cd_raw.iov_base = (char *)wrapped_key;
7972                 ciphertext.cd_raw.iov_len = wrapped_key_len;
7973                 ciphertext.cd_miscdata = NULL;
7974 
7975                 /*
7976                  * Plaintext length is less than or equal to
7977                  * the length of the ciphertext.
7978                  */
7979                 plaintext_buf = kmem_alloc(wrapped_key_len, KM_SLEEP);
7980                 plaintext.cd_format = CRYPTO_DATA_RAW;
7981                 plaintext.cd_offset = 0;
7982                 plaintext.cd_length = wrapped_key_len;
7983                 plaintext.cd_raw.iov_base = plaintext_buf;
7984                 plaintext.cd_raw.iov_len = wrapped_key_len;
7985                 plaintext.cd_miscdata = NULL;
7986 
7987                 error = crypto_decrypt_prov(pd, 0, &mech, &ciphertext, keyp,
7988                     NULL, &plaintext, NULL);
7989 
7990                 KCF_PROV_REFRELE(pd);
7991 
7992                 if (error != CRYPTO_SUCCESS)
7993                         goto free_unwrapped_key;
7994 
7995                 error = dprov_create_object_from_template(softc, session,
7996                     template, attribute_count, object_id_ptr, B_FALSE, B_FALSE);
7997 
7998                 if (error != CRYPTO_SUCCESS)
7999                         goto free_unwrapped_key;
8000 
8001                 switch (class) {
8002                 case DPROV_CKO_SECRET_KEY:
8003                         unwrapped_key.oa_type = DPROV_CKA_VALUE;
8004                         unwrapped_key.oa_value_len = plaintext.cd_length;
8005                         unwrapped_key.oa_value = plaintext_buf;
8006                         break;
8007                 case DPROV_CKO_PRIVATE_KEY:
8008                         /*
8009                          * PKCS#11 says that ASN.1 should be used to encode
8010                          * specific attributes before encrypting the blob.
8011                          * We only encrypt the private exponent for the
8012                          * purpose of testing.
8013                          */
8014                         unwrapped_key.oa_type = DPROV_CKA_PRIVATE_EXPONENT;
8015                         unwrapped_key.oa_value_len = plaintext.cd_length;
8016                         unwrapped_key.oa_value = plaintext_buf;
8017                         break;
8018                 default:
8019                         error = CRYPTO_TEMPLATE_INCONSISTENT;
8020                         goto free_unwrapped_key;
8021                 }
8022 
8023                 if ((error = dprov_object_set_attr(session, *object_id_ptr,
8024                     &unwrapped_key, 1, B_FALSE)) == CRYPTO_SUCCESS)
8025                         break;  /* don't free the unwrapped key */
8026 
8027                 /* failure */
8028                 (void) dprov_destroy_object(softc, session, *object_id_ptr);
8029                 break;
8030 
8031 free_unwrapped_key:
8032                 bzero(plaintext_buf, wrapped_key_len);
8033                 kmem_free(plaintext_buf, wrapped_key_len);
8034                 break;
8035         }
8036 
8037         case DPROV_REQ_KEY_DERIVE: {
8038                 crypto_mechanism_t digest_mech, *mechp;
8039                 crypto_key_t key, *base_keyp;
8040                 crypto_object_id_t *object_id_ptr;
8041                 crypto_data_t data;
8042                 crypto_data_t digest;
8043                 size_t hash_size;
8044                 char *digest_buf;
8045                 crypto_object_attribute_t derived_key;
8046                 crypto_object_attribute_t *template;
8047                 uint_t attribute_count;
8048                 ulong_t key_type;
8049                 void *value;
8050                 size_t value_len = 0;
8051 
8052                 error = CRYPTO_SUCCESS;
8053 
8054                 template = taskq_req->dr_key_req.kr_template;
8055                 attribute_count = taskq_req->dr_key_req.kr_attribute_count;
8056                 object_id_ptr = taskq_req->dr_key_req.kr_object_id_ptr;
8057 
8058                 /* required */
8059                 if (dprov_get_template_attr_ulong(template, attribute_count,
8060                     DPROV_CKA_KEY_TYPE, &key_type) != CRYPTO_SUCCESS) {
8061                         error = CRYPTO_TEMPLATE_INCOMPLETE;
8062                         break;
8063                 }
8064 
8065                 mechp = taskq_req->dr_key_req.kr_mechanism;
8066                 /* structure assignment */
8067                 digest_mech = *mechp;
8068 
8069                 switch (digest_mech.cm_type) {
8070                 case SHA1_KEY_DERIVATION_MECH_INFO_TYPE:
8071                         hash_size = SHA1_DIGEST_LEN;
8072                         digest_mech.cm_type = SHA1_MECH_INFO_TYPE;
8073                         break;
8074 
8075                 case SHA256_KEY_DERIVATION_MECH_INFO_TYPE:
8076                         hash_size = SHA256_DIGEST_LENGTH;
8077                         digest_mech.cm_type = SHA256_MECH_INFO_TYPE;
8078                         break;
8079 
8080                 case SHA384_KEY_DERIVATION_MECH_INFO_TYPE:
8081                         hash_size = SHA384_DIGEST_LENGTH;
8082                         digest_mech.cm_type = SHA384_MECH_INFO_TYPE;
8083                         break;
8084 
8085                 case SHA512_KEY_DERIVATION_MECH_INFO_TYPE:
8086                         hash_size = SHA512_DIGEST_LENGTH;
8087                         digest_mech.cm_type = SHA512_MECH_INFO_TYPE;
8088                         break;
8089 
8090                 case MD5_KEY_DERIVATION_MECH_INFO_TYPE:
8091                         hash_size = MD5_DIGEST_LEN;
8092                         digest_mech.cm_type = MD5_MECH_INFO_TYPE;
8093                         break;
8094 
8095                 default:
8096                         error = CRYPTO_MECHANISM_INVALID;
8097                 }
8098 
8099                 if (error != CRYPTO_SUCCESS)
8100                         break;
8101 
8102                 /* CKA_VALUE is optional */
8103                 (void) dprov_get_template_attr_array(template, attribute_count,
8104                     DPROV_CKA_VALUE, &value, &value_len);
8105 
8106                 /* check for inconsistent value length */
8107                 switch (key_type) {
8108                 case DPROV_CKK_GENERIC_SECRET:
8109                         if (value_len > 0) {
8110                                 if (value_len > hash_size)
8111                                         error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
8112                         } else {
8113                                 value_len = hash_size;
8114                         }
8115                         break;
8116 
8117                 case DPROV_CKK_RC4:
8118                 case DPROV_CKK_AES:
8119                         if (value_len == 0 ||
8120                             value_len > hash_size) {
8121                                 error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
8122                         }
8123                         break;
8124 
8125                 case DPROV_CKK_DES:
8126                         if (value_len > 0 &&
8127                             value_len != DES_KEY_LEN) {
8128                                 error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
8129                         }
8130                         value_len = DES_KEY_LEN;
8131                         break;
8132 
8133                 case DPROV_CKK_DES3:
8134                         if (value_len > 0 &&
8135                             value_len != DES3_KEY_LEN) {
8136                                 error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
8137                         }
8138                         value_len = DES3_KEY_LEN;
8139                         break;
8140 
8141                 default:
8142                         error = CRYPTO_ATTRIBUTE_VALUE_INVALID;
8143                         break;
8144                 }
8145 
8146                 if (error != CRYPTO_SUCCESS)
8147                         break;
8148 
8149                 /* get the software provider for this mechanism */
8150                 if ((error = dprov_get_sw_prov(&digest_mech, &pd,
8151                     &digest_mech.cm_type)) != CRYPTO_SUCCESS)
8152                         break;
8153 
8154                 /* get the base key */
8155                 error = dprov_key_value_secret(softc, session_id,
8156                     taskq_req->dr_type, taskq_req->dr_key_req.kr_key, &key);
8157                 if (error != CRYPTO_SUCCESS)
8158                         break;
8159 
8160                 base_keyp = &key;
8161 
8162                 data.cd_format = CRYPTO_DATA_RAW;
8163                 data.cd_offset = 0;
8164                 data.cd_length = CRYPTO_BITS2BYTES(base_keyp->ck_length);
8165                 data.cd_raw.iov_base = base_keyp->ck_data;
8166                 data.cd_raw.iov_len = data.cd_length;
8167 
8168                 digest_buf = kmem_alloc(hash_size, KM_SLEEP);
8169                 digest.cd_format = CRYPTO_DATA_RAW;
8170                 digest.cd_offset = 0;
8171                 digest.cd_length = hash_size;
8172                 digest.cd_raw.iov_base = digest_buf;
8173                 digest.cd_raw.iov_len = hash_size;
8174 
8175                 error = crypto_digest_prov(pd, 0, &digest_mech, &data,
8176                     &digest, NULL);
8177 
8178                 KCF_PROV_REFRELE(pd);
8179 
8180                 if (error != CRYPTO_SUCCESS)
8181                         goto free_derived_key;
8182 
8183                 error = dprov_create_object_from_template(softc, session,
8184                     template, attribute_count, object_id_ptr, B_FALSE, B_FALSE);
8185 
8186                 if (error != CRYPTO_SUCCESS)
8187                         goto free_derived_key;
8188 
8189                 derived_key.oa_type = DPROV_CKA_VALUE;
8190                 derived_key.oa_value = digest_buf;
8191                 derived_key.oa_value_len = value_len;
8192 
8193                 error = dprov_object_set_attr(session, *object_id_ptr,
8194                     &derived_key, 1, B_FALSE);
8195 
8196                 if (error != CRYPTO_SUCCESS) {
8197                         (void) dprov_destroy_object(softc, session,
8198                             *object_id_ptr);
8199                 }
8200 
8201 free_derived_key:
8202                 bzero(digest_buf, hash_size);
8203                 kmem_free(digest_buf, hash_size);
8204                 break;
8205         }
8206 
8207         case DPROV_REQ_NOSTORE_KEY_GENERATE: {
8208                 crypto_object_attribute_t *out_template;
8209                 uint_t out_attribute_count;
8210                 void *value;
8211                 size_t value_len = 0;
8212 
8213                 out_template = taskq_req->dr_key_req.kr_out_template1;
8214                 out_attribute_count =
8215                     taskq_req->dr_key_req.kr_out_attribute_count1;
8216 
8217                 error = dprov_get_template_attr_array(out_template,
8218                     out_attribute_count, DPROV_CKA_VALUE, &value, &value_len);
8219                 if (error != CRYPTO_SUCCESS)
8220                         break;
8221 
8222                 /* fill the entire array with pattern */
8223                 {
8224                         int i = 0;
8225                         char *p = value;
8226                         while (i < value_len) {
8227                                 p[i++] = 'A';
8228                                 if (i >= value_len)
8229                                         break;
8230                                 p[i++] = 'B';
8231                                 if (i >= value_len)
8232                                         break;
8233                                 p[i++] = 'C';
8234                         }
8235                 }
8236 
8237                 error = CRYPTO_SUCCESS;
8238                 break;
8239         }
8240 
8241         case DPROV_REQ_NOSTORE_KEY_GENERATE_PAIR: {
8242                 crypto_mechanism_t *mechp;
8243                 crypto_object_attribute_t *pub_template;
8244                 crypto_object_attribute_t *pri_template;
8245                 uint_t pub_attribute_count;
8246                 uint_t pri_attribute_count;
8247                 crypto_object_attribute_t *out_pub_template;
8248                 crypto_object_attribute_t *out_pri_template;
8249                 uint_t out_pub_attribute_count;
8250                 uint_t out_pri_attribute_count;
8251 
8252                 mechp = taskq_req->dr_key_req.kr_mechanism;
8253                 pub_template = taskq_req->dr_key_req.kr_template;
8254                 pub_attribute_count = taskq_req->dr_key_req.kr_attribute_count;
8255                 pri_template = taskq_req->dr_key_req.kr_private_key_template;
8256                 pri_attribute_count =
8257                     taskq_req->dr_key_req.kr_private_key_attribute_count;
8258                 out_pub_template = taskq_req->dr_key_req.kr_out_template1;
8259                 out_pub_attribute_count =
8260                     taskq_req->dr_key_req.kr_out_attribute_count1;
8261                 out_pri_template = taskq_req->dr_key_req.kr_out_template2;
8262                 out_pri_attribute_count =
8263                     taskq_req->dr_key_req.kr_out_attribute_count2;
8264 
8265                 switch (mechp->cm_type) {
8266                 case RSA_PKCS_KEY_PAIR_GEN_MECH_INFO_TYPE:
8267                         error = nostore_copy_attribute(out_pub_template,
8268                             out_pub_attribute_count, DPROV_CKA_MODULUS);
8269                         if (error != CRYPTO_SUCCESS)
8270                                 break;
8271 
8272                         error = nostore_copy_attribute(out_pub_template,
8273                             out_pub_attribute_count, DPROV_CKA_PUBLIC_EXPONENT);
8274                         if (error == CRYPTO_ARGUMENTS_BAD) {
8275                                 size_t tmp_len = 0;
8276                                 void *tmp;
8277 
8278                                 /* public exponent must be here */
8279                                 error = dprov_get_template_attr_array(
8280                                     pub_template, pub_attribute_count,
8281                                     DPROV_CKA_PUBLIC_EXPONENT, &tmp, &tmp_len);
8282                                 if (error != CRYPTO_SUCCESS)
8283                                         break;
8284                         }
8285                         error = nostore_copy_attribute(out_pri_template,
8286                             out_pri_attribute_count, DPROV_CKA_MODULUS);
8287                         if (error != CRYPTO_SUCCESS)
8288                                 break;
8289 
8290                         error = nostore_copy_attribute(out_pri_template,
8291                             out_pri_attribute_count,
8292                             DPROV_CKA_PRIVATE_EXPONENT);
8293                         break;
8294 
8295                 case DH_PKCS_KEY_PAIR_GEN_MECH_INFO_TYPE:
8296                         /*
8297                          * There is no software provider for DH mechanism;
8298                          * Just return pre-defined values.
8299                          */
8300                         error = nostore_copy_attribute(out_pub_template,
8301                             out_pub_attribute_count, DPROV_CKA_VALUE);
8302                         error = nostore_copy_attribute(out_pri_template,
8303                             out_pri_attribute_count, DPROV_CKA_VALUE);
8304                         break;
8305 
8306                 case EC_KEY_PAIR_GEN_MECH_INFO_TYPE: {
8307                         crypto_mechanism_t mech, *mechp;
8308                         kcf_req_params_t params;
8309                         crypto_object_attribute_t *pub_template;
8310                         uint_t pub_attribute_count;
8311                         crypto_object_attribute_t *out_pub_template;
8312                         crypto_object_attribute_t *out_pri_template;
8313                         uint_t out_pub_attribute_count;
8314                         uint_t out_pri_attribute_count;
8315 
8316                         mechp = taskq_req->dr_key_req.kr_mechanism;
8317                         pub_template = taskq_req->dr_key_req.kr_template;
8318                         pub_attribute_count =
8319                             taskq_req->dr_key_req.kr_attribute_count;
8320                         out_pub_template =
8321                             taskq_req->dr_key_req.kr_out_template1;
8322                         out_pub_attribute_count =
8323                             taskq_req->dr_key_req.kr_out_attribute_count1;
8324                         out_pri_template =
8325                             taskq_req->dr_key_req.kr_out_template2;
8326                         out_pri_attribute_count =
8327                             taskq_req->dr_key_req.kr_out_attribute_count2;
8328 
8329                         /* get the software provider for this mechanism */
8330                         mech = *mechp;
8331                         if ((error = dprov_get_sw_prov(mechp, &pd,
8332                             &mech.cm_type)) != CRYPTO_SUCCESS)
8333                                 break;
8334                         /*
8335                          * Turn 32-bit values into 64-bit values for certain
8336                          * attributes like CKA_CLASS.
8337                          */
8338                         dprov_adjust_attrs(pub_template, pub_attribute_count);
8339                         dprov_adjust_attrs(pri_template, pri_attribute_count);
8340 
8341                         /* bypass the kernel API for now */
8342                         KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(&params,
8343                             KCF_OP_KEY_GENERATE_PAIR,
8344                             0, /* session 0 for sw provider */
8345                             &mech, pub_template, pub_attribute_count,
8346                             pri_template, pri_attribute_count, NULL,
8347                             out_pub_template, out_pub_attribute_count,
8348                             out_pri_template, out_pri_attribute_count);
8349 
8350                         error = kcf_submit_request(pd, NULL, NULL, &params,
8351                             B_FALSE);
8352 
8353                         KCF_PROV_REFRELE(pd);
8354                         break;
8355                 }
8356                 default:
8357                         error = CRYPTO_MECHANISM_INVALID;
8358                 }
8359                 break;
8360         }
8361 
8362         case DPROV_REQ_NOSTORE_KEY_DERIVE: {
8363                 crypto_mechanism_t *mechp;
8364                 crypto_object_attribute_t *in_template, *out_template;
8365                 crypto_key_t *base_key;
8366                 uint_t in_attribute_count, out_attribute_count;
8367                 ulong_t key_type;
8368                 void *value;
8369                 size_t value_len = 0;
8370                 size_t value_len_value = 0;
8371 
8372                 in_template = taskq_req->dr_key_req.kr_template;
8373                 out_template = taskq_req->dr_key_req.kr_out_template1;
8374                 in_attribute_count = taskq_req->dr_key_req.kr_attribute_count;
8375                 out_attribute_count =
8376                     taskq_req->dr_key_req.kr_out_attribute_count1;
8377                 mechp = taskq_req->dr_key_req.kr_mechanism;
8378                 base_key = taskq_req->dr_key_req.kr_key;
8379 
8380                 /*
8381                  * CKA_VALUE must be present so the derived key can
8382                  * be returned by value.
8383                  */
8384                 if (dprov_get_template_attr_array(out_template,
8385                     out_attribute_count, DPROV_CKA_VALUE, &value,
8386                     &value_len) != CRYPTO_SUCCESS) {
8387                         error = CRYPTO_TEMPLATE_INCOMPLETE;
8388                         break;
8389                 }
8390 
8391                 if (dprov_get_template_attr_ulong(in_template,
8392                     in_attribute_count, DPROV_CKA_KEY_TYPE,
8393                     &key_type) != CRYPTO_SUCCESS) {
8394                         error = CRYPTO_TEMPLATE_INCOMPLETE;
8395                         break;
8396                 }
8397                 switch (mechp->cm_type) {
8398                 case DH_PKCS_DERIVE_MECH_INFO_TYPE: {
8399                         size_t tmp_len = 0;
8400                         void *tmp;
8401 
8402                         if (base_key->ck_format != CRYPTO_KEY_ATTR_LIST) {
8403                                 error = CRYPTO_ARGUMENTS_BAD;
8404                                 break;
8405                         }
8406 
8407                         if ((dprov_get_template_attr_array(base_key->ck_attrs,
8408                             base_key->ck_count, DPROV_CKA_BASE, &tmp,
8409                             &tmp_len) != CRYPTO_SUCCESS) ||
8410                             (dprov_get_template_attr_array(base_key->ck_attrs,
8411                             base_key->ck_count, DPROV_CKA_PRIME, &tmp,
8412                             &tmp_len) != CRYPTO_SUCCESS) ||
8413                             (dprov_get_template_attr_array(base_key->ck_attrs,
8414                             base_key->ck_count, DPROV_CKA_VALUE, &tmp,
8415                             &tmp_len) != CRYPTO_SUCCESS)) {
8416                                 error = CRYPTO_TEMPLATE_INCOMPLETE;
8417                                 break;
8418                         }
8419 
8420                         /*
8421                          * CKA_VALUE is added to the derived key template by
8422                          * the library.
8423                          */
8424                         error = CRYPTO_SUCCESS;
8425                         switch (key_type) {
8426                         case DPROV_CKK_AES:
8427                                 if (dprov_get_template_attr_ulong(in_template,
8428                                     in_attribute_count, DPROV_CKA_VALUE_LEN,
8429                                     &value_len_value) != CRYPTO_SUCCESS) {
8430                                         error = CRYPTO_TEMPLATE_INCOMPLETE;
8431                                         break;
8432                                 }
8433                                 if (value_len != value_len_value) {
8434                                         error = CRYPTO_TEMPLATE_INCONSISTENT;
8435                                         break;
8436                                 }
8437                         default:
8438                                 error = CRYPTO_MECHANISM_INVALID;
8439                         }
8440                         if (error == CRYPTO_SUCCESS)
8441                                 fill_dh(value, value_len);
8442                         break;
8443                 }
8444                 case ECDH1_DERIVE_MECH_INFO_TYPE: {
8445                         crypto_mechanism_t mech;
8446                         kcf_req_params_t params;
8447 
8448                         /* get the software provider for this mechanism */
8449                         mech = *mechp;
8450                         if ((error = dprov_get_sw_prov(mechp, &pd,
8451                             &mech.cm_type)) != CRYPTO_SUCCESS)
8452                                 break;
8453 
8454                         /*
8455                          * Turn 32-bit values into 64-bit values for certain
8456                          * attributes like CKA_VALUE_LEN.
8457                          */
8458                         dprov_adjust_attrs(in_template, in_attribute_count);
8459 
8460                         /* bypass the kernel API for now */
8461                         KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(&params,
8462                             KCF_OP_KEY_DERIVE,
8463                             0, /* session 0 for sw provider */
8464                             &mech, in_template, in_attribute_count,
8465                             NULL, 0, base_key,
8466                             out_template, out_attribute_count,
8467                             NULL, 0);
8468 
8469                         error = kcf_submit_request(pd, NULL, NULL, &params,
8470                             B_FALSE);
8471 
8472                         KCF_PROV_REFRELE(pd);
8473                         break;
8474                 }
8475 
8476                 default:
8477                         error = CRYPTO_MECHANISM_INVALID;
8478                 }
8479                 break;
8480         default:
8481                 error = CRYPTO_MECHANISM_INVALID;
8482         }
8483         } /* end case */
8484 
8485         mutex_exit(&softc->ds_lock);
8486         dprov_op_done(taskq_req, error);
8487         DPROV_DEBUG(D_KEY, ("(%d) dprov_key_task: end\n", instance));
8488 }
8489 
8490 /*
8491  * taskq dispatcher function for provider management operations.
8492  */
8493 static void
8494 dprov_mgmt_task(dprov_req_t *taskq_req)
8495 {
8496         dprov_state_t *softc;
8497         /* LINTED E_FUNC_SET_NOT_USED */
8498         int instance;
8499         int error = CRYPTO_NOT_SUPPORTED;
8500 
8501         DPROV_SOFTC_FROM_REQ(taskq_req, softc, instance);
8502         DPROV_DEBUG(D_DIGEST, ("(%d) dprov_mgmt_task: started\n", instance));
8503 
8504         mutex_enter(&softc->ds_lock);
8505 
8506         switch (taskq_req->dr_type) {
8507         case DPROV_REQ_MGMT_EXTINFO: {
8508                 crypto_provider_ext_info_t *ext_info =
8509                     taskq_req->dr_mgmt_req.mr_ext_info;
8510 
8511                 (void) memset(ext_info->ei_label, ' ', CRYPTO_EXT_SIZE_LABEL);
8512                 if (!softc->ds_token_initialized) {
8513                         bcopy("(not initialized)", ext_info->ei_label,
8514                             strlen("(not initialized)"));
8515                 } else {
8516                         bcopy(softc->ds_label, ext_info->ei_label,
8517                             CRYPTO_EXT_SIZE_LABEL);
8518                 }
8519 
8520                 bcopy(DPROV_MANUFACTURER, ext_info->ei_manufacturerID,
8521                     CRYPTO_EXT_SIZE_MANUF);
8522                 bcopy(DPROV_MODEL, ext_info->ei_model, CRYPTO_EXT_SIZE_MODEL);
8523 
8524                 (void) snprintf((char *)ext_info->ei_serial_number, 16, "%d%s",
8525                     instance, DPROV_ALLSPACES);
8526                 /* PKCS#11 blank padding */
8527                 ext_info->ei_serial_number[15] = ' ';
8528                 ext_info->ei_max_session_count = CRYPTO_EFFECTIVELY_INFINITE;
8529                 ext_info->ei_max_pin_len = (ulong_t)DPROV_MAX_PIN_LEN;
8530                 ext_info->ei_min_pin_len = 1;
8531                 ext_info->ei_total_public_memory = CRYPTO_EFFECTIVELY_INFINITE;
8532                 ext_info->ei_free_public_memory = CRYPTO_EFFECTIVELY_INFINITE;
8533                 ext_info->ei_total_private_memory = CRYPTO_EFFECTIVELY_INFINITE;
8534                 ext_info->ei_free_private_memory = CRYPTO_EFFECTIVELY_INFINITE;
8535                 ext_info->ei_hardware_version.cv_major = 1;
8536                 ext_info->ei_hardware_version.cv_minor = 0;
8537                 ext_info->ei_firmware_version.cv_major = 1;
8538                 ext_info->ei_firmware_version.cv_minor = 0;
8539 
8540                 ext_info->ei_flags = CRYPTO_EXTF_RNG |
8541                     CRYPTO_EXTF_LOGIN_REQUIRED |
8542                     CRYPTO_EXTF_DUAL_CRYPTO_OPERATIONS;
8543                 if (softc->ds_user_pin_set)
8544                         ext_info->ei_flags |= CRYPTO_EXTF_USER_PIN_INITIALIZED;
8545                 if (softc->ds_token_initialized)
8546                         ext_info->ei_flags |= CRYPTO_EXTF_TOKEN_INITIALIZED;
8547 
8548                 ext_info->ei_hash_max_input_len = dprov_max_digestsz;
8549                 ext_info->ei_hmac_max_input_len = dprov_max_digestsz;
8550                 error = CRYPTO_SUCCESS;
8551                 break;
8552         }
8553         case DPROV_REQ_MGMT_INITTOKEN: {
8554                 char *pin = taskq_req->dr_mgmt_req.mr_pin;
8555                 size_t pin_len = taskq_req->dr_mgmt_req.mr_pin_len;
8556                 char *label = taskq_req->dr_mgmt_req.mr_label;
8557 
8558                 /* cannot initialize token when a session is open */
8559                 if (softc->ds_sessions_count > 0) {
8560                         error = CRYPTO_SESSION_EXISTS;
8561                         break;
8562                 }
8563 
8564                 /* check PIN length */
8565                 if (pin_len > DPROV_MAX_PIN_LEN) {
8566                         error = CRYPTO_PIN_LEN_RANGE;
8567                         break;
8568                 }
8569 
8570                 /* check PIN */
8571                 if (pin == NULL) {
8572                         error = CRYPTO_PIN_INVALID;
8573                         break;
8574                 }
8575 
8576                 /*
8577                  * If the token has already been initialized, need
8578                  * to validate supplied PIN.
8579                  */
8580                 if (softc->ds_token_initialized &&
8581                     (softc->ds_so_pin_len != pin_len ||
8582                     strncmp(softc->ds_so_pin, pin, pin_len) != 0)) {
8583                         /* invalid SO PIN */
8584                         error = CRYPTO_PIN_INCORRECT;
8585                         break;
8586                 }
8587 
8588                 /* set label */
8589                 bcopy(label, softc->ds_label, CRYPTO_EXT_SIZE_LABEL);
8590 
8591                 /* set new SO PIN, update state */
8592                 bcopy(pin, softc->ds_so_pin, pin_len);
8593                 softc->ds_so_pin_len = pin_len;
8594                 softc->ds_token_initialized = B_TRUE;
8595                 softc->ds_user_pin_set = B_FALSE;
8596 
8597                 error = CRYPTO_SUCCESS;
8598                 break;
8599         }
8600         case DPROV_REQ_MGMT_INITPIN: {
8601                 char *pin = taskq_req->dr_mgmt_req.mr_pin;
8602                 size_t pin_len = taskq_req->dr_mgmt_req.mr_pin_len;
8603                 crypto_session_id_t session_id =
8604                     taskq_req->dr_mgmt_req.mr_session_id;
8605 
8606                 /* check session id */
8607                 if (softc->ds_sessions[session_id] == NULL) {
8608                         error = CRYPTO_SESSION_HANDLE_INVALID;
8609                         break;
8610                 }
8611 
8612                 /* fail if not logged in as SO */
8613                 if (softc->ds_sessions[session_id]->ds_state !=
8614                     DPROV_SESSION_STATE_SO) {
8615                         error = CRYPTO_USER_NOT_LOGGED_IN;
8616                         break;
8617                 }
8618 
8619                 /* check PIN length */
8620                 if (pin_len > DPROV_MAX_PIN_LEN) {
8621                         error = CRYPTO_PIN_LEN_RANGE;
8622                         break;
8623                 }
8624 
8625                 /* check PIN */
8626                 if (pin == NULL) {
8627                         error = CRYPTO_PIN_INVALID;
8628                         break;
8629                 }
8630 
8631                 /* set new normal user PIN */
8632                 bcopy(pin, softc->ds_user_pin, pin_len);
8633                 softc->ds_user_pin_len = pin_len;
8634                 softc->ds_user_pin_set = B_TRUE;
8635 
8636                 error = CRYPTO_SUCCESS;
8637                 break;
8638         }
8639         case DPROV_REQ_MGMT_SETPIN: {
8640                 char *new_pin = taskq_req->dr_mgmt_req.mr_pin;
8641                 size_t new_pin_len = taskq_req->dr_mgmt_req.mr_pin_len;
8642                 char *old_pin = taskq_req->dr_mgmt_req.mr_old_pin;
8643                 size_t old_pin_len = taskq_req->dr_mgmt_req.mr_old_pin_len;
8644                 crypto_session_id_t session_id =
8645                     taskq_req->dr_mgmt_req.mr_session_id;
8646 
8647                 /* check session id */
8648                 if (softc->ds_sessions[session_id] == NULL) {
8649                         error = CRYPTO_SESSION_HANDLE_INVALID;
8650                         break;
8651                 }
8652 
8653                 /* check PIN length */
8654                 if (old_pin_len > DPROV_MAX_PIN_LEN ||
8655                     new_pin_len > DPROV_MAX_PIN_LEN) {
8656                         error = CRYPTO_PIN_LEN_RANGE;
8657                         break;
8658                 }
8659 
8660                 /* check PIN */
8661                 if (old_pin == NULL || new_pin == NULL) {
8662                         error = CRYPTO_PIN_INVALID;
8663                         break;
8664                 }
8665 
8666                 /* check user PIN state */
8667                 if (!softc->ds_user_pin_set) {
8668                         error = CRYPTO_USER_PIN_NOT_INITIALIZED;
8669                         break;
8670                 }
8671 
8672                 /*
8673                  * If the token has already been initialized, need
8674                  * to validate supplied PIN.
8675                  */
8676                 if (softc->ds_user_pin_len != old_pin_len ||
8677                     strncmp(softc->ds_user_pin, old_pin, old_pin_len) != 0) {
8678                         /* invalid SO PIN */
8679                         error = CRYPTO_PIN_INCORRECT;
8680                         break;
8681                 }
8682 
8683                 /* set new PIN */
8684                 bcopy(new_pin, softc->ds_user_pin, new_pin_len);
8685                 softc->ds_user_pin_len = new_pin_len;
8686 
8687                 error = CRYPTO_SUCCESS;
8688                 break;
8689         }
8690         }
8691 
8692         mutex_exit(&softc->ds_lock);
8693         dprov_op_done(taskq_req, error);
8694         DPROV_DEBUG(D_DIGEST, ("(%d) dprov_mgmt_task: end\n", instance));
8695 }
8696 
8697 /*
8698  * Returns in the location pointed to by pd a pointer to the descriptor
8699  * for the software provider for the specified mechanism.
8700  * The provider descriptor is returned held. Returns one of the CRYPTO_
8701  * error codes on failure, CRYPTO_SUCCESS on success.
8702  */
8703 static int
8704 dprov_get_sw_prov(crypto_mechanism_t *mech, kcf_provider_desc_t **pd,
8705     crypto_mech_type_t *provider_mech_type)
8706 {
8707         crypto_mech_type_t kcf_mech_type = CRYPTO_MECH_INVALID;
8708         int i, rv;
8709 
8710         /* lookup the KCF mech type associated with our mech type */
8711         for (i = 0; i < sizeof (dprov_mech_info_tab)/
8712             sizeof (crypto_mech_info_t); i++) {
8713                 if (mech->cm_type == dprov_mech_info_tab[i].cm_mech_number) {
8714                         kcf_mech_type = crypto_mech2id_common(
8715                             dprov_mech_info_tab[i].cm_mech_name, B_TRUE);
8716                 }
8717         }
8718 
8719         rv = kcf_get_sw_prov(kcf_mech_type, pd, NULL, B_TRUE);
8720         if (rv == CRYPTO_SUCCESS)
8721                 *provider_mech_type = kcf_mech_type;
8722 
8723         return (rv);
8724 }
8725 
8726 /*
8727  * Object management helper functions.
8728  */
8729 
8730 /*
8731  * Given a crypto_key_t, return whether the key can be used or not
8732  * for the specified request. The attributes used here are defined
8733  * in table 42 of the PKCS#11 spec (Common secret key attributes).
8734  */
8735 static int
8736 dprov_key_can_use(dprov_object_t *object, dprov_req_type_t req_type)
8737 {
8738         boolean_t ret = 0;
8739         int rv = CRYPTO_SUCCESS;
8740 
8741         /* check if object is allowed for specified operation */
8742         switch (req_type) {
8743         case DPROV_REQ_ENCRYPT_INIT:
8744         case DPROV_REQ_ENCRYPT_ATOMIC:
8745                 rv = dprov_get_object_attr_boolean(object,
8746                     DPROV_CKA_ENCRYPT, &ret);
8747                 break;
8748         case DPROV_REQ_DECRYPT_INIT:
8749         case DPROV_REQ_DECRYPT_ATOMIC:
8750                 rv = dprov_get_object_attr_boolean(object,
8751                     DPROV_CKA_DECRYPT, &ret);
8752                 break;
8753         case DPROV_REQ_SIGN_INIT:
8754         case DPROV_REQ_SIGN_ATOMIC:
8755         case DPROV_REQ_MAC_INIT:
8756         case DPROV_REQ_MAC_ATOMIC:
8757         case DPROV_REQ_MAC_VERIFY_ATOMIC:
8758                 rv = dprov_get_object_attr_boolean(object,
8759                     DPROV_CKA_SIGN, &ret);
8760                 break;
8761         case DPROV_REQ_SIGN_RECOVER_INIT:
8762         case DPROV_REQ_SIGN_RECOVER_ATOMIC:
8763                 rv = dprov_get_object_attr_boolean(object,
8764                     DPROV_CKA_SIGN_RECOVER, &ret);
8765                 break;
8766         case DPROV_REQ_VERIFY_INIT:
8767         case DPROV_REQ_VERIFY_ATOMIC:
8768                 rv = dprov_get_object_attr_boolean(object,
8769                     DPROV_CKA_VERIFY, &ret);
8770                 break;
8771         case DPROV_REQ_VERIFY_RECOVER_INIT:
8772         case DPROV_REQ_VERIFY_RECOVER_ATOMIC:
8773                 rv = dprov_get_object_attr_boolean(object,
8774                     DPROV_CKA_VERIFY_RECOVER, &ret);
8775                 break;
8776         case DPROV_REQ_KEY_WRAP:
8777                 rv = dprov_get_object_attr_boolean(object,
8778                     DPROV_CKA_WRAP, &ret);
8779                 break;
8780         case DPROV_REQ_KEY_UNWRAP:
8781                 rv = dprov_get_object_attr_boolean(object,
8782                     DPROV_CKA_UNWRAP, &ret);
8783                 break;
8784         case DPROV_REQ_DIGEST_KEY:
8785                 /*
8786                  * There is no attribute to check for; therefore,
8787                  * any secret key can be used.
8788                  */
8789                 ret = B_TRUE;
8790                 rv = CRYPTO_SUCCESS;
8791                 break;
8792         case DPROV_REQ_KEY_DERIVE:
8793                 rv = dprov_get_object_attr_boolean(object,
8794                     DPROV_CKA_DERIVE, &ret);
8795                 break;
8796         }
8797 
8798         if (rv != CRYPTO_SUCCESS || !ret)
8799                 return (CRYPTO_KEY_FUNCTION_NOT_PERMITTED);
8800 
8801         return (CRYPTO_SUCCESS);
8802 }
8803 
8804 /*
8805  * Given a crypto_key_t corresponding to a secret key (i.e. for
8806  * use with symmetric crypto algorithms) specified in raw format, by
8807  * attribute, or by reference, initialize the ck_data and ck_length
8808  * fields of the ret_key argument so that they specify the key value
8809  * and length.
8810  *
8811  * For a key by value, this function uess the ck_data and ck_length,
8812  * for a key by reference, it looks up the corresponding object and
8813  * returns the appropriate attribute. For a key by attribute, it returns
8814  * the appropriate attribute. The attributes used are CKA_VALUE to retrieve
8815  * the value of the key, and CKA_VALUE_LEN to retrieve its length in bytes.
8816  */
8817 static int
8818 dprov_key_value_secret(dprov_state_t *softc, crypto_session_id_t session_id,
8819     dprov_req_type_t req_type, crypto_key_t *key, crypto_key_t *ret_key)
8820 {
8821         ulong_t key_type;
8822         int ret = CRYPTO_SUCCESS;
8823 
8824         ret_key->ck_format = CRYPTO_KEY_RAW;
8825 
8826         switch (key->ck_format) {
8827 
8828         case CRYPTO_KEY_RAW:
8829                 ret_key->ck_data = key->ck_data;
8830                 ret_key->ck_length = key->ck_length;
8831                 break;
8832 
8833         case CRYPTO_KEY_ATTR_LIST: {
8834                 void *value;
8835                 size_t len, value_len;
8836 
8837                 if ((ret = dprov_get_key_attr_ulong(key, DPROV_CKA_KEY_TYPE,
8838                     &key_type)) != CRYPTO_SUCCESS)
8839                         break;
8840 
8841                 if ((ret = dprov_get_key_attr_array(key, DPROV_CKA_VALUE,
8842                     &value, &len)) != CRYPTO_SUCCESS)
8843                         break;
8844 
8845                 /*
8846                  * The length of the array is expressed in bytes.
8847                  * Convert to bits now since that's how keys are measured.
8848                  */
8849                 len  = CRYPTO_BYTES2BITS(len);
8850 
8851                 /* optional */
8852                 if ((dprov_get_key_attr_ulong(key, DPROV_CKA_VALUE_LEN,
8853                     &value_len)) == CRYPTO_SUCCESS) {
8854                         len = value_len;
8855                 }
8856 
8857                 ret_key->ck_data = value;
8858                 ret_key->ck_length = (uint_t)len;
8859 
8860                 break;
8861         }
8862 
8863         case CRYPTO_KEY_REFERENCE: {
8864                 dprov_object_t *object;
8865                 void *value;
8866                 size_t len, value_len;
8867 
8868                 /* check session id */
8869                 if (softc->ds_sessions[session_id] == NULL) {
8870                         ret = CRYPTO_SESSION_HANDLE_INVALID;
8871                         break;
8872                 }
8873 
8874                 if (key->ck_obj_id >= DPROV_MAX_OBJECTS) {
8875                         ret = CRYPTO_KEY_HANDLE_INVALID;
8876                         goto bail;
8877                 }
8878 
8879                 /* check if object id specified by key is valid */
8880                 object = softc->ds_sessions[session_id]->
8881                     ds_objects[key->ck_obj_id];
8882                 if (object == NULL) {
8883                         ret = CRYPTO_KEY_HANDLE_INVALID;
8884                         goto bail;
8885                 }
8886 
8887                 /* check if object can be used for operation */
8888                 if ((ret = dprov_key_can_use(object, req_type)) !=
8889                     CRYPTO_SUCCESS)
8890                         goto bail;
8891 
8892                 if ((ret = dprov_get_object_attr_ulong(object,
8893                     DPROV_CKA_KEY_TYPE, &key_type)) != CRYPTO_SUCCESS)
8894                         goto bail;
8895 
8896                 if ((ret = dprov_get_object_attr_array(object,
8897                     DPROV_CKA_VALUE, &value, &len)) != CRYPTO_SUCCESS)
8898                         goto bail;
8899 
8900                 /* optional */
8901                 if ((dprov_get_object_attr_ulong(object, DPROV_CKA_VALUE_LEN,
8902                     &value_len)) == CRYPTO_SUCCESS) {
8903                         len = value_len;
8904                 }
8905 
8906                 /*
8907                  * The length of attributes are in bytes.
8908                  * Convert to bits now since that's how keys are measured.
8909                  */
8910                 len  = CRYPTO_BYTES2BITS(len);
8911 
8912                 ret_key->ck_data = value;
8913                 ret_key->ck_length = (uint_t)len;
8914 bail:
8915                 break;
8916         }
8917 
8918         default:
8919                 ret = CRYPTO_ARGUMENTS_BAD;
8920                 break;
8921         }
8922 
8923         return (ret);
8924 }
8925 
8926 /*
8927  * Get the attribute list for the specified asymmetric key.
8928  */
8929 static int
8930 dprov_key_attr_asymmetric(dprov_state_t *softc, crypto_session_id_t session_id,
8931     dprov_req_type_t req_type, crypto_key_t *key, crypto_key_t *ret_key)
8932 {
8933         int ret = CRYPTO_SUCCESS;
8934 
8935         ret_key->ck_format = CRYPTO_KEY_ATTR_LIST;
8936 
8937         switch (key->ck_format) {
8938 
8939         case CRYPTO_KEY_ATTR_LIST:
8940                 ret_key->ck_attrs = key->ck_attrs;
8941                 ret_key->ck_count = key->ck_count;
8942                 break;
8943 
8944         case CRYPTO_KEY_REFERENCE: {
8945                 dprov_object_t *object;
8946 
8947                 /* check session id */
8948                 if (softc->ds_sessions[session_id] == NULL) {
8949                         ret = CRYPTO_SESSION_HANDLE_INVALID;
8950                         break;
8951                 }
8952 
8953                 /* check if object id specified by key is valid */
8954                 object = softc->ds_sessions[session_id]->
8955                     ds_objects[key->ck_obj_id];
8956                 if (object == NULL) {
8957                         ret = CRYPTO_KEY_HANDLE_INVALID;
8958                         break;
8959                 }
8960 
8961                 /* check if object can be used for operation */
8962                 if ((ret = dprov_key_can_use(object, req_type)) !=
8963                     CRYPTO_SUCCESS)
8964                         break;
8965 
8966                 ret_key->ck_attrs = object->do_attr;
8967                 ret_key->ck_count = DPROV_MAX_ATTR;
8968                 break;
8969         }
8970 
8971         default:
8972                 ret = CRYPTO_ARGUMENTS_BAD;
8973         }
8974 
8975         return (ret);
8976 }
8977 
8978 /*
8979  * Return the index of an attribute of specified type found in
8980  * the specified array of attributes. If the attribute cannot
8981  * found, return -1.
8982  */
8983 static int
8984 dprov_find_attr(crypto_object_attribute_t *attr, uint_t nattr,
8985     uint64_t attr_type)
8986 {
8987         int i;
8988 
8989         for (i = 0; i < nattr; i++)
8990                 if (attr[i].oa_value != NULL &&
8991                     attr[i].oa_type == attr_type)
8992                         return (i);
8993 
8994         return (-1);
8995 }
8996 
8997 /*
8998  * Given the given object template and session, return whether
8999  * an object can be created from that template according to the
9000  * following rules:
9001  * - private objects can be created only by a logged-in user
9002  */
9003 static int
9004 dprov_template_can_create(dprov_session_t *session,
9005     crypto_object_attribute_t *template, uint_t nattr,
9006     boolean_t check_for_secret)
9007 {
9008         boolean_t is_private = B_FALSE;
9009         ulong_t key_type, class;
9010         int error;
9011 
9012         /* check CKA_PRIVATE attribute value */
9013         error = dprov_get_template_attr_boolean(template, nattr,
9014             DPROV_CKA_PRIVATE, &is_private);
9015         if (error == CRYPTO_SUCCESS && is_private) {
9016                 /* it's a private object */
9017                 if (session->ds_state != DPROV_SESSION_STATE_USER) {
9018                         /*
9019                          * Cannot create private object with SO or public
9020                          * sessions.
9021                          */
9022                         return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
9023                 }
9024         }
9025 
9026         /* all objects must have an object class attribute */
9027         if (dprov_get_template_attr_ulong(template, nattr, DPROV_CKA_CLASS,
9028             &class) != CRYPTO_SUCCESS) {
9029                 return (CRYPTO_TEMPLATE_INCOMPLETE);
9030         }
9031 
9032         /* key objects must have a key type attribute */
9033         if (class == DPROV_CKO_SECRET_KEY ||
9034             class == DPROV_CKO_PUBLIC_KEY ||
9035             class == DPROV_CKO_PRIVATE_KEY) {
9036                 if (!dprov_template_attr_present(template, nattr,
9037                     DPROV_CKA_KEY_TYPE)) {
9038                         return (CRYPTO_TEMPLATE_INCOMPLETE);
9039                 }
9040         }
9041 
9042         /* check for RSA public key attributes that must be present */
9043         if (class == DPROV_CKO_PUBLIC_KEY) {
9044                 if (dprov_get_template_attr_ulong(template, nattr,
9045                     DPROV_CKA_KEY_TYPE, &key_type) == CRYPTO_SUCCESS) {
9046                         if (key_type == DPROV_CKK_RSA) {
9047                                 if (!dprov_template_attr_present(template,
9048                                     nattr, DPROV_CKA_MODULUS) ||
9049                                     !dprov_template_attr_present(template,
9050                                     nattr, DPROV_CKA_PUBLIC_EXPONENT)) {
9051                                         return (CRYPTO_TEMPLATE_INCOMPLETE);
9052                                 }
9053 
9054                                 /* these attributes should not be present */
9055                                 if (dprov_template_attr_present(template, nattr,
9056                                     DPROV_CKA_MODULUS_BITS)) {
9057                                         return (CRYPTO_TEMPLATE_INCONSISTENT);
9058                                 }
9059                         }
9060                 }
9061         }
9062 
9063         /* check for RSA private key attributes that must be present */
9064         if (class == DPROV_CKO_PRIVATE_KEY) {
9065                 if (dprov_get_template_attr_ulong(template, nattr,
9066                     DPROV_CKA_KEY_TYPE, &key_type) == CRYPTO_SUCCESS) {
9067                         if (key_type == DPROV_CKK_RSA) {
9068                                 if (!dprov_template_attr_present(template,
9069                                     nattr, DPROV_CKA_MODULUS))
9070                                         return (CRYPTO_TEMPLATE_INCOMPLETE);
9071 
9072                                 if (check_for_secret) {
9073                                         if (!dprov_template_attr_present(
9074                                             template, nattr,
9075                                             DPROV_CKA_PRIVATE_EXPONENT))
9076                                                 return (
9077                                                     CRYPTO_TEMPLATE_INCOMPLETE);
9078                                 }
9079                         }
9080                 }
9081         }
9082 
9083         /* check for secret key attributes that must be present */
9084         if (class == DPROV_CKO_SECRET_KEY) {
9085                 if (check_for_secret) {
9086                         if (!dprov_template_attr_present(template, nattr,
9087                             DPROV_CKA_VALUE)) {
9088                                 return (CRYPTO_TEMPLATE_INCOMPLETE);
9089                         }
9090                 }
9091 
9092                 /* these attributes should not be present */
9093                 if (dprov_template_attr_present(template, nattr,
9094                     DPROV_CKA_VALUE_LEN)) {
9095                         return (CRYPTO_TEMPLATE_INCONSISTENT);
9096                 }
9097         }
9098 
9099         return (CRYPTO_SUCCESS);
9100 }
9101 
9102 /*
9103  * Create an object from the specified template. Checks whether the
9104  * object can be created according to its attributes and the state
9105  * of the session. The new session object id is returned. If the
9106  * object is a token object, it is added to the per-instance object
9107  * table as well.
9108  */
9109 static int
9110 dprov_create_object_from_template(dprov_state_t *softc,
9111     dprov_session_t *session, crypto_object_attribute_t *template,
9112     uint_t nattr, crypto_object_id_t *object_id, boolean_t check_for_secret,
9113     boolean_t force)
9114 {
9115         dprov_object_t *object;
9116         boolean_t is_token = B_FALSE;
9117         boolean_t extractable_attribute_present = B_FALSE;
9118         boolean_t sensitive_attribute_present = B_FALSE;
9119         boolean_t private_attribute_present = B_FALSE;
9120         boolean_t token_attribute_present = B_FALSE;
9121         uint_t i;
9122         int error;
9123         uint_t attr;
9124         uint_t oattr;
9125         crypto_attr_type_t type;
9126         size_t old_len, new_len;
9127         offset_t offset;
9128 
9129         if (nattr > DPROV_MAX_ATTR)
9130                 return (CRYPTO_HOST_MEMORY);
9131 
9132         if (!force) {
9133                 /* verify that object can be created */
9134                 if ((error = dprov_template_can_create(session, template,
9135                     nattr, check_for_secret)) != CRYPTO_SUCCESS)
9136                         return (error);
9137         }
9138 
9139         /* allocate new object */
9140         object = kmem_zalloc(sizeof (dprov_object_t), KM_SLEEP);
9141         if (object == NULL)
9142                 return (CRYPTO_HOST_MEMORY);
9143 
9144         /* is it a token object? */
9145         /* check CKA_TOKEN attribute value */
9146         error = dprov_get_template_attr_boolean(template, nattr,
9147             DPROV_CKA_TOKEN, &is_token);
9148         if (error == CRYPTO_SUCCESS && is_token) {
9149                 /* token object, add it to the per-instance object table */
9150                 for (i = 0; i < DPROV_MAX_OBJECTS; i++)
9151                         if (softc->ds_objects[i] == NULL)
9152                                 break;
9153                 if (i == DPROV_MAX_OBJECTS)
9154                         /* no free slot */
9155                         return (CRYPTO_HOST_MEMORY);
9156                 softc->ds_objects[i] = object;
9157                 object->do_token_idx = i;
9158                 DPROV_OBJECT_REFHOLD(object);
9159         }
9160 
9161         /* add object to session object table */
9162         for (i = 0; i < DPROV_MAX_OBJECTS; i++)
9163                 if (session->ds_objects[i] == NULL)
9164                         break;
9165         if (i == DPROV_MAX_OBJECTS) {
9166                 /* no more session object slots */
9167                 DPROV_OBJECT_REFRELE(object);
9168                 return (CRYPTO_HOST_MEMORY);
9169         }
9170         session->ds_objects[i] = object;
9171         DPROV_OBJECT_REFHOLD(object);
9172         *object_id = i;
9173 
9174         /* initialize object from template */
9175         for (attr = 0, oattr = 0; attr < nattr; attr++) {
9176                 if (template[attr].oa_value == NULL)
9177                         continue;
9178                 type = template[attr].oa_type;
9179                 old_len = template[attr].oa_value_len;
9180                 new_len = attribute_size(type, old_len);
9181 
9182                 if (type == DPROV_CKA_EXTRACTABLE) {
9183                         extractable_attribute_present = B_TRUE;
9184                 } else if (type == DPROV_CKA_PRIVATE) {
9185                         private_attribute_present = B_TRUE;
9186                 } else if (type == DPROV_CKA_TOKEN) {
9187                         token_attribute_present = B_TRUE;
9188                 }
9189                 object->do_attr[oattr].oa_type = type;
9190                 object->do_attr[oattr].oa_value_len = new_len;
9191 
9192                 object->do_attr[oattr].oa_value = kmem_zalloc(new_len,
9193                     KM_SLEEP);
9194 
9195                 offset = 0;
9196 #ifdef _BIG_ENDIAN
9197                 if (fixed_size_attribute(type)) {
9198                         offset = old_len - new_len;
9199                 }
9200 #endif
9201                 bcopy(&template[attr].oa_value[offset],
9202                     object->do_attr[oattr].oa_value, new_len);
9203                 oattr++;
9204         }
9205 
9206         /* add boolean attributes that must be present */
9207         if (extractable_attribute_present == B_FALSE) {
9208                 object->do_attr[oattr].oa_type = DPROV_CKA_EXTRACTABLE;
9209                 object->do_attr[oattr].oa_value_len = 1;
9210                 object->do_attr[oattr].oa_value = kmem_alloc(1, KM_SLEEP);
9211                 object->do_attr[oattr].oa_value[0] = B_TRUE;
9212                 oattr++;
9213         }
9214 
9215         if (private_attribute_present == B_FALSE) {
9216                 object->do_attr[oattr].oa_type = DPROV_CKA_PRIVATE;
9217                 object->do_attr[oattr].oa_value_len = 1;
9218                 object->do_attr[oattr].oa_value = kmem_alloc(1, KM_SLEEP);
9219                 object->do_attr[oattr].oa_value[0] = B_FALSE;
9220                 oattr++;
9221         }
9222 
9223         if (token_attribute_present == B_FALSE) {
9224                 object->do_attr[oattr].oa_type = DPROV_CKA_TOKEN;
9225                 object->do_attr[oattr].oa_value_len = 1;
9226                 object->do_attr[oattr].oa_value = kmem_alloc(1, KM_SLEEP);
9227                 object->do_attr[oattr].oa_value[0] = B_FALSE;
9228                 oattr++;
9229         }
9230 
9231         if (sensitive_attribute_present == B_FALSE) {
9232                 object->do_attr[oattr].oa_type = DPROV_CKA_SENSITIVE;
9233                 object->do_attr[oattr].oa_value_len = 1;
9234                 object->do_attr[oattr].oa_value = kmem_alloc(1, KM_SLEEP);
9235                 object->do_attr[oattr].oa_value[0] = B_FALSE;
9236                 oattr++;
9237         }
9238         return (CRYPTO_SUCCESS);
9239 }
9240 
9241 /*
9242  * Checks whether or not the object matches the specified attributes.
9243  *
9244  * PKCS#11 attributes which are longs are stored in uint32_t containers
9245  * so they can be matched by both 32 and 64-bit applications.
9246  */
9247 static boolean_t
9248 dprov_attributes_match(dprov_object_t *object,
9249     crypto_object_attribute_t *template, uint_t nattr)
9250 {
9251         crypto_attr_type_t type;
9252         size_t tlen, olen, diff;
9253         int ta_idx;     /* template attribute index */
9254         int oa_idx;     /* object attribute index */
9255 
9256         for (ta_idx = 0; ta_idx < nattr; ta_idx++) {
9257                 /* no value for template attribute */
9258                 if (template[ta_idx].oa_value == NULL)
9259                         continue;
9260 
9261                 /* find attribute in object */
9262                 type = template[ta_idx].oa_type;
9263                 oa_idx = dprov_find_attr(object->do_attr, DPROV_MAX_ATTR, type);
9264 
9265                 if (oa_idx == -1)
9266                         /* attribute not found in object */
9267                         return (B_FALSE);
9268 
9269                 tlen = template[ta_idx].oa_value_len;
9270                 olen = object->do_attr[oa_idx].oa_value_len;
9271                 if (tlen < olen)
9272                         return (B_FALSE);
9273 
9274                 diff = 0;
9275 #ifdef _BIG_ENDIAN
9276                 /* application may think attribute is 8 bytes */
9277                 if (fixed_size_attribute(type))
9278                         diff = tlen - olen;
9279 #endif
9280 
9281                 if (bcmp(&template[ta_idx].oa_value[diff],
9282                     object->do_attr[oa_idx].oa_value, olen) != 0)
9283                         /* value mismatch */
9284                         return (B_FALSE);
9285         }
9286 
9287         return (B_TRUE);
9288 }
9289 
9290 /*
9291  * Destroy the object specified by its session and object id.
9292  */
9293 static int
9294 dprov_destroy_object(dprov_state_t *softc, dprov_session_t *session,
9295     crypto_object_id_t object_id)
9296 {
9297         dprov_object_t *object;
9298 
9299         if ((object = session->ds_objects[object_id]) == NULL)
9300                 return (CRYPTO_OBJECT_HANDLE_INVALID);
9301 
9302         /* remove from session table */
9303         session->ds_objects[object_id] = NULL;
9304 
9305         if (dprov_object_is_token(object)) {
9306                 if (!object->do_destroyed) {
9307                         object->do_destroyed = B_TRUE;
9308                         /* remove from per-instance token table */
9309                         softc->ds_objects[object->do_token_idx] = NULL;
9310                         DPROV_OBJECT_REFRELE(object);
9311                 } else {
9312                         DPROV_DEBUG(D_OBJECT, ("dprov_destroy_object: "
9313                             "object %p already destroyed\n", (void *)object));
9314                 }
9315         }
9316 
9317         DPROV_OBJECT_REFRELE(object);
9318         return (CRYPTO_SUCCESS);
9319 }
9320 
9321 static int
9322 dprov_object_can_modify(dprov_object_t *object,
9323     crypto_object_attribute_t *template, uint_t nattr)
9324 {
9325         ulong_t object_class;
9326 
9327         /* all objects should have an object class attribute */
9328         if (dprov_get_object_attr_ulong(object, DPROV_CKA_CLASS,
9329             &object_class) != CRYPTO_SUCCESS) {
9330                 return (CRYPTO_SUCCESS);
9331         }
9332 
9333         if (object_class == DPROV_CKO_SECRET_KEY ||
9334             object_class == DPROV_CKO_PUBLIC_KEY ||
9335             object_class == DPROV_CKO_PRIVATE_KEY) {
9336                 if (dprov_template_attr_present(template, nattr,
9337                     DPROV_CKA_CLASS) ||
9338                     dprov_template_attr_present(template, nattr,
9339                     DPROV_CKA_KEY_TYPE))
9340                         return (CRYPTO_TEMPLATE_INCONSISTENT);
9341         }
9342 
9343         switch (object_class) {
9344         case DPROV_CKO_SECRET_KEY:
9345                 if (dprov_template_attr_present(template, nattr,
9346                     DPROV_CKA_VALUE))
9347                         return (CRYPTO_TEMPLATE_INCONSISTENT);
9348                 break;
9349 
9350         case DPROV_CKO_PUBLIC_KEY:
9351                 if (dprov_template_attr_present(template, nattr,
9352                     DPROV_CKA_MODULUS) ||
9353                     dprov_template_attr_present(template, nattr,
9354                     DPROV_CKA_PUBLIC_EXPONENT))
9355                         return (CRYPTO_TEMPLATE_INCONSISTENT);
9356                 break;
9357 
9358         case DPROV_CKO_PRIVATE_KEY:
9359                 if (dprov_template_attr_present(template, nattr,
9360                     DPROV_CKA_MODULUS) ||
9361                     dprov_template_attr_present(template, nattr,
9362                     DPROV_CKA_PRIVATE_EXPONENT))
9363                         return (CRYPTO_TEMPLATE_INCONSISTENT);
9364                 break;
9365 
9366         default:
9367                 return (CRYPTO_SUCCESS);
9368         }
9369 
9370         return (CRYPTO_SUCCESS);
9371 }
9372 
9373 /*
9374  * Set the attributes specified by the template in the specified object,
9375  * replacing existing ones if needed.
9376  */
9377 static int
9378 dprov_object_set_attr(dprov_session_t *session, crypto_object_id_t object_id,
9379     crypto_object_attribute_t *template, uint_t nattr,
9380     boolean_t check_attributes)
9381 {
9382         crypto_attr_type_t type;
9383         dprov_object_t *object;
9384         size_t old_len, new_len;
9385         uint_t i, j;
9386         int error;
9387 
9388         if ((object = session->ds_objects[object_id]) == NULL)
9389                 return (CRYPTO_OBJECT_HANDLE_INVALID);
9390 
9391         if (check_attributes) {
9392                 /* verify that attributes in the template can be modified */
9393                 if ((error = dprov_object_can_modify(object, template, nattr))
9394                     != CRYPTO_SUCCESS)
9395                         return (error);
9396         }
9397 
9398         /* go through the attributes specified in the template */
9399         for (i = 0; i < nattr; i++) {
9400                 if (template[i].oa_value == NULL)
9401                         continue;
9402 
9403                 /* find attribute in object */
9404                 type = template[i].oa_type;
9405                 j = dprov_find_attr(object->do_attr, DPROV_MAX_ATTR, type);
9406 
9407                 if (j != -1) {
9408                         /* attribute already exists, free old value */
9409                         kmem_free(object->do_attr[j].oa_value,
9410                             object->do_attr[j].oa_value_len);
9411                 } else {
9412                         /* attribute does not exist, create it */
9413                         for (j = 0; j < DPROV_MAX_ATTR; j++)
9414                                 if (object->do_attr[j].oa_value == NULL)
9415                                         break;
9416                         if (j == DPROV_MAX_ATTR)
9417                                 /* ran out of attribute slots */
9418                                 return (CRYPTO_HOST_MEMORY);
9419                 }
9420 
9421                 old_len = template[i].oa_value_len;
9422                 new_len = attribute_size(type, old_len);
9423 
9424                 /* set object attribute value */
9425                 object->do_attr[j].oa_value = kmem_alloc(new_len, KM_SLEEP);
9426                 bcopy(&template[i].oa_value[old_len - new_len],
9427                     object->do_attr[j].oa_value, new_len);
9428                 object->do_attr[j].oa_value_len = new_len;
9429 
9430                 /* and the type */
9431                 object->do_attr[j].oa_type = type;
9432         }
9433 
9434         return (CRYPTO_SUCCESS);
9435 }
9436 
9437 
9438 /*
9439  * Free the specified object.
9440  */
9441 static void
9442 dprov_free_object(dprov_object_t *object)
9443 {
9444         int i;
9445 
9446         /* free the object attributes values */
9447         for (i = 0; i < DPROV_MAX_ATTR; i++)
9448                 if (object->do_attr[i].oa_value != NULL)
9449                         kmem_free(object->do_attr[i].oa_value,
9450                             object->do_attr[i].oa_value_len);
9451 
9452         /* free the object */
9453         kmem_free(object, sizeof (dprov_object_t));
9454 }
9455 
9456 /*
9457  * Checks whether the specified object is a private or public object.
9458  */
9459 static boolean_t
9460 dprov_object_is_private(dprov_object_t *object)
9461 {
9462         boolean_t ret;
9463         int err;
9464 
9465         err = dprov_get_object_attr_boolean(object, DPROV_CKA_PRIVATE, &ret);
9466 
9467         if (err != CRYPTO_SUCCESS)
9468                 /* by default, CKA_PRIVATE is false */
9469                 ret = B_FALSE;
9470 
9471         return (ret);
9472 }
9473 
9474 /*
9475  * Checks whether the specified object is a token or session object.
9476  */
9477 static boolean_t
9478 dprov_object_is_token(dprov_object_t *object)
9479 {
9480         boolean_t ret;
9481         int err;
9482 
9483         err = dprov_get_object_attr_boolean(object, DPROV_CKA_TOKEN, &ret);
9484 
9485         if (err != CRYPTO_SUCCESS)
9486                 /* by default, CKA_TOKEN is false */
9487                 ret = B_FALSE;
9488 
9489         return (ret);
9490 }
9491 
9492 /*
9493  * Common function used by the dprov_get_object_attr_*() family of
9494  * functions. Returns the value of the specified attribute of specified
9495  * length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID
9496  * if the length of the attribute does not match the specified length,
9497  * or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found.
9498  */
9499 static int
9500 dprov_get_object_attr_scalar_common(dprov_object_t *object, uint64_t attr_type,
9501                                     void *value, size_t value_len)
9502 {
9503         int attr_idx;
9504         size_t oa_value_len;
9505         size_t offset = 0;
9506 
9507         if ((attr_idx = dprov_find_attr(object->do_attr, DPROV_MAX_ATTR,
9508             attr_type)) == -1)
9509                 return (CRYPTO_ARGUMENTS_BAD);
9510 
9511         oa_value_len = object->do_attr[attr_idx].oa_value_len;
9512         if (oa_value_len != value_len) {
9513                 /*
9514                  * For some attributes, it's okay to copy the value
9515                  * into a larger container, e.g. copy an unsigned
9516                  * 32-bit integer into a 64-bit container.
9517                  */
9518                 if (attr_type == DPROV_CKA_VALUE_LEN ||
9519                     attr_type == DPROV_CKA_KEY_TYPE ||
9520                     attr_type == DPROV_CKA_CLASS) {
9521                         if (oa_value_len < value_len) {
9522 #ifdef _BIG_ENDIAN
9523                                 offset = value_len - oa_value_len;
9524 #endif
9525                                 bzero(value, value_len);
9526                                 goto do_copy;
9527                         }
9528                 }
9529                 /* incorrect attribute value length */
9530                 return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
9531         }
9532 
9533 do_copy:
9534         bcopy(object->do_attr[attr_idx].oa_value, (uchar_t *)value + offset,
9535             oa_value_len);
9536 
9537         return (CRYPTO_SUCCESS);
9538 }
9539 
9540 /*
9541  * Get the value of the a boolean attribute from the specified object.
9542  */
9543 static int
9544 dprov_get_object_attr_boolean(dprov_object_t *object, uint64_t attr_type,
9545     boolean_t *attr_value)
9546 {
9547         uchar_t val;
9548         int ret;
9549 
9550         /* PKCS#11 defines a boolean as one byte */
9551         ret = dprov_get_object_attr_scalar_common(object, attr_type, &val, 1);
9552         if (ret == CRYPTO_SUCCESS) {
9553                 *attr_value = (val == '\0') ? B_FALSE : B_TRUE;
9554         }
9555         return (ret);
9556 }
9557 
9558 /*
9559  * Get the value of a ulong_t attribute from the specified object.
9560  */
9561 static int
9562 dprov_get_object_attr_ulong(dprov_object_t *object, uint64_t attr_type,
9563     ulong_t *attr_value)
9564 {
9565         return (dprov_get_object_attr_scalar_common(object, attr_type,
9566             attr_value, sizeof (ulong_t)));
9567 }
9568 
9569 /*
9570  * Find the specified byte array attribute of specified type in
9571  * the specified object. Returns CRYPTO_SUCCESS
9572  * on success or CRYPTO_ARGUMENTS_BAD if the specified
9573  * attribute cannot be found.
9574  */
9575 static int
9576 dprov_get_object_attr_array(dprov_object_t *object, uint64_t attr_type,
9577     void **array, size_t *len)
9578 {
9579         int attr_idx;
9580 
9581         if ((attr_idx = dprov_find_attr(object->do_attr, DPROV_MAX_ATTR,
9582             attr_type)) == -1)
9583                 return (CRYPTO_ARGUMENTS_BAD);
9584 
9585         *array = object->do_attr[attr_idx].oa_value;
9586         *len = object->do_attr[attr_idx].oa_value_len;
9587 
9588         return (CRYPTO_SUCCESS);
9589 }
9590 
9591 /*
9592  * Common function used by the dprov_get_template_attr_*() family of
9593  * functions. Returns the value of the specified attribute of specified
9594  * length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID
9595  * if the length of the attribute does not match the specified length,
9596  * or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found.
9597  */
9598 static int
9599 dprov_get_template_attr_scalar_common(crypto_object_attribute_t *template,
9600     uint_t nattr, uint64_t attr_type, void *value, size_t value_len)
9601 {
9602         size_t oa_value_len;
9603         size_t offset = 0;
9604         int attr_idx;
9605 
9606         if ((attr_idx = dprov_find_attr(template, nattr, attr_type)) == -1)
9607                 return (CRYPTO_ARGUMENTS_BAD);
9608 
9609         oa_value_len = template[attr_idx].oa_value_len;
9610         if (oa_value_len != value_len) {
9611                 /*
9612                  * For some attributes, it's okay to copy the value
9613                  * into a larger container, e.g. copy an unsigned
9614                  * 32-bit integer into a 64-bit container.
9615                  */
9616                 if (attr_type == DPROV_CKA_VALUE_LEN ||
9617                     attr_type == DPROV_CKA_KEY_TYPE ||
9618                     attr_type == DPROV_CKA_CLASS) {
9619                         if (oa_value_len < value_len) {
9620 #ifdef _BIG_ENDIAN
9621                                 offset = value_len - oa_value_len;
9622 #endif
9623                                 bzero(value, value_len);
9624                                 goto do_copy;
9625                         }
9626                 }
9627                 /* incorrect attribute value length */
9628                 return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
9629         }
9630 
9631 do_copy:
9632         bcopy(template[attr_idx].oa_value, (uchar_t *)value + offset,
9633             oa_value_len);
9634 
9635         return (CRYPTO_SUCCESS);
9636 }
9637 
9638 /*
9639  * Get the value of the a boolean attribute from the specified template
9640  */
9641 static int
9642 dprov_get_template_attr_boolean(crypto_object_attribute_t *template,
9643     uint_t nattr, uint64_t attr_type, boolean_t *attr_value)
9644 {
9645         uchar_t val;
9646         int ret;
9647 
9648         /* PKCS#11 defines a boolean as one byte */
9649         ret = dprov_get_template_attr_scalar_common(template, nattr,
9650             attr_type, &val, 1);
9651         if (ret == CRYPTO_SUCCESS) {
9652                 *attr_value = (val == '\0') ? B_FALSE : B_TRUE;
9653         }
9654         return (ret);
9655 }
9656 
9657 /*
9658  * Get the value of a ulong_t attribute from the specified template.
9659  */
9660 static int
9661 dprov_get_template_attr_ulong(crypto_object_attribute_t *template,
9662     uint_t nattr, uint64_t attr_type, ulong_t *attr_value)
9663 {
9664         return (dprov_get_template_attr_scalar_common(template, nattr,
9665             attr_type, attr_value, sizeof (ulong_t)));
9666 }
9667 
9668 static int
9669 dprov_template_attr_present(crypto_object_attribute_t *template,
9670     uint_t nattr, uint64_t attr_type)
9671 {
9672         return (dprov_find_attr(template, nattr,
9673             attr_type) == -1 ? B_FALSE : B_TRUE);
9674 }
9675 
9676 /*
9677  * Find the specified byte array attribute of specified type in
9678  * the specified template. Returns CRYPTO_SUCCESS on success or
9679  * CRYPTO_ARGUMENTS_BAD if the specified attribute cannot be found.
9680  */
9681 static int
9682 dprov_get_template_attr_array(crypto_object_attribute_t *template,
9683     uint_t nattr, uint64_t attr_type, void **array, size_t *len)
9684 {
9685         int attr_idx;
9686 
9687         if ((attr_idx = dprov_find_attr(template, nattr, attr_type)) == -1)
9688                 return (CRYPTO_ARGUMENTS_BAD);
9689 
9690         *array = template[attr_idx].oa_value;
9691         *len = template[attr_idx].oa_value_len;
9692 
9693         return (CRYPTO_SUCCESS);
9694 }
9695 
9696 /*
9697  * Common function used by the dprov_get_key_attr_*() family of
9698  * functions. Returns the value of the specified attribute of specified
9699  * length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID
9700  * if the length of the attribute does not match the specified length,
9701  * or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found.
9702  */
9703 static int
9704 dprov_get_key_attr_scalar_common(crypto_key_t *key, uint64_t attr_type,
9705     void *value, size_t value_len)
9706 {
9707         int attr_idx;
9708 
9709         ASSERT(key->ck_format == CRYPTO_KEY_ATTR_LIST);
9710 
9711         if ((attr_idx = dprov_find_attr(key->ck_attrs, key->ck_count,
9712             attr_type)) == -1)
9713                 return (CRYPTO_ARGUMENTS_BAD);
9714 
9715         if (key->ck_attrs[attr_idx].oa_value_len != value_len)
9716                 /* incorrect attribute value length */
9717                 return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
9718 
9719         bcopy(key->ck_attrs[attr_idx].oa_value, value, value_len);
9720 
9721         return (CRYPTO_SUCCESS);
9722 }
9723 
9724 /*
9725  * Get the value of a ulong_t attribute from the specified key.
9726  */
9727 static int
9728 dprov_get_key_attr_ulong(crypto_key_t *key, uint64_t attr_type,
9729     ulong_t *attr_value)
9730 {
9731         return (dprov_get_key_attr_scalar_common(key, attr_type,
9732             attr_value, sizeof (ulong_t)));
9733 }
9734 
9735 /*
9736  * Find the specified byte array attribute of specified type in
9737  * the specified key by attributes. Returns CRYPTO_SUCCESS
9738  * on success or CRYPTO_ARGUMENTS_BAD if the specified
9739  * attribute cannot be found.
9740  */
9741 static int
9742 dprov_get_key_attr_array(crypto_key_t *key, uint64_t attr_type,
9743     void **array, size_t *len)
9744 {
9745         int attr_idx;
9746 
9747         ASSERT(key->ck_format == CRYPTO_KEY_ATTR_LIST);
9748 
9749         if ((attr_idx = dprov_find_attr(key->ck_attrs, key->ck_count,
9750             attr_type)) == -1)
9751                 return (CRYPTO_ARGUMENTS_BAD);
9752 
9753         *array = key->ck_attrs[attr_idx].oa_value;
9754         *len = key->ck_attrs[attr_idx].oa_value_len;
9755 
9756         return (CRYPTO_SUCCESS);
9757 }
9758 
9759 static void
9760 dprov_release_session_objects(dprov_session_t *session)
9761 {
9762         dprov_object_t *object;
9763         int i;
9764 
9765         for (i = 0; i < DPROV_MAX_OBJECTS; i++) {
9766                 object = session->ds_objects[i];
9767                 if (object != NULL) {
9768                         DPROV_OBJECT_REFRELE(object);
9769                 }
9770         }
9771 }
9772 
9773 /*
9774  * Adjust an attribute list by turning 32-bit values into 64-bit values
9775  * for certain attributes like CKA_CLASS. Assumes that at least 8 bytes
9776  * of storage have been allocated for all attributes.
9777  */
9778 static void
9779 dprov_adjust_attrs(crypto_object_attribute_t *in, int in_count)
9780 {
9781         int i;
9782         size_t offset = 0;
9783         ulong_t tmp = 0;
9784 
9785         for (i = 0; i < in_count; i++) {
9786                 /*
9787                  * For some attributes, it's okay to copy the value
9788                  * into a larger container, e.g. copy an unsigned
9789                  * 32-bit integer into a 64-bit container.
9790                  */
9791                 if (in[i].oa_type == CKA_VALUE_LEN ||
9792                     in[i].oa_type == CKA_KEY_TYPE ||
9793                     in[i].oa_type == CKA_CLASS) {
9794                         if (in[i].oa_value_len < sizeof (ulong_t)) {
9795 #ifdef _BIG_ENDIAN
9796                                 offset = sizeof (ulong_t) - in[i].oa_value_len;
9797 #endif
9798                                 bcopy(in[i].oa_value, (uchar_t *)&tmp + offset,
9799                                     in[i].oa_value_len);
9800                                 bcopy(&tmp, in[i].oa_value, sizeof (ulong_t));
9801                                 in[i].oa_value_len = sizeof (ulong_t);
9802                         }
9803                 }
9804         }
9805 }