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