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 (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 
  25 
  26 /*
  27  * The ioctl interface for cryptographic commands.
  28  */
  29 
  30 #include <sys/types.h>
  31 #include <sys/modctl.h>
  32 #include <sys/conf.h>
  33 #include <sys/stat.h>
  34 #include <sys/ddi.h>
  35 #include <sys/sunddi.h>
  36 #include <sys/kmem.h>
  37 #include <sys/errno.h>
  38 #include <sys/ksynch.h>
  39 #include <sys/file.h>
  40 #include <sys/open.h>
  41 #include <sys/cred.h>
  42 #include <sys/proc.h>
  43 #include <sys/task.h>
  44 #include <sys/mkdev.h>
  45 #include <sys/model.h>
  46 #include <sys/sysmacros.h>
  47 #include <sys/crypto/common.h>
  48 #include <sys/crypto/api.h>
  49 #include <sys/crypto/impl.h>
  50 #include <sys/crypto/sched_impl.h>
  51 #include <sys/crypto/ioctl.h>
  52 
  53 extern int kcf_des3_threshold;
  54 extern int kcf_aes_threshold;
  55 extern int kcf_rc4_threshold;
  56 extern int kcf_md5_threshold;
  57 extern int kcf_sha1_threshold;
  58 
  59 /*
  60  * Locking notes:
  61  *
  62  * crypto_locks protects the global array of minor structures.
  63  * crypto_locks is an array of locks indexed by the cpuid. A reader needs
  64  * to hold a single lock while a writer needs to hold all locks.
  65  * krwlock_t is not an option here because the hold time
  66  * is very small for these locks.
  67  *
  68  * The fields in the minor structure are protected by the cm_lock member
  69  * of the minor structure. The cm_cv is used to signal decrements
  70  * in the cm_refcnt, and is used with the cm_lock.
  71  *
  72  * The locking order is crypto_locks followed by cm_lock.
  73  */
  74 
  75 /*
  76  * DDI entry points.
  77  */
  78 static int crypto_attach(dev_info_t *, ddi_attach_cmd_t);
  79 static int crypto_detach(dev_info_t *, ddi_detach_cmd_t);
  80 static int crypto_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
  81 static int crypto_open(dev_t *, int, int, cred_t *);
  82 static int crypto_close(dev_t, int, int, cred_t *);
  83 static int crypto_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
  84 
  85 static int cipher_init(dev_t, caddr_t, int, int (*)(crypto_provider_t,
  86     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
  87     crypto_ctx_template_t, crypto_context_t *, crypto_call_req_t *));
  88 
  89 static int common_digest(dev_t, caddr_t, int, int (*)(crypto_context_t,
  90     crypto_data_t *, crypto_data_t *, crypto_call_req_t *));
  91 
  92 static int cipher(dev_t, caddr_t, int, int (*)(crypto_context_t,
  93     crypto_data_t *, crypto_data_t *, crypto_call_req_t *));
  94 
  95 static int cipher_update(dev_t, caddr_t, int, int (*)(crypto_context_t,
  96     crypto_data_t *, crypto_data_t *, crypto_call_req_t *));
  97 
  98 static int common_final(dev_t, caddr_t, int, int (*)(crypto_context_t,
  99     crypto_data_t *, crypto_call_req_t *));
 100 
 101 static int sign_verify_init(dev_t, caddr_t, int, int (*)(crypto_provider_t,
 102     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
 103     crypto_ctx_template_t, crypto_context_t *, crypto_call_req_t *));
 104 
 105 static int sign_verify_update(dev_t dev, caddr_t arg, int mode,
 106     int (*)(crypto_context_t, crypto_data_t *, crypto_call_req_t *));
 107 
 108 static void crypto_release_provider_session(crypto_minor_t *,
 109     crypto_provider_session_t *);
 110 static int crypto_buffer_check(size_t);
 111 static int crypto_free_find_ctx(crypto_session_data_t *);
 112 static int crypto_get_provider_list(crypto_minor_t *, uint_t *,
 113     crypto_provider_entry_t **, boolean_t);
 114 
 115 /* number of minor numbers to allocate at a time */
 116 #define CRYPTO_MINOR_CHUNK      16
 117 
 118 /*
 119  * There are two limits associated with kernel memory. The first,
 120  * CRYPTO_MAX_BUFFER_LEN, is the maximum number of bytes that can be
 121  * allocated for a single copyin/copyout buffer. The second limit is
 122  * the total number of bytes that can be allocated by a process
 123  * for copyin/copyout buffers. The latter is enforced by the
 124  * project.max-crypto-memory resource control.
 125  */
 126 
 127 #define CRYPTO_MAX_BUFFER_LEN   (2 * 1024 * 1024)
 128 #define CRYPTO_MAX_FIND_COUNT   512
 129 
 130 /*
 131  * We preapprove some bytes for each session to avoid making the costly
 132  * crypto_buffer_check() calls. The preapproval is done when a new session
 133  * is created and that cost is amortized over later crypto calls.
 134  * Most applications create a session and then do a bunch of crypto calls
 135  * in that session. So, they benefit from this optimization.
 136  *
 137  * Note that we may hit the project.max-crypto-memory limit a bit sooner
 138  * because of this preapproval. But it is acceptable since the preapproved
 139  * amount is insignificant compared to the default max-crypto-memory limit
 140  * which is quarter of the machine's memory. The preapproved amount is
 141  * roughly 2 * 16K(maximum SSL record size).
 142  */
 143 #define CRYPTO_PRE_APPROVED_LIMIT       (32 * 1024)
 144 
 145 /* The session table grows by CRYPTO_SESSION_CHUNK increments */
 146 #define CRYPTO_SESSION_CHUNK    100
 147 
 148 size_t crypto_max_buffer_len = CRYPTO_MAX_BUFFER_LEN;
 149 size_t crypto_pre_approved_limit = CRYPTO_PRE_APPROVED_LIMIT;
 150 
 151 #define INIT_RAW_CRYPTO_DATA(data, len)                         \
 152         (data).cd_format = CRYPTO_DATA_RAW;                     \
 153         (data).cd_raw.iov_base = kmem_alloc(len, KM_SLEEP);     \
 154         (data).cd_raw.iov_len = len;                            \
 155         (data).cd_offset = 0;                                   \
 156         (data).cd_length = len;
 157 
 158 static struct kmem_cache *crypto_session_cache;
 159 static crypto_minor_t **crypto_minors = NULL;
 160 static dev_info_t *crypto_dip = NULL;
 161 static minor_t crypto_minor_chunk = CRYPTO_MINOR_CHUNK;
 162 static minor_t crypto_minors_table_count = 0;
 163 
 164 /*
 165  * Minors are started from 1 because vmem_alloc()
 166  * returns 0 in case of failure.
 167  */
 168 static vmem_t *crypto_arena = NULL;     /* Arena for device minors */
 169 static minor_t crypto_minors_count = 0;
 170 static kcf_lock_withpad_t *crypto_locks;
 171 
 172 #define CRYPTO_ENTER_ALL_LOCKS()                \
 173         for (i = 0; i < max_ncpus; i++)              \
 174                 mutex_enter(&crypto_locks[i].kl_lock);
 175 
 176 #define CRYPTO_EXIT_ALL_LOCKS()                 \
 177         for (i = 0; i < max_ncpus; i++)              \
 178                 mutex_exit(&crypto_locks[i].kl_lock);
 179 
 180 #define RETURN_LIST                     B_TRUE
 181 #define DONT_RETURN_LIST                B_FALSE
 182 
 183 #define CRYPTO_OPS_OFFSET(f)            offsetof(crypto_ops_t, co_##f)
 184 #define CRYPTO_RANDOM_OFFSET(f)         offsetof(crypto_random_number_ops_t, f)
 185 #define CRYPTO_SESSION_OFFSET(f)        offsetof(crypto_session_ops_t, f)
 186 #define CRYPTO_OBJECT_OFFSET(f)         offsetof(crypto_object_ops_t, f)
 187 #define CRYPTO_PROVIDER_OFFSET(f)       \
 188         offsetof(crypto_provider_management_ops_t, f)
 189 
 190 #define CRYPTO_CANCEL_CTX(spp) {        \
 191         crypto_cancel_ctx(*(spp));      \
 192         *(spp) = NULL;                  \
 193 }
 194 
 195 #define CRYPTO_CANCEL_ALL_CTX(sp) {                             \
 196         if ((sp)->sd_digest_ctx != NULL) {                   \
 197                 crypto_cancel_ctx((sp)->sd_digest_ctx);              \
 198                 (sp)->sd_digest_ctx = NULL;                  \
 199         }                                                       \
 200         if ((sp)->sd_encr_ctx != NULL) {                     \
 201                 crypto_cancel_ctx((sp)->sd_encr_ctx);                \
 202                 (sp)->sd_encr_ctx = NULL;                    \
 203         }                                                       \
 204         if ((sp)->sd_decr_ctx != NULL) {                     \
 205                 crypto_cancel_ctx((sp)->sd_decr_ctx);                \
 206                 (sp)->sd_decr_ctx = NULL;                    \
 207         }                                                       \
 208         if ((sp)->sd_sign_ctx != NULL) {                     \
 209                 crypto_cancel_ctx((sp)->sd_sign_ctx);                \
 210                 (sp)->sd_sign_ctx = NULL;                    \
 211         }                                                       \
 212         if ((sp)->sd_verify_ctx != NULL) {                   \
 213                 crypto_cancel_ctx((sp)->sd_verify_ctx);              \
 214                 (sp)->sd_verify_ctx = NULL;                  \
 215         }                                                       \
 216         if ((sp)->sd_sign_recover_ctx != NULL) {             \
 217                 crypto_cancel_ctx((sp)->sd_sign_recover_ctx);        \
 218                 (sp)->sd_sign_recover_ctx = NULL;            \
 219         }                                                       \
 220         if ((sp)->sd_verify_recover_ctx != NULL) {           \
 221                 crypto_cancel_ctx((sp)->sd_verify_recover_ctx);      \
 222                 (sp)->sd_verify_recover_ctx = NULL;          \
 223         }                                                       \
 224 }
 225 
 226 #define CRYPTO_DECREMENT_RCTL(val)      if ((val) != 0) {       \
 227         kproject_t *projp;                                      \
 228         mutex_enter(&curproc->p_lock);                           \
 229         projp = curproc->p_task->tk_proj;                 \
 230         ASSERT(projp != NULL);                                  \
 231         mutex_enter(&(projp->kpj_data.kpd_crypto_lock)); \
 232         projp->kpj_data.kpd_crypto_mem -= (val);             \
 233         mutex_exit(&(projp->kpj_data.kpd_crypto_lock));          \
 234         curproc->p_crypto_mem -= (val);                              \
 235         mutex_exit(&curproc->p_lock);                            \
 236 }
 237 
 238 /*
 239  * We do not need to hold sd_lock in the macros below
 240  * as they are called after doing a get_session_ptr() which
 241  * sets the CRYPTO_SESSION_IS_BUSY flag.
 242  */
 243 #define CRYPTO_DECREMENT_RCTL_SESSION(sp, val, rctl_chk)        \
 244         if (((val) != 0) && ((sp) != NULL)) {                   \
 245                 ASSERT(((sp)->sd_flags & CRYPTO_SESSION_IS_BUSY) != 0);  \
 246                 if (rctl_chk) {                         \
 247                         CRYPTO_DECREMENT_RCTL(val);             \
 248                 } else {                                        \
 249                         (sp)->sd_pre_approved_amount += (val);       \
 250                 }                                               \
 251         }
 252 
 253 #define CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)         \
 254         ((sp->sd_pre_approved_amount >= need) ?                   \
 255         (sp->sd_pre_approved_amount -= need,                 \
 256             rctl_chk = B_FALSE, CRYPTO_SUCCESS) :               \
 257             (rctl_chk = B_TRUE, crypto_buffer_check(need)))
 258 
 259 /*
 260  * Module linkage.
 261  */
 262 static struct cb_ops cbops = {
 263         crypto_open,            /* cb_open */
 264         crypto_close,           /* cb_close */
 265         nodev,                  /* cb_strategy */
 266         nodev,                  /* cb_print */
 267         nodev,                  /* cb_dump */
 268         nodev,                  /* cb_read */
 269         nodev,                  /* cb_write */
 270         crypto_ioctl,           /* cb_ioctl */
 271         nodev,                  /* cb_devmap */
 272         nodev,                  /* cb_mmap */
 273         nodev,                  /* cb_segmap */
 274         nochpoll,               /* cb_chpoll */
 275         ddi_prop_op,            /* cb_prop_op */
 276         NULL,                   /* cb_streamtab */
 277         D_MP,                   /* cb_flag */
 278         CB_REV,                 /* cb_rev */
 279         nodev,                  /* cb_aread */
 280         nodev,                  /* cb_awrite */
 281 };
 282 
 283 static struct dev_ops devops = {
 284         DEVO_REV,               /* devo_rev */
 285         0,                      /* devo_refcnt */
 286         crypto_getinfo,         /* devo_getinfo */
 287         nulldev,                /* devo_identify */
 288         nulldev,                /* devo_probe */
 289         crypto_attach,          /* devo_attach */
 290         crypto_detach,          /* devo_detach */
 291         nodev,                  /* devo_reset */
 292         &cbops,                     /* devo_cb_ops */
 293         NULL,                   /* devo_bus_ops */
 294         NULL,                   /* devo_power */
 295         ddi_quiesce_not_needed,         /* devo_quiesce */
 296 };
 297 
 298 static struct modldrv modldrv = {
 299         &mod_driverops,                                     /* drv_modops */
 300         "Cryptographic Library Interface",      /* drv_linkinfo */
 301         &devops,
 302 };
 303 
 304 static struct modlinkage modlinkage = {
 305         MODREV_1,               /* ml_rev */
 306         &modldrv,           /* ml_linkage */
 307         NULL
 308 };
 309 
 310 /*
 311  * DDI entry points.
 312  */
 313 int
 314 _init(void)
 315 {
 316         return (mod_install(&modlinkage));
 317 }
 318 
 319 int
 320 _fini(void)
 321 {
 322         return (mod_remove(&modlinkage));
 323 }
 324 
 325 int
 326 _info(struct modinfo *modinfop)
 327 {
 328         return (mod_info(&modlinkage, modinfop));
 329 }
 330 
 331 /* ARGSUSED */
 332 static int
 333 crypto_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
 334 {
 335         switch (cmd) {
 336         case DDI_INFO_DEVT2DEVINFO:
 337                 *result = crypto_dip;
 338                 return (DDI_SUCCESS);
 339 
 340         case DDI_INFO_DEVT2INSTANCE:
 341                 *result = (void *)0;
 342                 return (DDI_SUCCESS);
 343         }
 344         return (DDI_FAILURE);
 345 }
 346 
 347 static int
 348 crypto_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 349 {
 350         int i;
 351 
 352         if (cmd != DDI_ATTACH) {
 353                 return (DDI_FAILURE);
 354         }
 355 
 356         if (ddi_get_instance(dip) != 0) {
 357                 /* we only allow instance 0 to attach */
 358                 return (DDI_FAILURE);
 359         }
 360 
 361         crypto_session_cache = kmem_cache_create("crypto_session_cache",
 362             sizeof (crypto_session_data_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
 363 
 364         if (crypto_session_cache == NULL)
 365                 return (DDI_FAILURE);
 366 
 367         /* create the minor node */
 368         if (ddi_create_minor_node(dip, "crypto", S_IFCHR, 0,
 369             DDI_PSEUDO, 0) != DDI_SUCCESS) {
 370                 kmem_cache_destroy(crypto_session_cache);
 371                 crypto_session_cache = NULL;
 372                 cmn_err(CE_WARN, "crypto_attach: failed creating minor node");
 373                 ddi_remove_minor_node(dip, NULL);
 374                 return (DDI_FAILURE);
 375         }
 376 
 377         crypto_locks = kmem_zalloc(max_ncpus * sizeof (kcf_lock_withpad_t),
 378             KM_SLEEP);
 379         for (i = 0; i < max_ncpus; i++)
 380                 mutex_init(&crypto_locks[i].kl_lock, NULL, MUTEX_DRIVER, NULL);
 381 
 382         crypto_dip = dip;
 383 
 384         /* allocate integer space for minor numbers */
 385         crypto_arena = vmem_create("crypto", (void *)1,
 386             CRYPTO_MINOR_CHUNK, 1, NULL, NULL, NULL, 0,
 387             VM_SLEEP | VMC_IDENTIFIER);
 388 
 389         return (DDI_SUCCESS);
 390 }
 391 
 392 static int
 393 crypto_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 394 {
 395         minor_t i;
 396         kcf_lock_withpad_t *mp;
 397 
 398         if (cmd != DDI_DETACH)
 399                 return (DDI_FAILURE);
 400 
 401         mp = &crypto_locks[CPU_SEQID];
 402         mutex_enter(&mp->kl_lock);
 403 
 404         /* check if device is open */
 405         for (i = 0; i < crypto_minors_table_count; i++) {
 406                 if (crypto_minors[i] != NULL) {
 407                         mutex_exit(&mp->kl_lock);
 408                         return (DDI_FAILURE);
 409                 }
 410         }
 411         mutex_exit(&mp->kl_lock);
 412 
 413         crypto_dip = NULL;
 414         ddi_remove_minor_node(dip, NULL);
 415 
 416         kmem_cache_destroy(crypto_session_cache);
 417         crypto_session_cache = NULL;
 418 
 419         kmem_free(crypto_minors,
 420             sizeof (crypto_minor_t *) * crypto_minors_table_count);
 421         crypto_minors = NULL;
 422         crypto_minors_table_count = 0;
 423         for (i = 0; i < max_ncpus; i++)
 424                 mutex_destroy(&crypto_locks[i].kl_lock);
 425         kmem_free(crypto_locks, max_ncpus * sizeof (kcf_lock_withpad_t));
 426         crypto_locks = NULL;
 427 
 428         vmem_destroy(crypto_arena);
 429         crypto_arena = NULL;
 430 
 431         return (DDI_SUCCESS);
 432 }
 433 
 434 /* ARGSUSED3 */
 435 static int
 436 crypto_open(dev_t *devp, int flag, int otyp, cred_t *credp)
 437 {
 438         crypto_minor_t *cm = NULL;
 439         minor_t mn;
 440         kcf_lock_withpad_t *mp;
 441         int i;
 442 
 443         if (otyp != OTYP_CHR)
 444                 return (ENXIO);
 445 
 446         if (crypto_dip == NULL)
 447                 return (ENXIO);
 448 
 449         /* exclusive opens are not supported */
 450         if (flag & FEXCL)
 451                 return (ENOTSUP);
 452 
 453 again:
 454         mp = &crypto_locks[CPU_SEQID];
 455         mutex_enter(&mp->kl_lock);
 456 
 457         /* grow the minors table if needed */
 458         if (crypto_minors_count >= crypto_minors_table_count) {
 459                 crypto_minor_t **newtable;
 460                 minor_t chunk = crypto_minor_chunk;
 461                 minor_t saved_count;
 462                 size_t new_size;
 463                 ulong_t big_count;
 464 
 465                 big_count = crypto_minors_count + chunk;
 466                 if (big_count > MAXMIN) {
 467                         mutex_exit(&mp->kl_lock);
 468                         return (ENOMEM);
 469                 }
 470 
 471                 saved_count = crypto_minors_table_count;
 472                 new_size = sizeof (crypto_minor_t *) *
 473                     (crypto_minors_table_count + chunk);
 474 
 475                 mutex_exit(&mp->kl_lock);
 476 
 477                 newtable = kmem_zalloc(new_size, KM_SLEEP);
 478                 CRYPTO_ENTER_ALL_LOCKS();
 479                 /*
 480                  * Check if table grew while we were sleeping.
 481                  * The minors table never shrinks.
 482                  */
 483                 if (crypto_minors_table_count > saved_count) {
 484                         CRYPTO_EXIT_ALL_LOCKS();
 485                         kmem_free(newtable, new_size);
 486                         goto again;
 487                 }
 488 
 489                 /* we assume that bcopy() will return if count is 0 */
 490                 bcopy(crypto_minors, newtable,
 491                     sizeof (crypto_minor_t *) * crypto_minors_table_count);
 492 
 493                 kmem_free(crypto_minors,
 494                     sizeof (crypto_minor_t *) * crypto_minors_table_count);
 495 
 496                 /* grow the minors number space */
 497                 if (crypto_minors_table_count != 0) {
 498                         (void) vmem_add(crypto_arena,
 499                             (void *)(uintptr_t)(crypto_minors_table_count + 1),
 500                             crypto_minor_chunk, VM_SLEEP);
 501                 }
 502 
 503                 crypto_minors = newtable;
 504                 crypto_minors_table_count += chunk;
 505                 CRYPTO_EXIT_ALL_LOCKS();
 506         } else {
 507                 mutex_exit(&mp->kl_lock);
 508         }
 509 
 510         /* allocate a new minor number starting with 1 */
 511         mn = (minor_t)(uintptr_t)vmem_alloc(crypto_arena, 1, VM_SLEEP);
 512 
 513         cm = kmem_zalloc(sizeof (crypto_minor_t), KM_SLEEP);
 514         mutex_init(&cm->cm_lock, NULL, MUTEX_DRIVER, NULL);
 515         cv_init(&cm->cm_cv, NULL, CV_DRIVER, NULL);
 516 
 517         CRYPTO_ENTER_ALL_LOCKS();
 518         cm->cm_refcnt = 1;
 519         crypto_minors[mn - 1] = cm;
 520         crypto_minors_count++;
 521         CRYPTO_EXIT_ALL_LOCKS();
 522 
 523         *devp = makedevice(getmajor(*devp), mn);
 524 
 525         return (0);
 526 }
 527 
 528 /* ARGSUSED1 */
 529 static int
 530 crypto_close(dev_t dev, int flag, int otyp, cred_t *credp)
 531 {
 532         crypto_minor_t *cm = NULL;
 533         crypto_session_data_t *sp;
 534         minor_t mn = getminor(dev);
 535         uint_t i;
 536         size_t total = 0;
 537         kcf_lock_withpad_t *mp;
 538 
 539         mp = &crypto_locks[CPU_SEQID];
 540         mutex_enter(&mp->kl_lock);
 541 
 542         if (mn > crypto_minors_table_count) {
 543                 mutex_exit(&mp->kl_lock);
 544                 cmn_err(CE_WARN, "crypto_close: bad minor (too big) %d", mn);
 545                 return (ENODEV);
 546         }
 547 
 548         cm = crypto_minors[mn - 1];
 549         if (cm == NULL) {
 550                 mutex_exit(&mp->kl_lock);
 551                 cmn_err(CE_WARN, "crypto_close: duplicate close of minor %d",
 552                     getminor(dev));
 553                 return (ENODEV);
 554         }
 555 
 556         mutex_exit(&mp->kl_lock);
 557 
 558         CRYPTO_ENTER_ALL_LOCKS();
 559         /*
 560          * We free the minor number, mn, from the crypto_arena
 561          * only later. This ensures that we won't race with another
 562          * thread in crypto_open with the same minor number.
 563          */
 564         crypto_minors[mn - 1] = NULL;
 565         crypto_minors_count--;
 566         CRYPTO_EXIT_ALL_LOCKS();
 567 
 568         mutex_enter(&cm->cm_lock);
 569         cm->cm_refcnt --;            /* decrement refcnt held in open */
 570         while (cm->cm_refcnt > 0) {
 571                 cv_wait(&cm->cm_cv, &cm->cm_lock);
 572         }
 573 
 574         vmem_free(crypto_arena, (void *)(uintptr_t)mn, 1);
 575 
 576         /* free all session table entries starting with 1 */
 577         for (i = 1; i < cm->cm_session_table_count; i++) {
 578                 if (cm->cm_session_table[i] == NULL)
 579                         continue;
 580 
 581                 sp = cm->cm_session_table[i];
 582                 ASSERT((sp->sd_flags & CRYPTO_SESSION_IS_BUSY) == 0);
 583                 ASSERT(sp->sd_pre_approved_amount == 0 ||
 584                     sp->sd_pre_approved_amount == crypto_pre_approved_limit);
 585                 total += sp->sd_pre_approved_amount;
 586                 if (sp->sd_find_init_cookie != NULL) {
 587                         (void) crypto_free_find_ctx(sp);
 588                 }
 589                 crypto_release_provider_session(cm, sp->sd_provider_session);
 590                 KCF_PROV_REFRELE(sp->sd_provider);
 591                 CRYPTO_CANCEL_ALL_CTX(sp);
 592                 mutex_destroy(&sp->sd_lock);
 593                 cv_destroy(&sp->sd_cv);
 594                 kmem_cache_free(crypto_session_cache, sp);
 595                 cm->cm_session_table[i] = NULL;
 596         }
 597 
 598         /* free the session table */
 599         if (cm->cm_session_table != NULL && cm->cm_session_table_count > 0)
 600                 kmem_free(cm->cm_session_table, cm->cm_session_table_count *
 601                     sizeof (void *));
 602 
 603         total += (cm->cm_session_table_count * sizeof (void *));
 604         CRYPTO_DECREMENT_RCTL(total);
 605 
 606         kcf_free_provider_tab(cm->cm_provider_count,
 607             cm->cm_provider_array);
 608 
 609         mutex_exit(&cm->cm_lock);
 610         mutex_destroy(&cm->cm_lock);
 611         cv_destroy(&cm->cm_cv);
 612         kmem_free(cm, sizeof (crypto_minor_t));
 613 
 614         return (0);
 615 }
 616 
 617 static crypto_minor_t *
 618 crypto_hold_minor(minor_t minor)
 619 {
 620         crypto_minor_t *cm;
 621         kcf_lock_withpad_t *mp;
 622 
 623         if (minor > crypto_minors_table_count)
 624                 return (NULL);
 625 
 626         mp = &crypto_locks[CPU_SEQID];
 627         mutex_enter(&mp->kl_lock);
 628 
 629         if ((cm = crypto_minors[minor - 1]) != NULL) {
 630                 atomic_inc_32(&cm->cm_refcnt);
 631         }
 632         mutex_exit(&mp->kl_lock);
 633         return (cm);
 634 }
 635 
 636 static void
 637 crypto_release_minor(crypto_minor_t *cm)
 638 {
 639         if (atomic_dec_32_nv(&cm->cm_refcnt) == 0) {
 640                 cv_signal(&cm->cm_cv);
 641         }
 642 }
 643 
 644 /*
 645  * Build a list of functions and other information for the provider, pd.
 646  */
 647 static void
 648 crypto_build_function_list(crypto_function_list_t *fl, kcf_provider_desc_t *pd)
 649 {
 650         crypto_ops_t *ops;
 651         crypto_digest_ops_t *digest_ops;
 652         crypto_cipher_ops_t *cipher_ops;
 653         crypto_mac_ops_t *mac_ops;
 654         crypto_sign_ops_t *sign_ops;
 655         crypto_verify_ops_t *verify_ops;
 656         crypto_dual_ops_t *dual_ops;
 657         crypto_random_number_ops_t *random_number_ops;
 658         crypto_session_ops_t *session_ops;
 659         crypto_object_ops_t *object_ops;
 660         crypto_key_ops_t *key_ops;
 661         crypto_provider_management_ops_t *provider_ops;
 662 
 663         if ((ops = pd->pd_ops_vector) == NULL)
 664                 return;
 665 
 666         if ((digest_ops = ops->co_digest_ops) != NULL) {
 667                 if (digest_ops->digest_init != NULL)
 668                         fl->fl_digest_init = B_TRUE;
 669                 if (digest_ops->digest != NULL)
 670                         fl->fl_digest = B_TRUE;
 671                 if (digest_ops->digest_update != NULL)
 672                         fl->fl_digest_update = B_TRUE;
 673                 if (digest_ops->digest_key != NULL)
 674                         fl->fl_digest_key = B_TRUE;
 675                 if (digest_ops->digest_final != NULL)
 676                         fl->fl_digest_final = B_TRUE;
 677         }
 678         if ((cipher_ops = ops->co_cipher_ops) != NULL) {
 679                 if (cipher_ops->encrypt_init != NULL)
 680                         fl->fl_encrypt_init = B_TRUE;
 681                 if (cipher_ops->encrypt != NULL)
 682                         fl->fl_encrypt = B_TRUE;
 683                 if (cipher_ops->encrypt_update != NULL)
 684                         fl->fl_encrypt_update = B_TRUE;
 685                 if (cipher_ops->encrypt_final != NULL)
 686                         fl->fl_encrypt_final = B_TRUE;
 687                 if (cipher_ops->decrypt_init != NULL)
 688                         fl->fl_decrypt_init = B_TRUE;
 689                 if (cipher_ops->decrypt != NULL)
 690                         fl->fl_decrypt = B_TRUE;
 691                 if (cipher_ops->decrypt_update != NULL)
 692                         fl->fl_decrypt_update = B_TRUE;
 693                 if (cipher_ops->decrypt_final != NULL)
 694                         fl->fl_decrypt_final = B_TRUE;
 695         }
 696         if ((mac_ops = ops->co_mac_ops) != NULL) {
 697                 if (mac_ops->mac_init != NULL)
 698                         fl->fl_mac_init = B_TRUE;
 699                 if (mac_ops->mac != NULL)
 700                         fl->fl_mac = B_TRUE;
 701                 if (mac_ops->mac_update != NULL)
 702                         fl->fl_mac_update = B_TRUE;
 703                 if (mac_ops->mac_final != NULL)
 704                         fl->fl_mac_final = B_TRUE;
 705         }
 706         if ((sign_ops = ops->co_sign_ops) != NULL) {
 707                 if (sign_ops->sign_init != NULL)
 708                         fl->fl_sign_init = B_TRUE;
 709                 if (sign_ops->sign != NULL)
 710                         fl->fl_sign = B_TRUE;
 711                 if (sign_ops->sign_update != NULL)
 712                         fl->fl_sign_update = B_TRUE;
 713                 if (sign_ops->sign_final != NULL)
 714                         fl->fl_sign_final = B_TRUE;
 715                 if (sign_ops->sign_recover_init != NULL)
 716                         fl->fl_sign_recover_init = B_TRUE;
 717                 if (sign_ops->sign_recover != NULL)
 718                         fl->fl_sign_recover = B_TRUE;
 719         }
 720         if ((verify_ops = ops->co_verify_ops) != NULL) {
 721                 if (verify_ops->verify_init != NULL)
 722                         fl->fl_verify_init = B_TRUE;
 723                 if (verify_ops->verify != NULL)
 724                         fl->fl_verify = B_TRUE;
 725                 if (verify_ops->verify_update != NULL)
 726                         fl->fl_verify_update = B_TRUE;
 727                 if (verify_ops->verify_final != NULL)
 728                         fl->fl_verify_final = B_TRUE;
 729                 if (verify_ops->verify_recover_init != NULL)
 730                         fl->fl_verify_recover_init = B_TRUE;
 731                 if (verify_ops->verify_recover != NULL)
 732                         fl->fl_verify_recover = B_TRUE;
 733         }
 734         if ((dual_ops = ops->co_dual_ops) != NULL) {
 735                 if (dual_ops->digest_encrypt_update != NULL)
 736                         fl->fl_digest_encrypt_update = B_TRUE;
 737                 if (dual_ops->decrypt_digest_update != NULL)
 738                         fl->fl_decrypt_digest_update = B_TRUE;
 739                 if (dual_ops->sign_encrypt_update != NULL)
 740                         fl->fl_sign_encrypt_update = B_TRUE;
 741                 if (dual_ops->decrypt_verify_update != NULL)
 742                         fl->fl_decrypt_verify_update = B_TRUE;
 743         }
 744         if ((random_number_ops = ops->co_random_ops) != NULL) {
 745                 if (random_number_ops->seed_random != NULL)
 746                         fl->fl_seed_random = B_TRUE;
 747                 if (random_number_ops->generate_random != NULL)
 748                         fl->fl_generate_random = B_TRUE;
 749         }
 750         if ((session_ops = ops->co_session_ops) != NULL) {
 751                 if (session_ops->session_open != NULL)
 752                         fl->fl_session_open = B_TRUE;
 753                 if (session_ops->session_close != NULL)
 754                         fl->fl_session_close = B_TRUE;
 755                 if (session_ops->session_login != NULL)
 756                         fl->fl_session_login = B_TRUE;
 757                 if (session_ops->session_logout != NULL)
 758                         fl->fl_session_logout = B_TRUE;
 759         }
 760         if ((object_ops = ops->co_object_ops) != NULL) {
 761                 if (object_ops->object_create != NULL)
 762                         fl->fl_object_create = B_TRUE;
 763                 if (object_ops->object_copy != NULL)
 764                         fl->fl_object_copy = B_TRUE;
 765                 if (object_ops->object_destroy != NULL)
 766                         fl->fl_object_destroy = B_TRUE;
 767                 if (object_ops->object_get_size != NULL)
 768                         fl->fl_object_get_size = B_TRUE;
 769                 if (object_ops->object_get_attribute_value != NULL)
 770                         fl->fl_object_get_attribute_value = B_TRUE;
 771                 if (object_ops->object_set_attribute_value != NULL)
 772                         fl->fl_object_set_attribute_value = B_TRUE;
 773                 if (object_ops->object_find_init != NULL)
 774                         fl->fl_object_find_init = B_TRUE;
 775                 if (object_ops->object_find != NULL)
 776                         fl->fl_object_find = B_TRUE;
 777                 if (object_ops->object_find_final != NULL)
 778                         fl->fl_object_find_final = B_TRUE;
 779         }
 780         if ((key_ops = ops->co_key_ops) != NULL) {
 781                 if (key_ops->key_generate != NULL)
 782                         fl->fl_key_generate = B_TRUE;
 783                 if (key_ops->key_generate_pair != NULL)
 784                         fl->fl_key_generate_pair = B_TRUE;
 785                 if (key_ops->key_wrap != NULL)
 786                         fl->fl_key_wrap = B_TRUE;
 787                 if (key_ops->key_unwrap != NULL)
 788                         fl->fl_key_unwrap = B_TRUE;
 789                 if (key_ops->key_derive != NULL)
 790                         fl->fl_key_derive = B_TRUE;
 791         }
 792         if ((provider_ops = ops->co_provider_ops) != NULL) {
 793                 if (provider_ops->init_token != NULL)
 794                         fl->fl_init_token = B_TRUE;
 795                 if (provider_ops->init_pin != NULL)
 796                         fl->fl_init_pin = B_TRUE;
 797                 if (provider_ops->set_pin != NULL)
 798                         fl->fl_set_pin = B_TRUE;
 799         }
 800 
 801         fl->prov_is_hash_limited = pd->pd_flags & CRYPTO_HASH_NO_UPDATE;
 802         if (fl->prov_is_hash_limited) {
 803                 fl->prov_hash_limit = min(pd->pd_hash_limit,
 804                     min(CRYPTO_MAX_BUFFER_LEN,
 805                     curproc->p_task->tk_proj->kpj_data.kpd_crypto_mem_ctl));
 806         }
 807 
 808         fl->prov_is_hmac_limited = pd->pd_flags & CRYPTO_HMAC_NO_UPDATE;
 809         if (fl->prov_is_hmac_limited) {
 810                 fl->prov_hmac_limit = min(pd->pd_hmac_limit,
 811                     min(CRYPTO_MAX_BUFFER_LEN,
 812                     curproc->p_task->tk_proj->kpj_data.kpd_crypto_mem_ctl));
 813         }
 814 
 815         if (fl->prov_is_hash_limited || fl->prov_is_hmac_limited) {
 816                 /*
 817                  * XXX - The threshold should ideally be per hash/HMAC
 818                  * mechanism. For now, we use the same value for all
 819                  * hash/HMAC mechanisms. Empirical evidence suggests this
 820                  * is fine.
 821                  */
 822                 fl->prov_hash_threshold = kcf_md5_threshold;
 823         }
 824 
 825         fl->total_threshold_count = MAX_NUM_THRESHOLD;
 826         fl->fl_threshold[0].mech_type = CKM_DES3_CBC;
 827         fl->fl_threshold[0].mech_threshold = kcf_des3_threshold;
 828         fl->fl_threshold[1].mech_type = CKM_DES3_ECB;
 829         fl->fl_threshold[1].mech_threshold = kcf_des3_threshold;
 830         fl->fl_threshold[2].mech_type = CKM_AES_CBC;
 831         fl->fl_threshold[2].mech_threshold = kcf_aes_threshold;
 832         fl->fl_threshold[3].mech_type = CKM_AES_ECB;
 833         fl->fl_threshold[3].mech_threshold = kcf_aes_threshold;
 834         fl->fl_threshold[4].mech_type = CKM_RC4;
 835         fl->fl_threshold[4].mech_threshold = kcf_rc4_threshold;
 836         fl->fl_threshold[5].mech_type = CKM_MD5;
 837         fl->fl_threshold[5].mech_threshold = kcf_md5_threshold;
 838         fl->fl_threshold[6].mech_type = CKM_SHA_1;
 839         fl->fl_threshold[6].mech_threshold = kcf_sha1_threshold;
 840 }
 841 
 842 /* ARGSUSED */
 843 static int
 844 get_function_list(dev_t dev, caddr_t arg, int mode, int *rval)
 845 {
 846         crypto_get_function_list_t get_function_list;
 847         crypto_minor_t *cm;
 848         crypto_provider_id_t provider_id;
 849         crypto_function_list_t *fl;
 850         kcf_provider_desc_t *provider;
 851         int rv;
 852 
 853         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
 854                 cmn_err(CE_WARN, "get_function_list: failed holding minor");
 855                 return (ENXIO);
 856         }
 857 
 858         if (copyin(arg, &get_function_list, sizeof (get_function_list)) != 0) {
 859                 crypto_release_minor(cm);
 860                 return (EFAULT);
 861         }
 862 
 863         /* initialize provider_array */
 864         if (cm->cm_provider_array == NULL) {
 865                 rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST);
 866                 if (rv != CRYPTO_SUCCESS) {
 867                         goto release_minor;
 868                 }
 869         }
 870 
 871         provider_id = get_function_list.fl_provider_id;
 872         mutex_enter(&cm->cm_lock);
 873         /* index must be less than count of providers */
 874         if (provider_id >= cm->cm_provider_count) {
 875                 mutex_exit(&cm->cm_lock);
 876                 rv = CRYPTO_ARGUMENTS_BAD;
 877                 goto release_minor;
 878         }
 879 
 880         ASSERT(cm->cm_provider_array != NULL);
 881         provider = cm->cm_provider_array[provider_id];
 882         mutex_exit(&cm->cm_lock);
 883 
 884         fl = &get_function_list.fl_list;
 885         bzero(fl, sizeof (crypto_function_list_t));
 886 
 887         if (provider->pd_prov_type != CRYPTO_LOGICAL_PROVIDER) {
 888                 crypto_build_function_list(fl, provider);
 889         } else {
 890                 kcf_provider_desc_t *prev = NULL, *pd;
 891 
 892                 mutex_enter(&provider->pd_lock);
 893                 while (kcf_get_next_logical_provider_member(provider,
 894                     prev, &pd)) {
 895                         prev = pd;
 896                         crypto_build_function_list(fl, pd);
 897                         KCF_PROV_REFRELE(pd);
 898                 }
 899                 mutex_exit(&provider->pd_lock);
 900         }
 901 
 902         rv = CRYPTO_SUCCESS;
 903 
 904 release_minor:
 905         crypto_release_minor(cm);
 906 
 907         get_function_list.fl_return_value = rv;
 908 
 909         if (copyout(&get_function_list, arg, sizeof (get_function_list)) != 0) {
 910                 return (EFAULT);
 911         }
 912         return (0);
 913 }
 914 
 915 /*
 916  * This ioctl maps a PKCS#11 mechanism string into an internal number
 917  * that is used by the kernel.  pn_internal_number is set to the
 918  * internal number.
 919  */
 920 /* ARGSUSED */
 921 static int
 922 get_mechanism_number(dev_t dev, caddr_t arg, int mode, int *rval)
 923 {
 924         STRUCT_DECL(crypto_get_mechanism_number, get_number);
 925         crypto_mech_type_t number;
 926         size_t len;
 927         char *mechanism_name;
 928         int rv;
 929 
 930         STRUCT_INIT(get_number, mode);
 931 
 932         if (copyin(arg, STRUCT_BUF(get_number), STRUCT_SIZE(get_number)) != 0)
 933                 return (EFAULT);
 934 
 935         len = STRUCT_FGET(get_number, pn_mechanism_len);
 936         if (len == 0 || len > CRYPTO_MAX_MECH_NAME) {
 937                 rv = CRYPTO_ARGUMENTS_BAD;
 938                 goto out;
 939         }
 940         mechanism_name = kmem_alloc(len, KM_SLEEP);
 941 
 942         if (copyin(STRUCT_FGETP(get_number, pn_mechanism_string),
 943             mechanism_name, len) != 0) {
 944                 kmem_free(mechanism_name, len);
 945                 return (EFAULT);
 946         }
 947 
 948         /*
 949          * Get mechanism number from kcf. We set the load_module
 950          * flag to false since we use only hardware providers.
 951          */
 952         number = crypto_mech2id_common(mechanism_name, B_FALSE);
 953         kmem_free(mechanism_name, len);
 954         if (number == CRYPTO_MECH_INVALID) {
 955                 rv = CRYPTO_ARGUMENTS_BAD;
 956                 goto out;
 957         }
 958 
 959         bcopy((char *)&number, (char *)STRUCT_FADDR(get_number,
 960             pn_internal_number), sizeof (number));
 961 
 962         rv = CRYPTO_SUCCESS;
 963 out:
 964         STRUCT_FSET(get_number, pn_return_value, rv);
 965 
 966         if (copyout(STRUCT_BUF(get_number), arg,
 967             STRUCT_SIZE(get_number)) != 0) {
 968                 return (EFAULT);
 969         }
 970         return (0);
 971 }
 972 
 973 /*
 974  * This ioctl returns an array of crypto_mech_name_t entries.
 975  * It lists all the PKCS#11 mechanisms available in the kernel.
 976  */
 977 /* ARGSUSED */
 978 static int
 979 get_mechanism_list(dev_t dev, caddr_t arg, int mode, int *rval)
 980 {
 981         STRUCT_DECL(crypto_get_mechanism_list, get_list);
 982         crypto_mech_name_t *entries;
 983         size_t copyout_size;
 984         uint_t req_count;
 985         uint_t count;
 986         ulong_t offset;
 987         int error = 0;
 988 
 989         STRUCT_INIT(get_list, mode);
 990 
 991         if (copyin(arg, STRUCT_BUF(get_list), STRUCT_SIZE(get_list)) != 0) {
 992                 return (EFAULT);
 993         }
 994 
 995         entries = crypto_get_mech_list(&count, KM_SLEEP);
 996 
 997         /* Number of entries caller thinks we have */
 998         req_count = STRUCT_FGET(get_list, ml_count);
 999 
1000         STRUCT_FSET(get_list, ml_count, count);
1001         STRUCT_FSET(get_list, ml_return_value, CRYPTO_SUCCESS);
1002 
1003         /* check if buffer is too small */
1004         if (count > req_count) {
1005                 STRUCT_FSET(get_list, ml_return_value, CRYPTO_BUFFER_TOO_SMALL);
1006         }
1007 
1008         /* copyout the first stuff */
1009         if (copyout(STRUCT_BUF(get_list), arg, STRUCT_SIZE(get_list)) != 0) {
1010                 error = EFAULT;
1011         }
1012 
1013         /*
1014          * If only requesting number of entries or buffer too small or an
1015          * error occurred, stop here
1016          */
1017         if (req_count == 0 || count > req_count || error != 0) {
1018                 goto out;
1019         }
1020 
1021         copyout_size = count * sizeof (crypto_mech_name_t);
1022 
1023         /* copyout entries */
1024         offset = (ulong_t)STRUCT_FADDR(get_list, ml_list);
1025         offset -= (ulong_t)STRUCT_BUF(get_list);
1026         if (copyout(entries, arg + offset, copyout_size) != 0) {
1027                 error = EFAULT;
1028         }
1029 
1030 out:
1031         crypto_free_mech_list(entries, count);
1032         return (error);
1033 }
1034 
1035 /*
1036  * Copyout kernel array of mech_infos to user space.
1037  */
1038 /* ARGSUSED */
1039 static int
1040 copyout_mechinfos(int mode, caddr_t out, uint_t count,
1041     crypto_mechanism_info_t *k_minfos, caddr_t u_minfos)
1042 {
1043         STRUCT_DECL(crypto_mechanism_info, mi);
1044         caddr_t p;
1045         size_t len;
1046         int i;
1047 
1048         if (count == 0)
1049                 return (0);
1050 
1051         STRUCT_INIT(mi, mode);
1052 
1053         len = count * STRUCT_SIZE(mi);
1054 
1055         ASSERT(u_minfos != NULL);
1056         p = u_minfos;
1057         for (i = 0; i < count; i++) {
1058                 STRUCT_FSET(mi, mi_min_key_size, k_minfos[i].mi_min_key_size);
1059                 STRUCT_FSET(mi, mi_max_key_size, k_minfos[i].mi_max_key_size);
1060                 STRUCT_FSET(mi, mi_keysize_unit, k_minfos[i].mi_keysize_unit);
1061                 STRUCT_FSET(mi, mi_usage, k_minfos[i].mi_usage);
1062                 bcopy(STRUCT_BUF(mi), p, STRUCT_SIZE(mi));
1063                 p += STRUCT_SIZE(mi);
1064         }
1065 
1066         if (copyout(u_minfos, out, len) != 0)
1067                 return (EFAULT);
1068 
1069         return (0);
1070 }
1071 
1072 /*
1073  * This ioctl returns information for the specified mechanism.
1074  */
1075 /* ARGSUSED */
1076 static int
1077 get_all_mechanism_info(dev_t dev, caddr_t arg, int mode, int *rval)
1078 {
1079         STRUCT_DECL(crypto_get_all_mechanism_info, get_all_mech);
1080 #ifdef _LP64
1081         STRUCT_DECL(crypto_mechanism_info, mi);
1082 #else
1083         /* LINTED E_FUNC_SET_NOT_USED */
1084         STRUCT_DECL(crypto_mechanism_info, mi);
1085 #endif
1086         crypto_mech_name_t mech_name;
1087         crypto_mech_type_t mech_type;
1088         crypto_mechanism_info_t *mech_infos = NULL;
1089         uint_t num_mech_infos = 0;
1090         uint_t req_count;
1091         caddr_t u_minfos;
1092         ulong_t offset;
1093         int error = 0;
1094         int rv;
1095 
1096         STRUCT_INIT(get_all_mech, mode);
1097         STRUCT_INIT(mi, mode);
1098 
1099         if (copyin(arg, STRUCT_BUF(get_all_mech),
1100             STRUCT_SIZE(get_all_mech)) != 0) {
1101                 return (EFAULT);
1102         }
1103 
1104         (void) strncpy(mech_name, STRUCT_FGET(get_all_mech, mi_mechanism_name),
1105             CRYPTO_MAX_MECH_NAME);
1106         mech_type = crypto_mech2id(mech_name);
1107 
1108         if (mech_type == CRYPTO_MECH_INVALID) {
1109                 rv = CRYPTO_ARGUMENTS_BAD;
1110                 goto out1;
1111         }
1112 
1113         rv = crypto_get_all_mech_info(mech_type, &mech_infos, &num_mech_infos,
1114             KM_SLEEP);
1115         if (rv != CRYPTO_SUCCESS) {
1116                 goto out1;
1117         }
1118         /* rv is CRYPTO_SUCCESS at this point */
1119 
1120         /* Number of entries caller thinks we have */
1121         req_count = STRUCT_FGET(get_all_mech, mi_count);
1122 
1123         STRUCT_FSET(get_all_mech, mi_count, num_mech_infos);
1124 
1125         /* check if buffer is too small */
1126         if (num_mech_infos > req_count) {
1127                 rv = CRYPTO_BUFFER_TOO_SMALL;
1128         }
1129 
1130 out1:
1131         STRUCT_FSET(get_all_mech, mi_return_value, rv);
1132 
1133         /* copy the first part */
1134         if (copyout(STRUCT_BUF(get_all_mech), arg,
1135             STRUCT_SIZE(get_all_mech)) != 0) {
1136                 error = EFAULT;
1137         }
1138 
1139         /*
1140          * If only requesting number of entries, or there are no entries,
1141          * or rv is not CRYPTO_SUCCESS due to buffer too small or some other
1142          * crypto error, or an error occurred with copyout, stop here
1143          */
1144         if (req_count == 0 || num_mech_infos == 0 || rv != CRYPTO_SUCCESS ||
1145             error != 0) {
1146                 goto out2;
1147         }
1148 
1149         /* copyout mech_infos */
1150         offset = (ulong_t)STRUCT_FADDR(get_all_mech, mi_list);
1151         offset -= (ulong_t)STRUCT_BUF(get_all_mech);
1152 
1153         u_minfos = kmem_alloc(num_mech_infos * STRUCT_SIZE(mi), KM_SLEEP);
1154         error = copyout_mechinfos(mode, arg + offset, num_mech_infos,
1155             mech_infos, u_minfos);
1156         kmem_free(u_minfos, num_mech_infos * STRUCT_SIZE(mi));
1157 out2:
1158         if (mech_infos != NULL)
1159                 crypto_free_all_mech_info(mech_infos, num_mech_infos);
1160         return (error);
1161 }
1162 
1163 /*
1164  * Side-effects:
1165  *  1. This routine stores provider descriptor pointers in an array
1166  *     and increments each descriptor's reference count.  The array
1167  *     is stored in per-minor number storage.
1168  *  2. Destroys the old array and creates a new one every time
1169  *     this routine is called.
1170  */
1171 int
1172 crypto_get_provider_list(crypto_minor_t *cm, uint_t *count,
1173     crypto_provider_entry_t **array, boolean_t return_slot_list)
1174 {
1175         kcf_provider_desc_t **provider_array;
1176         crypto_provider_entry_t *p = NULL;
1177         uint_t provider_count;
1178         int rval;
1179         int i;
1180 
1181         /*
1182          * Take snapshot of provider table returning only HW entries
1183          * that are in a usable state. Also returns logical provider entries.
1184          */
1185         rval =  kcf_get_slot_list(&provider_count, &provider_array, B_FALSE);
1186         if (rval != CRYPTO_SUCCESS)
1187                 return (rval);
1188 
1189         /* allocate memory before taking cm->cm_lock */
1190         if (return_slot_list) {
1191                 if (provider_count != 0) {
1192                         p = kmem_alloc(provider_count *
1193                             sizeof (crypto_provider_entry_t), KM_SLEEP);
1194                         for (i = 0; i < provider_count; i++) {
1195                                 p[i].pe_provider_id = i;
1196                                 p[i].pe_mechanism_count =
1197                                     provider_array[i]->pd_mech_list_count;
1198                         }
1199                 }
1200                 *array = p;
1201                 *count = provider_count;
1202         }
1203 
1204         /*
1205          * Free existing array of providers and replace with new list.
1206          */
1207         mutex_enter(&cm->cm_lock);
1208         if (cm->cm_provider_array != NULL) {
1209                 ASSERT(cm->cm_provider_count > 0);
1210                 kcf_free_provider_tab(cm->cm_provider_count,
1211                     cm->cm_provider_array);
1212         }
1213 
1214         cm->cm_provider_array = provider_array;
1215         cm->cm_provider_count = provider_count;
1216         mutex_exit(&cm->cm_lock);
1217 
1218         return (CRYPTO_SUCCESS);
1219 }
1220 
1221 /*
1222  * This ioctl returns an array of crypto_provider_entry_t entries.
1223  * This is how consumers learn which hardware providers are available.
1224  */
1225 /* ARGSUSED */
1226 static int
1227 get_provider_list(dev_t dev, caddr_t arg, int mode, int *rval)
1228 {
1229         STRUCT_DECL(crypto_get_provider_list, get_list);
1230         crypto_provider_entry_t *entries;
1231         crypto_minor_t *cm;
1232         size_t copyout_size;
1233         uint_t req_count;
1234         uint_t count;
1235         ulong_t offset;
1236         int rv;
1237 
1238         STRUCT_INIT(get_list, mode);
1239 
1240         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
1241                 cmn_err(CE_WARN, "get_provider_list: failed holding minor");
1242                 return (ENXIO);
1243         }
1244 
1245         if (copyin(arg, STRUCT_BUF(get_list), STRUCT_SIZE(get_list)) != 0) {
1246                 crypto_release_minor(cm);
1247                 return (EFAULT);
1248         }
1249 
1250         rv = crypto_get_provider_list(cm, &count, &entries, RETURN_LIST);
1251         if (rv != CRYPTO_SUCCESS) {
1252                 crypto_release_minor(cm);
1253                 STRUCT_FSET(get_list, pl_return_value, rv);
1254                 if (copyout(STRUCT_BUF(get_list), arg,
1255                     STRUCT_SIZE(get_list)) != 0) {
1256                         return (EFAULT);
1257                 }
1258                 return (0);
1259         }
1260         crypto_release_minor(cm);
1261 
1262         /* Number of slots caller thinks we have */
1263         req_count = STRUCT_FGET(get_list, pl_count);
1264 
1265         /* Check if only requesting number of slots */
1266         if (req_count == 0) {
1267 
1268                 STRUCT_FSET(get_list, pl_count, count);
1269                 STRUCT_FSET(get_list, pl_return_value, CRYPTO_SUCCESS);
1270 
1271                 crypto_free_provider_list(entries, count);
1272                 if (copyout(STRUCT_BUF(get_list), arg,
1273                     STRUCT_SIZE(get_list)) != 0) {
1274                         return (EFAULT);
1275                 }
1276                 return (0);
1277         }
1278 
1279         /* check if buffer is too small */
1280         req_count = STRUCT_FGET(get_list, pl_count);
1281         if (count > req_count) {
1282                 STRUCT_FSET(get_list, pl_count, count);
1283                 STRUCT_FSET(get_list, pl_return_value, CRYPTO_BUFFER_TOO_SMALL);
1284                 crypto_free_provider_list(entries, count);
1285                 if (copyout(STRUCT_BUF(get_list), arg,
1286                     STRUCT_SIZE(get_list)) != 0) {
1287                         return (EFAULT);
1288                 }
1289                 return (0);
1290         }
1291 
1292         STRUCT_FSET(get_list, pl_count, count);
1293         STRUCT_FSET(get_list, pl_return_value, CRYPTO_SUCCESS);
1294 
1295         copyout_size = count * sizeof (crypto_provider_entry_t);
1296 
1297         /* copyout the first stuff */
1298         if (copyout(STRUCT_BUF(get_list), arg, STRUCT_SIZE(get_list)) != 0) {
1299                 crypto_free_provider_list(entries, count);
1300                 return (EFAULT);
1301         }
1302 
1303         if (count == 0) {
1304                 crypto_free_provider_list(entries, count);
1305                 return (0);
1306         }
1307 
1308         /* copyout entries */
1309         offset = (ulong_t)STRUCT_FADDR(get_list, pl_list);
1310         offset -= (ulong_t)STRUCT_BUF(get_list);
1311         if (copyout(entries, arg + offset, copyout_size) != 0) {
1312                 crypto_free_provider_list(entries, count);
1313                 return (EFAULT);
1314         }
1315 
1316         crypto_free_provider_list(entries, count);
1317         return (0);
1318 }
1319 
1320 static void
1321 ext_to_provider_data(int mode, kcf_provider_desc_t *provider,
1322     crypto_provider_ext_info_t *ei, void *out)
1323 {
1324         STRUCT_DECL(crypto_provider_data, pd);
1325         STRUCT_DECL(crypto_version, version);
1326 
1327         STRUCT_INIT(pd, mode);
1328         STRUCT_INIT(version, mode);
1329 
1330         bcopy(provider->pd_description, STRUCT_FGET(pd, pd_prov_desc),
1331             CRYPTO_PROVIDER_DESCR_MAX_LEN);
1332 
1333         bcopy(ei->ei_label, STRUCT_FGET(pd, pd_label), CRYPTO_EXT_SIZE_LABEL);
1334         bcopy(ei->ei_manufacturerID, STRUCT_FGET(pd, pd_manufacturerID),
1335             CRYPTO_EXT_SIZE_MANUF);
1336         bcopy(ei->ei_model, STRUCT_FGET(pd, pd_model), CRYPTO_EXT_SIZE_MODEL);
1337         bcopy(ei->ei_serial_number, STRUCT_FGET(pd, pd_serial_number),
1338             CRYPTO_EXT_SIZE_SERIAL);
1339         /*
1340          * We do not support ioctls for dual-function crypto operations yet.
1341          * So, we clear this flag as it might have been set by a provider.
1342          */
1343         ei->ei_flags &= ~CRYPTO_EXTF_DUAL_CRYPTO_OPERATIONS;
1344 
1345         STRUCT_FSET(pd, pd_flags, ei->ei_flags);
1346         STRUCT_FSET(pd, pd_max_session_count, ei->ei_max_session_count);
1347         STRUCT_FSET(pd, pd_session_count, (int)CRYPTO_UNAVAILABLE_INFO);
1348         STRUCT_FSET(pd, pd_max_rw_session_count, ei->ei_max_session_count);
1349         STRUCT_FSET(pd, pd_rw_session_count, (int)CRYPTO_UNAVAILABLE_INFO);
1350         STRUCT_FSET(pd, pd_max_pin_len, ei->ei_max_pin_len);
1351         STRUCT_FSET(pd, pd_min_pin_len, ei->ei_min_pin_len);
1352         STRUCT_FSET(pd, pd_total_public_memory, ei->ei_total_public_memory);
1353         STRUCT_FSET(pd, pd_free_public_memory, ei->ei_free_public_memory);
1354         STRUCT_FSET(pd, pd_total_private_memory, ei->ei_total_private_memory);
1355         STRUCT_FSET(pd, pd_free_private_memory, ei->ei_free_private_memory);
1356         STRUCT_FSET(version, cv_major, ei->ei_hardware_version.cv_major);
1357         STRUCT_FSET(version, cv_minor, ei->ei_hardware_version.cv_minor);
1358         bcopy(STRUCT_BUF(version), STRUCT_FADDR(pd, pd_hardware_version),
1359             STRUCT_SIZE(version));
1360         STRUCT_FSET(version, cv_major, ei->ei_firmware_version.cv_major);
1361         STRUCT_FSET(version, cv_minor, ei->ei_firmware_version.cv_minor);
1362         bcopy(STRUCT_BUF(version), STRUCT_FADDR(pd, pd_firmware_version),
1363             STRUCT_SIZE(version));
1364         bcopy(ei->ei_time, STRUCT_FGET(pd, pd_time), CRYPTO_EXT_SIZE_TIME);
1365         bcopy(STRUCT_BUF(pd), out, STRUCT_SIZE(pd));
1366 }
1367 
1368 /*
1369  * Utility routine to construct a crypto_provider_ext_info structure. Some
1370  * of the fields are constructed from information in the provider structure.
1371  * The rest of the fields have default values. We need to do this for
1372  * providers which do not support crypto_provider_management_ops routines.
1373  */
1374 static void
1375 fabricate_ext_info(kcf_provider_desc_t *provider,
1376     crypto_provider_ext_info_t *ei)
1377 {
1378         /* empty label */
1379         (void) memset(ei->ei_label, ' ', CRYPTO_EXT_SIZE_LABEL);
1380 
1381         (void) memset(ei->ei_manufacturerID, ' ', CRYPTO_EXT_SIZE_MANUF);
1382         (void) strncpy((char *)ei->ei_manufacturerID, "Unknown", 7);
1383 
1384         (void) memset(ei->ei_model, ' ', CRYPTO_EXT_SIZE_MODEL);
1385         (void) strncpy((char *)ei->ei_model, "Unknown", 7);
1386 
1387         (void) memset(ei->ei_serial_number, ' ', CRYPTO_EXT_SIZE_SERIAL);
1388         (void) strncpy((char *)ei->ei_serial_number, "Unknown", 7);
1389 
1390         if (KCF_PROV_RANDOM_OPS(provider) != NULL)
1391                 ei->ei_flags |= CRYPTO_EXTF_RNG;
1392         if (KCF_PROV_DUAL_OPS(provider) != NULL)
1393                 ei->ei_flags |= CRYPTO_EXTF_DUAL_CRYPTO_OPERATIONS;
1394 
1395         ei->ei_max_session_count = CRYPTO_UNAVAILABLE_INFO;
1396         ei->ei_max_pin_len = 0;
1397         ei->ei_min_pin_len = 0;
1398         ei->ei_total_public_memory = CRYPTO_UNAVAILABLE_INFO;
1399         ei->ei_free_public_memory = CRYPTO_UNAVAILABLE_INFO;
1400         ei->ei_total_private_memory = CRYPTO_UNAVAILABLE_INFO;
1401         ei->ei_free_private_memory = CRYPTO_UNAVAILABLE_INFO;
1402         ei->ei_hardware_version.cv_major = 1;
1403         ei->ei_hardware_version.cv_minor = 0;
1404         ei->ei_firmware_version.cv_major = 1;
1405         ei->ei_firmware_version.cv_minor = 0;
1406 }
1407 
1408 /* ARGSUSED */
1409 static int
1410 get_provider_info(dev_t dev, caddr_t arg, int mode, int *rval)
1411 {
1412         STRUCT_DECL(crypto_get_provider_info, get_info);
1413         crypto_minor_t *cm;
1414         crypto_provider_id_t provider_id;
1415         kcf_provider_desc_t *provider, *real_provider;
1416         crypto_provider_ext_info_t *ext_info = NULL;
1417         size_t need;
1418         int error = 0;
1419         int rv;
1420         kcf_req_params_t params;
1421 
1422         STRUCT_INIT(get_info, mode);
1423 
1424         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
1425                 cmn_err(CE_WARN, "get_provider_info: failed holding minor");
1426                 return (ENXIO);
1427         }
1428 
1429         if (copyin(arg, STRUCT_BUF(get_info), STRUCT_SIZE(get_info)) != 0) {
1430                 crypto_release_minor(cm);
1431                 return (EFAULT);
1432         }
1433 
1434         need = sizeof (crypto_provider_ext_info_t);
1435         if ((rv = crypto_buffer_check(need)) != CRYPTO_SUCCESS) {
1436                 need = 0;
1437                 goto release_minor;
1438         }
1439 
1440         /* initialize provider_array */
1441         if (cm->cm_provider_array == NULL) {
1442                 rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST);
1443                 if (rv != CRYPTO_SUCCESS) {
1444                         goto release_minor;
1445                 }
1446         }
1447 
1448         ext_info = kmem_zalloc(need, KM_SLEEP);
1449 
1450         provider_id = STRUCT_FGET(get_info, gi_provider_id);
1451         mutex_enter(&cm->cm_lock);
1452         /* index must be less than count of providers */
1453         if (provider_id >= cm->cm_provider_count) {
1454                 mutex_exit(&cm->cm_lock);
1455                 rv = CRYPTO_ARGUMENTS_BAD;
1456                 goto release_minor;
1457         }
1458 
1459         ASSERT(cm->cm_provider_array != NULL);
1460         provider = cm->cm_provider_array[provider_id];
1461         KCF_PROV_REFHOLD(provider);
1462         mutex_exit(&cm->cm_lock);
1463 
1464         (void) kcf_get_hardware_provider_nomech(
1465             CRYPTO_OPS_OFFSET(provider_ops), CRYPTO_PROVIDER_OFFSET(ext_info),
1466             provider, &real_provider);
1467 
1468         if (real_provider != NULL) {
1469                 ASSERT(real_provider == provider ||
1470                     provider->pd_prov_type == CRYPTO_LOGICAL_PROVIDER);
1471                 KCF_WRAP_PROVMGMT_OPS_PARAMS(&params, KCF_OP_MGMT_EXTINFO,
1472                     0, NULL, 0, NULL, 0, NULL, ext_info, provider);
1473                 rv = kcf_submit_request(real_provider, NULL, NULL, &params,
1474                     B_FALSE);
1475                 ASSERT(rv != CRYPTO_NOT_SUPPORTED);
1476                 KCF_PROV_REFRELE(real_provider);
1477         } else {
1478                 /* do the best we can */
1479                 fabricate_ext_info(provider, ext_info);
1480                 rv = CRYPTO_SUCCESS;
1481         }
1482         KCF_PROV_REFRELE(provider);
1483 
1484         if (rv == CRYPTO_SUCCESS) {
1485                 ext_to_provider_data(mode, provider, ext_info,
1486                     STRUCT_FADDR(get_info, gi_provider_data));
1487         }
1488 
1489 release_minor:
1490         CRYPTO_DECREMENT_RCTL(need);
1491         crypto_release_minor(cm);
1492 
1493         if (ext_info != NULL)
1494                 kmem_free(ext_info, sizeof (crypto_provider_ext_info_t));
1495 
1496         if (error != 0)
1497                 return (error);
1498 
1499         STRUCT_FSET(get_info, gi_return_value, rv);
1500         if (copyout(STRUCT_BUF(get_info), arg, STRUCT_SIZE(get_info)) != 0) {
1501                 return (EFAULT);
1502         }
1503         return (0);
1504 }
1505 
1506 /*
1507  * This ioctl returns an array of crypto_mech_name_t entries.
1508  * This is how consumers learn which mechanisms are permitted
1509  * by a provider.
1510  */
1511 /* ARGSUSED */
1512 static int
1513 get_provider_mechanisms(dev_t dev, caddr_t arg, int mode, int *rval)
1514 {
1515         STRUCT_DECL(crypto_get_provider_mechanisms, get_mechanisms);
1516         crypto_mech_name_t *entries;
1517         crypto_minor_t *cm;
1518         size_t copyout_size;
1519         uint_t req_count;
1520         uint_t count;
1521         ulong_t offset;
1522         int err;
1523 
1524         STRUCT_INIT(get_mechanisms, mode);
1525 
1526         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
1527                 cmn_err(CE_WARN,
1528                     "get_provider_mechanisms: failed holding minor");
1529                 return (ENXIO);
1530         }
1531 
1532         if (copyin(arg, STRUCT_BUF(get_mechanisms),
1533             STRUCT_SIZE(get_mechanisms)) != 0) {
1534                 crypto_release_minor(cm);
1535                 return (EFAULT);
1536         }
1537 
1538         /* get array of mechanisms from the core module */
1539         if ((err = crypto_get_provider_mechanisms(cm,
1540             STRUCT_FGET(get_mechanisms, pm_provider_id),
1541             &count, &entries)) != 0) {
1542                 crypto_release_minor(cm);
1543                 STRUCT_FSET(get_mechanisms, pm_return_value, err);
1544                 if (copyout(STRUCT_BUF(get_mechanisms), arg,
1545                     STRUCT_SIZE(get_mechanisms)) != 0) {
1546                         return (EFAULT);
1547                 }
1548                 return (0);
1549         }
1550         crypto_release_minor(cm);
1551         /* Number of mechs caller thinks we have */
1552         req_count = STRUCT_FGET(get_mechanisms, pm_count);
1553 
1554         /* Check if caller is just requesting a count of mechanisms */
1555         if (req_count == 0) {
1556                 STRUCT_FSET(get_mechanisms, pm_count, count);
1557                 STRUCT_FSET(get_mechanisms, pm_return_value, CRYPTO_SUCCESS);
1558 
1559                 crypto_free_mech_list(entries, count);
1560                 if (copyout(STRUCT_BUF(get_mechanisms), arg,
1561                     STRUCT_SIZE(get_mechanisms)) != 0) {
1562                         return (EFAULT);
1563                 }
1564                 return (0);
1565         }
1566 
1567         /* check if buffer is too small */
1568         if (count > req_count) {
1569                 STRUCT_FSET(get_mechanisms, pm_count, count);
1570                 STRUCT_FSET(get_mechanisms, pm_return_value,
1571                     CRYPTO_BUFFER_TOO_SMALL);
1572                 crypto_free_mech_list(entries, count);
1573                 if (copyout(STRUCT_BUF(get_mechanisms), arg,
1574                     STRUCT_SIZE(get_mechanisms)) != 0) {
1575                         return (EFAULT);
1576                 }
1577                 return (0);
1578         }
1579 
1580         STRUCT_FSET(get_mechanisms, pm_count, count);
1581         STRUCT_FSET(get_mechanisms, pm_return_value, CRYPTO_SUCCESS);
1582 
1583         copyout_size = count * sizeof (crypto_mech_name_t);
1584 
1585         /* copyout the first stuff */
1586         if (copyout(STRUCT_BUF(get_mechanisms), arg,
1587             STRUCT_SIZE(get_mechanisms)) != 0) {
1588                 crypto_free_mech_list(entries, count);
1589                 return (EFAULT);
1590         }
1591 
1592         if (count == 0) {
1593                 return (0);
1594         }
1595 
1596         /* copyout entries */
1597         offset = (ulong_t)STRUCT_FADDR(get_mechanisms, pm_list);
1598         offset -= (ulong_t)STRUCT_BUF(get_mechanisms);
1599         if (copyout(entries, arg + offset, copyout_size) != 0) {
1600                 crypto_free_mech_list(entries, count);
1601                 return (EFAULT);
1602         }
1603 
1604         crypto_free_mech_list(entries, count);
1605         return (0);
1606 }
1607 
1608 /*
1609  * This ioctl returns information about a provider's mechanism.
1610  */
1611 /* ARGSUSED */
1612 static int
1613 get_provider_mechanism_info(dev_t dev, caddr_t arg, int mode, int *rval)
1614 {
1615         crypto_get_provider_mechanism_info_t mechanism_info;
1616         crypto_minor_t *cm;
1617         kcf_provider_desc_t *pd;
1618         crypto_mech_info_t *mi = NULL;
1619         int rv = CRYPTO_SUCCESS;
1620         int i;
1621 
1622         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
1623                 cmn_err(CE_WARN,
1624                     "get_provider_mechanism_info: failed holding minor");
1625                 return (ENXIO);
1626         }
1627 
1628         if (copyin(arg, &mechanism_info, sizeof (mechanism_info)) != 0) {
1629                 crypto_release_minor(cm);
1630                 return (EFAULT);
1631         }
1632 
1633         /* initialize provider table */
1634         if (cm->cm_provider_array == NULL) {
1635                 rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST);
1636                 if (rv != CRYPTO_SUCCESS) {
1637                         mutex_enter(&cm->cm_lock);
1638                         goto fail;
1639                 }
1640         }
1641 
1642         /*
1643          * Provider ID must be less than the count of providers
1644          * obtained by calling get_provider_list().
1645          */
1646         mutex_enter(&cm->cm_lock);
1647         if (mechanism_info.mi_provider_id >= cm->cm_provider_count) {
1648                 rv = CRYPTO_ARGUMENTS_BAD;
1649                 goto fail;
1650         }
1651 
1652         pd = cm->cm_provider_array[mechanism_info.mi_provider_id];
1653 
1654         /* First check if the provider supports the mechanism. */
1655         for (i = 0; i < pd->pd_mech_list_count; i++) {
1656                 if (strncmp(pd->pd_mechanisms[i].cm_mech_name,
1657                     mechanism_info.mi_mechanism_name,
1658                     CRYPTO_MAX_MECH_NAME) == 0) {
1659                         mi = &pd->pd_mechanisms[i];
1660                         break;
1661                 }
1662         }
1663 
1664         if (mi == NULL) {
1665                 rv = CRYPTO_ARGUMENTS_BAD;
1666                 goto fail;
1667         }
1668 
1669         /* Now check if the mechanism is enabled for the provider. */
1670         if (is_mech_disabled(pd, mechanism_info.mi_mechanism_name)) {
1671                 rv = CRYPTO_MECHANISM_INVALID;
1672                 goto fail;
1673         }
1674 
1675         mechanism_info.mi_min_key_size = mi->cm_min_key_length;
1676         mechanism_info.mi_max_key_size = mi->cm_max_key_length;
1677         mechanism_info.mi_flags = mi->cm_func_group_mask;
1678 
1679 fail:
1680         mutex_exit(&cm->cm_lock);
1681         crypto_release_minor(cm);
1682         mechanism_info.mi_return_value = rv;
1683         if (copyout(&mechanism_info, arg, sizeof (mechanism_info)) != 0) {
1684                 return (EFAULT);
1685         }
1686 
1687         return (0);
1688 }
1689 
1690 /*
1691  * Every open of /dev/crypto multiplexes all PKCS#11 sessions across
1692  * a single session to each provider. Calls to open and close session
1693  * are not made to providers that do not support sessions. For these
1694  * providers, a session number of 0 is passed during subsequent operations,
1695  * and it is ignored by the provider.
1696  */
1697 static int
1698 crypto_get_provider_session(crypto_minor_t *cm,
1699     crypto_provider_id_t provider_index, crypto_provider_session_t **output_ps)
1700 {
1701         kcf_provider_desc_t *pd, *real_provider;
1702         kcf_req_params_t params;
1703         crypto_provider_session_t *ps, *new_ps;
1704         crypto_session_id_t provider_session_id = 0;
1705         int rv;
1706 
1707         ASSERT(MUTEX_HELD(&cm->cm_lock));
1708 
1709         /* pd may be a logical provider */
1710         pd = cm->cm_provider_array[provider_index];
1711 
1712 again:
1713         /*
1714          * Check if there is already a session to the provider.
1715          * Sessions may be to a logical provider or a real provider.
1716          */
1717         for (ps = cm->cm_provider_session; ps != NULL; ps = ps->ps_next) {
1718                 if (ps->ps_provider == pd)
1719                         break;
1720         }
1721 
1722         /* found existing session */
1723         if (ps != NULL) {
1724                 ps->ps_refcnt++;
1725                 *output_ps = ps;
1726                 return (CRYPTO_SUCCESS);
1727         }
1728         mutex_exit(&cm->cm_lock);
1729 
1730         /* find a hardware provider that supports session ops */
1731         (void) kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(session_ops),
1732             CRYPTO_SESSION_OFFSET(session_open), pd, &real_provider);
1733 
1734         if (real_provider != NULL) {
1735                 ASSERT(real_provider == pd ||
1736                     pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER);
1737                 /* open session to provider */
1738                 KCF_WRAP_SESSION_OPS_PARAMS(&params, KCF_OP_SESSION_OPEN,
1739                     &provider_session_id, 0, CRYPTO_USER, NULL, 0, pd);
1740                 rv = kcf_submit_request(real_provider, NULL, NULL, &params,
1741                     B_FALSE);
1742                 if (rv != CRYPTO_SUCCESS) {
1743                         mutex_enter(&cm->cm_lock);
1744                         KCF_PROV_REFRELE(real_provider);
1745                         return (rv);
1746                 }
1747         }
1748 
1749         /* allocate crypto_provider_session structure */
1750         new_ps = kmem_zalloc(sizeof (crypto_provider_session_t), KM_SLEEP);
1751 
1752         /*
1753          * Check if someone opened a session to the provider
1754          * while we dropped the lock.
1755          */
1756         mutex_enter(&cm->cm_lock);
1757         for (ps = cm->cm_provider_session; ps != NULL; ps = ps->ps_next) {
1758                 if (ps->ps_provider == pd) {
1759                         mutex_exit(&cm->cm_lock);
1760                         kmem_free(new_ps, sizeof (crypto_provider_session_t));
1761                         if (real_provider != NULL) {
1762                                 KCF_WRAP_SESSION_OPS_PARAMS(&params,
1763                                     KCF_OP_SESSION_CLOSE, NULL,
1764                                     provider_session_id, CRYPTO_USER, NULL, 0,
1765                                     pd);
1766                                 (void) kcf_submit_request(real_provider, NULL,
1767                                     NULL, &params, B_FALSE);
1768                                 KCF_PROV_REFRELE(real_provider);
1769                         }
1770                         mutex_enter(&cm->cm_lock);
1771                         goto again;
1772 
1773                 }
1774         }
1775 
1776         /* increment refcnt and attach to crypto_minor structure */
1777         new_ps->ps_session = provider_session_id;
1778         new_ps->ps_refcnt = 1;
1779         KCF_PROV_REFHOLD(pd);
1780         new_ps->ps_provider = pd;
1781         if (real_provider != NULL) {
1782                 new_ps->ps_real_provider = real_provider;
1783         }
1784         new_ps->ps_next = cm->cm_provider_session;
1785         cm->cm_provider_session = new_ps;
1786 
1787         *output_ps = new_ps;
1788         return (CRYPTO_SUCCESS);
1789 }
1790 
1791 /*
1792  * Release a provider session.
1793  * If the reference count goes to zero, then close the session
1794  * to the provider.
1795  */
1796 static void
1797 crypto_release_provider_session(crypto_minor_t *cm,
1798     crypto_provider_session_t *provider_session)
1799 {
1800         kcf_req_params_t params;
1801         crypto_provider_session_t *ps = NULL, **prev;
1802 
1803         ASSERT(MUTEX_HELD(&cm->cm_lock));
1804 
1805         /* verify that provider_session is valid */
1806         for (ps = cm->cm_provider_session, prev = &cm->cm_provider_session;
1807             ps != NULL; prev = &ps->ps_next, ps = ps->ps_next) {
1808                 if (ps == provider_session) {
1809                         break;
1810                 }
1811         }
1812 
1813         if (ps == NULL)
1814                 return;
1815 
1816         ps->ps_refcnt--;
1817 
1818         if (ps->ps_refcnt > 0)
1819                 return;
1820 
1821         if (ps->ps_real_provider != NULL) {
1822                 /* close session with provider */
1823                 KCF_WRAP_SESSION_OPS_PARAMS(&params, KCF_OP_SESSION_CLOSE, NULL,
1824                     ps->ps_session, CRYPTO_USER, NULL, 0, ps->ps_provider);
1825                 (void) kcf_submit_request(ps->ps_real_provider,
1826                     NULL, NULL, &params, B_FALSE);
1827                 KCF_PROV_REFRELE(ps->ps_real_provider);
1828         }
1829         KCF_PROV_REFRELE(ps->ps_provider);
1830         *prev = ps->ps_next;
1831         kmem_free(ps, sizeof (*ps));
1832 }
1833 
1834 static int
1835 grow_session_table(crypto_minor_t *cm)
1836 {
1837         crypto_session_data_t **session_table;
1838         crypto_session_data_t **new;
1839         uint_t session_table_count;
1840         uint_t need;
1841         size_t current_allocation;
1842         size_t new_allocation;
1843         int rv;
1844 
1845         ASSERT(MUTEX_HELD(&cm->cm_lock));
1846 
1847         session_table_count = cm->cm_session_table_count;
1848         session_table = cm->cm_session_table;
1849         need = session_table_count + CRYPTO_SESSION_CHUNK;
1850 
1851         current_allocation = session_table_count * sizeof (void *);
1852         new_allocation = need * sizeof (void *);
1853 
1854         /*
1855          * Memory needed to grow the session table is checked
1856          * against the project.max-crypto-memory resource control.
1857          */
1858         if ((rv = crypto_buffer_check(new_allocation - current_allocation)) !=
1859             CRYPTO_SUCCESS) {
1860                 return (rv);
1861         }
1862 
1863         /* drop lock while we allocate memory */
1864         mutex_exit(&cm->cm_lock);
1865         new = kmem_zalloc(new_allocation, KM_SLEEP);
1866         mutex_enter(&cm->cm_lock);
1867 
1868         /* check if another thread increased the table size */
1869         if (session_table_count != cm->cm_session_table_count) {
1870                 kmem_free(new, new_allocation);
1871                 return (CRYPTO_SUCCESS);
1872         }
1873 
1874         bcopy(session_table, new, current_allocation);
1875         kmem_free(session_table, current_allocation);
1876         cm->cm_session_table = new;
1877         cm->cm_session_table_count += CRYPTO_SESSION_CHUNK;
1878 
1879         return (CRYPTO_SUCCESS);
1880 }
1881 
1882 /*
1883  * Find unused entry in session table and return it's index.
1884  * Initialize session table entry.
1885  */
1886 /* ARGSUSED */
1887 static int
1888 crypto_open_session(dev_t dev, uint_t flags, crypto_session_id_t *session_index,
1889     crypto_provider_id_t provider_id)
1890 {
1891         crypto_session_data_t **session_table;
1892         crypto_session_data_t *sp;
1893         crypto_minor_t *cm;
1894         uint_t session_table_count;
1895         uint_t i;
1896         int rv;
1897         crypto_provider_session_t *ps;
1898         kcf_provider_desc_t *provider;
1899 
1900         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
1901                 cmn_err(CE_WARN, "crypto_open_session: failed holding minor");
1902                 return (CRYPTO_FAILED);
1903         }
1904 
1905         /* initialize provider_array */
1906         if (cm->cm_provider_array == NULL) {
1907                 rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST);
1908                 if (rv != 0) {
1909                         crypto_release_minor(cm);
1910                         return (rv);
1911                 }
1912         }
1913 
1914         mutex_enter(&cm->cm_lock);
1915         /* index must be less than count of providers */
1916         if (provider_id >= cm->cm_provider_count) {
1917                 mutex_exit(&cm->cm_lock);
1918                 crypto_release_minor(cm);
1919                 return (CRYPTO_INVALID_PROVIDER_ID);
1920         }
1921         ASSERT(cm->cm_provider_array != NULL);
1922 
1923         rv = crypto_get_provider_session(cm, provider_id, &ps);
1924         if (rv != CRYPTO_SUCCESS) {
1925                 mutex_exit(&cm->cm_lock);
1926                 crypto_release_minor(cm);
1927                 return (rv);
1928         }
1929         provider = cm->cm_provider_array[provider_id];
1930 
1931 again:
1932         session_table_count = cm->cm_session_table_count;
1933         session_table = cm->cm_session_table;
1934 
1935         /* session handles start with 1 */
1936         for (i = 1; i < session_table_count; i++) {
1937                 if (session_table[i] == NULL)
1938                         break;
1939         }
1940 
1941         if (i == session_table_count || session_table_count == 0) {
1942                 if ((rv = grow_session_table(cm)) != CRYPTO_SUCCESS) {
1943                         crypto_release_provider_session(cm, ps);
1944                         mutex_exit(&cm->cm_lock);
1945                         crypto_release_minor(cm);
1946                         return (rv);
1947                 }
1948                 goto again;
1949         }
1950 
1951         sp = kmem_cache_alloc(crypto_session_cache, KM_SLEEP);
1952         sp->sd_flags = 0;
1953         sp->sd_find_init_cookie = NULL;
1954         sp->sd_digest_ctx = NULL;
1955         sp->sd_encr_ctx = NULL;
1956         sp->sd_decr_ctx = NULL;
1957         sp->sd_sign_ctx = NULL;
1958         sp->sd_verify_ctx = NULL;
1959         sp->sd_sign_recover_ctx = NULL;
1960         sp->sd_verify_recover_ctx = NULL;
1961         mutex_init(&sp->sd_lock, NULL, MUTEX_DRIVER, NULL);
1962         cv_init(&sp->sd_cv, NULL, CV_DRIVER, NULL);
1963         KCF_PROV_REFHOLD(provider);
1964         sp->sd_provider = provider;
1965         sp->sd_provider_session = ps;
1966 
1967         /* See the comment for CRYPTO_PRE_APPROVED_LIMIT. */
1968         if ((rv = crypto_buffer_check(crypto_pre_approved_limit)) !=
1969             CRYPTO_SUCCESS) {
1970                 sp->sd_pre_approved_amount = 0;
1971         } else {
1972                 sp->sd_pre_approved_amount = (int)crypto_pre_approved_limit;
1973         }
1974 
1975         cm->cm_session_table[i] = sp;
1976         mutex_exit(&cm->cm_lock);
1977         crypto_release_minor(cm);
1978         *session_index = i;
1979 
1980         return (CRYPTO_SUCCESS);
1981 }
1982 
1983 /*
1984  * Close a session.
1985  */
1986 static int
1987 crypto_close_session(dev_t dev, crypto_session_id_t session_index)
1988 {
1989         crypto_session_data_t **session_table;
1990         crypto_session_data_t *sp;
1991         crypto_minor_t *cm;
1992 
1993         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
1994                 cmn_err(CE_WARN, "crypto_close_session: failed holding minor");
1995                 return (CRYPTO_FAILED);
1996         }
1997 
1998         mutex_enter(&cm->cm_lock);
1999         session_table = cm->cm_session_table;
2000 
2001         if ((session_index) == 0 ||
2002             (session_index >= cm->cm_session_table_count)) {
2003                 mutex_exit(&cm->cm_lock);
2004                 crypto_release_minor(cm);
2005                 return (CRYPTO_SESSION_HANDLE_INVALID);
2006         }
2007 
2008         sp = session_table[session_index];
2009         if (sp == NULL) {
2010                 mutex_exit(&cm->cm_lock);
2011                 crypto_release_minor(cm);
2012                 return (CRYPTO_SESSION_HANDLE_INVALID);
2013         }
2014         /*
2015          * If session is in use, free it when the thread
2016          * finishes with the session.
2017          */
2018         mutex_enter(&sp->sd_lock);
2019         if (sp->sd_flags & CRYPTO_SESSION_IS_BUSY) {
2020                 sp->sd_flags |= CRYPTO_SESSION_IS_CLOSED;
2021                 mutex_exit(&sp->sd_lock);
2022         } else {
2023                 ASSERT(sp->sd_pre_approved_amount == 0 ||
2024                     sp->sd_pre_approved_amount == crypto_pre_approved_limit);
2025                 CRYPTO_DECREMENT_RCTL(sp->sd_pre_approved_amount);
2026 
2027                 if (sp->sd_find_init_cookie != NULL) {
2028                         (void) crypto_free_find_ctx(sp);
2029                 }
2030 
2031                 crypto_release_provider_session(cm, sp->sd_provider_session);
2032                 KCF_PROV_REFRELE(sp->sd_provider);
2033                 CRYPTO_CANCEL_ALL_CTX(sp);
2034                 mutex_destroy(&sp->sd_lock);
2035                 cv_destroy(&sp->sd_cv);
2036                 kmem_cache_free(crypto_session_cache, sp);
2037                 session_table[session_index] = NULL;
2038         }
2039 
2040         mutex_exit(&cm->cm_lock);
2041         crypto_release_minor(cm);
2042 
2043         return (CRYPTO_SUCCESS);
2044 }
2045 
2046 /*
2047  * This ioctl opens a session and returns the session ID in os_session.
2048  */
2049 /* ARGSUSED */
2050 static int
2051 open_session(dev_t dev, caddr_t arg, int mode, int *rval)
2052 {
2053         crypto_open_session_t open_session;
2054         crypto_session_id_t session;
2055         int rv;
2056 
2057         if (copyin(arg, &open_session, sizeof (open_session)) != 0)
2058                 return (EFAULT);
2059 
2060         rv = crypto_open_session(dev, open_session.os_flags,
2061             &session, open_session.os_provider_id);
2062         if (rv != CRYPTO_SUCCESS) {
2063                 open_session.os_return_value = rv;
2064                 if (copyout(&open_session, arg, sizeof (open_session)) != 0) {
2065                         return (EFAULT);
2066                 }
2067                 return (0);
2068         }
2069 
2070         open_session.os_session = session;
2071         open_session.os_return_value = CRYPTO_SUCCESS;
2072 
2073         if (copyout(&open_session, arg, sizeof (open_session)) != 0) {
2074                 return (EFAULT);
2075         }
2076         return (0);
2077 }
2078 
2079 /*
2080  * This ioctl closes a session.
2081  */
2082 /* ARGSUSED */
2083 static int
2084 close_session(dev_t dev, caddr_t arg, int mode, int *rval)
2085 {
2086         crypto_close_session_t close_session;
2087         int rv;
2088 
2089         if (copyin(arg, &close_session, sizeof (close_session)) != 0)
2090                 return (EFAULT);
2091 
2092         rv = crypto_close_session(dev, close_session.cs_session);
2093         close_session.cs_return_value = rv;
2094         if (copyout(&close_session, arg, sizeof (close_session)) != 0) {
2095                 return (EFAULT);
2096         }
2097         return (0);
2098 }
2099 
2100 /*
2101  * Copy data model dependent mechanism structure into a kernel mechanism
2102  * structure.  Allocate param storage if necessary.
2103  */
2104 static boolean_t
2105 copyin_mech(int mode, crypto_session_data_t *sp, crypto_mechanism_t *in_mech,
2106     crypto_mechanism_t *out_mech, size_t *out_rctl_bytes,
2107     boolean_t *out_rctl_chk, int *out_rv, int *out_error)
2108 {
2109         STRUCT_DECL(crypto_mechanism, mech);
2110         caddr_t param;
2111         size_t param_len;
2112         size_t rctl_bytes = 0;
2113         int error = 0;
2114         int rv = 0;
2115 
2116         STRUCT_INIT(mech, mode);
2117         bcopy(in_mech, STRUCT_BUF(mech), STRUCT_SIZE(mech));
2118         param = STRUCT_FGETP(mech, cm_param);
2119         param_len = STRUCT_FGET(mech, cm_param_len);
2120         out_mech->cm_type = STRUCT_FGET(mech, cm_type);
2121         out_mech->cm_param = NULL;
2122         out_mech->cm_param_len = 0;
2123         if (param != NULL && param_len != 0) {
2124                 if (param_len > crypto_max_buffer_len) {
2125                         cmn_err(CE_NOTE, "copyin_mech: buffer greater than "
2126                             "%ld bytes, pid = %d", crypto_max_buffer_len,
2127                             curproc->p_pid);
2128                         rv = CRYPTO_ARGUMENTS_BAD;
2129                         goto out;
2130                 }
2131 
2132                 rv = CRYPTO_BUFFER_CHECK(sp, param_len, *out_rctl_chk);
2133                 if (rv != CRYPTO_SUCCESS) {
2134                         goto out;
2135                 }
2136                 rctl_bytes = param_len;
2137 
2138                 out_mech->cm_param = kmem_alloc(param_len, KM_SLEEP);
2139                 if (copyin((char *)param, out_mech->cm_param, param_len) != 0) {
2140                         kmem_free(out_mech->cm_param, param_len);
2141                         out_mech->cm_param = NULL;
2142                         error = EFAULT;
2143                         goto out;
2144                 }
2145                 out_mech->cm_param_len = param_len;
2146         }
2147 out:
2148         *out_rctl_bytes = rctl_bytes;
2149         *out_rv = rv;
2150         *out_error = error;
2151         return ((rv | error) ? B_FALSE : B_TRUE);
2152 }
2153 
2154 /*
2155  * Free key attributes when key type is CRYPTO_KEY_ATTR_LIST.
2156  * The crypto_key structure is not freed.
2157  */
2158 static void
2159 crypto_free_key_attributes(crypto_key_t *key)
2160 {
2161         crypto_object_attribute_t *attrs;
2162         size_t len = 0;
2163         int i;
2164 
2165         ASSERT(key->ck_format == CRYPTO_KEY_ATTR_LIST);
2166         if (key->ck_count == 0 || key->ck_attrs == NULL)
2167                 return;
2168 
2169         /* compute the size of the container */
2170         len = key->ck_count * sizeof (crypto_object_attribute_t);
2171 
2172         /* total up the size of all attributes in the container */
2173         for (i = 0; i < key->ck_count; i++) {
2174                 attrs = &key->ck_attrs[i];
2175                 if (attrs->oa_value_len != 0 &&
2176                     attrs->oa_value != NULL) {
2177                         len += roundup(attrs->oa_value_len, sizeof (caddr_t));
2178                 }
2179         }
2180 
2181         bzero(key->ck_attrs, len);
2182         kmem_free(key->ck_attrs, len);
2183 }
2184 
2185 /*
2186  * Frees allocated storage in the key structure, but doesn't free
2187  * the key structure.
2188  */
2189 static void
2190 free_crypto_key(crypto_key_t *key)
2191 {
2192         switch (key->ck_format) {
2193         case CRYPTO_KEY_RAW: {
2194                 size_t len;
2195 
2196                 if (key->ck_length == 0 || key->ck_data == NULL)
2197                         break;
2198 
2199                 len = CRYPTO_BITS2BYTES(key->ck_length);
2200                 bzero(key->ck_data, len);
2201                 kmem_free(key->ck_data, len);
2202                 break;
2203         }
2204 
2205         case CRYPTO_KEY_ATTR_LIST:
2206                 crypto_free_key_attributes(key);
2207                 break;
2208 
2209         default:
2210                 break;
2211         }
2212 }
2213 
2214 /*
2215  * Copy in an array of crypto_object_attribute structures from user-space.
2216  * Kernel memory is allocated for the array and the value of each attribute
2217  * in the array.  Since unprivileged users can specify the size of attributes,
2218  * the amount of memory needed is charged against the
2219  * project.max-crypto-memory resource control.
2220  *
2221  * Attribute values are copied in from user-space if copyin_value is set to
2222  * B_TRUE.  This routine returns B_TRUE if the copyin was successful.
2223  */
2224 static boolean_t
2225 copyin_attributes(int mode, crypto_session_data_t *sp,
2226     uint_t count, caddr_t oc_attributes,
2227     crypto_object_attribute_t **k_attrs_out, size_t *k_attrs_size_out,
2228     caddr_t *u_attrs_out, int *out_rv, int *out_error, size_t *out_rctl_bytes,
2229     boolean_t *out_rctl_chk, boolean_t copyin_value)
2230 {
2231         STRUCT_DECL(crypto_object_attribute, oa);
2232         crypto_object_attribute_t *k_attrs = NULL;
2233         caddr_t attrs = NULL, ap, p, value;
2234         caddr_t k_attrs_buf;
2235         size_t k_attrs_len;
2236         size_t k_attrs_buf_len = 0;
2237         size_t k_attrs_total_len = 0;
2238         size_t tmp_len;
2239         size_t rctl_bytes = 0;
2240         size_t len = 0;
2241         size_t value_len;
2242         int error = 0;
2243         int rv = 0;
2244         int i;
2245 
2246         STRUCT_INIT(oa, mode);
2247 
2248         if (count == 0) {
2249                 rv = CRYPTO_SUCCESS;
2250                 goto out;
2251         }
2252 
2253         if (count > CRYPTO_MAX_ATTRIBUTE_COUNT) {
2254                 rv = CRYPTO_ARGUMENTS_BAD;
2255                 goto out;
2256         }
2257 
2258         /* compute size of crypto_object_attribute array */
2259         len = count * STRUCT_SIZE(oa);
2260 
2261         /* this allocation is not charged against the user's resource limit */
2262         attrs = kmem_alloc(len, KM_SLEEP);
2263         if (copyin(oc_attributes, attrs, len) != 0) {
2264                 error = EFAULT;
2265                 goto out;
2266         }
2267 
2268         /* figure out how much memory to allocate for all of the attributes */
2269         ap = attrs;
2270         for (i = 0; i < count; i++) {
2271                 bcopy(ap, STRUCT_BUF(oa), STRUCT_SIZE(oa));
2272                 tmp_len = roundup(STRUCT_FGET(oa, oa_value_len),
2273                     sizeof (caddr_t));
2274                 if (tmp_len > crypto_max_buffer_len) {
2275                         cmn_err(CE_NOTE, "copyin_attributes: buffer greater "
2276                             "than %ld bytes, pid = %d", crypto_max_buffer_len,
2277                             curproc->p_pid);
2278                         rv = CRYPTO_ARGUMENTS_BAD;
2279                         goto out;
2280                 }
2281                 if (STRUCT_FGETP(oa, oa_value) != NULL)
2282                         k_attrs_buf_len += tmp_len;
2283                 ap += STRUCT_SIZE(oa);
2284         }
2285 
2286         k_attrs_len = count * sizeof (crypto_object_attribute_t);
2287         k_attrs_total_len = k_attrs_buf_len + k_attrs_len;
2288 
2289         rv = CRYPTO_BUFFER_CHECK(sp, k_attrs_total_len, *out_rctl_chk);
2290         if (rv != CRYPTO_SUCCESS) {
2291                 goto out;
2292         }
2293         rctl_bytes = k_attrs_total_len;
2294 
2295         /* one big allocation for everything */
2296         k_attrs = kmem_alloc(k_attrs_total_len, KM_SLEEP);
2297         k_attrs_buf = (char *)k_attrs + k_attrs_len;
2298 
2299         ap = attrs;
2300         p = k_attrs_buf;
2301         for (i = 0; i < count; i++) {
2302                 bcopy(ap, STRUCT_BUF(oa), STRUCT_SIZE(oa));
2303                 k_attrs[i].oa_type = STRUCT_FGET(oa, oa_type);
2304                 value = STRUCT_FGETP(oa, oa_value);
2305                 value_len = STRUCT_FGET(oa, oa_value_len);
2306                 if (value != NULL && value_len != 0 && copyin_value) {
2307                         if (copyin(value, p, value_len) != 0) {
2308                                 kmem_free(k_attrs, k_attrs_total_len);
2309                                 k_attrs = NULL;
2310                                 error = EFAULT;
2311                                 goto out;
2312                         }
2313                 }
2314 
2315                 if (value != NULL) {
2316                         k_attrs[i].oa_value = p;
2317                         p += roundup(value_len, sizeof (caddr_t));
2318                 } else {
2319                         k_attrs[i].oa_value = NULL;
2320                 }
2321                 k_attrs[i].oa_value_len = value_len;
2322                 ap += STRUCT_SIZE(oa);
2323         }
2324 out:
2325         if (attrs != NULL) {
2326                 /*
2327                  * Free the array if there is a failure or the caller
2328                  * doesn't want the array to be returned.
2329                  */
2330                 if (error != 0 || rv != CRYPTO_SUCCESS || u_attrs_out == NULL) {
2331                         kmem_free(attrs, len);
2332                         attrs = NULL;
2333                 }
2334         }
2335 
2336         if (u_attrs_out != NULL)
2337                 *u_attrs_out = attrs;
2338         if (k_attrs_size_out != NULL)
2339                 *k_attrs_size_out = k_attrs_total_len;
2340         *k_attrs_out = k_attrs;
2341         *out_rctl_bytes = rctl_bytes;
2342         *out_rv = rv;
2343         *out_error = error;
2344         return ((rv | error) ? B_FALSE : B_TRUE);
2345 }
2346 
2347 /*
2348  * Copy data model dependent raw key into a kernel key
2349  * structure.  Checks key length or attribute lengths against
2350  * resource controls before allocating memory.  Returns B_TRUE
2351  * if both error and rv are set to 0.
2352  */
2353 static boolean_t
2354 copyin_key(int mode, crypto_session_data_t *sp, crypto_key_t *in_key,
2355     crypto_key_t *out_key, size_t *out_rctl_bytes,
2356     boolean_t *out_rctl_chk, int *out_rv, int *out_error)
2357 {
2358         STRUCT_DECL(crypto_key, key);
2359         crypto_object_attribute_t *k_attrs = NULL;
2360         size_t key_bits;
2361         size_t key_bytes = 0;
2362         size_t rctl_bytes = 0;
2363         int count;
2364         int error = 0;
2365         int rv = CRYPTO_SUCCESS;
2366 
2367         STRUCT_INIT(key, mode);
2368         bcopy(in_key, STRUCT_BUF(key), STRUCT_SIZE(key));
2369         out_key->ck_format = STRUCT_FGET(key, ck_format);
2370         switch (out_key->ck_format) {
2371         case CRYPTO_KEY_RAW:
2372                 key_bits = STRUCT_FGET(key, ck_length);
2373                 if (key_bits != 0) {
2374                         if (key_bits >
2375                             (CRYPTO_BYTES2BITS(crypto_max_buffer_len))) {
2376                                 cmn_err(CE_NOTE, "copyin_key: buffer greater "
2377                                     "than %ld bytes, pid = %d",
2378                                     crypto_max_buffer_len, curproc->p_pid);
2379                                 rv = CRYPTO_ARGUMENTS_BAD;
2380                                 goto out;
2381                         }
2382                         key_bytes = CRYPTO_BITS2BYTES(key_bits);
2383 
2384                         rv = CRYPTO_BUFFER_CHECK(sp, key_bytes,
2385                             *out_rctl_chk);
2386                         if (rv != CRYPTO_SUCCESS) {
2387                                 goto out;
2388                         }
2389                         rctl_bytes = key_bytes;
2390 
2391                         out_key->ck_data = kmem_alloc(key_bytes, KM_SLEEP);
2392 
2393                         if (copyin((char *)STRUCT_FGETP(key, ck_data),
2394                             out_key->ck_data, key_bytes) != 0) {
2395                                 kmem_free(out_key->ck_data, key_bytes);
2396                                 out_key->ck_data = NULL;
2397                                 out_key->ck_length = 0;
2398                                 error = EFAULT;
2399                                 goto out;
2400                         }
2401                 }
2402                 out_key->ck_length = (ulong_t)key_bits;
2403                 break;
2404 
2405         case CRYPTO_KEY_ATTR_LIST:
2406                 count = STRUCT_FGET(key, ck_count);
2407 
2408                 if (copyin_attributes(mode, sp, count,
2409                     (caddr_t)STRUCT_FGETP(key, ck_attrs), &k_attrs, NULL, NULL,
2410                     &rv, &error, &rctl_bytes, out_rctl_chk, B_TRUE)) {
2411                         out_key->ck_count = count;
2412                         out_key->ck_attrs = k_attrs;
2413                         k_attrs = NULL;
2414                 } else {
2415                         out_key->ck_count = 0;
2416                         out_key->ck_attrs = NULL;
2417                 }
2418                 break;
2419 
2420         case CRYPTO_KEY_REFERENCE:
2421                 out_key->ck_obj_id = STRUCT_FGET(key, ck_obj_id);
2422                 break;
2423 
2424         default:
2425                 rv = CRYPTO_ARGUMENTS_BAD;
2426         }
2427 
2428 out:
2429         *out_rctl_bytes = rctl_bytes;
2430         *out_rv = rv;
2431         *out_error = error;
2432         return ((rv | error) ? B_FALSE : B_TRUE);
2433 }
2434 
2435 /*
2436  * This routine does two things:
2437  * 1. Given a crypto_minor structure and a session ID, it returns
2438  *    a valid session pointer.
2439  * 2. It checks that the provider, to which the session has been opened,
2440  *    has not been removed.
2441  */
2442 static boolean_t
2443 get_session_ptr(crypto_session_id_t i, crypto_minor_t *cm,
2444     crypto_session_data_t **session_ptr, int *out_error, int *out_rv)
2445 {
2446         crypto_session_data_t *sp = NULL;
2447         int rv = CRYPTO_SESSION_HANDLE_INVALID;
2448         int error = 0;
2449 
2450         mutex_enter(&cm->cm_lock);
2451         if ((i < cm->cm_session_table_count) &&
2452             (cm->cm_session_table[i] != NULL)) {
2453                 sp = cm->cm_session_table[i];
2454                 mutex_enter(&sp->sd_lock);
2455                 mutex_exit(&cm->cm_lock);
2456                 while (sp->sd_flags & CRYPTO_SESSION_IS_BUSY) {
2457                         if (cv_wait_sig(&sp->sd_cv, &sp->sd_lock) == 0) {
2458                                 mutex_exit(&sp->sd_lock);
2459                                 sp = NULL;
2460                                 error = EINTR;
2461                                 goto out;
2462                         }
2463                 }
2464 
2465                 if (sp->sd_flags & CRYPTO_SESSION_IS_CLOSED) {
2466                         mutex_exit(&sp->sd_lock);
2467                         sp = NULL;
2468                         goto out;
2469                 }
2470 
2471                 if (KCF_IS_PROV_REMOVED(sp->sd_provider)) {
2472                         mutex_exit(&sp->sd_lock);
2473                         sp = NULL;
2474                         rv = CRYPTO_DEVICE_ERROR;
2475                         goto out;
2476                 }
2477 
2478                 rv = CRYPTO_SUCCESS;
2479                 sp->sd_flags |= CRYPTO_SESSION_IS_BUSY;
2480                 mutex_exit(&sp->sd_lock);
2481         } else {
2482                 mutex_exit(&cm->cm_lock);
2483         }
2484 out:
2485         *session_ptr = sp;
2486         *out_error = error;
2487         *out_rv = rv;
2488         return ((rv == CRYPTO_SUCCESS && error == 0) ? B_TRUE : B_FALSE);
2489 }
2490 
2491 #define CRYPTO_SESSION_RELE(s)  if ((s) != NULL) {      \
2492         mutex_enter(&((s)->sd_lock));                    \
2493         (s)->sd_flags &= ~CRYPTO_SESSION_IS_BUSY;        \
2494         cv_broadcast(&(s)->sd_cv);                       \
2495         mutex_exit(&((s)->sd_lock));                     \
2496 }
2497 
2498 /* ARGSUSED */
2499 static int
2500 encrypt_init(dev_t dev, caddr_t arg, int mode, int *rval)
2501 {
2502         return (cipher_init(dev, arg, mode, crypto_encrypt_init_prov));
2503 }
2504 
2505 /* ARGSUSED */
2506 static int
2507 decrypt_init(dev_t dev, caddr_t arg, int mode, int *rval)
2508 {
2509         return (cipher_init(dev, arg, mode, crypto_decrypt_init_prov));
2510 }
2511 
2512 /*
2513  * umech is a mechanism structure that has been copied from user address
2514  * space into kernel address space. Only one copyin has been done.
2515  * The mechanism parameter, if non-null, still points to user address space.
2516  * If the mechanism parameter contains pointers, they are pointers into
2517  * user address space.
2518  *
2519  * kmech is a umech with all pointers and structures in kernel address space.
2520  *
2521  * This routine calls the provider's entry point to copy a umech parameter
2522  * into kernel address space. Kernel memory is allocated by the provider.
2523  */
2524 static int
2525 crypto_provider_copyin_mech_param(kcf_provider_desc_t *pd,
2526     crypto_mechanism_t *umech, crypto_mechanism_t *kmech, int mode, int *error)
2527 {
2528         crypto_mech_type_t provider_mech_type;
2529         int rv;
2530 
2531         /* get the provider's mech number */
2532         provider_mech_type = KCF_TO_PROV_MECHNUM(pd, umech->cm_type);
2533 
2534         kmech->cm_param = NULL;
2535         kmech->cm_param_len = 0;
2536         kmech->cm_type = provider_mech_type;
2537         rv = KCF_PROV_COPYIN_MECH(pd, umech, kmech, error, mode);
2538         kmech->cm_type = umech->cm_type;
2539 
2540         return (rv);
2541 }
2542 
2543 /*
2544  * umech is a mechanism structure that has been copied from user address
2545  * space into kernel address space. Only one copyin has been done.
2546  * The mechanism parameter, if non-null, still points to user address space.
2547  * If the mechanism parameter contains pointers, they are pointers into
2548  * user address space.
2549  *
2550  * kmech is a umech with all pointers and structures in kernel address space.
2551  *
2552  * This routine calls the provider's entry point to copy a kmech parameter
2553  * into user address space using umech as a template containing
2554  * user address pointers.
2555  */
2556 static int
2557 crypto_provider_copyout_mech_param(kcf_provider_desc_t *pd,
2558     crypto_mechanism_t *kmech, crypto_mechanism_t *umech, int mode, int *error)
2559 {
2560         crypto_mech_type_t provider_mech_type;
2561         int rv;
2562 
2563         /* get the provider's mech number */
2564         provider_mech_type = KCF_TO_PROV_MECHNUM(pd, umech->cm_type);
2565 
2566         kmech->cm_type = provider_mech_type;
2567         rv = KCF_PROV_COPYOUT_MECH(pd, kmech, umech, error, mode);
2568         kmech->cm_type = umech->cm_type;
2569 
2570         return (rv);
2571 }
2572 
2573 /*
2574  * Call the provider's entry point to free kernel memory that has been
2575  * allocated for the mechanism's parameter.
2576  */
2577 static void
2578 crypto_free_mech(kcf_provider_desc_t *pd, boolean_t allocated_by_crypto_module,
2579     crypto_mechanism_t *mech)
2580 {
2581         crypto_mech_type_t provider_mech_type;
2582 
2583         if (allocated_by_crypto_module) {
2584                 if (mech->cm_param != NULL)
2585                         kmem_free(mech->cm_param, mech->cm_param_len);
2586         } else {
2587                 /* get the provider's mech number */
2588                 provider_mech_type = KCF_TO_PROV_MECHNUM(pd, mech->cm_type);
2589 
2590                 if (mech->cm_param != NULL && mech->cm_param_len != 0) {
2591                         mech->cm_type = provider_mech_type;
2592                         (void) KCF_PROV_FREE_MECH(pd, mech);
2593                 }
2594         }
2595 }
2596 
2597 /*
2598  * ASSUMPTION: crypto_encrypt_init and crypto_decrypt_init
2599  * structures are identical except for field names.
2600  */
2601 static int
2602 cipher_init(dev_t dev, caddr_t arg, int mode, int (*init)(crypto_provider_t,
2603     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
2604     crypto_ctx_template_t, crypto_context_t *, crypto_call_req_t *))
2605 {
2606         STRUCT_DECL(crypto_encrypt_init, encrypt_init);
2607         kcf_provider_desc_t *real_provider = NULL;
2608         crypto_session_id_t session_id;
2609         crypto_mechanism_t mech;
2610         crypto_key_t key;
2611         crypto_minor_t *cm;
2612         crypto_session_data_t *sp = NULL;
2613         crypto_context_t cc;
2614         crypto_ctx_t **ctxpp;
2615         size_t mech_rctl_bytes = 0;
2616         boolean_t mech_rctl_chk = B_FALSE;
2617         size_t key_rctl_bytes = 0;
2618         boolean_t key_rctl_chk = B_FALSE;
2619         int error = 0;
2620         int rv;
2621         boolean_t allocated_by_crypto_module = B_FALSE;
2622         crypto_func_group_t fg;
2623 
2624         STRUCT_INIT(encrypt_init, mode);
2625 
2626         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
2627                 cmn_err(CE_WARN, "cipher_init: failed holding minor");
2628                 return (ENXIO);
2629         }
2630 
2631         if (copyin(arg, STRUCT_BUF(encrypt_init),
2632             STRUCT_SIZE(encrypt_init)) != 0) {
2633                 crypto_release_minor(cm);
2634                 return (EFAULT);
2635         }
2636 
2637         mech.cm_param = NULL;
2638         bzero(&key, sizeof (crypto_key_t));
2639 
2640         session_id = STRUCT_FGET(encrypt_init, ei_session);
2641 
2642         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
2643                 goto out;
2644         }
2645 
2646         bcopy(STRUCT_FADDR(encrypt_init, ei_mech), &mech.cm_type,
2647             sizeof (crypto_mech_type_t));
2648 
2649         if (init == crypto_encrypt_init_prov) {
2650                 fg = CRYPTO_FG_ENCRYPT;
2651         } else {
2652                 fg = CRYPTO_FG_DECRYPT;
2653         }
2654 
2655         /* We need the key length for provider selection so copy it in now. */
2656         if (!copyin_key(mode, sp, STRUCT_FADDR(encrypt_init, ei_key), &key,
2657             &key_rctl_bytes, &key_rctl_chk, &rv, &error)) {
2658                 goto out;
2659         }
2660 
2661         if ((rv = kcf_get_hardware_provider(mech.cm_type, &key,
2662             CRYPTO_MECH_INVALID, NULL, sp->sd_provider, &real_provider, fg))
2663             != CRYPTO_SUCCESS) {
2664                 goto out;
2665         }
2666 
2667         rv = crypto_provider_copyin_mech_param(real_provider,
2668             STRUCT_FADDR(encrypt_init, ei_mech), &mech, mode, &error);
2669 
2670         if (rv == CRYPTO_NOT_SUPPORTED) {
2671                 allocated_by_crypto_module = B_TRUE;
2672                 if (!copyin_mech(mode, sp, STRUCT_FADDR(encrypt_init, ei_mech),
2673                     &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) {
2674                         goto out;
2675                 }
2676         } else {
2677                 if (rv != CRYPTO_SUCCESS)
2678                         goto out;
2679         }
2680 
2681         rv = (init)(real_provider, sp->sd_provider_session->ps_session,
2682             &mech, &key, NULL, &cc, NULL);
2683 
2684         /*
2685          * Check if a context already exists. If so, it means it is being
2686          * abandoned. So, cancel it to avoid leaking it.
2687          */
2688         ctxpp = (init == crypto_encrypt_init_prov) ?
2689             &sp->sd_encr_ctx : &sp->sd_decr_ctx;
2690 
2691         if (*ctxpp != NULL)
2692                 CRYPTO_CANCEL_CTX(ctxpp);
2693         *ctxpp = (rv == CRYPTO_SUCCESS) ? cc : NULL;
2694 
2695 out:
2696         CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
2697         CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk);
2698         CRYPTO_SESSION_RELE(sp);
2699         crypto_release_minor(cm);
2700 
2701         if (real_provider != NULL) {
2702                 crypto_free_mech(real_provider,
2703                     allocated_by_crypto_module, &mech);
2704                 KCF_PROV_REFRELE(real_provider);
2705         }
2706 
2707         free_crypto_key(&key);
2708 
2709         if (error != 0)
2710                 /* XXX free context */
2711                 return (error);
2712 
2713         STRUCT_FSET(encrypt_init, ei_return_value, rv);
2714         if (copyout(STRUCT_BUF(encrypt_init), arg,
2715             STRUCT_SIZE(encrypt_init)) != 0) {
2716                 /* XXX free context */
2717                 return (EFAULT);
2718         }
2719         return (0);
2720 }
2721 
2722 /* ARGSUSED */
2723 static int
2724 encrypt(dev_t dev, caddr_t arg, int mode, int *rval)
2725 {
2726         return (cipher(dev, arg, mode, crypto_encrypt_single));
2727 }
2728 
2729 /* ARGSUSED */
2730 static int
2731 decrypt(dev_t dev, caddr_t arg, int mode, int *rval)
2732 {
2733         return (cipher(dev, arg, mode, crypto_decrypt_single));
2734 }
2735 
2736 /*
2737  * ASSUMPTION: crypto_encrypt and crypto_decrypt structures
2738  * are identical except for field names.
2739  */
2740 static int
2741 cipher(dev_t dev, caddr_t arg, int mode,
2742     int (*single)(crypto_context_t, crypto_data_t *, crypto_data_t *,
2743     crypto_call_req_t *))
2744 {
2745         STRUCT_DECL(crypto_encrypt, encrypt);
2746         crypto_session_id_t session_id;
2747         crypto_minor_t *cm;
2748         crypto_session_data_t *sp = NULL;
2749         crypto_ctx_t **ctxpp;
2750         crypto_data_t data, encr;
2751         size_t datalen, encrlen, need = 0;
2752         boolean_t do_inplace;
2753         char *encrbuf;
2754         int error = 0;
2755         int rv;
2756         boolean_t rctl_chk = B_FALSE;
2757 
2758         STRUCT_INIT(encrypt, mode);
2759 
2760         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
2761                 cmn_err(CE_WARN, "cipher: failed holding minor");
2762                 return (ENXIO);
2763         }
2764 
2765         if (copyin(arg, STRUCT_BUF(encrypt), STRUCT_SIZE(encrypt)) != 0) {
2766                 crypto_release_minor(cm);
2767                 return (EFAULT);
2768         }
2769 
2770         data.cd_raw.iov_base = NULL;
2771         encr.cd_raw.iov_base = NULL;
2772 
2773         datalen = STRUCT_FGET(encrypt, ce_datalen);
2774         encrlen = STRUCT_FGET(encrypt, ce_encrlen);
2775 
2776         /*
2777          * Don't allocate output buffer unless both buffer pointer and
2778          * buffer length are not NULL or 0 (length).
2779          */
2780         encrbuf = STRUCT_FGETP(encrypt, ce_encrbuf);
2781         if (encrbuf == NULL || encrlen == 0) {
2782                 encrlen = 0;
2783         }
2784 
2785         if (datalen > crypto_max_buffer_len ||
2786             encrlen > crypto_max_buffer_len) {
2787                 cmn_err(CE_NOTE, "cipher: buffer greater than %ld bytes, "
2788                     "pid = %d", crypto_max_buffer_len, curproc->p_pid);
2789                 rv = CRYPTO_ARGUMENTS_BAD;
2790                 goto release_minor;
2791         }
2792 
2793         session_id = STRUCT_FGET(encrypt, ce_session);
2794 
2795         if (!get_session_ptr(session_id, cm, &sp, &error, &rv))  {
2796                 goto release_minor;
2797         }
2798 
2799         do_inplace = (STRUCT_FGET(encrypt, ce_flags) &
2800             CRYPTO_INPLACE_OPERATION) != 0;
2801         need = do_inplace ? datalen : datalen + encrlen;
2802 
2803         if ((rv = CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)) !=
2804             CRYPTO_SUCCESS) {
2805                 need = 0;
2806                 goto release_minor;
2807         }
2808 
2809         INIT_RAW_CRYPTO_DATA(data, datalen);
2810         data.cd_miscdata = NULL;
2811 
2812         if (datalen != 0 && copyin(STRUCT_FGETP(encrypt, ce_databuf),
2813             data.cd_raw.iov_base, datalen) != 0) {
2814                 error = EFAULT;
2815                 goto release_minor;
2816         }
2817 
2818         if (do_inplace) {
2819                 /* set out = in for in-place */
2820                 encr = data;
2821         } else {
2822                 INIT_RAW_CRYPTO_DATA(encr, encrlen);
2823         }
2824 
2825         ctxpp = (single == crypto_encrypt_single) ?
2826             &sp->sd_encr_ctx : &sp->sd_decr_ctx;
2827 
2828         if (do_inplace)
2829                 /* specify in-place buffers with output = NULL */
2830                 rv = (single)(*ctxpp, &encr, NULL, NULL);
2831         else
2832                 rv = (single)(*ctxpp, &data, &encr, NULL);
2833 
2834         if (KCF_CONTEXT_DONE(rv))
2835                 *ctxpp = NULL;
2836 
2837         if (rv == CRYPTO_SUCCESS) {
2838                 ASSERT(encr.cd_length <= encrlen);
2839                 if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base,
2840                     encrbuf, encr.cd_length) != 0) {
2841                         error = EFAULT;
2842                         goto release_minor;
2843                 }
2844                 STRUCT_FSET(encrypt, ce_encrlen,
2845                     (ulong_t)encr.cd_length);
2846         }
2847 
2848         if (rv == CRYPTO_BUFFER_TOO_SMALL) {
2849                 /*
2850                  * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
2851                  * of section 11.2 of the pkcs11 spec. We catch it here and
2852                  * provide the correct pkcs11 return value.
2853                  */
2854                 if (STRUCT_FGETP(encrypt, ce_encrbuf) == NULL)
2855                         rv = CRYPTO_SUCCESS;
2856                 STRUCT_FSET(encrypt, ce_encrlen,
2857                     (ulong_t)encr.cd_length);
2858         }
2859 
2860 release_minor:
2861         CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
2862         CRYPTO_SESSION_RELE(sp);
2863         crypto_release_minor(cm);
2864 
2865         if (data.cd_raw.iov_base != NULL)
2866                 kmem_free(data.cd_raw.iov_base, datalen);
2867 
2868         if (!do_inplace && encr.cd_raw.iov_base != NULL)
2869                 kmem_free(encr.cd_raw.iov_base, encrlen);
2870 
2871         if (error != 0)
2872                 return (error);
2873 
2874         STRUCT_FSET(encrypt, ce_return_value, rv);
2875         if (copyout(STRUCT_BUF(encrypt), arg, STRUCT_SIZE(encrypt)) != 0) {
2876                 return (EFAULT);
2877         }
2878         return (0);
2879 }
2880 
2881 /* ARGSUSED */
2882 static int
2883 encrypt_update(dev_t dev, caddr_t arg, int mode, int *rval)
2884 {
2885         return (cipher_update(dev, arg, mode, crypto_encrypt_update));
2886 }
2887 
2888 /* ARGSUSED */
2889 static int
2890 decrypt_update(dev_t dev, caddr_t arg, int mode, int *rval)
2891 {
2892         return (cipher_update(dev, arg, mode, crypto_decrypt_update));
2893 }
2894 
2895 /*
2896  * ASSUMPTION: crypto_encrypt_update and crypto_decrypt_update
2897  * structures are identical except for field names.
2898  */
2899 static int
2900 cipher_update(dev_t dev, caddr_t arg, int mode,
2901     int (*update)(crypto_context_t, crypto_data_t *, crypto_data_t *,
2902     crypto_call_req_t *))
2903 {
2904         STRUCT_DECL(crypto_encrypt_update, encrypt_update);
2905         crypto_session_id_t session_id;
2906         crypto_minor_t *cm;
2907         crypto_session_data_t *sp = NULL;
2908         crypto_ctx_t **ctxpp;
2909         crypto_data_t data, encr;
2910         size_t datalen, encrlen, need = 0;
2911         boolean_t do_inplace;
2912         char *encrbuf;
2913         int error = 0;
2914         int rv;
2915         boolean_t rctl_chk = B_FALSE;
2916 
2917         STRUCT_INIT(encrypt_update, mode);
2918 
2919         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
2920                 cmn_err(CE_WARN, "cipher_update: failed holding minor");
2921                 return (ENXIO);
2922         }
2923 
2924         if (copyin(arg, STRUCT_BUF(encrypt_update),
2925             STRUCT_SIZE(encrypt_update)) != 0) {
2926                 crypto_release_minor(cm);
2927                 return (EFAULT);
2928         }
2929 
2930         data.cd_raw.iov_base = NULL;
2931         encr.cd_raw.iov_base = NULL;
2932 
2933         datalen = STRUCT_FGET(encrypt_update, eu_datalen);
2934         encrlen = STRUCT_FGET(encrypt_update, eu_encrlen);
2935 
2936         /*
2937          * Don't allocate output buffer unless both buffer pointer and
2938          * buffer length are not NULL or 0 (length).
2939          */
2940         encrbuf = STRUCT_FGETP(encrypt_update, eu_encrbuf);
2941         if (encrbuf == NULL || encrlen == 0) {
2942                 encrlen = 0;
2943         }
2944 
2945         if (datalen > crypto_max_buffer_len ||
2946             encrlen > crypto_max_buffer_len) {
2947                 cmn_err(CE_NOTE, "cipher_update: buffer greater than %ld "
2948                     "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
2949                 rv = CRYPTO_ARGUMENTS_BAD;
2950                 goto out;
2951         }
2952 
2953         session_id = STRUCT_FGET(encrypt_update, eu_session);
2954 
2955         if (!get_session_ptr(session_id, cm, &sp, &error, &rv))  {
2956                 goto out;
2957         }
2958 
2959         do_inplace = (STRUCT_FGET(encrypt_update, eu_flags) &
2960             CRYPTO_INPLACE_OPERATION) != 0;
2961         need = do_inplace ? datalen : datalen + encrlen;
2962 
2963         if ((rv = CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)) !=
2964             CRYPTO_SUCCESS) {
2965                 need = 0;
2966                 goto out;
2967         }
2968 
2969         INIT_RAW_CRYPTO_DATA(data, datalen);
2970         data.cd_miscdata = NULL;
2971 
2972         if (datalen != 0 && copyin(STRUCT_FGETP(encrypt_update, eu_databuf),
2973             data.cd_raw.iov_base, datalen) != 0) {
2974                 error = EFAULT;
2975                 goto out;
2976         }
2977 
2978         if (do_inplace) {
2979                 /* specify in-place buffers with output = input */
2980                 encr = data;
2981         } else {
2982                 INIT_RAW_CRYPTO_DATA(encr, encrlen);
2983         }
2984 
2985         ctxpp = (update == crypto_encrypt_update) ?
2986             &sp->sd_encr_ctx : &sp->sd_decr_ctx;
2987 
2988         if (do_inplace)
2989                 /* specify in-place buffers with output = NULL */
2990                 rv = (update)(*ctxpp, &encr, NULL, NULL);
2991         else
2992                 rv = (update)(*ctxpp, &data, &encr, NULL);
2993 
2994         if (rv == CRYPTO_SUCCESS || rv == CRYPTO_BUFFER_TOO_SMALL) {
2995                 if (rv == CRYPTO_SUCCESS) {
2996                         ASSERT(encr.cd_length <= encrlen);
2997                         if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base,
2998                             encrbuf, encr.cd_length) != 0) {
2999                                 error = EFAULT;
3000                                 goto out;
3001                         }
3002                 } else {
3003                         /*
3004                          * The providers return CRYPTO_BUFFER_TOO_SMALL even
3005                          * for case 1 of section 11.2 of the pkcs11 spec.
3006                          * We catch it here and provide the correct pkcs11
3007                          * return value.
3008                          */
3009                         if (STRUCT_FGETP(encrypt_update, eu_encrbuf) == NULL)
3010                                 rv = CRYPTO_SUCCESS;
3011                 }
3012                 STRUCT_FSET(encrypt_update, eu_encrlen,
3013                     (ulong_t)encr.cd_length);
3014         } else {
3015                 CRYPTO_CANCEL_CTX(ctxpp);
3016         }
3017 out:
3018         CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
3019         CRYPTO_SESSION_RELE(sp);
3020         crypto_release_minor(cm);
3021 
3022         if (data.cd_raw.iov_base != NULL)
3023                 kmem_free(data.cd_raw.iov_base, datalen);
3024 
3025         if (!do_inplace && (encr.cd_raw.iov_base != NULL))
3026                 kmem_free(encr.cd_raw.iov_base, encrlen);
3027 
3028         if (error != 0)
3029                 return (error);
3030 
3031         STRUCT_FSET(encrypt_update, eu_return_value, rv);
3032         if (copyout(STRUCT_BUF(encrypt_update), arg,
3033             STRUCT_SIZE(encrypt_update)) != 0) {
3034                 return (EFAULT);
3035         }
3036         return (0);
3037 }
3038 
3039 /* ARGSUSED */
3040 static int
3041 encrypt_final(dev_t dev, caddr_t arg, int mode, int *rval)
3042 {
3043         return (common_final(dev, arg, mode, crypto_encrypt_final));
3044 }
3045 
3046 /* ARGSUSED */
3047 static int
3048 decrypt_final(dev_t dev, caddr_t arg, int mode, int *rval)
3049 {
3050         return (common_final(dev, arg, mode, crypto_decrypt_final));
3051 }
3052 
3053 /*
3054  * ASSUMPTION: crypto_encrypt_final, crypto_decrypt_final, crypto_sign_final,
3055  * and crypto_digest_final structures are identical except for field names.
3056  */
3057 static int
3058 common_final(dev_t dev, caddr_t arg, int mode,
3059     int (*final)(crypto_context_t, crypto_data_t *, crypto_call_req_t *))
3060 {
3061         STRUCT_DECL(crypto_encrypt_final, encrypt_final);
3062         crypto_session_id_t session_id;
3063         crypto_minor_t *cm;
3064         crypto_session_data_t *sp = NULL;
3065         crypto_ctx_t **ctxpp;
3066         crypto_data_t encr;
3067         size_t encrlen, need = 0;
3068         char *encrbuf;
3069         int error = 0;
3070         int rv;
3071         boolean_t rctl_chk = B_FALSE;
3072 
3073         STRUCT_INIT(encrypt_final, mode);
3074 
3075         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3076                 cmn_err(CE_WARN, "common_final: failed holding minor");
3077                 return (ENXIO);
3078         }
3079 
3080         if (copyin(arg, STRUCT_BUF(encrypt_final),
3081             STRUCT_SIZE(encrypt_final)) != 0) {
3082                 crypto_release_minor(cm);
3083                 return (EFAULT);
3084         }
3085 
3086         encr.cd_format = CRYPTO_DATA_RAW;
3087         encr.cd_raw.iov_base = NULL;
3088 
3089         encrlen = STRUCT_FGET(encrypt_final, ef_encrlen);
3090 
3091         /*
3092          * Don't allocate output buffer unless both buffer pointer and
3093          * buffer length are not NULL or 0 (length).
3094          */
3095         encrbuf = STRUCT_FGETP(encrypt_final, ef_encrbuf);
3096         if (encrbuf == NULL || encrlen == 0) {
3097                 encrlen = 0;
3098         }
3099 
3100         if (encrlen > crypto_max_buffer_len) {
3101                 cmn_err(CE_NOTE, "common_final: buffer greater than %ld "
3102                     "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
3103                 rv = CRYPTO_ARGUMENTS_BAD;
3104                 goto release_minor;
3105         }
3106 
3107         session_id = STRUCT_FGET(encrypt_final, ef_session);
3108 
3109         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
3110                 goto release_minor;
3111         }
3112 
3113         if ((rv = CRYPTO_BUFFER_CHECK(sp, encrlen, rctl_chk)) !=
3114             CRYPTO_SUCCESS) {
3115                 goto release_minor;
3116         }
3117         need = encrlen;
3118         encr.cd_raw.iov_base = kmem_alloc(encrlen, KM_SLEEP);
3119         encr.cd_raw.iov_len = encrlen;
3120 
3121         encr.cd_offset = 0;
3122         encr.cd_length = encrlen;
3123 
3124         ASSERT(final == crypto_encrypt_final ||
3125             final == crypto_decrypt_final || final == crypto_sign_final ||
3126             final == crypto_digest_final);
3127 
3128         if (final == crypto_encrypt_final) {
3129                 ctxpp = &sp->sd_encr_ctx;
3130         } else if (final == crypto_decrypt_final) {
3131                 ctxpp = &sp->sd_decr_ctx;
3132         } else if (final == crypto_sign_final) {
3133                 ctxpp = &sp->sd_sign_ctx;
3134         } else {
3135                 ctxpp = &sp->sd_digest_ctx;
3136         }
3137 
3138         rv = (final)(*ctxpp, &encr, NULL);
3139         if (KCF_CONTEXT_DONE(rv))
3140                 *ctxpp = NULL;
3141 
3142         if (rv == CRYPTO_SUCCESS) {
3143                 ASSERT(encr.cd_length <= encrlen);
3144                 if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base,
3145                     encrbuf, encr.cd_length) != 0) {
3146                         error = EFAULT;
3147                         goto release_minor;
3148                 }
3149                 STRUCT_FSET(encrypt_final, ef_encrlen,
3150                     (ulong_t)encr.cd_length);
3151         }
3152 
3153         if (rv == CRYPTO_BUFFER_TOO_SMALL) {
3154                 /*
3155                  * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
3156                  * of section 11.2 of the pkcs11 spec. We catch it here and
3157                  * provide the correct pkcs11 return value.
3158                  */
3159                 if (STRUCT_FGETP(encrypt_final, ef_encrbuf) == NULL)
3160                         rv = CRYPTO_SUCCESS;
3161                 STRUCT_FSET(encrypt_final, ef_encrlen,
3162                     (ulong_t)encr.cd_length);
3163         }
3164 
3165 release_minor:
3166         CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
3167         CRYPTO_SESSION_RELE(sp);
3168         crypto_release_minor(cm);
3169 
3170         if (encr.cd_raw.iov_base != NULL)
3171                 kmem_free(encr.cd_raw.iov_base, encrlen);
3172 
3173         if (error != 0)
3174                 return (error);
3175 
3176         STRUCT_FSET(encrypt_final, ef_return_value, rv);
3177         if (copyout(STRUCT_BUF(encrypt_final), arg,
3178             STRUCT_SIZE(encrypt_final)) != 0) {
3179                 return (EFAULT);
3180         }
3181         return (0);
3182 }
3183 
3184 /* ARGSUSED */
3185 static int
3186 digest_init(dev_t dev, caddr_t arg, int mode, int *rval)
3187 {
3188         STRUCT_DECL(crypto_digest_init, digest_init);
3189         kcf_provider_desc_t *real_provider = NULL;
3190         crypto_session_id_t session_id;
3191         crypto_mechanism_t mech;
3192         crypto_minor_t *cm;
3193         crypto_session_data_t *sp = NULL;
3194         crypto_context_t cc;
3195         size_t rctl_bytes = 0;
3196         boolean_t rctl_chk = B_FALSE;
3197         int error = 0;
3198         int rv;
3199 
3200         STRUCT_INIT(digest_init, mode);
3201 
3202         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3203                 cmn_err(CE_WARN, "digest_init: failed holding minor");
3204                 return (ENXIO);
3205         }
3206 
3207         if (copyin(arg, STRUCT_BUF(digest_init),
3208             STRUCT_SIZE(digest_init)) != 0) {
3209                 crypto_release_minor(cm);
3210                 return (EFAULT);
3211         }
3212 
3213         mech.cm_param = NULL;
3214 
3215         session_id = STRUCT_FGET(digest_init, di_session);
3216 
3217         if (!get_session_ptr(session_id, cm, &sp, &error, &rv))  {
3218                 goto out;
3219         }
3220 
3221         if (!copyin_mech(mode, sp, STRUCT_FADDR(digest_init, di_mech), &mech,
3222             &rctl_bytes, &rctl_chk, &rv, &error)) {
3223                 goto out;
3224         }
3225 
3226         if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL,
3227             CRYPTO_MECH_INVALID, NULL, sp->sd_provider, &real_provider,
3228             CRYPTO_FG_DIGEST)) != CRYPTO_SUCCESS) {
3229                 goto out;
3230         }
3231 
3232         rv = crypto_digest_init_prov(real_provider,
3233             sp->sd_provider_session->ps_session, &mech, &cc, NULL);
3234 
3235         /*
3236          * Check if a context already exists. If so, it means it is being
3237          * abandoned. So, cancel it to avoid leaking it.
3238          */
3239         if (sp->sd_digest_ctx != NULL)
3240                 CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx);
3241         sp->sd_digest_ctx = (rv == CRYPTO_SUCCESS) ? cc : NULL;
3242 out:
3243         CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk);
3244         CRYPTO_SESSION_RELE(sp);
3245         crypto_release_minor(cm);
3246 
3247         if (real_provider != NULL)
3248                 KCF_PROV_REFRELE(real_provider);
3249 
3250         if (mech.cm_param != NULL)
3251                 kmem_free(mech.cm_param, mech.cm_param_len);
3252 
3253         if (error != 0)
3254                 return (error);
3255 
3256         STRUCT_FSET(digest_init, di_return_value, rv);
3257         if (copyout(STRUCT_BUF(digest_init), arg,
3258             STRUCT_SIZE(digest_init)) != 0) {
3259                 return (EFAULT);
3260         }
3261         return (0);
3262 }
3263 
3264 /* ARGSUSED */
3265 static int
3266 digest_update(dev_t dev, caddr_t arg, int mode, int *rval)
3267 {
3268         STRUCT_DECL(crypto_digest_update, digest_update);
3269         crypto_session_id_t session_id;
3270         crypto_minor_t *cm;
3271         crypto_session_data_t *sp = NULL;
3272         crypto_data_t data;
3273         size_t datalen, need = 0;
3274         int error = 0;
3275         int rv;
3276         boolean_t rctl_chk = B_FALSE;
3277 
3278         STRUCT_INIT(digest_update, mode);
3279 
3280         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3281                 cmn_err(CE_WARN, "digest_update: failed holding minor");
3282                 return (ENXIO);
3283         }
3284 
3285         if (copyin(arg, STRUCT_BUF(digest_update),
3286             STRUCT_SIZE(digest_update)) != 0) {
3287                 crypto_release_minor(cm);
3288                 return (EFAULT);
3289         }
3290 
3291         data.cd_format = CRYPTO_DATA_RAW;
3292         data.cd_raw.iov_base = NULL;
3293 
3294         datalen = STRUCT_FGET(digest_update, du_datalen);
3295         if (datalen > crypto_max_buffer_len) {
3296                 cmn_err(CE_NOTE, "digest_update: buffer greater than %ld "
3297                     "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
3298                 rv = CRYPTO_ARGUMENTS_BAD;
3299                 goto release_minor;
3300         }
3301 
3302         session_id = STRUCT_FGET(digest_update, du_session);
3303 
3304         if (!get_session_ptr(session_id, cm, &sp, &error, &rv))  {
3305                 goto release_minor;
3306         }
3307 
3308         if ((rv = CRYPTO_BUFFER_CHECK(sp, datalen, rctl_chk)) !=
3309             CRYPTO_SUCCESS) {
3310                 goto release_minor;
3311         }
3312 
3313         need = datalen;
3314         data.cd_raw.iov_base = kmem_alloc(datalen, KM_SLEEP);
3315         data.cd_raw.iov_len = datalen;
3316 
3317         if (datalen != 0 && copyin(STRUCT_FGETP(digest_update, du_databuf),
3318             data.cd_raw.iov_base, datalen) != 0) {
3319                 error = EFAULT;
3320                 goto release_minor;
3321         }
3322 
3323         data.cd_offset = 0;
3324         data.cd_length = datalen;
3325 
3326         rv = crypto_digest_update(sp->sd_digest_ctx, &data, NULL);
3327         if (rv != CRYPTO_SUCCESS)
3328                 CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx);
3329 
3330 release_minor:
3331         CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
3332         CRYPTO_SESSION_RELE(sp);
3333         crypto_release_minor(cm);
3334 
3335         if (data.cd_raw.iov_base != NULL)
3336                 kmem_free(data.cd_raw.iov_base, datalen);
3337 
3338         if (error != 0)
3339                 return (error);
3340 
3341         STRUCT_FSET(digest_update, du_return_value, rv);
3342         if (copyout(STRUCT_BUF(digest_update), arg,
3343             STRUCT_SIZE(digest_update)) != 0) {
3344                 return (EFAULT);
3345         }
3346         return (0);
3347 }
3348 
3349 /* ARGSUSED */
3350 static int
3351 digest_key(dev_t dev, caddr_t arg, int mode, int *rval)
3352 {
3353         STRUCT_DECL(crypto_digest_key, digest_key);
3354         crypto_session_id_t session_id;
3355         crypto_key_t key;
3356         crypto_minor_t *cm;
3357         crypto_session_data_t *sp = NULL;
3358         size_t rctl_bytes = 0;
3359         boolean_t key_rctl_chk = B_FALSE;
3360         int error = 0;
3361         int rv;
3362 
3363         STRUCT_INIT(digest_key, mode);
3364 
3365         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3366                 cmn_err(CE_WARN, "digest_key: failed holding minor");
3367                 return (ENXIO);
3368         }
3369 
3370         if (copyin(arg, STRUCT_BUF(digest_key), STRUCT_SIZE(digest_key)) != 0) {
3371                 crypto_release_minor(cm);
3372                 return (EFAULT);
3373         }
3374 
3375         bzero(&key, sizeof (crypto_key_t));
3376 
3377         session_id = STRUCT_FGET(digest_key, dk_session);
3378 
3379         if (!get_session_ptr(session_id, cm, &sp, &error, &rv))  {
3380                 goto out;
3381         }
3382 
3383         if (!copyin_key(mode, sp, STRUCT_FADDR(digest_key, dk_key), &key,
3384             &rctl_bytes, &key_rctl_chk, &rv, &error)) {
3385                 goto out;
3386         }
3387 
3388         rv = crypto_digest_key_prov(sp->sd_digest_ctx, &key, NULL);
3389         if (rv != CRYPTO_SUCCESS)
3390                 CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx);
3391 out:
3392         CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, key_rctl_chk);
3393         CRYPTO_SESSION_RELE(sp);
3394         crypto_release_minor(cm);
3395 
3396         free_crypto_key(&key);
3397 
3398         if (error != 0)
3399                 return (error);
3400 
3401         STRUCT_FSET(digest_key, dk_return_value, rv);
3402         if (copyout(STRUCT_BUF(digest_key), arg,
3403             STRUCT_SIZE(digest_key)) != 0) {
3404                 return (EFAULT);
3405         }
3406         return (0);
3407 }
3408 
3409 /* ARGSUSED */
3410 static int
3411 digest_final(dev_t dev, caddr_t arg, int mode, int *rval)
3412 {
3413         return (common_final(dev, arg, mode, crypto_digest_final));
3414 }
3415 
3416 /* ARGSUSED */
3417 static int
3418 digest(dev_t dev, caddr_t arg, int mode, int *rval)
3419 {
3420         return (common_digest(dev, arg, mode, crypto_digest_single));
3421 }
3422 
3423 /*
3424  * ASSUMPTION: crypto_digest, crypto_sign, crypto_sign_recover,
3425  * and crypto_verify_recover are identical except for field names.
3426  */
3427 static int
3428 common_digest(dev_t dev, caddr_t arg, int mode,
3429     int (*single)(crypto_context_t, crypto_data_t *, crypto_data_t *,
3430     crypto_call_req_t *))
3431 {
3432         STRUCT_DECL(crypto_digest, crypto_digest);
3433         crypto_session_id_t session_id;
3434         crypto_minor_t *cm;
3435         crypto_session_data_t *sp = NULL;
3436         crypto_data_t data, digest;
3437         crypto_ctx_t **ctxpp;
3438         size_t datalen, digestlen, need = 0;
3439         char *digestbuf;
3440         int error = 0;
3441         int rv;
3442         boolean_t rctl_chk = B_FALSE;
3443 
3444         STRUCT_INIT(crypto_digest, mode);
3445 
3446         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3447                 cmn_err(CE_WARN, "common_digest: failed holding minor");
3448                 return (ENXIO);
3449         }
3450 
3451         if (copyin(arg, STRUCT_BUF(crypto_digest),
3452             STRUCT_SIZE(crypto_digest)) != 0) {
3453                 crypto_release_minor(cm);
3454                 return (EFAULT);
3455         }
3456 
3457         data.cd_raw.iov_base = NULL;
3458         digest.cd_raw.iov_base = NULL;
3459 
3460         datalen = STRUCT_FGET(crypto_digest, cd_datalen);
3461         digestlen = STRUCT_FGET(crypto_digest, cd_digestlen);
3462 
3463         /*
3464          * Don't allocate output buffer unless both buffer pointer and
3465          * buffer length are not NULL or 0 (length).
3466          */
3467         digestbuf = STRUCT_FGETP(crypto_digest, cd_digestbuf);
3468         if (digestbuf == NULL || digestlen == 0) {
3469                 digestlen = 0;
3470         }
3471 
3472         if (datalen > crypto_max_buffer_len ||
3473             digestlen > crypto_max_buffer_len) {
3474                 cmn_err(CE_NOTE, "common_digest: buffer greater than %ld "
3475                     "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
3476                 rv = CRYPTO_ARGUMENTS_BAD;
3477                 goto release_minor;
3478         }
3479 
3480         session_id = STRUCT_FGET(crypto_digest, cd_session);
3481 
3482         if (!get_session_ptr(session_id, cm, &sp, &error, &rv))  {
3483                 goto release_minor;
3484         }
3485 
3486         need = datalen + digestlen;
3487         if ((rv = CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)) !=
3488             CRYPTO_SUCCESS) {
3489                 need = 0;
3490                 goto release_minor;
3491         }
3492 
3493         INIT_RAW_CRYPTO_DATA(data, datalen);
3494 
3495         if (datalen != 0 && copyin(STRUCT_FGETP(crypto_digest, cd_databuf),
3496             data.cd_raw.iov_base, datalen) != 0) {
3497                 error = EFAULT;
3498                 goto release_minor;
3499         }
3500 
3501         INIT_RAW_CRYPTO_DATA(digest, digestlen);
3502 
3503         ASSERT(single == crypto_digest_single ||
3504             single == crypto_sign_single ||
3505             single == crypto_verify_recover_single ||
3506             single == crypto_sign_recover_single);
3507 
3508         if (single == crypto_digest_single) {
3509                 ctxpp = &sp->sd_digest_ctx;
3510         } else if (single == crypto_sign_single) {
3511                 ctxpp = &sp->sd_sign_ctx;
3512         } else if (single == crypto_verify_recover_single) {
3513                 ctxpp = &sp->sd_verify_recover_ctx;
3514         } else {
3515                 ctxpp = &sp->sd_sign_recover_ctx;
3516         }
3517         rv = (single)(*ctxpp, &data, &digest, NULL);
3518         if (KCF_CONTEXT_DONE(rv))
3519                 *ctxpp = NULL;
3520 
3521         if (rv == CRYPTO_SUCCESS) {
3522                 ASSERT(digest.cd_length <= digestlen);
3523                 if (digest.cd_length != 0 && copyout(digest.cd_raw.iov_base,
3524                     digestbuf, digest.cd_length) != 0) {
3525                         error = EFAULT;
3526                         goto release_minor;
3527                 }
3528                 STRUCT_FSET(crypto_digest, cd_digestlen,
3529                     (ulong_t)digest.cd_length);
3530         }
3531 
3532         if (rv == CRYPTO_BUFFER_TOO_SMALL) {
3533                 /*
3534                  * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
3535                  * of section 11.2 of the pkcs11 spec. We catch it here and
3536                  * provide the correct pkcs11 return value.
3537                  */
3538                 if (STRUCT_FGETP(crypto_digest, cd_digestbuf) == NULL)
3539                         rv = CRYPTO_SUCCESS;
3540                 STRUCT_FSET(crypto_digest, cd_digestlen,
3541                     (ulong_t)digest.cd_length);
3542         }
3543 
3544 release_minor:
3545         CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
3546         CRYPTO_SESSION_RELE(sp);
3547         crypto_release_minor(cm);
3548 
3549         if (data.cd_raw.iov_base != NULL)
3550                 kmem_free(data.cd_raw.iov_base, datalen);
3551 
3552         if (digest.cd_raw.iov_base != NULL)
3553                 kmem_free(digest.cd_raw.iov_base, digestlen);
3554 
3555         if (error != 0)
3556                 return (error);
3557 
3558         STRUCT_FSET(crypto_digest, cd_return_value, rv);
3559         if (copyout(STRUCT_BUF(crypto_digest), arg,
3560             STRUCT_SIZE(crypto_digest)) != 0) {
3561                 return (EFAULT);
3562         }
3563         return (0);
3564 }
3565 
3566 /*
3567  * A helper function that does what the name suggests.
3568  * Returns 0 on success and non-zero otherwise.
3569  * On failure, out_pin is set to 0.
3570  */
3571 int
3572 get_pin_and_session_ptr(char *in_pin, char **out_pin, size_t pin_len,
3573     crypto_minor_t *cm, crypto_session_id_t sid, crypto_session_data_t **sp,
3574     int *rv, int *error)
3575 {
3576         char *tmp_pin = NULL;
3577         int tmp_error = 0, tmp_rv = 0;
3578 
3579         if (pin_len > KCF_MAX_PIN_LEN) {
3580                 tmp_rv = CRYPTO_PIN_LEN_RANGE;
3581                 goto out;
3582         }
3583         tmp_pin = kmem_alloc(pin_len, KM_SLEEP);
3584 
3585         if (pin_len != 0 && copyin(in_pin, tmp_pin, pin_len) != 0) {
3586                 tmp_error = EFAULT;
3587                 goto out;
3588         }
3589 
3590         (void) get_session_ptr(sid, cm, sp, &tmp_error, &tmp_rv);
3591 out:
3592         *out_pin = tmp_pin;
3593         *rv = tmp_rv;
3594         *error = tmp_error;
3595         return (tmp_rv | tmp_error);
3596 }
3597 
3598 /* ARGSUSED */
3599 static int
3600 set_pin(dev_t dev, caddr_t arg, int mode, int *rval)
3601 {
3602         STRUCT_DECL(crypto_set_pin, set_pin);
3603         kcf_provider_desc_t *real_provider;
3604         kcf_req_params_t params;
3605         crypto_minor_t *cm;
3606         crypto_session_data_t *sp;
3607         char *old_pin = NULL;
3608         char *new_pin = NULL;
3609         size_t old_pin_len;
3610         size_t new_pin_len;
3611         int error = 0;
3612         int rv;
3613 
3614         STRUCT_INIT(set_pin, mode);
3615 
3616         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3617                 cmn_err(CE_WARN, "set_pin: failed holding minor");
3618                 return (ENXIO);
3619         }
3620 
3621         if (copyin(arg, STRUCT_BUF(set_pin),
3622             STRUCT_SIZE(set_pin)) != 0) {
3623                 crypto_release_minor(cm);
3624                 return (EFAULT);
3625         }
3626 
3627         old_pin_len = STRUCT_FGET(set_pin, sp_old_len);
3628 
3629         if (get_pin_and_session_ptr(STRUCT_FGETP(set_pin, sp_old_pin),
3630             &old_pin, old_pin_len, cm, STRUCT_FGET(set_pin, sp_session),
3631             &sp, &rv, &error) != 0)
3632                 goto release_minor;
3633 
3634         new_pin_len = STRUCT_FGET(set_pin, sp_new_len);
3635         if (new_pin_len > KCF_MAX_PIN_LEN) {
3636                 rv = CRYPTO_PIN_LEN_RANGE;
3637                 goto out;
3638         }
3639         new_pin = kmem_alloc(new_pin_len, KM_SLEEP);
3640 
3641         if (new_pin_len != 0 && copyin(STRUCT_FGETP(set_pin, sp_new_pin),
3642             new_pin, new_pin_len) != 0) {
3643                 error = EFAULT;
3644                 goto out;
3645         }
3646 
3647         if ((rv = kcf_get_hardware_provider_nomech(
3648             CRYPTO_OPS_OFFSET(provider_ops), CRYPTO_PROVIDER_OFFSET(set_pin),
3649             sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
3650                 goto out;
3651         }
3652 
3653         KCF_WRAP_PROVMGMT_OPS_PARAMS(&params, KCF_OP_MGMT_SETPIN,
3654             sp->sd_provider_session->ps_session, old_pin, old_pin_len,
3655             new_pin, new_pin_len, NULL, NULL, real_provider);
3656 
3657         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
3658         KCF_PROV_REFRELE(real_provider);
3659 
3660 out:
3661         CRYPTO_SESSION_RELE(sp);
3662 
3663 release_minor:
3664         crypto_release_minor(cm);
3665 
3666         if (old_pin != NULL) {
3667                 bzero(old_pin, old_pin_len);
3668                 kmem_free(old_pin, old_pin_len);
3669         }
3670 
3671         if (new_pin != NULL) {
3672                 bzero(new_pin, new_pin_len);
3673                 kmem_free(new_pin, new_pin_len);
3674         }
3675 
3676         if (error != 0)
3677                 return (error);
3678 
3679         STRUCT_FSET(set_pin, sp_return_value, rv);
3680         if (copyout(STRUCT_BUF(set_pin), arg, STRUCT_SIZE(set_pin)) != 0) {
3681                 return (EFAULT);
3682         }
3683         return (0);
3684 }
3685 
3686 /* ARGSUSED */
3687 static int
3688 login(dev_t dev, caddr_t arg, int mode, int *rval)
3689 {
3690         STRUCT_DECL(crypto_login, login);
3691         kcf_provider_desc_t *real_provider;
3692         kcf_req_params_t params;
3693         crypto_minor_t *cm;
3694         crypto_session_data_t *sp;
3695         size_t pin_len;
3696         char *pin;
3697         uint_t user_type;
3698         int error = 0;
3699         int rv;
3700 
3701         STRUCT_INIT(login, mode);
3702 
3703         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3704                 cmn_err(CE_WARN, "login: failed holding minor");
3705                 return (ENXIO);
3706         }
3707 
3708         if (copyin(arg, STRUCT_BUF(login), STRUCT_SIZE(login)) != 0) {
3709                 crypto_release_minor(cm);
3710                 return (EFAULT);
3711         }
3712 
3713         user_type = STRUCT_FGET(login, co_user_type);
3714 
3715         pin_len = STRUCT_FGET(login, co_pin_len);
3716 
3717         if (get_pin_and_session_ptr(STRUCT_FGETP(login, co_pin),
3718             &pin, pin_len, cm, STRUCT_FGET(login, co_session),
3719             &sp, &rv, &error) != 0) {
3720                 if (rv == CRYPTO_PIN_LEN_RANGE)
3721                         rv = CRYPTO_PIN_INCORRECT;
3722                 goto release_minor;
3723         }
3724 
3725         if ((rv = kcf_get_hardware_provider_nomech(
3726             CRYPTO_OPS_OFFSET(session_ops),
3727             CRYPTO_SESSION_OFFSET(session_login), sp->sd_provider,
3728             &real_provider)) != CRYPTO_SUCCESS) {
3729                 goto out;
3730         }
3731 
3732         KCF_WRAP_SESSION_OPS_PARAMS(&params, KCF_OP_SESSION_LOGIN, NULL,
3733             sp->sd_provider_session->ps_session, user_type, pin, pin_len,
3734             real_provider);
3735 
3736         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
3737         KCF_PROV_REFRELE(real_provider);
3738 
3739 out:
3740         CRYPTO_SESSION_RELE(sp);
3741 
3742 release_minor:
3743         crypto_release_minor(cm);
3744 
3745         if (pin != NULL) {
3746                 bzero(pin, pin_len);
3747                 kmem_free(pin, pin_len);
3748         }
3749 
3750         if (error != 0)
3751                 return (error);
3752 
3753         STRUCT_FSET(login, co_return_value, rv);
3754         if (copyout(STRUCT_BUF(login), arg, STRUCT_SIZE(login)) != 0) {
3755                 return (EFAULT);
3756         }
3757         return (0);
3758 }
3759 
3760 /* ARGSUSED */
3761 static int
3762 logout(dev_t dev, caddr_t arg, int mode, int *rval)
3763 {
3764         crypto_logout_t logout;
3765         kcf_provider_desc_t *real_provider;
3766         kcf_req_params_t params;
3767         crypto_minor_t *cm;
3768         crypto_session_data_t *sp;
3769         int error = 0;
3770         int rv;
3771 
3772         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3773                 cmn_err(CE_WARN, "logout: failed holding minor");
3774                 return (ENXIO);
3775         }
3776 
3777         if (copyin(arg, &logout, sizeof (logout)) != 0) {
3778                 crypto_release_minor(cm);
3779                 return (EFAULT);
3780         }
3781 
3782         if (!get_session_ptr(logout.cl_session, cm, &sp, &error, &rv))  {
3783                 goto release_minor;
3784         }
3785 
3786         if ((rv = kcf_get_hardware_provider_nomech(
3787             CRYPTO_OPS_OFFSET(session_ops),
3788             CRYPTO_SESSION_OFFSET(session_logout), sp->sd_provider,
3789             &real_provider)) != CRYPTO_SUCCESS) {
3790                 goto out;
3791         }
3792 
3793         KCF_WRAP_SESSION_OPS_PARAMS(&params, KCF_OP_SESSION_LOGOUT, NULL,
3794             sp->sd_provider_session->ps_session, 0, NULL, 0, real_provider);
3795         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
3796         KCF_PROV_REFRELE(real_provider);
3797 
3798 out:
3799         CRYPTO_SESSION_RELE(sp);
3800 
3801 release_minor:
3802         crypto_release_minor(cm);
3803 
3804         if (error != 0)
3805                 return (error);
3806 
3807         logout.cl_return_value = rv;
3808         if (copyout(&logout, arg, sizeof (logout)) != 0) {
3809                 return (EFAULT);
3810         }
3811         return (0);
3812 }
3813 
3814 /* ARGSUSED */
3815 static int
3816 sign_init(dev_t dev, caddr_t arg, int mode, int *rval)
3817 {
3818         return (sign_verify_init(dev, arg, mode, crypto_sign_init_prov));
3819 }
3820 
3821 /* ARGSUSED */
3822 static int
3823 sign_recover_init(dev_t dev, caddr_t arg, int mode, int *rval)
3824 {
3825         return (sign_verify_init(dev, arg, mode,
3826             crypto_sign_recover_init_prov));
3827 }
3828 
3829 /* ARGSUSED */
3830 static int
3831 verify_init(dev_t dev, caddr_t arg, int mode, int *rval)
3832 {
3833         return (sign_verify_init(dev, arg, mode, crypto_verify_init_prov));
3834 }
3835 
3836 /* ARGSUSED */
3837 static int
3838 verify_recover_init(dev_t dev, caddr_t arg, int mode, int *rval)
3839 {
3840         return (sign_verify_init(dev, arg, mode,
3841             crypto_verify_recover_init_prov));
3842 }
3843 
3844 /*
3845  * ASSUMPTION: crypto_sign_init, crypto_verify_init, crypto_sign_recover_init,
3846  * and crypto_verify_recover_init structures are identical
3847  * except for field names.
3848  */
3849 static int
3850 sign_verify_init(dev_t dev, caddr_t arg, int mode,
3851     int (*init)(crypto_provider_t, crypto_session_id_t,
3852     crypto_mechanism_t *, crypto_key_t *, crypto_ctx_template_t,
3853     crypto_context_t *, crypto_call_req_t *))
3854 {
3855         STRUCT_DECL(crypto_sign_init, sign_init);
3856         kcf_provider_desc_t *real_provider = NULL;
3857         crypto_session_id_t session_id;
3858         crypto_mechanism_t mech;
3859         crypto_key_t key;
3860         crypto_minor_t *cm;
3861         crypto_session_data_t *sp = NULL;
3862         crypto_context_t cc;
3863         crypto_ctx_t **ctxpp;
3864         size_t mech_rctl_bytes = 0;
3865         boolean_t mech_rctl_chk = B_FALSE;
3866         size_t key_rctl_bytes = 0;
3867         boolean_t key_rctl_chk = B_FALSE;
3868         int error = 0;
3869         int rv;
3870         boolean_t allocated_by_crypto_module = B_FALSE;
3871         crypto_func_group_t fg;
3872 
3873         STRUCT_INIT(sign_init, mode);
3874 
3875         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3876                 cmn_err(CE_WARN, "sign_verify_init: failed holding minor");
3877                 return (ENXIO);
3878         }
3879 
3880         if (copyin(arg, STRUCT_BUF(sign_init), STRUCT_SIZE(sign_init)) != 0) {
3881                 crypto_release_minor(cm);
3882                 return (EFAULT);
3883         }
3884 
3885         mech.cm_param = NULL;
3886         bzero(&key, sizeof (key));
3887 
3888         session_id = STRUCT_FGET(sign_init, si_session);
3889 
3890         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
3891                 goto out;
3892         }
3893 
3894         bcopy(STRUCT_FADDR(sign_init, si_mech), &mech.cm_type,
3895             sizeof (crypto_mech_type_t));
3896 
3897         ASSERT(init == crypto_sign_init_prov ||
3898             init == crypto_verify_init_prov ||
3899             init == crypto_sign_recover_init_prov ||
3900             init == crypto_verify_recover_init_prov);
3901 
3902         if (init == crypto_sign_init_prov) {
3903                 fg =  CRYPTO_FG_SIGN;
3904                 ctxpp = &sp->sd_sign_ctx;
3905         } else if (init == crypto_verify_init_prov) {
3906                 fg =  CRYPTO_FG_VERIFY;
3907                 ctxpp = &sp->sd_verify_ctx;
3908         } else if (init == crypto_sign_recover_init_prov) {
3909                 fg =  CRYPTO_FG_SIGN_RECOVER;
3910                 ctxpp = &sp->sd_sign_recover_ctx;
3911         } else {
3912                 fg =  CRYPTO_FG_VERIFY_RECOVER;
3913                 ctxpp = &sp->sd_verify_recover_ctx;
3914         }
3915 
3916         /* We need the key length for provider selection so copy it in now. */
3917         if (!copyin_key(mode, sp, STRUCT_FADDR(sign_init, si_key), &key,
3918             &key_rctl_bytes, &key_rctl_chk, &rv, &error)) {
3919                 goto out;
3920         }
3921 
3922         if ((rv = kcf_get_hardware_provider(mech.cm_type, &key,
3923             CRYPTO_MECH_INVALID, NULL, sp->sd_provider, &real_provider,
3924             fg)) != CRYPTO_SUCCESS) {
3925                 goto out;
3926         }
3927 
3928         rv = crypto_provider_copyin_mech_param(real_provider,
3929             STRUCT_FADDR(sign_init, si_mech), &mech, mode, &error);
3930 
3931         if (rv == CRYPTO_NOT_SUPPORTED) {
3932                 allocated_by_crypto_module = B_TRUE;
3933                 if (!copyin_mech(mode, sp, STRUCT_FADDR(sign_init, si_mech),
3934                     &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) {
3935                         goto out;
3936                 }
3937         } else {
3938                 if (rv != CRYPTO_SUCCESS)
3939                         goto out;
3940         }
3941 
3942         rv = (init)(real_provider, sp->sd_provider_session->ps_session,
3943             &mech, &key, NULL, &cc, NULL);
3944 
3945         /*
3946          * Check if a context already exists. If so, it means it is being
3947          * abandoned. So, cancel it to avoid leaking it.
3948          */
3949         if (*ctxpp != NULL)
3950                 CRYPTO_CANCEL_CTX(ctxpp);
3951         *ctxpp = (rv == CRYPTO_SUCCESS) ? cc : NULL;
3952 
3953 out:
3954         CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
3955         CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk);
3956         CRYPTO_SESSION_RELE(sp);
3957         crypto_release_minor(cm);
3958 
3959         if (real_provider != NULL) {
3960                 crypto_free_mech(real_provider,
3961                     allocated_by_crypto_module, &mech);
3962                 KCF_PROV_REFRELE(real_provider);
3963         }
3964 
3965         free_crypto_key(&key);
3966 
3967         if (error != 0)
3968                 return (error);
3969 
3970         STRUCT_FSET(sign_init, si_return_value, rv);
3971         if (copyout(STRUCT_BUF(sign_init), arg, STRUCT_SIZE(sign_init)) != 0) {
3972                 return (EFAULT);
3973         }
3974         return (0);
3975 }
3976 
3977 /* ARGSUSED */
3978 static int
3979 sign(dev_t dev, caddr_t arg, int mode, int *rval)
3980 {
3981         return (common_digest(dev, arg, mode, crypto_sign_single));
3982 }
3983 
3984 /* ARGSUSED */
3985 static int
3986 sign_recover(dev_t dev, caddr_t arg, int mode, int *rval)
3987 {
3988         return (common_digest(dev, arg, mode, crypto_sign_recover_single));
3989 }
3990 
3991 /* ARGSUSED */
3992 static int
3993 verify(dev_t dev, caddr_t arg, int mode, int *rval)
3994 {
3995         STRUCT_DECL(crypto_verify, verify);
3996         crypto_session_id_t session_id;
3997         crypto_minor_t *cm;
3998         crypto_session_data_t *sp = NULL;
3999         crypto_data_t data, sign;
4000         size_t datalen, signlen, need = 0;
4001         int error = 0;
4002         int rv;
4003         boolean_t rctl_chk = B_FALSE;
4004 
4005         STRUCT_INIT(verify, mode);
4006 
4007         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4008                 cmn_err(CE_WARN, "verify: failed holding minor");
4009                 return (ENXIO);
4010         }
4011 
4012         if (copyin(arg, STRUCT_BUF(verify), STRUCT_SIZE(verify)) != 0) {
4013                 crypto_release_minor(cm);
4014                 return (EFAULT);
4015         }
4016 
4017         data.cd_raw.iov_base = NULL;
4018         sign.cd_raw.iov_base = NULL;
4019 
4020         datalen = STRUCT_FGET(verify, cv_datalen);
4021         signlen = STRUCT_FGET(verify, cv_signlen);
4022         if (datalen > crypto_max_buffer_len ||
4023             signlen > crypto_max_buffer_len) {
4024                 cmn_err(CE_NOTE, "verify: buffer greater than %ld bytes, "
4025                 "pid = %d", crypto_max_buffer_len, curproc->p_pid);
4026                 rv = CRYPTO_ARGUMENTS_BAD;
4027                 goto release_minor;
4028         }
4029 
4030         session_id = STRUCT_FGET(verify, cv_session);
4031 
4032         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4033                 goto release_minor;
4034         }
4035 
4036         need = datalen + signlen;
4037         if ((rv = CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)) !=
4038             CRYPTO_SUCCESS) {
4039                 need = 0;
4040                 goto release_minor;
4041         }
4042 
4043         INIT_RAW_CRYPTO_DATA(data, datalen);
4044         INIT_RAW_CRYPTO_DATA(sign, signlen);
4045 
4046         if (datalen != 0 && copyin(STRUCT_FGETP(verify, cv_databuf),
4047             data.cd_raw.iov_base, datalen) != 0) {
4048                 error = EFAULT;
4049                 goto release_minor;
4050         }
4051 
4052         if (signlen != 0 && copyin(STRUCT_FGETP(verify, cv_signbuf),
4053             sign.cd_raw.iov_base, signlen) != 0) {
4054                 error = EFAULT;
4055                 goto release_minor;
4056         }
4057 
4058         rv = crypto_verify_single(sp->sd_verify_ctx, &data, &sign, NULL);
4059         if (KCF_CONTEXT_DONE(rv))
4060                 sp->sd_verify_ctx = NULL;
4061 
4062 release_minor:
4063         CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
4064         CRYPTO_SESSION_RELE(sp);
4065         crypto_release_minor(cm);
4066 
4067         if (data.cd_raw.iov_base != NULL)
4068                 kmem_free(data.cd_raw.iov_base, datalen);
4069 
4070         if (sign.cd_raw.iov_base != NULL)
4071                 kmem_free(sign.cd_raw.iov_base, signlen);
4072 
4073         if (error != 0)
4074                 return (error);
4075 
4076         STRUCT_FSET(verify, cv_return_value, rv);
4077         if (copyout(STRUCT_BUF(verify), arg, STRUCT_SIZE(verify)) != 0) {
4078                 return (EFAULT);
4079         }
4080         return (0);
4081 }
4082 
4083 /* ARGSUSED */
4084 static int
4085 verify_recover(dev_t dev, caddr_t arg, int mode, int *rval)
4086 {
4087         return (common_digest(dev, arg, mode, crypto_verify_recover_single));
4088 }
4089 
4090 /* ARGSUSED */
4091 static int
4092 sign_update(dev_t dev, caddr_t arg, int mode, int *rval)
4093 {
4094         return (sign_verify_update(dev, arg, mode, crypto_sign_update));
4095 }
4096 
4097 /* ARGSUSED */
4098 static int
4099 verify_update(dev_t dev, caddr_t arg, int mode, int *rval)
4100 {
4101         return (sign_verify_update(dev, arg, mode, crypto_verify_update));
4102 }
4103 
4104 /*
4105  * ASSUMPTION: crypto_sign_update and crypto_verify_update structures
4106  * are identical except for field names.
4107  */
4108 static int
4109 sign_verify_update(dev_t dev, caddr_t arg, int mode,
4110     int (*update)(crypto_context_t, crypto_data_t *, crypto_call_req_t *))
4111 {
4112         STRUCT_DECL(crypto_sign_update, sign_update);
4113         crypto_session_id_t session_id;
4114         crypto_minor_t *cm;
4115         crypto_session_data_t *sp = NULL;
4116         crypto_ctx_t **ctxpp;
4117         crypto_data_t data;
4118         size_t datalen, need = 0;
4119         int error = 0;
4120         int rv;
4121         boolean_t rctl_chk = B_FALSE;
4122 
4123         STRUCT_INIT(sign_update, mode);
4124 
4125         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4126                 cmn_err(CE_WARN, "sign_verify_update: failed holding minor");
4127                 return (ENXIO);
4128         }
4129 
4130         if (copyin(arg, STRUCT_BUF(sign_update),
4131             STRUCT_SIZE(sign_update)) != 0) {
4132                 crypto_release_minor(cm);
4133                 return (EFAULT);
4134         }
4135 
4136         data.cd_raw.iov_base = NULL;
4137 
4138         datalen = STRUCT_FGET(sign_update, su_datalen);
4139         if (datalen > crypto_max_buffer_len) {
4140                 cmn_err(CE_NOTE, "sign_verify_update: buffer greater than %ld "
4141                     "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
4142                 rv = CRYPTO_ARGUMENTS_BAD;
4143                 goto release_minor;
4144         }
4145 
4146         session_id = STRUCT_FGET(sign_update, su_session);
4147 
4148         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4149                 goto release_minor;
4150         }
4151 
4152         if ((rv = CRYPTO_BUFFER_CHECK(sp, datalen, rctl_chk)) !=
4153             CRYPTO_SUCCESS) {
4154                 goto release_minor;
4155         }
4156         need = datalen;
4157 
4158         INIT_RAW_CRYPTO_DATA(data, datalen);
4159 
4160         if (datalen != 0 && copyin(STRUCT_FGETP(sign_update, su_databuf),
4161             data.cd_raw.iov_base, datalen) != 0) {
4162                 error = EFAULT;
4163                 goto release_minor;
4164         }
4165 
4166         ctxpp = (update == crypto_sign_update) ?
4167             &sp->sd_sign_ctx : &sp->sd_verify_ctx;
4168 
4169         rv = (update)(*ctxpp, &data, NULL);
4170         if (rv != CRYPTO_SUCCESS)
4171                 CRYPTO_CANCEL_CTX(ctxpp);
4172 
4173 release_minor:
4174         CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
4175         CRYPTO_SESSION_RELE(sp);
4176         crypto_release_minor(cm);
4177 
4178         if (data.cd_raw.iov_base != NULL)
4179                 kmem_free(data.cd_raw.iov_base, datalen);
4180 
4181         if (error != 0)
4182                 return (error);
4183 
4184         STRUCT_FSET(sign_update, su_return_value, rv);
4185         if (copyout(STRUCT_BUF(sign_update), arg,
4186             STRUCT_SIZE(sign_update)) != 0) {
4187                 return (EFAULT);
4188         }
4189         return (0);
4190 }
4191 
4192 /* ARGSUSED */
4193 static int
4194 sign_final(dev_t dev, caddr_t arg, int mode, int *rval)
4195 {
4196         return (common_final(dev, arg, mode, crypto_sign_final));
4197 }
4198 
4199 /*
4200  * Can't use the common final because it does a copyout of
4201  * the final part.
4202  */
4203 /* ARGSUSED */
4204 static int
4205 verify_final(dev_t dev, caddr_t arg, int mode, int *rval)
4206 {
4207         STRUCT_DECL(crypto_verify_final, verify_final);
4208         crypto_session_id_t session_id;
4209         crypto_minor_t *cm;
4210         crypto_session_data_t *sp = NULL;
4211         crypto_data_t sign;
4212         size_t signlen, need = 0;
4213         int error = 0;
4214         int rv;
4215         boolean_t rctl_chk = B_FALSE;
4216 
4217         STRUCT_INIT(verify_final, mode);
4218 
4219         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4220                 cmn_err(CE_WARN, "verify_final: failed holding minor");
4221                 return (ENXIO);
4222         }
4223 
4224         if (copyin(arg, STRUCT_BUF(verify_final),
4225             STRUCT_SIZE(verify_final)) != 0) {
4226                 crypto_release_minor(cm);
4227                 return (EFAULT);
4228         }
4229 
4230         sign.cd_raw.iov_base = NULL;
4231 
4232         signlen = STRUCT_FGET(verify_final, vf_signlen);
4233         if (signlen > crypto_max_buffer_len) {
4234                 cmn_err(CE_NOTE, "verify_final: buffer greater than %ld "
4235                     "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
4236                 rv = CRYPTO_ARGUMENTS_BAD;
4237                 goto release_minor;
4238         }
4239 
4240         session_id = STRUCT_FGET(verify_final, vf_session);
4241 
4242         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4243                 goto release_minor;
4244         }
4245 
4246         if ((rv = CRYPTO_BUFFER_CHECK(sp, signlen, rctl_chk)) !=
4247             CRYPTO_SUCCESS) {
4248                 goto release_minor;
4249         }
4250         need = signlen;
4251 
4252         INIT_RAW_CRYPTO_DATA(sign, signlen);
4253 
4254         if (signlen != 0 && copyin(STRUCT_FGETP(verify_final, vf_signbuf),
4255             sign.cd_raw.iov_base, signlen) != 0) {
4256                 error = EFAULT;
4257                 goto release_minor;
4258         }
4259 
4260         rv = crypto_verify_final(sp->sd_verify_ctx, &sign, NULL);
4261         if (KCF_CONTEXT_DONE(rv))
4262                 sp->sd_verify_ctx = NULL;
4263 
4264 release_minor:
4265         CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
4266         CRYPTO_SESSION_RELE(sp);
4267         crypto_release_minor(cm);
4268 
4269         if (sign.cd_raw.iov_base != NULL)
4270                 kmem_free(sign.cd_raw.iov_base, signlen);
4271 
4272         if (error != 0)
4273                 return (error);
4274 
4275         STRUCT_FSET(verify_final, vf_return_value, rv);
4276         if (copyout(STRUCT_BUF(verify_final), arg,
4277             STRUCT_SIZE(verify_final)) != 0) {
4278                 return (EFAULT);
4279         }
4280         return (0);
4281 }
4282 
4283 /* ARGSUSED */
4284 static int
4285 seed_random(dev_t dev, caddr_t arg, int mode, int *rval)
4286 {
4287         STRUCT_DECL(crypto_seed_random, seed_random);
4288         kcf_provider_desc_t *real_provider = NULL;
4289         kcf_req_params_t params;
4290         crypto_session_id_t session_id;
4291         crypto_minor_t *cm;
4292         crypto_session_data_t *sp = NULL;
4293         uchar_t *seed_buffer = NULL;
4294         size_t seed_len;
4295         size_t need = 0;
4296         int error = 0;
4297         int rv;
4298         boolean_t rctl_chk = B_FALSE;
4299 
4300         STRUCT_INIT(seed_random, mode);
4301 
4302         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4303                 cmn_err(CE_WARN, "seed_random: failed holding minor");
4304                 return (ENXIO);
4305         }
4306 
4307         if (copyin(arg, STRUCT_BUF(seed_random),
4308             STRUCT_SIZE(seed_random)) != 0) {
4309                 crypto_release_minor(cm);
4310                 return (EFAULT);
4311         }
4312 
4313         seed_len = STRUCT_FGET(seed_random, sr_seedlen);
4314         if (seed_len > crypto_max_buffer_len) {
4315                 cmn_err(CE_NOTE, "seed_random: buffer greater than %ld "
4316                     "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
4317                 rv = CRYPTO_ARGUMENTS_BAD;
4318                 goto release_minor;
4319         }
4320 
4321         session_id = STRUCT_FGET(seed_random, sr_session);
4322 
4323         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4324                 goto release_minor;
4325         }
4326 
4327         if ((rv = CRYPTO_BUFFER_CHECK(sp, seed_len, rctl_chk)) !=
4328             CRYPTO_SUCCESS) {
4329                 goto release_minor;
4330         }
4331         need = seed_len;
4332         seed_buffer = kmem_alloc(seed_len, KM_SLEEP);
4333 
4334         if (seed_len != 0 && copyin(STRUCT_FGETP(seed_random, sr_seedbuf),
4335             seed_buffer, seed_len) != 0) {
4336                 error = EFAULT;
4337                 goto release_minor;
4338         }
4339 
4340         if ((rv = kcf_get_hardware_provider_nomech(
4341             CRYPTO_OPS_OFFSET(random_ops), CRYPTO_RANDOM_OFFSET(seed_random),
4342             sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
4343                 goto release_minor;
4344         }
4345 
4346         KCF_WRAP_RANDOM_OPS_PARAMS(&params, KCF_OP_RANDOM_SEED,
4347             sp->sd_provider_session->ps_session, seed_buffer, seed_len, 0,
4348             CRYPTO_SEED_NOW);
4349 
4350         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4351 
4352 release_minor:
4353         CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
4354         CRYPTO_SESSION_RELE(sp);
4355         crypto_release_minor(cm);
4356 
4357         if (real_provider != NULL)
4358                 KCF_PROV_REFRELE(real_provider);
4359 
4360         if (seed_buffer != NULL)
4361                 kmem_free(seed_buffer, seed_len);
4362 
4363         if (error != 0)
4364                 return (error);
4365 
4366         STRUCT_FSET(seed_random, sr_return_value, rv);
4367         if (copyout(STRUCT_BUF(seed_random), arg,
4368             STRUCT_SIZE(seed_random)) != 0) {
4369                 return (EFAULT);
4370         }
4371         return (0);
4372 }
4373 
4374 /* ARGSUSED */
4375 static int
4376 generate_random(dev_t dev, caddr_t arg, int mode, int *rval)
4377 {
4378         STRUCT_DECL(crypto_generate_random, generate_random);
4379         kcf_provider_desc_t *real_provider = NULL;
4380         kcf_req_params_t params;
4381         crypto_session_id_t session_id;
4382         crypto_minor_t *cm;
4383         crypto_session_data_t *sp = NULL;
4384         uchar_t *buffer = NULL;
4385         size_t len;
4386         size_t need = 0;
4387         int error = 0;
4388         int rv;
4389         boolean_t rctl_chk = B_FALSE;
4390 
4391         STRUCT_INIT(generate_random, mode);
4392 
4393         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4394                 cmn_err(CE_WARN, "generate_random: failed holding minor");
4395                 return (ENXIO);
4396         }
4397 
4398         if (copyin(arg, STRUCT_BUF(generate_random),
4399             STRUCT_SIZE(generate_random)) != 0) {
4400                 crypto_release_minor(cm);
4401                 return (EFAULT);
4402         }
4403 
4404         len = STRUCT_FGET(generate_random, gr_buflen);
4405         if (len > crypto_max_buffer_len) {
4406                 cmn_err(CE_NOTE, "generate_random: buffer greater than %ld "
4407                     "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
4408                 rv = CRYPTO_ARGUMENTS_BAD;
4409                 goto release_minor;
4410         }
4411 
4412         session_id = STRUCT_FGET(generate_random, gr_session);
4413 
4414         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4415                 goto release_minor;
4416         }
4417 
4418         if ((rv = CRYPTO_BUFFER_CHECK(sp, len, rctl_chk)) !=
4419             CRYPTO_SUCCESS) {
4420                 goto release_minor;
4421         }
4422         need = len;
4423         buffer = kmem_alloc(len, KM_SLEEP);
4424 
4425         if ((rv = kcf_get_hardware_provider_nomech(
4426             CRYPTO_OPS_OFFSET(random_ops),
4427             CRYPTO_RANDOM_OFFSET(generate_random), sp->sd_provider,
4428             &real_provider)) != CRYPTO_SUCCESS) {
4429                 goto release_minor;
4430         }
4431 
4432         KCF_WRAP_RANDOM_OPS_PARAMS(&params, KCF_OP_RANDOM_GENERATE,
4433             sp->sd_provider_session->ps_session, buffer, len, 0, 0);
4434 
4435         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4436 
4437         if (rv == CRYPTO_SUCCESS) {
4438                 if (len != 0 && copyout(buffer,
4439                     STRUCT_FGETP(generate_random, gr_buf), len) != 0) {
4440                         error = EFAULT;
4441                 }
4442         }
4443 
4444 release_minor:
4445         CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
4446         CRYPTO_SESSION_RELE(sp);
4447         crypto_release_minor(cm);
4448 
4449         if (real_provider != NULL)
4450                 KCF_PROV_REFRELE(real_provider);
4451 
4452         if (buffer != NULL) {
4453                 /* random numbers are often used to create keys */
4454                 bzero(buffer, len);
4455                 kmem_free(buffer, len);
4456         }
4457 
4458         if (error != 0)
4459                 return (error);
4460 
4461         STRUCT_FSET(generate_random, gr_return_value, rv);
4462         if (copyout(STRUCT_BUF(generate_random), arg,
4463             STRUCT_SIZE(generate_random)) != 0) {
4464                 return (EFAULT);
4465         }
4466         return (0);
4467 }
4468 
4469 /*
4470  * Copyout a kernel array of attributes to user space.
4471  * u_attrs is the corresponding user space array containing
4472  * user space pointers necessary for the copyout.
4473  */
4474 /* ARGSUSED */
4475 static int
4476 copyout_attributes(int mode, caddr_t out, uint_t count,
4477     crypto_object_attribute_t *k_attrs, caddr_t u_attrs)
4478 {
4479         STRUCT_DECL(crypto_object_attribute, oa);
4480         caddr_t p, valuep;
4481         size_t value_len;
4482         size_t len;
4483         int i;
4484         int error = 0;
4485 
4486         if (count == 0)
4487                 return (0);
4488 
4489         STRUCT_INIT(oa, mode);
4490 
4491         len = count * STRUCT_SIZE(oa);
4492 
4493         ASSERT(u_attrs != NULL);
4494         p = u_attrs;
4495         for (i = 0; i < count; i++) {
4496                 /* can this bcopy be eliminated? */
4497                 bcopy(p, STRUCT_BUF(oa), STRUCT_SIZE(oa));
4498                 value_len = k_attrs[i].oa_value_len;
4499                 STRUCT_FSET(oa, oa_type, k_attrs[i].oa_type);
4500                 STRUCT_FSET(oa, oa_value_len, (ssize_t)value_len);
4501                 valuep = STRUCT_FGETP(oa, oa_value);
4502                 if ((valuep != NULL) && (value_len != (size_t)-1)) {
4503                         if (copyout(k_attrs[i].oa_value,
4504                             valuep, value_len) != 0) {
4505                                 error = EFAULT;
4506                                 goto out;
4507                         }
4508                 }
4509                 bcopy(STRUCT_BUF(oa), p, STRUCT_SIZE(oa));
4510                 p += STRUCT_SIZE(oa);
4511         }
4512         if (copyout(u_attrs, out, len)) {
4513                 error = EFAULT;
4514         }
4515 out:
4516         return (error);
4517 }
4518 
4519 
4520 /* ARGSUSED */
4521 static int
4522 object_create(dev_t dev, caddr_t arg, int mode, int *rval)
4523 {
4524         STRUCT_DECL(crypto_object_create, object_create);
4525         kcf_provider_desc_t *real_provider = NULL;
4526         kcf_req_params_t params;
4527         crypto_object_attribute_t *k_attrs = NULL;
4528         crypto_session_id_t session_id;
4529         crypto_minor_t *cm;
4530         crypto_session_data_t *sp = NULL;
4531         crypto_object_id_t object_handle;
4532         caddr_t oc_attributes;
4533         size_t k_attrs_size;
4534         size_t rctl_bytes = 0;
4535         boolean_t rctl_chk = B_FALSE;
4536         int error = 0;
4537         int rv;
4538         uint_t count;
4539 
4540         STRUCT_INIT(object_create, mode);
4541 
4542         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4543                 cmn_err(CE_WARN, "object_create: failed holding minor");
4544                 return (ENXIO);
4545         }
4546 
4547         if (copyin(arg, STRUCT_BUF(object_create),
4548             STRUCT_SIZE(object_create)) != 0) {
4549                 crypto_release_minor(cm);
4550                 return (EFAULT);
4551         }
4552 
4553         count = STRUCT_FGET(object_create, oc_count);
4554         oc_attributes = STRUCT_FGETP(object_create, oc_attributes);
4555 
4556         session_id = STRUCT_FGET(object_create, oc_session);
4557         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4558                 goto release_minor;
4559         }
4560         if (!copyin_attributes(mode, sp, count, oc_attributes, &k_attrs,
4561             &k_attrs_size, NULL, &rv, &error, &rctl_bytes,
4562             &rctl_chk, B_TRUE)) {
4563                 goto release_minor;
4564         }
4565 
4566         if ((rv = kcf_get_hardware_provider_nomech(
4567             CRYPTO_OPS_OFFSET(object_ops),
4568             CRYPTO_OBJECT_OFFSET(object_create), sp->sd_provider,
4569             &real_provider)) != CRYPTO_SUCCESS) {
4570                 goto release_minor;
4571         }
4572 
4573         KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_CREATE,
4574             sp->sd_provider_session->ps_session, 0, k_attrs, count,
4575             &object_handle, 0, NULL, NULL, 0, NULL);
4576 
4577         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4578 
4579         if (rv == CRYPTO_SUCCESS)
4580                 STRUCT_FSET(object_create, oc_handle, object_handle);
4581 
4582 release_minor:
4583         CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk);
4584 
4585         if (k_attrs != NULL)
4586                 kmem_free(k_attrs, k_attrs_size);
4587 
4588         if (error != 0)
4589                 goto out;
4590 
4591         STRUCT_FSET(object_create, oc_return_value, rv);
4592         if (copyout(STRUCT_BUF(object_create), arg,
4593             STRUCT_SIZE(object_create)) != 0) {
4594                 if (rv == CRYPTO_SUCCESS) {
4595                         KCF_WRAP_OBJECT_OPS_PARAMS(&params,
4596                             KCF_OP_OBJECT_DESTROY,
4597                             sp->sd_provider_session->ps_session, object_handle,
4598                             NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
4599 
4600                         (void) kcf_submit_request(real_provider, NULL,
4601                             NULL, &params, B_FALSE);
4602 
4603                         error = EFAULT;
4604                 }
4605         }
4606 out:
4607         CRYPTO_SESSION_RELE(sp);
4608         crypto_release_minor(cm);
4609         if (real_provider != NULL)
4610                 KCF_PROV_REFRELE(real_provider);
4611         return (error);
4612 }
4613 
4614 /* ARGSUSED */
4615 static int
4616 object_copy(dev_t dev, caddr_t arg, int mode, int *rval)
4617 {
4618         STRUCT_DECL(crypto_object_copy, object_copy);
4619         kcf_provider_desc_t *real_provider = NULL;
4620         kcf_req_params_t params;
4621         crypto_object_attribute_t *k_attrs = NULL;
4622         crypto_session_id_t session_id;
4623         crypto_minor_t *cm;
4624         crypto_session_data_t *sp = NULL;
4625         crypto_object_id_t handle, new_handle;
4626         caddr_t oc_new_attributes;
4627         size_t k_attrs_size;
4628         size_t rctl_bytes = 0;
4629         boolean_t rctl_chk = B_FALSE;
4630         int error = 0;
4631         int rv;
4632         uint_t count;
4633 
4634         STRUCT_INIT(object_copy, mode);
4635 
4636         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4637                 cmn_err(CE_WARN, "object_copy: failed holding minor");
4638                 return (ENXIO);
4639         }
4640 
4641         if (copyin(arg, STRUCT_BUF(object_copy),
4642             STRUCT_SIZE(object_copy)) != 0) {
4643                 crypto_release_minor(cm);
4644                 return (EFAULT);
4645         }
4646 
4647         count = STRUCT_FGET(object_copy, oc_count);
4648         oc_new_attributes = STRUCT_FGETP(object_copy, oc_new_attributes);
4649 
4650         session_id = STRUCT_FGET(object_copy, oc_session);
4651 
4652         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4653                 goto release_minor;
4654         }
4655         if (!copyin_attributes(mode, sp, count, oc_new_attributes, &k_attrs,
4656             &k_attrs_size, NULL, &rv, &error, &rctl_bytes,
4657             &rctl_chk, B_TRUE)) {
4658                 goto release_minor;
4659         }
4660 
4661         if ((rv = kcf_get_hardware_provider_nomech(
4662             CRYPTO_OPS_OFFSET(object_ops),
4663             CRYPTO_OBJECT_OFFSET(object_copy), sp->sd_provider,
4664             &real_provider)) != CRYPTO_SUCCESS) {
4665                 goto release_minor;
4666         }
4667 
4668         handle = STRUCT_FGET(object_copy, oc_handle);
4669         KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_COPY,
4670             sp->sd_provider_session->ps_session, handle, k_attrs, count,
4671             &new_handle, 0, NULL, NULL, 0, NULL);
4672 
4673         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4674 
4675         if (rv == CRYPTO_SUCCESS)
4676                 STRUCT_FSET(object_copy, oc_new_handle, new_handle);
4677 
4678 release_minor:
4679         CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk);
4680 
4681         if (k_attrs != NULL)
4682                 kmem_free(k_attrs, k_attrs_size);
4683 
4684         if (error != 0)
4685                 goto out;
4686 
4687         STRUCT_FSET(object_copy, oc_return_value, rv);
4688         if (copyout(STRUCT_BUF(object_copy), arg,
4689             STRUCT_SIZE(object_copy)) != 0) {
4690                 if (rv == CRYPTO_SUCCESS) {
4691                         KCF_WRAP_OBJECT_OPS_PARAMS(&params,
4692                             KCF_OP_OBJECT_DESTROY,
4693                             sp->sd_provider_session->ps_session, new_handle,
4694                             NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
4695 
4696                         (void) kcf_submit_request(real_provider, NULL,
4697                             NULL, &params, B_FALSE);
4698 
4699                         error = EFAULT;
4700                 }
4701         }
4702 out:
4703         CRYPTO_SESSION_RELE(sp);
4704         crypto_release_minor(cm);
4705         if (real_provider != NULL)
4706                 KCF_PROV_REFRELE(real_provider);
4707         return (error);
4708 }
4709 
4710 /* ARGSUSED */
4711 static int
4712 object_destroy(dev_t dev, caddr_t arg, int mode, int *rval)
4713 {
4714         STRUCT_DECL(crypto_object_destroy, object_destroy);
4715         kcf_provider_desc_t *real_provider;
4716         kcf_req_params_t params;
4717         crypto_session_id_t session_id;
4718         crypto_minor_t *cm;
4719         crypto_session_data_t *sp;
4720         crypto_object_id_t handle;
4721         int error = 0;
4722         int rv;
4723 
4724         STRUCT_INIT(object_destroy, mode);
4725 
4726         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4727                 cmn_err(CE_WARN, "object_destroy: failed holding minor");
4728                 return (ENXIO);
4729         }
4730 
4731         if (copyin(arg, STRUCT_BUF(object_destroy),
4732             STRUCT_SIZE(object_destroy)) != 0) {
4733                 crypto_release_minor(cm);
4734                 return (EFAULT);
4735         }
4736 
4737         session_id = STRUCT_FGET(object_destroy, od_session);
4738 
4739         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4740                 goto release_minor;
4741         }
4742 
4743         if ((rv = kcf_get_hardware_provider_nomech(
4744             CRYPTO_OPS_OFFSET(object_ops),
4745             CRYPTO_OBJECT_OFFSET(object_destroy), sp->sd_provider,
4746             &real_provider)) != CRYPTO_SUCCESS) {
4747                 goto out;
4748         }
4749 
4750         handle = STRUCT_FGET(object_destroy, od_handle);
4751         KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_DESTROY,
4752             sp->sd_provider_session->ps_session, handle, NULL, 0, NULL, 0,
4753             NULL, NULL, 0, NULL);
4754 
4755         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4756         KCF_PROV_REFRELE(real_provider);
4757 
4758 out:
4759         CRYPTO_SESSION_RELE(sp);
4760 
4761 release_minor:
4762         crypto_release_minor(cm);
4763 
4764         if (error != 0)
4765                 return (error);
4766 
4767         STRUCT_FSET(object_destroy, od_return_value, rv);
4768 
4769         if (copyout(STRUCT_BUF(object_destroy), arg,
4770             STRUCT_SIZE(object_destroy)) != 0) {
4771                 return (EFAULT);
4772         }
4773         return (0);
4774 }
4775 
4776 /* ARGSUSED */
4777 static int
4778 object_get_attribute_value(dev_t dev, caddr_t arg, int mode, int *rval)
4779 {
4780         STRUCT_DECL(crypto_object_get_attribute_value, get_attribute_value);
4781 #ifdef _LP64
4782         STRUCT_DECL(crypto_object_attribute, oa);
4783 #else
4784         /* LINTED E_FUNC_SET_NOT_USED */
4785         STRUCT_DECL(crypto_object_attribute, oa);
4786 #endif
4787         kcf_provider_desc_t *real_provider;
4788         kcf_req_params_t params;
4789         crypto_object_attribute_t *k_attrs = NULL;
4790         crypto_session_id_t session_id;
4791         crypto_minor_t *cm;
4792         crypto_session_data_t *sp = NULL;
4793         crypto_object_id_t handle;
4794         caddr_t og_attributes;
4795         caddr_t u_attrs = NULL;
4796         size_t k_attrs_size;
4797         size_t rctl_bytes = 0;
4798         boolean_t rctl_chk = B_FALSE;
4799         int error = 0;
4800         int rv;
4801         uint_t count;
4802 
4803         STRUCT_INIT(get_attribute_value, mode);
4804         STRUCT_INIT(oa, mode);
4805 
4806         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4807                 cmn_err(CE_WARN,
4808                     "object_get_attribute_value: failed holding minor");
4809                 return (ENXIO);
4810         }
4811 
4812         if (copyin(arg, STRUCT_BUF(get_attribute_value),
4813             STRUCT_SIZE(get_attribute_value)) != 0) {
4814                 crypto_release_minor(cm);
4815                 return (EFAULT);
4816         }
4817 
4818         count = STRUCT_FGET(get_attribute_value, og_count);
4819         og_attributes = STRUCT_FGETP(get_attribute_value, og_attributes);
4820 
4821         session_id = STRUCT_FGET(get_attribute_value, og_session);
4822 
4823         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4824                 goto release_minor;
4825         }
4826         if (!copyin_attributes(mode, sp, count, og_attributes, &k_attrs,
4827             &k_attrs_size, &u_attrs, &rv, &error, &rctl_bytes,
4828             &rctl_chk, B_FALSE)) {
4829                 goto release_minor;
4830         }
4831 
4832         if ((rv = kcf_get_hardware_provider_nomech(
4833             CRYPTO_OPS_OFFSET(object_ops),
4834             CRYPTO_OBJECT_OFFSET(object_get_attribute_value),
4835             sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
4836                 goto out;
4837         }
4838 
4839         handle = STRUCT_FGET(get_attribute_value, og_handle);
4840         KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_GET_ATTRIBUTE_VALUE,
4841             sp->sd_provider_session->ps_session, handle, k_attrs, count, NULL,
4842             0, NULL, NULL, 0, NULL);
4843 
4844         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4845         KCF_PROV_REFRELE(real_provider);
4846 
4847 out:
4848         if (rv == CRYPTO_SUCCESS || rv == CRYPTO_ATTRIBUTE_SENSITIVE ||
4849             rv == CRYPTO_ATTRIBUTE_TYPE_INVALID ||
4850             rv == CRYPTO_BUFFER_TOO_SMALL) {
4851                 error = copyout_attributes(mode,
4852                     STRUCT_FGETP(get_attribute_value, og_attributes),
4853                     count, k_attrs, u_attrs);
4854         }
4855 
4856 release_minor:
4857         CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk);
4858         CRYPTO_SESSION_RELE(sp);
4859         crypto_release_minor(cm);
4860 
4861         if (k_attrs != NULL)
4862                 kmem_free(k_attrs, k_attrs_size);
4863 
4864         if (u_attrs != NULL)
4865                 kmem_free(u_attrs, count * STRUCT_SIZE(oa));
4866 
4867         if (error != 0)
4868                 return (error);
4869 
4870         STRUCT_FSET(get_attribute_value, og_return_value, rv);
4871         if (copyout(STRUCT_BUF(get_attribute_value), arg,
4872             STRUCT_SIZE(get_attribute_value)) != 0) {
4873                 return (EFAULT);
4874         }
4875         return (0);
4876 }
4877 
4878 /* ARGSUSED */
4879 static int
4880 object_get_size(dev_t dev, caddr_t arg, int mode, int *rval)
4881 {
4882         STRUCT_DECL(crypto_object_get_size, object_get_size);
4883         kcf_provider_desc_t *real_provider;
4884         kcf_req_params_t params;
4885         crypto_session_id_t session_id;
4886         crypto_minor_t *cm;
4887         crypto_session_data_t *sp = NULL;
4888         crypto_object_id_t handle;
4889         size_t size;
4890         int error = 0;
4891         int rv;
4892 
4893         STRUCT_INIT(object_get_size, mode);
4894 
4895         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4896                 cmn_err(CE_WARN, "object_get_size: failed holding minor");
4897                 return (ENXIO);
4898         }
4899 
4900         if (copyin(arg, STRUCT_BUF(object_get_size),
4901             STRUCT_SIZE(object_get_size)) != 0) {
4902                 crypto_release_minor(cm);
4903                 return (EFAULT);
4904         }
4905 
4906         session_id = STRUCT_FGET(object_get_size, gs_session);
4907 
4908         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4909                 goto release_minor;
4910         }
4911 
4912         if ((rv = kcf_get_hardware_provider_nomech(
4913             CRYPTO_OPS_OFFSET(object_ops),
4914             CRYPTO_OBJECT_OFFSET(object_get_size),
4915             sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
4916                 goto release_minor;
4917         }
4918 
4919         handle = STRUCT_FGET(object_get_size, gs_handle);
4920         KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_GET_SIZE,
4921             sp->sd_provider_session->ps_session, handle, NULL, 0, NULL, &size,
4922             NULL, NULL, 0, NULL);
4923 
4924         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
4925         KCF_PROV_REFRELE(real_provider);
4926 
4927         if (rv == CRYPTO_SUCCESS) {
4928                 STRUCT_FSET(object_get_size, gs_size, (ulong_t)size);
4929         }
4930 
4931 release_minor:
4932         crypto_release_minor(cm);
4933         CRYPTO_SESSION_RELE(sp);
4934 
4935         if (error != 0)
4936                 return (error);
4937 
4938         STRUCT_FSET(object_get_size, gs_return_value, rv);
4939         if (copyout(STRUCT_BUF(object_get_size), arg,
4940             STRUCT_SIZE(object_get_size)) != 0) {
4941                 return (EFAULT);
4942         }
4943         return (0);
4944 }
4945 
4946 /* ARGSUSED */
4947 static int
4948 object_set_attribute_value(dev_t dev, caddr_t arg, int mode, int *rval)
4949 {
4950         STRUCT_DECL(crypto_object_set_attribute_value, set_attribute_value);
4951         kcf_provider_desc_t *real_provider;
4952         kcf_req_params_t params;
4953         crypto_object_attribute_t *k_attrs = NULL;
4954         crypto_session_id_t session_id;
4955         crypto_minor_t *cm;
4956         crypto_session_data_t *sp = NULL;
4957         crypto_object_id_t object_handle;
4958         caddr_t sa_attributes;
4959         size_t k_attrs_size;
4960         size_t rctl_bytes = 0;
4961         boolean_t rctl_chk = B_FALSE;
4962         int error = 0;
4963         int rv;
4964         uint_t count;
4965 
4966         STRUCT_INIT(set_attribute_value, mode);
4967 
4968         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4969                 cmn_err(CE_WARN,
4970                     "object_set_attribute_value: failed holding minor");
4971                 return (ENXIO);
4972         }
4973 
4974         if (copyin(arg, STRUCT_BUF(set_attribute_value),
4975             STRUCT_SIZE(set_attribute_value)) != 0) {
4976                 crypto_release_minor(cm);
4977                 return (EFAULT);
4978         }
4979 
4980         count = STRUCT_FGET(set_attribute_value, sa_count);
4981         sa_attributes = STRUCT_FGETP(set_attribute_value, sa_attributes);
4982 
4983         session_id = STRUCT_FGET(set_attribute_value, sa_session);
4984 
4985         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4986                 goto release_minor;
4987         }
4988         if (!copyin_attributes(mode, sp, count, sa_attributes, &k_attrs,
4989             &k_attrs_size, NULL, &rv, &error, &rctl_bytes,
4990             &rctl_chk, B_TRUE)) {
4991                 goto release_minor;
4992         }
4993 
4994         if ((rv = kcf_get_hardware_provider_nomech(
4995             CRYPTO_OPS_OFFSET(object_ops),
4996             CRYPTO_OBJECT_OFFSET(object_set_attribute_value),
4997             sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
4998                 goto release_minor;
4999         }
5000 
5001         object_handle = STRUCT_FGET(set_attribute_value, sa_handle);
5002         KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_SET_ATTRIBUTE_VALUE,
5003             sp->sd_provider_session->ps_session, object_handle, k_attrs, count,
5004             NULL, 0, NULL, NULL, 0, NULL);
5005 
5006         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5007         KCF_PROV_REFRELE(real_provider);
5008 
5009 release_minor:
5010         CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk);
5011         CRYPTO_SESSION_RELE(sp);
5012         crypto_release_minor(cm);
5013 
5014         if (k_attrs != NULL)
5015                 kmem_free(k_attrs, k_attrs_size);
5016 
5017         if (error != 0)
5018                 return (error);
5019 
5020         STRUCT_FSET(set_attribute_value, sa_return_value, rv);
5021         if (copyout(STRUCT_BUF(set_attribute_value), arg,
5022             STRUCT_SIZE(set_attribute_value)) != 0) {
5023                 return (EFAULT);
5024         }
5025         return (0);
5026 }
5027 
5028 /* ARGSUSED */
5029 static int
5030 object_find_init(dev_t dev, caddr_t arg, int mode, int *rval)
5031 {
5032         STRUCT_DECL(crypto_object_find_init, find_init);
5033         kcf_provider_desc_t *real_provider = NULL;
5034         kcf_req_params_t params;
5035         crypto_object_attribute_t *k_attrs = NULL;
5036         crypto_session_id_t session_id;
5037         crypto_minor_t *cm;
5038         crypto_session_data_t *sp = NULL;
5039         caddr_t attributes;
5040         size_t k_attrs_size;
5041         size_t rctl_bytes = 0;
5042         boolean_t rctl_chk = B_FALSE;
5043         int error = 0;
5044         int rv;
5045         uint_t count;
5046         void *cookie;
5047 
5048         STRUCT_INIT(find_init, mode);
5049 
5050         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5051                 cmn_err(CE_WARN, "object_find_init: failed holding minor");
5052                 return (ENXIO);
5053         }
5054 
5055         if (copyin(arg, STRUCT_BUF(find_init), STRUCT_SIZE(find_init)) != 0) {
5056                 crypto_release_minor(cm);
5057                 return (EFAULT);
5058         }
5059 
5060         count = STRUCT_FGET(find_init, fi_count);
5061         attributes = STRUCT_FGETP(find_init, fi_attributes);
5062 
5063         session_id = STRUCT_FGET(find_init, fi_session);
5064 
5065         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5066                 goto release_minor;
5067         }
5068         if (!copyin_attributes(mode, sp, count, attributes, &k_attrs,
5069             &k_attrs_size, NULL, &rv, &error, &rctl_bytes,
5070             &rctl_chk, B_TRUE)) {
5071                 goto release_minor;
5072         }
5073 
5074         if ((rv = kcf_get_hardware_provider_nomech(
5075             CRYPTO_OPS_OFFSET(object_ops),
5076             CRYPTO_OBJECT_OFFSET(object_find_init),
5077             sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
5078                 goto release_minor;
5079         }
5080 
5081         /* check for an active find */
5082         if (sp->sd_find_init_cookie != NULL) {
5083                 rv = CRYPTO_OPERATION_IS_ACTIVE;
5084                 goto release_minor;
5085         }
5086 
5087         KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_FIND_INIT,
5088             sp->sd_provider_session->ps_session, 0, k_attrs, count, NULL, 0,
5089             &cookie, NULL, 0, NULL);
5090 
5091         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5092 
5093         if (rv == CRYPTO_SUCCESS) {
5094                 /*
5095                  * The cookie is allocated by a provider at the start of an
5096                  * object search.  It is freed when the search is terminated
5097                  * by a final operation, or when the session is closed.
5098                  * It contains state information about which object handles
5099                  * have been returned to the caller.
5100                  */
5101                 sp->sd_find_init_cookie = cookie;
5102         }
5103 
5104 release_minor:
5105         CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk);
5106         CRYPTO_SESSION_RELE(sp);
5107         crypto_release_minor(cm);
5108 
5109         if (real_provider != NULL)
5110                 KCF_PROV_REFRELE(real_provider);
5111 
5112         if (k_attrs != NULL)
5113                 kmem_free(k_attrs, k_attrs_size);
5114 
5115         if (error != 0)
5116                 return (error);
5117 
5118         STRUCT_FSET(find_init, fi_return_value, rv);
5119         if (copyout(STRUCT_BUF(find_init), arg, STRUCT_SIZE(find_init)) != 0) {
5120                 return (EFAULT);
5121         }
5122         return (0);
5123 }
5124 
5125 /* ARGSUSED */
5126 static int
5127 object_find_update(dev_t dev, caddr_t arg, int mode, int *rval)
5128 {
5129         STRUCT_DECL(crypto_object_find_update, find_update);
5130         kcf_provider_desc_t *real_provider;
5131         kcf_req_params_t params;
5132         crypto_minor_t *cm;
5133         crypto_session_data_t *sp = NULL;
5134         crypto_object_id_t *buffer = NULL;
5135         crypto_session_id_t session_id;
5136         size_t len, rctl_bytes = 0;
5137         uint_t count, max_count;
5138         int rv, error = 0;
5139         boolean_t rctl_chk = B_FALSE;
5140 
5141         STRUCT_INIT(find_update, mode);
5142 
5143         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5144                 cmn_err(CE_WARN, "object_find_update: failed holding minor");
5145                 return (ENXIO);
5146         }
5147 
5148         if (copyin(arg, STRUCT_BUF(find_update),
5149             STRUCT_SIZE(find_update)) != 0) {
5150                 crypto_release_minor(cm);
5151                 return (EFAULT);
5152         }
5153 
5154         max_count = STRUCT_FGET(find_update, fu_max_count);
5155         if (max_count > CRYPTO_MAX_FIND_COUNT) {
5156                 cmn_err(CE_NOTE, "object_find_update: count greater than %d, "
5157                     "pid = %d", CRYPTO_MAX_FIND_COUNT, curproc->p_pid);
5158                 rv = CRYPTO_ARGUMENTS_BAD;
5159                 goto release_minor;
5160         }
5161         len = max_count * sizeof (crypto_object_id_t);
5162         session_id = STRUCT_FGET(find_update, fu_session);
5163 
5164         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5165                 goto release_minor;
5166         }
5167         if ((rv = CRYPTO_BUFFER_CHECK(sp, len, rctl_chk)) !=
5168             CRYPTO_SUCCESS) {
5169                 goto release_minor;
5170         }
5171         rctl_bytes = len;
5172         buffer = kmem_alloc(len, KM_SLEEP);
5173 
5174         if ((rv = kcf_get_hardware_provider_nomech(
5175             CRYPTO_OPS_OFFSET(object_ops),
5176             CRYPTO_OBJECT_OFFSET(object_find), sp->sd_provider,
5177             &real_provider)) != CRYPTO_SUCCESS) {
5178                 goto release_minor;
5179         }
5180 
5181         KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_FIND,
5182             sp->sd_provider_session->ps_session, 0, NULL, 0, buffer, 0,
5183             NULL, sp->sd_find_init_cookie, max_count, &count);
5184 
5185         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5186         KCF_PROV_REFRELE(real_provider);
5187 
5188         if (rv == CRYPTO_SUCCESS) {
5189                 if (count > max_count) {
5190                         /* bad bad provider */
5191                         rv = CRYPTO_FAILED;
5192                         goto release_minor;
5193                 }
5194                 if (count != 0) {
5195                         /* copyout handles */
5196                         if (copyout(buffer,
5197                             STRUCT_FGETP(find_update, fu_handles),
5198                             count * sizeof (crypto_object_id_t)) != 0) {
5199                                 error = EFAULT;
5200                         }
5201                 }
5202                 STRUCT_FSET(find_update, fu_count, count);
5203         }
5204 
5205 release_minor:
5206         CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk);
5207         CRYPTO_SESSION_RELE(sp);
5208         crypto_release_minor(cm);
5209 
5210         if (buffer != NULL)
5211                 kmem_free(buffer, len);
5212 
5213         if (error != 0)
5214                 return (error);
5215 
5216         STRUCT_FSET(find_update, fu_return_value, rv);
5217         if (copyout(STRUCT_BUF(find_update), arg,
5218             STRUCT_SIZE(find_update)) != 0) {
5219                 return (EFAULT);
5220         }
5221 
5222         return (0);
5223 }
5224 
5225 /*
5226  * Free provider-allocated storage used for find object searches.
5227  */
5228 static int
5229 crypto_free_find_ctx(crypto_session_data_t *sp)
5230 {
5231         kcf_provider_desc_t *real_provider;
5232         kcf_req_params_t params;
5233         int rv;
5234 
5235         if ((rv = kcf_get_hardware_provider_nomech(
5236             CRYPTO_OPS_OFFSET(object_ops),
5237             CRYPTO_OBJECT_OFFSET(object_find_final),
5238             sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
5239                 return (rv);
5240         }
5241 
5242         KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_FIND_FINAL,
5243             sp->sd_provider_session->ps_session, 0, NULL, 0, NULL, 0,
5244             NULL, sp->sd_find_init_cookie, 0, NULL);
5245 
5246         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5247         KCF_PROV_REFRELE(real_provider);
5248         return (rv);
5249 }
5250 
5251 /* ARGSUSED */
5252 static int
5253 object_find_final(dev_t dev, caddr_t arg, int mode, int *rval)
5254 {
5255         STRUCT_DECL(crypto_object_find_final, object_find_final);
5256         crypto_session_id_t session_id;
5257         crypto_minor_t *cm;
5258         crypto_session_data_t *sp;
5259         int error = 0;
5260         int rv;
5261 
5262         STRUCT_INIT(object_find_final, mode);
5263 
5264         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5265                 cmn_err(CE_WARN, "object_find_final: failed holding minor");
5266                 return (ENXIO);
5267         }
5268 
5269         if (copyin(arg, STRUCT_BUF(object_find_final),
5270             STRUCT_SIZE(object_find_final)) != 0) {
5271                 crypto_release_minor(cm);
5272                 return (EFAULT);
5273         }
5274 
5275         session_id = STRUCT_FGET(object_find_final, ff_session);
5276 
5277         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5278                 goto release_minor;
5279         }
5280 
5281         if ((rv = crypto_free_find_ctx(sp)) == CRYPTO_SUCCESS) {
5282                 sp->sd_find_init_cookie = NULL;
5283         }
5284 
5285         CRYPTO_SESSION_RELE(sp);
5286 
5287 release_minor:
5288         crypto_release_minor(cm);
5289 
5290         if (error != 0)
5291                 return (error);
5292 
5293         STRUCT_FSET(object_find_final, ff_return_value, rv);
5294 
5295         if (copyout(STRUCT_BUF(object_find_final), arg,
5296             STRUCT_SIZE(object_find_final)) != 0) {
5297                 return (EFAULT);
5298         }
5299         return (0);
5300 }
5301 
5302 /* ARGSUSED */
5303 static int
5304 object_generate_key(dev_t dev, caddr_t arg, int mode, int *rval)
5305 {
5306         STRUCT_DECL(crypto_object_generate_key, generate_key);
5307         kcf_provider_desc_t *real_provider = NULL;
5308         kcf_req_params_t params;
5309         crypto_mechanism_t mech;
5310         crypto_object_attribute_t *k_attrs = NULL;
5311         crypto_session_id_t session_id;
5312         crypto_minor_t *cm;
5313         crypto_session_data_t *sp = NULL;
5314         crypto_object_id_t key_handle;
5315         caddr_t attributes;
5316         size_t k_attrs_size;
5317         size_t mech_rctl_bytes = 0, key_rctl_bytes = 0;
5318         boolean_t mech_rctl_chk = B_FALSE;
5319         boolean_t key_rctl_chk = B_FALSE;
5320         uint_t count;
5321         int error = 0;
5322         int rv;
5323         boolean_t allocated_by_crypto_module = B_FALSE;
5324 
5325         STRUCT_INIT(generate_key, mode);
5326 
5327         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5328                 cmn_err(CE_WARN, "object_generate_key: failed holding minor");
5329                 return (ENXIO);
5330         }
5331 
5332         if (copyin(arg, STRUCT_BUF(generate_key),
5333             STRUCT_SIZE(generate_key)) != 0) {
5334                 crypto_release_minor(cm);
5335                 return (EFAULT);
5336         }
5337 
5338         session_id = STRUCT_FGET(generate_key, gk_session);
5339 
5340         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5341                 goto release_minor;
5342         }
5343 
5344         bcopy(STRUCT_FADDR(generate_key, gk_mechanism), &mech.cm_type,
5345             sizeof (crypto_mech_type_t));
5346 
5347         if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL,
5348             CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
5349             &real_provider, CRYPTO_FG_GENERATE)) != CRYPTO_SUCCESS) {
5350                 goto release_minor;
5351         }
5352 
5353         rv = crypto_provider_copyin_mech_param(real_provider,
5354             STRUCT_FADDR(generate_key, gk_mechanism), &mech, mode, &error);
5355 
5356         if (rv == CRYPTO_NOT_SUPPORTED) {
5357                 allocated_by_crypto_module = B_TRUE;
5358                 if (!copyin_mech(mode, sp,
5359                     STRUCT_FADDR(generate_key, gk_mechanism),
5360                     &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) {
5361                         goto release_minor;
5362                 }
5363         } else {
5364                 if (rv != CRYPTO_SUCCESS)
5365                         goto release_minor;
5366         }
5367 
5368         count = STRUCT_FGET(generate_key, gk_count);
5369         attributes = STRUCT_FGETP(generate_key, gk_attributes);
5370         if (!copyin_attributes(mode, sp, count, attributes, &k_attrs,
5371             &k_attrs_size, NULL, &rv, &error, &key_rctl_bytes,
5372             &key_rctl_chk, B_TRUE)) {
5373                 goto release_minor;
5374         }
5375 
5376         KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_GENERATE,
5377             sp->sd_provider_session->ps_session, &mech, k_attrs, count,
5378             &key_handle, NULL, 0, NULL, NULL, NULL, 0);
5379 
5380         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5381 
5382         if (rv == CRYPTO_SUCCESS)
5383                 STRUCT_FSET(generate_key, gk_handle, key_handle);
5384 
5385 release_minor:
5386         CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
5387         CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk);
5388 
5389         if (k_attrs != NULL)
5390                 kmem_free(k_attrs, k_attrs_size);
5391 
5392         if (error != 0)
5393                 goto out;
5394 
5395         STRUCT_FSET(generate_key, gk_return_value, rv);
5396         if (copyout(STRUCT_BUF(generate_key), arg,
5397             STRUCT_SIZE(generate_key)) != 0) {
5398                 if (rv == CRYPTO_SUCCESS) {
5399                         KCF_WRAP_OBJECT_OPS_PARAMS(&params,
5400                             KCF_OP_OBJECT_DESTROY,
5401                             sp->sd_provider_session->ps_session, key_handle,
5402                             NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
5403 
5404                         (void) kcf_submit_request(real_provider, NULL,
5405                             NULL, &params, B_FALSE);
5406 
5407                         error = EFAULT;
5408                 }
5409         }
5410 out:
5411         CRYPTO_SESSION_RELE(sp);
5412         crypto_release_minor(cm);
5413 
5414         if (real_provider != NULL) {
5415                 crypto_free_mech(real_provider,
5416                     allocated_by_crypto_module, &mech);
5417                 KCF_PROV_REFRELE(real_provider);
5418         }
5419         return (error);
5420 }
5421 
5422 /* ARGSUSED */
5423 static int
5424 nostore_generate_key(dev_t dev, caddr_t arg, int mode, int *rval)
5425 {
5426         STRUCT_DECL(crypto_nostore_generate_key, generate_key);
5427 #ifdef _LP64
5428         STRUCT_DECL(crypto_object_attribute, oa);
5429 #else
5430         /* LINTED E_FUNC_SET_NOT_USED */
5431         STRUCT_DECL(crypto_object_attribute, oa);
5432 #endif
5433         kcf_provider_desc_t *real_provider = NULL;
5434         kcf_req_params_t params;
5435         crypto_mechanism_t mech;
5436         crypto_object_attribute_t *k_in_attrs = NULL;
5437         crypto_object_attribute_t *k_out_attrs = NULL;
5438         crypto_session_id_t session_id;
5439         crypto_minor_t *cm;
5440         crypto_session_data_t *sp = NULL;
5441         caddr_t in_attributes;
5442         caddr_t out_attributes;
5443         size_t k_in_attrs_size;
5444         size_t k_out_attrs_size;
5445         size_t mech_rctl_bytes = 0;
5446         boolean_t mech_rctl_chk = B_FALSE;
5447         size_t in_key_rctl_bytes = 0, out_key_rctl_bytes = 0;
5448         boolean_t in_key_rctl_chk = B_FALSE;
5449         boolean_t out_key_rctl_chk = B_FALSE;
5450         uint_t in_count;
5451         uint_t out_count;
5452         int error = 0;
5453         int rv;
5454         boolean_t allocated_by_crypto_module = B_FALSE;
5455         caddr_t u_attrs = NULL;
5456 
5457         STRUCT_INIT(generate_key, mode);
5458         STRUCT_INIT(oa, mode);
5459 
5460         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5461                 cmn_err(CE_WARN, "nostore_generate_key: failed holding minor");
5462                 return (ENXIO);
5463         }
5464 
5465         if (copyin(arg, STRUCT_BUF(generate_key),
5466             STRUCT_SIZE(generate_key)) != 0) {
5467                 crypto_release_minor(cm);
5468                 return (EFAULT);
5469         }
5470 
5471         session_id = STRUCT_FGET(generate_key, ngk_session);
5472 
5473         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5474                 goto release_minor;
5475         }
5476 
5477         bcopy(STRUCT_FADDR(generate_key, ngk_mechanism), &mech.cm_type,
5478             sizeof (crypto_mech_type_t));
5479 
5480         if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL,
5481             CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
5482             &real_provider, CRYPTO_FG_GENERATE)) != CRYPTO_SUCCESS) {
5483                 goto release_minor;
5484         }
5485 
5486         rv = crypto_provider_copyin_mech_param(real_provider,
5487             STRUCT_FADDR(generate_key, ngk_mechanism), &mech, mode, &error);
5488 
5489         if (rv == CRYPTO_NOT_SUPPORTED) {
5490                 allocated_by_crypto_module = B_TRUE;
5491                 if (!copyin_mech(mode, sp, STRUCT_FADDR(generate_key,
5492                     ngk_mechanism), &mech, &mech_rctl_bytes,
5493                     &mech_rctl_chk, &rv, &error)) {
5494                         goto release_minor;
5495                 }
5496         } else {
5497                 if (rv != CRYPTO_SUCCESS)
5498                         goto release_minor;
5499         }
5500 
5501         in_count = STRUCT_FGET(generate_key, ngk_in_count);
5502         in_attributes = STRUCT_FGETP(generate_key, ngk_in_attributes);
5503         if (!copyin_attributes(mode, sp, in_count, in_attributes, &k_in_attrs,
5504             &k_in_attrs_size, NULL, &rv, &error, &in_key_rctl_bytes,
5505             &in_key_rctl_chk, B_TRUE)) {
5506                 goto release_minor;
5507         }
5508 
5509         out_count = STRUCT_FGET(generate_key, ngk_out_count);
5510         out_attributes = STRUCT_FGETP(generate_key, ngk_out_attributes);
5511         if (!copyin_attributes(mode, sp, out_count, out_attributes,
5512             &k_out_attrs,
5513             &k_out_attrs_size, &u_attrs, &rv, &error, &out_key_rctl_bytes,
5514             &out_key_rctl_chk, B_FALSE)) {
5515                 goto release_minor;
5516         }
5517 
5518         KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(&params, KCF_OP_KEY_GENERATE,
5519             sp->sd_provider_session->ps_session, &mech, k_in_attrs, in_count,
5520             NULL, 0, NULL, k_out_attrs, out_count, NULL, 0);
5521 
5522         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5523 
5524         if (rv == CRYPTO_SUCCESS) {
5525                 error = copyout_attributes(mode, out_attributes,
5526                     out_count, k_out_attrs, u_attrs);
5527         }
5528 release_minor:
5529         CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
5530         CRYPTO_DECREMENT_RCTL_SESSION(sp, in_key_rctl_bytes, in_key_rctl_chk);
5531         CRYPTO_DECREMENT_RCTL_SESSION(sp, out_key_rctl_bytes,
5532             out_key_rctl_chk);
5533 
5534         if (k_in_attrs != NULL)
5535                 kmem_free(k_in_attrs, k_in_attrs_size);
5536         if (k_out_attrs != NULL) {
5537                 bzero(k_out_attrs, k_out_attrs_size);
5538                 kmem_free(k_out_attrs, k_out_attrs_size);
5539         }
5540 
5541         if (u_attrs != NULL)
5542                 kmem_free(u_attrs, out_count * STRUCT_SIZE(oa));
5543 
5544         if (error != 0)
5545                 goto out;
5546 
5547         STRUCT_FSET(generate_key, ngk_return_value, rv);
5548         if (copyout(STRUCT_BUF(generate_key), arg,
5549             STRUCT_SIZE(generate_key)) != 0) {
5550                 error = EFAULT;
5551         }
5552 out:
5553         CRYPTO_SESSION_RELE(sp);
5554         crypto_release_minor(cm);
5555 
5556         if (real_provider != NULL) {
5557                 crypto_free_mech(real_provider,
5558                     allocated_by_crypto_module, &mech);
5559                 KCF_PROV_REFRELE(real_provider);
5560         }
5561         return (error);
5562 }
5563 
5564 /* ARGSUSED */
5565 static int
5566 object_generate_key_pair(dev_t dev, caddr_t arg, int mode, int *rval)
5567 {
5568         STRUCT_DECL(crypto_object_generate_key_pair, generate_key_pair);
5569         kcf_provider_desc_t *real_provider = NULL;
5570         kcf_req_params_t params;
5571         crypto_mechanism_t mech;
5572         crypto_object_attribute_t *k_pub_attrs = NULL;
5573         crypto_object_attribute_t *k_pri_attrs = NULL;
5574         crypto_session_id_t session_id;
5575         crypto_minor_t *cm;
5576         crypto_session_data_t *sp = NULL;
5577         crypto_object_id_t pub_handle;
5578         crypto_object_id_t pri_handle;
5579         caddr_t pri_attributes;
5580         caddr_t pub_attributes;
5581         size_t k_pub_attrs_size, k_pri_attrs_size;
5582         size_t mech_rctl_bytes = 0;
5583         boolean_t mech_rctl_chk = B_FALSE;
5584         size_t pub_rctl_bytes = 0;
5585         boolean_t pub_rctl_chk = B_FALSE;
5586         size_t pri_rctl_bytes = 0;
5587         boolean_t pri_rctl_chk = B_FALSE;
5588         uint_t pub_count;
5589         uint_t pri_count;
5590         int error = 0;
5591         int rv;
5592         boolean_t allocated_by_crypto_module = B_FALSE;
5593 
5594         STRUCT_INIT(generate_key_pair, mode);
5595 
5596         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5597                 cmn_err(CE_WARN,
5598                     "object_generate_key_pair: failed holding minor");
5599                 return (ENXIO);
5600         }
5601 
5602         if (copyin(arg, STRUCT_BUF(generate_key_pair),
5603             STRUCT_SIZE(generate_key_pair)) != 0) {
5604                 crypto_release_minor(cm);
5605                 return (EFAULT);
5606         }
5607 
5608         session_id = STRUCT_FGET(generate_key_pair, kp_session);
5609 
5610         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5611                 goto release_minor;
5612         }
5613 
5614         bcopy(STRUCT_FADDR(generate_key_pair, kp_mechanism), &mech.cm_type,
5615             sizeof (crypto_mech_type_t));
5616 
5617         if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL,
5618             CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
5619             &real_provider, CRYPTO_FG_GENERATE_KEY_PAIR)) != CRYPTO_SUCCESS) {
5620                 goto release_minor;
5621         }
5622 
5623         rv = crypto_provider_copyin_mech_param(real_provider,
5624             STRUCT_FADDR(generate_key_pair, kp_mechanism), &mech, mode, &error);
5625 
5626         if (rv == CRYPTO_NOT_SUPPORTED) {
5627                 allocated_by_crypto_module = B_TRUE;
5628                 if (!copyin_mech(mode, sp, STRUCT_FADDR(generate_key_pair,
5629                     kp_mechanism), &mech, &mech_rctl_bytes,
5630                     &mech_rctl_chk, &rv, &error)) {
5631                         goto release_minor;
5632                 }
5633         } else {
5634                 if (rv != CRYPTO_SUCCESS)
5635                         goto release_minor;
5636         }
5637 
5638         pub_count = STRUCT_FGET(generate_key_pair, kp_public_count);
5639         pri_count = STRUCT_FGET(generate_key_pair, kp_private_count);
5640 
5641         pub_attributes = STRUCT_FGETP(generate_key_pair, kp_public_attributes);
5642         if (!copyin_attributes(mode, sp, pub_count, pub_attributes,
5643             &k_pub_attrs, &k_pub_attrs_size, NULL, &rv, &error, &pub_rctl_bytes,
5644             &pub_rctl_chk, B_TRUE)) {
5645                 goto release_minor;
5646         }
5647 
5648         pri_attributes = STRUCT_FGETP(generate_key_pair, kp_private_attributes);
5649         if (!copyin_attributes(mode, sp, pri_count, pri_attributes,
5650             &k_pri_attrs, &k_pri_attrs_size, NULL, &rv, &error,
5651             &pri_rctl_bytes, &pri_rctl_chk, B_TRUE)) {
5652                 goto release_minor;
5653         }
5654 
5655         KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_GENERATE_PAIR,
5656             sp->sd_provider_session->ps_session, &mech, k_pub_attrs,
5657             pub_count, &pub_handle, k_pri_attrs, pri_count, &pri_handle,
5658             NULL, NULL, 0);
5659 
5660         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5661 
5662         if (rv == CRYPTO_SUCCESS) {
5663                 STRUCT_FSET(generate_key_pair, kp_public_handle, pub_handle);
5664                 STRUCT_FSET(generate_key_pair, kp_private_handle, pri_handle);
5665         }
5666 
5667 release_minor:
5668         CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
5669         CRYPTO_DECREMENT_RCTL_SESSION(sp, pub_rctl_bytes, pub_rctl_chk);
5670         CRYPTO_DECREMENT_RCTL_SESSION(sp, pri_rctl_bytes, pri_rctl_chk);
5671 
5672         if (k_pub_attrs != NULL)
5673                 kmem_free(k_pub_attrs, k_pub_attrs_size);
5674 
5675         if (k_pri_attrs != NULL)
5676                 kmem_free(k_pri_attrs, k_pri_attrs_size);
5677 
5678         if (error != 0)
5679                 goto out;
5680 
5681         STRUCT_FSET(generate_key_pair, kp_return_value, rv);
5682         if (copyout(STRUCT_BUF(generate_key_pair), arg,
5683             STRUCT_SIZE(generate_key_pair)) != 0) {
5684                 if (rv == CRYPTO_SUCCESS) {
5685                         KCF_WRAP_OBJECT_OPS_PARAMS(&params,
5686                             KCF_OP_OBJECT_DESTROY,
5687                             sp->sd_provider_session->ps_session, pub_handle,
5688                             NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
5689 
5690                         (void) kcf_submit_request(real_provider, NULL,
5691                             NULL, &params, B_FALSE);
5692 
5693                         KCF_WRAP_OBJECT_OPS_PARAMS(&params,
5694                             KCF_OP_OBJECT_DESTROY,
5695                             sp->sd_provider_session->ps_session, pri_handle,
5696                             NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
5697 
5698                         (void) kcf_submit_request(real_provider, NULL,
5699                             NULL, &params, B_FALSE);
5700 
5701                         error = EFAULT;
5702                 }
5703         }
5704 out:
5705         CRYPTO_SESSION_RELE(sp);
5706         crypto_release_minor(cm);
5707 
5708         if (real_provider != NULL) {
5709                 crypto_free_mech(real_provider,
5710                     allocated_by_crypto_module, &mech);
5711                 KCF_PROV_REFRELE(real_provider);
5712         }
5713         return (error);
5714 }
5715 
5716 /* ARGSUSED */
5717 static int
5718 nostore_generate_key_pair(dev_t dev, caddr_t arg, int mode, int *rval)
5719 {
5720         STRUCT_DECL(crypto_nostore_generate_key_pair, generate_key_pair);
5721 #ifdef _LP64
5722         STRUCT_DECL(crypto_object_attribute, oa);
5723 #else
5724         /* LINTED E_FUNC_SET_NOT_USED */
5725         STRUCT_DECL(crypto_object_attribute, oa);
5726 #endif
5727         kcf_provider_desc_t *real_provider = NULL;
5728         kcf_req_params_t params;
5729         crypto_mechanism_t mech;
5730         crypto_object_attribute_t *k_in_pub_attrs = NULL;
5731         crypto_object_attribute_t *k_in_pri_attrs = NULL;
5732         crypto_object_attribute_t *k_out_pub_attrs = NULL;
5733         crypto_object_attribute_t *k_out_pri_attrs = NULL;
5734         crypto_session_id_t session_id;
5735         crypto_minor_t *cm;
5736         crypto_session_data_t *sp = NULL;
5737         caddr_t in_pri_attributes;
5738         caddr_t in_pub_attributes;
5739         caddr_t out_pri_attributes;
5740         caddr_t out_pub_attributes;
5741         size_t k_in_pub_attrs_size, k_in_pri_attrs_size;
5742         size_t k_out_pub_attrs_size, k_out_pri_attrs_size;
5743         size_t mech_rctl_bytes = 0;
5744         boolean_t mech_rctl_chk = B_FALSE;
5745         size_t in_pub_rctl_bytes = 0;
5746         boolean_t in_pub_rctl_chk = B_FALSE;
5747         size_t in_pri_rctl_bytes = 0;
5748         boolean_t in_pri_rctl_chk = B_FALSE;
5749         size_t out_pub_rctl_bytes = 0;
5750         boolean_t out_pub_rctl_chk = B_FALSE;
5751         size_t out_pri_rctl_bytes = 0;
5752         boolean_t out_pri_rctl_chk = B_FALSE;
5753         uint_t in_pub_count;
5754         uint_t in_pri_count;
5755         uint_t out_pub_count;
5756         uint_t out_pri_count;
5757         int error = 0;
5758         int rv;
5759         boolean_t allocated_by_crypto_module = B_FALSE;
5760         caddr_t u_pub_attrs = NULL;
5761         caddr_t u_pri_attrs = NULL;
5762 
5763         STRUCT_INIT(generate_key_pair, mode);
5764         STRUCT_INIT(oa, mode);
5765 
5766         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5767                 cmn_err(CE_WARN,
5768                     "nostore_generate_key_pair: failed holding minor");
5769                 return (ENXIO);
5770         }
5771 
5772         if (copyin(arg, STRUCT_BUF(generate_key_pair),
5773             STRUCT_SIZE(generate_key_pair)) != 0) {
5774                 crypto_release_minor(cm);
5775                 return (EFAULT);
5776         }
5777 
5778         session_id = STRUCT_FGET(generate_key_pair, nkp_session);
5779 
5780         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5781                 goto release_minor;
5782         }
5783 
5784         bcopy(STRUCT_FADDR(generate_key_pair, nkp_mechanism), &mech.cm_type,
5785             sizeof (crypto_mech_type_t));
5786 
5787         if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL,
5788             CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
5789             &real_provider, CRYPTO_FG_GENERATE_KEY_PAIR)) != CRYPTO_SUCCESS) {
5790                 goto release_minor;
5791         }
5792 
5793         rv = crypto_provider_copyin_mech_param(real_provider,
5794             STRUCT_FADDR(generate_key_pair, nkp_mechanism), &mech, mode,
5795             &error);
5796 
5797         if (rv == CRYPTO_NOT_SUPPORTED) {
5798                 allocated_by_crypto_module = B_TRUE;
5799                 if (!copyin_mech(mode, sp, STRUCT_FADDR(generate_key_pair,
5800                     nkp_mechanism), &mech, &mech_rctl_bytes,
5801                     &mech_rctl_chk, &rv, &error)) {
5802                         goto release_minor;
5803                 }
5804         } else {
5805                 if (rv != CRYPTO_SUCCESS)
5806                         goto release_minor;
5807         }
5808 
5809         in_pub_count = STRUCT_FGET(generate_key_pair, nkp_in_public_count);
5810         in_pri_count = STRUCT_FGET(generate_key_pair, nkp_in_private_count);
5811 
5812         in_pub_attributes = STRUCT_FGETP(generate_key_pair,
5813             nkp_in_public_attributes);
5814         if (!copyin_attributes(mode, sp, in_pub_count, in_pub_attributes,
5815             &k_in_pub_attrs, &k_in_pub_attrs_size, NULL, &rv, &error,
5816             &in_pub_rctl_bytes, &in_pub_rctl_chk, B_TRUE)) {
5817                 goto release_minor;
5818         }
5819 
5820         in_pri_attributes = STRUCT_FGETP(generate_key_pair,
5821             nkp_in_private_attributes);
5822         if (!copyin_attributes(mode, sp, in_pri_count, in_pri_attributes,
5823             &k_in_pri_attrs, &k_in_pri_attrs_size, NULL, &rv, &error,
5824             &in_pri_rctl_bytes, &in_pri_rctl_chk, B_TRUE)) {
5825                 goto release_minor;
5826         }
5827 
5828         out_pub_count = STRUCT_FGET(generate_key_pair, nkp_out_public_count);
5829         out_pri_count = STRUCT_FGET(generate_key_pair, nkp_out_private_count);
5830 
5831         out_pub_attributes = STRUCT_FGETP(generate_key_pair,
5832             nkp_out_public_attributes);
5833         if (!copyin_attributes(mode, sp, out_pub_count, out_pub_attributes,
5834             &k_out_pub_attrs, &k_out_pub_attrs_size, &u_pub_attrs, &rv, &error,
5835             &out_pub_rctl_bytes, &out_pub_rctl_chk, B_FALSE)) {
5836                 goto release_minor;
5837         }
5838 
5839         out_pri_attributes = STRUCT_FGETP(generate_key_pair,
5840             nkp_out_private_attributes);
5841         if (!copyin_attributes(mode, sp, out_pri_count, out_pri_attributes,
5842             &k_out_pri_attrs, &k_out_pri_attrs_size, &u_pri_attrs, &rv, &error,
5843             &out_pri_rctl_bytes, &out_pri_rctl_chk, B_FALSE)) {
5844                 goto release_minor;
5845         }
5846 
5847         KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(&params, KCF_OP_KEY_GENERATE_PAIR,
5848             sp->sd_provider_session->ps_session, &mech, k_in_pub_attrs,
5849             in_pub_count, k_in_pri_attrs, in_pri_count, NULL, k_out_pub_attrs,
5850             out_pub_count, k_out_pri_attrs, out_pri_count);
5851 
5852         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
5853 
5854         if (rv == CRYPTO_SUCCESS) {
5855                 error = copyout_attributes(mode, out_pub_attributes,
5856                     out_pub_count, k_out_pub_attrs, u_pub_attrs);
5857                 if (error != CRYPTO_SUCCESS)
5858                         goto release_minor;
5859                 error = copyout_attributes(mode, out_pri_attributes,
5860                     out_pri_count, k_out_pri_attrs, u_pri_attrs);
5861         }
5862 
5863 release_minor:
5864         CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
5865         CRYPTO_DECREMENT_RCTL_SESSION(sp, in_pub_rctl_bytes, in_pub_rctl_chk);
5866         CRYPTO_DECREMENT_RCTL_SESSION(sp, in_pri_rctl_bytes, in_pri_rctl_chk);
5867         CRYPTO_DECREMENT_RCTL_SESSION(sp, out_pub_rctl_bytes,
5868             out_pub_rctl_chk);
5869         CRYPTO_DECREMENT_RCTL_SESSION(sp, out_pri_rctl_bytes,
5870             out_pri_rctl_chk);
5871 
5872         if (k_in_pub_attrs != NULL)
5873                 kmem_free(k_in_pub_attrs, k_in_pub_attrs_size);
5874 
5875         if (k_in_pri_attrs != NULL)
5876                 kmem_free(k_in_pri_attrs, k_in_pri_attrs_size);
5877 
5878         if (k_out_pub_attrs != NULL)
5879                 kmem_free(k_out_pub_attrs, k_out_pub_attrs_size);
5880 
5881         if (k_out_pri_attrs != NULL) {
5882                 bzero(k_out_pri_attrs, k_out_pri_attrs_size);
5883                 kmem_free(k_out_pri_attrs, k_out_pri_attrs_size);
5884         }
5885 
5886         if (u_pub_attrs != NULL)
5887                 kmem_free(u_pub_attrs, out_pub_count * STRUCT_SIZE(oa));
5888 
5889         if (u_pri_attrs != NULL)
5890                 kmem_free(u_pri_attrs, out_pri_count * STRUCT_SIZE(oa));
5891 
5892         if (error != 0)
5893                 goto out;
5894 
5895         STRUCT_FSET(generate_key_pair, nkp_return_value, rv);
5896         if (copyout(STRUCT_BUF(generate_key_pair), arg,
5897             STRUCT_SIZE(generate_key_pair)) != 0) {
5898                 error = EFAULT;
5899         }
5900 out:
5901         CRYPTO_SESSION_RELE(sp);
5902         crypto_release_minor(cm);
5903 
5904         if (real_provider != NULL) {
5905                 crypto_free_mech(real_provider,
5906                     allocated_by_crypto_module, &mech);
5907                 KCF_PROV_REFRELE(real_provider);
5908         }
5909         return (error);
5910 }
5911 
5912 /* ARGSUSED */
5913 static int
5914 object_wrap_key(dev_t dev, caddr_t arg, int mode, int *rval)
5915 {
5916         STRUCT_DECL(crypto_object_wrap_key, wrap_key);
5917         kcf_provider_desc_t *real_provider = NULL;
5918         kcf_req_params_t params;
5919         crypto_mechanism_t mech;
5920         crypto_key_t key;
5921         crypto_session_id_t session_id;
5922         crypto_minor_t *cm;
5923         crypto_session_data_t *sp = NULL;
5924         crypto_object_id_t handle;
5925         size_t mech_rctl_bytes = 0, key_rctl_bytes = 0;
5926         boolean_t mech_rctl_chk = B_FALSE;
5927         boolean_t key_rctl_chk = B_FALSE;
5928         size_t wrapped_key_rctl_bytes = 0;
5929         boolean_t wrapped_key_rctl_chk = B_FALSE;
5930         size_t wrapped_key_len, new_wrapped_key_len;
5931         uchar_t *wrapped_key = NULL;
5932         char *wrapped_key_buffer;
5933         int error = 0;
5934         int rv;
5935         boolean_t allocated_by_crypto_module = B_FALSE;
5936 
5937         STRUCT_INIT(wrap_key, mode);
5938 
5939         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5940                 cmn_err(CE_WARN, "object_wrap_key: failed holding minor");
5941                 return (ENXIO);
5942         }
5943 
5944         if (copyin(arg, STRUCT_BUF(wrap_key), STRUCT_SIZE(wrap_key)) != 0) {
5945                 crypto_release_minor(cm);
5946                 return (EFAULT);
5947         }
5948 
5949         bzero(&key, sizeof (crypto_key_t));
5950 
5951         session_id = STRUCT_FGET(wrap_key, wk_session);
5952 
5953         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5954                 goto out;
5955         }
5956 
5957         bcopy(STRUCT_FADDR(wrap_key, wk_mechanism), &mech.cm_type,
5958             sizeof (crypto_mech_type_t));
5959 
5960         /* We need the key length for provider selection so copy it in now. */
5961         if (!copyin_key(mode, sp, STRUCT_FADDR(wrap_key, wk_wrapping_key), &key,
5962             &key_rctl_bytes, &key_rctl_chk, &rv, &error)) {
5963                 goto out;
5964         }
5965 
5966         wrapped_key_len = STRUCT_FGET(wrap_key, wk_wrapped_key_len);
5967 
5968         if ((rv = kcf_get_hardware_provider(mech.cm_type, &key,
5969             CRYPTO_MECH_INVALID, NULL,  sp->sd_provider,
5970             &real_provider, CRYPTO_FG_WRAP)) != CRYPTO_SUCCESS) {
5971                 goto out;
5972         }
5973 
5974         rv = crypto_provider_copyin_mech_param(real_provider,
5975             STRUCT_FADDR(wrap_key, wk_mechanism), &mech, mode, &error);
5976 
5977         if (rv == CRYPTO_NOT_SUPPORTED) {
5978                 allocated_by_crypto_module = B_TRUE;
5979                 if (!copyin_mech(mode, sp, STRUCT_FADDR(wrap_key, wk_mechanism),
5980                     &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) {
5981                         goto out;
5982                 }
5983         } else {
5984                 if (rv != CRYPTO_SUCCESS)
5985                         goto out;
5986         }
5987 
5988         /*
5989          * Don't allocate output buffer unless both buffer pointer and
5990          * buffer length are not NULL or 0 (length).
5991          */
5992         wrapped_key_buffer = STRUCT_FGETP(wrap_key, wk_wrapped_key);
5993         if (wrapped_key_buffer == NULL || wrapped_key_len == 0) {
5994                 wrapped_key_len = 0;
5995         }
5996 
5997         if (wrapped_key_len > crypto_max_buffer_len) {
5998                 cmn_err(CE_NOTE, "object_wrap_key: buffer greater than %ld "
5999                     "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
6000                 rv = CRYPTO_ARGUMENTS_BAD;
6001                 goto out;
6002         }
6003 
6004         if ((rv = CRYPTO_BUFFER_CHECK(sp, wrapped_key_len,
6005             wrapped_key_rctl_chk)) != CRYPTO_SUCCESS) {
6006                 goto out;
6007         }
6008 
6009         /* new_wrapped_key_len can be modified by the provider */
6010         wrapped_key_rctl_bytes = new_wrapped_key_len = wrapped_key_len;
6011         wrapped_key = kmem_alloc(wrapped_key_len, KM_SLEEP);
6012 
6013         handle = STRUCT_FGET(wrap_key, wk_object_handle);
6014         KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_WRAP,
6015             sp->sd_provider_session->ps_session, &mech, NULL, 0, &handle,
6016             NULL, 0, NULL, &key, wrapped_key, &new_wrapped_key_len);
6017 
6018         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
6019 
6020         if (rv == CRYPTO_SUCCESS) {
6021                 if (wrapped_key_len != 0 && copyout(wrapped_key,
6022                     wrapped_key_buffer, new_wrapped_key_len) != 0) {
6023                         error = EFAULT;
6024                 }
6025                 STRUCT_FSET(wrap_key, wk_wrapped_key_len,
6026                     (ulong_t)new_wrapped_key_len);
6027         }
6028 
6029         if (rv == CRYPTO_BUFFER_TOO_SMALL) {
6030                 /*
6031                  * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
6032                  * of section 11.2 of the pkcs11 spec. We catch it here and
6033                  * provide the correct pkcs11 return value.
6034                  */
6035                 if (STRUCT_FGETP(wrap_key, wk_wrapped_key) == NULL)
6036                         rv = CRYPTO_SUCCESS;
6037                 STRUCT_FSET(wrap_key, wk_wrapped_key_len,
6038                     (ulong_t)new_wrapped_key_len);
6039         }
6040 
6041 out:
6042         CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
6043         CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk);
6044         CRYPTO_DECREMENT_RCTL_SESSION(sp, wrapped_key_rctl_bytes,
6045             wrapped_key_rctl_chk);
6046         CRYPTO_SESSION_RELE(sp);
6047 
6048         crypto_release_minor(cm);
6049 
6050         if (real_provider != NULL) {
6051                 crypto_free_mech(real_provider,
6052                     allocated_by_crypto_module, &mech);
6053                 KCF_PROV_REFRELE(real_provider);
6054         }
6055 
6056         if (wrapped_key != NULL)
6057                 kmem_free(wrapped_key, wrapped_key_len);
6058 
6059         free_crypto_key(&key);
6060 
6061         if (error != 0)
6062                 return (error);
6063 
6064         STRUCT_FSET(wrap_key, wk_return_value, rv);
6065         if (copyout(STRUCT_BUF(wrap_key), arg, STRUCT_SIZE(wrap_key)) != 0) {
6066                 return (EFAULT);
6067         }
6068         return (0);
6069 }
6070 
6071 /* ARGSUSED */
6072 static int
6073 object_unwrap_key(dev_t dev, caddr_t arg, int mode, int *rval)
6074 {
6075         STRUCT_DECL(crypto_object_unwrap_key, unwrap_key);
6076         kcf_provider_desc_t *real_provider = NULL;
6077         kcf_req_params_t params;
6078         crypto_mechanism_t mech;
6079         crypto_key_t unwrapping_key;
6080         crypto_session_id_t session_id;
6081         crypto_minor_t *cm;
6082         crypto_session_data_t *sp = NULL;
6083         crypto_object_id_t handle;
6084         crypto_object_attribute_t *k_attrs = NULL;
6085         size_t k_attrs_size;
6086         size_t mech_rctl_bytes = 0, unwrapping_key_rctl_bytes = 0;
6087         boolean_t mech_rctl_chk = B_FALSE;
6088         boolean_t unwrapping_key_rctl_chk = B_FALSE;
6089         size_t wrapped_key_rctl_bytes = 0, k_attrs_rctl_bytes = 0;
6090         boolean_t wrapped_key_rctl_chk = B_FALSE;
6091         boolean_t k_attrs_rctl_chk = B_FALSE;
6092         size_t wrapped_key_len;
6093         uchar_t *wrapped_key = NULL;
6094         int error = 0;
6095         int rv;
6096         uint_t count;
6097         caddr_t uk_attributes;
6098         boolean_t allocated_by_crypto_module = B_FALSE;
6099 
6100         STRUCT_INIT(unwrap_key, mode);
6101 
6102         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
6103                 cmn_err(CE_WARN, "object_unwrap_key: failed holding minor");
6104                 return (ENXIO);
6105         }
6106 
6107         if (copyin(arg, STRUCT_BUF(unwrap_key), STRUCT_SIZE(unwrap_key)) != 0) {
6108                 crypto_release_minor(cm);
6109                 return (EFAULT);
6110         }
6111 
6112         bzero(&unwrapping_key, sizeof (unwrapping_key));
6113 
6114         session_id = STRUCT_FGET(unwrap_key, uk_session);
6115 
6116         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
6117                 goto release_minor;
6118         }
6119 
6120         bcopy(STRUCT_FADDR(unwrap_key, uk_mechanism), &mech.cm_type,
6121             sizeof (crypto_mech_type_t));
6122 
6123         /* We need the key length for provider selection so copy it in now. */
6124         if (!copyin_key(mode, sp, STRUCT_FADDR(unwrap_key, uk_unwrapping_key),
6125             &unwrapping_key, &unwrapping_key_rctl_bytes,
6126             &unwrapping_key_rctl_chk, &rv, &error)) {
6127                 goto release_minor;
6128         }
6129 
6130         if ((rv = kcf_get_hardware_provider(mech.cm_type, &unwrapping_key,
6131             CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
6132             &real_provider, CRYPTO_FG_UNWRAP)) != CRYPTO_SUCCESS) {
6133                 goto release_minor;
6134         }
6135 
6136         rv = crypto_provider_copyin_mech_param(real_provider,
6137             STRUCT_FADDR(unwrap_key, uk_mechanism), &mech, mode, &error);
6138 
6139         if (rv == CRYPTO_NOT_SUPPORTED) {
6140                 allocated_by_crypto_module = B_TRUE;
6141                 if (!copyin_mech(mode, sp,
6142                     STRUCT_FADDR(unwrap_key, uk_mechanism),
6143                     &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) {
6144                         goto release_minor;
6145                 }
6146         } else {
6147                 if (rv != CRYPTO_SUCCESS)
6148                         goto release_minor;
6149         }
6150 
6151         count = STRUCT_FGET(unwrap_key, uk_count);
6152         uk_attributes = STRUCT_FGETP(unwrap_key, uk_attributes);
6153         if (!copyin_attributes(mode, sp, count, uk_attributes, &k_attrs,
6154             &k_attrs_size, NULL, &rv, &error, &k_attrs_rctl_bytes,
6155             &k_attrs_rctl_chk, B_TRUE)) {
6156                 goto release_minor;
6157         }
6158 
6159         wrapped_key_len = STRUCT_FGET(unwrap_key, uk_wrapped_key_len);
6160         if (wrapped_key_len > crypto_max_buffer_len) {
6161                 cmn_err(CE_NOTE, "object_unwrap_key: buffer greater than %ld "
6162                     "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
6163                 rv = CRYPTO_ARGUMENTS_BAD;
6164                 goto release_minor;
6165         }
6166 
6167         if ((rv = CRYPTO_BUFFER_CHECK(sp, wrapped_key_len,
6168             wrapped_key_rctl_chk)) != CRYPTO_SUCCESS) {
6169                 goto release_minor;
6170         }
6171         wrapped_key_rctl_bytes = wrapped_key_len;
6172         wrapped_key = kmem_alloc(wrapped_key_len, KM_SLEEP);
6173 
6174         if (wrapped_key_len != 0 && copyin(STRUCT_FGETP(unwrap_key,
6175             uk_wrapped_key), wrapped_key, wrapped_key_len) != 0) {
6176                 error = EFAULT;
6177                 goto release_minor;
6178         }
6179 
6180         /* wrapped_key_len is not modified by the unwrap operation */
6181         KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_UNWRAP,
6182             sp->sd_provider_session->ps_session, &mech, k_attrs, count, &handle,
6183             NULL, 0, NULL, &unwrapping_key, wrapped_key, &wrapped_key_len);
6184 
6185         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
6186 
6187         if (rv == CRYPTO_SUCCESS)
6188                 STRUCT_FSET(unwrap_key, uk_object_handle, handle);
6189 
6190 release_minor:
6191         CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
6192         CRYPTO_DECREMENT_RCTL_SESSION(sp, unwrapping_key_rctl_bytes,
6193             unwrapping_key_rctl_chk);
6194         CRYPTO_DECREMENT_RCTL_SESSION(sp, wrapped_key_rctl_bytes,
6195             wrapped_key_rctl_chk);
6196         CRYPTO_DECREMENT_RCTL_SESSION(sp, k_attrs_rctl_bytes,
6197             k_attrs_rctl_chk);
6198 
6199         if (k_attrs != NULL)
6200                 kmem_free(k_attrs, k_attrs_size);
6201 
6202         if (wrapped_key != NULL)
6203                 kmem_free(wrapped_key, wrapped_key_len);
6204 
6205         free_crypto_key(&unwrapping_key);
6206 
6207         if (error != 0)
6208                 goto out;
6209 
6210         STRUCT_FSET(unwrap_key, uk_return_value, rv);
6211         if (copyout(STRUCT_BUF(unwrap_key), arg,
6212             STRUCT_SIZE(unwrap_key)) != 0) {
6213                 if (rv == CRYPTO_SUCCESS) {
6214                         KCF_WRAP_OBJECT_OPS_PARAMS(&params,
6215                             KCF_OP_OBJECT_DESTROY,
6216                             sp->sd_provider_session->ps_session, handle,
6217                             NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
6218 
6219                         (void) kcf_submit_request(real_provider, NULL,
6220                             NULL, &params, B_FALSE);
6221 
6222                         error = EFAULT;
6223                 }
6224         }
6225 out:
6226         CRYPTO_SESSION_RELE(sp);
6227         crypto_release_minor(cm);
6228 
6229         if (real_provider != NULL) {
6230                 crypto_free_mech(real_provider,
6231                     allocated_by_crypto_module, &mech);
6232                 KCF_PROV_REFRELE(real_provider);
6233         }
6234 
6235         return (error);
6236 }
6237 
6238 /* ARGSUSED */
6239 static int
6240 object_derive_key(dev_t dev, caddr_t arg, int mode, int *rval)
6241 {
6242         STRUCT_DECL(crypto_derive_key, derive_key);
6243         kcf_provider_desc_t *real_provider = NULL;
6244         kcf_req_params_t params;
6245         crypto_object_attribute_t *k_attrs = NULL;
6246         crypto_mechanism_t mech;
6247         crypto_key_t base_key;
6248         crypto_session_id_t session_id;
6249         crypto_minor_t *cm;
6250         crypto_session_data_t *sp = NULL;
6251         crypto_object_id_t handle;
6252         size_t k_attrs_size;
6253         size_t key_rctl_bytes = 0, mech_rctl_bytes = 0;
6254         boolean_t mech_rctl_chk = B_FALSE;
6255         boolean_t key_rctl_chk = B_FALSE;
6256         size_t attributes_rctl_bytes = 0;
6257         boolean_t attributes_rctl_chk = B_FALSE;
6258         caddr_t attributes;
6259         uint_t count;
6260         int error = 0;
6261         int rv;
6262         boolean_t allocated_by_crypto_module = B_FALSE;
6263         boolean_t please_destroy_object = B_FALSE;
6264 
6265         STRUCT_INIT(derive_key, mode);
6266 
6267         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
6268                 cmn_err(CE_WARN, "object_derive_key: failed holding minor");
6269                 return (ENXIO);
6270         }
6271 
6272         if (copyin(arg, STRUCT_BUF(derive_key), STRUCT_SIZE(derive_key)) != 0) {
6273                 crypto_release_minor(cm);
6274                 return (EFAULT);
6275         }
6276 
6277         bzero(&base_key, sizeof (base_key));
6278 
6279         session_id = STRUCT_FGET(derive_key, dk_session);
6280 
6281         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
6282                 goto release_minor;
6283         }
6284 
6285         bcopy(STRUCT_FADDR(derive_key, dk_mechanism), &mech.cm_type,
6286             sizeof (crypto_mech_type_t));
6287 
6288         /* We need the key length for provider selection so copy it in now. */
6289         if (!copyin_key(mode, sp, STRUCT_FADDR(derive_key, dk_base_key),
6290             &base_key, &key_rctl_bytes, &key_rctl_chk, &rv, &error)) {
6291                 goto release_minor;
6292         }
6293 
6294         if ((rv = kcf_get_hardware_provider(mech.cm_type, &base_key,
6295             CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
6296             &real_provider, CRYPTO_FG_DERIVE)) != CRYPTO_SUCCESS) {
6297                 goto release_minor;
6298         }
6299 
6300         rv = crypto_provider_copyin_mech_param(real_provider,
6301             STRUCT_FADDR(derive_key, dk_mechanism), &mech, mode, &error);
6302 
6303         if (rv == CRYPTO_NOT_SUPPORTED) {
6304                 allocated_by_crypto_module = B_TRUE;
6305                 if (!copyin_mech(mode, sp,
6306                     STRUCT_FADDR(derive_key, dk_mechanism),
6307                     &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) {
6308                         goto release_minor;
6309                 }
6310         } else {
6311                 if (rv != CRYPTO_SUCCESS)
6312                         goto release_minor;
6313         }
6314 
6315         count = STRUCT_FGET(derive_key, dk_count);
6316 
6317         attributes = STRUCT_FGETP(derive_key, dk_attributes);
6318         if (!copyin_attributes(mode, sp, count, attributes, &k_attrs,
6319             &k_attrs_size, NULL, &rv, &error,
6320             &attributes_rctl_bytes, &attributes_rctl_chk, B_TRUE)) {
6321                 goto release_minor;
6322         }
6323 
6324         KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_DERIVE,
6325             sp->sd_provider_session->ps_session, &mech, k_attrs, count,
6326             &handle, NULL, 0, NULL, &base_key, NULL, NULL);
6327 
6328         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
6329 
6330         if (rv == CRYPTO_SUCCESS) {
6331                 STRUCT_FSET(derive_key, dk_object_handle, handle);
6332 
6333                 rv = crypto_provider_copyout_mech_param(real_provider,
6334                     &mech, STRUCT_FADDR(derive_key, dk_mechanism),
6335                     mode, &error);
6336 
6337                 if (rv == CRYPTO_NOT_SUPPORTED) {
6338                         rv = CRYPTO_SUCCESS;
6339                         goto release_minor;
6340                 }
6341 
6342                 if (rv != CRYPTO_SUCCESS)
6343                         please_destroy_object = B_TRUE;
6344         }
6345 
6346 release_minor:
6347         CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
6348         CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk);
6349         CRYPTO_DECREMENT_RCTL_SESSION(sp, attributes_rctl_bytes,
6350             attributes_rctl_chk);
6351 
6352         if (k_attrs != NULL)
6353                 kmem_free(k_attrs, k_attrs_size);
6354 
6355         free_crypto_key(&base_key);
6356 
6357         if (error != 0)
6358                 goto out;
6359 
6360         STRUCT_FSET(derive_key, dk_return_value, rv);
6361         if (copyout(STRUCT_BUF(derive_key), arg,
6362             STRUCT_SIZE(derive_key)) != 0) {
6363                 if (rv == CRYPTO_SUCCESS) {
6364                         please_destroy_object = B_TRUE;
6365                         error = EFAULT;
6366                 }
6367         }
6368 out:
6369         if (please_destroy_object) {
6370                 KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_DESTROY,
6371                     sp->sd_provider_session->ps_session, handle,
6372                     NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
6373 
6374                 (void) kcf_submit_request(real_provider, NULL,
6375                     NULL, &params, B_FALSE);
6376         }
6377 
6378         CRYPTO_SESSION_RELE(sp);
6379         crypto_release_minor(cm);
6380 
6381         if (real_provider != NULL) {
6382                 crypto_free_mech(real_provider,
6383                     allocated_by_crypto_module, &mech);
6384                 KCF_PROV_REFRELE(real_provider);
6385         }
6386         return (error);
6387 }
6388 
6389 /* ARGSUSED */
6390 static int
6391 nostore_derive_key(dev_t dev, caddr_t arg, int mode, int *rval)
6392 {
6393         STRUCT_DECL(crypto_nostore_derive_key, derive_key);
6394 #ifdef _LP64
6395         STRUCT_DECL(crypto_object_attribute, oa);
6396 #else
6397         /* LINTED E_FUNC_SET_NOT_USED */
6398         STRUCT_DECL(crypto_object_attribute, oa);
6399 #endif
6400         kcf_provider_desc_t *real_provider = NULL;
6401         kcf_req_params_t params;
6402         crypto_object_attribute_t *k_in_attrs = NULL;
6403         crypto_object_attribute_t *k_out_attrs = NULL;
6404         crypto_mechanism_t mech;
6405         crypto_key_t base_key;
6406         crypto_session_id_t session_id;
6407         crypto_minor_t *cm;
6408         crypto_session_data_t *sp = NULL;
6409         size_t k_in_attrs_size, k_out_attrs_size;
6410         size_t key_rctl_bytes = 0, mech_rctl_bytes = 0;
6411         boolean_t mech_rctl_chk = B_FALSE;
6412         boolean_t key_rctl_chk = B_FALSE;
6413         size_t in_attributes_rctl_bytes = 0;
6414         size_t out_attributes_rctl_bytes = 0;
6415         boolean_t in_attributes_rctl_chk = B_FALSE;
6416         boolean_t out_attributes_rctl_chk = B_FALSE;
6417         caddr_t in_attributes, out_attributes;
6418         uint_t in_count, out_count;
6419         int error = 0;
6420         int rv;
6421         boolean_t allocated_by_crypto_module = B_FALSE;
6422         caddr_t u_attrs = NULL;
6423 
6424         STRUCT_INIT(derive_key, mode);
6425         STRUCT_INIT(oa, mode);
6426 
6427         if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
6428                 cmn_err(CE_WARN, "nostore_derive_key: failed holding minor");
6429                 return (ENXIO);
6430         }
6431 
6432         if (copyin(arg, STRUCT_BUF(derive_key), STRUCT_SIZE(derive_key)) != 0) {
6433                 crypto_release_minor(cm);
6434                 return (EFAULT);
6435         }
6436 
6437         bzero(&base_key, sizeof (base_key));
6438 
6439         session_id = STRUCT_FGET(derive_key, ndk_session);
6440 
6441         if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
6442                 goto release_minor;
6443         }
6444 
6445         bcopy(STRUCT_FADDR(derive_key, ndk_mechanism), &mech.cm_type,
6446             sizeof (crypto_mech_type_t));
6447 
6448         /* We need the key length for provider selection so copy it in now. */
6449         if (!copyin_key(mode, sp, STRUCT_FADDR(derive_key, ndk_base_key),
6450             &base_key, &key_rctl_bytes, &key_rctl_chk, &rv, &error)) {
6451                 goto release_minor;
6452         }
6453 
6454         if ((rv = kcf_get_hardware_provider(mech.cm_type, &base_key,
6455             CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
6456             &real_provider, CRYPTO_FG_DERIVE)) != CRYPTO_SUCCESS) {
6457                 goto release_minor;
6458         }
6459 
6460         rv = crypto_provider_copyin_mech_param(real_provider,
6461             STRUCT_FADDR(derive_key, ndk_mechanism), &mech, mode, &error);
6462 
6463         if (rv == CRYPTO_NOT_SUPPORTED) {
6464                 allocated_by_crypto_module = B_TRUE;
6465                 if (!copyin_mech(mode, sp,
6466                     STRUCT_FADDR(derive_key, ndk_mechanism),
6467                     &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) {
6468                         goto release_minor;
6469                 }
6470         } else {
6471                 if (rv != CRYPTO_SUCCESS)
6472                         goto release_minor;
6473         }
6474 
6475         in_count = STRUCT_FGET(derive_key, ndk_in_count);
6476         out_count = STRUCT_FGET(derive_key, ndk_out_count);
6477 
6478         in_attributes = STRUCT_FGETP(derive_key, ndk_in_attributes);
6479         if (!copyin_attributes(mode, sp, in_count, in_attributes, &k_in_attrs,
6480             &k_in_attrs_size, NULL, &rv, &error, &in_attributes_rctl_bytes,
6481             &in_attributes_rctl_chk, B_TRUE)) {
6482                 goto release_minor;
6483         }
6484 
6485         out_attributes = STRUCT_FGETP(derive_key, ndk_out_attributes);
6486         if (!copyin_attributes(mode, sp, out_count, out_attributes,
6487             &k_out_attrs, &k_out_attrs_size, &u_attrs, &rv, &error,
6488             &out_attributes_rctl_bytes,
6489             &out_attributes_rctl_chk, B_FALSE)) {
6490                 goto release_minor;
6491         }
6492 
6493         KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(&params, KCF_OP_KEY_DERIVE,
6494             sp->sd_provider_session->ps_session, &mech, k_in_attrs, in_count,
6495             NULL, 0, &base_key, k_out_attrs, out_count, NULL, 0);
6496 
6497         rv = kcf_submit_request(real_provider, NULL, NULL, &params, B_FALSE);
6498 
6499         if (rv == CRYPTO_SUCCESS) {
6500                 rv = crypto_provider_copyout_mech_param(real_provider,
6501                     &mech, STRUCT_FADDR(derive_key, ndk_mechanism),
6502                     mode, &error);
6503 
6504                 if (rv == CRYPTO_NOT_SUPPORTED) {
6505                         rv = CRYPTO_SUCCESS;
6506                 }
6507                 /* copyout the derived secret */
6508                 if (copyout_attributes(mode, out_attributes, out_count,
6509                     k_out_attrs, u_attrs) != 0)
6510                         error = EFAULT;
6511         }
6512 
6513 release_minor:
6514         CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
6515         CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk);
6516         CRYPTO_DECREMENT_RCTL_SESSION(sp, in_attributes_rctl_bytes,
6517             in_attributes_rctl_chk);
6518         CRYPTO_DECREMENT_RCTL_SESSION(sp, out_attributes_rctl_bytes,
6519             out_attributes_rctl_chk);
6520 
6521         if (k_in_attrs != NULL)
6522                 kmem_free(k_in_attrs, k_in_attrs_size);
6523         if (k_out_attrs != NULL) {
6524                 bzero(k_out_attrs, k_out_attrs_size);
6525                 kmem_free(k_out_attrs, k_out_attrs_size);
6526         }
6527 
6528         if (u_attrs != NULL)
6529                 kmem_free(u_attrs, out_count * STRUCT_SIZE(oa));
6530 
6531         free_crypto_key(&base_key);
6532 
6533         if (error != 0)
6534                 goto out;
6535 
6536         STRUCT_FSET(derive_key, ndk_return_value, rv);
6537         if (copyout(STRUCT_BUF(derive_key), arg,
6538             STRUCT_SIZE(derive_key)) != 0) {
6539                 error = EFAULT;
6540         }
6541 out:
6542         CRYPTO_SESSION_RELE(sp);
6543         crypto_release_minor(cm);
6544 
6545         if (real_provider != NULL) {
6546                 crypto_free_mech(real_provider,
6547                     allocated_by_crypto_module, &mech);
6548                 KCF_PROV_REFRELE(real_provider);
6549         }
6550         return (error);
6551 }
6552 
6553 /* ARGSUSED */
6554 static int
6555 crypto_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c,
6556     int *rval)
6557 {
6558 #define ARG     ((caddr_t)arg)
6559 
6560         switch (cmd) {
6561         case CRYPTO_GET_FUNCTION_LIST:
6562                 return (get_function_list(dev, ARG, mode, rval));
6563 
6564         case CRYPTO_GET_MECHANISM_NUMBER:
6565                 return (get_mechanism_number(dev, ARG, mode, rval));
6566 
6567         case CRYPTO_GET_MECHANISM_LIST:
6568                 return (get_mechanism_list(dev, ARG, mode, rval));
6569 
6570         case CRYPTO_GET_ALL_MECHANISM_INFO:
6571                 return (get_all_mechanism_info(dev, ARG, mode, rval));
6572 
6573         case CRYPTO_GET_PROVIDER_LIST:
6574                 return (get_provider_list(dev, ARG, mode, rval));
6575 
6576         case CRYPTO_GET_PROVIDER_INFO:
6577                 return (get_provider_info(dev, ARG, mode, rval));
6578 
6579         case CRYPTO_GET_PROVIDER_MECHANISMS:
6580                 return (get_provider_mechanisms(dev, ARG, mode, rval));
6581 
6582         case CRYPTO_GET_PROVIDER_MECHANISM_INFO:
6583                 return (get_provider_mechanism_info(dev, ARG, mode, rval));
6584 
6585         case CRYPTO_OPEN_SESSION:
6586                 return (open_session(dev, ARG, mode, rval));
6587 
6588         case CRYPTO_CLOSE_SESSION:
6589                 return (close_session(dev, ARG, mode, rval));
6590 
6591         case CRYPTO_ENCRYPT_INIT:
6592                 return (encrypt_init(dev, ARG, mode, rval));
6593 
6594         case CRYPTO_DECRYPT_INIT:
6595                 return (decrypt_init(dev, ARG, mode, rval));
6596 
6597         case CRYPTO_ENCRYPT:
6598                 return (encrypt(dev, ARG, mode, rval));
6599 
6600         case CRYPTO_DECRYPT:
6601                 return (decrypt(dev, ARG, mode, rval));
6602 
6603         case CRYPTO_ENCRYPT_UPDATE:
6604                 return (encrypt_update(dev, ARG, mode, rval));
6605 
6606         case CRYPTO_DECRYPT_UPDATE:
6607                 return (decrypt_update(dev, ARG, mode, rval));
6608 
6609         case CRYPTO_ENCRYPT_FINAL:
6610                 return (encrypt_final(dev, ARG, mode, rval));
6611 
6612         case CRYPTO_DECRYPT_FINAL:
6613                 return (decrypt_final(dev, ARG, mode, rval));
6614 
6615         case CRYPTO_DIGEST_INIT:
6616                 return (digest_init(dev, ARG, mode, rval));
6617 
6618         case CRYPTO_DIGEST:
6619                 return (digest(dev, ARG, mode, rval));
6620 
6621         case CRYPTO_DIGEST_UPDATE:
6622                 return (digest_update(dev, ARG, mode, rval));
6623 
6624         case CRYPTO_DIGEST_KEY:
6625                 return (digest_key(dev, ARG, mode, rval));
6626 
6627         case CRYPTO_DIGEST_FINAL:
6628                 return (digest_final(dev, ARG, mode, rval));
6629 
6630         case CRYPTO_SIGN_INIT:
6631                 return (sign_init(dev, ARG, mode, rval));
6632 
6633         case CRYPTO_SIGN:
6634                 return (sign(dev, ARG, mode, rval));
6635 
6636         case CRYPTO_SIGN_UPDATE:
6637                 return (sign_update(dev, ARG, mode, rval));
6638 
6639         case CRYPTO_SIGN_FINAL:
6640                 return (sign_final(dev, ARG, mode, rval));
6641 
6642         case CRYPTO_SIGN_RECOVER_INIT:
6643                 return (sign_recover_init(dev, ARG, mode, rval));
6644 
6645         case CRYPTO_SIGN_RECOVER:
6646                 return (sign_recover(dev, ARG, mode, rval));
6647 
6648         case CRYPTO_VERIFY_INIT:
6649                 return (verify_init(dev, ARG, mode, rval));
6650 
6651         case CRYPTO_VERIFY:
6652                 return (verify(dev, ARG, mode, rval));
6653 
6654         case CRYPTO_VERIFY_UPDATE:
6655                 return (verify_update(dev, ARG, mode, rval));
6656 
6657         case CRYPTO_VERIFY_FINAL:
6658                 return (verify_final(dev, ARG, mode, rval));
6659 
6660         case CRYPTO_VERIFY_RECOVER_INIT:
6661                 return (verify_recover_init(dev, ARG, mode, rval));
6662 
6663         case CRYPTO_VERIFY_RECOVER:
6664                 return (verify_recover(dev, ARG, mode, rval));
6665 
6666         case CRYPTO_SET_PIN:
6667                 return (set_pin(dev, ARG, mode, rval));
6668 
6669         case CRYPTO_LOGIN:
6670                 return (login(dev, ARG, mode, rval));
6671 
6672         case CRYPTO_LOGOUT:
6673                 return (logout(dev, ARG, mode, rval));
6674 
6675         case CRYPTO_SEED_RANDOM:
6676                 return (seed_random(dev, ARG, mode, rval));
6677 
6678         case CRYPTO_GENERATE_RANDOM:
6679                 return (generate_random(dev, ARG, mode, rval));
6680 
6681         case CRYPTO_OBJECT_CREATE:
6682                 return (object_create(dev, ARG, mode, rval));
6683 
6684         case CRYPTO_OBJECT_COPY:
6685                 return (object_copy(dev, ARG, mode, rval));
6686 
6687         case CRYPTO_OBJECT_DESTROY:
6688                 return (object_destroy(dev, ARG, mode, rval));
6689 
6690         case CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE:
6691                 return (object_get_attribute_value(dev, ARG, mode, rval));
6692 
6693         case CRYPTO_OBJECT_GET_SIZE:
6694                 return (object_get_size(dev, ARG, mode, rval));
6695 
6696         case CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE:
6697                 return (object_set_attribute_value(dev, ARG, mode, rval));
6698 
6699         case CRYPTO_OBJECT_FIND_INIT:
6700                 return (object_find_init(dev, ARG, mode, rval));
6701 
6702         case CRYPTO_OBJECT_FIND_UPDATE:
6703                 return (object_find_update(dev, ARG, mode, rval));
6704 
6705         case CRYPTO_OBJECT_FIND_FINAL:
6706                 return (object_find_final(dev, ARG, mode, rval));
6707 
6708         case CRYPTO_GENERATE_KEY:
6709                 return (object_generate_key(dev, ARG, mode, rval));
6710 
6711         case CRYPTO_GENERATE_KEY_PAIR:
6712                 return (object_generate_key_pair(dev, ARG, mode, rval));
6713 
6714         case CRYPTO_WRAP_KEY:
6715                 return (object_wrap_key(dev, ARG, mode, rval));
6716 
6717         case CRYPTO_UNWRAP_KEY:
6718                 return (object_unwrap_key(dev, ARG, mode, rval));
6719 
6720         case CRYPTO_DERIVE_KEY:
6721                 return (object_derive_key(dev, ARG, mode, rval));
6722 
6723         case CRYPTO_NOSTORE_GENERATE_KEY:
6724                 return (nostore_generate_key(dev, ARG, mode, rval));
6725 
6726         case CRYPTO_NOSTORE_GENERATE_KEY_PAIR:
6727                 return (nostore_generate_key_pair(dev, ARG, mode, rval));
6728 
6729         case CRYPTO_NOSTORE_DERIVE_KEY:
6730                 return (nostore_derive_key(dev, ARG, mode, rval));
6731         }
6732         return (EINVAL);
6733 }
6734 
6735 /*
6736  * Check for the project.max-crypto-memory resource control.
6737  */
6738 static int
6739 crypto_buffer_check(size_t need)
6740 {
6741         kproject_t *kpj;
6742 
6743         if (need == 0)
6744                 return (CRYPTO_SUCCESS);
6745 
6746         mutex_enter(&curproc->p_lock);
6747         kpj = curproc->p_task->tk_proj;
6748         mutex_enter(&(kpj->kpj_data.kpd_crypto_lock));
6749 
6750         if (kpj->kpj_data.kpd_crypto_mem + need >
6751             kpj->kpj_data.kpd_crypto_mem_ctl) {
6752                 if (rctl_test(rc_project_crypto_mem,
6753                     kpj->kpj_rctls, curproc, need, 0) & RCT_DENY) {
6754                         mutex_exit(&(kpj->kpj_data.kpd_crypto_lock));
6755                         mutex_exit(&curproc->p_lock);
6756                         return (CRYPTO_HOST_MEMORY);
6757                 }
6758         }
6759 
6760         kpj->kpj_data.kpd_crypto_mem += need;
6761         mutex_exit(&(kpj->kpj_data.kpd_crypto_lock));
6762 
6763         curproc->p_crypto_mem += need;
6764         mutex_exit(&curproc->p_lock);
6765 
6766         return (CRYPTO_SUCCESS);
6767 }