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