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