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