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 STRUCT_FSET(version, cv_major, ei->ei_firmware_version.cv_major); 1349 STRUCT_FSET(version, cv_minor, ei->ei_firmware_version.cv_minor); 1350 bcopy(STRUCT_BUF(version), STRUCT_FADDR(pd, pd_firmware_version), 1351 STRUCT_SIZE(version)); 1352 bcopy(ei->ei_time, STRUCT_FGET(pd, pd_time), CRYPTO_EXT_SIZE_TIME); 1353 bcopy(STRUCT_BUF(pd), out, STRUCT_SIZE(pd)); 1354 } 1355 1356 /* 1357 * Utility routine to construct a crypto_provider_ext_info structure. Some 1358 * of the fields are constructed from information in the provider structure. 1359 * The rest of the fields have default values. We need to do this for 1360 * providers which do not support crypto_provider_management_ops routines. 1361 */ 1362 static void 1363 fabricate_ext_info(kcf_provider_desc_t *provider, 1364 crypto_provider_ext_info_t *ei) 1365 { 1366 /* empty label */ 1367 (void) memset(ei->ei_label, ' ', CRYPTO_EXT_SIZE_LABEL); 1368 1369 (void) memset(ei->ei_manufacturerID, ' ', CRYPTO_EXT_SIZE_MANUF); 1370 (void) strncpy((char *)ei->ei_manufacturerID, "Unknown", 7); 1371 1372 (void) memset(ei->ei_model, ' ', CRYPTO_EXT_SIZE_MODEL); 1373 (void) strncpy((char *)ei->ei_model, "Unknown", 7); 1374 1375 (void) memset(ei->ei_serial_number, ' ', CRYPTO_EXT_SIZE_SERIAL); 1376 (void) strncpy((char *)ei->ei_serial_number, "Unknown", 7); 1377 1378 if (KCF_PROV_RANDOM_OPS(provider) != NULL) 1379 ei->ei_flags |= CRYPTO_EXTF_RNG; 1380 if (KCF_PROV_DUAL_OPS(provider) != NULL) 1381 ei->ei_flags |= CRYPTO_EXTF_DUAL_CRYPTO_OPERATIONS; 1382 1383 ei->ei_max_session_count = CRYPTO_UNAVAILABLE_INFO; 1384 ei->ei_max_pin_len = 0; 1385 ei->ei_min_pin_len = 0; 1386 ei->ei_total_public_memory = CRYPTO_UNAVAILABLE_INFO; 1387 ei->ei_free_public_memory = CRYPTO_UNAVAILABLE_INFO; 1388 ei->ei_total_private_memory = CRYPTO_UNAVAILABLE_INFO; 1389 ei->ei_free_private_memory = CRYPTO_UNAVAILABLE_INFO; 1390 ei->ei_hardware_version.cv_major = 1; 1391 ei->ei_hardware_version.cv_minor = 0; 1392 ei->ei_firmware_version.cv_major = 1; 1393 ei->ei_firmware_version.cv_minor = 0; 1394 } 1395 1396 /* ARGSUSED */ 1397 static int 1398 get_provider_info(dev_t dev, caddr_t arg, int mode, int *rval) 1399 { 1400 STRUCT_DECL(crypto_get_provider_info, get_info); 1401 crypto_minor_t *cm; 1402 crypto_provider_id_t provider_id; 1403 kcf_provider_desc_t *provider, *real_provider; 1404 crypto_provider_ext_info_t *ext_info = NULL; 1405 size_t need; 1406 int error = 0; 1407 int rv; 1408 kcf_req_params_t params; 1409 1410 STRUCT_INIT(get_info, mode); 1411 1412 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 1413 cmn_err(CE_WARN, "get_provider_info: failed holding minor"); 1414 return (ENXIO); 1415 } 1416 1417 if (copyin(arg, STRUCT_BUF(get_info), STRUCT_SIZE(get_info)) != 0) { 1418 crypto_release_minor(cm); 1419 return (EFAULT); 1420 } 1421 1422 need = sizeof (crypto_provider_ext_info_t); 1423 if ((rv = crypto_buffer_check(need)) != CRYPTO_SUCCESS) { 1424 need = 0; 1425 goto release_minor; 1426 } 1427 1428 /* initialize provider_array */ 1429 if (cm->cm_provider_array == NULL) { 1430 rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST); 1431 if (rv != CRYPTO_SUCCESS) { 1432 goto release_minor; 1433 } 1434 } 1435 1436 ext_info = kmem_zalloc(need, KM_SLEEP); 1437 1438 provider_id = STRUCT_FGET(get_info, gi_provider_id); 1439 mutex_enter(&cm->cm_lock); 1440 /* index must be less than count of providers */ 1441 if (provider_id >= cm->cm_provider_count) { 1442 mutex_exit(&cm->cm_lock); 1443 rv = CRYPTO_ARGUMENTS_BAD; 1444 goto release_minor; 1445 } 1446 1447 ASSERT(cm->cm_provider_array != NULL); 1448 provider = cm->cm_provider_array[provider_id]; 1449 KCF_PROV_REFHOLD(provider); 1450 mutex_exit(&cm->cm_lock); 1451 1452 (void) kcf_get_hardware_provider_nomech( 1453 CRYPTO_OPS_OFFSET(provider_ops), CRYPTO_PROVIDER_OFFSET(ext_info), 1454 CHECK_RESTRICT_FALSE, provider, &real_provider); 1455 1456 if (real_provider != NULL) { 1457 ASSERT(real_provider == provider || 1458 provider->pd_prov_type == CRYPTO_LOGICAL_PROVIDER); 1459 KCF_WRAP_PROVMGMT_OPS_PARAMS(¶ms, KCF_OP_MGMT_EXTINFO, 1460 0, NULL, 0, NULL, 0, NULL, ext_info, provider); 1461 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, 1462 B_FALSE); 1463 ASSERT(rv != CRYPTO_NOT_SUPPORTED); 1464 KCF_PROV_REFRELE(real_provider); 1465 } else { 1466 /* do the best we can */ 1467 fabricate_ext_info(provider, ext_info); 1468 rv = CRYPTO_SUCCESS; 1469 } 1470 KCF_PROV_REFRELE(provider); 1471 1472 if (rv == CRYPTO_SUCCESS) { 1473 ext_to_provider_data(mode, provider, ext_info, 1474 STRUCT_FADDR(get_info, gi_provider_data)); 1475 } 1476 1477 release_minor: 1478 CRYPTO_DECREMENT_RCTL(need); 1479 crypto_release_minor(cm); 1480 1481 if (ext_info != NULL) 1482 kmem_free(ext_info, sizeof (crypto_provider_ext_info_t)); 1483 1484 if (error != 0) 1485 return (error); 1486 1487 STRUCT_FSET(get_info, gi_return_value, rv); 1488 if (copyout(STRUCT_BUF(get_info), arg, STRUCT_SIZE(get_info)) != 0) { 1489 return (EFAULT); 1490 } 1491 return (0); 1492 } 1493 1494 /* 1495 * This ioctl returns an array of crypto_mech_name_t entries. 1496 * This is how consumers learn which mechanisms are permitted 1497 * by a provider. 1498 */ 1499 /* ARGSUSED */ 1500 static int 1501 get_provider_mechanisms(dev_t dev, caddr_t arg, int mode, int *rval) 1502 { 1503 STRUCT_DECL(crypto_get_provider_mechanisms, get_mechanisms); 1504 crypto_mech_name_t *entries; 1505 crypto_minor_t *cm; 1506 size_t copyout_size; 1507 uint_t req_count; 1508 uint_t count; 1509 ulong_t offset; 1510 int err; 1511 1512 STRUCT_INIT(get_mechanisms, mode); 1513 1514 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 1515 cmn_err(CE_WARN, 1516 "get_provider_mechanisms: failed holding minor"); 1517 return (ENXIO); 1518 } 1519 1520 if (copyin(arg, STRUCT_BUF(get_mechanisms), 1521 STRUCT_SIZE(get_mechanisms)) != 0) { 1522 crypto_release_minor(cm); 1523 return (EFAULT); 1524 } 1525 1526 /* get array of mechanisms from the core module */ 1527 if ((err = crypto_get_provider_mechanisms(cm, 1528 STRUCT_FGET(get_mechanisms, pm_provider_id), 1529 &count, &entries)) != 0) { 1530 crypto_release_minor(cm); 1531 STRUCT_FSET(get_mechanisms, pm_return_value, err); 1532 if (copyout(STRUCT_BUF(get_mechanisms), arg, 1533 STRUCT_SIZE(get_mechanisms)) != 0) { 1534 return (EFAULT); 1535 } 1536 return (0); 1537 } 1538 crypto_release_minor(cm); 1539 /* Number of mechs caller thinks we have */ 1540 req_count = STRUCT_FGET(get_mechanisms, pm_count); 1541 1542 /* Check if caller is just requesting a count of mechanisms */ 1543 if (req_count == 0) { 1544 STRUCT_FSET(get_mechanisms, pm_count, count); 1545 STRUCT_FSET(get_mechanisms, pm_return_value, CRYPTO_SUCCESS); 1546 1547 crypto_free_mech_list(entries, count); 1548 if (copyout(STRUCT_BUF(get_mechanisms), arg, 1549 STRUCT_SIZE(get_mechanisms)) != 0) { 1550 return (EFAULT); 1551 } 1552 return (0); 1553 } 1554 1555 /* check if buffer is too small */ 1556 if (count > req_count) { 1557 STRUCT_FSET(get_mechanisms, pm_count, count); 1558 STRUCT_FSET(get_mechanisms, pm_return_value, 1559 CRYPTO_BUFFER_TOO_SMALL); 1560 crypto_free_mech_list(entries, count); 1561 if (copyout(STRUCT_BUF(get_mechanisms), arg, 1562 STRUCT_SIZE(get_mechanisms)) != 0) { 1563 return (EFAULT); 1564 } 1565 return (0); 1566 } 1567 1568 STRUCT_FSET(get_mechanisms, pm_count, count); 1569 STRUCT_FSET(get_mechanisms, pm_return_value, CRYPTO_SUCCESS); 1570 1571 copyout_size = count * sizeof (crypto_mech_name_t); 1572 1573 /* copyout the first stuff */ 1574 if (copyout(STRUCT_BUF(get_mechanisms), arg, 1575 STRUCT_SIZE(get_mechanisms)) != 0) { 1576 crypto_free_mech_list(entries, count); 1577 return (EFAULT); 1578 } 1579 1580 if (count == 0) { 1581 return (0); 1582 } 1583 1584 /* copyout entries */ 1585 offset = (ulong_t)STRUCT_FADDR(get_mechanisms, pm_list); 1586 offset -= (ulong_t)STRUCT_BUF(get_mechanisms); 1587 if (copyout(entries, arg + offset, copyout_size) != 0) { 1588 crypto_free_mech_list(entries, count); 1589 return (EFAULT); 1590 } 1591 1592 crypto_free_mech_list(entries, count); 1593 return (0); 1594 } 1595 1596 /* 1597 * This ioctl returns information about a provider's mechanism. 1598 */ 1599 /* ARGSUSED */ 1600 static int 1601 get_provider_mechanism_info(dev_t dev, caddr_t arg, int mode, int *rval) 1602 { 1603 crypto_get_provider_mechanism_info_t mechanism_info; 1604 crypto_minor_t *cm; 1605 kcf_provider_desc_t *pd; 1606 crypto_mech_info_t *mi = NULL; 1607 int rv = CRYPTO_SUCCESS; 1608 int i; 1609 1610 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 1611 cmn_err(CE_WARN, 1612 "get_provider_mechanism_info: failed holding minor"); 1613 return (ENXIO); 1614 } 1615 1616 if (copyin(arg, &mechanism_info, sizeof (mechanism_info)) != 0) { 1617 crypto_release_minor(cm); 1618 return (EFAULT); 1619 } 1620 1621 /* initialize provider table */ 1622 if (cm->cm_provider_array == NULL) { 1623 rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST); 1624 if (rv != CRYPTO_SUCCESS) { 1625 mutex_enter(&cm->cm_lock); 1626 goto fail; 1627 } 1628 } 1629 1630 /* 1631 * Provider ID must be less than the count of providers 1632 * obtained by calling get_provider_list(). 1633 */ 1634 mutex_enter(&cm->cm_lock); 1635 if (mechanism_info.mi_provider_id >= cm->cm_provider_count) { 1636 rv = CRYPTO_ARGUMENTS_BAD; 1637 goto fail; 1638 } 1639 1640 pd = cm->cm_provider_array[mechanism_info.mi_provider_id]; 1641 1642 for (i = 0; i < pd->pd_mech_list_count; i++) { 1643 if (strncmp(pd->pd_mechanisms[i].cm_mech_name, 1644 mechanism_info.mi_mechanism_name, 1645 CRYPTO_MAX_MECH_NAME) == 0) { 1646 mi = &pd->pd_mechanisms[i]; 1647 } 1648 } 1649 1650 if (mi == NULL) { 1651 rv = CRYPTO_ARGUMENTS_BAD; 1652 goto fail; 1653 } 1654 1655 mechanism_info.mi_min_key_size = mi->cm_min_key_length; 1656 mechanism_info.mi_max_key_size = mi->cm_max_key_length; 1657 mechanism_info.mi_flags = mi->cm_func_group_mask; 1658 1659 fail: 1660 mutex_exit(&cm->cm_lock); 1661 crypto_release_minor(cm); 1662 mechanism_info.mi_return_value = rv; 1663 if (copyout(&mechanism_info, arg, sizeof (mechanism_info)) != 0) { 1664 return (EFAULT); 1665 } 1666 1667 return (0); 1668 } 1669 1670 /* 1671 * Every open of /dev/crypto multiplexes all PKCS#11 sessions across 1672 * a single session to each provider. Calls to open and close session 1673 * are not made to providers that do not support sessions. For these 1674 * providers, a session number of 0 is passed during subsequent operations, 1675 * and it is ignored by the provider. 1676 */ 1677 static int 1678 crypto_get_provider_session(crypto_minor_t *cm, 1679 crypto_provider_id_t provider_index, crypto_provider_session_t **output_ps) 1680 { 1681 kcf_provider_desc_t *pd, *real_provider; 1682 kcf_req_params_t params; 1683 crypto_provider_session_t *ps, *new_ps; 1684 crypto_session_id_t provider_session_id = 0; 1685 int rv; 1686 1687 ASSERT(MUTEX_HELD(&cm->cm_lock)); 1688 1689 /* pd may be a logical provider */ 1690 pd = cm->cm_provider_array[provider_index]; 1691 1692 again: 1693 /* 1694 * Check if there is already a session to the provider. 1695 * Sessions may be to a logical provider or a real provider. 1696 */ 1697 for (ps = cm->cm_provider_session; ps != NULL; ps = ps->ps_next) { 1698 if (ps->ps_provider == pd) 1699 break; 1700 } 1701 1702 /* found existing session */ 1703 if (ps != NULL) { 1704 ps->ps_refcnt++; 1705 *output_ps = ps; 1706 return (CRYPTO_SUCCESS); 1707 } 1708 mutex_exit(&cm->cm_lock); 1709 1710 /* find a hardware provider that supports session ops */ 1711 (void) kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(session_ops), 1712 CRYPTO_SESSION_OFFSET(session_open), CHECK_RESTRICT_FALSE, 1713 pd, &real_provider); 1714 1715 if (real_provider != NULL) { 1716 ASSERT(real_provider == pd || 1717 pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER); 1718 /* open session to provider */ 1719 KCF_WRAP_SESSION_OPS_PARAMS(¶ms, KCF_OP_SESSION_OPEN, 1720 &provider_session_id, 0, CRYPTO_USER, NULL, 0, pd); 1721 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, 1722 B_FALSE); 1723 if (rv != CRYPTO_SUCCESS) { 1724 mutex_enter(&cm->cm_lock); 1725 KCF_PROV_REFRELE(real_provider); 1726 return (rv); 1727 } 1728 } 1729 1730 /* allocate crypto_provider_session structure */ 1731 new_ps = kmem_zalloc(sizeof (crypto_provider_session_t), KM_SLEEP); 1732 1733 /* 1734 * Check if someone opened a session to the provider 1735 * while we dropped the lock. 1736 */ 1737 mutex_enter(&cm->cm_lock); 1738 for (ps = cm->cm_provider_session; ps != NULL; ps = ps->ps_next) { 1739 if (ps->ps_provider == pd) { 1740 mutex_exit(&cm->cm_lock); 1741 kmem_free(new_ps, sizeof (crypto_provider_session_t)); 1742 if (real_provider != NULL) { 1743 KCF_WRAP_SESSION_OPS_PARAMS(¶ms, 1744 KCF_OP_SESSION_CLOSE, NULL, 1745 provider_session_id, CRYPTO_USER, NULL, 0, 1746 pd); 1747 (void) kcf_submit_request(real_provider, NULL, 1748 NULL, ¶ms, B_FALSE); 1749 KCF_PROV_REFRELE(real_provider); 1750 } 1751 mutex_enter(&cm->cm_lock); 1752 goto again; 1753 1754 } 1755 } 1756 1757 /* increment refcnt and attach to crypto_minor structure */ 1758 new_ps->ps_session = provider_session_id; 1759 new_ps->ps_refcnt = 1; 1760 KCF_PROV_REFHOLD(pd); 1761 new_ps->ps_provider = pd; 1762 if (real_provider != NULL) { 1763 new_ps->ps_real_provider = real_provider; 1764 } 1765 new_ps->ps_next = cm->cm_provider_session; 1766 cm->cm_provider_session = new_ps; 1767 1768 *output_ps = new_ps; 1769 return (CRYPTO_SUCCESS); 1770 } 1771 1772 /* 1773 * Release a provider session. 1774 * If the reference count goes to zero, then close the session 1775 * to the provider. 1776 */ 1777 static void 1778 crypto_release_provider_session(crypto_minor_t *cm, 1779 crypto_provider_session_t *provider_session) 1780 { 1781 kcf_req_params_t params; 1782 crypto_provider_session_t *ps = NULL, **prev; 1783 1784 ASSERT(MUTEX_HELD(&cm->cm_lock)); 1785 1786 /* verify that provider_session is valid */ 1787 for (ps = cm->cm_provider_session, prev = &cm->cm_provider_session; 1788 ps != NULL; prev = &ps->ps_next, ps = ps->ps_next) { 1789 if (ps == provider_session) { 1790 break; 1791 } 1792 } 1793 1794 if (ps == NULL) 1795 return; 1796 1797 ps->ps_refcnt--; 1798 1799 if (ps->ps_refcnt > 0) 1800 return; 1801 1802 if (ps->ps_real_provider != NULL) { 1803 /* close session with provider */ 1804 KCF_WRAP_SESSION_OPS_PARAMS(¶ms, KCF_OP_SESSION_CLOSE, NULL, 1805 ps->ps_session, CRYPTO_USER, NULL, 0, ps->ps_provider); 1806 (void) kcf_submit_request(ps->ps_real_provider, 1807 NULL, NULL, ¶ms, B_FALSE); 1808 KCF_PROV_REFRELE(ps->ps_real_provider); 1809 } 1810 KCF_PROV_REFRELE(ps->ps_provider); 1811 *prev = ps->ps_next; 1812 kmem_free(ps, sizeof (*ps)); 1813 } 1814 1815 static int 1816 grow_session_table(crypto_minor_t *cm) 1817 { 1818 crypto_session_data_t **session_table; 1819 crypto_session_data_t **new; 1820 uint_t session_table_count; 1821 uint_t need; 1822 size_t current_allocation; 1823 size_t new_allocation; 1824 int rv; 1825 1826 ASSERT(MUTEX_HELD(&cm->cm_lock)); 1827 1828 session_table_count = cm->cm_session_table_count; 1829 session_table = cm->cm_session_table; 1830 need = session_table_count + CRYPTO_SESSION_CHUNK; 1831 1832 current_allocation = session_table_count * sizeof (void *); 1833 new_allocation = need * sizeof (void *); 1834 1835 /* 1836 * Memory needed to grow the session table is checked 1837 * against the project.max-crypto-memory resource control. 1838 */ 1839 if ((rv = crypto_buffer_check(new_allocation - current_allocation)) != 1840 CRYPTO_SUCCESS) { 1841 return (rv); 1842 } 1843 1844 /* drop lock while we allocate memory */ 1845 mutex_exit(&cm->cm_lock); 1846 new = kmem_zalloc(new_allocation, KM_SLEEP); 1847 mutex_enter(&cm->cm_lock); 1848 1849 /* check if another thread increased the table size */ 1850 if (session_table_count != cm->cm_session_table_count) { 1851 kmem_free(new, new_allocation); 1852 return (CRYPTO_SUCCESS); 1853 } 1854 1855 bcopy(session_table, new, current_allocation); 1856 kmem_free(session_table, current_allocation); 1857 cm->cm_session_table = new; 1858 cm->cm_session_table_count += CRYPTO_SESSION_CHUNK; 1859 1860 return (CRYPTO_SUCCESS); 1861 } 1862 1863 /* 1864 * Find unused entry in session table and return it's index. 1865 * Initialize session table entry. 1866 */ 1867 /* ARGSUSED */ 1868 static int 1869 crypto_open_session(dev_t dev, uint_t flags, crypto_session_id_t *session_index, 1870 crypto_provider_id_t provider_id) 1871 { 1872 crypto_session_data_t **session_table; 1873 crypto_session_data_t *sp; 1874 crypto_minor_t *cm; 1875 uint_t session_table_count; 1876 uint_t i; 1877 int rv; 1878 crypto_provider_session_t *ps; 1879 kcf_provider_desc_t *provider; 1880 1881 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 1882 cmn_err(CE_WARN, "crypto_open_session: failed holding minor"); 1883 return (CRYPTO_FAILED); 1884 } 1885 1886 /* initialize provider_array */ 1887 if (cm->cm_provider_array == NULL) { 1888 rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST); 1889 if (rv != 0) { 1890 crypto_release_minor(cm); 1891 return (rv); 1892 } 1893 } 1894 1895 mutex_enter(&cm->cm_lock); 1896 /* index must be less than count of providers */ 1897 if (provider_id >= cm->cm_provider_count) { 1898 mutex_exit(&cm->cm_lock); 1899 crypto_release_minor(cm); 1900 return (CRYPTO_INVALID_PROVIDER_ID); 1901 } 1902 ASSERT(cm->cm_provider_array != NULL); 1903 1904 rv = crypto_get_provider_session(cm, provider_id, &ps); 1905 if (rv != CRYPTO_SUCCESS) { 1906 mutex_exit(&cm->cm_lock); 1907 crypto_release_minor(cm); 1908 return (rv); 1909 } 1910 provider = cm->cm_provider_array[provider_id]; 1911 1912 again: 1913 session_table_count = cm->cm_session_table_count; 1914 session_table = cm->cm_session_table; 1915 1916 /* session handles start with 1 */ 1917 for (i = 1; i < session_table_count; i++) { 1918 if (session_table[i] == NULL) 1919 break; 1920 } 1921 1922 if (i == session_table_count || session_table_count == 0) { 1923 if ((rv = grow_session_table(cm)) != CRYPTO_SUCCESS) { 1924 crypto_release_provider_session(cm, ps); 1925 mutex_exit(&cm->cm_lock); 1926 crypto_release_minor(cm); 1927 return (rv); 1928 } 1929 goto again; 1930 } 1931 1932 sp = kmem_cache_alloc(crypto_session_cache, KM_SLEEP); 1933 sp->sd_flags = 0; 1934 sp->sd_find_init_cookie = NULL; 1935 sp->sd_digest_ctx = NULL; 1936 sp->sd_encr_ctx = NULL; 1937 sp->sd_decr_ctx = NULL; 1938 sp->sd_sign_ctx = NULL; 1939 sp->sd_verify_ctx = NULL; 1940 sp->sd_sign_recover_ctx = NULL; 1941 sp->sd_verify_recover_ctx = NULL; 1942 mutex_init(&sp->sd_lock, NULL, MUTEX_DRIVER, NULL); 1943 cv_init(&sp->sd_cv, NULL, CV_DRIVER, NULL); 1944 KCF_PROV_REFHOLD(provider); 1945 sp->sd_provider = provider; 1946 sp->sd_provider_session = ps; 1947 1948 /* See the comment for CRYPTO_PRE_APPROVED_LIMIT. */ 1949 if ((rv = crypto_buffer_check(crypto_pre_approved_limit)) != 1950 CRYPTO_SUCCESS) { 1951 sp->sd_pre_approved_amount = 0; 1952 } else { 1953 sp->sd_pre_approved_amount = crypto_pre_approved_limit; 1954 } 1955 1956 cm->cm_session_table[i] = sp; 1957 mutex_exit(&cm->cm_lock); 1958 crypto_release_minor(cm); 1959 *session_index = i; 1960 1961 return (CRYPTO_SUCCESS); 1962 } 1963 1964 /* 1965 * Close a session. 1966 */ 1967 static int 1968 crypto_close_session(dev_t dev, crypto_session_id_t session_index) 1969 { 1970 crypto_session_data_t **session_table; 1971 crypto_session_data_t *sp; 1972 crypto_minor_t *cm; 1973 1974 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 1975 cmn_err(CE_WARN, "crypto_close_session: failed holding minor"); 1976 return (CRYPTO_FAILED); 1977 } 1978 1979 mutex_enter(&cm->cm_lock); 1980 session_table = cm->cm_session_table; 1981 1982 if ((session_index) == 0 || 1983 (session_index >= cm->cm_session_table_count)) { 1984 mutex_exit(&cm->cm_lock); 1985 crypto_release_minor(cm); 1986 return (CRYPTO_SESSION_HANDLE_INVALID); 1987 } 1988 1989 sp = session_table[session_index]; 1990 if (sp == NULL) { 1991 mutex_exit(&cm->cm_lock); 1992 crypto_release_minor(cm); 1993 return (CRYPTO_SESSION_HANDLE_INVALID); 1994 } 1995 /* 1996 * If session is in use, free it when the thread 1997 * finishes with the session. 1998 */ 1999 mutex_enter(&sp->sd_lock); 2000 if (sp->sd_flags & CRYPTO_SESSION_IS_BUSY) { 2001 sp->sd_flags |= CRYPTO_SESSION_IS_CLOSED; 2002 mutex_exit(&sp->sd_lock); 2003 } else { 2004 ASSERT(sp->sd_pre_approved_amount == 0 || 2005 sp->sd_pre_approved_amount == crypto_pre_approved_limit); 2006 CRYPTO_DECREMENT_RCTL(sp->sd_pre_approved_amount); 2007 2008 if (sp->sd_find_init_cookie != NULL) { 2009 (void) crypto_free_find_ctx(sp); 2010 } 2011 2012 crypto_release_provider_session(cm, sp->sd_provider_session); 2013 KCF_PROV_REFRELE(sp->sd_provider); 2014 CRYPTO_CANCEL_ALL_CTX(sp); 2015 mutex_destroy(&sp->sd_lock); 2016 cv_destroy(&sp->sd_cv); 2017 kmem_cache_free(crypto_session_cache, sp); 2018 session_table[session_index] = NULL; 2019 } 2020 2021 mutex_exit(&cm->cm_lock); 2022 crypto_release_minor(cm); 2023 2024 return (CRYPTO_SUCCESS); 2025 } 2026 2027 /* 2028 * This ioctl opens a session and returns the session ID in os_session. 2029 */ 2030 /* ARGSUSED */ 2031 static int 2032 open_session(dev_t dev, caddr_t arg, int mode, int *rval) 2033 { 2034 crypto_open_session_t open_session; 2035 crypto_session_id_t session; 2036 int rv; 2037 2038 if (copyin(arg, &open_session, sizeof (open_session)) != 0) 2039 return (EFAULT); 2040 2041 rv = crypto_open_session(dev, open_session.os_flags, 2042 &session, open_session.os_provider_id); 2043 if (rv != CRYPTO_SUCCESS) { 2044 open_session.os_return_value = rv; 2045 if (copyout(&open_session, arg, sizeof (open_session)) != 0) { 2046 return (EFAULT); 2047 } 2048 return (0); 2049 } 2050 2051 open_session.os_session = session; 2052 open_session.os_return_value = CRYPTO_SUCCESS; 2053 2054 if (copyout(&open_session, arg, sizeof (open_session)) != 0) { 2055 return (EFAULT); 2056 } 2057 return (0); 2058 } 2059 2060 /* 2061 * This ioctl closes a session. 2062 */ 2063 /* ARGSUSED */ 2064 static int 2065 close_session(dev_t dev, caddr_t arg, int mode, int *rval) 2066 { 2067 crypto_close_session_t close_session; 2068 int rv; 2069 2070 if (copyin(arg, &close_session, sizeof (close_session)) != 0) 2071 return (EFAULT); 2072 2073 rv = crypto_close_session(dev, close_session.cs_session); 2074 close_session.cs_return_value = rv; 2075 if (copyout(&close_session, arg, sizeof (close_session)) != 0) { 2076 return (EFAULT); 2077 } 2078 return (0); 2079 } 2080 2081 /* 2082 * Copy data model dependent mechanism structure into a kernel mechanism 2083 * structure. Allocate param storage if necessary. 2084 */ 2085 static boolean_t 2086 copyin_mech(int mode, crypto_session_data_t *sp, crypto_mechanism_t *in_mech, 2087 crypto_mechanism_t *out_mech, size_t *out_rctl_bytes, 2088 boolean_t *out_rctl_chk, int *out_rv, int *out_error) 2089 { 2090 STRUCT_DECL(crypto_mechanism, mech); 2091 caddr_t param; 2092 size_t param_len; 2093 size_t rctl_bytes = 0; 2094 int error = 0; 2095 int rv = 0; 2096 2097 STRUCT_INIT(mech, mode); 2098 bcopy(in_mech, STRUCT_BUF(mech), STRUCT_SIZE(mech)); 2099 param = STRUCT_FGETP(mech, cm_param); 2100 param_len = STRUCT_FGET(mech, cm_param_len); 2101 out_mech->cm_type = STRUCT_FGET(mech, cm_type); 2102 out_mech->cm_param = NULL; 2103 out_mech->cm_param_len = 0; 2104 if (param != NULL && param_len != 0) { 2105 if (param_len > crypto_max_buffer_len) { 2106 cmn_err(CE_NOTE, "copyin_mech: buffer greater than " 2107 "%ld bytes, pid = %d", crypto_max_buffer_len, 2108 curproc->p_pid); 2109 rv = CRYPTO_ARGUMENTS_BAD; 2110 goto out; 2111 } 2112 2113 rv = CRYPTO_BUFFER_CHECK(sp, param_len, *out_rctl_chk); 2114 if (rv != CRYPTO_SUCCESS) { 2115 goto out; 2116 } 2117 rctl_bytes = param_len; 2118 2119 out_mech->cm_param = kmem_alloc(param_len, KM_SLEEP); 2120 if (copyin((char *)param, out_mech->cm_param, param_len) != 0) { 2121 kmem_free(out_mech->cm_param, param_len); 2122 out_mech->cm_param = NULL; 2123 error = EFAULT; 2124 goto out; 2125 } 2126 out_mech->cm_param_len = param_len; 2127 } 2128 out: 2129 *out_rctl_bytes = rctl_bytes; 2130 *out_rv = rv; 2131 *out_error = error; 2132 return ((rv | error) ? B_FALSE : B_TRUE); 2133 } 2134 2135 /* 2136 * Free key attributes when key type is CRYPTO_KEY_ATTR_LIST. 2137 * The crypto_key structure is not freed. 2138 */ 2139 static void 2140 crypto_free_key_attributes(crypto_key_t *key) 2141 { 2142 crypto_object_attribute_t *attrs; 2143 size_t len = 0; 2144 int i; 2145 2146 ASSERT(key->ck_format == CRYPTO_KEY_ATTR_LIST); 2147 if (key->ck_count == 0 || key->ck_attrs == NULL) 2148 return; 2149 2150 /* compute the size of the container */ 2151 len = key->ck_count * sizeof (crypto_object_attribute_t); 2152 2153 /* total up the size of all attributes in the container */ 2154 for (i = 0; i < key->ck_count; i++) { 2155 attrs = &key->ck_attrs[i]; 2156 if (attrs->oa_value_len != 0 && 2157 attrs->oa_value != NULL) { 2158 len += roundup(attrs->oa_value_len, sizeof (caddr_t)); 2159 } 2160 } 2161 2162 bzero(key->ck_attrs, len); 2163 kmem_free(key->ck_attrs, len); 2164 } 2165 2166 /* 2167 * Frees allocated storage in the key structure, but doesn't free 2168 * the key structure. 2169 */ 2170 static void 2171 free_crypto_key(crypto_key_t *key) 2172 { 2173 switch (key->ck_format) { 2174 case CRYPTO_KEY_RAW: { 2175 size_t len; 2176 2177 if (key->ck_length == 0 || key->ck_data == NULL) 2178 break; 2179 2180 len = CRYPTO_BITS2BYTES(key->ck_length); 2181 bzero(key->ck_data, len); 2182 kmem_free(key->ck_data, len); 2183 break; 2184 } 2185 2186 case CRYPTO_KEY_ATTR_LIST: 2187 crypto_free_key_attributes(key); 2188 break; 2189 2190 default: 2191 break; 2192 } 2193 } 2194 2195 /* 2196 * Copy in an array of crypto_object_attribute structures from user-space. 2197 * Kernel memory is allocated for the array and the value of each attribute 2198 * in the array. Since unprivileged users can specify the size of attributes, 2199 * the amount of memory needed is charged against the 2200 * project.max-crypto-memory resource control. 2201 * 2202 * Attribute values are copied in from user-space if copyin_value is set to 2203 * B_TRUE. This routine returns B_TRUE if the copyin was successful. 2204 */ 2205 static boolean_t 2206 copyin_attributes(int mode, crypto_session_data_t *sp, 2207 uint_t count, caddr_t oc_attributes, 2208 crypto_object_attribute_t **k_attrs_out, size_t *k_attrs_size_out, 2209 caddr_t *u_attrs_out, int *out_rv, int *out_error, size_t *out_rctl_bytes, 2210 boolean_t *out_rctl_chk, boolean_t copyin_value) 2211 { 2212 STRUCT_DECL(crypto_object_attribute, oa); 2213 crypto_object_attribute_t *k_attrs = NULL; 2214 caddr_t attrs = NULL, ap, p, value; 2215 caddr_t k_attrs_buf; 2216 size_t k_attrs_len; 2217 size_t k_attrs_buf_len = 0; 2218 size_t k_attrs_total_len = 0; 2219 size_t tmp_len; 2220 size_t rctl_bytes = 0; 2221 size_t len = 0; 2222 size_t value_len; 2223 int error = 0; 2224 int rv = 0; 2225 int i; 2226 2227 STRUCT_INIT(oa, mode); 2228 2229 if (count == 0) { 2230 rv = CRYPTO_SUCCESS; 2231 goto out; 2232 } 2233 2234 if (count > CRYPTO_MAX_ATTRIBUTE_COUNT) { 2235 rv = CRYPTO_ARGUMENTS_BAD; 2236 goto out; 2237 } 2238 2239 /* compute size of crypto_object_attribute array */ 2240 len = count * STRUCT_SIZE(oa); 2241 2242 /* this allocation is not charged against the user's resource limit */ 2243 attrs = kmem_alloc(len, KM_SLEEP); 2244 if (copyin(oc_attributes, attrs, len) != 0) { 2245 error = EFAULT; 2246 goto out; 2247 } 2248 2249 /* figure out how much memory to allocate for all of the attributes */ 2250 ap = attrs; 2251 for (i = 0; i < count; i++) { 2252 bcopy(ap, STRUCT_BUF(oa), STRUCT_SIZE(oa)); 2253 tmp_len = roundup(STRUCT_FGET(oa, oa_value_len), 2254 sizeof (caddr_t)); 2255 if (tmp_len > crypto_max_buffer_len) { 2256 cmn_err(CE_NOTE, "copyin_attributes: buffer greater " 2257 "than %ld bytes, pid = %d", crypto_max_buffer_len, 2258 curproc->p_pid); 2259 rv = CRYPTO_ARGUMENTS_BAD; 2260 goto out; 2261 } 2262 if (STRUCT_FGETP(oa, oa_value) != NULL) 2263 k_attrs_buf_len += tmp_len; 2264 ap += STRUCT_SIZE(oa); 2265 } 2266 2267 k_attrs_len = count * sizeof (crypto_object_attribute_t); 2268 k_attrs_total_len = k_attrs_buf_len + k_attrs_len; 2269 2270 rv = CRYPTO_BUFFER_CHECK(sp, k_attrs_total_len, *out_rctl_chk); 2271 if (rv != CRYPTO_SUCCESS) { 2272 goto out; 2273 } 2274 rctl_bytes = k_attrs_total_len; 2275 2276 /* one big allocation for everything */ 2277 k_attrs = kmem_alloc(k_attrs_total_len, KM_SLEEP); 2278 k_attrs_buf = (char *)k_attrs + k_attrs_len; 2279 2280 ap = attrs; 2281 p = k_attrs_buf; 2282 for (i = 0; i < count; i++) { 2283 bcopy(ap, STRUCT_BUF(oa), STRUCT_SIZE(oa)); 2284 k_attrs[i].oa_type = STRUCT_FGET(oa, oa_type); 2285 value = STRUCT_FGETP(oa, oa_value); 2286 value_len = STRUCT_FGET(oa, oa_value_len); 2287 if (value != NULL && value_len != 0 && copyin_value) { 2288 if (copyin(value, p, value_len) != 0) { 2289 kmem_free(k_attrs, k_attrs_total_len); 2290 k_attrs = NULL; 2291 error = EFAULT; 2292 goto out; 2293 } 2294 } 2295 2296 if (value != NULL) { 2297 k_attrs[i].oa_value = p; 2298 p += roundup(value_len, sizeof (caddr_t)); 2299 } else { 2300 k_attrs[i].oa_value = NULL; 2301 } 2302 k_attrs[i].oa_value_len = value_len; 2303 ap += STRUCT_SIZE(oa); 2304 } 2305 out: 2306 if (attrs != NULL) { 2307 /* 2308 * Free the array if there is a failure or the caller 2309 * doesn't want the array to be returned. 2310 */ 2311 if (error != 0 || rv != CRYPTO_SUCCESS || u_attrs_out == NULL) { 2312 kmem_free(attrs, len); 2313 attrs = NULL; 2314 } 2315 } 2316 2317 if (u_attrs_out != NULL) 2318 *u_attrs_out = attrs; 2319 if (k_attrs_size_out != NULL) 2320 *k_attrs_size_out = k_attrs_total_len; 2321 *k_attrs_out = k_attrs; 2322 *out_rctl_bytes = rctl_bytes; 2323 *out_rv = rv; 2324 *out_error = error; 2325 return ((rv | error) ? B_FALSE : B_TRUE); 2326 } 2327 2328 /* 2329 * Copy data model dependent raw key into a kernel key 2330 * structure. Checks key length or attribute lengths against 2331 * resource controls before allocating memory. Returns B_TRUE 2332 * if both error and rv are set to 0. 2333 */ 2334 static boolean_t 2335 copyin_key(int mode, crypto_session_data_t *sp, crypto_key_t *in_key, 2336 crypto_key_t *out_key, size_t *out_rctl_bytes, 2337 boolean_t *out_rctl_chk, int *out_rv, int *out_error) 2338 { 2339 STRUCT_DECL(crypto_key, key); 2340 crypto_object_attribute_t *k_attrs = NULL; 2341 size_t key_bits; 2342 size_t key_bytes = 0; 2343 size_t rctl_bytes = 0; 2344 int count; 2345 int error = 0; 2346 int rv = CRYPTO_SUCCESS; 2347 2348 STRUCT_INIT(key, mode); 2349 bcopy(in_key, STRUCT_BUF(key), STRUCT_SIZE(key)); 2350 out_key->ck_format = STRUCT_FGET(key, ck_format); 2351 switch (out_key->ck_format) { 2352 case CRYPTO_KEY_RAW: 2353 key_bits = STRUCT_FGET(key, ck_length); 2354 if (key_bits != 0) { 2355 key_bytes = CRYPTO_BITS2BYTES(key_bits); 2356 if (key_bytes > crypto_max_buffer_len) { 2357 cmn_err(CE_NOTE, "copyin_key: buffer greater " 2358 "than %ld bytes, pid = %d", 2359 crypto_max_buffer_len, curproc->p_pid); 2360 rv = CRYPTO_ARGUMENTS_BAD; 2361 goto out; 2362 } 2363 2364 rv = CRYPTO_BUFFER_CHECK(sp, key_bytes, 2365 *out_rctl_chk); 2366 if (rv != CRYPTO_SUCCESS) { 2367 goto out; 2368 } 2369 rctl_bytes = key_bytes; 2370 2371 out_key->ck_data = kmem_alloc(key_bytes, KM_SLEEP); 2372 2373 if (copyin((char *)STRUCT_FGETP(key, ck_data), 2374 out_key->ck_data, key_bytes) != 0) { 2375 kmem_free(out_key->ck_data, key_bytes); 2376 out_key->ck_data = NULL; 2377 out_key->ck_length = 0; 2378 error = EFAULT; 2379 goto out; 2380 } 2381 } 2382 out_key->ck_length = key_bits; 2383 break; 2384 2385 case CRYPTO_KEY_ATTR_LIST: 2386 count = STRUCT_FGET(key, ck_count); 2387 2388 if (copyin_attributes(mode, sp, count, 2389 (caddr_t)STRUCT_FGETP(key, ck_attrs), &k_attrs, NULL, NULL, 2390 &rv, &error, &rctl_bytes, out_rctl_chk, B_TRUE)) { 2391 out_key->ck_count = count; 2392 out_key->ck_attrs = k_attrs; 2393 k_attrs = NULL; 2394 } else { 2395 out_key->ck_count = 0; 2396 out_key->ck_attrs = NULL; 2397 } 2398 break; 2399 2400 case CRYPTO_KEY_REFERENCE: 2401 out_key->ck_obj_id = STRUCT_FGET(key, ck_obj_id); 2402 break; 2403 2404 default: 2405 rv = CRYPTO_ARGUMENTS_BAD; 2406 } 2407 2408 out: 2409 *out_rctl_bytes = rctl_bytes; 2410 *out_rv = rv; 2411 *out_error = error; 2412 return ((rv | error) ? B_FALSE : B_TRUE); 2413 } 2414 2415 /* 2416 * This routine does two things: 2417 * 1. Given a crypto_minor structure and a session ID, it returns 2418 * a valid session pointer. 2419 * 2. It checks that the provider, to which the session has been opened, 2420 * has not been removed. 2421 */ 2422 static boolean_t 2423 get_session_ptr(crypto_session_id_t i, crypto_minor_t *cm, 2424 crypto_session_data_t **session_ptr, int *out_error, int *out_rv) 2425 { 2426 crypto_session_data_t *sp = NULL; 2427 int rv = CRYPTO_SESSION_HANDLE_INVALID; 2428 int error = 0; 2429 2430 mutex_enter(&cm->cm_lock); 2431 if ((i < cm->cm_session_table_count) && 2432 (cm->cm_session_table[i] != NULL)) { 2433 sp = cm->cm_session_table[i]; 2434 mutex_enter(&sp->sd_lock); 2435 mutex_exit(&cm->cm_lock); 2436 while (sp->sd_flags & CRYPTO_SESSION_IS_BUSY) { 2437 if (cv_wait_sig(&sp->sd_cv, &sp->sd_lock) == 0) { 2438 mutex_exit(&sp->sd_lock); 2439 sp = NULL; 2440 error = EINTR; 2441 goto out; 2442 } 2443 } 2444 2445 if (sp->sd_flags & CRYPTO_SESSION_IS_CLOSED) { 2446 mutex_exit(&sp->sd_lock); 2447 sp = NULL; 2448 goto out; 2449 } 2450 2451 if (KCF_IS_PROV_REMOVED(sp->sd_provider)) { 2452 mutex_exit(&sp->sd_lock); 2453 sp = NULL; 2454 rv = CRYPTO_DEVICE_ERROR; 2455 goto out; 2456 } 2457 2458 rv = CRYPTO_SUCCESS; 2459 sp->sd_flags |= CRYPTO_SESSION_IS_BUSY; 2460 mutex_exit(&sp->sd_lock); 2461 } else { 2462 mutex_exit(&cm->cm_lock); 2463 } 2464 out: 2465 *session_ptr = sp; 2466 *out_error = error; 2467 *out_rv = rv; 2468 return ((rv == CRYPTO_SUCCESS && error == 0) ? B_TRUE : B_FALSE); 2469 } 2470 2471 #define CRYPTO_SESSION_RELE(s) if ((s) != NULL) { \ 2472 mutex_enter(&((s)->sd_lock)); \ 2473 (s)->sd_flags &= ~CRYPTO_SESSION_IS_BUSY; \ 2474 cv_broadcast(&(s)->sd_cv); \ 2475 mutex_exit(&((s)->sd_lock)); \ 2476 } 2477 2478 /* ARGSUSED */ 2479 static int 2480 encrypt_init(dev_t dev, caddr_t arg, int mode, int *rval) 2481 { 2482 return (cipher_init(dev, arg, mode, crypto_encrypt_init_prov)); 2483 } 2484 2485 /* ARGSUSED */ 2486 static int 2487 decrypt_init(dev_t dev, caddr_t arg, int mode, int *rval) 2488 { 2489 return (cipher_init(dev, arg, mode, crypto_decrypt_init_prov)); 2490 } 2491 2492 /* 2493 * umech is a mechanism structure that has been copied from user address 2494 * space into kernel address space. Only one copyin has been done. 2495 * The mechanism parameter, if non-null, still points to user address space. 2496 * If the mechanism parameter contains pointers, they are pointers into 2497 * user address space. 2498 * 2499 * kmech is a umech with all pointers and structures in kernel address space. 2500 * 2501 * This routine calls the provider's entry point to copy a umech parameter 2502 * into kernel address space. Kernel memory is allocated by the provider. 2503 */ 2504 static int 2505 crypto_provider_copyin_mech_param(kcf_provider_desc_t *pd, 2506 crypto_mechanism_t *umech, crypto_mechanism_t *kmech, int mode, int *error) 2507 { 2508 crypto_mech_type_t provider_mech_type; 2509 int rv; 2510 2511 /* get the provider's mech number */ 2512 provider_mech_type = KCF_TO_PROV_MECHNUM(pd, umech->cm_type); 2513 2514 kmech->cm_param = NULL; 2515 kmech->cm_param_len = 0; 2516 kmech->cm_type = provider_mech_type; 2517 rv = KCF_PROV_COPYIN_MECH(pd, umech, kmech, error, mode); 2518 kmech->cm_type = umech->cm_type; 2519 2520 return (rv); 2521 } 2522 2523 /* 2524 * umech is a mechanism structure that has been copied from user address 2525 * space into kernel address space. Only one copyin has been done. 2526 * The mechanism parameter, if non-null, still points to user address space. 2527 * If the mechanism parameter contains pointers, they are pointers into 2528 * user address space. 2529 * 2530 * kmech is a umech with all pointers and structures in kernel address space. 2531 * 2532 * This routine calls the provider's entry point to copy a kmech parameter 2533 * into user address space using umech as a template containing 2534 * user address pointers. 2535 */ 2536 static int 2537 crypto_provider_copyout_mech_param(kcf_provider_desc_t *pd, 2538 crypto_mechanism_t *kmech, crypto_mechanism_t *umech, int mode, int *error) 2539 { 2540 crypto_mech_type_t provider_mech_type; 2541 int rv; 2542 2543 /* get the provider's mech number */ 2544 provider_mech_type = KCF_TO_PROV_MECHNUM(pd, umech->cm_type); 2545 2546 kmech->cm_type = provider_mech_type; 2547 rv = KCF_PROV_COPYOUT_MECH(pd, kmech, umech, error, mode); 2548 kmech->cm_type = umech->cm_type; 2549 2550 return (rv); 2551 } 2552 2553 /* 2554 * Call the provider's entry point to free kernel memory that has been 2555 * allocated for the mechanism's parameter. 2556 */ 2557 static void 2558 crypto_free_mech(kcf_provider_desc_t *pd, boolean_t allocated_by_crypto_module, 2559 crypto_mechanism_t *mech) 2560 { 2561 crypto_mech_type_t provider_mech_type; 2562 2563 if (allocated_by_crypto_module) { 2564 if (mech->cm_param != NULL) 2565 kmem_free(mech->cm_param, mech->cm_param_len); 2566 } else { 2567 /* get the provider's mech number */ 2568 provider_mech_type = KCF_TO_PROV_MECHNUM(pd, mech->cm_type); 2569 2570 if (mech->cm_param != NULL && mech->cm_param_len != 0) { 2571 mech->cm_type = provider_mech_type; 2572 (void) KCF_PROV_FREE_MECH(pd, mech); 2573 } 2574 } 2575 } 2576 2577 /* 2578 * ASSUMPTION: crypto_encrypt_init and crypto_decrypt_init 2579 * structures are identical except for field names. 2580 */ 2581 static int 2582 cipher_init(dev_t dev, caddr_t arg, int mode, int (*init)(crypto_provider_t, 2583 crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, 2584 crypto_ctx_template_t, crypto_context_t *, crypto_call_req_t *)) 2585 { 2586 STRUCT_DECL(crypto_encrypt_init, encrypt_init); 2587 kcf_provider_desc_t *real_provider = NULL; 2588 crypto_session_id_t session_id; 2589 crypto_mechanism_t mech; 2590 crypto_key_t key; 2591 crypto_minor_t *cm; 2592 crypto_session_data_t *sp = NULL; 2593 crypto_context_t cc; 2594 crypto_ctx_t **ctxpp; 2595 size_t mech_rctl_bytes = 0; 2596 boolean_t mech_rctl_chk = B_FALSE; 2597 size_t key_rctl_bytes = 0; 2598 boolean_t key_rctl_chk = B_FALSE; 2599 int error = 0; 2600 int rv; 2601 boolean_t allocated_by_crypto_module = B_FALSE; 2602 crypto_func_group_t fg; 2603 2604 STRUCT_INIT(encrypt_init, mode); 2605 2606 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 2607 cmn_err(CE_WARN, "cipher_init: failed holding minor"); 2608 return (ENXIO); 2609 } 2610 2611 if (copyin(arg, STRUCT_BUF(encrypt_init), 2612 STRUCT_SIZE(encrypt_init)) != 0) { 2613 crypto_release_minor(cm); 2614 return (EFAULT); 2615 } 2616 2617 mech.cm_param = NULL; 2618 bzero(&key, sizeof (crypto_key_t)); 2619 2620 session_id = STRUCT_FGET(encrypt_init, ei_session); 2621 2622 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 2623 goto out; 2624 } 2625 2626 bcopy(STRUCT_FADDR(encrypt_init, ei_mech), &mech.cm_type, 2627 sizeof (crypto_mech_type_t)); 2628 2629 if (init == crypto_encrypt_init_prov) { 2630 fg = CRYPTO_FG_ENCRYPT; 2631 } else { 2632 fg = CRYPTO_FG_DECRYPT; 2633 } 2634 2635 /* We need the key length for provider selection so copy it in now. */ 2636 if (!copyin_key(mode, sp, STRUCT_FADDR(encrypt_init, ei_key), &key, 2637 &key_rctl_bytes, &key_rctl_chk, &rv, &error)) { 2638 goto out; 2639 } 2640 2641 if ((rv = kcf_get_hardware_provider(mech.cm_type, &key, 2642 CRYPTO_MECH_INVALID, NULL, CHECK_RESTRICT_FALSE, sp->sd_provider, 2643 &real_provider, fg)) 2644 != CRYPTO_SUCCESS) { 2645 goto out; 2646 } 2647 2648 rv = crypto_provider_copyin_mech_param(real_provider, 2649 STRUCT_FADDR(encrypt_init, ei_mech), &mech, mode, &error); 2650 2651 if (rv == CRYPTO_NOT_SUPPORTED) { 2652 allocated_by_crypto_module = B_TRUE; 2653 if (!copyin_mech(mode, sp, STRUCT_FADDR(encrypt_init, ei_mech), 2654 &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) { 2655 goto out; 2656 } 2657 } else { 2658 if (rv != CRYPTO_SUCCESS) 2659 goto out; 2660 } 2661 2662 rv = (init)(real_provider, sp->sd_provider_session->ps_session, 2663 &mech, &key, NULL, &cc, NULL); 2664 2665 /* 2666 * Check if a context already exists. If so, it means it is being 2667 * abandoned. So, cancel it to avoid leaking it. 2668 */ 2669 ctxpp = (init == crypto_encrypt_init_prov) ? 2670 &sp->sd_encr_ctx : &sp->sd_decr_ctx; 2671 2672 if (*ctxpp != NULL) 2673 CRYPTO_CANCEL_CTX(ctxpp); 2674 *ctxpp = (rv == CRYPTO_SUCCESS) ? cc : NULL; 2675 2676 out: 2677 CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk); 2678 CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk); 2679 CRYPTO_SESSION_RELE(sp); 2680 crypto_release_minor(cm); 2681 2682 if (real_provider != NULL) { 2683 crypto_free_mech(real_provider, 2684 allocated_by_crypto_module, &mech); 2685 KCF_PROV_REFRELE(real_provider); 2686 } 2687 2688 free_crypto_key(&key); 2689 2690 if (error != 0) 2691 /* XXX free context */ 2692 return (error); 2693 2694 STRUCT_FSET(encrypt_init, ei_return_value, rv); 2695 if (copyout(STRUCT_BUF(encrypt_init), arg, 2696 STRUCT_SIZE(encrypt_init)) != 0) { 2697 /* XXX free context */ 2698 return (EFAULT); 2699 } 2700 return (0); 2701 } 2702 2703 /* ARGSUSED */ 2704 static int 2705 encrypt(dev_t dev, caddr_t arg, int mode, int *rval) 2706 { 2707 return (cipher(dev, arg, mode, crypto_encrypt_single)); 2708 } 2709 2710 /* ARGSUSED */ 2711 static int 2712 decrypt(dev_t dev, caddr_t arg, int mode, int *rval) 2713 { 2714 return (cipher(dev, arg, mode, crypto_decrypt_single)); 2715 } 2716 2717 /* 2718 * ASSUMPTION: crypto_encrypt and crypto_decrypt structures 2719 * are identical except for field names. 2720 */ 2721 static int 2722 cipher(dev_t dev, caddr_t arg, int mode, 2723 int (*single)(crypto_context_t, crypto_data_t *, crypto_data_t *, 2724 crypto_call_req_t *)) 2725 { 2726 STRUCT_DECL(crypto_encrypt, encrypt); 2727 crypto_session_id_t session_id; 2728 crypto_minor_t *cm; 2729 crypto_session_data_t *sp = NULL; 2730 crypto_ctx_t **ctxpp; 2731 crypto_data_t data, encr; 2732 size_t datalen, encrlen, need = 0; 2733 boolean_t do_inplace; 2734 char *encrbuf; 2735 int error = 0; 2736 int rv; 2737 boolean_t rctl_chk = B_FALSE; 2738 2739 STRUCT_INIT(encrypt, mode); 2740 2741 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 2742 cmn_err(CE_WARN, "cipher: failed holding minor"); 2743 return (ENXIO); 2744 } 2745 2746 if (copyin(arg, STRUCT_BUF(encrypt), STRUCT_SIZE(encrypt)) != 0) { 2747 crypto_release_minor(cm); 2748 return (EFAULT); 2749 } 2750 2751 data.cd_raw.iov_base = NULL; 2752 encr.cd_raw.iov_base = NULL; 2753 2754 datalen = STRUCT_FGET(encrypt, ce_datalen); 2755 encrlen = STRUCT_FGET(encrypt, ce_encrlen); 2756 2757 /* 2758 * Don't allocate output buffer unless both buffer pointer and 2759 * buffer length are not NULL or 0 (length). 2760 */ 2761 encrbuf = STRUCT_FGETP(encrypt, ce_encrbuf); 2762 if (encrbuf == NULL || encrlen == 0) { 2763 encrlen = 0; 2764 } 2765 2766 if (datalen > crypto_max_buffer_len || 2767 encrlen > crypto_max_buffer_len) { 2768 cmn_err(CE_NOTE, "cipher: buffer greater than %ld bytes, " 2769 "pid = %d", crypto_max_buffer_len, curproc->p_pid); 2770 rv = CRYPTO_ARGUMENTS_BAD; 2771 goto release_minor; 2772 } 2773 2774 session_id = STRUCT_FGET(encrypt, ce_session); 2775 2776 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 2777 goto release_minor; 2778 } 2779 2780 do_inplace = (STRUCT_FGET(encrypt, ce_flags) & 2781 CRYPTO_INPLACE_OPERATION) != 0; 2782 need = do_inplace ? datalen : datalen + encrlen; 2783 2784 if ((rv = CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)) != 2785 CRYPTO_SUCCESS) { 2786 need = 0; 2787 goto release_minor; 2788 } 2789 2790 INIT_RAW_CRYPTO_DATA(data, datalen); 2791 data.cd_miscdata = NULL; 2792 2793 if (datalen != 0 && copyin(STRUCT_FGETP(encrypt, ce_databuf), 2794 data.cd_raw.iov_base, datalen) != 0) { 2795 error = EFAULT; 2796 goto release_minor; 2797 } 2798 2799 if (do_inplace) { 2800 /* set out = in for in-place */ 2801 encr = data; 2802 } else { 2803 INIT_RAW_CRYPTO_DATA(encr, encrlen); 2804 } 2805 2806 ctxpp = (single == crypto_encrypt_single) ? 2807 &sp->sd_encr_ctx : &sp->sd_decr_ctx; 2808 2809 if (do_inplace) 2810 /* specify in-place buffers with output = NULL */ 2811 rv = (single)(*ctxpp, &encr, NULL, NULL); 2812 else 2813 rv = (single)(*ctxpp, &data, &encr, NULL); 2814 2815 if (KCF_CONTEXT_DONE(rv)) 2816 *ctxpp = NULL; 2817 2818 if (rv == CRYPTO_SUCCESS) { 2819 ASSERT(encr.cd_length <= encrlen); 2820 if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base, 2821 encrbuf, encr.cd_length) != 0) { 2822 error = EFAULT; 2823 goto release_minor; 2824 } 2825 STRUCT_FSET(encrypt, ce_encrlen, encr.cd_length); 2826 } 2827 2828 if (rv == CRYPTO_BUFFER_TOO_SMALL) { 2829 /* 2830 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1 2831 * of section 11.2 of the pkcs11 spec. We catch it here and 2832 * provide the correct pkcs11 return value. 2833 */ 2834 if (STRUCT_FGETP(encrypt, ce_encrbuf) == NULL) 2835 rv = CRYPTO_SUCCESS; 2836 STRUCT_FSET(encrypt, ce_encrlen, encr.cd_length); 2837 } 2838 2839 release_minor: 2840 CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk); 2841 CRYPTO_SESSION_RELE(sp); 2842 crypto_release_minor(cm); 2843 2844 if (data.cd_raw.iov_base != NULL) 2845 kmem_free(data.cd_raw.iov_base, datalen); 2846 2847 if (!do_inplace && encr.cd_raw.iov_base != NULL) 2848 kmem_free(encr.cd_raw.iov_base, encrlen); 2849 2850 if (error != 0) 2851 return (error); 2852 2853 STRUCT_FSET(encrypt, ce_return_value, rv); 2854 if (copyout(STRUCT_BUF(encrypt), arg, STRUCT_SIZE(encrypt)) != 0) { 2855 return (EFAULT); 2856 } 2857 return (0); 2858 } 2859 2860 /* ARGSUSED */ 2861 static int 2862 encrypt_update(dev_t dev, caddr_t arg, int mode, int *rval) 2863 { 2864 return (cipher_update(dev, arg, mode, crypto_encrypt_update)); 2865 } 2866 2867 /* ARGSUSED */ 2868 static int 2869 decrypt_update(dev_t dev, caddr_t arg, int mode, int *rval) 2870 { 2871 return (cipher_update(dev, arg, mode, crypto_decrypt_update)); 2872 } 2873 2874 /* 2875 * ASSUMPTION: crypto_encrypt_update and crypto_decrypt_update 2876 * structures are identical except for field names. 2877 */ 2878 static int 2879 cipher_update(dev_t dev, caddr_t arg, int mode, 2880 int (*update)(crypto_context_t, crypto_data_t *, crypto_data_t *, 2881 crypto_call_req_t *)) 2882 { 2883 STRUCT_DECL(crypto_encrypt_update, encrypt_update); 2884 crypto_session_id_t session_id; 2885 crypto_minor_t *cm; 2886 crypto_session_data_t *sp = NULL; 2887 crypto_ctx_t **ctxpp; 2888 crypto_data_t data, encr; 2889 size_t datalen, encrlen, need = 0; 2890 boolean_t do_inplace; 2891 char *encrbuf; 2892 int error = 0; 2893 int rv; 2894 boolean_t rctl_chk = B_FALSE; 2895 2896 STRUCT_INIT(encrypt_update, mode); 2897 2898 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 2899 cmn_err(CE_WARN, "cipher_update: failed holding minor"); 2900 return (ENXIO); 2901 } 2902 2903 if (copyin(arg, STRUCT_BUF(encrypt_update), 2904 STRUCT_SIZE(encrypt_update)) != 0) { 2905 crypto_release_minor(cm); 2906 return (EFAULT); 2907 } 2908 2909 data.cd_raw.iov_base = NULL; 2910 encr.cd_raw.iov_base = NULL; 2911 2912 datalen = STRUCT_FGET(encrypt_update, eu_datalen); 2913 encrlen = STRUCT_FGET(encrypt_update, eu_encrlen); 2914 2915 /* 2916 * Don't allocate output buffer unless both buffer pointer and 2917 * buffer length are not NULL or 0 (length). 2918 */ 2919 encrbuf = STRUCT_FGETP(encrypt_update, eu_encrbuf); 2920 if (encrbuf == NULL || encrlen == 0) { 2921 encrlen = 0; 2922 } 2923 2924 if (datalen > crypto_max_buffer_len || 2925 encrlen > crypto_max_buffer_len) { 2926 cmn_err(CE_NOTE, "cipher_update: buffer greater than %ld " 2927 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 2928 rv = CRYPTO_ARGUMENTS_BAD; 2929 goto out; 2930 } 2931 2932 session_id = STRUCT_FGET(encrypt_update, eu_session); 2933 2934 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 2935 goto out; 2936 } 2937 2938 do_inplace = (STRUCT_FGET(encrypt_update, eu_flags) & 2939 CRYPTO_INPLACE_OPERATION) != 0; 2940 need = do_inplace ? datalen : datalen + encrlen; 2941 2942 if ((rv = CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)) != 2943 CRYPTO_SUCCESS) { 2944 need = 0; 2945 goto out; 2946 } 2947 2948 INIT_RAW_CRYPTO_DATA(data, datalen); 2949 data.cd_miscdata = NULL; 2950 2951 if (datalen != 0 && copyin(STRUCT_FGETP(encrypt_update, eu_databuf), 2952 data.cd_raw.iov_base, datalen) != 0) { 2953 error = EFAULT; 2954 goto out; 2955 } 2956 2957 if (do_inplace) { 2958 /* specify in-place buffers with output = input */ 2959 encr = data; 2960 } else { 2961 INIT_RAW_CRYPTO_DATA(encr, encrlen); 2962 } 2963 2964 ctxpp = (update == crypto_encrypt_update) ? 2965 &sp->sd_encr_ctx : &sp->sd_decr_ctx; 2966 2967 if (do_inplace) 2968 /* specify in-place buffers with output = NULL */ 2969 rv = (update)(*ctxpp, &encr, NULL, NULL); 2970 else 2971 rv = (update)(*ctxpp, &data, &encr, NULL); 2972 2973 if (rv == CRYPTO_SUCCESS || rv == CRYPTO_BUFFER_TOO_SMALL) { 2974 if (rv == CRYPTO_SUCCESS) { 2975 ASSERT(encr.cd_length <= encrlen); 2976 if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base, 2977 encrbuf, encr.cd_length) != 0) { 2978 error = EFAULT; 2979 goto out; 2980 } 2981 } else { 2982 /* 2983 * The providers return CRYPTO_BUFFER_TOO_SMALL even 2984 * for case 1 of section 11.2 of the pkcs11 spec. 2985 * We catch it here and provide the correct pkcs11 2986 * return value. 2987 */ 2988 if (STRUCT_FGETP(encrypt_update, eu_encrbuf) == NULL) 2989 rv = CRYPTO_SUCCESS; 2990 } 2991 STRUCT_FSET(encrypt_update, eu_encrlen, encr.cd_length); 2992 } else { 2993 CRYPTO_CANCEL_CTX(ctxpp); 2994 } 2995 out: 2996 CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk); 2997 CRYPTO_SESSION_RELE(sp); 2998 crypto_release_minor(cm); 2999 3000 if (data.cd_raw.iov_base != NULL) 3001 kmem_free(data.cd_raw.iov_base, datalen); 3002 3003 if (!do_inplace && (encr.cd_raw.iov_base != NULL)) 3004 kmem_free(encr.cd_raw.iov_base, encrlen); 3005 3006 if (error != 0) 3007 return (error); 3008 3009 STRUCT_FSET(encrypt_update, eu_return_value, rv); 3010 if (copyout(STRUCT_BUF(encrypt_update), arg, 3011 STRUCT_SIZE(encrypt_update)) != 0) { 3012 return (EFAULT); 3013 } 3014 return (0); 3015 } 3016 3017 /* ARGSUSED */ 3018 static int 3019 encrypt_final(dev_t dev, caddr_t arg, int mode, int *rval) 3020 { 3021 return (common_final(dev, arg, mode, crypto_encrypt_final)); 3022 } 3023 3024 /* ARGSUSED */ 3025 static int 3026 decrypt_final(dev_t dev, caddr_t arg, int mode, int *rval) 3027 { 3028 return (common_final(dev, arg, mode, crypto_decrypt_final)); 3029 } 3030 3031 /* 3032 * ASSUMPTION: crypto_encrypt_final, crypto_decrypt_final, crypto_sign_final, 3033 * and crypto_digest_final structures are identical except for field names. 3034 */ 3035 static int 3036 common_final(dev_t dev, caddr_t arg, int mode, 3037 int (*final)(crypto_context_t, crypto_data_t *, crypto_call_req_t *)) 3038 { 3039 STRUCT_DECL(crypto_encrypt_final, encrypt_final); 3040 crypto_session_id_t session_id; 3041 crypto_minor_t *cm; 3042 crypto_session_data_t *sp = NULL; 3043 crypto_ctx_t **ctxpp; 3044 crypto_data_t encr; 3045 size_t encrlen, need = 0; 3046 char *encrbuf; 3047 int error = 0; 3048 int rv; 3049 boolean_t rctl_chk = B_FALSE; 3050 3051 STRUCT_INIT(encrypt_final, mode); 3052 3053 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3054 cmn_err(CE_WARN, "common_final: failed holding minor"); 3055 return (ENXIO); 3056 } 3057 3058 if (copyin(arg, STRUCT_BUF(encrypt_final), 3059 STRUCT_SIZE(encrypt_final)) != 0) { 3060 crypto_release_minor(cm); 3061 return (EFAULT); 3062 } 3063 3064 encr.cd_format = CRYPTO_DATA_RAW; 3065 encr.cd_raw.iov_base = NULL; 3066 3067 encrlen = STRUCT_FGET(encrypt_final, ef_encrlen); 3068 3069 /* 3070 * Don't allocate output buffer unless both buffer pointer and 3071 * buffer length are not NULL or 0 (length). 3072 */ 3073 encrbuf = STRUCT_FGETP(encrypt_final, ef_encrbuf); 3074 if (encrbuf == NULL || encrlen == 0) { 3075 encrlen = 0; 3076 } 3077 3078 if (encrlen > crypto_max_buffer_len) { 3079 cmn_err(CE_NOTE, "common_final: buffer greater than %ld " 3080 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 3081 rv = CRYPTO_ARGUMENTS_BAD; 3082 goto release_minor; 3083 } 3084 3085 session_id = STRUCT_FGET(encrypt_final, ef_session); 3086 3087 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 3088 goto release_minor; 3089 } 3090 3091 if ((rv = CRYPTO_BUFFER_CHECK(sp, encrlen, rctl_chk)) != 3092 CRYPTO_SUCCESS) { 3093 goto release_minor; 3094 } 3095 need = encrlen; 3096 encr.cd_raw.iov_base = kmem_alloc(encrlen, KM_SLEEP); 3097 encr.cd_raw.iov_len = encrlen; 3098 3099 encr.cd_offset = 0; 3100 encr.cd_length = encrlen; 3101 3102 ASSERT(final == crypto_encrypt_final || 3103 final == crypto_decrypt_final || final == crypto_sign_final || 3104 final == crypto_digest_final); 3105 3106 if (final == crypto_encrypt_final) { 3107 ctxpp = &sp->sd_encr_ctx; 3108 } else if (final == crypto_decrypt_final) { 3109 ctxpp = &sp->sd_decr_ctx; 3110 } else if (final == crypto_sign_final) { 3111 ctxpp = &sp->sd_sign_ctx; 3112 } else { 3113 ctxpp = &sp->sd_digest_ctx; 3114 } 3115 3116 rv = (final)(*ctxpp, &encr, NULL); 3117 if (KCF_CONTEXT_DONE(rv)) 3118 *ctxpp = NULL; 3119 3120 if (rv == CRYPTO_SUCCESS) { 3121 ASSERT(encr.cd_length <= encrlen); 3122 if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base, 3123 encrbuf, encr.cd_length) != 0) { 3124 error = EFAULT; 3125 goto release_minor; 3126 } 3127 STRUCT_FSET(encrypt_final, ef_encrlen, encr.cd_length); 3128 } 3129 3130 if (rv == CRYPTO_BUFFER_TOO_SMALL) { 3131 /* 3132 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1 3133 * of section 11.2 of the pkcs11 spec. We catch it here and 3134 * provide the correct pkcs11 return value. 3135 */ 3136 if (STRUCT_FGETP(encrypt_final, ef_encrbuf) == NULL) 3137 rv = CRYPTO_SUCCESS; 3138 STRUCT_FSET(encrypt_final, ef_encrlen, encr.cd_length); 3139 } 3140 3141 release_minor: 3142 CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk); 3143 CRYPTO_SESSION_RELE(sp); 3144 crypto_release_minor(cm); 3145 3146 if (encr.cd_raw.iov_base != NULL) 3147 kmem_free(encr.cd_raw.iov_base, encrlen); 3148 3149 if (error != 0) 3150 return (error); 3151 3152 STRUCT_FSET(encrypt_final, ef_return_value, rv); 3153 if (copyout(STRUCT_BUF(encrypt_final), arg, 3154 STRUCT_SIZE(encrypt_final)) != 0) { 3155 return (EFAULT); 3156 } 3157 return (0); 3158 } 3159 3160 /* ARGSUSED */ 3161 static int 3162 digest_init(dev_t dev, caddr_t arg, int mode, int *rval) 3163 { 3164 STRUCT_DECL(crypto_digest_init, digest_init); 3165 kcf_provider_desc_t *real_provider = NULL; 3166 crypto_session_id_t session_id; 3167 crypto_mechanism_t mech; 3168 crypto_minor_t *cm; 3169 crypto_session_data_t *sp = NULL; 3170 crypto_context_t cc; 3171 size_t rctl_bytes = 0; 3172 boolean_t rctl_chk = B_FALSE; 3173 int error = 0; 3174 int rv; 3175 3176 STRUCT_INIT(digest_init, mode); 3177 3178 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3179 cmn_err(CE_WARN, "digest_init: failed holding minor"); 3180 return (ENXIO); 3181 } 3182 3183 if (copyin(arg, STRUCT_BUF(digest_init), 3184 STRUCT_SIZE(digest_init)) != 0) { 3185 crypto_release_minor(cm); 3186 return (EFAULT); 3187 } 3188 3189 mech.cm_param = NULL; 3190 3191 session_id = STRUCT_FGET(digest_init, di_session); 3192 3193 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 3194 goto out; 3195 } 3196 3197 if (!copyin_mech(mode, sp, STRUCT_FADDR(digest_init, di_mech), &mech, 3198 &rctl_bytes, &rctl_chk, &rv, &error)) { 3199 goto out; 3200 } 3201 3202 if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL, 3203 CRYPTO_MECH_INVALID, NULL, CHECK_RESTRICT_FALSE, sp->sd_provider, 3204 &real_provider, CRYPTO_FG_DIGEST)) != CRYPTO_SUCCESS) { 3205 goto out; 3206 } 3207 3208 rv = crypto_digest_init_prov(real_provider, 3209 sp->sd_provider_session->ps_session, &mech, &cc, NULL); 3210 3211 /* 3212 * Check if a context already exists. If so, it means it is being 3213 * abandoned. So, cancel it to avoid leaking it. 3214 */ 3215 if (sp->sd_digest_ctx != NULL) 3216 CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx); 3217 sp->sd_digest_ctx = (rv == CRYPTO_SUCCESS) ? cc : NULL; 3218 out: 3219 CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk); 3220 CRYPTO_SESSION_RELE(sp); 3221 crypto_release_minor(cm); 3222 3223 if (real_provider != NULL) 3224 KCF_PROV_REFRELE(real_provider); 3225 3226 if (mech.cm_param != NULL) 3227 kmem_free(mech.cm_param, mech.cm_param_len); 3228 3229 if (error != 0) 3230 return (error); 3231 3232 STRUCT_FSET(digest_init, di_return_value, rv); 3233 if (copyout(STRUCT_BUF(digest_init), arg, 3234 STRUCT_SIZE(digest_init)) != 0) { 3235 return (EFAULT); 3236 } 3237 return (0); 3238 } 3239 3240 /* ARGSUSED */ 3241 static int 3242 digest_update(dev_t dev, caddr_t arg, int mode, int *rval) 3243 { 3244 STRUCT_DECL(crypto_digest_update, digest_update); 3245 crypto_session_id_t session_id; 3246 crypto_minor_t *cm; 3247 crypto_session_data_t *sp = NULL; 3248 crypto_data_t data; 3249 size_t datalen, need = 0; 3250 int error = 0; 3251 int rv; 3252 boolean_t rctl_chk = B_FALSE; 3253 3254 STRUCT_INIT(digest_update, mode); 3255 3256 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3257 cmn_err(CE_WARN, "digest_update: failed holding minor"); 3258 return (ENXIO); 3259 } 3260 3261 if (copyin(arg, STRUCT_BUF(digest_update), 3262 STRUCT_SIZE(digest_update)) != 0) { 3263 crypto_release_minor(cm); 3264 return (EFAULT); 3265 } 3266 3267 data.cd_format = CRYPTO_DATA_RAW; 3268 data.cd_raw.iov_base = NULL; 3269 3270 datalen = STRUCT_FGET(digest_update, du_datalen); 3271 if (datalen > crypto_max_buffer_len) { 3272 cmn_err(CE_NOTE, "digest_update: buffer greater than %ld " 3273 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 3274 rv = CRYPTO_ARGUMENTS_BAD; 3275 goto release_minor; 3276 } 3277 3278 session_id = STRUCT_FGET(digest_update, du_session); 3279 3280 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 3281 goto release_minor; 3282 } 3283 3284 if ((rv = CRYPTO_BUFFER_CHECK(sp, datalen, rctl_chk)) != 3285 CRYPTO_SUCCESS) { 3286 goto release_minor; 3287 } 3288 3289 need = datalen; 3290 data.cd_raw.iov_base = kmem_alloc(datalen, KM_SLEEP); 3291 data.cd_raw.iov_len = datalen; 3292 3293 if (datalen != 0 && copyin(STRUCT_FGETP(digest_update, du_databuf), 3294 data.cd_raw.iov_base, datalen) != 0) { 3295 error = EFAULT; 3296 goto release_minor; 3297 } 3298 3299 data.cd_offset = 0; 3300 data.cd_length = datalen; 3301 3302 rv = crypto_digest_update(sp->sd_digest_ctx, &data, NULL); 3303 if (rv != CRYPTO_SUCCESS) 3304 CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx); 3305 3306 release_minor: 3307 CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk); 3308 CRYPTO_SESSION_RELE(sp); 3309 crypto_release_minor(cm); 3310 3311 if (data.cd_raw.iov_base != NULL) 3312 kmem_free(data.cd_raw.iov_base, datalen); 3313 3314 if (error != 0) 3315 return (error); 3316 3317 STRUCT_FSET(digest_update, du_return_value, rv); 3318 if (copyout(STRUCT_BUF(digest_update), arg, 3319 STRUCT_SIZE(digest_update)) != 0) { 3320 return (EFAULT); 3321 } 3322 return (0); 3323 } 3324 3325 /* ARGSUSED */ 3326 static int 3327 digest_key(dev_t dev, caddr_t arg, int mode, int *rval) 3328 { 3329 STRUCT_DECL(crypto_digest_key, digest_key); 3330 crypto_session_id_t session_id; 3331 crypto_key_t key; 3332 crypto_minor_t *cm; 3333 crypto_session_data_t *sp = NULL; 3334 size_t rctl_bytes = 0; 3335 boolean_t key_rctl_chk = B_FALSE; 3336 int error = 0; 3337 int rv; 3338 3339 STRUCT_INIT(digest_key, mode); 3340 3341 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3342 cmn_err(CE_WARN, "digest_key: failed holding minor"); 3343 return (ENXIO); 3344 } 3345 3346 if (copyin(arg, STRUCT_BUF(digest_key), STRUCT_SIZE(digest_key)) != 0) { 3347 crypto_release_minor(cm); 3348 return (EFAULT); 3349 } 3350 3351 bzero(&key, sizeof (crypto_key_t)); 3352 3353 session_id = STRUCT_FGET(digest_key, dk_session); 3354 3355 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 3356 goto out; 3357 } 3358 3359 if (!copyin_key(mode, sp, STRUCT_FADDR(digest_key, dk_key), &key, 3360 &rctl_bytes, &key_rctl_chk, &rv, &error)) { 3361 goto out; 3362 } 3363 3364 rv = crypto_digest_key_prov(sp->sd_digest_ctx, &key, NULL); 3365 if (rv != CRYPTO_SUCCESS) 3366 CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx); 3367 out: 3368 CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, key_rctl_chk); 3369 CRYPTO_SESSION_RELE(sp); 3370 crypto_release_minor(cm); 3371 3372 free_crypto_key(&key); 3373 3374 if (error != 0) 3375 return (error); 3376 3377 STRUCT_FSET(digest_key, dk_return_value, rv); 3378 if (copyout(STRUCT_BUF(digest_key), arg, 3379 STRUCT_SIZE(digest_key)) != 0) { 3380 return (EFAULT); 3381 } 3382 return (0); 3383 } 3384 3385 /* ARGSUSED */ 3386 static int 3387 digest_final(dev_t dev, caddr_t arg, int mode, int *rval) 3388 { 3389 return (common_final(dev, arg, mode, crypto_digest_final)); 3390 } 3391 3392 /* ARGSUSED */ 3393 static int 3394 digest(dev_t dev, caddr_t arg, int mode, int *rval) 3395 { 3396 return (common_digest(dev, arg, mode, crypto_digest_single)); 3397 } 3398 3399 /* 3400 * ASSUMPTION: crypto_digest, crypto_sign, crypto_sign_recover, 3401 * and crypto_verify_recover are identical except for field names. 3402 */ 3403 static int 3404 common_digest(dev_t dev, caddr_t arg, int mode, 3405 int (*single)(crypto_context_t, crypto_data_t *, crypto_data_t *, 3406 crypto_call_req_t *)) 3407 { 3408 STRUCT_DECL(crypto_digest, crypto_digest); 3409 crypto_session_id_t session_id; 3410 crypto_minor_t *cm; 3411 crypto_session_data_t *sp = NULL; 3412 crypto_data_t data, digest; 3413 crypto_ctx_t **ctxpp; 3414 size_t datalen, digestlen, need = 0; 3415 char *digestbuf; 3416 int error = 0; 3417 int rv; 3418 boolean_t rctl_chk = B_FALSE; 3419 3420 STRUCT_INIT(crypto_digest, mode); 3421 3422 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3423 cmn_err(CE_WARN, "common_digest: failed holding minor"); 3424 return (ENXIO); 3425 } 3426 3427 if (copyin(arg, STRUCT_BUF(crypto_digest), 3428 STRUCT_SIZE(crypto_digest)) != 0) { 3429 crypto_release_minor(cm); 3430 return (EFAULT); 3431 } 3432 3433 data.cd_raw.iov_base = NULL; 3434 digest.cd_raw.iov_base = NULL; 3435 3436 datalen = STRUCT_FGET(crypto_digest, cd_datalen); 3437 digestlen = STRUCT_FGET(crypto_digest, cd_digestlen); 3438 3439 /* 3440 * Don't allocate output buffer unless both buffer pointer and 3441 * buffer length are not NULL or 0 (length). 3442 */ 3443 digestbuf = STRUCT_FGETP(crypto_digest, cd_digestbuf); 3444 if (digestbuf == NULL || digestlen == 0) { 3445 digestlen = 0; 3446 } 3447 3448 if (datalen > crypto_max_buffer_len || 3449 digestlen > crypto_max_buffer_len) { 3450 cmn_err(CE_NOTE, "common_digest: buffer greater than %ld " 3451 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 3452 rv = CRYPTO_ARGUMENTS_BAD; 3453 goto release_minor; 3454 } 3455 3456 session_id = STRUCT_FGET(crypto_digest, cd_session); 3457 3458 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 3459 goto release_minor; 3460 } 3461 3462 need = datalen + digestlen; 3463 if ((rv = CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)) != 3464 CRYPTO_SUCCESS) { 3465 need = 0; 3466 goto release_minor; 3467 } 3468 3469 INIT_RAW_CRYPTO_DATA(data, datalen); 3470 3471 if (datalen != 0 && copyin(STRUCT_FGETP(crypto_digest, cd_databuf), 3472 data.cd_raw.iov_base, datalen) != 0) { 3473 error = EFAULT; 3474 goto release_minor; 3475 } 3476 3477 INIT_RAW_CRYPTO_DATA(digest, digestlen); 3478 3479 ASSERT(single == crypto_digest_single || 3480 single == crypto_sign_single || 3481 single == crypto_verify_recover_single || 3482 single == crypto_sign_recover_single); 3483 3484 if (single == crypto_digest_single) { 3485 ctxpp = &sp->sd_digest_ctx; 3486 } else if (single == crypto_sign_single) { 3487 ctxpp = &sp->sd_sign_ctx; 3488 } else if (single == crypto_verify_recover_single) { 3489 ctxpp = &sp->sd_verify_recover_ctx; 3490 } else { 3491 ctxpp = &sp->sd_sign_recover_ctx; 3492 } 3493 rv = (single)(*ctxpp, &data, &digest, NULL); 3494 if (KCF_CONTEXT_DONE(rv)) 3495 *ctxpp = NULL; 3496 3497 if (rv == CRYPTO_SUCCESS) { 3498 ASSERT(digest.cd_length <= digestlen); 3499 if (digest.cd_length != 0 && copyout(digest.cd_raw.iov_base, 3500 digestbuf, digest.cd_length) != 0) { 3501 error = EFAULT; 3502 goto release_minor; 3503 } 3504 STRUCT_FSET(crypto_digest, cd_digestlen, digest.cd_length); 3505 } 3506 3507 if (rv == CRYPTO_BUFFER_TOO_SMALL) { 3508 /* 3509 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1 3510 * of section 11.2 of the pkcs11 spec. We catch it here and 3511 * provide the correct pkcs11 return value. 3512 */ 3513 if (STRUCT_FGETP(crypto_digest, cd_digestbuf) == NULL) 3514 rv = CRYPTO_SUCCESS; 3515 STRUCT_FSET(crypto_digest, cd_digestlen, digest.cd_length); 3516 } 3517 3518 release_minor: 3519 CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk); 3520 CRYPTO_SESSION_RELE(sp); 3521 crypto_release_minor(cm); 3522 3523 if (data.cd_raw.iov_base != NULL) 3524 kmem_free(data.cd_raw.iov_base, datalen); 3525 3526 if (digest.cd_raw.iov_base != NULL) 3527 kmem_free(digest.cd_raw.iov_base, digestlen); 3528 3529 if (error != 0) 3530 return (error); 3531 3532 STRUCT_FSET(crypto_digest, cd_return_value, rv); 3533 if (copyout(STRUCT_BUF(crypto_digest), arg, 3534 STRUCT_SIZE(crypto_digest)) != 0) { 3535 return (EFAULT); 3536 } 3537 return (0); 3538 } 3539 3540 /* 3541 * A helper function that does what the name suggests. 3542 * Returns 0 on success and non-zero otherwise. 3543 * On failure, out_pin is set to 0. 3544 */ 3545 int 3546 get_pin_and_session_ptr(char *in_pin, char **out_pin, size_t pin_len, 3547 crypto_minor_t *cm, crypto_session_id_t sid, crypto_session_data_t **sp, 3548 int *rv, int *error) 3549 { 3550 char *tmp_pin = NULL; 3551 int tmp_error = 0, tmp_rv = 0; 3552 3553 if (pin_len > KCF_MAX_PIN_LEN) { 3554 tmp_rv = CRYPTO_PIN_LEN_RANGE; 3555 goto out; 3556 } 3557 tmp_pin = kmem_alloc(pin_len, KM_SLEEP); 3558 3559 if (pin_len != 0 && copyin(in_pin, tmp_pin, pin_len) != 0) { 3560 tmp_error = EFAULT; 3561 goto out; 3562 } 3563 3564 (void) get_session_ptr(sid, cm, sp, &tmp_error, &tmp_rv); 3565 out: 3566 *out_pin = tmp_pin; 3567 *rv = tmp_rv; 3568 *error = tmp_error; 3569 return (tmp_rv | tmp_error); 3570 } 3571 3572 /* ARGSUSED */ 3573 static int 3574 set_pin(dev_t dev, caddr_t arg, int mode, int *rval) 3575 { 3576 STRUCT_DECL(crypto_set_pin, set_pin); 3577 kcf_provider_desc_t *real_provider; 3578 kcf_req_params_t params; 3579 crypto_minor_t *cm; 3580 crypto_session_data_t *sp; 3581 char *old_pin = NULL; 3582 char *new_pin = NULL; 3583 size_t old_pin_len; 3584 size_t new_pin_len; 3585 int error = 0; 3586 int rv; 3587 3588 STRUCT_INIT(set_pin, mode); 3589 3590 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3591 cmn_err(CE_WARN, "set_pin: failed holding minor"); 3592 return (ENXIO); 3593 } 3594 3595 if (copyin(arg, STRUCT_BUF(set_pin), 3596 STRUCT_SIZE(set_pin)) != 0) { 3597 crypto_release_minor(cm); 3598 return (EFAULT); 3599 } 3600 3601 old_pin_len = STRUCT_FGET(set_pin, sp_old_len); 3602 3603 if (get_pin_and_session_ptr(STRUCT_FGETP(set_pin, sp_old_pin), 3604 &old_pin, old_pin_len, cm, STRUCT_FGET(set_pin, sp_session), 3605 &sp, &rv, &error) != 0) 3606 goto release_minor; 3607 3608 new_pin_len = STRUCT_FGET(set_pin, sp_new_len); 3609 if (new_pin_len > KCF_MAX_PIN_LEN) { 3610 rv = CRYPTO_PIN_LEN_RANGE; 3611 goto out; 3612 } 3613 new_pin = kmem_alloc(new_pin_len, KM_SLEEP); 3614 3615 if (new_pin_len != 0 && copyin(STRUCT_FGETP(set_pin, sp_new_pin), 3616 new_pin, new_pin_len) != 0) { 3617 error = EFAULT; 3618 goto out; 3619 } 3620 3621 if ((rv = kcf_get_hardware_provider_nomech( 3622 CRYPTO_OPS_OFFSET(provider_ops), CRYPTO_PROVIDER_OFFSET(set_pin), 3623 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider)) 3624 != CRYPTO_SUCCESS) { 3625 goto out; 3626 } 3627 3628 KCF_WRAP_PROVMGMT_OPS_PARAMS(¶ms, KCF_OP_MGMT_SETPIN, 3629 sp->sd_provider_session->ps_session, old_pin, old_pin_len, 3630 new_pin, new_pin_len, NULL, NULL, real_provider); 3631 3632 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 3633 KCF_PROV_REFRELE(real_provider); 3634 3635 out: 3636 CRYPTO_SESSION_RELE(sp); 3637 3638 release_minor: 3639 crypto_release_minor(cm); 3640 3641 if (old_pin != NULL) { 3642 bzero(old_pin, old_pin_len); 3643 kmem_free(old_pin, old_pin_len); 3644 } 3645 3646 if (new_pin != NULL) { 3647 bzero(new_pin, new_pin_len); 3648 kmem_free(new_pin, new_pin_len); 3649 } 3650 3651 if (error != 0) 3652 return (error); 3653 3654 STRUCT_FSET(set_pin, sp_return_value, rv); 3655 if (copyout(STRUCT_BUF(set_pin), arg, STRUCT_SIZE(set_pin)) != 0) { 3656 return (EFAULT); 3657 } 3658 return (0); 3659 } 3660 3661 /* ARGSUSED */ 3662 static int 3663 login(dev_t dev, caddr_t arg, int mode, int *rval) 3664 { 3665 STRUCT_DECL(crypto_login, login); 3666 kcf_provider_desc_t *real_provider; 3667 kcf_req_params_t params; 3668 crypto_minor_t *cm; 3669 crypto_session_data_t *sp; 3670 size_t pin_len; 3671 char *pin; 3672 uint_t user_type; 3673 int error = 0; 3674 int rv; 3675 3676 STRUCT_INIT(login, mode); 3677 3678 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3679 cmn_err(CE_WARN, "login: failed holding minor"); 3680 return (ENXIO); 3681 } 3682 3683 if (copyin(arg, STRUCT_BUF(login), STRUCT_SIZE(login)) != 0) { 3684 crypto_release_minor(cm); 3685 return (EFAULT); 3686 } 3687 3688 user_type = STRUCT_FGET(login, co_user_type); 3689 3690 pin_len = STRUCT_FGET(login, co_pin_len); 3691 3692 if (get_pin_and_session_ptr(STRUCT_FGETP(login, co_pin), 3693 &pin, pin_len, cm, STRUCT_FGET(login, co_session), 3694 &sp, &rv, &error) != 0) { 3695 if (rv == CRYPTO_PIN_LEN_RANGE) 3696 rv = CRYPTO_PIN_INCORRECT; 3697 goto release_minor; 3698 } 3699 3700 if ((rv = kcf_get_hardware_provider_nomech( 3701 CRYPTO_OPS_OFFSET(session_ops), 3702 CRYPTO_SESSION_OFFSET(session_login), 3703 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider)) 3704 != CRYPTO_SUCCESS) { 3705 goto out; 3706 } 3707 3708 KCF_WRAP_SESSION_OPS_PARAMS(¶ms, KCF_OP_SESSION_LOGIN, NULL, 3709 sp->sd_provider_session->ps_session, user_type, pin, pin_len, 3710 real_provider); 3711 3712 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 3713 KCF_PROV_REFRELE(real_provider); 3714 3715 out: 3716 CRYPTO_SESSION_RELE(sp); 3717 3718 release_minor: 3719 crypto_release_minor(cm); 3720 3721 if (pin != NULL) { 3722 bzero(pin, pin_len); 3723 kmem_free(pin, pin_len); 3724 } 3725 3726 if (error != 0) 3727 return (error); 3728 3729 STRUCT_FSET(login, co_return_value, rv); 3730 if (copyout(STRUCT_BUF(login), arg, STRUCT_SIZE(login)) != 0) { 3731 return (EFAULT); 3732 } 3733 return (0); 3734 } 3735 3736 /* ARGSUSED */ 3737 static int 3738 logout(dev_t dev, caddr_t arg, int mode, int *rval) 3739 { 3740 crypto_logout_t logout; 3741 kcf_provider_desc_t *real_provider; 3742 kcf_req_params_t params; 3743 crypto_minor_t *cm; 3744 crypto_session_data_t *sp; 3745 int error = 0; 3746 int rv; 3747 3748 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3749 cmn_err(CE_WARN, "logout: failed holding minor"); 3750 return (ENXIO); 3751 } 3752 3753 if (copyin(arg, &logout, sizeof (logout)) != 0) { 3754 crypto_release_minor(cm); 3755 return (EFAULT); 3756 } 3757 3758 if (!get_session_ptr(logout.cl_session, cm, &sp, &error, &rv)) { 3759 goto release_minor; 3760 } 3761 3762 if ((rv = kcf_get_hardware_provider_nomech( 3763 CRYPTO_OPS_OFFSET(session_ops), 3764 CRYPTO_SESSION_OFFSET(session_logout), CHECK_RESTRICT_FALSE, 3765 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 3766 goto out; 3767 } 3768 3769 KCF_WRAP_SESSION_OPS_PARAMS(¶ms, KCF_OP_SESSION_LOGOUT, NULL, 3770 sp->sd_provider_session->ps_session, 0, NULL, 0, real_provider); 3771 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 3772 KCF_PROV_REFRELE(real_provider); 3773 3774 out: 3775 CRYPTO_SESSION_RELE(sp); 3776 3777 release_minor: 3778 crypto_release_minor(cm); 3779 3780 if (error != 0) 3781 return (error); 3782 3783 logout.cl_return_value = rv; 3784 if (copyout(&logout, arg, sizeof (logout)) != 0) { 3785 return (EFAULT); 3786 } 3787 return (0); 3788 } 3789 3790 /* ARGSUSED */ 3791 static int 3792 sign_init(dev_t dev, caddr_t arg, int mode, int *rval) 3793 { 3794 return (sign_verify_init(dev, arg, mode, crypto_sign_init_prov)); 3795 } 3796 3797 /* ARGSUSED */ 3798 static int 3799 sign_recover_init(dev_t dev, caddr_t arg, int mode, int *rval) 3800 { 3801 return (sign_verify_init(dev, arg, mode, 3802 crypto_sign_recover_init_prov)); 3803 } 3804 3805 /* ARGSUSED */ 3806 static int 3807 verify_init(dev_t dev, caddr_t arg, int mode, int *rval) 3808 { 3809 return (sign_verify_init(dev, arg, mode, crypto_verify_init_prov)); 3810 } 3811 3812 /* ARGSUSED */ 3813 static int 3814 verify_recover_init(dev_t dev, caddr_t arg, int mode, int *rval) 3815 { 3816 return (sign_verify_init(dev, arg, mode, 3817 crypto_verify_recover_init_prov)); 3818 } 3819 3820 /* 3821 * ASSUMPTION: crypto_sign_init, crypto_verify_init, crypto_sign_recover_init, 3822 * and crypto_verify_recover_init structures are identical 3823 * except for field names. 3824 */ 3825 static int 3826 sign_verify_init(dev_t dev, caddr_t arg, int mode, 3827 int (*init)(crypto_provider_t, crypto_session_id_t, 3828 crypto_mechanism_t *, crypto_key_t *, crypto_ctx_template_t, 3829 crypto_context_t *, crypto_call_req_t *)) 3830 { 3831 STRUCT_DECL(crypto_sign_init, sign_init); 3832 kcf_provider_desc_t *real_provider = NULL; 3833 crypto_session_id_t session_id; 3834 crypto_mechanism_t mech; 3835 crypto_key_t key; 3836 crypto_minor_t *cm; 3837 crypto_session_data_t *sp = NULL; 3838 crypto_context_t cc; 3839 crypto_ctx_t **ctxpp; 3840 size_t mech_rctl_bytes = 0; 3841 boolean_t mech_rctl_chk = B_FALSE; 3842 size_t key_rctl_bytes = 0; 3843 boolean_t key_rctl_chk = B_FALSE; 3844 int error = 0; 3845 int rv; 3846 boolean_t allocated_by_crypto_module = B_FALSE; 3847 crypto_func_group_t fg; 3848 3849 STRUCT_INIT(sign_init, mode); 3850 3851 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3852 cmn_err(CE_WARN, "sign_verify_init: failed holding minor"); 3853 return (ENXIO); 3854 } 3855 3856 if (copyin(arg, STRUCT_BUF(sign_init), STRUCT_SIZE(sign_init)) != 0) { 3857 crypto_release_minor(cm); 3858 return (EFAULT); 3859 } 3860 3861 mech.cm_param = NULL; 3862 bzero(&key, sizeof (key)); 3863 3864 session_id = STRUCT_FGET(sign_init, si_session); 3865 3866 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 3867 goto out; 3868 } 3869 3870 bcopy(STRUCT_FADDR(sign_init, si_mech), &mech.cm_type, 3871 sizeof (crypto_mech_type_t)); 3872 3873 ASSERT(init == crypto_sign_init_prov || 3874 init == crypto_verify_init_prov || 3875 init == crypto_sign_recover_init_prov || 3876 init == crypto_verify_recover_init_prov); 3877 3878 if (init == crypto_sign_init_prov) { 3879 fg = CRYPTO_FG_SIGN; 3880 ctxpp = &sp->sd_sign_ctx; 3881 } else if (init == crypto_verify_init_prov) { 3882 fg = CRYPTO_FG_VERIFY; 3883 ctxpp = &sp->sd_verify_ctx; 3884 } else if (init == crypto_sign_recover_init_prov) { 3885 fg = CRYPTO_FG_SIGN_RECOVER; 3886 ctxpp = &sp->sd_sign_recover_ctx; 3887 } else { 3888 fg = CRYPTO_FG_VERIFY_RECOVER; 3889 ctxpp = &sp->sd_verify_recover_ctx; 3890 } 3891 3892 /* We need the key length for provider selection so copy it in now. */ 3893 if (!copyin_key(mode, sp, STRUCT_FADDR(sign_init, si_key), &key, 3894 &key_rctl_bytes, &key_rctl_chk, &rv, &error)) { 3895 goto out; 3896 } 3897 3898 if ((rv = kcf_get_hardware_provider(mech.cm_type, &key, 3899 CRYPTO_MECH_INVALID, NULL, CHECK_RESTRICT_FALSE, sp->sd_provider, 3900 &real_provider, fg)) != CRYPTO_SUCCESS) { 3901 goto out; 3902 } 3903 3904 rv = crypto_provider_copyin_mech_param(real_provider, 3905 STRUCT_FADDR(sign_init, si_mech), &mech, mode, &error); 3906 3907 if (rv == CRYPTO_NOT_SUPPORTED) { 3908 allocated_by_crypto_module = B_TRUE; 3909 if (!copyin_mech(mode, sp, STRUCT_FADDR(sign_init, si_mech), 3910 &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) { 3911 goto out; 3912 } 3913 } else { 3914 if (rv != CRYPTO_SUCCESS) 3915 goto out; 3916 } 3917 3918 rv = (init)(real_provider, sp->sd_provider_session->ps_session, 3919 &mech, &key, NULL, &cc, NULL); 3920 3921 /* 3922 * Check if a context already exists. If so, it means it is being 3923 * abandoned. So, cancel it to avoid leaking it. 3924 */ 3925 if (*ctxpp != NULL) 3926 CRYPTO_CANCEL_CTX(ctxpp); 3927 *ctxpp = (rv == CRYPTO_SUCCESS) ? cc : NULL; 3928 3929 out: 3930 CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk); 3931 CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk); 3932 CRYPTO_SESSION_RELE(sp); 3933 crypto_release_minor(cm); 3934 3935 if (real_provider != NULL) { 3936 crypto_free_mech(real_provider, 3937 allocated_by_crypto_module, &mech); 3938 KCF_PROV_REFRELE(real_provider); 3939 } 3940 3941 free_crypto_key(&key); 3942 3943 if (error != 0) 3944 return (error); 3945 3946 STRUCT_FSET(sign_init, si_return_value, rv); 3947 if (copyout(STRUCT_BUF(sign_init), arg, STRUCT_SIZE(sign_init)) != 0) { 3948 return (EFAULT); 3949 } 3950 return (0); 3951 } 3952 3953 /* ARGSUSED */ 3954 static int 3955 sign(dev_t dev, caddr_t arg, int mode, int *rval) 3956 { 3957 return (common_digest(dev, arg, mode, crypto_sign_single)); 3958 } 3959 3960 /* ARGSUSED */ 3961 static int 3962 sign_recover(dev_t dev, caddr_t arg, int mode, int *rval) 3963 { 3964 return (common_digest(dev, arg, mode, crypto_sign_recover_single)); 3965 } 3966 3967 /* ARGSUSED */ 3968 static int 3969 verify(dev_t dev, caddr_t arg, int mode, int *rval) 3970 { 3971 STRUCT_DECL(crypto_verify, verify); 3972 crypto_session_id_t session_id; 3973 crypto_minor_t *cm; 3974 crypto_session_data_t *sp = NULL; 3975 crypto_data_t data, sign; 3976 size_t datalen, signlen, need = 0; 3977 int error = 0; 3978 int rv; 3979 boolean_t rctl_chk = B_FALSE; 3980 3981 STRUCT_INIT(verify, mode); 3982 3983 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3984 cmn_err(CE_WARN, "verify: failed holding minor"); 3985 return (ENXIO); 3986 } 3987 3988 if (copyin(arg, STRUCT_BUF(verify), STRUCT_SIZE(verify)) != 0) { 3989 crypto_release_minor(cm); 3990 return (EFAULT); 3991 } 3992 3993 data.cd_raw.iov_base = NULL; 3994 sign.cd_raw.iov_base = NULL; 3995 3996 datalen = STRUCT_FGET(verify, cv_datalen); 3997 signlen = STRUCT_FGET(verify, cv_signlen); 3998 if (datalen > crypto_max_buffer_len || 3999 signlen > crypto_max_buffer_len) { 4000 cmn_err(CE_NOTE, "verify: buffer greater than %ld bytes, " 4001 "pid = %d", crypto_max_buffer_len, curproc->p_pid); 4002 rv = CRYPTO_ARGUMENTS_BAD; 4003 goto release_minor; 4004 } 4005 4006 session_id = STRUCT_FGET(verify, cv_session); 4007 4008 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4009 goto release_minor; 4010 } 4011 4012 need = datalen + signlen; 4013 if ((rv = CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)) != 4014 CRYPTO_SUCCESS) { 4015 need = 0; 4016 goto release_minor; 4017 } 4018 4019 INIT_RAW_CRYPTO_DATA(data, datalen); 4020 INIT_RAW_CRYPTO_DATA(sign, signlen); 4021 4022 if (datalen != 0 && copyin(STRUCT_FGETP(verify, cv_databuf), 4023 data.cd_raw.iov_base, datalen) != 0) { 4024 error = EFAULT; 4025 goto release_minor; 4026 } 4027 4028 if (signlen != 0 && copyin(STRUCT_FGETP(verify, cv_signbuf), 4029 sign.cd_raw.iov_base, signlen) != 0) { 4030 error = EFAULT; 4031 goto release_minor; 4032 } 4033 4034 rv = crypto_verify_single(sp->sd_verify_ctx, &data, &sign, NULL); 4035 if (KCF_CONTEXT_DONE(rv)) 4036 sp->sd_verify_ctx = NULL; 4037 4038 release_minor: 4039 CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk); 4040 CRYPTO_SESSION_RELE(sp); 4041 crypto_release_minor(cm); 4042 4043 if (data.cd_raw.iov_base != NULL) 4044 kmem_free(data.cd_raw.iov_base, datalen); 4045 4046 if (sign.cd_raw.iov_base != NULL) 4047 kmem_free(sign.cd_raw.iov_base, signlen); 4048 4049 if (error != 0) 4050 return (error); 4051 4052 STRUCT_FSET(verify, cv_return_value, rv); 4053 if (copyout(STRUCT_BUF(verify), arg, STRUCT_SIZE(verify)) != 0) { 4054 return (EFAULT); 4055 } 4056 return (0); 4057 } 4058 4059 /* ARGSUSED */ 4060 static int 4061 verify_recover(dev_t dev, caddr_t arg, int mode, int *rval) 4062 { 4063 return (common_digest(dev, arg, mode, crypto_verify_recover_single)); 4064 } 4065 4066 /* ARGSUSED */ 4067 static int 4068 sign_update(dev_t dev, caddr_t arg, int mode, int *rval) 4069 { 4070 return (sign_verify_update(dev, arg, mode, crypto_sign_update)); 4071 } 4072 4073 /* ARGSUSED */ 4074 static int 4075 verify_update(dev_t dev, caddr_t arg, int mode, int *rval) 4076 { 4077 return (sign_verify_update(dev, arg, mode, crypto_verify_update)); 4078 } 4079 4080 /* 4081 * ASSUMPTION: crypto_sign_update and crypto_verify_update structures 4082 * are identical except for field names. 4083 */ 4084 static int 4085 sign_verify_update(dev_t dev, caddr_t arg, int mode, 4086 int (*update)(crypto_context_t, crypto_data_t *, crypto_call_req_t *)) 4087 { 4088 STRUCT_DECL(crypto_sign_update, sign_update); 4089 crypto_session_id_t session_id; 4090 crypto_minor_t *cm; 4091 crypto_session_data_t *sp = NULL; 4092 crypto_ctx_t **ctxpp; 4093 crypto_data_t data; 4094 size_t datalen, need = 0; 4095 int error = 0; 4096 int rv; 4097 boolean_t rctl_chk = B_FALSE; 4098 4099 STRUCT_INIT(sign_update, mode); 4100 4101 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4102 cmn_err(CE_WARN, "sign_verify_update: failed holding minor"); 4103 return (ENXIO); 4104 } 4105 4106 if (copyin(arg, STRUCT_BUF(sign_update), 4107 STRUCT_SIZE(sign_update)) != 0) { 4108 crypto_release_minor(cm); 4109 return (EFAULT); 4110 } 4111 4112 data.cd_raw.iov_base = NULL; 4113 4114 datalen = STRUCT_FGET(sign_update, su_datalen); 4115 if (datalen > crypto_max_buffer_len) { 4116 cmn_err(CE_NOTE, "sign_verify_update: buffer greater than %ld " 4117 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 4118 rv = CRYPTO_ARGUMENTS_BAD; 4119 goto release_minor; 4120 } 4121 4122 session_id = STRUCT_FGET(sign_update, su_session); 4123 4124 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4125 goto release_minor; 4126 } 4127 4128 if ((rv = CRYPTO_BUFFER_CHECK(sp, datalen, rctl_chk)) != 4129 CRYPTO_SUCCESS) { 4130 goto release_minor; 4131 } 4132 need = datalen; 4133 4134 INIT_RAW_CRYPTO_DATA(data, datalen); 4135 4136 if (datalen != 0 && copyin(STRUCT_FGETP(sign_update, su_databuf), 4137 data.cd_raw.iov_base, datalen) != 0) { 4138 error = EFAULT; 4139 goto release_minor; 4140 } 4141 4142 ctxpp = (update == crypto_sign_update) ? 4143 &sp->sd_sign_ctx : &sp->sd_verify_ctx; 4144 4145 rv = (update)(*ctxpp, &data, NULL); 4146 if (rv != CRYPTO_SUCCESS) 4147 CRYPTO_CANCEL_CTX(ctxpp); 4148 4149 release_minor: 4150 CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk); 4151 CRYPTO_SESSION_RELE(sp); 4152 crypto_release_minor(cm); 4153 4154 if (data.cd_raw.iov_base != NULL) 4155 kmem_free(data.cd_raw.iov_base, datalen); 4156 4157 if (error != 0) 4158 return (error); 4159 4160 STRUCT_FSET(sign_update, su_return_value, rv); 4161 if (copyout(STRUCT_BUF(sign_update), arg, 4162 STRUCT_SIZE(sign_update)) != 0) { 4163 return (EFAULT); 4164 } 4165 return (0); 4166 } 4167 4168 /* ARGSUSED */ 4169 static int 4170 sign_final(dev_t dev, caddr_t arg, int mode, int *rval) 4171 { 4172 return (common_final(dev, arg, mode, crypto_sign_final)); 4173 } 4174 4175 /* 4176 * Can't use the common final because it does a copyout of 4177 * the final part. 4178 */ 4179 /* ARGSUSED */ 4180 static int 4181 verify_final(dev_t dev, caddr_t arg, int mode, int *rval) 4182 { 4183 STRUCT_DECL(crypto_verify_final, verify_final); 4184 crypto_session_id_t session_id; 4185 crypto_minor_t *cm; 4186 crypto_session_data_t *sp = NULL; 4187 crypto_data_t sign; 4188 size_t signlen, need = 0; 4189 int error = 0; 4190 int rv; 4191 boolean_t rctl_chk = B_FALSE; 4192 4193 STRUCT_INIT(verify_final, mode); 4194 4195 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4196 cmn_err(CE_WARN, "verify_final: failed holding minor"); 4197 return (ENXIO); 4198 } 4199 4200 if (copyin(arg, STRUCT_BUF(verify_final), 4201 STRUCT_SIZE(verify_final)) != 0) { 4202 crypto_release_minor(cm); 4203 return (EFAULT); 4204 } 4205 4206 sign.cd_raw.iov_base = NULL; 4207 4208 signlen = STRUCT_FGET(verify_final, vf_signlen); 4209 if (signlen > crypto_max_buffer_len) { 4210 cmn_err(CE_NOTE, "verify_final: buffer greater than %ld " 4211 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 4212 rv = CRYPTO_ARGUMENTS_BAD; 4213 goto release_minor; 4214 } 4215 4216 session_id = STRUCT_FGET(verify_final, vf_session); 4217 4218 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4219 goto release_minor; 4220 } 4221 4222 if ((rv = CRYPTO_BUFFER_CHECK(sp, signlen, rctl_chk)) != 4223 CRYPTO_SUCCESS) { 4224 goto release_minor; 4225 } 4226 need = signlen; 4227 4228 INIT_RAW_CRYPTO_DATA(sign, signlen); 4229 4230 if (signlen != 0 && copyin(STRUCT_FGETP(verify_final, vf_signbuf), 4231 sign.cd_raw.iov_base, signlen) != 0) { 4232 error = EFAULT; 4233 goto release_minor; 4234 } 4235 4236 rv = crypto_verify_final(sp->sd_verify_ctx, &sign, NULL); 4237 if (KCF_CONTEXT_DONE(rv)) 4238 sp->sd_verify_ctx = NULL; 4239 4240 release_minor: 4241 CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk); 4242 CRYPTO_SESSION_RELE(sp); 4243 crypto_release_minor(cm); 4244 4245 if (sign.cd_raw.iov_base != NULL) 4246 kmem_free(sign.cd_raw.iov_base, signlen); 4247 4248 if (error != 0) 4249 return (error); 4250 4251 STRUCT_FSET(verify_final, vf_return_value, rv); 4252 if (copyout(STRUCT_BUF(verify_final), arg, 4253 STRUCT_SIZE(verify_final)) != 0) { 4254 return (EFAULT); 4255 } 4256 return (0); 4257 } 4258 4259 /* ARGSUSED */ 4260 static int 4261 seed_random(dev_t dev, caddr_t arg, int mode, int *rval) 4262 { 4263 STRUCT_DECL(crypto_seed_random, seed_random); 4264 kcf_provider_desc_t *real_provider = NULL; 4265 kcf_req_params_t params; 4266 crypto_session_id_t session_id; 4267 crypto_minor_t *cm; 4268 crypto_session_data_t *sp = NULL; 4269 uchar_t *seed_buffer = NULL; 4270 size_t seed_len; 4271 size_t need = 0; 4272 int error = 0; 4273 int rv; 4274 boolean_t rctl_chk = B_FALSE; 4275 4276 STRUCT_INIT(seed_random, mode); 4277 4278 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4279 cmn_err(CE_WARN, "seed_random: failed holding minor"); 4280 return (ENXIO); 4281 } 4282 4283 if (copyin(arg, STRUCT_BUF(seed_random), 4284 STRUCT_SIZE(seed_random)) != 0) { 4285 crypto_release_minor(cm); 4286 return (EFAULT); 4287 } 4288 4289 seed_len = STRUCT_FGET(seed_random, sr_seedlen); 4290 if (seed_len > crypto_max_buffer_len) { 4291 cmn_err(CE_NOTE, "seed_random: buffer greater than %ld " 4292 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 4293 rv = CRYPTO_ARGUMENTS_BAD; 4294 goto release_minor; 4295 } 4296 4297 session_id = STRUCT_FGET(seed_random, sr_session); 4298 4299 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4300 goto release_minor; 4301 } 4302 4303 if ((rv = CRYPTO_BUFFER_CHECK(sp, seed_len, rctl_chk)) != 4304 CRYPTO_SUCCESS) { 4305 goto release_minor; 4306 } 4307 need = seed_len; 4308 seed_buffer = kmem_alloc(seed_len, KM_SLEEP); 4309 4310 if (seed_len != 0 && copyin(STRUCT_FGETP(seed_random, sr_seedbuf), 4311 seed_buffer, seed_len) != 0) { 4312 error = EFAULT; 4313 goto release_minor; 4314 } 4315 4316 if ((rv = kcf_get_hardware_provider_nomech( 4317 CRYPTO_OPS_OFFSET(random_ops), CRYPTO_RANDOM_OFFSET(seed_random), 4318 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider)) 4319 != CRYPTO_SUCCESS) { 4320 goto release_minor; 4321 } 4322 4323 KCF_WRAP_RANDOM_OPS_PARAMS(¶ms, KCF_OP_RANDOM_SEED, 4324 sp->sd_provider_session->ps_session, seed_buffer, seed_len, 0, 4325 CRYPTO_SEED_NOW); 4326 4327 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4328 4329 release_minor: 4330 CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk); 4331 CRYPTO_SESSION_RELE(sp); 4332 crypto_release_minor(cm); 4333 4334 if (real_provider != NULL) 4335 KCF_PROV_REFRELE(real_provider); 4336 4337 if (seed_buffer != NULL) 4338 kmem_free(seed_buffer, seed_len); 4339 4340 if (error != 0) 4341 return (error); 4342 4343 STRUCT_FSET(seed_random, sr_return_value, rv); 4344 if (copyout(STRUCT_BUF(seed_random), arg, 4345 STRUCT_SIZE(seed_random)) != 0) { 4346 return (EFAULT); 4347 } 4348 return (0); 4349 } 4350 4351 /* ARGSUSED */ 4352 static int 4353 generate_random(dev_t dev, caddr_t arg, int mode, int *rval) 4354 { 4355 STRUCT_DECL(crypto_generate_random, generate_random); 4356 kcf_provider_desc_t *real_provider = NULL; 4357 kcf_req_params_t params; 4358 crypto_session_id_t session_id; 4359 crypto_minor_t *cm; 4360 crypto_session_data_t *sp = NULL; 4361 uchar_t *buffer = NULL; 4362 size_t len; 4363 size_t need = 0; 4364 int error = 0; 4365 int rv; 4366 boolean_t rctl_chk = B_FALSE; 4367 4368 STRUCT_INIT(generate_random, mode); 4369 4370 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4371 cmn_err(CE_WARN, "generate_random: failed holding minor"); 4372 return (ENXIO); 4373 } 4374 4375 if (copyin(arg, STRUCT_BUF(generate_random), 4376 STRUCT_SIZE(generate_random)) != 0) { 4377 crypto_release_minor(cm); 4378 return (EFAULT); 4379 } 4380 4381 len = STRUCT_FGET(generate_random, gr_buflen); 4382 if (len > crypto_max_buffer_len) { 4383 cmn_err(CE_NOTE, "generate_random: buffer greater than %ld " 4384 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 4385 rv = CRYPTO_ARGUMENTS_BAD; 4386 goto release_minor; 4387 } 4388 4389 session_id = STRUCT_FGET(generate_random, gr_session); 4390 4391 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4392 goto release_minor; 4393 } 4394 4395 if ((rv = CRYPTO_BUFFER_CHECK(sp, len, rctl_chk)) != 4396 CRYPTO_SUCCESS) { 4397 goto release_minor; 4398 } 4399 need = len; 4400 buffer = kmem_alloc(len, KM_SLEEP); 4401 4402 if ((rv = kcf_get_hardware_provider_nomech( 4403 CRYPTO_OPS_OFFSET(random_ops), 4404 CRYPTO_RANDOM_OFFSET(generate_random), CHECK_RESTRICT_FALSE, 4405 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 4406 goto release_minor; 4407 } 4408 4409 KCF_WRAP_RANDOM_OPS_PARAMS(¶ms, KCF_OP_RANDOM_GENERATE, 4410 sp->sd_provider_session->ps_session, buffer, len, 0, 0); 4411 4412 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4413 4414 if (rv == CRYPTO_SUCCESS) { 4415 if (len != 0 && copyout(buffer, 4416 STRUCT_FGETP(generate_random, gr_buf), len) != 0) { 4417 error = EFAULT; 4418 } 4419 } 4420 4421 release_minor: 4422 CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk); 4423 CRYPTO_SESSION_RELE(sp); 4424 crypto_release_minor(cm); 4425 4426 if (real_provider != NULL) 4427 KCF_PROV_REFRELE(real_provider); 4428 4429 if (buffer != NULL) { 4430 /* random numbers are often used to create keys */ 4431 bzero(buffer, len); 4432 kmem_free(buffer, len); 4433 } 4434 4435 if (error != 0) 4436 return (error); 4437 4438 STRUCT_FSET(generate_random, gr_return_value, rv); 4439 if (copyout(STRUCT_BUF(generate_random), arg, 4440 STRUCT_SIZE(generate_random)) != 0) { 4441 return (EFAULT); 4442 } 4443 return (0); 4444 } 4445 4446 /* 4447 * Copyout a kernel array of attributes to user space. 4448 * u_attrs is the corresponding user space array containing 4449 * user space pointers necessary for the copyout. 4450 */ 4451 /* ARGSUSED */ 4452 static int 4453 copyout_attributes(int mode, caddr_t out, uint_t count, 4454 crypto_object_attribute_t *k_attrs, caddr_t u_attrs) 4455 { 4456 STRUCT_DECL(crypto_object_attribute, oa); 4457 caddr_t p, valuep; 4458 size_t value_len; 4459 size_t len; 4460 int i; 4461 int error = 0; 4462 4463 if (count == 0) 4464 return (0); 4465 4466 STRUCT_INIT(oa, mode); 4467 4468 len = count * STRUCT_SIZE(oa); 4469 4470 ASSERT(u_attrs != NULL); 4471 p = u_attrs; 4472 for (i = 0; i < count; i++) { 4473 /* can this bcopy be eliminated? */ 4474 bcopy(p, STRUCT_BUF(oa), STRUCT_SIZE(oa)); 4475 value_len = k_attrs[i].oa_value_len; 4476 STRUCT_FSET(oa, oa_type, k_attrs[i].oa_type); 4477 STRUCT_FSET(oa, oa_value_len, value_len); 4478 valuep = STRUCT_FGETP(oa, oa_value); 4479 if (valuep != NULL && value_len != -1) { 4480 if (copyout(k_attrs[i].oa_value, 4481 valuep, value_len) != 0) { 4482 error = EFAULT; 4483 goto out; 4484 } 4485 } 4486 bcopy(STRUCT_BUF(oa), p, STRUCT_SIZE(oa)); 4487 p += STRUCT_SIZE(oa); 4488 } 4489 if (copyout(u_attrs, out, len)) { 4490 error = EFAULT; 4491 } 4492 out: 4493 return (error); 4494 } 4495 4496 4497 /* ARGSUSED */ 4498 static int 4499 object_create(dev_t dev, caddr_t arg, int mode, int *rval) 4500 { 4501 STRUCT_DECL(crypto_object_create, object_create); 4502 kcf_provider_desc_t *real_provider = NULL; 4503 kcf_req_params_t params; 4504 crypto_object_attribute_t *k_attrs = NULL; 4505 crypto_session_id_t session_id; 4506 crypto_minor_t *cm; 4507 crypto_session_data_t *sp = NULL; 4508 crypto_object_id_t object_handle; 4509 caddr_t oc_attributes; 4510 size_t k_attrs_size; 4511 size_t rctl_bytes = 0; 4512 boolean_t rctl_chk = B_FALSE; 4513 int error = 0; 4514 int rv; 4515 uint_t count; 4516 4517 STRUCT_INIT(object_create, mode); 4518 4519 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4520 cmn_err(CE_WARN, "object_create: failed holding minor"); 4521 return (ENXIO); 4522 } 4523 4524 if (copyin(arg, STRUCT_BUF(object_create), 4525 STRUCT_SIZE(object_create)) != 0) { 4526 crypto_release_minor(cm); 4527 return (EFAULT); 4528 } 4529 4530 count = STRUCT_FGET(object_create, oc_count); 4531 oc_attributes = STRUCT_FGETP(object_create, oc_attributes); 4532 4533 session_id = STRUCT_FGET(object_create, oc_session); 4534 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4535 goto release_minor; 4536 } 4537 if (!copyin_attributes(mode, sp, count, oc_attributes, &k_attrs, 4538 &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 4539 &rctl_chk, B_TRUE)) { 4540 goto release_minor; 4541 } 4542 4543 if ((rv = kcf_get_hardware_provider_nomech( 4544 CRYPTO_OPS_OFFSET(object_ops), 4545 CRYPTO_OBJECT_OFFSET(object_create), 4546 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider)) 4547 != CRYPTO_SUCCESS) { 4548 goto release_minor; 4549 } 4550 4551 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_CREATE, 4552 sp->sd_provider_session->ps_session, 0, k_attrs, count, 4553 &object_handle, 0, NULL, NULL, 0, NULL); 4554 4555 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4556 4557 if (rv == CRYPTO_SUCCESS) 4558 STRUCT_FSET(object_create, oc_handle, object_handle); 4559 4560 release_minor: 4561 CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk); 4562 4563 if (k_attrs != NULL) 4564 kmem_free(k_attrs, k_attrs_size); 4565 4566 if (error != 0) 4567 goto out; 4568 4569 STRUCT_FSET(object_create, oc_return_value, rv); 4570 if (copyout(STRUCT_BUF(object_create), arg, 4571 STRUCT_SIZE(object_create)) != 0) { 4572 if (rv == CRYPTO_SUCCESS) { 4573 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 4574 KCF_OP_OBJECT_DESTROY, 4575 sp->sd_provider_session->ps_session, object_handle, 4576 NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 4577 4578 (void) kcf_submit_request(real_provider, NULL, 4579 NULL, ¶ms, B_FALSE); 4580 4581 error = EFAULT; 4582 } 4583 } 4584 out: 4585 CRYPTO_SESSION_RELE(sp); 4586 crypto_release_minor(cm); 4587 if (real_provider != NULL) 4588 KCF_PROV_REFRELE(real_provider); 4589 return (error); 4590 } 4591 4592 /* ARGSUSED */ 4593 static int 4594 object_copy(dev_t dev, caddr_t arg, int mode, int *rval) 4595 { 4596 STRUCT_DECL(crypto_object_copy, object_copy); 4597 kcf_provider_desc_t *real_provider = NULL; 4598 kcf_req_params_t params; 4599 crypto_object_attribute_t *k_attrs = NULL; 4600 crypto_session_id_t session_id; 4601 crypto_minor_t *cm; 4602 crypto_session_data_t *sp = NULL; 4603 crypto_object_id_t handle, new_handle; 4604 caddr_t oc_new_attributes; 4605 size_t k_attrs_size; 4606 size_t rctl_bytes = 0; 4607 boolean_t rctl_chk = B_FALSE; 4608 int error = 0; 4609 int rv; 4610 uint_t count; 4611 4612 STRUCT_INIT(object_copy, mode); 4613 4614 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4615 cmn_err(CE_WARN, "object_copy: failed holding minor"); 4616 return (ENXIO); 4617 } 4618 4619 if (copyin(arg, STRUCT_BUF(object_copy), 4620 STRUCT_SIZE(object_copy)) != 0) { 4621 crypto_release_minor(cm); 4622 return (EFAULT); 4623 } 4624 4625 count = STRUCT_FGET(object_copy, oc_count); 4626 oc_new_attributes = STRUCT_FGETP(object_copy, oc_new_attributes); 4627 4628 session_id = STRUCT_FGET(object_copy, oc_session); 4629 4630 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4631 goto release_minor; 4632 } 4633 if (!copyin_attributes(mode, sp, count, oc_new_attributes, &k_attrs, 4634 &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 4635 &rctl_chk, B_TRUE)) { 4636 goto release_minor; 4637 } 4638 4639 if ((rv = kcf_get_hardware_provider_nomech( 4640 CRYPTO_OPS_OFFSET(object_ops), 4641 CRYPTO_OBJECT_OFFSET(object_copy), CHECK_RESTRICT_FALSE, 4642 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 4643 goto release_minor; 4644 } 4645 4646 handle = STRUCT_FGET(object_copy, oc_handle); 4647 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_COPY, 4648 sp->sd_provider_session->ps_session, handle, k_attrs, count, 4649 &new_handle, 0, NULL, NULL, 0, NULL); 4650 4651 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4652 4653 if (rv == CRYPTO_SUCCESS) 4654 STRUCT_FSET(object_copy, oc_new_handle, new_handle); 4655 4656 release_minor: 4657 CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk); 4658 4659 if (k_attrs != NULL) 4660 kmem_free(k_attrs, k_attrs_size); 4661 4662 if (error != 0) 4663 goto out; 4664 4665 STRUCT_FSET(object_copy, oc_return_value, rv); 4666 if (copyout(STRUCT_BUF(object_copy), arg, 4667 STRUCT_SIZE(object_copy)) != 0) { 4668 if (rv == CRYPTO_SUCCESS) { 4669 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 4670 KCF_OP_OBJECT_DESTROY, 4671 sp->sd_provider_session->ps_session, new_handle, 4672 NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 4673 4674 (void) kcf_submit_request(real_provider, NULL, 4675 NULL, ¶ms, B_FALSE); 4676 4677 error = EFAULT; 4678 } 4679 } 4680 out: 4681 CRYPTO_SESSION_RELE(sp); 4682 crypto_release_minor(cm); 4683 if (real_provider != NULL) 4684 KCF_PROV_REFRELE(real_provider); 4685 return (error); 4686 } 4687 4688 /* ARGSUSED */ 4689 static int 4690 object_destroy(dev_t dev, caddr_t arg, int mode, int *rval) 4691 { 4692 STRUCT_DECL(crypto_object_destroy, object_destroy); 4693 kcf_provider_desc_t *real_provider; 4694 kcf_req_params_t params; 4695 crypto_session_id_t session_id; 4696 crypto_minor_t *cm; 4697 crypto_session_data_t *sp; 4698 crypto_object_id_t handle; 4699 int error = 0; 4700 int rv; 4701 4702 STRUCT_INIT(object_destroy, mode); 4703 4704 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4705 cmn_err(CE_WARN, "object_destroy: failed holding minor"); 4706 return (ENXIO); 4707 } 4708 4709 if (copyin(arg, STRUCT_BUF(object_destroy), 4710 STRUCT_SIZE(object_destroy)) != 0) { 4711 crypto_release_minor(cm); 4712 return (EFAULT); 4713 } 4714 4715 session_id = STRUCT_FGET(object_destroy, od_session); 4716 4717 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4718 goto release_minor; 4719 } 4720 4721 if ((rv = kcf_get_hardware_provider_nomech( 4722 CRYPTO_OPS_OFFSET(object_ops), 4723 CRYPTO_OBJECT_OFFSET(object_destroy), CHECK_RESTRICT_FALSE, 4724 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 4725 goto out; 4726 } 4727 4728 handle = STRUCT_FGET(object_destroy, od_handle); 4729 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_DESTROY, 4730 sp->sd_provider_session->ps_session, handle, NULL, 0, NULL, 0, 4731 NULL, NULL, 0, NULL); 4732 4733 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4734 KCF_PROV_REFRELE(real_provider); 4735 4736 out: 4737 CRYPTO_SESSION_RELE(sp); 4738 4739 release_minor: 4740 crypto_release_minor(cm); 4741 4742 if (error != 0) 4743 return (error); 4744 4745 STRUCT_FSET(object_destroy, od_return_value, rv); 4746 4747 if (copyout(STRUCT_BUF(object_destroy), arg, 4748 STRUCT_SIZE(object_destroy)) != 0) { 4749 return (EFAULT); 4750 } 4751 return (0); 4752 } 4753 4754 /* ARGSUSED */ 4755 static int 4756 object_get_attribute_value(dev_t dev, caddr_t arg, int mode, int *rval) 4757 { 4758 STRUCT_DECL(crypto_object_get_attribute_value, get_attribute_value); 4759 /* LINTED E_FUNC_SET_NOT_USED */ 4760 STRUCT_DECL(crypto_object_attribute, oa); 4761 kcf_provider_desc_t *real_provider; 4762 kcf_req_params_t params; 4763 crypto_object_attribute_t *k_attrs = NULL; 4764 crypto_session_id_t session_id; 4765 crypto_minor_t *cm; 4766 crypto_session_data_t *sp = NULL; 4767 crypto_object_id_t handle; 4768 caddr_t og_attributes; 4769 caddr_t u_attrs = NULL; 4770 size_t k_attrs_size; 4771 size_t rctl_bytes = 0; 4772 boolean_t rctl_chk = B_FALSE; 4773 int error = 0; 4774 int rv; 4775 uint_t count; 4776 4777 STRUCT_INIT(get_attribute_value, mode); 4778 STRUCT_INIT(oa, mode); 4779 4780 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4781 cmn_err(CE_WARN, 4782 "object_get_attribute_value: failed holding minor"); 4783 return (ENXIO); 4784 } 4785 4786 if (copyin(arg, STRUCT_BUF(get_attribute_value), 4787 STRUCT_SIZE(get_attribute_value)) != 0) { 4788 crypto_release_minor(cm); 4789 return (EFAULT); 4790 } 4791 4792 count = STRUCT_FGET(get_attribute_value, og_count); 4793 og_attributes = STRUCT_FGETP(get_attribute_value, og_attributes); 4794 4795 session_id = STRUCT_FGET(get_attribute_value, og_session); 4796 4797 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4798 goto release_minor; 4799 } 4800 if (!copyin_attributes(mode, sp, count, og_attributes, &k_attrs, 4801 &k_attrs_size, &u_attrs, &rv, &error, &rctl_bytes, 4802 &rctl_chk, B_FALSE)) { 4803 goto release_minor; 4804 } 4805 4806 if ((rv = kcf_get_hardware_provider_nomech( 4807 CRYPTO_OPS_OFFSET(object_ops), 4808 CRYPTO_OBJECT_OFFSET(object_get_attribute_value), 4809 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider)) 4810 != CRYPTO_SUCCESS) { 4811 goto out; 4812 } 4813 4814 handle = STRUCT_FGET(get_attribute_value, og_handle); 4815 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_GET_ATTRIBUTE_VALUE, 4816 sp->sd_provider_session->ps_session, handle, k_attrs, count, NULL, 4817 0, NULL, NULL, 0, NULL); 4818 4819 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4820 KCF_PROV_REFRELE(real_provider); 4821 4822 out: 4823 if (rv == CRYPTO_SUCCESS || rv == CRYPTO_ATTRIBUTE_SENSITIVE || 4824 rv == CRYPTO_ATTRIBUTE_TYPE_INVALID || 4825 rv == CRYPTO_BUFFER_TOO_SMALL) { 4826 error = copyout_attributes(mode, 4827 STRUCT_FGETP(get_attribute_value, og_attributes), 4828 count, k_attrs, u_attrs); 4829 } 4830 4831 release_minor: 4832 CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk); 4833 CRYPTO_SESSION_RELE(sp); 4834 crypto_release_minor(cm); 4835 4836 if (k_attrs != NULL) 4837 kmem_free(k_attrs, k_attrs_size); 4838 4839 if (u_attrs != NULL) 4840 kmem_free(u_attrs, count * STRUCT_SIZE(oa)); 4841 4842 if (error != 0) 4843 return (error); 4844 4845 STRUCT_FSET(get_attribute_value, og_return_value, rv); 4846 if (copyout(STRUCT_BUF(get_attribute_value), arg, 4847 STRUCT_SIZE(get_attribute_value)) != 0) { 4848 return (EFAULT); 4849 } 4850 return (0); 4851 } 4852 4853 /* ARGSUSED */ 4854 static int 4855 object_get_size(dev_t dev, caddr_t arg, int mode, int *rval) 4856 { 4857 STRUCT_DECL(crypto_object_get_size, object_get_size); 4858 kcf_provider_desc_t *real_provider; 4859 kcf_req_params_t params; 4860 crypto_session_id_t session_id; 4861 crypto_minor_t *cm; 4862 crypto_session_data_t *sp = NULL; 4863 crypto_object_id_t handle; 4864 size_t size; 4865 int error = 0; 4866 int rv; 4867 4868 STRUCT_INIT(object_get_size, mode); 4869 4870 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4871 cmn_err(CE_WARN, "object_get_size: failed holding minor"); 4872 return (ENXIO); 4873 } 4874 4875 if (copyin(arg, STRUCT_BUF(object_get_size), 4876 STRUCT_SIZE(object_get_size)) != 0) { 4877 crypto_release_minor(cm); 4878 return (EFAULT); 4879 } 4880 4881 session_id = STRUCT_FGET(object_get_size, gs_session); 4882 4883 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4884 goto release_minor; 4885 } 4886 4887 if ((rv = kcf_get_hardware_provider_nomech( 4888 CRYPTO_OPS_OFFSET(object_ops), 4889 CRYPTO_OBJECT_OFFSET(object_get_size), CHECK_RESTRICT_FALSE, 4890 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 4891 goto release_minor; 4892 } 4893 4894 handle = STRUCT_FGET(object_get_size, gs_handle); 4895 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_GET_SIZE, 4896 sp->sd_provider_session->ps_session, handle, NULL, 0, NULL, &size, 4897 NULL, NULL, 0, NULL); 4898 4899 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4900 KCF_PROV_REFRELE(real_provider); 4901 4902 if (rv == CRYPTO_SUCCESS) { 4903 STRUCT_FSET(object_get_size, gs_size, size); 4904 } 4905 4906 release_minor: 4907 crypto_release_minor(cm); 4908 CRYPTO_SESSION_RELE(sp); 4909 4910 if (error != 0) 4911 return (error); 4912 4913 STRUCT_FSET(object_get_size, gs_return_value, rv); 4914 if (copyout(STRUCT_BUF(object_get_size), arg, 4915 STRUCT_SIZE(object_get_size)) != 0) { 4916 return (EFAULT); 4917 } 4918 return (0); 4919 } 4920 4921 /* ARGSUSED */ 4922 static int 4923 object_set_attribute_value(dev_t dev, caddr_t arg, int mode, int *rval) 4924 { 4925 STRUCT_DECL(crypto_object_set_attribute_value, set_attribute_value); 4926 kcf_provider_desc_t *real_provider; 4927 kcf_req_params_t params; 4928 crypto_object_attribute_t *k_attrs = NULL; 4929 crypto_session_id_t session_id; 4930 crypto_minor_t *cm; 4931 crypto_session_data_t *sp = NULL; 4932 crypto_object_id_t object_handle; 4933 caddr_t sa_attributes; 4934 size_t k_attrs_size; 4935 size_t rctl_bytes = 0; 4936 boolean_t rctl_chk = B_FALSE; 4937 int error = 0; 4938 int rv; 4939 uint_t count; 4940 4941 STRUCT_INIT(set_attribute_value, mode); 4942 4943 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4944 cmn_err(CE_WARN, 4945 "object_set_attribute_value: failed holding minor"); 4946 return (ENXIO); 4947 } 4948 4949 if (copyin(arg, STRUCT_BUF(set_attribute_value), 4950 STRUCT_SIZE(set_attribute_value)) != 0) { 4951 crypto_release_minor(cm); 4952 return (EFAULT); 4953 } 4954 4955 count = STRUCT_FGET(set_attribute_value, sa_count); 4956 sa_attributes = STRUCT_FGETP(set_attribute_value, sa_attributes); 4957 4958 session_id = STRUCT_FGET(set_attribute_value, sa_session); 4959 4960 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4961 goto release_minor; 4962 } 4963 if (!copyin_attributes(mode, sp, count, sa_attributes, &k_attrs, 4964 &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 4965 &rctl_chk, B_TRUE)) { 4966 goto release_minor; 4967 } 4968 4969 if ((rv = kcf_get_hardware_provider_nomech( 4970 CRYPTO_OPS_OFFSET(object_ops), 4971 CRYPTO_OBJECT_OFFSET(object_set_attribute_value), 4972 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider)) 4973 != CRYPTO_SUCCESS) { 4974 goto release_minor; 4975 } 4976 4977 object_handle = STRUCT_FGET(set_attribute_value, sa_handle); 4978 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_SET_ATTRIBUTE_VALUE, 4979 sp->sd_provider_session->ps_session, object_handle, k_attrs, count, 4980 NULL, 0, NULL, NULL, 0, NULL); 4981 4982 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4983 KCF_PROV_REFRELE(real_provider); 4984 4985 release_minor: 4986 CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk); 4987 CRYPTO_SESSION_RELE(sp); 4988 crypto_release_minor(cm); 4989 4990 if (k_attrs != NULL) 4991 kmem_free(k_attrs, k_attrs_size); 4992 4993 if (error != 0) 4994 return (error); 4995 4996 STRUCT_FSET(set_attribute_value, sa_return_value, rv); 4997 if (copyout(STRUCT_BUF(set_attribute_value), arg, 4998 STRUCT_SIZE(set_attribute_value)) != 0) { 4999 return (EFAULT); 5000 } 5001 return (0); 5002 } 5003 5004 /* ARGSUSED */ 5005 static int 5006 object_find_init(dev_t dev, caddr_t arg, int mode, int *rval) 5007 { 5008 STRUCT_DECL(crypto_object_find_init, find_init); 5009 kcf_provider_desc_t *real_provider = NULL; 5010 kcf_req_params_t params; 5011 crypto_object_attribute_t *k_attrs = NULL; 5012 crypto_session_id_t session_id; 5013 crypto_minor_t *cm; 5014 crypto_session_data_t *sp = NULL; 5015 caddr_t attributes; 5016 size_t k_attrs_size; 5017 size_t rctl_bytes = 0; 5018 boolean_t rctl_chk = B_FALSE; 5019 int error = 0; 5020 int rv; 5021 uint_t count; 5022 void *cookie; 5023 5024 STRUCT_INIT(find_init, mode); 5025 5026 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 5027 cmn_err(CE_WARN, "object_find_init: failed holding minor"); 5028 return (ENXIO); 5029 } 5030 5031 if (copyin(arg, STRUCT_BUF(find_init), STRUCT_SIZE(find_init)) != 0) { 5032 crypto_release_minor(cm); 5033 return (EFAULT); 5034 } 5035 5036 count = STRUCT_FGET(find_init, fi_count); 5037 attributes = STRUCT_FGETP(find_init, fi_attributes); 5038 5039 session_id = STRUCT_FGET(find_init, fi_session); 5040 5041 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 5042 goto release_minor; 5043 } 5044 if (!copyin_attributes(mode, sp, count, attributes, &k_attrs, 5045 &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 5046 &rctl_chk, B_TRUE)) { 5047 goto release_minor; 5048 } 5049 5050 if ((rv = kcf_get_hardware_provider_nomech( 5051 CRYPTO_OPS_OFFSET(object_ops), 5052 CRYPTO_OBJECT_OFFSET(object_find_init), CHECK_RESTRICT_FALSE, 5053 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 5054 goto release_minor; 5055 } 5056 5057 /* check for an active find */ 5058 if (sp->sd_find_init_cookie != NULL) { 5059 rv = CRYPTO_OPERATION_IS_ACTIVE; 5060 goto release_minor; 5061 } 5062 5063 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_FIND_INIT, 5064 sp->sd_provider_session->ps_session, 0, k_attrs, count, NULL, 0, 5065 &cookie, NULL, 0, NULL); 5066 5067 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5068 5069 if (rv == CRYPTO_SUCCESS) { 5070 /* 5071 * The cookie is allocated by a provider at the start of an 5072 * object search. It is freed when the search is terminated 5073 * by a final operation, or when the session is closed. 5074 * It contains state information about which object handles 5075 * have been returned to the caller. 5076 */ 5077 sp->sd_find_init_cookie = cookie; 5078 } 5079 5080 release_minor: 5081 CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk); 5082 CRYPTO_SESSION_RELE(sp); 5083 crypto_release_minor(cm); 5084 5085 if (real_provider != NULL) 5086 KCF_PROV_REFRELE(real_provider); 5087 5088 if (k_attrs != NULL) 5089 kmem_free(k_attrs, k_attrs_size); 5090 5091 if (error != 0) 5092 return (error); 5093 5094 STRUCT_FSET(find_init, fi_return_value, rv); 5095 if (copyout(STRUCT_BUF(find_init), arg, STRUCT_SIZE(find_init)) != 0) { 5096 return (EFAULT); 5097 } 5098 return (0); 5099 } 5100 5101 /* ARGSUSED */ 5102 static int 5103 object_find_update(dev_t dev, caddr_t arg, int mode, int *rval) 5104 { 5105 STRUCT_DECL(crypto_object_find_update, find_update); 5106 kcf_provider_desc_t *real_provider; 5107 kcf_req_params_t params; 5108 crypto_minor_t *cm; 5109 crypto_session_data_t *sp = NULL; 5110 crypto_object_id_t *buffer = NULL; 5111 crypto_session_id_t session_id; 5112 size_t len, rctl_bytes = 0; 5113 uint_t count, max_count; 5114 int rv, error = 0; 5115 boolean_t rctl_chk = B_FALSE; 5116 5117 STRUCT_INIT(find_update, mode); 5118 5119 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 5120 cmn_err(CE_WARN, "object_find_update: failed holding minor"); 5121 return (ENXIO); 5122 } 5123 5124 if (copyin(arg, STRUCT_BUF(find_update), 5125 STRUCT_SIZE(find_update)) != 0) { 5126 crypto_release_minor(cm); 5127 return (EFAULT); 5128 } 5129 5130 max_count = STRUCT_FGET(find_update, fu_max_count); 5131 if (max_count > CRYPTO_MAX_FIND_COUNT) { 5132 cmn_err(CE_NOTE, "object_find_update: count greater than %d, " 5133 "pid = %d", CRYPTO_MAX_FIND_COUNT, curproc->p_pid); 5134 rv = CRYPTO_ARGUMENTS_BAD; 5135 goto release_minor; 5136 } 5137 len = max_count * sizeof (crypto_object_id_t); 5138 session_id = STRUCT_FGET(find_update, fu_session); 5139 5140 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 5141 goto release_minor; 5142 } 5143 if ((rv = CRYPTO_BUFFER_CHECK(sp, len, rctl_chk)) != 5144 CRYPTO_SUCCESS) { 5145 goto release_minor; 5146 } 5147 rctl_bytes = len; 5148 buffer = kmem_alloc(len, KM_SLEEP); 5149 5150 if ((rv = kcf_get_hardware_provider_nomech( 5151 CRYPTO_OPS_OFFSET(object_ops), 5152 CRYPTO_OBJECT_OFFSET(object_find), CHECK_RESTRICT_FALSE, 5153 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 5154 goto release_minor; 5155 } 5156 5157 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_FIND, 5158 sp->sd_provider_session->ps_session, 0, NULL, 0, buffer, 0, 5159 NULL, sp->sd_find_init_cookie, max_count, &count); 5160 5161 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5162 KCF_PROV_REFRELE(real_provider); 5163 5164 if (rv == CRYPTO_SUCCESS) { 5165 if (count > max_count) { 5166 /* bad bad provider */ 5167 rv = CRYPTO_FAILED; 5168 goto release_minor; 5169 } 5170 if (count != 0) { 5171 /* copyout handles */ 5172 if (copyout(buffer, 5173 STRUCT_FGETP(find_update, fu_handles), 5174 count * sizeof (crypto_object_id_t)) != 0) { 5175 error = EFAULT; 5176 } 5177 } 5178 STRUCT_FSET(find_update, fu_count, count); 5179 } 5180 5181 release_minor: 5182 CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk); 5183 CRYPTO_SESSION_RELE(sp); 5184 crypto_release_minor(cm); 5185 5186 if (buffer != NULL) 5187 kmem_free(buffer, len); 5188 5189 if (error != 0) 5190 return (error); 5191 5192 STRUCT_FSET(find_update, fu_return_value, rv); 5193 if (copyout(STRUCT_BUF(find_update), arg, 5194 STRUCT_SIZE(find_update)) != 0) { 5195 return (EFAULT); 5196 } 5197 5198 return (0); 5199 } 5200 5201 /* 5202 * Free provider-allocated storage used for find object searches. 5203 */ 5204 static int 5205 crypto_free_find_ctx(crypto_session_data_t *sp) 5206 { 5207 kcf_provider_desc_t *real_provider; 5208 kcf_req_params_t params; 5209 int rv; 5210 5211 if ((rv = kcf_get_hardware_provider_nomech( 5212 CRYPTO_OPS_OFFSET(object_ops), 5213 CRYPTO_OBJECT_OFFSET(object_find_final), CHECK_RESTRICT_FALSE, 5214 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 5215 return (rv); 5216 } 5217 5218 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_FIND_FINAL, 5219 sp->sd_provider_session->ps_session, 0, NULL, 0, NULL, 0, 5220 NULL, sp->sd_find_init_cookie, 0, NULL); 5221 5222 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5223 KCF_PROV_REFRELE(real_provider); 5224 return (rv); 5225 } 5226 5227 /* ARGSUSED */ 5228 static int 5229 object_find_final(dev_t dev, caddr_t arg, int mode, int *rval) 5230 { 5231 STRUCT_DECL(crypto_object_find_final, object_find_final); 5232 crypto_session_id_t session_id; 5233 crypto_minor_t *cm; 5234 crypto_session_data_t *sp; 5235 int error = 0; 5236 int rv; 5237 5238 STRUCT_INIT(object_find_final, mode); 5239 5240 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 5241 cmn_err(CE_WARN, "object_find_final: failed holding minor"); 5242 return (ENXIO); 5243 } 5244 5245 if (copyin(arg, STRUCT_BUF(object_find_final), 5246 STRUCT_SIZE(object_find_final)) != 0) { 5247 crypto_release_minor(cm); 5248 return (EFAULT); 5249 } 5250 5251 session_id = STRUCT_FGET(object_find_final, ff_session); 5252 5253 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 5254 goto release_minor; 5255 } 5256 5257 if ((rv = crypto_free_find_ctx(sp)) == CRYPTO_SUCCESS) { 5258 sp->sd_find_init_cookie = NULL; 5259 } 5260 5261 CRYPTO_SESSION_RELE(sp); 5262 5263 release_minor: 5264 crypto_release_minor(cm); 5265 5266 if (error != 0) 5267 return (error); 5268 5269 STRUCT_FSET(object_find_final, ff_return_value, rv); 5270 5271 if (copyout(STRUCT_BUF(object_find_final), arg, 5272 STRUCT_SIZE(object_find_final)) != 0) { 5273 return (EFAULT); 5274 } 5275 return (0); 5276 } 5277 5278 /* ARGSUSED */ 5279 static int 5280 object_generate_key(dev_t dev, caddr_t arg, int mode, int *rval) 5281 { 5282 STRUCT_DECL(crypto_object_generate_key, generate_key); 5283 kcf_provider_desc_t *real_provider = NULL; 5284 kcf_req_params_t params; 5285 crypto_mechanism_t mech; 5286 crypto_object_attribute_t *k_attrs = NULL; 5287 crypto_session_id_t session_id; 5288 crypto_minor_t *cm; 5289 crypto_session_data_t *sp = NULL; 5290 crypto_object_id_t key_handle; 5291 caddr_t attributes; 5292 size_t k_attrs_size; 5293 size_t mech_rctl_bytes = 0, key_rctl_bytes = 0; 5294 boolean_t mech_rctl_chk = B_FALSE; 5295 boolean_t key_rctl_chk = B_FALSE; 5296 uint_t count; 5297 int error = 0; 5298 int rv; 5299 boolean_t allocated_by_crypto_module = B_FALSE; 5300 5301 STRUCT_INIT(generate_key, mode); 5302 5303 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 5304 cmn_err(CE_WARN, "object_generate_key: failed holding minor"); 5305 return (ENXIO); 5306 } 5307 5308 if (copyin(arg, STRUCT_BUF(generate_key), 5309 STRUCT_SIZE(generate_key)) != 0) { 5310 crypto_release_minor(cm); 5311 return (EFAULT); 5312 } 5313 5314 session_id = STRUCT_FGET(generate_key, gk_session); 5315 5316 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 5317 goto release_minor; 5318 } 5319 5320 bcopy(STRUCT_FADDR(generate_key, gk_mechanism), &mech.cm_type, 5321 sizeof (crypto_mech_type_t)); 5322 5323 if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL, 5324 CRYPTO_MECH_INVALID, NULL, CHECK_RESTRICT_FALSE, sp->sd_provider, 5325 &real_provider, CRYPTO_FG_GENERATE)) != CRYPTO_SUCCESS) { 5326 goto release_minor; 5327 } 5328 5329 rv = crypto_provider_copyin_mech_param(real_provider, 5330 STRUCT_FADDR(generate_key, gk_mechanism), &mech, mode, &error); 5331 5332 if (rv == CRYPTO_NOT_SUPPORTED) { 5333 allocated_by_crypto_module = B_TRUE; 5334 if (!copyin_mech(mode, sp, 5335 STRUCT_FADDR(generate_key, gk_mechanism), 5336 &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) { 5337 goto release_minor; 5338 } 5339 } else { 5340 if (rv != CRYPTO_SUCCESS) 5341 goto release_minor; 5342 } 5343 5344 count = STRUCT_FGET(generate_key, gk_count); 5345 attributes = STRUCT_FGETP(generate_key, gk_attributes); 5346 if (!copyin_attributes(mode, sp, count, attributes, &k_attrs, 5347 &k_attrs_size, NULL, &rv, &error, &key_rctl_bytes, 5348 &key_rctl_chk, B_TRUE)) { 5349 goto release_minor; 5350 } 5351 5352 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_GENERATE, 5353 sp->sd_provider_session->ps_session, &mech, k_attrs, count, 5354 &key_handle, NULL, 0, NULL, NULL, NULL, 0); 5355 5356 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5357 5358 if (rv == CRYPTO_SUCCESS) 5359 STRUCT_FSET(generate_key, gk_handle, key_handle); 5360 5361 release_minor: 5362 CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk); 5363 CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk); 5364 5365 if (k_attrs != NULL) 5366 kmem_free(k_attrs, k_attrs_size); 5367 5368 if (error != 0) 5369 goto out; 5370 5371 STRUCT_FSET(generate_key, gk_return_value, rv); 5372 if (copyout(STRUCT_BUF(generate_key), arg, 5373 STRUCT_SIZE(generate_key)) != 0) { 5374 if (rv == CRYPTO_SUCCESS) { 5375 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 5376 KCF_OP_OBJECT_DESTROY, 5377 sp->sd_provider_session->ps_session, key_handle, 5378 NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 5379 5380 (void) kcf_submit_request(real_provider, NULL, 5381 NULL, ¶ms, B_FALSE); 5382 5383 error = EFAULT; 5384 } 5385 } 5386 out: 5387 CRYPTO_SESSION_RELE(sp); 5388 crypto_release_minor(cm); 5389 5390 if (real_provider != NULL) { 5391 crypto_free_mech(real_provider, 5392 allocated_by_crypto_module, &mech); 5393 KCF_PROV_REFRELE(real_provider); 5394 } 5395 return (error); 5396 } 5397 5398 /* ARGSUSED */ 5399 static int 5400 nostore_generate_key(dev_t dev, caddr_t arg, int mode, int *rval) 5401 { 5402 STRUCT_DECL(crypto_nostore_generate_key, generate_key); 5403 /* LINTED E_FUNC_SET_NOT_USED */ 5404 STRUCT_DECL(crypto_object_attribute, oa); 5405 kcf_provider_desc_t *real_provider = NULL; 5406 kcf_req_params_t params; 5407 crypto_mechanism_t mech; 5408 crypto_object_attribute_t *k_in_attrs = NULL; 5409 crypto_object_attribute_t *k_out_attrs = NULL; 5410 crypto_session_id_t session_id; 5411 crypto_minor_t *cm; 5412 crypto_session_data_t *sp = NULL; 5413 caddr_t in_attributes; 5414 caddr_t out_attributes; 5415 size_t k_in_attrs_size; 5416 size_t k_out_attrs_size; 5417 size_t mech_rctl_bytes = 0; 5418 boolean_t mech_rctl_chk = B_FALSE; 5419 size_t in_key_rctl_bytes = 0, out_key_rctl_bytes = 0; 5420 boolean_t in_key_rctl_chk = B_FALSE; 5421 boolean_t out_key_rctl_chk = B_FALSE; 5422 uint_t in_count; 5423 uint_t out_count; 5424 int error = 0; 5425 int rv; 5426 boolean_t allocated_by_crypto_module = B_FALSE; 5427 caddr_t u_attrs = NULL; 5428 5429 STRUCT_INIT(generate_key, mode); 5430 STRUCT_INIT(oa, mode); 5431 5432 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 5433 cmn_err(CE_WARN, "nostore_generate_key: failed holding minor"); 5434 return (ENXIO); 5435 } 5436 5437 if (copyin(arg, STRUCT_BUF(generate_key), 5438 STRUCT_SIZE(generate_key)) != 0) { 5439 crypto_release_minor(cm); 5440 return (EFAULT); 5441 } 5442 5443 session_id = STRUCT_FGET(generate_key, ngk_session); 5444 5445 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 5446 goto release_minor; 5447 } 5448 5449 bcopy(STRUCT_FADDR(generate_key, ngk_mechanism), &mech.cm_type, 5450 sizeof (crypto_mech_type_t)); 5451 5452 if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL, 5453 CRYPTO_MECH_INVALID, NULL, CHECK_RESTRICT_FALSE, sp->sd_provider, 5454 &real_provider, CRYPTO_FG_GENERATE)) != CRYPTO_SUCCESS) { 5455 goto release_minor; 5456 } 5457 5458 rv = crypto_provider_copyin_mech_param(real_provider, 5459 STRUCT_FADDR(generate_key, ngk_mechanism), &mech, mode, &error); 5460 5461 if (rv == CRYPTO_NOT_SUPPORTED) { 5462 allocated_by_crypto_module = B_TRUE; 5463 if (!copyin_mech(mode, sp, STRUCT_FADDR(generate_key, 5464 ngk_mechanism), &mech, &mech_rctl_bytes, 5465 &mech_rctl_chk, &rv, &error)) { 5466 goto release_minor; 5467 } 5468 } else { 5469 if (rv != CRYPTO_SUCCESS) 5470 goto release_minor; 5471 } 5472 5473 in_count = STRUCT_FGET(generate_key, ngk_in_count); 5474 in_attributes = STRUCT_FGETP(generate_key, ngk_in_attributes); 5475 if (!copyin_attributes(mode, sp, in_count, in_attributes, &k_in_attrs, 5476 &k_in_attrs_size, NULL, &rv, &error, &in_key_rctl_bytes, 5477 &in_key_rctl_chk, B_TRUE)) { 5478 goto release_minor; 5479 } 5480 5481 out_count = STRUCT_FGET(generate_key, ngk_out_count); 5482 out_attributes = STRUCT_FGETP(generate_key, ngk_out_attributes); 5483 if (!copyin_attributes(mode, sp, out_count, out_attributes, 5484 &k_out_attrs, 5485 &k_out_attrs_size, &u_attrs, &rv, &error, &out_key_rctl_bytes, 5486 &out_key_rctl_chk, B_FALSE)) { 5487 goto release_minor; 5488 } 5489 5490 KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_GENERATE, 5491 sp->sd_provider_session->ps_session, &mech, k_in_attrs, in_count, 5492 NULL, 0, NULL, k_out_attrs, out_count, NULL, 0); 5493 5494 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5495 5496 if (rv == CRYPTO_SUCCESS) { 5497 error = copyout_attributes(mode, out_attributes, 5498 out_count, k_out_attrs, u_attrs); 5499 } 5500 release_minor: 5501 CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk); 5502 CRYPTO_DECREMENT_RCTL_SESSION(sp, in_key_rctl_bytes, in_key_rctl_chk); 5503 CRYPTO_DECREMENT_RCTL_SESSION(sp, out_key_rctl_bytes, 5504 out_key_rctl_chk); 5505 5506 if (k_in_attrs != NULL) 5507 kmem_free(k_in_attrs, k_in_attrs_size); 5508 if (k_out_attrs != NULL) { 5509 bzero(k_out_attrs, k_out_attrs_size); 5510 kmem_free(k_out_attrs, k_out_attrs_size); 5511 } 5512 5513 if (u_attrs != NULL) 5514 kmem_free(u_attrs, out_count * STRUCT_SIZE(oa)); 5515 5516 if (error != 0) 5517 goto out; 5518 5519 STRUCT_FSET(generate_key, ngk_return_value, rv); 5520 if (copyout(STRUCT_BUF(generate_key), arg, 5521 STRUCT_SIZE(generate_key)) != 0) { 5522 error = EFAULT; 5523 } 5524 out: 5525 CRYPTO_SESSION_RELE(sp); 5526 crypto_release_minor(cm); 5527 5528 if (real_provider != NULL) { 5529 crypto_free_mech(real_provider, 5530 allocated_by_crypto_module, &mech); 5531 KCF_PROV_REFRELE(real_provider); 5532 } 5533 return (error); 5534 } 5535 5536 /* ARGSUSED */ 5537 static int 5538 object_generate_key_pair(dev_t dev, caddr_t arg, int mode, int *rval) 5539 { 5540 STRUCT_DECL(crypto_object_generate_key_pair, generate_key_pair); 5541 kcf_provider_desc_t *real_provider = NULL; 5542 kcf_req_params_t params; 5543 crypto_mechanism_t mech; 5544 crypto_object_attribute_t *k_pub_attrs = NULL; 5545 crypto_object_attribute_t *k_pri_attrs = NULL; 5546 crypto_session_id_t session_id; 5547 crypto_minor_t *cm; 5548 crypto_session_data_t *sp = NULL; 5549 crypto_object_id_t pub_handle; 5550 crypto_object_id_t pri_handle; 5551 caddr_t pri_attributes; 5552 caddr_t pub_attributes; 5553 size_t k_pub_attrs_size, k_pri_attrs_size; 5554 size_t mech_rctl_bytes = 0; 5555 boolean_t mech_rctl_chk = B_FALSE; 5556 size_t pub_rctl_bytes = 0; 5557 boolean_t pub_rctl_chk = B_FALSE; 5558 size_t pri_rctl_bytes = 0; 5559 boolean_t pri_rctl_chk = B_FALSE; 5560 uint_t pub_count; 5561 uint_t pri_count; 5562 int error = 0; 5563 int rv; 5564 boolean_t allocated_by_crypto_module = B_FALSE; 5565 5566 STRUCT_INIT(generate_key_pair, mode); 5567 5568 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 5569 cmn_err(CE_WARN, 5570 "object_generate_key_pair: failed holding minor"); 5571 return (ENXIO); 5572 } 5573 5574 if (copyin(arg, STRUCT_BUF(generate_key_pair), 5575 STRUCT_SIZE(generate_key_pair)) != 0) { 5576 crypto_release_minor(cm); 5577 return (EFAULT); 5578 } 5579 5580 session_id = STRUCT_FGET(generate_key_pair, kp_session); 5581 5582 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 5583 goto release_minor; 5584 } 5585 5586 bcopy(STRUCT_FADDR(generate_key_pair, kp_mechanism), &mech.cm_type, 5587 sizeof (crypto_mech_type_t)); 5588 5589 if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL, 5590 CRYPTO_MECH_INVALID, NULL, CHECK_RESTRICT_FALSE, sp->sd_provider, 5591 &real_provider, CRYPTO_FG_GENERATE_KEY_PAIR)) != CRYPTO_SUCCESS) { 5592 goto release_minor; 5593 } 5594 5595 rv = crypto_provider_copyin_mech_param(real_provider, 5596 STRUCT_FADDR(generate_key_pair, kp_mechanism), &mech, mode, &error); 5597 5598 if (rv == CRYPTO_NOT_SUPPORTED) { 5599 allocated_by_crypto_module = B_TRUE; 5600 if (!copyin_mech(mode, sp, STRUCT_FADDR(generate_key_pair, 5601 kp_mechanism), &mech, &mech_rctl_bytes, 5602 &mech_rctl_chk, &rv, &error)) { 5603 goto release_minor; 5604 } 5605 } else { 5606 if (rv != CRYPTO_SUCCESS) 5607 goto release_minor; 5608 } 5609 5610 pub_count = STRUCT_FGET(generate_key_pair, kp_public_count); 5611 pri_count = STRUCT_FGET(generate_key_pair, kp_private_count); 5612 5613 pub_attributes = STRUCT_FGETP(generate_key_pair, kp_public_attributes); 5614 if (!copyin_attributes(mode, sp, pub_count, pub_attributes, 5615 &k_pub_attrs, &k_pub_attrs_size, NULL, &rv, &error, &pub_rctl_bytes, 5616 &pub_rctl_chk, B_TRUE)) { 5617 goto release_minor; 5618 } 5619 5620 pri_attributes = STRUCT_FGETP(generate_key_pair, kp_private_attributes); 5621 if (!copyin_attributes(mode, sp, pri_count, pri_attributes, 5622 &k_pri_attrs, &k_pri_attrs_size, NULL, &rv, &error, 5623 &pri_rctl_bytes, &pri_rctl_chk, B_TRUE)) { 5624 goto release_minor; 5625 } 5626 5627 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_GENERATE_PAIR, 5628 sp->sd_provider_session->ps_session, &mech, k_pub_attrs, 5629 pub_count, &pub_handle, k_pri_attrs, pri_count, &pri_handle, 5630 NULL, NULL, 0); 5631 5632 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5633 5634 if (rv == CRYPTO_SUCCESS) { 5635 STRUCT_FSET(generate_key_pair, kp_public_handle, pub_handle); 5636 STRUCT_FSET(generate_key_pair, kp_private_handle, pri_handle); 5637 } 5638 5639 release_minor: 5640 CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk); 5641 CRYPTO_DECREMENT_RCTL_SESSION(sp, pub_rctl_bytes, pub_rctl_chk); 5642 CRYPTO_DECREMENT_RCTL_SESSION(sp, pri_rctl_bytes, pri_rctl_chk); 5643 5644 if (k_pub_attrs != NULL) 5645 kmem_free(k_pub_attrs, k_pub_attrs_size); 5646 5647 if (k_pri_attrs != NULL) 5648 kmem_free(k_pri_attrs, k_pri_attrs_size); 5649 5650 if (error != 0) 5651 goto out; 5652 5653 STRUCT_FSET(generate_key_pair, kp_return_value, rv); 5654 if (copyout(STRUCT_BUF(generate_key_pair), arg, 5655 STRUCT_SIZE(generate_key_pair)) != 0) { 5656 if (rv == CRYPTO_SUCCESS) { 5657 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 5658 KCF_OP_OBJECT_DESTROY, 5659 sp->sd_provider_session->ps_session, pub_handle, 5660 NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 5661 5662 (void) kcf_submit_request(real_provider, NULL, 5663 NULL, ¶ms, B_FALSE); 5664 5665 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 5666 KCF_OP_OBJECT_DESTROY, 5667 sp->sd_provider_session->ps_session, pri_handle, 5668 NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 5669 5670 (void) kcf_submit_request(real_provider, NULL, 5671 NULL, ¶ms, B_FALSE); 5672 5673 error = EFAULT; 5674 } 5675 } 5676 out: 5677 CRYPTO_SESSION_RELE(sp); 5678 crypto_release_minor(cm); 5679 5680 if (real_provider != NULL) { 5681 crypto_free_mech(real_provider, 5682 allocated_by_crypto_module, &mech); 5683 KCF_PROV_REFRELE(real_provider); 5684 } 5685 return (error); 5686 } 5687 5688 /* ARGSUSED */ 5689 static int 5690 nostore_generate_key_pair(dev_t dev, caddr_t arg, int mode, int *rval) 5691 { 5692 STRUCT_DECL(crypto_nostore_generate_key_pair, generate_key_pair); 5693 /* LINTED E_FUNC_SET_NOT_USED */ 5694 STRUCT_DECL(crypto_object_attribute, oa); 5695 kcf_provider_desc_t *real_provider = NULL; 5696 kcf_req_params_t params; 5697 crypto_mechanism_t mech; 5698 crypto_object_attribute_t *k_in_pub_attrs = NULL; 5699 crypto_object_attribute_t *k_in_pri_attrs = NULL; 5700 crypto_object_attribute_t *k_out_pub_attrs = NULL; 5701 crypto_object_attribute_t *k_out_pri_attrs = NULL; 5702 crypto_session_id_t session_id; 5703 crypto_minor_t *cm; 5704 crypto_session_data_t *sp = NULL; 5705 caddr_t in_pri_attributes; 5706 caddr_t in_pub_attributes; 5707 caddr_t out_pri_attributes; 5708 caddr_t out_pub_attributes; 5709 size_t k_in_pub_attrs_size, k_in_pri_attrs_size; 5710 size_t k_out_pub_attrs_size, k_out_pri_attrs_size; 5711 size_t mech_rctl_bytes = 0; 5712 boolean_t mech_rctl_chk = B_FALSE; 5713 size_t in_pub_rctl_bytes = 0; 5714 boolean_t in_pub_rctl_chk = B_FALSE; 5715 size_t in_pri_rctl_bytes = 0; 5716 boolean_t in_pri_rctl_chk = B_FALSE; 5717 size_t out_pub_rctl_bytes = 0; 5718 boolean_t out_pub_rctl_chk = B_FALSE; 5719 size_t out_pri_rctl_bytes = 0; 5720 boolean_t out_pri_rctl_chk = B_FALSE; 5721 uint_t in_pub_count; 5722 uint_t in_pri_count; 5723 uint_t out_pub_count; 5724 uint_t out_pri_count; 5725 int error = 0; 5726 int rv; 5727 boolean_t allocated_by_crypto_module = B_FALSE; 5728 caddr_t u_pub_attrs = NULL; 5729 caddr_t u_pri_attrs = NULL; 5730 5731 STRUCT_INIT(generate_key_pair, mode); 5732 STRUCT_INIT(oa, mode); 5733 5734 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 5735 cmn_err(CE_WARN, 5736 "nostore_generate_key_pair: failed holding minor"); 5737 return (ENXIO); 5738 } 5739 5740 if (copyin(arg, STRUCT_BUF(generate_key_pair), 5741 STRUCT_SIZE(generate_key_pair)) != 0) { 5742 crypto_release_minor(cm); 5743 return (EFAULT); 5744 } 5745 5746 session_id = STRUCT_FGET(generate_key_pair, nkp_session); 5747 5748 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 5749 goto release_minor; 5750 } 5751 5752 bcopy(STRUCT_FADDR(generate_key_pair, nkp_mechanism), &mech.cm_type, 5753 sizeof (crypto_mech_type_t)); 5754 5755 if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL, 5756 CRYPTO_MECH_INVALID, NULL, CHECK_RESTRICT_FALSE, sp->sd_provider, 5757 &real_provider, CRYPTO_FG_GENERATE_KEY_PAIR)) != CRYPTO_SUCCESS) { 5758 goto release_minor; 5759 } 5760 5761 rv = crypto_provider_copyin_mech_param(real_provider, 5762 STRUCT_FADDR(generate_key_pair, nkp_mechanism), &mech, mode, 5763 &error); 5764 5765 if (rv == CRYPTO_NOT_SUPPORTED) { 5766 allocated_by_crypto_module = B_TRUE; 5767 if (!copyin_mech(mode, sp, STRUCT_FADDR(generate_key_pair, 5768 nkp_mechanism), &mech, &mech_rctl_bytes, 5769 &mech_rctl_chk, &rv, &error)) { 5770 goto release_minor; 5771 } 5772 } else { 5773 if (rv != CRYPTO_SUCCESS) 5774 goto release_minor; 5775 } 5776 5777 in_pub_count = STRUCT_FGET(generate_key_pair, nkp_in_public_count); 5778 in_pri_count = STRUCT_FGET(generate_key_pair, nkp_in_private_count); 5779 5780 in_pub_attributes = STRUCT_FGETP(generate_key_pair, 5781 nkp_in_public_attributes); 5782 if (!copyin_attributes(mode, sp, in_pub_count, in_pub_attributes, 5783 &k_in_pub_attrs, &k_in_pub_attrs_size, NULL, &rv, &error, 5784 &in_pub_rctl_bytes, &in_pub_rctl_chk, B_TRUE)) { 5785 goto release_minor; 5786 } 5787 5788 in_pri_attributes = STRUCT_FGETP(generate_key_pair, 5789 nkp_in_private_attributes); 5790 if (!copyin_attributes(mode, sp, in_pri_count, in_pri_attributes, 5791 &k_in_pri_attrs, &k_in_pri_attrs_size, NULL, &rv, &error, 5792 &in_pri_rctl_bytes, &in_pri_rctl_chk, B_TRUE)) { 5793 goto release_minor; 5794 } 5795 5796 out_pub_count = STRUCT_FGET(generate_key_pair, nkp_out_public_count); 5797 out_pri_count = STRUCT_FGET(generate_key_pair, nkp_out_private_count); 5798 5799 out_pub_attributes = STRUCT_FGETP(generate_key_pair, 5800 nkp_out_public_attributes); 5801 if (!copyin_attributes(mode, sp, out_pub_count, out_pub_attributes, 5802 &k_out_pub_attrs, &k_out_pub_attrs_size, &u_pub_attrs, &rv, &error, 5803 &out_pub_rctl_bytes, &out_pub_rctl_chk, B_FALSE)) { 5804 goto release_minor; 5805 } 5806 5807 out_pri_attributes = STRUCT_FGETP(generate_key_pair, 5808 nkp_out_private_attributes); 5809 if (!copyin_attributes(mode, sp, out_pri_count, out_pri_attributes, 5810 &k_out_pri_attrs, &k_out_pri_attrs_size, &u_pri_attrs, &rv, &error, 5811 &out_pri_rctl_bytes, &out_pri_rctl_chk, B_FALSE)) { 5812 goto release_minor; 5813 } 5814 5815 KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_GENERATE_PAIR, 5816 sp->sd_provider_session->ps_session, &mech, k_in_pub_attrs, 5817 in_pub_count, k_in_pri_attrs, in_pri_count, NULL, k_out_pub_attrs, 5818 out_pub_count, k_out_pri_attrs, out_pri_count); 5819 5820 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5821 5822 if (rv == CRYPTO_SUCCESS) { 5823 error = copyout_attributes(mode, out_pub_attributes, 5824 out_pub_count, k_out_pub_attrs, u_pub_attrs); 5825 if (error != CRYPTO_SUCCESS) 5826 goto release_minor; 5827 error = copyout_attributes(mode, out_pri_attributes, 5828 out_pri_count, k_out_pri_attrs, u_pri_attrs); 5829 } 5830 5831 release_minor: 5832 CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk); 5833 CRYPTO_DECREMENT_RCTL_SESSION(sp, in_pub_rctl_bytes, in_pub_rctl_chk); 5834 CRYPTO_DECREMENT_RCTL_SESSION(sp, in_pri_rctl_bytes, in_pri_rctl_chk); 5835 CRYPTO_DECREMENT_RCTL_SESSION(sp, out_pub_rctl_bytes, 5836 out_pub_rctl_chk); 5837 CRYPTO_DECREMENT_RCTL_SESSION(sp, out_pri_rctl_bytes, 5838 out_pri_rctl_chk); 5839 5840 if (k_in_pub_attrs != NULL) 5841 kmem_free(k_in_pub_attrs, k_in_pub_attrs_size); 5842 5843 if (k_in_pri_attrs != NULL) 5844 kmem_free(k_in_pri_attrs, k_in_pri_attrs_size); 5845 5846 if (k_out_pub_attrs != NULL) 5847 kmem_free(k_out_pub_attrs, k_out_pub_attrs_size); 5848 5849 if (k_out_pri_attrs != NULL) { 5850 bzero(k_out_pri_attrs, k_out_pri_attrs_size); 5851 kmem_free(k_out_pri_attrs, k_out_pri_attrs_size); 5852 } 5853 5854 if (u_pub_attrs != NULL) 5855 kmem_free(u_pub_attrs, out_pub_count * STRUCT_SIZE(oa)); 5856 5857 if (u_pri_attrs != NULL) 5858 kmem_free(u_pri_attrs, out_pri_count * STRUCT_SIZE(oa)); 5859 5860 if (error != 0) 5861 goto out; 5862 5863 STRUCT_FSET(generate_key_pair, nkp_return_value, rv); 5864 if (copyout(STRUCT_BUF(generate_key_pair), arg, 5865 STRUCT_SIZE(generate_key_pair)) != 0) { 5866 error = EFAULT; 5867 } 5868 out: 5869 CRYPTO_SESSION_RELE(sp); 5870 crypto_release_minor(cm); 5871 5872 if (real_provider != NULL) { 5873 crypto_free_mech(real_provider, 5874 allocated_by_crypto_module, &mech); 5875 KCF_PROV_REFRELE(real_provider); 5876 } 5877 return (error); 5878 } 5879 5880 /* ARGSUSED */ 5881 static int 5882 object_wrap_key(dev_t dev, caddr_t arg, int mode, int *rval) 5883 { 5884 STRUCT_DECL(crypto_object_wrap_key, wrap_key); 5885 kcf_provider_desc_t *real_provider = NULL; 5886 kcf_req_params_t params; 5887 crypto_mechanism_t mech; 5888 crypto_key_t key; 5889 crypto_session_id_t session_id; 5890 crypto_minor_t *cm; 5891 crypto_session_data_t *sp = NULL; 5892 crypto_object_id_t handle; 5893 size_t mech_rctl_bytes = 0, key_rctl_bytes = 0; 5894 boolean_t mech_rctl_chk = B_FALSE; 5895 boolean_t key_rctl_chk = B_FALSE; 5896 size_t wrapped_key_rctl_bytes = 0; 5897 boolean_t wrapped_key_rctl_chk = B_FALSE; 5898 size_t wrapped_key_len, new_wrapped_key_len; 5899 uchar_t *wrapped_key = NULL; 5900 char *wrapped_key_buffer; 5901 int error = 0; 5902 int rv; 5903 boolean_t allocated_by_crypto_module = B_FALSE; 5904 5905 STRUCT_INIT(wrap_key, mode); 5906 5907 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 5908 cmn_err(CE_WARN, "object_wrap_key: failed holding minor"); 5909 return (ENXIO); 5910 } 5911 5912 if (copyin(arg, STRUCT_BUF(wrap_key), STRUCT_SIZE(wrap_key)) != 0) { 5913 crypto_release_minor(cm); 5914 return (EFAULT); 5915 } 5916 5917 bzero(&key, sizeof (crypto_key_t)); 5918 5919 session_id = STRUCT_FGET(wrap_key, wk_session); 5920 5921 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 5922 goto out; 5923 } 5924 5925 bcopy(STRUCT_FADDR(wrap_key, wk_mechanism), &mech.cm_type, 5926 sizeof (crypto_mech_type_t)); 5927 5928 /* We need the key length for provider selection so copy it in now. */ 5929 if (!copyin_key(mode, sp, STRUCT_FADDR(wrap_key, wk_wrapping_key), &key, 5930 &key_rctl_bytes, &key_rctl_chk, &rv, &error)) { 5931 goto out; 5932 } 5933 5934 wrapped_key_len = STRUCT_FGET(wrap_key, wk_wrapped_key_len); 5935 5936 if ((rv = kcf_get_hardware_provider(mech.cm_type, &key, 5937 CRYPTO_MECH_INVALID, NULL, CHECK_RESTRICT_FALSE, sp->sd_provider, 5938 &real_provider, CRYPTO_FG_WRAP)) != CRYPTO_SUCCESS) { 5939 goto out; 5940 } 5941 5942 rv = crypto_provider_copyin_mech_param(real_provider, 5943 STRUCT_FADDR(wrap_key, wk_mechanism), &mech, mode, &error); 5944 5945 if (rv == CRYPTO_NOT_SUPPORTED) { 5946 allocated_by_crypto_module = B_TRUE; 5947 if (!copyin_mech(mode, sp, STRUCT_FADDR(wrap_key, wk_mechanism), 5948 &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) { 5949 goto out; 5950 } 5951 } else { 5952 if (rv != CRYPTO_SUCCESS) 5953 goto out; 5954 } 5955 5956 /* 5957 * Don't allocate output buffer unless both buffer pointer and 5958 * buffer length are not NULL or 0 (length). 5959 */ 5960 wrapped_key_buffer = STRUCT_FGETP(wrap_key, wk_wrapped_key); 5961 if (wrapped_key_buffer == NULL || wrapped_key_len == 0) { 5962 wrapped_key_len = 0; 5963 } 5964 5965 if (wrapped_key_len > crypto_max_buffer_len) { 5966 cmn_err(CE_NOTE, "object_wrap_key: buffer greater than %ld " 5967 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 5968 rv = CRYPTO_ARGUMENTS_BAD; 5969 goto out; 5970 } 5971 5972 if ((rv = CRYPTO_BUFFER_CHECK(sp, wrapped_key_len, 5973 wrapped_key_rctl_chk)) != CRYPTO_SUCCESS) { 5974 goto out; 5975 } 5976 5977 /* new_wrapped_key_len can be modified by the provider */ 5978 wrapped_key_rctl_bytes = new_wrapped_key_len = wrapped_key_len; 5979 wrapped_key = kmem_alloc(wrapped_key_len, KM_SLEEP); 5980 5981 handle = STRUCT_FGET(wrap_key, wk_object_handle); 5982 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_WRAP, 5983 sp->sd_provider_session->ps_session, &mech, NULL, 0, &handle, 5984 NULL, 0, NULL, &key, wrapped_key, &new_wrapped_key_len); 5985 5986 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5987 5988 if (rv == CRYPTO_SUCCESS) { 5989 if (wrapped_key_len != 0 && copyout(wrapped_key, 5990 wrapped_key_buffer, new_wrapped_key_len) != 0) { 5991 error = EFAULT; 5992 } 5993 STRUCT_FSET(wrap_key, wk_wrapped_key_len, new_wrapped_key_len); 5994 } 5995 5996 if (rv == CRYPTO_BUFFER_TOO_SMALL) { 5997 /* 5998 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1 5999 * of section 11.2 of the pkcs11 spec. We catch it here and 6000 * provide the correct pkcs11 return value. 6001 */ 6002 if (STRUCT_FGETP(wrap_key, wk_wrapped_key) == NULL) 6003 rv = CRYPTO_SUCCESS; 6004 STRUCT_FSET(wrap_key, wk_wrapped_key_len, new_wrapped_key_len); 6005 } 6006 6007 out: 6008 CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk); 6009 CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk); 6010 CRYPTO_DECREMENT_RCTL_SESSION(sp, wrapped_key_rctl_bytes, 6011 wrapped_key_rctl_chk); 6012 CRYPTO_SESSION_RELE(sp); 6013 6014 crypto_release_minor(cm); 6015 6016 if (real_provider != NULL) { 6017 crypto_free_mech(real_provider, 6018 allocated_by_crypto_module, &mech); 6019 KCF_PROV_REFRELE(real_provider); 6020 } 6021 6022 if (wrapped_key != NULL) 6023 kmem_free(wrapped_key, wrapped_key_len); 6024 6025 free_crypto_key(&key); 6026 6027 if (error != 0) 6028 return (error); 6029 6030 STRUCT_FSET(wrap_key, wk_return_value, rv); 6031 if (copyout(STRUCT_BUF(wrap_key), arg, STRUCT_SIZE(wrap_key)) != 0) { 6032 return (EFAULT); 6033 } 6034 return (0); 6035 } 6036 6037 /* ARGSUSED */ 6038 static int 6039 object_unwrap_key(dev_t dev, caddr_t arg, int mode, int *rval) 6040 { 6041 STRUCT_DECL(crypto_object_unwrap_key, unwrap_key); 6042 kcf_provider_desc_t *real_provider = NULL; 6043 kcf_req_params_t params; 6044 crypto_mechanism_t mech; 6045 crypto_key_t unwrapping_key; 6046 crypto_session_id_t session_id; 6047 crypto_minor_t *cm; 6048 crypto_session_data_t *sp = NULL; 6049 crypto_object_id_t handle; 6050 crypto_object_attribute_t *k_attrs = NULL; 6051 size_t k_attrs_size; 6052 size_t mech_rctl_bytes = 0, unwrapping_key_rctl_bytes = 0; 6053 boolean_t mech_rctl_chk = B_FALSE; 6054 boolean_t unwrapping_key_rctl_chk = B_FALSE; 6055 size_t wrapped_key_rctl_bytes = 0, k_attrs_rctl_bytes = 0; 6056 boolean_t wrapped_key_rctl_chk = B_FALSE; 6057 boolean_t k_attrs_rctl_chk = B_FALSE; 6058 size_t wrapped_key_len; 6059 uchar_t *wrapped_key = NULL; 6060 int error = 0; 6061 int rv; 6062 uint_t count; 6063 caddr_t uk_attributes; 6064 boolean_t allocated_by_crypto_module = B_FALSE; 6065 6066 STRUCT_INIT(unwrap_key, mode); 6067 6068 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 6069 cmn_err(CE_WARN, "object_unwrap_key: failed holding minor"); 6070 return (ENXIO); 6071 } 6072 6073 if (copyin(arg, STRUCT_BUF(unwrap_key), STRUCT_SIZE(unwrap_key)) != 0) { 6074 crypto_release_minor(cm); 6075 return (EFAULT); 6076 } 6077 6078 bzero(&unwrapping_key, sizeof (unwrapping_key)); 6079 6080 session_id = STRUCT_FGET(unwrap_key, uk_session); 6081 6082 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 6083 goto release_minor; 6084 } 6085 6086 bcopy(STRUCT_FADDR(unwrap_key, uk_mechanism), &mech.cm_type, 6087 sizeof (crypto_mech_type_t)); 6088 6089 /* We need the key length for provider selection so copy it in now. */ 6090 if (!copyin_key(mode, sp, STRUCT_FADDR(unwrap_key, uk_unwrapping_key), 6091 &unwrapping_key, &unwrapping_key_rctl_bytes, 6092 &unwrapping_key_rctl_chk, &rv, &error)) { 6093 goto release_minor; 6094 } 6095 6096 if ((rv = kcf_get_hardware_provider(mech.cm_type, &unwrapping_key, 6097 CRYPTO_MECH_INVALID, NULL, CHECK_RESTRICT_FALSE, sp->sd_provider, 6098 &real_provider, CRYPTO_FG_UNWRAP)) != CRYPTO_SUCCESS) { 6099 goto release_minor; 6100 } 6101 6102 rv = crypto_provider_copyin_mech_param(real_provider, 6103 STRUCT_FADDR(unwrap_key, uk_mechanism), &mech, mode, &error); 6104 6105 if (rv == CRYPTO_NOT_SUPPORTED) { 6106 allocated_by_crypto_module = B_TRUE; 6107 if (!copyin_mech(mode, sp, 6108 STRUCT_FADDR(unwrap_key, uk_mechanism), 6109 &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) { 6110 goto release_minor; 6111 } 6112 } else { 6113 if (rv != CRYPTO_SUCCESS) 6114 goto release_minor; 6115 } 6116 6117 count = STRUCT_FGET(unwrap_key, uk_count); 6118 uk_attributes = STRUCT_FGETP(unwrap_key, uk_attributes); 6119 if (!copyin_attributes(mode, sp, count, uk_attributes, &k_attrs, 6120 &k_attrs_size, NULL, &rv, &error, &k_attrs_rctl_bytes, 6121 &k_attrs_rctl_chk, B_TRUE)) { 6122 goto release_minor; 6123 } 6124 6125 wrapped_key_len = STRUCT_FGET(unwrap_key, uk_wrapped_key_len); 6126 if (wrapped_key_len > crypto_max_buffer_len) { 6127 cmn_err(CE_NOTE, "object_unwrap_key: buffer greater than %ld " 6128 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 6129 rv = CRYPTO_ARGUMENTS_BAD; 6130 goto release_minor; 6131 } 6132 6133 if ((rv = CRYPTO_BUFFER_CHECK(sp, wrapped_key_len, 6134 wrapped_key_rctl_chk)) != CRYPTO_SUCCESS) { 6135 goto release_minor; 6136 } 6137 wrapped_key_rctl_bytes = wrapped_key_len; 6138 wrapped_key = kmem_alloc(wrapped_key_len, KM_SLEEP); 6139 6140 if (wrapped_key_len != 0 && copyin(STRUCT_FGETP(unwrap_key, 6141 uk_wrapped_key), wrapped_key, wrapped_key_len) != 0) { 6142 error = EFAULT; 6143 goto release_minor; 6144 } 6145 6146 /* wrapped_key_len is not modified by the unwrap operation */ 6147 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_UNWRAP, 6148 sp->sd_provider_session->ps_session, &mech, k_attrs, count, &handle, 6149 NULL, 0, NULL, &unwrapping_key, wrapped_key, &wrapped_key_len); 6150 6151 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 6152 6153 if (rv == CRYPTO_SUCCESS) 6154 STRUCT_FSET(unwrap_key, uk_object_handle, handle); 6155 6156 release_minor: 6157 CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk); 6158 CRYPTO_DECREMENT_RCTL_SESSION(sp, unwrapping_key_rctl_bytes, 6159 unwrapping_key_rctl_chk); 6160 CRYPTO_DECREMENT_RCTL_SESSION(sp, wrapped_key_rctl_bytes, 6161 wrapped_key_rctl_chk); 6162 CRYPTO_DECREMENT_RCTL_SESSION(sp, k_attrs_rctl_bytes, 6163 k_attrs_rctl_chk); 6164 6165 if (k_attrs != NULL) 6166 kmem_free(k_attrs, k_attrs_size); 6167 6168 if (wrapped_key != NULL) 6169 kmem_free(wrapped_key, wrapped_key_len); 6170 6171 free_crypto_key(&unwrapping_key); 6172 6173 if (error != 0) 6174 goto out; 6175 6176 STRUCT_FSET(unwrap_key, uk_return_value, rv); 6177 if (copyout(STRUCT_BUF(unwrap_key), arg, 6178 STRUCT_SIZE(unwrap_key)) != 0) { 6179 if (rv == CRYPTO_SUCCESS) { 6180 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 6181 KCF_OP_OBJECT_DESTROY, 6182 sp->sd_provider_session->ps_session, handle, 6183 NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 6184 6185 (void) kcf_submit_request(real_provider, NULL, 6186 NULL, ¶ms, B_FALSE); 6187 6188 error = EFAULT; 6189 } 6190 } 6191 out: 6192 CRYPTO_SESSION_RELE(sp); 6193 crypto_release_minor(cm); 6194 6195 if (real_provider != NULL) { 6196 crypto_free_mech(real_provider, 6197 allocated_by_crypto_module, &mech); 6198 KCF_PROV_REFRELE(real_provider); 6199 } 6200 6201 return (error); 6202 } 6203 6204 /* ARGSUSED */ 6205 static int 6206 object_derive_key(dev_t dev, caddr_t arg, int mode, int *rval) 6207 { 6208 STRUCT_DECL(crypto_derive_key, derive_key); 6209 kcf_provider_desc_t *real_provider = NULL; 6210 kcf_req_params_t params; 6211 crypto_object_attribute_t *k_attrs = NULL; 6212 crypto_mechanism_t mech; 6213 crypto_key_t base_key; 6214 crypto_session_id_t session_id; 6215 crypto_minor_t *cm; 6216 crypto_session_data_t *sp = NULL; 6217 crypto_object_id_t handle; 6218 size_t k_attrs_size; 6219 size_t key_rctl_bytes = 0, mech_rctl_bytes = 0; 6220 boolean_t mech_rctl_chk = B_FALSE; 6221 boolean_t key_rctl_chk = B_FALSE; 6222 size_t attributes_rctl_bytes = 0; 6223 boolean_t attributes_rctl_chk = B_FALSE; 6224 caddr_t attributes; 6225 uint_t count; 6226 int error = 0; 6227 int rv; 6228 boolean_t allocated_by_crypto_module = B_FALSE; 6229 boolean_t please_destroy_object = B_FALSE; 6230 6231 STRUCT_INIT(derive_key, mode); 6232 6233 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 6234 cmn_err(CE_WARN, "object_derive_key: failed holding minor"); 6235 return (ENXIO); 6236 } 6237 6238 if (copyin(arg, STRUCT_BUF(derive_key), STRUCT_SIZE(derive_key)) != 0) { 6239 crypto_release_minor(cm); 6240 return (EFAULT); 6241 } 6242 6243 bzero(&base_key, sizeof (base_key)); 6244 6245 session_id = STRUCT_FGET(derive_key, dk_session); 6246 6247 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 6248 goto release_minor; 6249 } 6250 6251 bcopy(STRUCT_FADDR(derive_key, dk_mechanism), &mech.cm_type, 6252 sizeof (crypto_mech_type_t)); 6253 6254 /* We need the key length for provider selection so copy it in now. */ 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 if ((rv = kcf_get_hardware_provider(mech.cm_type, &base_key, 6261 CRYPTO_MECH_INVALID, NULL, CHECK_RESTRICT_FALSE, sp->sd_provider, 6262 &real_provider, CRYPTO_FG_DERIVE)) != CRYPTO_SUCCESS) { 6263 goto release_minor; 6264 } 6265 6266 rv = crypto_provider_copyin_mech_param(real_provider, 6267 STRUCT_FADDR(derive_key, dk_mechanism), &mech, mode, &error); 6268 6269 if (rv == CRYPTO_NOT_SUPPORTED) { 6270 allocated_by_crypto_module = B_TRUE; 6271 if (!copyin_mech(mode, sp, 6272 STRUCT_FADDR(derive_key, dk_mechanism), 6273 &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) { 6274 goto release_minor; 6275 } 6276 } else { 6277 if (rv != CRYPTO_SUCCESS) 6278 goto release_minor; 6279 } 6280 6281 count = STRUCT_FGET(derive_key, dk_count); 6282 6283 attributes = STRUCT_FGETP(derive_key, dk_attributes); 6284 if (!copyin_attributes(mode, sp, count, attributes, &k_attrs, 6285 &k_attrs_size, NULL, &rv, &error, 6286 &attributes_rctl_bytes, &attributes_rctl_chk, B_TRUE)) { 6287 goto release_minor; 6288 } 6289 6290 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_DERIVE, 6291 sp->sd_provider_session->ps_session, &mech, k_attrs, count, 6292 &handle, NULL, 0, NULL, &base_key, NULL, NULL); 6293 6294 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 6295 6296 if (rv == CRYPTO_SUCCESS) { 6297 STRUCT_FSET(derive_key, dk_object_handle, handle); 6298 6299 rv = crypto_provider_copyout_mech_param(real_provider, 6300 &mech, STRUCT_FADDR(derive_key, dk_mechanism), 6301 mode, &error); 6302 6303 if (rv == CRYPTO_NOT_SUPPORTED) { 6304 rv = CRYPTO_SUCCESS; 6305 goto release_minor; 6306 } 6307 6308 if (rv != CRYPTO_SUCCESS) 6309 please_destroy_object = B_TRUE; 6310 } 6311 6312 release_minor: 6313 CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk); 6314 CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk); 6315 CRYPTO_DECREMENT_RCTL_SESSION(sp, attributes_rctl_bytes, 6316 attributes_rctl_chk); 6317 6318 if (k_attrs != NULL) 6319 kmem_free(k_attrs, k_attrs_size); 6320 6321 free_crypto_key(&base_key); 6322 6323 if (error != 0) 6324 goto out; 6325 6326 STRUCT_FSET(derive_key, dk_return_value, rv); 6327 if (copyout(STRUCT_BUF(derive_key), arg, 6328 STRUCT_SIZE(derive_key)) != 0) { 6329 if (rv == CRYPTO_SUCCESS) { 6330 please_destroy_object = B_TRUE; 6331 error = EFAULT; 6332 } 6333 } 6334 out: 6335 if (please_destroy_object) { 6336 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_DESTROY, 6337 sp->sd_provider_session->ps_session, handle, 6338 NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 6339 6340 (void) kcf_submit_request(real_provider, NULL, 6341 NULL, ¶ms, B_FALSE); 6342 } 6343 6344 CRYPTO_SESSION_RELE(sp); 6345 crypto_release_minor(cm); 6346 6347 if (real_provider != NULL) { 6348 crypto_free_mech(real_provider, 6349 allocated_by_crypto_module, &mech); 6350 KCF_PROV_REFRELE(real_provider); 6351 } 6352 return (error); 6353 } 6354 6355 /* ARGSUSED */ 6356 static int 6357 nostore_derive_key(dev_t dev, caddr_t arg, int mode, int *rval) 6358 { 6359 STRUCT_DECL(crypto_nostore_derive_key, derive_key); 6360 /* LINTED E_FUNC_SET_NOT_USED */ 6361 STRUCT_DECL(crypto_object_attribute, oa); 6362 kcf_provider_desc_t *real_provider = NULL; 6363 kcf_req_params_t params; 6364 crypto_object_attribute_t *k_in_attrs = NULL; 6365 crypto_object_attribute_t *k_out_attrs = NULL; 6366 crypto_mechanism_t mech; 6367 crypto_key_t base_key; 6368 crypto_session_id_t session_id; 6369 crypto_minor_t *cm; 6370 crypto_session_data_t *sp = NULL; 6371 size_t k_in_attrs_size, k_out_attrs_size; 6372 size_t key_rctl_bytes = 0, mech_rctl_bytes = 0; 6373 boolean_t mech_rctl_chk = B_FALSE; 6374 boolean_t key_rctl_chk = B_FALSE; 6375 size_t in_attributes_rctl_bytes = 0; 6376 size_t out_attributes_rctl_bytes = 0; 6377 boolean_t in_attributes_rctl_chk = B_FALSE; 6378 boolean_t out_attributes_rctl_chk = B_FALSE; 6379 caddr_t in_attributes, out_attributes; 6380 uint_t in_count, out_count; 6381 int error = 0; 6382 int rv; 6383 boolean_t allocated_by_crypto_module = B_FALSE; 6384 caddr_t u_attrs = NULL; 6385 6386 STRUCT_INIT(derive_key, mode); 6387 STRUCT_INIT(oa, mode); 6388 6389 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 6390 cmn_err(CE_WARN, "nostore_derive_key: failed holding minor"); 6391 return (ENXIO); 6392 } 6393 6394 if (copyin(arg, STRUCT_BUF(derive_key), STRUCT_SIZE(derive_key)) != 0) { 6395 crypto_release_minor(cm); 6396 return (EFAULT); 6397 } 6398 6399 bzero(&base_key, sizeof (base_key)); 6400 6401 session_id = STRUCT_FGET(derive_key, ndk_session); 6402 6403 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 6404 goto release_minor; 6405 } 6406 6407 bcopy(STRUCT_FADDR(derive_key, ndk_mechanism), &mech.cm_type, 6408 sizeof (crypto_mech_type_t)); 6409 6410 /* We need the key length for provider selection so copy it in now. */ 6411 if (!copyin_key(mode, sp, STRUCT_FADDR(derive_key, ndk_base_key), 6412 &base_key, &key_rctl_bytes, &key_rctl_chk, &rv, &error)) { 6413 goto release_minor; 6414 } 6415 6416 if ((rv = kcf_get_hardware_provider(mech.cm_type, &base_key, 6417 CRYPTO_MECH_INVALID, NULL, CHECK_RESTRICT_FALSE, sp->sd_provider, 6418 &real_provider, CRYPTO_FG_DERIVE)) != CRYPTO_SUCCESS) { 6419 goto release_minor; 6420 } 6421 6422 rv = crypto_provider_copyin_mech_param(real_provider, 6423 STRUCT_FADDR(derive_key, ndk_mechanism), &mech, mode, &error); 6424 6425 if (rv == CRYPTO_NOT_SUPPORTED) { 6426 allocated_by_crypto_module = B_TRUE; 6427 if (!copyin_mech(mode, sp, 6428 STRUCT_FADDR(derive_key, ndk_mechanism), 6429 &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) { 6430 goto release_minor; 6431 } 6432 } else { 6433 if (rv != CRYPTO_SUCCESS) 6434 goto release_minor; 6435 } 6436 6437 in_count = STRUCT_FGET(derive_key, ndk_in_count); 6438 out_count = STRUCT_FGET(derive_key, ndk_out_count); 6439 6440 in_attributes = STRUCT_FGETP(derive_key, ndk_in_attributes); 6441 if (!copyin_attributes(mode, sp, in_count, in_attributes, &k_in_attrs, 6442 &k_in_attrs_size, NULL, &rv, &error, &in_attributes_rctl_bytes, 6443 &in_attributes_rctl_chk, B_TRUE)) { 6444 goto release_minor; 6445 } 6446 6447 out_attributes = STRUCT_FGETP(derive_key, ndk_out_attributes); 6448 if (!copyin_attributes(mode, sp, out_count, out_attributes, 6449 &k_out_attrs, &k_out_attrs_size, &u_attrs, &rv, &error, 6450 &out_attributes_rctl_bytes, 6451 &out_attributes_rctl_chk, B_FALSE)) { 6452 goto release_minor; 6453 } 6454 6455 KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_DERIVE, 6456 sp->sd_provider_session->ps_session, &mech, k_in_attrs, in_count, 6457 NULL, 0, &base_key, k_out_attrs, out_count, NULL, 0); 6458 6459 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 6460 6461 if (rv == CRYPTO_SUCCESS) { 6462 rv = crypto_provider_copyout_mech_param(real_provider, 6463 &mech, STRUCT_FADDR(derive_key, ndk_mechanism), 6464 mode, &error); 6465 6466 if (rv == CRYPTO_NOT_SUPPORTED) { 6467 rv = CRYPTO_SUCCESS; 6468 } 6469 /* copyout the derived secret */ 6470 if (copyout_attributes(mode, out_attributes, out_count, 6471 k_out_attrs, u_attrs) != 0) 6472 error = EFAULT; 6473 } 6474 6475 release_minor: 6476 CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk); 6477 CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk); 6478 CRYPTO_DECREMENT_RCTL_SESSION(sp, in_attributes_rctl_bytes, 6479 in_attributes_rctl_chk); 6480 CRYPTO_DECREMENT_RCTL_SESSION(sp, out_attributes_rctl_bytes, 6481 out_attributes_rctl_chk); 6482 6483 if (k_in_attrs != NULL) 6484 kmem_free(k_in_attrs, k_in_attrs_size); 6485 if (k_out_attrs != NULL) { 6486 bzero(k_out_attrs, k_out_attrs_size); 6487 kmem_free(k_out_attrs, k_out_attrs_size); 6488 } 6489 6490 if (u_attrs != NULL) 6491 kmem_free(u_attrs, out_count * STRUCT_SIZE(oa)); 6492 6493 free_crypto_key(&base_key); 6494 6495 if (error != 0) 6496 goto out; 6497 6498 STRUCT_FSET(derive_key, ndk_return_value, rv); 6499 if (copyout(STRUCT_BUF(derive_key), arg, 6500 STRUCT_SIZE(derive_key)) != 0) { 6501 error = EFAULT; 6502 } 6503 out: 6504 CRYPTO_SESSION_RELE(sp); 6505 crypto_release_minor(cm); 6506 6507 if (real_provider != NULL) { 6508 crypto_free_mech(real_provider, 6509 allocated_by_crypto_module, &mech); 6510 KCF_PROV_REFRELE(real_provider); 6511 } 6512 return (error); 6513 } 6514 6515 /* ARGSUSED */ 6516 static int 6517 crypto_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c, 6518 int *rval) 6519 { 6520 #define ARG ((caddr_t)arg) 6521 6522 switch (cmd) { 6523 case CRYPTO_GET_FUNCTION_LIST: 6524 return (get_function_list(dev, ARG, mode, rval)); 6525 6526 case CRYPTO_GET_MECHANISM_NUMBER: 6527 return (get_mechanism_number(dev, ARG, mode, rval)); 6528 6529 case CRYPTO_GET_MECHANISM_LIST: 6530 return (get_mechanism_list(dev, ARG, mode, rval)); 6531 6532 case CRYPTO_GET_ALL_MECHANISM_INFO: 6533 return (get_all_mechanism_info(dev, ARG, mode, rval)); 6534 6535 case CRYPTO_GET_PROVIDER_LIST: 6536 return (get_provider_list(dev, ARG, mode, rval)); 6537 6538 case CRYPTO_GET_PROVIDER_INFO: 6539 return (get_provider_info(dev, ARG, mode, rval)); 6540 6541 case CRYPTO_GET_PROVIDER_MECHANISMS: 6542 return (get_provider_mechanisms(dev, ARG, mode, rval)); 6543 6544 case CRYPTO_GET_PROVIDER_MECHANISM_INFO: 6545 return (get_provider_mechanism_info(dev, ARG, mode, rval)); 6546 6547 case CRYPTO_OPEN_SESSION: 6548 return (open_session(dev, ARG, mode, rval)); 6549 6550 case CRYPTO_CLOSE_SESSION: 6551 return (close_session(dev, ARG, mode, rval)); 6552 6553 case CRYPTO_ENCRYPT_INIT: 6554 return (encrypt_init(dev, ARG, mode, rval)); 6555 6556 case CRYPTO_DECRYPT_INIT: 6557 return (decrypt_init(dev, ARG, mode, rval)); 6558 6559 case CRYPTO_ENCRYPT: 6560 return (encrypt(dev, ARG, mode, rval)); 6561 6562 case CRYPTO_DECRYPT: 6563 return (decrypt(dev, ARG, mode, rval)); 6564 6565 case CRYPTO_ENCRYPT_UPDATE: 6566 return (encrypt_update(dev, ARG, mode, rval)); 6567 6568 case CRYPTO_DECRYPT_UPDATE: 6569 return (decrypt_update(dev, ARG, mode, rval)); 6570 6571 case CRYPTO_ENCRYPT_FINAL: 6572 return (encrypt_final(dev, ARG, mode, rval)); 6573 6574 case CRYPTO_DECRYPT_FINAL: 6575 return (decrypt_final(dev, ARG, mode, rval)); 6576 6577 case CRYPTO_DIGEST_INIT: 6578 return (digest_init(dev, ARG, mode, rval)); 6579 6580 case CRYPTO_DIGEST: 6581 return (digest(dev, ARG, mode, rval)); 6582 6583 case CRYPTO_DIGEST_UPDATE: 6584 return (digest_update(dev, ARG, mode, rval)); 6585 6586 case CRYPTO_DIGEST_KEY: 6587 return (digest_key(dev, ARG, mode, rval)); 6588 6589 case CRYPTO_DIGEST_FINAL: 6590 return (digest_final(dev, ARG, mode, rval)); 6591 6592 case CRYPTO_SIGN_INIT: 6593 return (sign_init(dev, ARG, mode, rval)); 6594 6595 case CRYPTO_SIGN: 6596 return (sign(dev, ARG, mode, rval)); 6597 6598 case CRYPTO_SIGN_UPDATE: 6599 return (sign_update(dev, ARG, mode, rval)); 6600 6601 case CRYPTO_SIGN_FINAL: 6602 return (sign_final(dev, ARG, mode, rval)); 6603 6604 case CRYPTO_SIGN_RECOVER_INIT: 6605 return (sign_recover_init(dev, ARG, mode, rval)); 6606 6607 case CRYPTO_SIGN_RECOVER: 6608 return (sign_recover(dev, ARG, mode, rval)); 6609 6610 case CRYPTO_VERIFY_INIT: 6611 return (verify_init(dev, ARG, mode, rval)); 6612 6613 case CRYPTO_VERIFY: 6614 return (verify(dev, ARG, mode, rval)); 6615 6616 case CRYPTO_VERIFY_UPDATE: 6617 return (verify_update(dev, ARG, mode, rval)); 6618 6619 case CRYPTO_VERIFY_FINAL: 6620 return (verify_final(dev, ARG, mode, rval)); 6621 6622 case CRYPTO_VERIFY_RECOVER_INIT: 6623 return (verify_recover_init(dev, ARG, mode, rval)); 6624 6625 case CRYPTO_VERIFY_RECOVER: 6626 return (verify_recover(dev, ARG, mode, rval)); 6627 6628 case CRYPTO_SET_PIN: 6629 return (set_pin(dev, ARG, mode, rval)); 6630 6631 case CRYPTO_LOGIN: 6632 return (login(dev, ARG, mode, rval)); 6633 6634 case CRYPTO_LOGOUT: 6635 return (logout(dev, ARG, mode, rval)); 6636 6637 case CRYPTO_SEED_RANDOM: 6638 return (seed_random(dev, ARG, mode, rval)); 6639 6640 case CRYPTO_GENERATE_RANDOM: 6641 return (generate_random(dev, ARG, mode, rval)); 6642 6643 case CRYPTO_OBJECT_CREATE: 6644 return (object_create(dev, ARG, mode, rval)); 6645 6646 case CRYPTO_OBJECT_COPY: 6647 return (object_copy(dev, ARG, mode, rval)); 6648 6649 case CRYPTO_OBJECT_DESTROY: 6650 return (object_destroy(dev, ARG, mode, rval)); 6651 6652 case CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE: 6653 return (object_get_attribute_value(dev, ARG, mode, rval)); 6654 6655 case CRYPTO_OBJECT_GET_SIZE: 6656 return (object_get_size(dev, ARG, mode, rval)); 6657 6658 case CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE: 6659 return (object_set_attribute_value(dev, ARG, mode, rval)); 6660 6661 case CRYPTO_OBJECT_FIND_INIT: 6662 return (object_find_init(dev, ARG, mode, rval)); 6663 6664 case CRYPTO_OBJECT_FIND_UPDATE: 6665 return (object_find_update(dev, ARG, mode, rval)); 6666 6667 case CRYPTO_OBJECT_FIND_FINAL: 6668 return (object_find_final(dev, ARG, mode, rval)); 6669 6670 case CRYPTO_GENERATE_KEY: 6671 return (object_generate_key(dev, ARG, mode, rval)); 6672 6673 case CRYPTO_GENERATE_KEY_PAIR: 6674 return (object_generate_key_pair(dev, ARG, mode, rval)); 6675 6676 case CRYPTO_WRAP_KEY: 6677 return (object_wrap_key(dev, ARG, mode, rval)); 6678 6679 case CRYPTO_UNWRAP_KEY: 6680 return (object_unwrap_key(dev, ARG, mode, rval)); 6681 6682 case CRYPTO_DERIVE_KEY: 6683 return (object_derive_key(dev, ARG, mode, rval)); 6684 6685 case CRYPTO_NOSTORE_GENERATE_KEY: 6686 return (nostore_generate_key(dev, ARG, mode, rval)); 6687 6688 case CRYPTO_NOSTORE_GENERATE_KEY_PAIR: 6689 return (nostore_generate_key_pair(dev, ARG, mode, rval)); 6690 6691 case CRYPTO_NOSTORE_DERIVE_KEY: 6692 return (nostore_derive_key(dev, ARG, mode, rval)); 6693 } 6694 return (EINVAL); 6695 } 6696 6697 /* 6698 * Check for the project.max-crypto-memory resource control. 6699 */ 6700 static int 6701 crypto_buffer_check(size_t need) 6702 { 6703 kproject_t *kpj; 6704 6705 if (need == 0) 6706 return (CRYPTO_SUCCESS); 6707 6708 mutex_enter(&curproc->p_lock); 6709 kpj = curproc->p_task->tk_proj; 6710 mutex_enter(&(kpj->kpj_data.kpd_crypto_lock)); 6711 6712 if (kpj->kpj_data.kpd_crypto_mem + need > 6713 kpj->kpj_data.kpd_crypto_mem_ctl) { 6714 if (rctl_test(rc_project_crypto_mem, 6715 kpj->kpj_rctls, curproc, need, 0) & RCT_DENY) { 6716 mutex_exit(&(kpj->kpj_data.kpd_crypto_lock)); 6717 mutex_exit(&curproc->p_lock); 6718 return (CRYPTO_HOST_MEMORY); 6719 } 6720 } 6721 6722 kpj->kpj_data.kpd_crypto_mem += need; 6723 mutex_exit(&(kpj->kpj_data.kpd_crypto_lock)); 6724 6725 curproc->p_crypto_mem += need; 6726 mutex_exit(&curproc->p_lock); 6727 6728 return (CRYPTO_SUCCESS); 6729 } 6730