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