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 v1.47", /* 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 boolean_t do_inplace; 2451 char *encrbuf; 2452 int error = 0; 2453 int rv; 2454 2455 STRUCT_INIT(encrypt, mode); 2456 2457 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 2458 cmn_err(CE_WARN, "cipher: failed holding minor"); 2459 return (ENXIO); 2460 } 2461 2462 if (copyin(arg, STRUCT_BUF(encrypt), STRUCT_SIZE(encrypt)) != 0) { 2463 crypto_release_minor(cm); 2464 return (EFAULT); 2465 } 2466 2467 data.cd_raw.iov_base = NULL; 2468 encr.cd_raw.iov_base = NULL; 2469 2470 datalen = STRUCT_FGET(encrypt, ce_datalen); 2471 encrlen = STRUCT_FGET(encrypt, ce_encrlen); 2472 2473 /* 2474 * Don't allocate output buffer unless both buffer pointer and 2475 * buffer length are not NULL or 0 (length). 2476 */ 2477 encrbuf = STRUCT_FGETP(encrypt, ce_encrbuf); 2478 if (encrbuf == NULL || encrlen == 0) { 2479 encrlen = 0; 2480 } 2481 2482 if (datalen > crypto_max_buffer_len || 2483 encrlen > crypto_max_buffer_len) { 2484 cmn_err(CE_NOTE, "cipher: buffer greater than %ld bytes, " 2485 "pid = %d", crypto_max_buffer_len, curproc->p_pid); 2486 rv = CRYPTO_ARGUMENTS_BAD; 2487 goto release_minor; 2488 } 2489 2490 do_inplace = (STRUCT_FGET(encrypt, ce_flags) & 2491 CRYPTO_INPLACE_OPERATION) != 0; 2492 need = do_inplace ? datalen : datalen + encrlen; 2493 if ((rv = crypto_buffer_check(need)) != CRYPTO_SUCCESS) { 2494 need = 0; 2495 goto release_minor; 2496 } 2497 2498 INIT_RAW_CRYPTO_DATA(data, datalen); 2499 data.cd_miscdata = NULL; 2500 2501 if (datalen != 0 && copyin(STRUCT_FGETP(encrypt, ce_databuf), 2502 data.cd_raw.iov_base, datalen) != 0) { 2503 error = EFAULT; 2504 goto release_minor; 2505 } 2506 2507 if (do_inplace) { 2508 /* set out = in for in-place */ 2509 encr = data; 2510 } else { 2511 INIT_RAW_CRYPTO_DATA(encr, encrlen); 2512 } 2513 2514 session_id = STRUCT_FGET(encrypt, ce_session); 2515 2516 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 2517 goto release_minor; 2518 } 2519 2520 ctxpp = (single == crypto_encrypt_single) ? 2521 &sp->sd_encr_ctx : &sp->sd_decr_ctx; 2522 2523 /* in-place is specified by setting output NULL */ 2524 if (do_inplace) 2525 rv = (single)(*ctxpp, &encr, NULL, NULL); 2526 else 2527 rv = (single)(*ctxpp, &data, &encr, NULL); 2528 if (KCF_CONTEXT_DONE(rv)) 2529 *ctxpp = NULL; 2530 2531 CRYPTO_SESSION_RELE(sp); 2532 2533 if (rv == CRYPTO_SUCCESS) { 2534 ASSERT(encr.cd_length <= encrlen); 2535 if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base, 2536 encrbuf, encr.cd_length) != 0) { 2537 error = EFAULT; 2538 goto release_minor; 2539 } 2540 STRUCT_FSET(encrypt, ce_encrlen, encr.cd_length); 2541 } 2542 2543 if (rv == CRYPTO_BUFFER_TOO_SMALL) { 2544 /* 2545 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1 2546 * of section 11.2 of the pkcs11 spec. We catch it here and 2547 * provide the correct pkcs11 return value. 2548 */ 2549 if (STRUCT_FGETP(encrypt, ce_encrbuf) == NULL) 2550 rv = CRYPTO_SUCCESS; 2551 STRUCT_FSET(encrypt, ce_encrlen, encr.cd_length); 2552 } 2553 2554 release_minor: 2555 if (need != 0) { 2556 CRYPTO_DECREMENT_RCTL(need); 2557 } 2558 crypto_release_minor(cm); 2559 2560 if (data.cd_raw.iov_base != NULL) 2561 kmem_free(data.cd_raw.iov_base, datalen); 2562 2563 if (!do_inplace && encr.cd_raw.iov_base != NULL) 2564 kmem_free(encr.cd_raw.iov_base, encrlen); 2565 2566 if (error != 0) 2567 return (error); 2568 2569 STRUCT_FSET(encrypt, ce_return_value, rv); 2570 if (copyout(STRUCT_BUF(encrypt), arg, STRUCT_SIZE(encrypt)) != 0) { 2571 return (EFAULT); 2572 } 2573 return (0); 2574 } 2575 2576 /* ARGSUSED */ 2577 static int 2578 encrypt_update(dev_t dev, caddr_t arg, int mode, int *rval) 2579 { 2580 return (cipher_update(dev, arg, mode, crypto_encrypt_update)); 2581 } 2582 2583 /* ARGSUSED */ 2584 static int 2585 decrypt_update(dev_t dev, caddr_t arg, int mode, int *rval) 2586 { 2587 return (cipher_update(dev, arg, mode, crypto_decrypt_update)); 2588 } 2589 2590 /* 2591 * ASSUMPTION: crypto_encrypt_update and crypto_decrypt_update 2592 * structures are identical except for field names. 2593 */ 2594 static int 2595 cipher_update(dev_t dev, caddr_t arg, int mode, 2596 int (*update)(crypto_context_t, crypto_data_t *, crypto_data_t *, 2597 crypto_call_req_t *)) 2598 { 2599 STRUCT_DECL(crypto_encrypt_update, encrypt_update); 2600 crypto_session_id_t session_id; 2601 crypto_minor_t *cm; 2602 crypto_session_data_t *sp; 2603 crypto_ctx_t **ctxpp; 2604 crypto_data_t data, encr; 2605 size_t datalen, encrlen, need = 0; 2606 char *encrbuf; 2607 int error = 0; 2608 int rv; 2609 2610 STRUCT_INIT(encrypt_update, mode); 2611 2612 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 2613 cmn_err(CE_WARN, "cipher_update: failed holding minor"); 2614 return (ENXIO); 2615 } 2616 2617 if (copyin(arg, STRUCT_BUF(encrypt_update), 2618 STRUCT_SIZE(encrypt_update)) != 0) { 2619 crypto_release_minor(cm); 2620 return (EFAULT); 2621 } 2622 2623 data.cd_raw.iov_base = NULL; 2624 encr.cd_raw.iov_base = NULL; 2625 2626 datalen = STRUCT_FGET(encrypt_update, eu_datalen); 2627 encrlen = STRUCT_FGET(encrypt_update, eu_encrlen); 2628 2629 /* 2630 * Don't allocate output buffer unless both buffer pointer and 2631 * buffer length are not NULL or 0 (length). 2632 */ 2633 encrbuf = STRUCT_FGETP(encrypt_update, eu_encrbuf); 2634 if (encrbuf == NULL || encrlen == 0) { 2635 encrlen = 0; 2636 } 2637 2638 if (datalen > crypto_max_buffer_len || 2639 encrlen > crypto_max_buffer_len) { 2640 cmn_err(CE_NOTE, "cipher_update: buffer greater than %ld " 2641 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 2642 rv = CRYPTO_ARGUMENTS_BAD; 2643 goto release_minor; 2644 } 2645 2646 need = datalen + encrlen; 2647 if ((rv = crypto_buffer_check(need)) != CRYPTO_SUCCESS) { 2648 need = 0; 2649 goto release_minor; 2650 } 2651 2652 INIT_RAW_CRYPTO_DATA(data, datalen); 2653 data.cd_miscdata = NULL; 2654 2655 if (datalen != 0 && copyin(STRUCT_FGETP(encrypt_update, eu_databuf), 2656 data.cd_raw.iov_base, datalen) != 0) { 2657 error = EFAULT; 2658 goto release_minor; 2659 } 2660 2661 INIT_RAW_CRYPTO_DATA(encr, encrlen); 2662 2663 session_id = STRUCT_FGET(encrypt_update, eu_session); 2664 2665 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 2666 goto release_minor; 2667 } 2668 2669 ctxpp = (update == crypto_encrypt_update) ? 2670 &sp->sd_encr_ctx : &sp->sd_decr_ctx; 2671 2672 rv = (update)(*ctxpp, &data, &encr, NULL); 2673 2674 if (rv == CRYPTO_SUCCESS || rv == CRYPTO_BUFFER_TOO_SMALL) { 2675 if (rv == CRYPTO_SUCCESS) { 2676 ASSERT(encr.cd_length <= encrlen); 2677 if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base, 2678 encrbuf, encr.cd_length) != 0) { 2679 error = EFAULT; 2680 goto out; 2681 } 2682 } else { 2683 /* 2684 * The providers return CRYPTO_BUFFER_TOO_SMALL even 2685 * for case 1 of section 11.2 of the pkcs11 spec. 2686 * We catch it here and provide the correct pkcs11 2687 * return value. 2688 */ 2689 if (STRUCT_FGETP(encrypt_update, eu_encrbuf) == NULL) 2690 rv = CRYPTO_SUCCESS; 2691 } 2692 STRUCT_FSET(encrypt_update, eu_encrlen, encr.cd_length); 2693 } else { 2694 CRYPTO_CANCEL_CTX(ctxpp); 2695 } 2696 out: 2697 CRYPTO_SESSION_RELE(sp); 2698 2699 release_minor: 2700 if (need != 0) { 2701 CRYPTO_DECREMENT_RCTL(need); 2702 } 2703 crypto_release_minor(cm); 2704 2705 if (data.cd_raw.iov_base != NULL) 2706 kmem_free(data.cd_raw.iov_base, datalen); 2707 2708 if (encr.cd_raw.iov_base != NULL) 2709 kmem_free(encr.cd_raw.iov_base, encrlen); 2710 2711 if (error != 0) 2712 return (error); 2713 2714 STRUCT_FSET(encrypt_update, eu_return_value, rv); 2715 if (copyout(STRUCT_BUF(encrypt_update), arg, 2716 STRUCT_SIZE(encrypt_update)) != 0) { 2717 return (EFAULT); 2718 } 2719 return (0); 2720 } 2721 2722 /* ARGSUSED */ 2723 static int 2724 encrypt_final(dev_t dev, caddr_t arg, int mode, int *rval) 2725 { 2726 return (common_final(dev, arg, mode, crypto_encrypt_final)); 2727 } 2728 2729 /* ARGSUSED */ 2730 static int 2731 decrypt_final(dev_t dev, caddr_t arg, int mode, int *rval) 2732 { 2733 return (common_final(dev, arg, mode, crypto_decrypt_final)); 2734 } 2735 2736 /* 2737 * ASSUMPTION: crypto_encrypt_final, crypto_decrypt_final, crypto_sign_final, 2738 * and crypto_digest_final structures are identical except for field names. 2739 */ 2740 static int 2741 common_final(dev_t dev, caddr_t arg, int mode, 2742 int (*final)(crypto_context_t, crypto_data_t *, crypto_call_req_t *)) 2743 { 2744 STRUCT_DECL(crypto_encrypt_final, encrypt_final); 2745 crypto_session_id_t session_id; 2746 crypto_minor_t *cm; 2747 crypto_session_data_t *sp; 2748 crypto_ctx_t **ctxpp; 2749 crypto_data_t encr; 2750 size_t encrlen, need = 0; 2751 char *encrbuf; 2752 int error = 0; 2753 int rv; 2754 2755 STRUCT_INIT(encrypt_final, mode); 2756 2757 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 2758 cmn_err(CE_WARN, "common_final: failed holding minor"); 2759 return (ENXIO); 2760 } 2761 2762 if (copyin(arg, STRUCT_BUF(encrypt_final), 2763 STRUCT_SIZE(encrypt_final)) != 0) { 2764 crypto_release_minor(cm); 2765 return (EFAULT); 2766 } 2767 2768 encr.cd_format = CRYPTO_DATA_RAW; 2769 encr.cd_raw.iov_base = NULL; 2770 2771 encrlen = STRUCT_FGET(encrypt_final, ef_encrlen); 2772 2773 /* 2774 * Don't allocate output buffer unless both buffer pointer and 2775 * buffer length are not NULL or 0 (length). 2776 */ 2777 encrbuf = STRUCT_FGETP(encrypt_final, ef_encrbuf); 2778 if (encrbuf == NULL || encrlen == 0) { 2779 encrlen = 0; 2780 } 2781 2782 if (encrlen > crypto_max_buffer_len) { 2783 cmn_err(CE_NOTE, "common_final: buffer greater than %ld " 2784 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 2785 rv = CRYPTO_ARGUMENTS_BAD; 2786 goto release_minor; 2787 } 2788 2789 if ((rv = crypto_buffer_check(encrlen)) != CRYPTO_SUCCESS) { 2790 goto release_minor; 2791 } 2792 need = encrlen; 2793 encr.cd_raw.iov_base = kmem_alloc(encrlen, KM_SLEEP); 2794 encr.cd_raw.iov_len = encrlen; 2795 2796 encr.cd_offset = 0; 2797 encr.cd_length = encrlen; 2798 2799 session_id = STRUCT_FGET(encrypt_final, ef_session); 2800 2801 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 2802 goto release_minor; 2803 } 2804 2805 ASSERT(final == crypto_encrypt_final || 2806 final == crypto_decrypt_final || final == crypto_sign_final || 2807 final == crypto_digest_final); 2808 2809 if (final == crypto_encrypt_final) { 2810 ctxpp = &sp->sd_encr_ctx; 2811 } else if (final == crypto_decrypt_final) { 2812 ctxpp = &sp->sd_decr_ctx; 2813 } else if (final == crypto_sign_final) { 2814 ctxpp = &sp->sd_sign_ctx; 2815 } else { 2816 ctxpp = &sp->sd_digest_ctx; 2817 } 2818 2819 rv = (final)(*ctxpp, &encr, NULL); 2820 if (KCF_CONTEXT_DONE(rv)) 2821 *ctxpp = NULL; 2822 2823 CRYPTO_SESSION_RELE(sp); 2824 2825 if (rv == CRYPTO_SUCCESS) { 2826 ASSERT(encr.cd_length <= encrlen); 2827 if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base, 2828 encrbuf, encr.cd_length) != 0) { 2829 error = EFAULT; 2830 goto release_minor; 2831 } 2832 STRUCT_FSET(encrypt_final, ef_encrlen, encr.cd_length); 2833 } 2834 2835 if (rv == CRYPTO_BUFFER_TOO_SMALL) { 2836 /* 2837 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1 2838 * of section 11.2 of the pkcs11 spec. We catch it here and 2839 * provide the correct pkcs11 return value. 2840 */ 2841 if (STRUCT_FGETP(encrypt_final, ef_encrbuf) == NULL) 2842 rv = CRYPTO_SUCCESS; 2843 STRUCT_FSET(encrypt_final, ef_encrlen, encr.cd_length); 2844 } 2845 2846 release_minor: 2847 if (need != 0) { 2848 CRYPTO_DECREMENT_RCTL(need); 2849 } 2850 crypto_release_minor(cm); 2851 2852 if (encr.cd_raw.iov_base != NULL) 2853 kmem_free(encr.cd_raw.iov_base, encrlen); 2854 2855 if (error != 0) 2856 return (error); 2857 2858 STRUCT_FSET(encrypt_final, ef_return_value, rv); 2859 if (copyout(STRUCT_BUF(encrypt_final), arg, 2860 STRUCT_SIZE(encrypt_final)) != 0) { 2861 return (EFAULT); 2862 } 2863 return (0); 2864 } 2865 2866 /* ARGSUSED */ 2867 static int 2868 digest_init(dev_t dev, caddr_t arg, int mode, int *rval) 2869 { 2870 STRUCT_DECL(crypto_digest_init, digest_init); 2871 kcf_provider_desc_t *real_provider = NULL; 2872 crypto_session_id_t session_id; 2873 crypto_mechanism_t mech; 2874 crypto_minor_t *cm; 2875 crypto_session_data_t *sp; 2876 crypto_context_t cc; 2877 size_t rctl_bytes = 0; 2878 int error = 0; 2879 int rv; 2880 2881 STRUCT_INIT(digest_init, mode); 2882 2883 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 2884 cmn_err(CE_WARN, "digest_init: failed holding minor"); 2885 return (ENXIO); 2886 } 2887 2888 if (copyin(arg, STRUCT_BUF(digest_init), 2889 STRUCT_SIZE(digest_init)) != 0) { 2890 crypto_release_minor(cm); 2891 return (EFAULT); 2892 } 2893 2894 mech.cm_param = NULL; 2895 2896 session_id = STRUCT_FGET(digest_init, di_session); 2897 2898 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 2899 goto release_minor; 2900 } 2901 2902 if (!copyin_mech(mode, STRUCT_FADDR(digest_init, di_mech), &mech, 2903 &rctl_bytes, NULL, &rv, &error)) { 2904 goto out; 2905 } 2906 2907 if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID, 2908 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider, 2909 CRYPTO_FG_DIGEST)) != CRYPTO_SUCCESS) { 2910 goto out; 2911 } 2912 2913 rv = crypto_digest_init_prov(real_provider, 2914 sp->sd_provider_session->ps_session, &mech, &cc, NULL); 2915 2916 /* 2917 * Check if a context already exists. If so, it means it is being 2918 * abandoned. So, cancel it to avoid leaking it. 2919 */ 2920 if (sp->sd_digest_ctx != NULL) 2921 CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx); 2922 sp->sd_digest_ctx = (rv == CRYPTO_SUCCESS) ? cc : NULL; 2923 out: 2924 CRYPTO_SESSION_RELE(sp); 2925 2926 release_minor: 2927 if (rctl_bytes != 0) { 2928 CRYPTO_DECREMENT_RCTL(rctl_bytes); 2929 } 2930 crypto_release_minor(cm); 2931 2932 if (real_provider != NULL) 2933 KCF_PROV_REFRELE(real_provider); 2934 2935 if (mech.cm_param != NULL) 2936 kmem_free(mech.cm_param, mech.cm_param_len); 2937 2938 if (error != 0) 2939 return (error); 2940 2941 STRUCT_FSET(digest_init, di_return_value, rv); 2942 if (copyout(STRUCT_BUF(digest_init), arg, 2943 STRUCT_SIZE(digest_init)) != 0) { 2944 return (EFAULT); 2945 } 2946 return (0); 2947 } 2948 2949 /* ARGSUSED */ 2950 static int 2951 digest_update(dev_t dev, caddr_t arg, int mode, int *rval) 2952 { 2953 STRUCT_DECL(crypto_digest_update, digest_update); 2954 crypto_session_id_t session_id; 2955 crypto_minor_t *cm; 2956 crypto_session_data_t *sp; 2957 crypto_data_t data; 2958 size_t datalen, need = 0; 2959 int error = 0; 2960 int rv; 2961 2962 STRUCT_INIT(digest_update, mode); 2963 2964 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 2965 cmn_err(CE_WARN, "digest_update: failed holding minor"); 2966 return (ENXIO); 2967 } 2968 2969 if (copyin(arg, STRUCT_BUF(digest_update), 2970 STRUCT_SIZE(digest_update)) != 0) { 2971 crypto_release_minor(cm); 2972 return (EFAULT); 2973 } 2974 2975 data.cd_format = CRYPTO_DATA_RAW; 2976 data.cd_raw.iov_base = NULL; 2977 2978 datalen = STRUCT_FGET(digest_update, du_datalen); 2979 if (datalen > crypto_max_buffer_len) { 2980 cmn_err(CE_NOTE, "digest_update: buffer greater than %ld " 2981 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 2982 rv = CRYPTO_ARGUMENTS_BAD; 2983 goto release_minor; 2984 } 2985 2986 if ((rv = crypto_buffer_check(datalen)) != CRYPTO_SUCCESS) { 2987 goto release_minor; 2988 } 2989 need = datalen; 2990 data.cd_raw.iov_base = kmem_alloc(datalen, KM_SLEEP); 2991 data.cd_raw.iov_len = datalen; 2992 2993 if (datalen != 0 && copyin(STRUCT_FGETP(digest_update, du_databuf), 2994 data.cd_raw.iov_base, datalen) != 0) { 2995 error = EFAULT; 2996 goto release_minor; 2997 } 2998 2999 data.cd_offset = 0; 3000 data.cd_length = datalen; 3001 3002 session_id = STRUCT_FGET(digest_update, du_session); 3003 3004 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 3005 goto release_minor; 3006 } 3007 3008 rv = crypto_digest_update(sp->sd_digest_ctx, &data, NULL); 3009 if (rv != CRYPTO_SUCCESS) 3010 CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx); 3011 CRYPTO_SESSION_RELE(sp); 3012 3013 release_minor: 3014 if (need != 0) { 3015 CRYPTO_DECREMENT_RCTL(need); 3016 } 3017 crypto_release_minor(cm); 3018 3019 if (data.cd_raw.iov_base != NULL) 3020 kmem_free(data.cd_raw.iov_base, datalen); 3021 3022 if (error != 0) 3023 return (error); 3024 3025 STRUCT_FSET(digest_update, du_return_value, rv); 3026 if (copyout(STRUCT_BUF(digest_update), arg, 3027 STRUCT_SIZE(digest_update)) != 0) { 3028 return (EFAULT); 3029 } 3030 return (0); 3031 } 3032 3033 /* ARGSUSED */ 3034 static int 3035 digest_key(dev_t dev, caddr_t arg, int mode, int *rval) 3036 { 3037 STRUCT_DECL(crypto_digest_key, digest_key); 3038 crypto_session_id_t session_id; 3039 crypto_key_t key; 3040 crypto_minor_t *cm; 3041 crypto_session_data_t *sp; 3042 size_t rctl_bytes = 0; 3043 int error = 0; 3044 int rv; 3045 3046 STRUCT_INIT(digest_key, mode); 3047 3048 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3049 cmn_err(CE_WARN, "digest_key: failed holding minor"); 3050 return (ENXIO); 3051 } 3052 3053 if (copyin(arg, STRUCT_BUF(digest_key), STRUCT_SIZE(digest_key)) != 0) { 3054 crypto_release_minor(cm); 3055 return (EFAULT); 3056 } 3057 3058 bzero(&key, sizeof (crypto_key_t)); 3059 3060 session_id = STRUCT_FGET(digest_key, dk_session); 3061 3062 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 3063 goto release_minor; 3064 } 3065 3066 if (!copyin_key(mode, STRUCT_FADDR(digest_key, dk_key), &key, 3067 &rctl_bytes, &rv, &error, 0)) { 3068 goto out; 3069 } 3070 3071 rv = crypto_digest_key_prov(sp->sd_digest_ctx, &key, NULL); 3072 if (rv != CRYPTO_SUCCESS) 3073 CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx); 3074 out: 3075 CRYPTO_SESSION_RELE(sp); 3076 3077 release_minor: 3078 if (rctl_bytes != 0) { 3079 CRYPTO_DECREMENT_RCTL(rctl_bytes); 3080 } 3081 crypto_release_minor(cm); 3082 3083 free_crypto_key(&key); 3084 3085 if (error != 0) 3086 return (error); 3087 3088 STRUCT_FSET(digest_key, dk_return_value, rv); 3089 if (copyout(STRUCT_BUF(digest_key), arg, 3090 STRUCT_SIZE(digest_key)) != 0) { 3091 return (EFAULT); 3092 } 3093 return (0); 3094 } 3095 3096 /* ARGSUSED */ 3097 static int 3098 digest_final(dev_t dev, caddr_t arg, int mode, int *rval) 3099 { 3100 return (common_final(dev, arg, mode, crypto_digest_final)); 3101 } 3102 3103 /* ARGSUSED */ 3104 static int 3105 digest(dev_t dev, caddr_t arg, int mode, int *rval) 3106 { 3107 return (common_digest(dev, arg, mode, crypto_digest_single)); 3108 } 3109 3110 /* 3111 * ASSUMPTION: crypto_digest, crypto_sign, crypto_sign_recover, 3112 * and crypto_verify_recover are identical except for field names. 3113 */ 3114 static int 3115 common_digest(dev_t dev, caddr_t arg, int mode, 3116 int (*single)(crypto_context_t, crypto_data_t *, crypto_data_t *, 3117 crypto_call_req_t *)) 3118 { 3119 STRUCT_DECL(crypto_digest, crypto_digest); 3120 crypto_session_id_t session_id; 3121 crypto_minor_t *cm; 3122 crypto_session_data_t *sp; 3123 crypto_data_t data, digest; 3124 crypto_ctx_t **ctxpp; 3125 size_t datalen, digestlen, need = 0; 3126 char *digestbuf; 3127 int error = 0; 3128 int rv; 3129 3130 STRUCT_INIT(crypto_digest, mode); 3131 3132 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3133 cmn_err(CE_WARN, "common_digest: failed holding minor"); 3134 return (ENXIO); 3135 } 3136 3137 if (copyin(arg, STRUCT_BUF(crypto_digest), 3138 STRUCT_SIZE(crypto_digest)) != 0) { 3139 crypto_release_minor(cm); 3140 return (EFAULT); 3141 } 3142 3143 data.cd_raw.iov_base = NULL; 3144 digest.cd_raw.iov_base = NULL; 3145 3146 datalen = STRUCT_FGET(crypto_digest, cd_datalen); 3147 digestlen = STRUCT_FGET(crypto_digest, cd_digestlen); 3148 3149 /* 3150 * Don't allocate output buffer unless both buffer pointer and 3151 * buffer length are not NULL or 0 (length). 3152 */ 3153 digestbuf = STRUCT_FGETP(crypto_digest, cd_digestbuf); 3154 if (digestbuf == NULL || digestlen == 0) { 3155 digestlen = 0; 3156 } 3157 3158 if (datalen > crypto_max_buffer_len || 3159 digestlen > crypto_max_buffer_len) { 3160 cmn_err(CE_NOTE, "common_digest: buffer greater than %ld " 3161 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 3162 rv = CRYPTO_ARGUMENTS_BAD; 3163 goto release_minor; 3164 } 3165 3166 need = datalen + digestlen; 3167 if ((rv = crypto_buffer_check(need)) != CRYPTO_SUCCESS) { 3168 need = 0; 3169 goto release_minor; 3170 } 3171 3172 INIT_RAW_CRYPTO_DATA(data, datalen); 3173 3174 if (datalen != 0 && copyin(STRUCT_FGETP(crypto_digest, cd_databuf), 3175 data.cd_raw.iov_base, datalen) != 0) { 3176 error = EFAULT; 3177 goto release_minor; 3178 } 3179 3180 INIT_RAW_CRYPTO_DATA(digest, digestlen); 3181 3182 session_id = STRUCT_FGET(crypto_digest, cd_session); 3183 3184 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 3185 goto release_minor; 3186 } 3187 3188 ASSERT(single == crypto_digest_single || 3189 single == crypto_sign_single || 3190 single == crypto_verify_recover_single || 3191 single == crypto_sign_recover_single); 3192 3193 if (single == crypto_digest_single) { 3194 ctxpp = &sp->sd_digest_ctx; 3195 } else if (single == crypto_sign_single) { 3196 ctxpp = &sp->sd_sign_ctx; 3197 } else if (single == crypto_verify_recover_single) { 3198 ctxpp = &sp->sd_verify_recover_ctx; 3199 } else { 3200 ctxpp = &sp->sd_sign_recover_ctx; 3201 } 3202 rv = (single)(*ctxpp, &data, &digest, NULL); 3203 if (KCF_CONTEXT_DONE(rv)) 3204 *ctxpp = NULL; 3205 3206 CRYPTO_SESSION_RELE(sp); 3207 3208 if (rv == CRYPTO_SUCCESS) { 3209 ASSERT(digest.cd_length <= digestlen); 3210 if (digest.cd_length != 0 && copyout(digest.cd_raw.iov_base, 3211 digestbuf, digest.cd_length) != 0) { 3212 error = EFAULT; 3213 goto release_minor; 3214 } 3215 STRUCT_FSET(crypto_digest, cd_digestlen, digest.cd_length); 3216 } 3217 3218 if (rv == CRYPTO_BUFFER_TOO_SMALL) { 3219 /* 3220 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1 3221 * of section 11.2 of the pkcs11 spec. We catch it here and 3222 * provide the correct pkcs11 return value. 3223 */ 3224 if (STRUCT_FGETP(crypto_digest, cd_digestbuf) == NULL) 3225 rv = CRYPTO_SUCCESS; 3226 STRUCT_FSET(crypto_digest, cd_digestlen, digest.cd_length); 3227 } 3228 3229 release_minor: 3230 if (need != 0) { 3231 CRYPTO_DECREMENT_RCTL(need); 3232 } 3233 crypto_release_minor(cm); 3234 3235 if (data.cd_raw.iov_base != NULL) 3236 kmem_free(data.cd_raw.iov_base, datalen); 3237 3238 if (digest.cd_raw.iov_base != NULL) 3239 kmem_free(digest.cd_raw.iov_base, digestlen); 3240 3241 if (error != 0) 3242 return (error); 3243 3244 STRUCT_FSET(crypto_digest, cd_return_value, rv); 3245 if (copyout(STRUCT_BUF(crypto_digest), arg, 3246 STRUCT_SIZE(crypto_digest)) != 0) { 3247 return (EFAULT); 3248 } 3249 return (0); 3250 } 3251 3252 /* 3253 * A helper function that does what the name suggests. 3254 * Returns 0 on success and non-zero otherwise. 3255 * On failure, out_pin is set to 0. 3256 */ 3257 int 3258 get_pin_and_session_ptr(char *in_pin, char **out_pin, size_t pin_len, 3259 crypto_minor_t *cm, crypto_session_id_t sid, crypto_session_data_t **sp, 3260 int *rv, int *error) 3261 { 3262 char *tmp_pin = NULL; 3263 int tmp_error = 0, tmp_rv = 0; 3264 3265 if (pin_len > KCF_MAX_PIN_LEN) { 3266 tmp_rv = CRYPTO_PIN_LEN_RANGE; 3267 goto out; 3268 } 3269 tmp_pin = kmem_alloc(pin_len, KM_SLEEP); 3270 3271 if (pin_len != 0 && copyin(in_pin, tmp_pin, pin_len) != 0) { 3272 tmp_error = EFAULT; 3273 goto out; 3274 } 3275 3276 (void) get_session_ptr(sid, cm, sp, &tmp_error, &tmp_rv); 3277 out: 3278 *out_pin = tmp_pin; 3279 *rv = tmp_rv; 3280 *error = tmp_error; 3281 return (tmp_rv | tmp_error); 3282 } 3283 3284 /* ARGSUSED */ 3285 static int 3286 set_pin(dev_t dev, caddr_t arg, int mode, int *rval) 3287 { 3288 STRUCT_DECL(crypto_set_pin, set_pin); 3289 kcf_provider_desc_t *real_provider; 3290 kcf_req_params_t params; 3291 crypto_minor_t *cm; 3292 crypto_session_data_t *sp; 3293 char *old_pin = NULL; 3294 char *new_pin = NULL; 3295 size_t old_pin_len; 3296 size_t new_pin_len; 3297 int error = 0; 3298 int rv; 3299 3300 STRUCT_INIT(set_pin, mode); 3301 3302 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3303 cmn_err(CE_WARN, "set_pin: failed holding minor"); 3304 return (ENXIO); 3305 } 3306 3307 if (copyin(arg, STRUCT_BUF(set_pin), 3308 STRUCT_SIZE(set_pin)) != 0) { 3309 crypto_release_minor(cm); 3310 return (EFAULT); 3311 } 3312 3313 old_pin_len = STRUCT_FGET(set_pin, sp_old_len); 3314 3315 if (get_pin_and_session_ptr(STRUCT_FGETP(set_pin, sp_old_pin), 3316 &old_pin, old_pin_len, cm, STRUCT_FGET(set_pin, sp_session), 3317 &sp, &rv, &error) != 0) 3318 goto release_minor; 3319 3320 new_pin_len = STRUCT_FGET(set_pin, sp_new_len); 3321 if (new_pin_len > KCF_MAX_PIN_LEN) { 3322 rv = CRYPTO_PIN_LEN_RANGE; 3323 goto out; 3324 } 3325 new_pin = kmem_alloc(new_pin_len, KM_SLEEP); 3326 3327 if (new_pin_len != 0 && copyin(STRUCT_FGETP(set_pin, sp_new_pin), 3328 new_pin, new_pin_len) != 0) { 3329 error = EFAULT; 3330 goto out; 3331 } 3332 3333 if ((rv = kcf_get_hardware_provider_nomech( 3334 CRYPTO_OPS_OFFSET(provider_ops), CRYPTO_PROVIDER_OFFSET(set_pin), 3335 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider)) 3336 != CRYPTO_SUCCESS) { 3337 goto out; 3338 } 3339 3340 KCF_WRAP_PROVMGMT_OPS_PARAMS(¶ms, KCF_OP_MGMT_SETPIN, 3341 sp->sd_provider_session->ps_session, old_pin, old_pin_len, 3342 new_pin, new_pin_len, NULL, NULL, real_provider); 3343 3344 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 3345 KCF_PROV_REFRELE(real_provider); 3346 3347 out: 3348 CRYPTO_SESSION_RELE(sp); 3349 3350 release_minor: 3351 crypto_release_minor(cm); 3352 3353 if (old_pin != NULL) { 3354 bzero(old_pin, old_pin_len); 3355 kmem_free(old_pin, old_pin_len); 3356 } 3357 3358 if (new_pin != NULL) { 3359 bzero(new_pin, new_pin_len); 3360 kmem_free(new_pin, new_pin_len); 3361 } 3362 3363 if (error != 0) 3364 return (error); 3365 3366 STRUCT_FSET(set_pin, sp_return_value, rv); 3367 if (copyout(STRUCT_BUF(set_pin), arg, STRUCT_SIZE(set_pin)) != 0) { 3368 return (EFAULT); 3369 } 3370 return (0); 3371 } 3372 3373 /* ARGSUSED */ 3374 static int 3375 login(dev_t dev, caddr_t arg, int mode, int *rval) 3376 { 3377 STRUCT_DECL(crypto_login, login); 3378 kcf_provider_desc_t *real_provider; 3379 kcf_req_params_t params; 3380 crypto_minor_t *cm; 3381 crypto_session_data_t *sp; 3382 size_t pin_len; 3383 char *pin; 3384 uint_t user_type; 3385 int error = 0; 3386 int rv; 3387 3388 STRUCT_INIT(login, mode); 3389 3390 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3391 cmn_err(CE_WARN, "login: failed holding minor"); 3392 return (ENXIO); 3393 } 3394 3395 if (copyin(arg, STRUCT_BUF(login), STRUCT_SIZE(login)) != 0) { 3396 crypto_release_minor(cm); 3397 return (EFAULT); 3398 } 3399 3400 user_type = STRUCT_FGET(login, co_user_type); 3401 3402 pin_len = STRUCT_FGET(login, co_pin_len); 3403 3404 if (get_pin_and_session_ptr(STRUCT_FGETP(login, co_pin), 3405 &pin, pin_len, cm, STRUCT_FGET(login, co_session), 3406 &sp, &rv, &error) != 0) { 3407 if (rv == CRYPTO_PIN_LEN_RANGE) 3408 rv = CRYPTO_PIN_INCORRECT; 3409 goto release_minor; 3410 } 3411 3412 if ((rv = kcf_get_hardware_provider_nomech( 3413 CRYPTO_OPS_OFFSET(session_ops), 3414 CRYPTO_SESSION_OFFSET(session_login), 3415 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider)) 3416 != CRYPTO_SUCCESS) { 3417 goto out; 3418 } 3419 3420 KCF_WRAP_SESSION_OPS_PARAMS(¶ms, KCF_OP_SESSION_LOGIN, NULL, 3421 sp->sd_provider_session->ps_session, user_type, pin, pin_len, 3422 real_provider); 3423 3424 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 3425 KCF_PROV_REFRELE(real_provider); 3426 3427 out: 3428 CRYPTO_SESSION_RELE(sp); 3429 3430 release_minor: 3431 crypto_release_minor(cm); 3432 3433 if (pin != NULL) { 3434 bzero(pin, pin_len); 3435 kmem_free(pin, pin_len); 3436 } 3437 3438 if (error != 0) 3439 return (error); 3440 3441 STRUCT_FSET(login, co_return_value, rv); 3442 if (copyout(STRUCT_BUF(login), arg, STRUCT_SIZE(login)) != 0) { 3443 return (EFAULT); 3444 } 3445 return (0); 3446 } 3447 3448 /* ARGSUSED */ 3449 static int 3450 logout(dev_t dev, caddr_t arg, int mode, int *rval) 3451 { 3452 crypto_logout_t logout; 3453 kcf_provider_desc_t *real_provider; 3454 kcf_req_params_t params; 3455 crypto_minor_t *cm; 3456 crypto_session_data_t *sp; 3457 int error = 0; 3458 int rv; 3459 3460 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3461 cmn_err(CE_WARN, "logout: failed holding minor"); 3462 return (ENXIO); 3463 } 3464 3465 if (copyin(arg, &logout, sizeof (logout)) != 0) { 3466 crypto_release_minor(cm); 3467 return (EFAULT); 3468 } 3469 3470 if (!get_session_ptr(logout.cl_session, cm, &sp, &error, &rv)) { 3471 goto release_minor; 3472 } 3473 3474 if ((rv = kcf_get_hardware_provider_nomech( 3475 CRYPTO_OPS_OFFSET(session_ops), 3476 CRYPTO_SESSION_OFFSET(session_logout), CHECK_RESTRICT_FALSE, 3477 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 3478 goto out; 3479 } 3480 3481 KCF_WRAP_SESSION_OPS_PARAMS(¶ms, KCF_OP_SESSION_LOGOUT, NULL, 3482 sp->sd_provider_session->ps_session, 0, NULL, 0, real_provider); 3483 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 3484 KCF_PROV_REFRELE(real_provider); 3485 3486 out: 3487 CRYPTO_SESSION_RELE(sp); 3488 3489 release_minor: 3490 crypto_release_minor(cm); 3491 3492 if (error != 0) 3493 return (error); 3494 3495 logout.cl_return_value = rv; 3496 if (copyout(&logout, arg, sizeof (logout)) != 0) { 3497 return (EFAULT); 3498 } 3499 return (0); 3500 } 3501 3502 /* ARGSUSED */ 3503 static int 3504 sign_init(dev_t dev, caddr_t arg, int mode, int *rval) 3505 { 3506 return (sign_verify_init(dev, arg, mode, crypto_sign_init_prov)); 3507 } 3508 3509 /* ARGSUSED */ 3510 static int 3511 sign_recover_init(dev_t dev, caddr_t arg, int mode, int *rval) 3512 { 3513 return (sign_verify_init(dev, arg, mode, 3514 crypto_sign_recover_init_prov)); 3515 } 3516 3517 /* ARGSUSED */ 3518 static int 3519 verify_init(dev_t dev, caddr_t arg, int mode, int *rval) 3520 { 3521 return (sign_verify_init(dev, arg, mode, crypto_verify_init_prov)); 3522 } 3523 3524 /* ARGSUSED */ 3525 static int 3526 verify_recover_init(dev_t dev, caddr_t arg, int mode, int *rval) 3527 { 3528 return (sign_verify_init(dev, arg, mode, 3529 crypto_verify_recover_init_prov)); 3530 } 3531 3532 /* 3533 * ASSUMPTION: crypto_sign_init, crypto_verify_init, crypto_sign_recover_init, 3534 * and crypto_verify_recover_init structures are identical 3535 * except for field names. 3536 */ 3537 static int 3538 sign_verify_init(dev_t dev, caddr_t arg, int mode, 3539 int (*init)(crypto_provider_t, crypto_session_id_t, 3540 crypto_mechanism_t *, crypto_key_t *, crypto_ctx_template_t, 3541 crypto_context_t *, crypto_call_req_t *)) 3542 { 3543 STRUCT_DECL(crypto_sign_init, sign_init); 3544 kcf_provider_desc_t *real_provider = NULL; 3545 crypto_session_id_t session_id; 3546 crypto_mechanism_t mech; 3547 crypto_key_t key; 3548 crypto_minor_t *cm; 3549 crypto_session_data_t *sp; 3550 crypto_context_t cc; 3551 crypto_ctx_t **ctxpp; 3552 size_t mech_rctl_bytes = 0; 3553 size_t key_rctl_bytes = 0; 3554 size_t carry; 3555 int error = 0; 3556 int rv; 3557 boolean_t allocated_by_crypto_module = B_FALSE; 3558 crypto_func_group_t fg; 3559 3560 STRUCT_INIT(sign_init, mode); 3561 3562 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3563 cmn_err(CE_WARN, "sign_verify_init: failed holding minor"); 3564 return (ENXIO); 3565 } 3566 3567 if (copyin(arg, STRUCT_BUF(sign_init), STRUCT_SIZE(sign_init)) != 0) { 3568 crypto_release_minor(cm); 3569 return (EFAULT); 3570 } 3571 3572 mech.cm_param = NULL; 3573 bzero(&key, sizeof (key)); 3574 3575 session_id = STRUCT_FGET(sign_init, si_session); 3576 3577 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 3578 goto release_minor; 3579 } 3580 3581 bcopy(STRUCT_FADDR(sign_init, si_mech), &mech.cm_type, 3582 sizeof (crypto_mech_type_t)); 3583 3584 ASSERT(init == crypto_sign_init_prov || 3585 init == crypto_verify_init_prov || 3586 init == crypto_sign_recover_init_prov || 3587 init == crypto_verify_recover_init_prov); 3588 3589 if (init == crypto_sign_init_prov) { 3590 fg = CRYPTO_FG_SIGN; 3591 ctxpp = &sp->sd_sign_ctx; 3592 } else if (init == crypto_verify_init_prov) { 3593 fg = CRYPTO_FG_VERIFY; 3594 ctxpp = &sp->sd_verify_ctx; 3595 } else if (init == crypto_sign_recover_init_prov) { 3596 fg = CRYPTO_FG_SIGN_RECOVER; 3597 ctxpp = &sp->sd_sign_recover_ctx; 3598 } else { 3599 fg = CRYPTO_FG_VERIFY_RECOVER; 3600 ctxpp = &sp->sd_verify_recover_ctx; 3601 } 3602 3603 if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID, 3604 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider, fg)) 3605 != CRYPTO_SUCCESS) { 3606 goto out; 3607 } 3608 3609 carry = 0; 3610 rv = crypto_provider_copyin_mech_param(real_provider, 3611 STRUCT_FADDR(sign_init, si_mech), &mech, mode, &error); 3612 3613 if (rv == CRYPTO_NOT_SUPPORTED) { 3614 allocated_by_crypto_module = B_TRUE; 3615 if (!copyin_mech(mode, STRUCT_FADDR(sign_init, si_mech), 3616 &mech, &mech_rctl_bytes, &carry, &rv, &error)) { 3617 goto out; 3618 } 3619 } else { 3620 if (rv != CRYPTO_SUCCESS) 3621 goto out; 3622 } 3623 3624 if (!copyin_key(mode, STRUCT_FADDR(sign_init, si_key), &key, 3625 &key_rctl_bytes, &rv, &error, carry)) { 3626 goto out; 3627 } 3628 3629 rv = (init)(real_provider, sp->sd_provider_session->ps_session, 3630 &mech, &key, NULL, &cc, NULL); 3631 3632 /* 3633 * Check if a context already exists. If so, it means it is being 3634 * abandoned. So, cancel it to avoid leaking it. 3635 */ 3636 if (*ctxpp != NULL) 3637 CRYPTO_CANCEL_CTX(ctxpp); 3638 *ctxpp = (rv == CRYPTO_SUCCESS) ? cc : NULL; 3639 3640 out: 3641 CRYPTO_SESSION_RELE(sp); 3642 3643 release_minor: 3644 if (mech_rctl_bytes + key_rctl_bytes != 0) 3645 CRYPTO_DECREMENT_RCTL(mech_rctl_bytes + key_rctl_bytes); 3646 crypto_release_minor(cm); 3647 3648 if (real_provider != NULL) { 3649 crypto_free_mech(real_provider, 3650 allocated_by_crypto_module, &mech); 3651 KCF_PROV_REFRELE(real_provider); 3652 } 3653 3654 free_crypto_key(&key); 3655 3656 if (error != 0) 3657 return (error); 3658 3659 STRUCT_FSET(sign_init, si_return_value, rv); 3660 if (copyout(STRUCT_BUF(sign_init), arg, STRUCT_SIZE(sign_init)) != 0) { 3661 return (EFAULT); 3662 } 3663 return (0); 3664 } 3665 3666 /* ARGSUSED */ 3667 static int 3668 sign(dev_t dev, caddr_t arg, int mode, int *rval) 3669 { 3670 return (common_digest(dev, arg, mode, crypto_sign_single)); 3671 } 3672 3673 /* ARGSUSED */ 3674 static int 3675 sign_recover(dev_t dev, caddr_t arg, int mode, int *rval) 3676 { 3677 return (common_digest(dev, arg, mode, crypto_sign_recover_single)); 3678 } 3679 3680 /* ARGSUSED */ 3681 static int 3682 verify(dev_t dev, caddr_t arg, int mode, int *rval) 3683 { 3684 STRUCT_DECL(crypto_verify, verify); 3685 crypto_session_id_t session_id; 3686 crypto_minor_t *cm; 3687 crypto_session_data_t *sp; 3688 crypto_data_t data, sign; 3689 size_t datalen, signlen, need = 0; 3690 int error = 0; 3691 int rv; 3692 3693 STRUCT_INIT(verify, mode); 3694 3695 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3696 cmn_err(CE_WARN, "verify: failed holding minor"); 3697 return (ENXIO); 3698 } 3699 3700 if (copyin(arg, STRUCT_BUF(verify), STRUCT_SIZE(verify)) != 0) { 3701 crypto_release_minor(cm); 3702 return (EFAULT); 3703 } 3704 3705 data.cd_raw.iov_base = NULL; 3706 sign.cd_raw.iov_base = NULL; 3707 3708 datalen = STRUCT_FGET(verify, cv_datalen); 3709 signlen = STRUCT_FGET(verify, cv_signlen); 3710 if (datalen > crypto_max_buffer_len || 3711 signlen > crypto_max_buffer_len) { 3712 cmn_err(CE_NOTE, "verify: buffer greater than %ld bytes, " 3713 "pid = %d", crypto_max_buffer_len, curproc->p_pid); 3714 rv = CRYPTO_ARGUMENTS_BAD; 3715 goto release_minor; 3716 } 3717 3718 need = datalen + signlen; 3719 if ((rv = crypto_buffer_check(need)) != CRYPTO_SUCCESS) { 3720 need = 0; 3721 goto release_minor; 3722 } 3723 3724 INIT_RAW_CRYPTO_DATA(data, datalen); 3725 INIT_RAW_CRYPTO_DATA(sign, signlen); 3726 3727 if (datalen != 0 && copyin(STRUCT_FGETP(verify, cv_databuf), 3728 data.cd_raw.iov_base, datalen) != 0) { 3729 error = EFAULT; 3730 goto release_minor; 3731 } 3732 3733 if (signlen != 0 && copyin(STRUCT_FGETP(verify, cv_signbuf), 3734 sign.cd_raw.iov_base, signlen) != 0) { 3735 error = EFAULT; 3736 goto release_minor; 3737 } 3738 session_id = STRUCT_FGET(verify, cv_session); 3739 3740 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 3741 goto release_minor; 3742 } 3743 3744 rv = crypto_verify_single(sp->sd_verify_ctx, &data, &sign, NULL); 3745 if (KCF_CONTEXT_DONE(rv)) 3746 sp->sd_verify_ctx = NULL; 3747 3748 CRYPTO_SESSION_RELE(sp); 3749 3750 release_minor: 3751 if (need != 0) { 3752 CRYPTO_DECREMENT_RCTL(need); 3753 } 3754 crypto_release_minor(cm); 3755 3756 if (data.cd_raw.iov_base != NULL) 3757 kmem_free(data.cd_raw.iov_base, datalen); 3758 3759 if (sign.cd_raw.iov_base != NULL) 3760 kmem_free(sign.cd_raw.iov_base, signlen); 3761 3762 if (error != 0) 3763 return (error); 3764 3765 STRUCT_FSET(verify, cv_return_value, rv); 3766 if (copyout(STRUCT_BUF(verify), arg, STRUCT_SIZE(verify)) != 0) { 3767 return (EFAULT); 3768 } 3769 return (0); 3770 } 3771 3772 /* ARGSUSED */ 3773 static int 3774 verify_recover(dev_t dev, caddr_t arg, int mode, int *rval) 3775 { 3776 return (common_digest(dev, arg, mode, crypto_verify_recover_single)); 3777 } 3778 3779 /* ARGSUSED */ 3780 static int 3781 sign_update(dev_t dev, caddr_t arg, int mode, int *rval) 3782 { 3783 return (sign_verify_update(dev, arg, mode, crypto_sign_update)); 3784 } 3785 3786 /* ARGSUSED */ 3787 static int 3788 verify_update(dev_t dev, caddr_t arg, int mode, int *rval) 3789 { 3790 return (sign_verify_update(dev, arg, mode, crypto_verify_update)); 3791 } 3792 3793 /* 3794 * ASSUMPTION: crypto_sign_update and crypto_verify_update structures 3795 * are identical except for field names. 3796 */ 3797 static int 3798 sign_verify_update(dev_t dev, caddr_t arg, int mode, 3799 int (*update)(crypto_context_t, crypto_data_t *, crypto_call_req_t *)) 3800 { 3801 STRUCT_DECL(crypto_sign_update, sign_update); 3802 crypto_session_id_t session_id; 3803 crypto_minor_t *cm; 3804 crypto_session_data_t *sp; 3805 crypto_ctx_t **ctxpp; 3806 crypto_data_t data; 3807 size_t datalen, need = 0; 3808 int error = 0; 3809 int rv; 3810 3811 STRUCT_INIT(sign_update, mode); 3812 3813 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3814 cmn_err(CE_WARN, "sign_verify_update: failed holding minor"); 3815 return (ENXIO); 3816 } 3817 3818 if (copyin(arg, STRUCT_BUF(sign_update), 3819 STRUCT_SIZE(sign_update)) != 0) { 3820 crypto_release_minor(cm); 3821 return (EFAULT); 3822 } 3823 3824 data.cd_raw.iov_base = NULL; 3825 3826 datalen = STRUCT_FGET(sign_update, su_datalen); 3827 if (datalen > crypto_max_buffer_len) { 3828 cmn_err(CE_NOTE, "sign_verify_update: buffer greater than %ld " 3829 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 3830 rv = CRYPTO_ARGUMENTS_BAD; 3831 goto release_minor; 3832 } 3833 3834 if ((rv = crypto_buffer_check(datalen)) != CRYPTO_SUCCESS) { 3835 goto release_minor; 3836 } 3837 need = datalen; 3838 3839 INIT_RAW_CRYPTO_DATA(data, datalen); 3840 3841 if (datalen != 0 && copyin(STRUCT_FGETP(sign_update, su_databuf), 3842 data.cd_raw.iov_base, datalen) != 0) { 3843 error = EFAULT; 3844 goto release_minor; 3845 } 3846 3847 session_id = STRUCT_FGET(sign_update, su_session); 3848 3849 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 3850 goto release_minor; 3851 } 3852 3853 ctxpp = (update == crypto_sign_update) ? 3854 &sp->sd_sign_ctx : &sp->sd_verify_ctx; 3855 3856 rv = (update)(*ctxpp, &data, NULL); 3857 if (rv != CRYPTO_SUCCESS) 3858 CRYPTO_CANCEL_CTX(ctxpp); 3859 CRYPTO_SESSION_RELE(sp); 3860 3861 release_minor: 3862 if (need != 0) { 3863 CRYPTO_DECREMENT_RCTL(need); 3864 } 3865 crypto_release_minor(cm); 3866 3867 if (data.cd_raw.iov_base != NULL) 3868 kmem_free(data.cd_raw.iov_base, datalen); 3869 3870 if (error != 0) 3871 return (error); 3872 3873 STRUCT_FSET(sign_update, su_return_value, rv); 3874 if (copyout(STRUCT_BUF(sign_update), arg, 3875 STRUCT_SIZE(sign_update)) != 0) { 3876 return (EFAULT); 3877 } 3878 return (0); 3879 } 3880 3881 /* ARGSUSED */ 3882 static int 3883 sign_final(dev_t dev, caddr_t arg, int mode, int *rval) 3884 { 3885 return (common_final(dev, arg, mode, crypto_sign_final)); 3886 } 3887 3888 /* 3889 * Can't use the common final because it does a copyout of 3890 * the final part. 3891 */ 3892 /* ARGSUSED */ 3893 static int 3894 verify_final(dev_t dev, caddr_t arg, int mode, int *rval) 3895 { 3896 STRUCT_DECL(crypto_verify_final, verify_final); 3897 crypto_session_id_t session_id; 3898 crypto_minor_t *cm; 3899 crypto_session_data_t *sp; 3900 crypto_data_t sign; 3901 size_t signlen, need = 0; 3902 int error = 0; 3903 int rv; 3904 3905 STRUCT_INIT(verify_final, mode); 3906 3907 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3908 cmn_err(CE_WARN, "verify_final: failed holding minor"); 3909 return (ENXIO); 3910 } 3911 3912 if (copyin(arg, STRUCT_BUF(verify_final), 3913 STRUCT_SIZE(verify_final)) != 0) { 3914 crypto_release_minor(cm); 3915 return (EFAULT); 3916 } 3917 3918 sign.cd_raw.iov_base = NULL; 3919 3920 signlen = STRUCT_FGET(verify_final, vf_signlen); 3921 if (signlen > crypto_max_buffer_len) { 3922 cmn_err(CE_NOTE, "verify_final: buffer greater than %ld " 3923 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 3924 rv = CRYPTO_ARGUMENTS_BAD; 3925 goto release_minor; 3926 } 3927 3928 if ((rv = crypto_buffer_check(signlen)) != CRYPTO_SUCCESS) { 3929 goto release_minor; 3930 } 3931 need = signlen; 3932 3933 INIT_RAW_CRYPTO_DATA(sign, signlen); 3934 3935 if (signlen != 0 && copyin(STRUCT_FGETP(verify_final, vf_signbuf), 3936 sign.cd_raw.iov_base, signlen) != 0) { 3937 error = EFAULT; 3938 goto release_minor; 3939 } 3940 3941 session_id = STRUCT_FGET(verify_final, vf_session); 3942 3943 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 3944 goto release_minor; 3945 } 3946 3947 rv = crypto_verify_final(sp->sd_verify_ctx, &sign, NULL); 3948 if (KCF_CONTEXT_DONE(rv)) 3949 sp->sd_verify_ctx = NULL; 3950 3951 CRYPTO_SESSION_RELE(sp); 3952 3953 release_minor: 3954 if (need != 0) { 3955 CRYPTO_DECREMENT_RCTL(need); 3956 } 3957 crypto_release_minor(cm); 3958 3959 if (sign.cd_raw.iov_base != NULL) 3960 kmem_free(sign.cd_raw.iov_base, signlen); 3961 3962 if (error != 0) 3963 return (error); 3964 3965 STRUCT_FSET(verify_final, vf_return_value, rv); 3966 if (copyout(STRUCT_BUF(verify_final), arg, 3967 STRUCT_SIZE(verify_final)) != 0) { 3968 return (EFAULT); 3969 } 3970 return (0); 3971 } 3972 3973 /* ARGSUSED */ 3974 static int 3975 seed_random(dev_t dev, caddr_t arg, int mode, int *rval) 3976 { 3977 STRUCT_DECL(crypto_seed_random, seed_random); 3978 kcf_provider_desc_t *real_provider = NULL; 3979 kcf_req_params_t params; 3980 crypto_session_id_t session_id; 3981 crypto_minor_t *cm; 3982 crypto_session_data_t *sp; 3983 uchar_t *seed_buffer = NULL; 3984 size_t seed_len; 3985 size_t need = 0; 3986 int error = 0; 3987 int rv; 3988 3989 STRUCT_INIT(seed_random, mode); 3990 3991 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3992 cmn_err(CE_WARN, "seed_random: failed holding minor"); 3993 return (ENXIO); 3994 } 3995 3996 if (copyin(arg, STRUCT_BUF(seed_random), 3997 STRUCT_SIZE(seed_random)) != 0) { 3998 crypto_release_minor(cm); 3999 return (EFAULT); 4000 } 4001 4002 seed_len = STRUCT_FGET(seed_random, sr_seedlen); 4003 if (seed_len > crypto_max_buffer_len) { 4004 cmn_err(CE_NOTE, "seed_random: buffer greater than %ld " 4005 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 4006 rv = CRYPTO_ARGUMENTS_BAD; 4007 goto release_minor; 4008 } 4009 4010 if ((rv = crypto_buffer_check(seed_len)) != CRYPTO_SUCCESS) { 4011 goto release_minor; 4012 } 4013 need = seed_len; 4014 seed_buffer = kmem_alloc(seed_len, KM_SLEEP); 4015 4016 if (seed_len != 0 && copyin(STRUCT_FGETP(seed_random, sr_seedbuf), 4017 seed_buffer, seed_len) != 0) { 4018 error = EFAULT; 4019 goto release_minor; 4020 } 4021 4022 session_id = STRUCT_FGET(seed_random, sr_session); 4023 4024 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4025 goto release_minor; 4026 } 4027 4028 if ((rv = kcf_get_hardware_provider_nomech( 4029 CRYPTO_OPS_OFFSET(random_ops), CRYPTO_RANDOM_OFFSET(seed_random), 4030 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider)) 4031 != CRYPTO_SUCCESS) { 4032 goto out; 4033 } 4034 4035 KCF_WRAP_RANDOM_OPS_PARAMS(¶ms, KCF_OP_RANDOM_SEED, 4036 sp->sd_provider_session->ps_session, seed_buffer, seed_len, 0, 4037 CRYPTO_SEED_NOW); 4038 4039 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4040 4041 out: 4042 CRYPTO_SESSION_RELE(sp); 4043 4044 release_minor: 4045 if (need != 0) { 4046 CRYPTO_DECREMENT_RCTL(need); 4047 } 4048 crypto_release_minor(cm); 4049 4050 if (real_provider != NULL) 4051 KCF_PROV_REFRELE(real_provider); 4052 4053 if (seed_buffer != NULL) 4054 kmem_free(seed_buffer, seed_len); 4055 4056 if (error != 0) 4057 return (error); 4058 4059 STRUCT_FSET(seed_random, sr_return_value, rv); 4060 if (copyout(STRUCT_BUF(seed_random), arg, 4061 STRUCT_SIZE(seed_random)) != 0) { 4062 return (EFAULT); 4063 } 4064 return (0); 4065 } 4066 4067 /* ARGSUSED */ 4068 static int 4069 generate_random(dev_t dev, caddr_t arg, int mode, int *rval) 4070 { 4071 STRUCT_DECL(crypto_generate_random, generate_random); 4072 kcf_provider_desc_t *real_provider = NULL; 4073 kcf_req_params_t params; 4074 crypto_session_id_t session_id; 4075 crypto_minor_t *cm; 4076 crypto_session_data_t *sp; 4077 uchar_t *buffer = NULL; 4078 size_t len; 4079 size_t need = 0; 4080 int error = 0; 4081 int rv; 4082 4083 STRUCT_INIT(generate_random, mode); 4084 4085 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4086 cmn_err(CE_WARN, "generate_random: failed holding minor"); 4087 return (ENXIO); 4088 } 4089 4090 if (copyin(arg, STRUCT_BUF(generate_random), 4091 STRUCT_SIZE(generate_random)) != 0) { 4092 crypto_release_minor(cm); 4093 return (EFAULT); 4094 } 4095 4096 len = STRUCT_FGET(generate_random, gr_buflen); 4097 if (len > crypto_max_buffer_len) { 4098 cmn_err(CE_NOTE, "generate_random: buffer greater than %ld " 4099 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 4100 rv = CRYPTO_ARGUMENTS_BAD; 4101 goto release_minor; 4102 } 4103 4104 if ((rv = crypto_buffer_check(len)) != CRYPTO_SUCCESS) { 4105 goto release_minor; 4106 } 4107 need = len; 4108 buffer = kmem_alloc(len, KM_SLEEP); 4109 4110 session_id = STRUCT_FGET(generate_random, gr_session); 4111 4112 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4113 goto release_minor; 4114 } 4115 4116 if ((rv = kcf_get_hardware_provider_nomech( 4117 CRYPTO_OPS_OFFSET(random_ops), 4118 CRYPTO_RANDOM_OFFSET(generate_random), CHECK_RESTRICT_FALSE, 4119 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 4120 goto out; 4121 } 4122 4123 KCF_WRAP_RANDOM_OPS_PARAMS(¶ms, KCF_OP_RANDOM_GENERATE, 4124 sp->sd_provider_session->ps_session, buffer, len, 0, 0); 4125 4126 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4127 4128 out: 4129 CRYPTO_SESSION_RELE(sp); 4130 4131 if (rv == CRYPTO_SUCCESS) { 4132 if (len != 0 && copyout(buffer, 4133 STRUCT_FGETP(generate_random, gr_buf), len) != 0) { 4134 error = EFAULT; 4135 } 4136 } 4137 4138 release_minor: 4139 if (need != 0) { 4140 CRYPTO_DECREMENT_RCTL(need); 4141 } 4142 crypto_release_minor(cm); 4143 4144 if (real_provider != NULL) 4145 KCF_PROV_REFRELE(real_provider); 4146 4147 if (buffer != NULL) { 4148 /* random numbers are often used to create keys */ 4149 bzero(buffer, len); 4150 kmem_free(buffer, len); 4151 } 4152 4153 if (error != 0) 4154 return (error); 4155 4156 STRUCT_FSET(generate_random, gr_return_value, rv); 4157 if (copyout(STRUCT_BUF(generate_random), arg, 4158 STRUCT_SIZE(generate_random)) != 0) { 4159 return (EFAULT); 4160 } 4161 return (0); 4162 } 4163 4164 /* 4165 * Copyout a kernel array of attributes to user space. 4166 * u_attrs is the corresponding user space array containing 4167 * user space pointers necessary for the copyout. 4168 */ 4169 /* ARGSUSED */ 4170 static int 4171 copyout_attributes(int mode, caddr_t out, uint_t count, 4172 crypto_object_attribute_t *k_attrs, caddr_t u_attrs) 4173 { 4174 STRUCT_DECL(crypto_object_attribute, oa); 4175 caddr_t p, valuep; 4176 size_t value_len; 4177 size_t len; 4178 int i; 4179 int error = 0; 4180 4181 if (count == 0) 4182 return (0); 4183 4184 STRUCT_INIT(oa, mode); 4185 4186 len = count * STRUCT_SIZE(oa); 4187 4188 ASSERT(u_attrs != NULL); 4189 p = u_attrs; 4190 for (i = 0; i < count; i++) { 4191 /* can this bcopy be eliminated? */ 4192 bcopy(p, STRUCT_BUF(oa), STRUCT_SIZE(oa)); 4193 value_len = k_attrs[i].oa_value_len; 4194 STRUCT_FSET(oa, oa_type, k_attrs[i].oa_type); 4195 STRUCT_FSET(oa, oa_value_len, value_len); 4196 valuep = STRUCT_FGETP(oa, oa_value); 4197 if (valuep != NULL && value_len != -1) { 4198 if (copyout(k_attrs[i].oa_value, 4199 valuep, value_len) != 0) { 4200 error = EFAULT; 4201 goto out; 4202 } 4203 } 4204 bcopy(STRUCT_BUF(oa), p, STRUCT_SIZE(oa)); 4205 p += STRUCT_SIZE(oa); 4206 } 4207 if (copyout(u_attrs, out, len)) { 4208 error = EFAULT; 4209 } 4210 out: 4211 return (error); 4212 } 4213 4214 4215 /* ARGSUSED */ 4216 static int 4217 object_create(dev_t dev, caddr_t arg, int mode, int *rval) 4218 { 4219 STRUCT_DECL(crypto_object_create, object_create); 4220 kcf_provider_desc_t *real_provider = NULL; 4221 kcf_req_params_t params; 4222 crypto_object_attribute_t *k_attrs = NULL; 4223 crypto_session_id_t session_id; 4224 crypto_minor_t *cm; 4225 crypto_session_data_t *sp = NULL; 4226 crypto_object_id_t object_handle; 4227 caddr_t oc_attributes; 4228 size_t k_attrs_size; 4229 size_t rctl_bytes = 0; 4230 int error = 0; 4231 int rv; 4232 uint_t count; 4233 4234 STRUCT_INIT(object_create, mode); 4235 4236 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4237 cmn_err(CE_WARN, "object_create: failed holding minor"); 4238 return (ENXIO); 4239 } 4240 4241 if (copyin(arg, STRUCT_BUF(object_create), 4242 STRUCT_SIZE(object_create)) != 0) { 4243 crypto_release_minor(cm); 4244 return (EFAULT); 4245 } 4246 4247 count = STRUCT_FGET(object_create, oc_count); 4248 oc_attributes = STRUCT_FGETP(object_create, oc_attributes); 4249 if (!copyin_attributes(mode, count, oc_attributes, &k_attrs, 4250 &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 0, B_TRUE)) { 4251 goto release_minor; 4252 } 4253 4254 session_id = STRUCT_FGET(object_create, oc_session); 4255 4256 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4257 goto release_minor; 4258 } 4259 4260 if ((rv = kcf_get_hardware_provider_nomech( 4261 CRYPTO_OPS_OFFSET(object_ops), 4262 CRYPTO_OBJECT_OFFSET(object_create), 4263 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider)) 4264 != CRYPTO_SUCCESS) { 4265 goto release_minor; 4266 } 4267 4268 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_CREATE, 4269 sp->sd_provider_session->ps_session, 0, k_attrs, count, 4270 &object_handle, 0, NULL, NULL, 0, NULL); 4271 4272 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4273 4274 if (rv == CRYPTO_SUCCESS) 4275 STRUCT_FSET(object_create, oc_handle, object_handle); 4276 4277 release_minor: 4278 if (rctl_bytes != 0) { 4279 CRYPTO_DECREMENT_RCTL(rctl_bytes); 4280 } 4281 4282 if (k_attrs != NULL) 4283 kmem_free(k_attrs, k_attrs_size); 4284 4285 if (error != 0) 4286 goto out; 4287 4288 STRUCT_FSET(object_create, oc_return_value, rv); 4289 if (copyout(STRUCT_BUF(object_create), arg, 4290 STRUCT_SIZE(object_create)) != 0) { 4291 if (rv == CRYPTO_SUCCESS) { 4292 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 4293 KCF_OP_OBJECT_DESTROY, 4294 sp->sd_provider_session->ps_session, object_handle, 4295 NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 4296 4297 (void) kcf_submit_request(real_provider, NULL, 4298 NULL, ¶ms, B_FALSE); 4299 4300 error = EFAULT; 4301 } 4302 } 4303 out: 4304 if (sp != NULL) 4305 CRYPTO_SESSION_RELE(sp); 4306 crypto_release_minor(cm); 4307 if (real_provider != NULL) 4308 KCF_PROV_REFRELE(real_provider); 4309 return (error); 4310 } 4311 4312 /* ARGSUSED */ 4313 static int 4314 object_copy(dev_t dev, caddr_t arg, int mode, int *rval) 4315 { 4316 STRUCT_DECL(crypto_object_copy, object_copy); 4317 kcf_provider_desc_t *real_provider = NULL; 4318 kcf_req_params_t params; 4319 crypto_object_attribute_t *k_attrs = NULL; 4320 crypto_session_id_t session_id; 4321 crypto_minor_t *cm; 4322 crypto_session_data_t *sp = NULL; 4323 crypto_object_id_t handle, new_handle; 4324 caddr_t oc_new_attributes; 4325 size_t k_attrs_size; 4326 size_t rctl_bytes = 0; 4327 int error = 0; 4328 int rv; 4329 uint_t count; 4330 4331 STRUCT_INIT(object_copy, mode); 4332 4333 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4334 cmn_err(CE_WARN, "object_copy: failed holding minor"); 4335 return (ENXIO); 4336 } 4337 4338 if (copyin(arg, STRUCT_BUF(object_copy), 4339 STRUCT_SIZE(object_copy)) != 0) { 4340 crypto_release_minor(cm); 4341 return (EFAULT); 4342 } 4343 4344 count = STRUCT_FGET(object_copy, oc_count); 4345 oc_new_attributes = STRUCT_FGETP(object_copy, oc_new_attributes); 4346 if (!copyin_attributes(mode, count, oc_new_attributes, &k_attrs, 4347 &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 0, B_TRUE)) { 4348 goto release_minor; 4349 } 4350 4351 session_id = STRUCT_FGET(object_copy, oc_session); 4352 4353 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4354 goto release_minor; 4355 } 4356 4357 if ((rv = kcf_get_hardware_provider_nomech( 4358 CRYPTO_OPS_OFFSET(object_ops), 4359 CRYPTO_OBJECT_OFFSET(object_copy), CHECK_RESTRICT_FALSE, 4360 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 4361 goto release_minor; 4362 } 4363 4364 handle = STRUCT_FGET(object_copy, oc_handle); 4365 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_COPY, 4366 sp->sd_provider_session->ps_session, handle, k_attrs, count, 4367 &new_handle, 0, NULL, NULL, 0, NULL); 4368 4369 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4370 4371 if (rv == CRYPTO_SUCCESS) 4372 STRUCT_FSET(object_copy, oc_new_handle, new_handle); 4373 4374 release_minor: 4375 if (rctl_bytes != 0) { 4376 CRYPTO_DECREMENT_RCTL(rctl_bytes); 4377 } 4378 4379 if (k_attrs != NULL) 4380 kmem_free(k_attrs, k_attrs_size); 4381 4382 if (error != 0) 4383 goto out; 4384 4385 STRUCT_FSET(object_copy, oc_return_value, rv); 4386 if (copyout(STRUCT_BUF(object_copy), arg, 4387 STRUCT_SIZE(object_copy)) != 0) { 4388 if (rv == CRYPTO_SUCCESS) { 4389 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 4390 KCF_OP_OBJECT_DESTROY, 4391 sp->sd_provider_session->ps_session, new_handle, 4392 NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 4393 4394 (void) kcf_submit_request(real_provider, NULL, 4395 NULL, ¶ms, B_FALSE); 4396 4397 error = EFAULT; 4398 } 4399 } 4400 out: 4401 if (sp != NULL) 4402 CRYPTO_SESSION_RELE(sp); 4403 crypto_release_minor(cm); 4404 if (real_provider != NULL) 4405 KCF_PROV_REFRELE(real_provider); 4406 return (error); 4407 } 4408 4409 /* ARGSUSED */ 4410 static int 4411 object_destroy(dev_t dev, caddr_t arg, int mode, int *rval) 4412 { 4413 STRUCT_DECL(crypto_object_destroy, object_destroy); 4414 kcf_provider_desc_t *real_provider; 4415 kcf_req_params_t params; 4416 crypto_session_id_t session_id; 4417 crypto_minor_t *cm; 4418 crypto_session_data_t *sp; 4419 crypto_object_id_t handle; 4420 int error = 0; 4421 int rv; 4422 4423 STRUCT_INIT(object_destroy, mode); 4424 4425 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4426 cmn_err(CE_WARN, "object_destroy: failed holding minor"); 4427 return (ENXIO); 4428 } 4429 4430 if (copyin(arg, STRUCT_BUF(object_destroy), 4431 STRUCT_SIZE(object_destroy)) != 0) { 4432 crypto_release_minor(cm); 4433 return (EFAULT); 4434 } 4435 4436 session_id = STRUCT_FGET(object_destroy, od_session); 4437 4438 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4439 goto release_minor; 4440 } 4441 4442 if ((rv = kcf_get_hardware_provider_nomech( 4443 CRYPTO_OPS_OFFSET(object_ops), 4444 CRYPTO_OBJECT_OFFSET(object_destroy), CHECK_RESTRICT_FALSE, 4445 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 4446 goto out; 4447 } 4448 4449 handle = STRUCT_FGET(object_destroy, od_handle); 4450 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_DESTROY, 4451 sp->sd_provider_session->ps_session, handle, NULL, 0, NULL, 0, 4452 NULL, NULL, 0, NULL); 4453 4454 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4455 KCF_PROV_REFRELE(real_provider); 4456 4457 out: 4458 CRYPTO_SESSION_RELE(sp); 4459 4460 release_minor: 4461 crypto_release_minor(cm); 4462 4463 if (error != 0) 4464 return (error); 4465 4466 STRUCT_FSET(object_destroy, od_return_value, rv); 4467 4468 if (copyout(STRUCT_BUF(object_destroy), arg, 4469 STRUCT_SIZE(object_destroy)) != 0) { 4470 return (EFAULT); 4471 } 4472 return (0); 4473 } 4474 4475 /* ARGSUSED */ 4476 static int 4477 object_get_attribute_value(dev_t dev, caddr_t arg, int mode, int *rval) 4478 { 4479 STRUCT_DECL(crypto_object_get_attribute_value, get_attribute_value); 4480 /* LINTED E_FUNC_SET_NOT_USED */ 4481 STRUCT_DECL(crypto_object_attribute, oa); 4482 kcf_provider_desc_t *real_provider; 4483 kcf_req_params_t params; 4484 crypto_object_attribute_t *k_attrs = NULL; 4485 crypto_session_id_t session_id; 4486 crypto_minor_t *cm; 4487 crypto_session_data_t *sp; 4488 crypto_object_id_t handle; 4489 caddr_t og_attributes; 4490 caddr_t u_attrs; 4491 size_t k_attrs_size; 4492 size_t rctl_bytes = 0; 4493 int error = 0; 4494 int rv; 4495 uint_t count; 4496 4497 STRUCT_INIT(get_attribute_value, mode); 4498 STRUCT_INIT(oa, mode); 4499 4500 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4501 cmn_err(CE_WARN, 4502 "object_get_attribute_value: failed holding minor"); 4503 return (ENXIO); 4504 } 4505 4506 if (copyin(arg, STRUCT_BUF(get_attribute_value), 4507 STRUCT_SIZE(get_attribute_value)) != 0) { 4508 crypto_release_minor(cm); 4509 return (EFAULT); 4510 } 4511 4512 count = STRUCT_FGET(get_attribute_value, og_count); 4513 og_attributes = STRUCT_FGETP(get_attribute_value, og_attributes); 4514 if (!copyin_attributes(mode, count, og_attributes, &k_attrs, 4515 &k_attrs_size, &u_attrs, &rv, &error, &rctl_bytes, 0, B_FALSE)) { 4516 goto release_minor; 4517 } 4518 4519 session_id = STRUCT_FGET(get_attribute_value, og_session); 4520 4521 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4522 goto release_minor; 4523 } 4524 4525 if ((rv = kcf_get_hardware_provider_nomech( 4526 CRYPTO_OPS_OFFSET(object_ops), 4527 CRYPTO_OBJECT_OFFSET(object_get_attribute_value), 4528 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider)) 4529 != CRYPTO_SUCCESS) { 4530 goto out; 4531 } 4532 4533 handle = STRUCT_FGET(get_attribute_value, og_handle); 4534 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_GET_ATTRIBUTE_VALUE, 4535 sp->sd_provider_session->ps_session, handle, k_attrs, count, NULL, 4536 0, NULL, NULL, 0, NULL); 4537 4538 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4539 KCF_PROV_REFRELE(real_provider); 4540 4541 out: 4542 CRYPTO_SESSION_RELE(sp); 4543 4544 if (rv == CRYPTO_SUCCESS || rv == CRYPTO_ATTRIBUTE_SENSITIVE || 4545 rv == CRYPTO_ATTRIBUTE_TYPE_INVALID || 4546 rv == CRYPTO_BUFFER_TOO_SMALL) { 4547 error = copyout_attributes(mode, 4548 STRUCT_FGETP(get_attribute_value, og_attributes), 4549 count, k_attrs, u_attrs); 4550 } 4551 4552 release_minor: 4553 if (rctl_bytes != 0) { 4554 CRYPTO_DECREMENT_RCTL(rctl_bytes); 4555 } 4556 crypto_release_minor(cm); 4557 4558 if (k_attrs != NULL) 4559 kmem_free(k_attrs, k_attrs_size); 4560 4561 if (u_attrs != NULL) 4562 kmem_free(u_attrs, count * STRUCT_SIZE(oa)); 4563 4564 if (error != 0) 4565 return (error); 4566 4567 STRUCT_FSET(get_attribute_value, og_return_value, rv); 4568 if (copyout(STRUCT_BUF(get_attribute_value), arg, 4569 STRUCT_SIZE(get_attribute_value)) != 0) { 4570 return (EFAULT); 4571 } 4572 return (0); 4573 } 4574 4575 /* ARGSUSED */ 4576 static int 4577 object_get_size(dev_t dev, caddr_t arg, int mode, int *rval) 4578 { 4579 STRUCT_DECL(crypto_object_get_size, object_get_size); 4580 kcf_provider_desc_t *real_provider; 4581 kcf_req_params_t params; 4582 crypto_session_id_t session_id; 4583 crypto_minor_t *cm; 4584 crypto_session_data_t *sp; 4585 crypto_object_id_t handle; 4586 size_t size; 4587 int error = 0; 4588 int rv; 4589 4590 STRUCT_INIT(object_get_size, mode); 4591 4592 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4593 cmn_err(CE_WARN, "object_get_size: failed holding minor"); 4594 return (ENXIO); 4595 } 4596 4597 if (copyin(arg, STRUCT_BUF(object_get_size), 4598 STRUCT_SIZE(object_get_size)) != 0) { 4599 crypto_release_minor(cm); 4600 return (EFAULT); 4601 } 4602 4603 session_id = STRUCT_FGET(object_get_size, gs_session); 4604 4605 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4606 goto release_minor; 4607 } 4608 4609 if ((rv = kcf_get_hardware_provider_nomech( 4610 CRYPTO_OPS_OFFSET(object_ops), 4611 CRYPTO_OBJECT_OFFSET(object_get_size), CHECK_RESTRICT_FALSE, 4612 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 4613 goto out; 4614 } 4615 4616 handle = STRUCT_FGET(object_get_size, gs_handle); 4617 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_GET_SIZE, 4618 sp->sd_provider_session->ps_session, handle, NULL, 0, NULL, &size, 4619 NULL, NULL, 0, NULL); 4620 4621 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4622 KCF_PROV_REFRELE(real_provider); 4623 4624 out: 4625 CRYPTO_SESSION_RELE(sp); 4626 4627 if (rv == CRYPTO_SUCCESS) { 4628 STRUCT_FSET(object_get_size, gs_size, size); 4629 } 4630 release_minor: 4631 crypto_release_minor(cm); 4632 4633 if (error != 0) 4634 return (error); 4635 4636 STRUCT_FSET(object_get_size, gs_return_value, rv); 4637 if (copyout(STRUCT_BUF(object_get_size), arg, 4638 STRUCT_SIZE(object_get_size)) != 0) { 4639 return (EFAULT); 4640 } 4641 return (0); 4642 } 4643 4644 /* ARGSUSED */ 4645 static int 4646 object_set_attribute_value(dev_t dev, caddr_t arg, int mode, int *rval) 4647 { 4648 STRUCT_DECL(crypto_object_set_attribute_value, set_attribute_value); 4649 kcf_provider_desc_t *real_provider; 4650 kcf_req_params_t params; 4651 crypto_object_attribute_t *k_attrs = NULL; 4652 crypto_session_id_t session_id; 4653 crypto_minor_t *cm; 4654 crypto_session_data_t *sp; 4655 crypto_object_id_t object_handle; 4656 caddr_t sa_attributes; 4657 size_t k_attrs_size; 4658 size_t rctl_bytes = 0; 4659 int error = 0; 4660 int rv; 4661 uint_t count; 4662 4663 STRUCT_INIT(set_attribute_value, mode); 4664 4665 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4666 cmn_err(CE_WARN, 4667 "object_set_attribute_value: failed holding minor"); 4668 return (ENXIO); 4669 } 4670 4671 if (copyin(arg, STRUCT_BUF(set_attribute_value), 4672 STRUCT_SIZE(set_attribute_value)) != 0) { 4673 crypto_release_minor(cm); 4674 return (EFAULT); 4675 } 4676 4677 count = STRUCT_FGET(set_attribute_value, sa_count); 4678 sa_attributes = STRUCT_FGETP(set_attribute_value, sa_attributes); 4679 if (!copyin_attributes(mode, count, sa_attributes, &k_attrs, 4680 &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 0, B_TRUE)) { 4681 goto release_minor; 4682 } 4683 4684 session_id = STRUCT_FGET(set_attribute_value, sa_session); 4685 4686 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4687 goto release_minor; 4688 } 4689 4690 if ((rv = kcf_get_hardware_provider_nomech( 4691 CRYPTO_OPS_OFFSET(object_ops), 4692 CRYPTO_OBJECT_OFFSET(object_set_attribute_value), 4693 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider)) 4694 != CRYPTO_SUCCESS) { 4695 goto out; 4696 } 4697 4698 object_handle = STRUCT_FGET(set_attribute_value, sa_handle); 4699 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_SET_ATTRIBUTE_VALUE, 4700 sp->sd_provider_session->ps_session, object_handle, k_attrs, count, 4701 NULL, 0, NULL, NULL, 0, NULL); 4702 4703 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4704 KCF_PROV_REFRELE(real_provider); 4705 4706 out: 4707 CRYPTO_SESSION_RELE(sp); 4708 4709 release_minor: 4710 if (rctl_bytes != 0) { 4711 CRYPTO_DECREMENT_RCTL(rctl_bytes); 4712 } 4713 crypto_release_minor(cm); 4714 4715 if (k_attrs != NULL) 4716 kmem_free(k_attrs, k_attrs_size); 4717 4718 if (error != 0) 4719 return (error); 4720 4721 STRUCT_FSET(set_attribute_value, sa_return_value, rv); 4722 if (copyout(STRUCT_BUF(set_attribute_value), arg, 4723 STRUCT_SIZE(set_attribute_value)) != 0) { 4724 return (EFAULT); 4725 } 4726 return (0); 4727 } 4728 4729 /* ARGSUSED */ 4730 static int 4731 object_find_init(dev_t dev, caddr_t arg, int mode, int *rval) 4732 { 4733 STRUCT_DECL(crypto_object_find_init, find_init); 4734 kcf_provider_desc_t *real_provider = NULL; 4735 kcf_req_params_t params; 4736 crypto_object_attribute_t *k_attrs = NULL; 4737 crypto_session_id_t session_id; 4738 crypto_minor_t *cm; 4739 crypto_session_data_t *sp; 4740 caddr_t attributes; 4741 size_t k_attrs_size; 4742 size_t rctl_bytes = 0; 4743 int error = 0; 4744 int rv; 4745 uint_t count; 4746 void *cookie; 4747 4748 STRUCT_INIT(find_init, mode); 4749 4750 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4751 cmn_err(CE_WARN, "object_find_init: failed holding minor"); 4752 return (ENXIO); 4753 } 4754 4755 if (copyin(arg, STRUCT_BUF(find_init), STRUCT_SIZE(find_init)) != 0) { 4756 crypto_release_minor(cm); 4757 return (EFAULT); 4758 } 4759 4760 count = STRUCT_FGET(find_init, fi_count); 4761 attributes = STRUCT_FGETP(find_init, fi_attributes); 4762 if (!copyin_attributes(mode, count, attributes, &k_attrs, 4763 &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 0, B_TRUE)) { 4764 goto release_minor; 4765 } 4766 4767 session_id = STRUCT_FGET(find_init, fi_session); 4768 4769 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4770 goto release_minor; 4771 } 4772 4773 if ((rv = kcf_get_hardware_provider_nomech( 4774 CRYPTO_OPS_OFFSET(object_ops), 4775 CRYPTO_OBJECT_OFFSET(object_find_init), CHECK_RESTRICT_FALSE, 4776 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 4777 goto out; 4778 } 4779 4780 /* check for an active find */ 4781 if (sp->sd_find_init_cookie != NULL) { 4782 rv = CRYPTO_OPERATION_IS_ACTIVE; 4783 CRYPTO_SESSION_RELE(sp); 4784 goto release_minor; 4785 } 4786 4787 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_FIND_INIT, 4788 sp->sd_provider_session->ps_session, 0, k_attrs, count, NULL, 0, 4789 &cookie, NULL, 0, NULL); 4790 4791 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4792 4793 if (rv == CRYPTO_SUCCESS) { 4794 /* 4795 * The cookie is allocated by a provider at the start of an 4796 * object search. It is freed when the search is terminated 4797 * by a final operation, or when the session is closed. 4798 * It contains state information about which object handles 4799 * have been returned to the caller. 4800 */ 4801 sp->sd_find_init_cookie = cookie; 4802 } 4803 4804 out: 4805 CRYPTO_SESSION_RELE(sp); 4806 4807 release_minor: 4808 if (rctl_bytes != 0) { 4809 CRYPTO_DECREMENT_RCTL(rctl_bytes); 4810 } 4811 crypto_release_minor(cm); 4812 4813 if (real_provider != NULL) 4814 KCF_PROV_REFRELE(real_provider); 4815 4816 if (k_attrs != NULL) 4817 kmem_free(k_attrs, k_attrs_size); 4818 4819 if (error != 0) 4820 return (error); 4821 4822 STRUCT_FSET(find_init, fi_return_value, rv); 4823 if (copyout(STRUCT_BUF(find_init), arg, STRUCT_SIZE(find_init)) != 0) { 4824 return (EFAULT); 4825 } 4826 return (0); 4827 } 4828 4829 /* ARGSUSED */ 4830 static int 4831 object_find_update(dev_t dev, caddr_t arg, int mode, int *rval) 4832 { 4833 STRUCT_DECL(crypto_object_find_update, find_update); 4834 kcf_provider_desc_t *real_provider; 4835 kcf_req_params_t params; 4836 crypto_minor_t *cm; 4837 crypto_session_data_t *sp; 4838 crypto_object_id_t *buffer = NULL; 4839 crypto_session_id_t session_id; 4840 size_t len, rctl_bytes = 0; 4841 uint_t count, max_count; 4842 int rv, error = 0; 4843 4844 STRUCT_INIT(find_update, mode); 4845 4846 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4847 cmn_err(CE_WARN, "object_find_update: failed holding minor"); 4848 return (ENXIO); 4849 } 4850 4851 if (copyin(arg, STRUCT_BUF(find_update), 4852 STRUCT_SIZE(find_update)) != 0) { 4853 crypto_release_minor(cm); 4854 return (EFAULT); 4855 } 4856 4857 max_count = STRUCT_FGET(find_update, fu_max_count); 4858 if (max_count > CRYPTO_MAX_FIND_COUNT) { 4859 cmn_err(CE_NOTE, "object_find_update: count greater than %d, " 4860 "pid = %d", CRYPTO_MAX_FIND_COUNT, curproc->p_pid); 4861 rv = CRYPTO_ARGUMENTS_BAD; 4862 goto release_minor; 4863 } 4864 len = max_count * sizeof (crypto_object_id_t); 4865 if ((rv = crypto_buffer_check(len)) != CRYPTO_SUCCESS) { 4866 goto release_minor; 4867 } 4868 rctl_bytes = len; 4869 buffer = kmem_alloc(len, KM_SLEEP); 4870 4871 session_id = STRUCT_FGET(find_update, fu_session); 4872 4873 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4874 goto release_minor; 4875 } 4876 4877 if ((rv = kcf_get_hardware_provider_nomech( 4878 CRYPTO_OPS_OFFSET(object_ops), 4879 CRYPTO_OBJECT_OFFSET(object_find), CHECK_RESTRICT_FALSE, 4880 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 4881 goto out; 4882 } 4883 4884 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_FIND, 4885 sp->sd_provider_session->ps_session, 0, NULL, 0, buffer, 0, 4886 NULL, sp->sd_find_init_cookie, max_count, &count); 4887 4888 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4889 KCF_PROV_REFRELE(real_provider); 4890 4891 out: 4892 CRYPTO_SESSION_RELE(sp); 4893 if (rv == CRYPTO_SUCCESS) { 4894 if (count > max_count) { 4895 /* bad bad provider */ 4896 rv = CRYPTO_FAILED; 4897 goto release_minor; 4898 } 4899 if (count != 0) { 4900 /* copyout handles */ 4901 if (copyout(buffer, 4902 STRUCT_FGETP(find_update, fu_handles), 4903 count * sizeof (crypto_object_id_t)) != 0) { 4904 error = EFAULT; 4905 } 4906 } 4907 STRUCT_FSET(find_update, fu_count, count); 4908 } 4909 4910 release_minor: 4911 if (rctl_bytes != 0) { 4912 CRYPTO_DECREMENT_RCTL(rctl_bytes); 4913 } 4914 crypto_release_minor(cm); 4915 4916 if (buffer != NULL) 4917 kmem_free(buffer, len); 4918 4919 if (error != 0) 4920 return (error); 4921 4922 STRUCT_FSET(find_update, fu_return_value, rv); 4923 if (copyout(STRUCT_BUF(find_update), arg, 4924 STRUCT_SIZE(find_update)) != 0) { 4925 return (EFAULT); 4926 } 4927 4928 return (0); 4929 } 4930 4931 /* 4932 * Free provider-allocated storage used for find object searches. 4933 */ 4934 static int 4935 crypto_free_find_ctx(crypto_session_data_t *sp) 4936 { 4937 kcf_provider_desc_t *real_provider; 4938 kcf_req_params_t params; 4939 int rv; 4940 4941 if ((rv = kcf_get_hardware_provider_nomech( 4942 CRYPTO_OPS_OFFSET(object_ops), 4943 CRYPTO_OBJECT_OFFSET(object_find_final), CHECK_RESTRICT_FALSE, 4944 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 4945 return (rv); 4946 } 4947 4948 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_FIND_FINAL, 4949 sp->sd_provider_session->ps_session, 0, NULL, 0, NULL, 0, 4950 NULL, sp->sd_find_init_cookie, 0, NULL); 4951 4952 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4953 KCF_PROV_REFRELE(real_provider); 4954 return (rv); 4955 } 4956 4957 /* ARGSUSED */ 4958 static int 4959 object_find_final(dev_t dev, caddr_t arg, int mode, int *rval) 4960 { 4961 STRUCT_DECL(crypto_object_find_final, object_find_final); 4962 crypto_session_id_t session_id; 4963 crypto_minor_t *cm; 4964 crypto_session_data_t *sp; 4965 int error = 0; 4966 int rv; 4967 4968 STRUCT_INIT(object_find_final, mode); 4969 4970 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4971 cmn_err(CE_WARN, "object_find_final: failed holding minor"); 4972 return (ENXIO); 4973 } 4974 4975 if (copyin(arg, STRUCT_BUF(object_find_final), 4976 STRUCT_SIZE(object_find_final)) != 0) { 4977 crypto_release_minor(cm); 4978 return (EFAULT); 4979 } 4980 4981 session_id = STRUCT_FGET(object_find_final, ff_session); 4982 4983 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4984 goto release_minor; 4985 } 4986 4987 if ((rv = crypto_free_find_ctx(sp)) == CRYPTO_SUCCESS) { 4988 sp->sd_find_init_cookie = NULL; 4989 } 4990 4991 CRYPTO_SESSION_RELE(sp); 4992 4993 release_minor: 4994 crypto_release_minor(cm); 4995 4996 if (error != 0) 4997 return (error); 4998 4999 STRUCT_FSET(object_find_final, ff_return_value, rv); 5000 5001 if (copyout(STRUCT_BUF(object_find_final), arg, 5002 STRUCT_SIZE(object_find_final)) != 0) { 5003 return (EFAULT); 5004 } 5005 return (0); 5006 } 5007 5008 /* ARGSUSED */ 5009 static int 5010 object_generate_key(dev_t dev, caddr_t arg, int mode, int *rval) 5011 { 5012 STRUCT_DECL(crypto_object_generate_key, generate_key); 5013 kcf_provider_desc_t *real_provider = NULL; 5014 kcf_req_params_t params; 5015 crypto_mechanism_t mech; 5016 crypto_object_attribute_t *k_attrs = NULL; 5017 crypto_session_id_t session_id; 5018 crypto_minor_t *cm; 5019 crypto_session_data_t *sp = NULL; 5020 crypto_object_id_t key_handle; 5021 caddr_t attributes; 5022 size_t k_attrs_size; 5023 size_t mech_rctl_bytes = 0, key_rctl_bytes = 0; 5024 size_t carry; 5025 uint_t count; 5026 int error = 0; 5027 int rv; 5028 boolean_t allocated_by_crypto_module = B_FALSE; 5029 5030 STRUCT_INIT(generate_key, mode); 5031 5032 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 5033 cmn_err(CE_WARN, "object_generate_key: failed holding minor"); 5034 return (ENXIO); 5035 } 5036 5037 if (copyin(arg, STRUCT_BUF(generate_key), 5038 STRUCT_SIZE(generate_key)) != 0) { 5039 crypto_release_minor(cm); 5040 return (EFAULT); 5041 } 5042 5043 session_id = STRUCT_FGET(generate_key, gk_session); 5044 5045 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 5046 goto release_minor; 5047 } 5048 5049 bcopy(STRUCT_FADDR(generate_key, gk_mechanism), &mech.cm_type, 5050 sizeof (crypto_mech_type_t)); 5051 5052 if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID, 5053 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider, 5054 CRYPTO_FG_GENERATE)) != CRYPTO_SUCCESS) { 5055 goto release_minor; 5056 } 5057 5058 carry = 0; 5059 rv = crypto_provider_copyin_mech_param(real_provider, 5060 STRUCT_FADDR(generate_key, gk_mechanism), &mech, mode, &error); 5061 5062 if (rv == CRYPTO_NOT_SUPPORTED) { 5063 allocated_by_crypto_module = B_TRUE; 5064 if (!copyin_mech(mode, STRUCT_FADDR(generate_key, gk_mechanism), 5065 &mech, &mech_rctl_bytes, &carry, &rv, &error)) { 5066 goto release_minor; 5067 } 5068 } else { 5069 if (rv != CRYPTO_SUCCESS) 5070 goto release_minor; 5071 } 5072 5073 count = STRUCT_FGET(generate_key, gk_count); 5074 attributes = STRUCT_FGETP(generate_key, gk_attributes); 5075 if (!copyin_attributes(mode, count, attributes, &k_attrs, 5076 &k_attrs_size, NULL, &rv, &error, &key_rctl_bytes, carry, B_TRUE)) { 5077 goto release_minor; 5078 } 5079 5080 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_GENERATE, 5081 sp->sd_provider_session->ps_session, &mech, k_attrs, count, 5082 &key_handle, NULL, 0, NULL, NULL, NULL, 0); 5083 5084 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5085 5086 if (rv == CRYPTO_SUCCESS) 5087 STRUCT_FSET(generate_key, gk_handle, key_handle); 5088 5089 release_minor: 5090 if (mech_rctl_bytes + key_rctl_bytes != 0) 5091 CRYPTO_DECREMENT_RCTL(mech_rctl_bytes + key_rctl_bytes); 5092 5093 if (k_attrs != NULL) 5094 kmem_free(k_attrs, k_attrs_size); 5095 5096 if (error != 0) 5097 goto out; 5098 5099 STRUCT_FSET(generate_key, gk_return_value, rv); 5100 if (copyout(STRUCT_BUF(generate_key), arg, 5101 STRUCT_SIZE(generate_key)) != 0) { 5102 if (rv == CRYPTO_SUCCESS) { 5103 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 5104 KCF_OP_OBJECT_DESTROY, 5105 sp->sd_provider_session->ps_session, key_handle, 5106 NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 5107 5108 (void) kcf_submit_request(real_provider, NULL, 5109 NULL, ¶ms, B_FALSE); 5110 5111 error = EFAULT; 5112 } 5113 } 5114 out: 5115 if (sp != NULL) 5116 CRYPTO_SESSION_RELE(sp); 5117 crypto_release_minor(cm); 5118 5119 if (real_provider != NULL) { 5120 crypto_free_mech(real_provider, 5121 allocated_by_crypto_module, &mech); 5122 KCF_PROV_REFRELE(real_provider); 5123 } 5124 return (error); 5125 } 5126 5127 /* ARGSUSED */ 5128 static int 5129 nostore_generate_key(dev_t dev, caddr_t arg, int mode, int *rval) 5130 { 5131 STRUCT_DECL(crypto_nostore_generate_key, generate_key); 5132 /* LINTED E_FUNC_SET_NOT_USED */ 5133 STRUCT_DECL(crypto_object_attribute, oa); 5134 kcf_provider_desc_t *real_provider = NULL; 5135 kcf_req_params_t params; 5136 crypto_mechanism_t mech; 5137 crypto_object_attribute_t *k_in_attrs = NULL; 5138 crypto_object_attribute_t *k_out_attrs = NULL; 5139 crypto_session_id_t session_id; 5140 crypto_minor_t *cm; 5141 crypto_session_data_t *sp = NULL; 5142 caddr_t in_attributes; 5143 caddr_t out_attributes; 5144 size_t k_in_attrs_size; 5145 size_t k_out_attrs_size; 5146 size_t mech_rctl_bytes = 0; 5147 size_t in_key_rctl_bytes = 0, out_key_rctl_bytes = 0; 5148 size_t carry; 5149 uint_t in_count; 5150 uint_t out_count; 5151 int error = 0; 5152 int rv; 5153 boolean_t allocated_by_crypto_module = B_FALSE; 5154 caddr_t u_attrs = NULL; 5155 5156 STRUCT_INIT(generate_key, mode); 5157 STRUCT_INIT(oa, mode); 5158 5159 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 5160 cmn_err(CE_WARN, "nostore_generate_key: failed holding minor"); 5161 return (ENXIO); 5162 } 5163 5164 if (copyin(arg, STRUCT_BUF(generate_key), 5165 STRUCT_SIZE(generate_key)) != 0) { 5166 crypto_release_minor(cm); 5167 return (EFAULT); 5168 } 5169 5170 session_id = STRUCT_FGET(generate_key, ngk_session); 5171 5172 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 5173 goto release_minor; 5174 } 5175 5176 bcopy(STRUCT_FADDR(generate_key, ngk_mechanism), &mech.cm_type, 5177 sizeof (crypto_mech_type_t)); 5178 5179 if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID, 5180 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider, 5181 CRYPTO_FG_GENERATE)) != CRYPTO_SUCCESS) { 5182 goto release_minor; 5183 } 5184 5185 carry = 0; 5186 rv = crypto_provider_copyin_mech_param(real_provider, 5187 STRUCT_FADDR(generate_key, ngk_mechanism), &mech, mode, &error); 5188 5189 if (rv == CRYPTO_NOT_SUPPORTED) { 5190 allocated_by_crypto_module = B_TRUE; 5191 if (!copyin_mech(mode, STRUCT_FADDR(generate_key, 5192 ngk_mechanism), &mech, &mech_rctl_bytes, &carry, &rv, 5193 &error)) { 5194 goto release_minor; 5195 } 5196 } else { 5197 if (rv != CRYPTO_SUCCESS) 5198 goto release_minor; 5199 } 5200 5201 in_count = STRUCT_FGET(generate_key, ngk_in_count); 5202 in_attributes = STRUCT_FGETP(generate_key, ngk_in_attributes); 5203 if (!copyin_attributes(mode, in_count, in_attributes, &k_in_attrs, 5204 &k_in_attrs_size, NULL, &rv, &error, &in_key_rctl_bytes, 5205 carry, B_TRUE)) { 5206 goto release_minor; 5207 } 5208 5209 out_count = STRUCT_FGET(generate_key, ngk_out_count); 5210 out_attributes = STRUCT_FGETP(generate_key, ngk_out_attributes); 5211 if (!copyin_attributes(mode, out_count, out_attributes, &k_out_attrs, 5212 &k_out_attrs_size, &u_attrs, &rv, &error, &out_key_rctl_bytes, 5213 0, B_FALSE)) { 5214 goto release_minor; 5215 } 5216 5217 KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_GENERATE, 5218 sp->sd_provider_session->ps_session, &mech, k_in_attrs, in_count, 5219 NULL, 0, NULL, k_out_attrs, out_count, NULL, 0); 5220 5221 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5222 5223 if (rv == CRYPTO_SUCCESS) { 5224 error = copyout_attributes(mode, out_attributes, 5225 out_count, k_out_attrs, u_attrs); 5226 } 5227 release_minor: 5228 if (mech_rctl_bytes + in_key_rctl_bytes + out_key_rctl_bytes != 0) 5229 CRYPTO_DECREMENT_RCTL(mech_rctl_bytes + in_key_rctl_bytes + 5230 out_key_rctl_bytes); 5231 5232 if (k_in_attrs != NULL) 5233 kmem_free(k_in_attrs, k_in_attrs_size); 5234 if (k_out_attrs != NULL) { 5235 bzero(k_out_attrs, k_out_attrs_size); 5236 kmem_free(k_out_attrs, k_out_attrs_size); 5237 } 5238 5239 if (u_attrs != NULL) 5240 kmem_free(u_attrs, out_count * STRUCT_SIZE(oa)); 5241 5242 if (error != 0) 5243 goto out; 5244 5245 STRUCT_FSET(generate_key, ngk_return_value, rv); 5246 if (copyout(STRUCT_BUF(generate_key), arg, 5247 STRUCT_SIZE(generate_key)) != 0) { 5248 error = EFAULT; 5249 } 5250 out: 5251 if (sp != NULL) 5252 CRYPTO_SESSION_RELE(sp); 5253 crypto_release_minor(cm); 5254 5255 if (real_provider != NULL) { 5256 crypto_free_mech(real_provider, 5257 allocated_by_crypto_module, &mech); 5258 KCF_PROV_REFRELE(real_provider); 5259 } 5260 return (error); 5261 } 5262 5263 /* ARGSUSED */ 5264 static int 5265 object_generate_key_pair(dev_t dev, caddr_t arg, int mode, int *rval) 5266 { 5267 STRUCT_DECL(crypto_object_generate_key_pair, generate_key_pair); 5268 kcf_provider_desc_t *real_provider = NULL; 5269 kcf_req_params_t params; 5270 crypto_mechanism_t mech; 5271 crypto_object_attribute_t *k_pub_attrs = NULL; 5272 crypto_object_attribute_t *k_pri_attrs = NULL; 5273 crypto_session_id_t session_id; 5274 crypto_minor_t *cm; 5275 crypto_session_data_t *sp = NULL; 5276 crypto_object_id_t pub_handle; 5277 crypto_object_id_t pri_handle; 5278 caddr_t pri_attributes; 5279 caddr_t pub_attributes; 5280 size_t k_pub_attrs_size, k_pri_attrs_size; 5281 size_t mech_rctl_bytes = 0; 5282 size_t pub_rctl_bytes = 0; 5283 size_t pri_rctl_bytes = 0; 5284 size_t carry; 5285 uint_t pub_count; 5286 uint_t pri_count; 5287 int error = 0; 5288 int rv; 5289 boolean_t allocated_by_crypto_module = B_FALSE; 5290 5291 STRUCT_INIT(generate_key_pair, mode); 5292 5293 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 5294 cmn_err(CE_WARN, 5295 "object_generate_key_pair: failed holding minor"); 5296 return (ENXIO); 5297 } 5298 5299 if (copyin(arg, STRUCT_BUF(generate_key_pair), 5300 STRUCT_SIZE(generate_key_pair)) != 0) { 5301 crypto_release_minor(cm); 5302 return (EFAULT); 5303 } 5304 5305 session_id = STRUCT_FGET(generate_key_pair, kp_session); 5306 5307 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 5308 goto release_minor; 5309 } 5310 5311 bcopy(STRUCT_FADDR(generate_key_pair, kp_mechanism), &mech.cm_type, 5312 sizeof (crypto_mech_type_t)); 5313 5314 if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID, 5315 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider, 5316 CRYPTO_FG_GENERATE_KEY_PAIR)) != CRYPTO_SUCCESS) { 5317 goto release_minor; 5318 } 5319 5320 carry = 0; 5321 rv = crypto_provider_copyin_mech_param(real_provider, 5322 STRUCT_FADDR(generate_key_pair, kp_mechanism), &mech, mode, &error); 5323 5324 if (rv == CRYPTO_NOT_SUPPORTED) { 5325 allocated_by_crypto_module = B_TRUE; 5326 if (!copyin_mech(mode, STRUCT_FADDR(generate_key_pair, 5327 kp_mechanism), &mech, &mech_rctl_bytes, &carry, &rv, 5328 &error)) { 5329 goto release_minor; 5330 } 5331 } else { 5332 if (rv != CRYPTO_SUCCESS) 5333 goto release_minor; 5334 } 5335 5336 pub_count = STRUCT_FGET(generate_key_pair, kp_public_count); 5337 pri_count = STRUCT_FGET(generate_key_pair, kp_private_count); 5338 5339 pub_attributes = STRUCT_FGETP(generate_key_pair, kp_public_attributes); 5340 if (!copyin_attributes(mode, pub_count, pub_attributes, &k_pub_attrs, 5341 &k_pub_attrs_size, NULL, &rv, &error, &pub_rctl_bytes, carry, 5342 B_TRUE)) { 5343 goto release_minor; 5344 } 5345 5346 pri_attributes = STRUCT_FGETP(generate_key_pair, kp_private_attributes); 5347 if (!copyin_attributes(mode, pri_count, pri_attributes, &k_pri_attrs, 5348 &k_pri_attrs_size, NULL, &rv, &error, &pri_rctl_bytes, 0, 5349 B_TRUE)) { 5350 goto release_minor; 5351 } 5352 5353 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_GENERATE_PAIR, 5354 sp->sd_provider_session->ps_session, &mech, k_pub_attrs, 5355 pub_count, &pub_handle, k_pri_attrs, pri_count, &pri_handle, 5356 NULL, NULL, 0); 5357 5358 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5359 5360 if (rv == CRYPTO_SUCCESS) { 5361 STRUCT_FSET(generate_key_pair, kp_public_handle, pub_handle); 5362 STRUCT_FSET(generate_key_pair, kp_private_handle, pri_handle); 5363 } 5364 5365 release_minor: 5366 if (mech_rctl_bytes + pub_rctl_bytes + pri_rctl_bytes != 0) 5367 CRYPTO_DECREMENT_RCTL(mech_rctl_bytes + pub_rctl_bytes + 5368 pri_rctl_bytes); 5369 5370 if (k_pub_attrs != NULL) 5371 kmem_free(k_pub_attrs, k_pub_attrs_size); 5372 5373 if (k_pri_attrs != NULL) 5374 kmem_free(k_pri_attrs, k_pri_attrs_size); 5375 5376 if (error != 0) 5377 goto out; 5378 5379 STRUCT_FSET(generate_key_pair, kp_return_value, rv); 5380 if (copyout(STRUCT_BUF(generate_key_pair), arg, 5381 STRUCT_SIZE(generate_key_pair)) != 0) { 5382 if (rv == CRYPTO_SUCCESS) { 5383 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 5384 KCF_OP_OBJECT_DESTROY, 5385 sp->sd_provider_session->ps_session, pub_handle, 5386 NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 5387 5388 (void) kcf_submit_request(real_provider, NULL, 5389 NULL, ¶ms, B_FALSE); 5390 5391 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 5392 KCF_OP_OBJECT_DESTROY, 5393 sp->sd_provider_session->ps_session, pri_handle, 5394 NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 5395 5396 (void) kcf_submit_request(real_provider, NULL, 5397 NULL, ¶ms, B_FALSE); 5398 5399 error = EFAULT; 5400 } 5401 } 5402 out: 5403 if (sp != NULL) 5404 CRYPTO_SESSION_RELE(sp); 5405 crypto_release_minor(cm); 5406 5407 if (real_provider != NULL) { 5408 crypto_free_mech(real_provider, 5409 allocated_by_crypto_module, &mech); 5410 KCF_PROV_REFRELE(real_provider); 5411 } 5412 return (error); 5413 } 5414 5415 /* ARGSUSED */ 5416 static int 5417 nostore_generate_key_pair(dev_t dev, caddr_t arg, int mode, int *rval) 5418 { 5419 STRUCT_DECL(crypto_nostore_generate_key_pair, generate_key_pair); 5420 /* LINTED E_FUNC_SET_NOT_USED */ 5421 STRUCT_DECL(crypto_object_attribute, oa); 5422 kcf_provider_desc_t *real_provider = NULL; 5423 kcf_req_params_t params; 5424 crypto_mechanism_t mech; 5425 crypto_object_attribute_t *k_in_pub_attrs = NULL; 5426 crypto_object_attribute_t *k_in_pri_attrs = NULL; 5427 crypto_object_attribute_t *k_out_pub_attrs = NULL; 5428 crypto_object_attribute_t *k_out_pri_attrs = NULL; 5429 crypto_session_id_t session_id; 5430 crypto_minor_t *cm; 5431 crypto_session_data_t *sp = NULL; 5432 caddr_t in_pri_attributes; 5433 caddr_t in_pub_attributes; 5434 caddr_t out_pri_attributes; 5435 caddr_t out_pub_attributes; 5436 size_t k_in_pub_attrs_size, k_in_pri_attrs_size; 5437 size_t k_out_pub_attrs_size, k_out_pri_attrs_size; 5438 size_t mech_rctl_bytes = 0; 5439 size_t in_pub_rctl_bytes = 0; 5440 size_t in_pri_rctl_bytes = 0; 5441 size_t out_pub_rctl_bytes = 0; 5442 size_t out_pri_rctl_bytes = 0; 5443 size_t carry; 5444 uint_t in_pub_count; 5445 uint_t in_pri_count; 5446 uint_t out_pub_count; 5447 uint_t out_pri_count; 5448 int error = 0; 5449 int rv; 5450 boolean_t allocated_by_crypto_module = B_FALSE; 5451 caddr_t u_pub_attrs = NULL; 5452 caddr_t u_pri_attrs = NULL; 5453 5454 STRUCT_INIT(generate_key_pair, mode); 5455 STRUCT_INIT(oa, mode); 5456 5457 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 5458 cmn_err(CE_WARN, 5459 "nostore_generate_key_pair: failed holding minor"); 5460 return (ENXIO); 5461 } 5462 5463 if (copyin(arg, STRUCT_BUF(generate_key_pair), 5464 STRUCT_SIZE(generate_key_pair)) != 0) { 5465 crypto_release_minor(cm); 5466 return (EFAULT); 5467 } 5468 5469 session_id = STRUCT_FGET(generate_key_pair, nkp_session); 5470 5471 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 5472 goto release_minor; 5473 } 5474 5475 bcopy(STRUCT_FADDR(generate_key_pair, nkp_mechanism), &mech.cm_type, 5476 sizeof (crypto_mech_type_t)); 5477 5478 if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID, 5479 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider, 5480 CRYPTO_FG_GENERATE_KEY_PAIR)) != CRYPTO_SUCCESS) { 5481 goto release_minor; 5482 } 5483 5484 carry = 0; 5485 rv = crypto_provider_copyin_mech_param(real_provider, 5486 STRUCT_FADDR(generate_key_pair, nkp_mechanism), &mech, mode, 5487 &error); 5488 5489 if (rv == CRYPTO_NOT_SUPPORTED) { 5490 allocated_by_crypto_module = B_TRUE; 5491 if (!copyin_mech(mode, STRUCT_FADDR(generate_key_pair, 5492 nkp_mechanism), &mech, &mech_rctl_bytes, &carry, &rv, 5493 &error)) { 5494 goto release_minor; 5495 } 5496 } else { 5497 if (rv != CRYPTO_SUCCESS) 5498 goto release_minor; 5499 } 5500 5501 in_pub_count = STRUCT_FGET(generate_key_pair, nkp_in_public_count); 5502 in_pri_count = STRUCT_FGET(generate_key_pair, nkp_in_private_count); 5503 5504 in_pub_attributes = STRUCT_FGETP(generate_key_pair, 5505 nkp_in_public_attributes); 5506 if (!copyin_attributes(mode, in_pub_count, in_pub_attributes, 5507 &k_in_pub_attrs, &k_in_pub_attrs_size, NULL, &rv, &error, 5508 &in_pub_rctl_bytes, carry, B_TRUE)) { 5509 goto release_minor; 5510 } 5511 5512 in_pri_attributes = STRUCT_FGETP(generate_key_pair, 5513 nkp_in_private_attributes); 5514 if (!copyin_attributes(mode, in_pri_count, in_pri_attributes, 5515 &k_in_pri_attrs, &k_in_pri_attrs_size, NULL, &rv, &error, 5516 &in_pri_rctl_bytes, 0, B_TRUE)) { 5517 goto release_minor; 5518 } 5519 5520 out_pub_count = STRUCT_FGET(generate_key_pair, nkp_out_public_count); 5521 out_pri_count = STRUCT_FGET(generate_key_pair, nkp_out_private_count); 5522 5523 out_pub_attributes = STRUCT_FGETP(generate_key_pair, 5524 nkp_out_public_attributes); 5525 if (!copyin_attributes(mode, out_pub_count, out_pub_attributes, 5526 &k_out_pub_attrs, &k_out_pub_attrs_size, &u_pub_attrs, &rv, &error, 5527 &out_pub_rctl_bytes, 0, B_FALSE)) { 5528 goto release_minor; 5529 } 5530 5531 out_pri_attributes = STRUCT_FGETP(generate_key_pair, 5532 nkp_out_private_attributes); 5533 if (!copyin_attributes(mode, out_pri_count, out_pri_attributes, 5534 &k_out_pri_attrs, &k_out_pri_attrs_size, &u_pri_attrs, &rv, &error, 5535 &out_pri_rctl_bytes, 0, B_FALSE)) { 5536 goto release_minor; 5537 } 5538 5539 KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_GENERATE_PAIR, 5540 sp->sd_provider_session->ps_session, &mech, k_in_pub_attrs, 5541 in_pub_count, k_in_pri_attrs, in_pri_count, NULL, k_out_pub_attrs, 5542 out_pub_count, k_out_pri_attrs, out_pri_count); 5543 5544 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5545 5546 if (rv == CRYPTO_SUCCESS) { 5547 error = copyout_attributes(mode, out_pub_attributes, 5548 out_pub_count, k_out_pub_attrs, u_pub_attrs); 5549 if (error != CRYPTO_SUCCESS) 5550 goto release_minor; 5551 error = copyout_attributes(mode, out_pri_attributes, 5552 out_pri_count, k_out_pri_attrs, u_pri_attrs); 5553 } 5554 5555 release_minor: 5556 if (mech_rctl_bytes + in_pub_rctl_bytes + in_pri_rctl_bytes + 5557 out_pub_rctl_bytes + out_pri_rctl_bytes != 0) 5558 CRYPTO_DECREMENT_RCTL(mech_rctl_bytes + in_pub_rctl_bytes + 5559 in_pri_rctl_bytes + out_pub_rctl_bytes + 5560 out_pri_rctl_bytes); 5561 5562 if (k_in_pub_attrs != NULL) 5563 kmem_free(k_in_pub_attrs, k_in_pub_attrs_size); 5564 5565 if (k_in_pri_attrs != NULL) 5566 kmem_free(k_in_pri_attrs, k_in_pri_attrs_size); 5567 5568 if (k_out_pub_attrs != NULL) 5569 kmem_free(k_out_pub_attrs, k_out_pub_attrs_size); 5570 5571 if (k_out_pri_attrs != NULL) { 5572 bzero(k_out_pri_attrs, k_out_pri_attrs_size); 5573 kmem_free(k_out_pri_attrs, k_out_pri_attrs_size); 5574 } 5575 5576 if (u_pub_attrs != NULL) 5577 kmem_free(u_pub_attrs, out_pub_count * STRUCT_SIZE(oa)); 5578 5579 if (u_pri_attrs != NULL) 5580 kmem_free(u_pri_attrs, out_pri_count * STRUCT_SIZE(oa)); 5581 5582 if (error != 0) 5583 goto out; 5584 5585 STRUCT_FSET(generate_key_pair, nkp_return_value, rv); 5586 if (copyout(STRUCT_BUF(generate_key_pair), arg, 5587 STRUCT_SIZE(generate_key_pair)) != 0) { 5588 error = EFAULT; 5589 } 5590 out: 5591 if (sp != NULL) 5592 CRYPTO_SESSION_RELE(sp); 5593 crypto_release_minor(cm); 5594 5595 if (real_provider != NULL) { 5596 crypto_free_mech(real_provider, 5597 allocated_by_crypto_module, &mech); 5598 KCF_PROV_REFRELE(real_provider); 5599 } 5600 return (error); 5601 } 5602 5603 /* ARGSUSED */ 5604 static int 5605 object_wrap_key(dev_t dev, caddr_t arg, int mode, int *rval) 5606 { 5607 STRUCT_DECL(crypto_object_wrap_key, wrap_key); 5608 kcf_provider_desc_t *real_provider = NULL; 5609 kcf_req_params_t params; 5610 crypto_mechanism_t mech; 5611 crypto_key_t key; 5612 crypto_session_id_t session_id; 5613 crypto_minor_t *cm; 5614 crypto_session_data_t *sp; 5615 crypto_object_id_t handle; 5616 size_t mech_rctl_bytes = 0, key_rctl_bytes = 0; 5617 size_t wrapped_key_rctl_bytes = 0; 5618 size_t carry; 5619 size_t wrapped_key_len, new_wrapped_key_len; 5620 uchar_t *wrapped_key = NULL; 5621 char *wrapped_key_buffer; 5622 int error = 0; 5623 int rv; 5624 boolean_t allocated_by_crypto_module = B_FALSE; 5625 5626 STRUCT_INIT(wrap_key, mode); 5627 5628 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 5629 cmn_err(CE_WARN, "object_wrap_key: failed holding minor"); 5630 return (ENXIO); 5631 } 5632 5633 if (copyin(arg, STRUCT_BUF(wrap_key), STRUCT_SIZE(wrap_key)) != 0) { 5634 crypto_release_minor(cm); 5635 return (EFAULT); 5636 } 5637 5638 bzero(&key, sizeof (crypto_key_t)); 5639 5640 session_id = STRUCT_FGET(wrap_key, wk_session); 5641 5642 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 5643 goto release_minor; 5644 } 5645 5646 bcopy(STRUCT_FADDR(wrap_key, wk_mechanism), &mech.cm_type, 5647 sizeof (crypto_mech_type_t)); 5648 5649 if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID, 5650 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider, 5651 CRYPTO_FG_WRAP)) != CRYPTO_SUCCESS) { 5652 goto out; 5653 } 5654 5655 carry = 0; 5656 rv = crypto_provider_copyin_mech_param(real_provider, 5657 STRUCT_FADDR(wrap_key, wk_mechanism), &mech, mode, &error); 5658 5659 if (rv == CRYPTO_NOT_SUPPORTED) { 5660 allocated_by_crypto_module = B_TRUE; 5661 if (!copyin_mech(mode, STRUCT_FADDR(wrap_key, wk_mechanism), 5662 &mech, &mech_rctl_bytes, &carry, &rv, &error)) { 5663 goto out; 5664 } 5665 } else { 5666 if (rv != CRYPTO_SUCCESS) 5667 goto out; 5668 } 5669 5670 if (!copyin_key(mode, STRUCT_FADDR(wrap_key, wk_wrapping_key), &key, 5671 &key_rctl_bytes, &rv, &error, carry)) { 5672 goto out; 5673 } 5674 5675 wrapped_key_len = STRUCT_FGET(wrap_key, wk_wrapped_key_len); 5676 5677 /* 5678 * Don't allocate output buffer unless both buffer pointer and 5679 * buffer length are not NULL or 0 (length). 5680 */ 5681 wrapped_key_buffer = STRUCT_FGETP(wrap_key, wk_wrapped_key); 5682 if (wrapped_key_buffer == NULL || wrapped_key_len == 0) { 5683 wrapped_key_len = 0; 5684 } 5685 5686 if (wrapped_key_len > crypto_max_buffer_len) { 5687 cmn_err(CE_NOTE, "object_wrap_key: buffer greater than %ld " 5688 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 5689 rv = CRYPTO_ARGUMENTS_BAD; 5690 goto out; 5691 } 5692 5693 if ((rv = crypto_buffer_check(wrapped_key_len)) != CRYPTO_SUCCESS) { 5694 goto out; 5695 } 5696 5697 /* new_wrapped_key_len can be modified by the provider */ 5698 wrapped_key_rctl_bytes = new_wrapped_key_len = wrapped_key_len; 5699 wrapped_key = kmem_alloc(wrapped_key_len, KM_SLEEP); 5700 5701 handle = STRUCT_FGET(wrap_key, wk_object_handle); 5702 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_WRAP, 5703 sp->sd_provider_session->ps_session, &mech, NULL, 0, &handle, 5704 NULL, 0, NULL, &key, wrapped_key, &new_wrapped_key_len); 5705 5706 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5707 5708 if (rv == CRYPTO_SUCCESS) { 5709 if (wrapped_key_len != 0 && copyout(wrapped_key, 5710 wrapped_key_buffer, new_wrapped_key_len) != 0) { 5711 error = EFAULT; 5712 } 5713 STRUCT_FSET(wrap_key, wk_wrapped_key_len, new_wrapped_key_len); 5714 } 5715 5716 if (rv == CRYPTO_BUFFER_TOO_SMALL) { 5717 /* 5718 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1 5719 * of section 11.2 of the pkcs11 spec. We catch it here and 5720 * provide the correct pkcs11 return value. 5721 */ 5722 if (STRUCT_FGETP(wrap_key, wk_wrapped_key) == NULL) 5723 rv = CRYPTO_SUCCESS; 5724 STRUCT_FSET(wrap_key, wk_wrapped_key_len, new_wrapped_key_len); 5725 } 5726 out: 5727 CRYPTO_SESSION_RELE(sp); 5728 5729 release_minor: 5730 if (mech_rctl_bytes + key_rctl_bytes + wrapped_key_rctl_bytes != 0) 5731 CRYPTO_DECREMENT_RCTL(mech_rctl_bytes + key_rctl_bytes + 5732 wrapped_key_rctl_bytes); 5733 crypto_release_minor(cm); 5734 5735 if (real_provider != NULL) { 5736 crypto_free_mech(real_provider, 5737 allocated_by_crypto_module, &mech); 5738 KCF_PROV_REFRELE(real_provider); 5739 } 5740 5741 if (wrapped_key != NULL) 5742 kmem_free(wrapped_key, wrapped_key_len); 5743 5744 free_crypto_key(&key); 5745 5746 if (error != 0) 5747 return (error); 5748 5749 STRUCT_FSET(wrap_key, wk_return_value, rv); 5750 if (copyout(STRUCT_BUF(wrap_key), arg, STRUCT_SIZE(wrap_key)) != 0) { 5751 return (EFAULT); 5752 } 5753 return (0); 5754 } 5755 5756 /* ARGSUSED */ 5757 static int 5758 object_unwrap_key(dev_t dev, caddr_t arg, int mode, int *rval) 5759 { 5760 STRUCT_DECL(crypto_object_unwrap_key, unwrap_key); 5761 kcf_provider_desc_t *real_provider = NULL; 5762 kcf_req_params_t params; 5763 crypto_mechanism_t mech; 5764 crypto_key_t unwrapping_key; 5765 crypto_session_id_t session_id; 5766 crypto_minor_t *cm; 5767 crypto_session_data_t *sp = NULL; 5768 crypto_object_id_t handle; 5769 crypto_object_attribute_t *k_attrs = NULL; 5770 size_t k_attrs_size; 5771 size_t mech_rctl_bytes = 0, unwrapping_key_rctl_bytes = 0; 5772 size_t wrapped_key_rctl_bytes = 0, k_attrs_rctl_bytes = 0; 5773 size_t carry; 5774 size_t wrapped_key_len; 5775 uchar_t *wrapped_key = NULL; 5776 int error = 0; 5777 int rv; 5778 uint_t count; 5779 caddr_t uk_attributes; 5780 boolean_t allocated_by_crypto_module = B_FALSE; 5781 5782 STRUCT_INIT(unwrap_key, mode); 5783 5784 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 5785 cmn_err(CE_WARN, "object_unwrap_key: failed holding minor"); 5786 return (ENXIO); 5787 } 5788 5789 if (copyin(arg, STRUCT_BUF(unwrap_key), STRUCT_SIZE(unwrap_key)) != 0) { 5790 crypto_release_minor(cm); 5791 return (EFAULT); 5792 } 5793 5794 bzero(&unwrapping_key, sizeof (unwrapping_key)); 5795 5796 session_id = STRUCT_FGET(unwrap_key, uk_session); 5797 5798 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 5799 goto release_minor; 5800 } 5801 5802 bcopy(STRUCT_FADDR(unwrap_key, uk_mechanism), &mech.cm_type, 5803 sizeof (crypto_mech_type_t)); 5804 5805 if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID, 5806 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider, 5807 CRYPTO_FG_UNWRAP)) != CRYPTO_SUCCESS) { 5808 goto release_minor; 5809 } 5810 5811 carry = 0; 5812 rv = crypto_provider_copyin_mech_param(real_provider, 5813 STRUCT_FADDR(unwrap_key, uk_mechanism), &mech, mode, &error); 5814 5815 if (rv == CRYPTO_NOT_SUPPORTED) { 5816 allocated_by_crypto_module = B_TRUE; 5817 if (!copyin_mech(mode, STRUCT_FADDR(unwrap_key, uk_mechanism), 5818 &mech, &mech_rctl_bytes, &carry, &rv, &error)) { 5819 goto release_minor; 5820 } 5821 } else { 5822 if (rv != CRYPTO_SUCCESS) 5823 goto release_minor; 5824 } 5825 5826 if (!copyin_key(mode, STRUCT_FADDR(unwrap_key, uk_unwrapping_key), 5827 &unwrapping_key, &unwrapping_key_rctl_bytes, &rv, &error, carry)) { 5828 goto release_minor; 5829 } 5830 5831 count = STRUCT_FGET(unwrap_key, uk_count); 5832 uk_attributes = STRUCT_FGETP(unwrap_key, uk_attributes); 5833 if (!copyin_attributes(mode, count, uk_attributes, &k_attrs, 5834 &k_attrs_size, NULL, &rv, &error, &k_attrs_rctl_bytes, 0, B_TRUE)) { 5835 goto release_minor; 5836 } 5837 5838 wrapped_key_len = STRUCT_FGET(unwrap_key, uk_wrapped_key_len); 5839 if (wrapped_key_len > crypto_max_buffer_len) { 5840 cmn_err(CE_NOTE, "object_unwrap_key: buffer greater than %ld " 5841 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 5842 rv = CRYPTO_ARGUMENTS_BAD; 5843 goto release_minor; 5844 } 5845 5846 if ((rv = crypto_buffer_check(wrapped_key_len)) 5847 != CRYPTO_SUCCESS) { 5848 goto release_minor; 5849 } 5850 wrapped_key_rctl_bytes = wrapped_key_len; 5851 wrapped_key = kmem_alloc(wrapped_key_len, KM_SLEEP); 5852 5853 if (wrapped_key_len != 0 && copyin(STRUCT_FGETP(unwrap_key, 5854 uk_wrapped_key), wrapped_key, wrapped_key_len) != 0) { 5855 error = EFAULT; 5856 goto release_minor; 5857 } 5858 5859 /* wrapped_key_len is not modified by the unwrap operation */ 5860 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_UNWRAP, 5861 sp->sd_provider_session->ps_session, &mech, k_attrs, count, &handle, 5862 NULL, 0, NULL, &unwrapping_key, wrapped_key, &wrapped_key_len); 5863 5864 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5865 5866 if (rv == CRYPTO_SUCCESS) 5867 STRUCT_FSET(unwrap_key, uk_object_handle, handle); 5868 5869 release_minor: 5870 if (mech_rctl_bytes + unwrapping_key_rctl_bytes + 5871 wrapped_key_rctl_bytes + k_attrs_rctl_bytes != 0) 5872 CRYPTO_DECREMENT_RCTL(mech_rctl_bytes + 5873 unwrapping_key_rctl_bytes + 5874 wrapped_key_rctl_bytes + k_attrs_rctl_bytes); 5875 5876 if (k_attrs != NULL) 5877 kmem_free(k_attrs, k_attrs_size); 5878 5879 if (wrapped_key != NULL) 5880 kmem_free(wrapped_key, wrapped_key_len); 5881 5882 free_crypto_key(&unwrapping_key); 5883 5884 if (error != 0) 5885 goto out; 5886 5887 STRUCT_FSET(unwrap_key, uk_return_value, rv); 5888 if (copyout(STRUCT_BUF(unwrap_key), arg, 5889 STRUCT_SIZE(unwrap_key)) != 0) { 5890 if (rv == CRYPTO_SUCCESS) { 5891 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 5892 KCF_OP_OBJECT_DESTROY, 5893 sp->sd_provider_session->ps_session, handle, 5894 NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 5895 5896 (void) kcf_submit_request(real_provider, NULL, 5897 NULL, ¶ms, B_FALSE); 5898 5899 error = EFAULT; 5900 } 5901 } 5902 out: 5903 if (sp != NULL) 5904 CRYPTO_SESSION_RELE(sp); 5905 crypto_release_minor(cm); 5906 5907 if (real_provider != NULL) { 5908 crypto_free_mech(real_provider, 5909 allocated_by_crypto_module, &mech); 5910 KCF_PROV_REFRELE(real_provider); 5911 } 5912 5913 return (error); 5914 } 5915 5916 /* ARGSUSED */ 5917 static int 5918 object_derive_key(dev_t dev, caddr_t arg, int mode, int *rval) 5919 { 5920 STRUCT_DECL(crypto_derive_key, derive_key); 5921 kcf_provider_desc_t *real_provider = NULL; 5922 kcf_req_params_t params; 5923 crypto_object_attribute_t *k_attrs = NULL; 5924 crypto_mechanism_t mech; 5925 crypto_key_t base_key; 5926 crypto_session_id_t session_id; 5927 crypto_minor_t *cm; 5928 crypto_session_data_t *sp = NULL; 5929 crypto_object_id_t handle; 5930 size_t k_attrs_size; 5931 size_t key_rctl_bytes = 0, mech_rctl_bytes = 0; 5932 size_t attributes_rctl_bytes = 0; 5933 size_t carry; 5934 caddr_t attributes; 5935 uint_t count; 5936 int error = 0; 5937 int rv; 5938 boolean_t allocated_by_crypto_module = B_FALSE; 5939 boolean_t please_destroy_object = B_FALSE; 5940 5941 STRUCT_INIT(derive_key, mode); 5942 5943 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 5944 cmn_err(CE_WARN, "object_derive_key: failed holding minor"); 5945 return (ENXIO); 5946 } 5947 5948 if (copyin(arg, STRUCT_BUF(derive_key), STRUCT_SIZE(derive_key)) != 0) { 5949 crypto_release_minor(cm); 5950 return (EFAULT); 5951 } 5952 5953 bzero(&base_key, sizeof (base_key)); 5954 5955 session_id = STRUCT_FGET(derive_key, dk_session); 5956 5957 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 5958 goto release_minor; 5959 } 5960 5961 bcopy(STRUCT_FADDR(derive_key, dk_mechanism), &mech.cm_type, 5962 sizeof (crypto_mech_type_t)); 5963 5964 if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID, 5965 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider, 5966 CRYPTO_FG_DERIVE)) != CRYPTO_SUCCESS) { 5967 goto release_minor; 5968 } 5969 5970 carry = 0; 5971 rv = crypto_provider_copyin_mech_param(real_provider, 5972 STRUCT_FADDR(derive_key, dk_mechanism), &mech, mode, &error); 5973 5974 if (rv == CRYPTO_NOT_SUPPORTED) { 5975 allocated_by_crypto_module = B_TRUE; 5976 if (!copyin_mech(mode, STRUCT_FADDR(derive_key, dk_mechanism), 5977 &mech, &mech_rctl_bytes, &carry, &rv, &error)) { 5978 goto release_minor; 5979 } 5980 } else { 5981 if (rv != CRYPTO_SUCCESS) 5982 goto release_minor; 5983 } 5984 5985 if (!copyin_key(mode, STRUCT_FADDR(derive_key, dk_base_key), 5986 &base_key, &key_rctl_bytes, &rv, &error, carry)) { 5987 goto release_minor; 5988 } 5989 5990 count = STRUCT_FGET(derive_key, dk_count); 5991 5992 attributes = STRUCT_FGETP(derive_key, dk_attributes); 5993 if (!copyin_attributes(mode, count, attributes, &k_attrs, 5994 &k_attrs_size, NULL, &rv, &error, 5995 &attributes_rctl_bytes, 0, B_TRUE)) { 5996 goto release_minor; 5997 } 5998 5999 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_DERIVE, 6000 sp->sd_provider_session->ps_session, &mech, k_attrs, count, 6001 &handle, NULL, 0, NULL, &base_key, NULL, NULL); 6002 6003 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 6004 6005 if (rv == CRYPTO_SUCCESS) { 6006 STRUCT_FSET(derive_key, dk_object_handle, handle); 6007 6008 rv = crypto_provider_copyout_mech_param(real_provider, 6009 &mech, STRUCT_FADDR(derive_key, dk_mechanism), 6010 mode, &error); 6011 6012 if (rv == CRYPTO_NOT_SUPPORTED) { 6013 rv = CRYPTO_SUCCESS; 6014 goto release_minor; 6015 } 6016 6017 if (rv != CRYPTO_SUCCESS) 6018 please_destroy_object = B_TRUE; 6019 } 6020 6021 release_minor: 6022 if (mech_rctl_bytes + key_rctl_bytes + attributes_rctl_bytes != 0) 6023 CRYPTO_DECREMENT_RCTL(mech_rctl_bytes + key_rctl_bytes + 6024 attributes_rctl_bytes); 6025 6026 if (k_attrs != NULL) 6027 kmem_free(k_attrs, k_attrs_size); 6028 6029 free_crypto_key(&base_key); 6030 6031 if (error != 0) 6032 goto out; 6033 6034 STRUCT_FSET(derive_key, dk_return_value, rv); 6035 if (copyout(STRUCT_BUF(derive_key), arg, 6036 STRUCT_SIZE(derive_key)) != 0) { 6037 if (rv == CRYPTO_SUCCESS) { 6038 please_destroy_object = B_TRUE; 6039 error = EFAULT; 6040 } 6041 } 6042 out: 6043 if (please_destroy_object) { 6044 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_DESTROY, 6045 sp->sd_provider_session->ps_session, handle, 6046 NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 6047 6048 (void) kcf_submit_request(real_provider, NULL, 6049 NULL, ¶ms, B_FALSE); 6050 } 6051 6052 if (sp != NULL) 6053 CRYPTO_SESSION_RELE(sp); 6054 crypto_release_minor(cm); 6055 6056 if (real_provider != NULL) { 6057 crypto_free_mech(real_provider, 6058 allocated_by_crypto_module, &mech); 6059 KCF_PROV_REFRELE(real_provider); 6060 } 6061 return (error); 6062 } 6063 6064 /* ARGSUSED */ 6065 static int 6066 nostore_derive_key(dev_t dev, caddr_t arg, int mode, int *rval) 6067 { 6068 STRUCT_DECL(crypto_nostore_derive_key, derive_key); 6069 /* LINTED E_FUNC_SET_NOT_USED */ 6070 STRUCT_DECL(crypto_object_attribute, oa); 6071 kcf_provider_desc_t *real_provider = NULL; 6072 kcf_req_params_t params; 6073 crypto_object_attribute_t *k_in_attrs = NULL; 6074 crypto_object_attribute_t *k_out_attrs = NULL; 6075 crypto_mechanism_t mech; 6076 crypto_key_t base_key; 6077 crypto_session_id_t session_id; 6078 crypto_minor_t *cm; 6079 crypto_session_data_t *sp = NULL; 6080 size_t k_in_attrs_size, k_out_attrs_size; 6081 size_t key_rctl_bytes = 0, mech_rctl_bytes = 0; 6082 size_t in_attributes_rctl_bytes = 0; 6083 size_t out_attributes_rctl_bytes = 0; 6084 size_t carry; 6085 caddr_t in_attributes, out_attributes; 6086 uint_t in_count, out_count; 6087 int error = 0; 6088 int rv; 6089 boolean_t allocated_by_crypto_module = B_FALSE; 6090 caddr_t u_attrs = NULL; 6091 6092 STRUCT_INIT(derive_key, mode); 6093 STRUCT_INIT(oa, mode); 6094 6095 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 6096 cmn_err(CE_WARN, "nostore_derive_key: failed holding minor"); 6097 return (ENXIO); 6098 } 6099 6100 if (copyin(arg, STRUCT_BUF(derive_key), STRUCT_SIZE(derive_key)) != 0) { 6101 crypto_release_minor(cm); 6102 return (EFAULT); 6103 } 6104 6105 bzero(&base_key, sizeof (base_key)); 6106 6107 session_id = STRUCT_FGET(derive_key, ndk_session); 6108 6109 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 6110 goto release_minor; 6111 } 6112 6113 bcopy(STRUCT_FADDR(derive_key, ndk_mechanism), &mech.cm_type, 6114 sizeof (crypto_mech_type_t)); 6115 6116 if ((rv = kcf_get_hardware_provider(mech.cm_type, CRYPTO_MECH_INVALID, 6117 CHECK_RESTRICT_FALSE, sp->sd_provider, &real_provider, 6118 CRYPTO_FG_DERIVE)) != CRYPTO_SUCCESS) { 6119 goto release_minor; 6120 } 6121 6122 carry = 0; 6123 rv = crypto_provider_copyin_mech_param(real_provider, 6124 STRUCT_FADDR(derive_key, ndk_mechanism), &mech, mode, &error); 6125 6126 if (rv == CRYPTO_NOT_SUPPORTED) { 6127 allocated_by_crypto_module = B_TRUE; 6128 if (!copyin_mech(mode, STRUCT_FADDR(derive_key, ndk_mechanism), 6129 &mech, &mech_rctl_bytes, &carry, &rv, &error)) { 6130 goto release_minor; 6131 } 6132 } else { 6133 if (rv != CRYPTO_SUCCESS) 6134 goto release_minor; 6135 } 6136 6137 if (!copyin_key(mode, STRUCT_FADDR(derive_key, ndk_base_key), 6138 &base_key, &key_rctl_bytes, &rv, &error, carry)) { 6139 goto release_minor; 6140 } 6141 6142 in_count = STRUCT_FGET(derive_key, ndk_in_count); 6143 out_count = STRUCT_FGET(derive_key, ndk_out_count); 6144 6145 in_attributes = STRUCT_FGETP(derive_key, ndk_in_attributes); 6146 if (!copyin_attributes(mode, in_count, in_attributes, &k_in_attrs, 6147 &k_in_attrs_size, NULL, &rv, &error, &in_attributes_rctl_bytes, 6148 0, B_TRUE)) { 6149 goto release_minor; 6150 } 6151 6152 out_attributes = STRUCT_FGETP(derive_key, ndk_out_attributes); 6153 if (!copyin_attributes(mode, out_count, out_attributes, &k_out_attrs, 6154 &k_out_attrs_size, &u_attrs, &rv, &error, 6155 &out_attributes_rctl_bytes, 0, B_FALSE)) { 6156 goto release_minor; 6157 } 6158 6159 KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_DERIVE, 6160 sp->sd_provider_session->ps_session, &mech, k_in_attrs, in_count, 6161 NULL, 0, &base_key, k_out_attrs, out_count, NULL, 0); 6162 6163 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 6164 6165 if (rv == CRYPTO_SUCCESS) { 6166 rv = crypto_provider_copyout_mech_param(real_provider, 6167 &mech, STRUCT_FADDR(derive_key, ndk_mechanism), 6168 mode, &error); 6169 6170 if (rv == CRYPTO_NOT_SUPPORTED) { 6171 rv = CRYPTO_SUCCESS; 6172 } 6173 /* copyout the derived secret */ 6174 if (copyout_attributes(mode, out_attributes, out_count, 6175 k_out_attrs, u_attrs) != 0) 6176 error = EFAULT; 6177 } 6178 6179 release_minor: 6180 if (mech_rctl_bytes + key_rctl_bytes + in_attributes_rctl_bytes + 6181 out_attributes_rctl_bytes != 0) 6182 CRYPTO_DECREMENT_RCTL(mech_rctl_bytes + key_rctl_bytes + 6183 in_attributes_rctl_bytes + out_attributes_rctl_bytes); 6184 6185 if (k_in_attrs != NULL) 6186 kmem_free(k_in_attrs, k_in_attrs_size); 6187 if (k_out_attrs != NULL) { 6188 bzero(k_out_attrs, k_out_attrs_size); 6189 kmem_free(k_out_attrs, k_out_attrs_size); 6190 } 6191 6192 if (u_attrs != NULL) 6193 kmem_free(u_attrs, out_count * STRUCT_SIZE(oa)); 6194 6195 free_crypto_key(&base_key); 6196 6197 if (error != 0) 6198 goto out; 6199 6200 STRUCT_FSET(derive_key, ndk_return_value, rv); 6201 if (copyout(STRUCT_BUF(derive_key), arg, 6202 STRUCT_SIZE(derive_key)) != 0) { 6203 error = EFAULT; 6204 } 6205 out: 6206 if (sp != NULL) 6207 CRYPTO_SESSION_RELE(sp); 6208 crypto_release_minor(cm); 6209 6210 if (real_provider != NULL) { 6211 crypto_free_mech(real_provider, 6212 allocated_by_crypto_module, &mech); 6213 KCF_PROV_REFRELE(real_provider); 6214 } 6215 return (error); 6216 } 6217 6218 /* ARGSUSED */ 6219 static int 6220 crypto_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c, 6221 int *rval) 6222 { 6223 #define ARG ((caddr_t)arg) 6224 6225 switch (cmd) { 6226 case CRYPTO_GET_FUNCTION_LIST: 6227 return (get_function_list(dev, ARG, mode, rval)); 6228 6229 case CRYPTO_GET_MECHANISM_NUMBER: 6230 return (get_mechanism_number(dev, ARG, mode, rval)); 6231 6232 case CRYPTO_GET_PROVIDER_LIST: 6233 return (get_provider_list(dev, ARG, mode, rval)); 6234 6235 case CRYPTO_GET_PROVIDER_INFO: 6236 return (get_provider_info(dev, ARG, mode, rval)); 6237 6238 case CRYPTO_GET_PROVIDER_MECHANISMS: 6239 return (get_provider_mechanisms(dev, ARG, mode, rval)); 6240 6241 case CRYPTO_GET_PROVIDER_MECHANISM_INFO: 6242 return (get_provider_mechanism_info(dev, ARG, mode, rval)); 6243 6244 case CRYPTO_OPEN_SESSION: 6245 return (open_session(dev, ARG, mode, rval)); 6246 6247 case CRYPTO_CLOSE_SESSION: 6248 return (close_session(dev, ARG, mode, rval)); 6249 6250 case CRYPTO_ENCRYPT_INIT: 6251 return (encrypt_init(dev, ARG, mode, rval)); 6252 6253 case CRYPTO_DECRYPT_INIT: 6254 return (decrypt_init(dev, ARG, mode, rval)); 6255 6256 case CRYPTO_ENCRYPT: 6257 return (encrypt(dev, ARG, mode, rval)); 6258 6259 case CRYPTO_DECRYPT: 6260 return (decrypt(dev, ARG, mode, rval)); 6261 6262 case CRYPTO_ENCRYPT_UPDATE: 6263 return (encrypt_update(dev, ARG, mode, rval)); 6264 6265 case CRYPTO_DECRYPT_UPDATE: 6266 return (decrypt_update(dev, ARG, mode, rval)); 6267 6268 case CRYPTO_ENCRYPT_FINAL: 6269 return (encrypt_final(dev, ARG, mode, rval)); 6270 6271 case CRYPTO_DECRYPT_FINAL: 6272 return (decrypt_final(dev, ARG, mode, rval)); 6273 6274 case CRYPTO_DIGEST_INIT: 6275 return (digest_init(dev, ARG, mode, rval)); 6276 6277 case CRYPTO_DIGEST: 6278 return (digest(dev, ARG, mode, rval)); 6279 6280 case CRYPTO_DIGEST_UPDATE: 6281 return (digest_update(dev, ARG, mode, rval)); 6282 6283 case CRYPTO_DIGEST_KEY: 6284 return (digest_key(dev, ARG, mode, rval)); 6285 6286 case CRYPTO_DIGEST_FINAL: 6287 return (digest_final(dev, ARG, mode, rval)); 6288 6289 case CRYPTO_SIGN_INIT: 6290 return (sign_init(dev, ARG, mode, rval)); 6291 6292 case CRYPTO_SIGN: 6293 return (sign(dev, ARG, mode, rval)); 6294 6295 case CRYPTO_SIGN_UPDATE: 6296 return (sign_update(dev, ARG, mode, rval)); 6297 6298 case CRYPTO_SIGN_FINAL: 6299 return (sign_final(dev, ARG, mode, rval)); 6300 6301 case CRYPTO_SIGN_RECOVER_INIT: 6302 return (sign_recover_init(dev, ARG, mode, rval)); 6303 6304 case CRYPTO_SIGN_RECOVER: 6305 return (sign_recover(dev, ARG, mode, rval)); 6306 6307 case CRYPTO_VERIFY_INIT: 6308 return (verify_init(dev, ARG, mode, rval)); 6309 6310 case CRYPTO_VERIFY: 6311 return (verify(dev, ARG, mode, rval)); 6312 6313 case CRYPTO_VERIFY_UPDATE: 6314 return (verify_update(dev, ARG, mode, rval)); 6315 6316 case CRYPTO_VERIFY_FINAL: 6317 return (verify_final(dev, ARG, mode, rval)); 6318 6319 case CRYPTO_VERIFY_RECOVER_INIT: 6320 return (verify_recover_init(dev, ARG, mode, rval)); 6321 6322 case CRYPTO_VERIFY_RECOVER: 6323 return (verify_recover(dev, ARG, mode, rval)); 6324 6325 case CRYPTO_SET_PIN: 6326 return (set_pin(dev, ARG, mode, rval)); 6327 6328 case CRYPTO_LOGIN: 6329 return (login(dev, ARG, mode, rval)); 6330 6331 case CRYPTO_LOGOUT: 6332 return (logout(dev, ARG, mode, rval)); 6333 6334 case CRYPTO_SEED_RANDOM: 6335 return (seed_random(dev, ARG, mode, rval)); 6336 6337 case CRYPTO_GENERATE_RANDOM: 6338 return (generate_random(dev, ARG, mode, rval)); 6339 6340 case CRYPTO_OBJECT_CREATE: 6341 return (object_create(dev, ARG, mode, rval)); 6342 6343 case CRYPTO_OBJECT_COPY: 6344 return (object_copy(dev, ARG, mode, rval)); 6345 6346 case CRYPTO_OBJECT_DESTROY: 6347 return (object_destroy(dev, ARG, mode, rval)); 6348 6349 case CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE: 6350 return (object_get_attribute_value(dev, ARG, mode, rval)); 6351 6352 case CRYPTO_OBJECT_GET_SIZE: 6353 return (object_get_size(dev, ARG, mode, rval)); 6354 6355 case CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE: 6356 return (object_set_attribute_value(dev, ARG, mode, rval)); 6357 6358 case CRYPTO_OBJECT_FIND_INIT: 6359 return (object_find_init(dev, ARG, mode, rval)); 6360 6361 case CRYPTO_OBJECT_FIND_UPDATE: 6362 return (object_find_update(dev, ARG, mode, rval)); 6363 6364 case CRYPTO_OBJECT_FIND_FINAL: 6365 return (object_find_final(dev, ARG, mode, rval)); 6366 6367 case CRYPTO_GENERATE_KEY: 6368 return (object_generate_key(dev, ARG, mode, rval)); 6369 6370 case CRYPTO_GENERATE_KEY_PAIR: 6371 return (object_generate_key_pair(dev, ARG, mode, rval)); 6372 6373 case CRYPTO_WRAP_KEY: 6374 return (object_wrap_key(dev, ARG, mode, rval)); 6375 6376 case CRYPTO_UNWRAP_KEY: 6377 return (object_unwrap_key(dev, ARG, mode, rval)); 6378 6379 case CRYPTO_DERIVE_KEY: 6380 return (object_derive_key(dev, ARG, mode, rval)); 6381 6382 case CRYPTO_NOSTORE_GENERATE_KEY: 6383 return (nostore_generate_key(dev, ARG, mode, rval)); 6384 6385 case CRYPTO_NOSTORE_GENERATE_KEY_PAIR: 6386 return (nostore_generate_key_pair(dev, ARG, mode, rval)); 6387 6388 case CRYPTO_NOSTORE_DERIVE_KEY: 6389 return (nostore_derive_key(dev, ARG, mode, rval)); 6390 } 6391 return (EINVAL); 6392 } 6393 6394 /* 6395 * Check for the project.max-crypto-memory resource control. 6396 */ 6397 static int 6398 crypto_buffer_check(size_t need) 6399 { 6400 kproject_t *kpj; 6401 6402 if (need == 0) 6403 return (CRYPTO_SUCCESS); 6404 6405 mutex_enter(&curproc->p_lock); 6406 kpj = curproc->p_task->tk_proj; 6407 mutex_enter(&(kpj->kpj_data.kpd_crypto_lock)); 6408 6409 if (kpj->kpj_data.kpd_crypto_mem + need > 6410 kpj->kpj_data.kpd_crypto_mem_ctl) { 6411 if (rctl_test(rc_project_crypto_mem, 6412 kpj->kpj_rctls, curproc, need, 0) & RCT_DENY) { 6413 mutex_exit(&(kpj->kpj_data.kpd_crypto_lock)); 6414 mutex_exit(&curproc->p_lock); 6415 return (CRYPTO_HOST_MEMORY); 6416 } 6417 } 6418 6419 kpj->kpj_data.kpd_crypto_mem += need; 6420 mutex_exit(&(kpj->kpj_data.kpd_crypto_lock)); 6421 6422 curproc->p_crypto_mem += need; 6423 mutex_exit(&curproc->p_lock); 6424 6425 return (CRYPTO_SUCCESS); 6426 } 6427