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