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