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