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