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