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