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 if (value != NULL) { 2038 k_attrs[i].oa_value = p; 2039 p += roundup(value_len, sizeof (caddr_t)); 2040 } else { 2041 k_attrs[i].oa_value = NULL; 2042 } 2043 k_attrs[i].oa_value_len = value_len; 2044 ap += STRUCT_SIZE(oa); 2045 } 2046 out: 2047 if (attrs != NULL) { 2048 /* 2049 * Free the array if there is a failure or the caller 2050 * doesn't want the array to be returned. 2051 */ 2052 if (error != 0 || rv != CRYPTO_SUCCESS || u_attrs_out == NULL) { 2053 kmem_free(attrs, len); 2054 attrs = NULL; 2055 } 2056 } 2057 2058 if (u_attrs_out != NULL) 2059 *u_attrs_out = attrs; 2060 if (k_attrs_size_out != NULL) 2061 *k_attrs_size_out = k_attrs_total_len; 2062 *k_attrs_out = k_attrs; 2063 *out_rctl_bytes = rctl_bytes; 2064 *out_rv = rv; 2065 *out_error = error; 2066 return ((rv | error) ? B_FALSE : B_TRUE); 2067 } 2068 2069 /* 2070 * Copy data model dependent raw key into a kernel key 2071 * structure. Checks key length or attribute lengths against 2072 * resource controls before allocating memory. Returns B_TRUE 2073 * if both error and rv are set to 0. 2074 */ 2075 static boolean_t 2076 copyin_key(int mode, crypto_key_t *in_key, crypto_key_t *out_key, 2077 size_t *out_rctl_bytes, int *out_rv, int *out_error, size_t carry, 2078 kproject_t **projp) 2079 { 2080 STRUCT_DECL(crypto_key, key); 2081 crypto_object_attribute_t *k_attrs = NULL; 2082 size_t key_bits; 2083 size_t key_bytes = 0; 2084 size_t rctl_bytes = 0; 2085 int count; 2086 int error = 0; 2087 int rv = CRYPTO_SUCCESS; 2088 2089 STRUCT_INIT(key, mode); 2090 bcopy(in_key, STRUCT_BUF(key), STRUCT_SIZE(key)); 2091 out_key->ck_format = STRUCT_FGET(key, ck_format); 2092 switch (out_key->ck_format) { 2093 case CRYPTO_KEY_RAW: 2094 key_bits = STRUCT_FGET(key, ck_length); 2095 if (key_bits != 0) { 2096 key_bytes = CRYPTO_BITS2BYTES(key_bits); 2097 if (key_bytes > crypto_max_buffer_len) { 2098 cmn_err(CE_NOTE, "copyin_key: buffer greater " 2099 "than %ld bytes, pid = %d", 2100 crypto_max_buffer_len, curproc->p_pid); 2101 rv = CRYPTO_ARGUMENTS_BAD; 2102 goto out; 2103 } 2104 2105 rv = crypto_buffer_check(key_bytes + carry, projp); 2106 if (rv != CRYPTO_SUCCESS) { 2107 goto out; 2108 } 2109 rctl_bytes = key_bytes + carry; 2110 2111 out_key->ck_data = kmem_alloc(key_bytes, KM_SLEEP); 2112 2113 if (copyin((char *)STRUCT_FGETP(key, ck_data), 2114 out_key->ck_data, key_bytes) != 0) { 2115 kmem_free(out_key->ck_data, key_bytes); 2116 out_key->ck_data = NULL; 2117 out_key->ck_length = 0; 2118 error = EFAULT; 2119 goto out; 2120 } 2121 } 2122 out_key->ck_length = key_bits; 2123 break; 2124 2125 case CRYPTO_KEY_ATTR_LIST: 2126 count = STRUCT_FGET(key, ck_count); 2127 2128 if (copyin_attributes(mode, count, 2129 (caddr_t)STRUCT_FGETP(key, ck_attrs), &k_attrs, NULL, NULL, 2130 &rv, &error, &rctl_bytes, carry, B_TRUE, projp)) { 2131 out_key->ck_count = count; 2132 out_key->ck_attrs = k_attrs; 2133 k_attrs = NULL; 2134 } else { 2135 out_key->ck_count = 0; 2136 out_key->ck_attrs = NULL; 2137 } 2138 break; 2139 2140 case CRYPTO_KEY_REFERENCE: 2141 out_key->ck_obj_id = STRUCT_FGET(key, ck_obj_id); 2142 break; 2143 2144 default: 2145 rv = CRYPTO_ARGUMENTS_BAD; 2146 } 2147 2148 out: 2149 *out_rctl_bytes = rctl_bytes; 2150 *out_rv = rv; 2151 *out_error = error; 2152 return ((rv | error) ? B_FALSE : B_TRUE); 2153 } 2154 2155 /* 2156 * This routine does two things: 2157 * 1. Given a crypto_minor structure and a session ID, it returns 2158 * a valid session pointer. 2159 * 2. It checks that the provider, to which the session has been opened, 2160 * has not been removed. 2161 */ 2162 static boolean_t 2163 get_session_ptr(crypto_session_id_t i, crypto_minor_t *cm, 2164 crypto_session_data_t **session_ptr, int *out_error, int *out_rv) 2165 { 2166 crypto_session_data_t *sp = NULL; 2167 int rv = CRYPTO_SESSION_HANDLE_INVALID; 2168 int error = 0; 2169 2170 mutex_enter(&cm->cm_lock); 2171 if ((i < cm->cm_session_table_count) && 2172 (cm->cm_session_table[i] != NULL)) { 2173 sp = cm->cm_session_table[i]; 2174 mutex_enter(&sp->sd_lock); 2175 mutex_exit(&cm->cm_lock); 2176 while (sp->sd_flags & CRYPTO_SESSION_IS_BUSY) { 2177 if (cv_wait_sig(&sp->sd_cv, &sp->sd_lock) == 0) { 2178 mutex_exit(&sp->sd_lock); 2179 sp = NULL; 2180 error = EINTR; 2181 goto out; 2182 } 2183 } 2184 2185 if (sp->sd_flags & CRYPTO_SESSION_IS_CLOSED) { 2186 mutex_exit(&sp->sd_lock); 2187 sp = NULL; 2188 goto out; 2189 } 2190 2191 if (KCF_IS_PROV_REMOVED(sp->sd_provider)) { 2192 mutex_exit(&sp->sd_lock); 2193 sp = NULL; 2194 rv = CRYPTO_DEVICE_ERROR; 2195 goto out; 2196 } 2197 2198 rv = CRYPTO_SUCCESS; 2199 sp->sd_flags |= CRYPTO_SESSION_IS_BUSY; 2200 mutex_exit(&sp->sd_lock); 2201 } else { 2202 mutex_exit(&cm->cm_lock); 2203 } 2204 out: 2205 *session_ptr = sp; 2206 *out_error = error; 2207 *out_rv = rv; 2208 return ((rv == CRYPTO_SUCCESS && error == 0) ? B_TRUE : B_FALSE); 2209 } 2210 2211 #define CRYPTO_SESSION_RELE(s) { \ 2212 mutex_enter(&((s)->sd_lock)); \ 2213 (s)->sd_flags &= ~CRYPTO_SESSION_IS_BUSY; \ 2214 cv_broadcast(&(s)->sd_cv); \ 2215 mutex_exit(&((s)->sd_lock)); \ 2216 } 2217 2218 /* ARGSUSED */ 2219 static int 2220 encrypt_init(dev_t dev, caddr_t arg, int mode, int *rval) 2221 { 2222 return (cipher_init(dev, arg, mode, crypto_encrypt_init_prov)); 2223 } 2224 2225 /* ARGSUSED */ 2226 static int 2227 decrypt_init(dev_t dev, caddr_t arg, int mode, int *rval) 2228 { 2229 return (cipher_init(dev, arg, mode, crypto_decrypt_init_prov)); 2230 } 2231 2232 /* 2233 * ASSUMPTION: crypto_encrypt_init and crypto_decrypt_init 2234 * structures are identical except for field names. 2235 */ 2236 static int 2237 cipher_init(dev_t dev, caddr_t arg, int mode, int (*init)(kcf_provider_desc_t *, 2238 crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, 2239 crypto_ctx_template_t, crypto_context_t *, crypto_call_req_t *)) 2240 { 2241 STRUCT_DECL(crypto_encrypt_init, encrypt_init); 2242 kproject_t *mech_projp, *key_projp; 2243 kcf_provider_desc_t *real_provider; 2244 crypto_session_id_t session_id; 2245 crypto_mechanism_t mech; 2246 crypto_key_t key; 2247 crypto_minor_t *cm; 2248 crypto_session_data_t *sp; 2249 crypto_context_t cc; 2250 crypto_ctx_t **ctxpp; 2251 size_t mech_rctl_bytes = 0; 2252 size_t key_rctl_bytes = 0; 2253 size_t carry; 2254 offset_t offset; 2255 int error = 0; 2256 int rv; 2257 2258 STRUCT_INIT(encrypt_init, mode); 2259 2260 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 2261 cmn_err(CE_WARN, "cipher_init: failed holding minor"); 2262 return (ENXIO); 2263 } 2264 2265 if (copyin(arg, STRUCT_BUF(encrypt_init), 2266 STRUCT_SIZE(encrypt_init)) != 0) { 2267 crypto_release_minor(cm); 2268 return (EFAULT); 2269 } 2270 2271 mech.cm_param = NULL; 2272 bzero(&key, sizeof (crypto_key_t)); 2273 2274 session_id = STRUCT_FGET(encrypt_init, ei_session); 2275 2276 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 2277 goto release_minor; 2278 } 2279 2280 if (!copyin_mech(mode, STRUCT_FADDR(encrypt_init, ei_mech), &mech, 2281 &mech_rctl_bytes, &carry, &rv, &error, &mech_projp)) { 2282 goto out; 2283 } 2284 2285 if (init == crypto_encrypt_init_prov) 2286 offset = CRYPTO_CIPHER_OFFSET(encrypt_init); 2287 else 2288 offset = CRYPTO_CIPHER_OFFSET(decrypt_init); 2289 2290 if ((rv = kcf_get_hardware_provider(mech.cm_type, 2291 CRYPTO_OPS_OFFSET(cipher_ops), offset, 2292 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 2293 goto out; 2294 } 2295 2296 if (!copyin_key(mode, STRUCT_FADDR(encrypt_init, ei_key), &key, 2297 &key_rctl_bytes, &rv, &error, carry, &key_projp)) { 2298 goto out; 2299 } 2300 2301 rv = (init)(real_provider, sp->sd_provider_session->ps_session, 2302 &mech, &key, NULL, &cc, NULL); 2303 2304 /* 2305 * Check if a context already exists. If so, it means it is being 2306 * abandoned. So, cancel it to avoid leaking it. 2307 */ 2308 ctxpp = (init == crypto_encrypt_init_prov) ? 2309 &sp->sd_encr_ctx : &sp->sd_decr_ctx; 2310 2311 if (*ctxpp != NULL) 2312 CRYPTO_CANCEL_CTX(ctxpp); 2313 *ctxpp = (rv == CRYPTO_SUCCESS) ? cc : NULL; 2314 out: 2315 CRYPTO_SESSION_RELE(sp); 2316 2317 release_minor: 2318 mutex_enter(&crypto_rctl_lock); 2319 if (mech_rctl_bytes != 0) 2320 CRYPTO_DECREMENT_RCTL(mech_rctl_bytes, mech_projp); 2321 if (key_rctl_bytes != 0) 2322 CRYPTO_DECREMENT_RCTL(key_rctl_bytes, key_projp); 2323 mutex_exit(&crypto_rctl_lock); 2324 crypto_release_minor(cm); 2325 2326 if (mech.cm_param != NULL) 2327 kmem_free(mech.cm_param, mech.cm_param_len); 2328 2329 free_crypto_key(&key); 2330 2331 if (error != 0) 2332 return (error); 2333 2334 STRUCT_FSET(encrypt_init, ei_return_value, rv); 2335 if (copyout(STRUCT_BUF(encrypt_init), arg, 2336 STRUCT_SIZE(encrypt_init)) != 0) { 2337 return (EFAULT); 2338 } 2339 return (0); 2340 } 2341 2342 /* ARGSUSED */ 2343 static int 2344 encrypt(dev_t dev, caddr_t arg, int mode, int *rval) 2345 { 2346 return (cipher(dev, arg, mode, crypto_encrypt_single)); 2347 } 2348 2349 /* ARGSUSED */ 2350 static int 2351 decrypt(dev_t dev, caddr_t arg, int mode, int *rval) 2352 { 2353 return (cipher(dev, arg, mode, crypto_decrypt_single)); 2354 } 2355 2356 /* 2357 * ASSUMPTION: crypto_encrypt and crypto_decrypt structures 2358 * are identical except for field names. 2359 */ 2360 static int 2361 cipher(dev_t dev, caddr_t arg, int mode, 2362 int (*single)(crypto_context_t, crypto_data_t *, crypto_data_t *, 2363 crypto_call_req_t *)) 2364 { 2365 STRUCT_DECL(crypto_encrypt, encrypt); 2366 kproject_t *projp; 2367 crypto_session_id_t session_id; 2368 crypto_minor_t *cm; 2369 crypto_session_data_t *sp; 2370 crypto_ctx_t **ctxpp; 2371 crypto_data_t data, encr; 2372 size_t datalen, encrlen, need = 0; 2373 char *encrbuf; 2374 int error = 0; 2375 int rv; 2376 2377 STRUCT_INIT(encrypt, mode); 2378 2379 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 2380 cmn_err(CE_WARN, "cipher: failed holding minor"); 2381 return (ENXIO); 2382 } 2383 2384 if (copyin(arg, STRUCT_BUF(encrypt), STRUCT_SIZE(encrypt)) != 0) { 2385 crypto_release_minor(cm); 2386 return (EFAULT); 2387 } 2388 2389 data.cd_raw.iov_base = NULL; 2390 encr.cd_raw.iov_base = NULL; 2391 2392 datalen = STRUCT_FGET(encrypt, ce_datalen); 2393 encrlen = STRUCT_FGET(encrypt, ce_encrlen); 2394 2395 /* 2396 * Don't allocate output buffer unless both buffer pointer and 2397 * buffer length are not NULL or 0 (length). 2398 */ 2399 encrbuf = STRUCT_FGETP(encrypt, ce_encrbuf); 2400 if (encrbuf == NULL || encrlen == 0) { 2401 encrlen = 0; 2402 } 2403 2404 if (datalen > crypto_max_buffer_len || 2405 encrlen > crypto_max_buffer_len) { 2406 cmn_err(CE_NOTE, "cipher: buffer greater than %ld bytes, " 2407 "pid = %d", crypto_max_buffer_len, curproc->p_pid); 2408 rv = CRYPTO_ARGUMENTS_BAD; 2409 goto release_minor; 2410 } 2411 2412 need = datalen + encrlen; 2413 if ((rv = crypto_buffer_check(need, &projp)) != CRYPTO_SUCCESS) { 2414 need = 0; 2415 goto release_minor; 2416 } 2417 2418 INIT_RAW_CRYPTO_DATA(data, datalen); 2419 data.cd_miscdata = NULL; 2420 2421 if (datalen != 0 && copyin(STRUCT_FGETP(encrypt, ce_databuf), 2422 data.cd_raw.iov_base, datalen) != 0) { 2423 error = EFAULT; 2424 goto release_minor; 2425 } 2426 2427 INIT_RAW_CRYPTO_DATA(encr, encrlen); 2428 2429 session_id = STRUCT_FGET(encrypt, ce_session); 2430 2431 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 2432 goto release_minor; 2433 } 2434 2435 ctxpp = (single == crypto_encrypt_single) ? 2436 &sp->sd_encr_ctx : &sp->sd_decr_ctx; 2437 2438 rv = (single)(*ctxpp, &data, &encr, NULL); 2439 if (KCF_CONTEXT_DONE(rv)) 2440 *ctxpp = NULL; 2441 2442 CRYPTO_SESSION_RELE(sp); 2443 2444 if (rv == CRYPTO_SUCCESS) { 2445 ASSERT(encr.cd_length <= encrlen); 2446 if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base, 2447 encrbuf, encr.cd_length) != 0) { 2448 error = EFAULT; 2449 goto release_minor; 2450 } 2451 STRUCT_FSET(encrypt, ce_encrlen, encr.cd_length); 2452 } 2453 2454 if (rv == CRYPTO_BUFFER_TOO_SMALL) { 2455 /* 2456 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1 2457 * of section 11.2 of the pkcs11 spec. We catch it here and 2458 * provide the correct pkcs11 return value. 2459 */ 2460 if (STRUCT_FGETP(encrypt, ce_encrbuf) == NULL) 2461 rv = CRYPTO_SUCCESS; 2462 STRUCT_FSET(encrypt, ce_encrlen, encr.cd_length); 2463 } 2464 2465 release_minor: 2466 if (need != 0) { 2467 mutex_enter(&crypto_rctl_lock); 2468 CRYPTO_DECREMENT_RCTL(need, projp); 2469 mutex_exit(&crypto_rctl_lock); 2470 } 2471 crypto_release_minor(cm); 2472 2473 if (data.cd_raw.iov_base != NULL) 2474 kmem_free(data.cd_raw.iov_base, datalen); 2475 2476 if (encr.cd_raw.iov_base != NULL) 2477 kmem_free(encr.cd_raw.iov_base, encrlen); 2478 2479 if (error != 0) 2480 return (error); 2481 2482 STRUCT_FSET(encrypt, ce_return_value, rv); 2483 if (copyout(STRUCT_BUF(encrypt), arg, STRUCT_SIZE(encrypt)) != 0) { 2484 return (EFAULT); 2485 } 2486 return (0); 2487 } 2488 2489 /* ARGSUSED */ 2490 static int 2491 encrypt_update(dev_t dev, caddr_t arg, int mode, int *rval) 2492 { 2493 return (cipher_update(dev, arg, mode, crypto_encrypt_update)); 2494 } 2495 2496 /* ARGSUSED */ 2497 static int 2498 decrypt_update(dev_t dev, caddr_t arg, int mode, int *rval) 2499 { 2500 return (cipher_update(dev, arg, mode, crypto_decrypt_update)); 2501 } 2502 2503 /* 2504 * ASSUMPTION: crypto_encrypt_update and crypto_decrypt_update 2505 * structures are identical except for field names. 2506 */ 2507 static int 2508 cipher_update(dev_t dev, caddr_t arg, int mode, 2509 int (*update)(crypto_context_t, crypto_data_t *, crypto_data_t *, 2510 crypto_call_req_t *)) 2511 { 2512 STRUCT_DECL(crypto_encrypt_update, encrypt_update); 2513 kproject_t *projp; 2514 crypto_session_id_t session_id; 2515 crypto_minor_t *cm; 2516 crypto_session_data_t *sp; 2517 crypto_ctx_t **ctxpp; 2518 crypto_data_t data, encr; 2519 size_t datalen, encrlen, need = 0; 2520 char *encrbuf; 2521 int error = 0; 2522 int rv; 2523 2524 STRUCT_INIT(encrypt_update, mode); 2525 2526 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 2527 cmn_err(CE_WARN, "cipher_update: failed holding minor"); 2528 return (ENXIO); 2529 } 2530 2531 if (copyin(arg, STRUCT_BUF(encrypt_update), 2532 STRUCT_SIZE(encrypt_update)) != 0) { 2533 crypto_release_minor(cm); 2534 return (EFAULT); 2535 } 2536 2537 data.cd_raw.iov_base = NULL; 2538 encr.cd_raw.iov_base = NULL; 2539 2540 datalen = STRUCT_FGET(encrypt_update, eu_datalen); 2541 encrlen = STRUCT_FGET(encrypt_update, eu_encrlen); 2542 2543 /* 2544 * Don't allocate output buffer unless both buffer pointer and 2545 * buffer length are not NULL or 0 (length). 2546 */ 2547 encrbuf = STRUCT_FGETP(encrypt_update, eu_encrbuf); 2548 if (encrbuf == NULL || encrlen == 0) { 2549 encrlen = 0; 2550 } 2551 2552 if (datalen > crypto_max_buffer_len || 2553 encrlen > crypto_max_buffer_len) { 2554 cmn_err(CE_NOTE, "cipher_update: buffer greater than %ld " 2555 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 2556 rv = CRYPTO_ARGUMENTS_BAD; 2557 goto release_minor; 2558 } 2559 2560 need = datalen + encrlen; 2561 if ((rv = crypto_buffer_check(need, &projp)) != CRYPTO_SUCCESS) { 2562 need = 0; 2563 goto release_minor; 2564 } 2565 2566 INIT_RAW_CRYPTO_DATA(data, datalen); 2567 data.cd_miscdata = NULL; 2568 2569 if (datalen != 0 && copyin(STRUCT_FGETP(encrypt_update, eu_databuf), 2570 data.cd_raw.iov_base, datalen) != 0) { 2571 error = EFAULT; 2572 goto release_minor; 2573 } 2574 2575 INIT_RAW_CRYPTO_DATA(encr, encrlen); 2576 2577 session_id = STRUCT_FGET(encrypt_update, eu_session); 2578 2579 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 2580 goto release_minor; 2581 } 2582 2583 ctxpp = (update == crypto_encrypt_update) ? 2584 &sp->sd_encr_ctx : &sp->sd_decr_ctx; 2585 2586 rv = (update)(*ctxpp, &data, &encr, NULL); 2587 2588 if (rv == CRYPTO_SUCCESS || rv == CRYPTO_BUFFER_TOO_SMALL) { 2589 if (rv == CRYPTO_SUCCESS) { 2590 ASSERT(encr.cd_length <= encrlen); 2591 if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base, 2592 encrbuf, encr.cd_length) != 0) { 2593 error = EFAULT; 2594 goto out; 2595 } 2596 } else { 2597 /* 2598 * The providers return CRYPTO_BUFFER_TOO_SMALL even 2599 * for case 1 of section 11.2 of the pkcs11 spec. 2600 * We catch it here and provide the correct pkcs11 2601 * return value. 2602 */ 2603 if (STRUCT_FGETP(encrypt_update, eu_encrbuf) == NULL) 2604 rv = CRYPTO_SUCCESS; 2605 } 2606 STRUCT_FSET(encrypt_update, eu_encrlen, encr.cd_length); 2607 } else { 2608 CRYPTO_CANCEL_CTX(ctxpp); 2609 } 2610 out: 2611 CRYPTO_SESSION_RELE(sp); 2612 2613 release_minor: 2614 if (need != 0) { 2615 mutex_enter(&crypto_rctl_lock); 2616 CRYPTO_DECREMENT_RCTL(need, projp); 2617 mutex_exit(&crypto_rctl_lock); 2618 } 2619 crypto_release_minor(cm); 2620 2621 if (data.cd_raw.iov_base != NULL) 2622 kmem_free(data.cd_raw.iov_base, datalen); 2623 2624 if (encr.cd_raw.iov_base != NULL) 2625 kmem_free(encr.cd_raw.iov_base, encrlen); 2626 2627 if (error != 0) 2628 return (error); 2629 2630 STRUCT_FSET(encrypt_update, eu_return_value, rv); 2631 if (copyout(STRUCT_BUF(encrypt_update), arg, 2632 STRUCT_SIZE(encrypt_update)) != 0) { 2633 return (EFAULT); 2634 } 2635 return (0); 2636 } 2637 2638 /* ARGSUSED */ 2639 static int 2640 encrypt_final(dev_t dev, caddr_t arg, int mode, int *rval) 2641 { 2642 return (common_final(dev, arg, mode, crypto_encrypt_final)); 2643 } 2644 2645 /* ARGSUSED */ 2646 static int 2647 decrypt_final(dev_t dev, caddr_t arg, int mode, int *rval) 2648 { 2649 return (common_final(dev, arg, mode, crypto_decrypt_final)); 2650 } 2651 2652 /* 2653 * ASSUMPTION: crypto_encrypt_final, crypto_decrypt_final, crypto_sign_final, 2654 * and crypto_digest_final structures are identical except for field names. 2655 */ 2656 static int 2657 common_final(dev_t dev, caddr_t arg, int mode, 2658 int (*final)(crypto_context_t, crypto_data_t *, crypto_call_req_t *)) 2659 { 2660 STRUCT_DECL(crypto_encrypt_final, encrypt_final); 2661 kproject_t *projp; 2662 crypto_session_id_t session_id; 2663 crypto_minor_t *cm; 2664 crypto_session_data_t *sp; 2665 crypto_ctx_t **ctxpp; 2666 crypto_data_t encr; 2667 size_t encrlen, need = 0; 2668 char *encrbuf; 2669 int error = 0; 2670 int rv; 2671 2672 STRUCT_INIT(encrypt_final, mode); 2673 2674 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 2675 cmn_err(CE_WARN, "common_final: failed holding minor"); 2676 return (ENXIO); 2677 } 2678 2679 if (copyin(arg, STRUCT_BUF(encrypt_final), 2680 STRUCT_SIZE(encrypt_final)) != 0) { 2681 crypto_release_minor(cm); 2682 return (EFAULT); 2683 } 2684 2685 encr.cd_format = CRYPTO_DATA_RAW; 2686 encr.cd_raw.iov_base = NULL; 2687 2688 encrlen = STRUCT_FGET(encrypt_final, ef_encrlen); 2689 2690 /* 2691 * Don't allocate output buffer unless both buffer pointer and 2692 * buffer length are not NULL or 0 (length). 2693 */ 2694 encrbuf = STRUCT_FGETP(encrypt_final, ef_encrbuf); 2695 if (encrbuf == NULL || encrlen == 0) { 2696 encrlen = 0; 2697 } 2698 2699 if (encrlen > crypto_max_buffer_len) { 2700 cmn_err(CE_NOTE, "common_final: buffer greater than %ld " 2701 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 2702 rv = CRYPTO_ARGUMENTS_BAD; 2703 goto release_minor; 2704 } 2705 2706 if ((rv = crypto_buffer_check(encrlen, &projp)) != CRYPTO_SUCCESS) { 2707 goto release_minor; 2708 } 2709 need = encrlen; 2710 encr.cd_raw.iov_base = kmem_alloc(encrlen, KM_SLEEP); 2711 encr.cd_raw.iov_len = encrlen; 2712 2713 encr.cd_offset = 0; 2714 encr.cd_length = encrlen; 2715 2716 session_id = STRUCT_FGET(encrypt_final, ef_session); 2717 2718 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 2719 goto release_minor; 2720 } 2721 2722 ASSERT(final == crypto_encrypt_final || 2723 final == crypto_decrypt_final || final == crypto_sign_final || 2724 final == crypto_digest_final); 2725 2726 if (final == crypto_encrypt_final) { 2727 ctxpp = &sp->sd_encr_ctx; 2728 } else if (final == crypto_decrypt_final) { 2729 ctxpp = &sp->sd_decr_ctx; 2730 } else if (final == crypto_sign_final) { 2731 ctxpp = &sp->sd_sign_ctx; 2732 } else { 2733 ctxpp = &sp->sd_digest_ctx; 2734 } 2735 2736 rv = (final)(*ctxpp, &encr, NULL); 2737 if (KCF_CONTEXT_DONE(rv)) 2738 *ctxpp = NULL; 2739 2740 CRYPTO_SESSION_RELE(sp); 2741 2742 if (rv == CRYPTO_SUCCESS) { 2743 ASSERT(encr.cd_length <= encrlen); 2744 if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base, 2745 encrbuf, encr.cd_length) != 0) { 2746 error = EFAULT; 2747 goto release_minor; 2748 } 2749 STRUCT_FSET(encrypt_final, ef_encrlen, encr.cd_length); 2750 } 2751 2752 if (rv == CRYPTO_BUFFER_TOO_SMALL) { 2753 /* 2754 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1 2755 * of section 11.2 of the pkcs11 spec. We catch it here and 2756 * provide the correct pkcs11 return value. 2757 */ 2758 if (STRUCT_FGETP(encrypt_final, ef_encrbuf) == NULL) 2759 rv = CRYPTO_SUCCESS; 2760 STRUCT_FSET(encrypt_final, ef_encrlen, encr.cd_length); 2761 } 2762 2763 release_minor: 2764 if (need != 0) { 2765 mutex_enter(&crypto_rctl_lock); 2766 CRYPTO_DECREMENT_RCTL(need, projp); 2767 mutex_exit(&crypto_rctl_lock); 2768 } 2769 crypto_release_minor(cm); 2770 2771 if (encr.cd_raw.iov_base != NULL) 2772 kmem_free(encr.cd_raw.iov_base, encrlen); 2773 2774 if (error != 0) 2775 return (error); 2776 2777 STRUCT_FSET(encrypt_final, ef_return_value, rv); 2778 if (copyout(STRUCT_BUF(encrypt_final), arg, 2779 STRUCT_SIZE(encrypt_final)) != 0) { 2780 return (EFAULT); 2781 } 2782 return (0); 2783 } 2784 2785 /* ARGSUSED */ 2786 static int 2787 digest_init(dev_t dev, caddr_t arg, int mode, int *rval) 2788 { 2789 STRUCT_DECL(crypto_digest_init, digest_init); 2790 kproject_t *mech_projp; 2791 kcf_provider_desc_t *real_provider; 2792 crypto_session_id_t session_id; 2793 crypto_mechanism_t mech; 2794 crypto_minor_t *cm; 2795 crypto_session_data_t *sp; 2796 crypto_context_t cc; 2797 size_t rctl_bytes = 0; 2798 int error = 0; 2799 int rv; 2800 2801 STRUCT_INIT(digest_init, mode); 2802 2803 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 2804 cmn_err(CE_WARN, "digest_init: failed holding minor"); 2805 return (ENXIO); 2806 } 2807 2808 if (copyin(arg, STRUCT_BUF(digest_init), 2809 STRUCT_SIZE(digest_init)) != 0) { 2810 crypto_release_minor(cm); 2811 return (EFAULT); 2812 } 2813 2814 mech.cm_param = NULL; 2815 2816 session_id = STRUCT_FGET(digest_init, di_session); 2817 2818 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 2819 goto release_minor; 2820 } 2821 2822 if (!copyin_mech(mode, STRUCT_FADDR(digest_init, di_mech), &mech, 2823 &rctl_bytes, NULL, &rv, &error, &mech_projp)) { 2824 goto out; 2825 } 2826 2827 if ((rv = kcf_get_hardware_provider(mech.cm_type, 2828 CRYPTO_OPS_OFFSET(digest_ops), 2829 CRYPTO_DIGEST_OFFSET(digest_init), 2830 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 2831 goto out; 2832 } 2833 2834 rv = crypto_digest_init_prov(real_provider, 2835 sp->sd_provider_session->ps_session, &mech, &cc, NULL); 2836 2837 /* 2838 * Check if a context already exists. If so, it means it is being 2839 * abandoned. So, cancel it to avoid leaking it. 2840 */ 2841 if (sp->sd_digest_ctx != NULL) 2842 CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx); 2843 sp->sd_digest_ctx = (rv == CRYPTO_SUCCESS) ? cc : NULL; 2844 out: 2845 CRYPTO_SESSION_RELE(sp); 2846 2847 release_minor: 2848 if (rctl_bytes != 0) { 2849 mutex_enter(&crypto_rctl_lock); 2850 CRYPTO_DECREMENT_RCTL(rctl_bytes, mech_projp); 2851 mutex_exit(&crypto_rctl_lock); 2852 } 2853 crypto_release_minor(cm); 2854 2855 if (mech.cm_param != NULL) 2856 kmem_free(mech.cm_param, mech.cm_param_len); 2857 2858 if (error != 0) 2859 return (error); 2860 2861 STRUCT_FSET(digest_init, di_return_value, rv); 2862 if (copyout(STRUCT_BUF(digest_init), arg, 2863 STRUCT_SIZE(digest_init)) != 0) { 2864 return (EFAULT); 2865 } 2866 return (0); 2867 } 2868 2869 /* ARGSUSED */ 2870 static int 2871 digest_update(dev_t dev, caddr_t arg, int mode, int *rval) 2872 { 2873 STRUCT_DECL(crypto_digest_update, digest_update); 2874 kproject_t *projp; 2875 crypto_session_id_t session_id; 2876 crypto_minor_t *cm; 2877 crypto_session_data_t *sp; 2878 crypto_data_t data; 2879 size_t datalen, need = 0; 2880 int error = 0; 2881 int rv; 2882 2883 STRUCT_INIT(digest_update, mode); 2884 2885 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 2886 cmn_err(CE_WARN, "digest_update: failed holding minor"); 2887 return (ENXIO); 2888 } 2889 2890 if (copyin(arg, STRUCT_BUF(digest_update), 2891 STRUCT_SIZE(digest_update)) != 0) { 2892 crypto_release_minor(cm); 2893 return (EFAULT); 2894 } 2895 2896 data.cd_format = CRYPTO_DATA_RAW; 2897 data.cd_raw.iov_base = NULL; 2898 2899 datalen = STRUCT_FGET(digest_update, du_datalen); 2900 if (datalen > crypto_max_buffer_len) { 2901 cmn_err(CE_NOTE, "digest_update: buffer greater than %ld " 2902 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 2903 rv = CRYPTO_ARGUMENTS_BAD; 2904 goto release_minor; 2905 } 2906 2907 if ((rv = crypto_buffer_check(datalen, &projp)) != CRYPTO_SUCCESS) { 2908 goto release_minor; 2909 } 2910 need = datalen; 2911 data.cd_raw.iov_base = kmem_alloc(datalen, KM_SLEEP); 2912 data.cd_raw.iov_len = datalen; 2913 2914 if (datalen != 0 && copyin(STRUCT_FGETP(digest_update, du_databuf), 2915 data.cd_raw.iov_base, datalen) != 0) { 2916 error = EFAULT; 2917 goto release_minor; 2918 } 2919 2920 data.cd_offset = 0; 2921 data.cd_length = datalen; 2922 2923 session_id = STRUCT_FGET(digest_update, du_session); 2924 2925 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 2926 goto release_minor; 2927 } 2928 2929 rv = crypto_digest_update(sp->sd_digest_ctx, &data, NULL); 2930 if (rv != CRYPTO_SUCCESS) 2931 CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx); 2932 CRYPTO_SESSION_RELE(sp); 2933 2934 release_minor: 2935 if (need != 0) { 2936 mutex_enter(&crypto_rctl_lock); 2937 CRYPTO_DECREMENT_RCTL(need, projp); 2938 mutex_exit(&crypto_rctl_lock); 2939 } 2940 crypto_release_minor(cm); 2941 2942 if (data.cd_raw.iov_base != NULL) 2943 kmem_free(data.cd_raw.iov_base, datalen); 2944 2945 if (error != 0) 2946 return (error); 2947 2948 STRUCT_FSET(digest_update, du_return_value, rv); 2949 if (copyout(STRUCT_BUF(digest_update), arg, 2950 STRUCT_SIZE(digest_update)) != 0) { 2951 return (EFAULT); 2952 } 2953 return (0); 2954 } 2955 2956 /* ARGSUSED */ 2957 static int 2958 digest_key(dev_t dev, caddr_t arg, int mode, int *rval) 2959 { 2960 STRUCT_DECL(crypto_digest_key, digest_key); 2961 kproject_t *projp; 2962 crypto_session_id_t session_id; 2963 crypto_key_t key; 2964 crypto_minor_t *cm; 2965 crypto_session_data_t *sp; 2966 size_t rctl_bytes = 0; 2967 int error = 0; 2968 int rv; 2969 2970 STRUCT_INIT(digest_key, mode); 2971 2972 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 2973 cmn_err(CE_WARN, "digest_key: failed holding minor"); 2974 return (ENXIO); 2975 } 2976 2977 if (copyin(arg, STRUCT_BUF(digest_key), STRUCT_SIZE(digest_key)) != 0) { 2978 crypto_release_minor(cm); 2979 return (EFAULT); 2980 } 2981 2982 bzero(&key, sizeof (crypto_key_t)); 2983 2984 session_id = STRUCT_FGET(digest_key, dk_session); 2985 2986 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 2987 goto release_minor; 2988 } 2989 2990 if (!copyin_key(mode, STRUCT_FADDR(digest_key, dk_key), &key, 2991 &rctl_bytes, &rv, &error, 0, &projp)) { 2992 goto out; 2993 } 2994 2995 rv = crypto_digest_key_prov(sp->sd_digest_ctx, &key, NULL); 2996 if (rv != CRYPTO_SUCCESS) 2997 CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx); 2998 out: 2999 CRYPTO_SESSION_RELE(sp); 3000 3001 release_minor: 3002 if (rctl_bytes != 0) { 3003 mutex_enter(&crypto_rctl_lock); 3004 CRYPTO_DECREMENT_RCTL(rctl_bytes, projp); 3005 mutex_exit(&crypto_rctl_lock); 3006 } 3007 crypto_release_minor(cm); 3008 3009 free_crypto_key(&key); 3010 3011 if (error != 0) 3012 return (error); 3013 3014 STRUCT_FSET(digest_key, dk_return_value, rv); 3015 if (copyout(STRUCT_BUF(digest_key), arg, 3016 STRUCT_SIZE(digest_key)) != 0) { 3017 return (EFAULT); 3018 } 3019 return (0); 3020 } 3021 3022 /* ARGSUSED */ 3023 static int 3024 digest_final(dev_t dev, caddr_t arg, int mode, int *rval) 3025 { 3026 return (common_final(dev, arg, mode, crypto_digest_final)); 3027 } 3028 3029 /* ARGSUSED */ 3030 static int 3031 digest(dev_t dev, caddr_t arg, int mode, int *rval) 3032 { 3033 return (common_digest(dev, arg, mode, crypto_digest_single)); 3034 } 3035 3036 /* 3037 * ASSUMPTION: crypto_digest, crypto_sign, crypto_sign_recover, 3038 * and crypto_verify_recover are identical except for field names. 3039 */ 3040 static int 3041 common_digest(dev_t dev, caddr_t arg, int mode, 3042 int (*single)(crypto_context_t, crypto_data_t *, crypto_data_t *, 3043 crypto_call_req_t *)) 3044 { 3045 STRUCT_DECL(crypto_digest, crypto_digest); 3046 kproject_t *projp; 3047 crypto_session_id_t session_id; 3048 crypto_minor_t *cm; 3049 crypto_session_data_t *sp; 3050 crypto_data_t data, digest; 3051 crypto_ctx_t **ctxpp; 3052 size_t datalen, digestlen, need = 0; 3053 char *digestbuf; 3054 int error = 0; 3055 int rv; 3056 3057 STRUCT_INIT(crypto_digest, mode); 3058 3059 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3060 cmn_err(CE_WARN, "common_digest: failed holding minor"); 3061 return (ENXIO); 3062 } 3063 3064 if (copyin(arg, STRUCT_BUF(crypto_digest), 3065 STRUCT_SIZE(crypto_digest)) != 0) { 3066 crypto_release_minor(cm); 3067 return (EFAULT); 3068 } 3069 3070 data.cd_raw.iov_base = NULL; 3071 digest.cd_raw.iov_base = NULL; 3072 3073 datalen = STRUCT_FGET(crypto_digest, cd_datalen); 3074 digestlen = STRUCT_FGET(crypto_digest, cd_digestlen); 3075 3076 /* 3077 * Don't allocate output buffer unless both buffer pointer and 3078 * buffer length are not NULL or 0 (length). 3079 */ 3080 digestbuf = STRUCT_FGETP(crypto_digest, cd_digestbuf); 3081 if (digestbuf == NULL || digestlen == 0) { 3082 digestlen = 0; 3083 } 3084 3085 if (datalen > crypto_max_buffer_len || 3086 digestlen > crypto_max_buffer_len) { 3087 cmn_err(CE_NOTE, "common_digest: buffer greater than %ld " 3088 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 3089 rv = CRYPTO_ARGUMENTS_BAD; 3090 goto release_minor; 3091 } 3092 3093 need = datalen + digestlen; 3094 if ((rv = crypto_buffer_check(need, &projp)) != CRYPTO_SUCCESS) { 3095 need = 0; 3096 goto release_minor; 3097 } 3098 3099 INIT_RAW_CRYPTO_DATA(data, datalen); 3100 3101 if (datalen != 0 && copyin(STRUCT_FGETP(crypto_digest, cd_databuf), 3102 data.cd_raw.iov_base, datalen) != 0) { 3103 error = EFAULT; 3104 goto release_minor; 3105 } 3106 3107 INIT_RAW_CRYPTO_DATA(digest, digestlen); 3108 3109 session_id = STRUCT_FGET(crypto_digest, cd_session); 3110 3111 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 3112 goto release_minor; 3113 } 3114 3115 ASSERT(single == crypto_digest_single || 3116 single == crypto_sign_single || 3117 single == crypto_verify_recover_single || 3118 single == crypto_sign_recover_single); 3119 3120 if (single == crypto_digest_single) { 3121 ctxpp = &sp->sd_digest_ctx; 3122 } else if (single == crypto_sign_single) { 3123 ctxpp = &sp->sd_sign_ctx; 3124 } else if (single == crypto_verify_recover_single) { 3125 ctxpp = &sp->sd_verify_recover_ctx; 3126 } else { 3127 ctxpp = &sp->sd_sign_recover_ctx; 3128 } 3129 rv = (single)(*ctxpp, &data, &digest, NULL); 3130 if (KCF_CONTEXT_DONE(rv)) 3131 *ctxpp = NULL; 3132 3133 CRYPTO_SESSION_RELE(sp); 3134 3135 if (rv == CRYPTO_SUCCESS) { 3136 ASSERT(digest.cd_length <= digestlen); 3137 if (digest.cd_length != 0 && copyout(digest.cd_raw.iov_base, 3138 digestbuf, digest.cd_length) != 0) { 3139 error = EFAULT; 3140 goto release_minor; 3141 } 3142 STRUCT_FSET(crypto_digest, cd_digestlen, digest.cd_length); 3143 } 3144 3145 if (rv == CRYPTO_BUFFER_TOO_SMALL) { 3146 /* 3147 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1 3148 * of section 11.2 of the pkcs11 spec. We catch it here and 3149 * provide the correct pkcs11 return value. 3150 */ 3151 if (STRUCT_FGETP(crypto_digest, cd_digestbuf) == NULL) 3152 rv = CRYPTO_SUCCESS; 3153 STRUCT_FSET(crypto_digest, cd_digestlen, digest.cd_length); 3154 } 3155 3156 release_minor: 3157 if (need != 0) { 3158 mutex_enter(&crypto_rctl_lock); 3159 CRYPTO_DECREMENT_RCTL(need, projp); 3160 mutex_exit(&crypto_rctl_lock); 3161 } 3162 crypto_release_minor(cm); 3163 3164 if (data.cd_raw.iov_base != NULL) 3165 kmem_free(data.cd_raw.iov_base, datalen); 3166 3167 if (digest.cd_raw.iov_base != NULL) 3168 kmem_free(digest.cd_raw.iov_base, digestlen); 3169 3170 if (error != 0) 3171 return (error); 3172 3173 STRUCT_FSET(crypto_digest, cd_return_value, rv); 3174 if (copyout(STRUCT_BUF(crypto_digest), arg, 3175 STRUCT_SIZE(crypto_digest)) != 0) { 3176 return (EFAULT); 3177 } 3178 return (0); 3179 } 3180 3181 /* 3182 * A helper function that does what the name suggests. 3183 * Returns 0 on success and non-zero otherwise. 3184 * On failure, out_pin is set to 0. 3185 */ 3186 int 3187 get_pin_and_session_ptr(char *in_pin, char **out_pin, size_t pin_len, 3188 crypto_minor_t *cm, crypto_session_id_t sid, crypto_session_data_t **sp, 3189 int *rv, int *error) 3190 { 3191 char *tmp_pin = NULL; 3192 int tmp_error = 0, tmp_rv = 0; 3193 3194 if (pin_len > KCF_MAX_PIN_LEN) { 3195 tmp_rv = CRYPTO_PIN_LEN_RANGE; 3196 goto out; 3197 } 3198 tmp_pin = kmem_alloc(pin_len, KM_SLEEP); 3199 3200 if (pin_len != 0 && copyin(in_pin, tmp_pin, pin_len) != 0) { 3201 tmp_error = EFAULT; 3202 goto out; 3203 } 3204 3205 (void) get_session_ptr(sid, cm, sp, &tmp_error, &tmp_rv); 3206 out: 3207 *out_pin = tmp_pin; 3208 *rv = tmp_rv; 3209 *error = tmp_error; 3210 return (tmp_rv | tmp_error); 3211 } 3212 3213 /* ARGSUSED */ 3214 static int 3215 set_pin(dev_t dev, caddr_t arg, int mode, int *rval) 3216 { 3217 STRUCT_DECL(crypto_set_pin, set_pin); 3218 kcf_provider_desc_t *real_provider; 3219 kcf_req_params_t params; 3220 crypto_minor_t *cm; 3221 crypto_session_data_t *sp; 3222 char *old_pin = NULL; 3223 char *new_pin = NULL; 3224 size_t old_pin_len; 3225 size_t new_pin_len; 3226 int error = 0; 3227 int rv; 3228 3229 STRUCT_INIT(set_pin, mode); 3230 3231 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3232 cmn_err(CE_WARN, "set_pin: failed holding minor"); 3233 return (ENXIO); 3234 } 3235 3236 if (copyin(arg, STRUCT_BUF(set_pin), 3237 STRUCT_SIZE(set_pin)) != 0) { 3238 crypto_release_minor(cm); 3239 return (EFAULT); 3240 } 3241 3242 old_pin_len = STRUCT_FGET(set_pin, sp_old_len); 3243 3244 if (get_pin_and_session_ptr(STRUCT_FGETP(set_pin, sp_old_pin), 3245 &old_pin, old_pin_len, cm, STRUCT_FGET(set_pin, sp_session), 3246 &sp, &rv, &error) != 0) 3247 goto release_minor; 3248 3249 new_pin_len = STRUCT_FGET(set_pin, sp_new_len); 3250 if (new_pin_len > KCF_MAX_PIN_LEN) { 3251 rv = CRYPTO_PIN_LEN_RANGE; 3252 goto out; 3253 } 3254 new_pin = kmem_alloc(new_pin_len, KM_SLEEP); 3255 3256 if (new_pin_len != 0 && copyin(STRUCT_FGETP(set_pin, sp_new_pin), 3257 new_pin, new_pin_len) != 0) { 3258 error = EFAULT; 3259 goto out; 3260 } 3261 3262 if ((rv = kcf_get_hardware_provider_nomech( 3263 CRYPTO_OPS_OFFSET(provider_ops), CRYPTO_PROVIDER_OFFSET(set_pin), 3264 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 3265 goto out; 3266 } 3267 3268 KCF_WRAP_PROVMGMT_OPS_PARAMS(¶ms, KCF_OP_MGMT_SETPIN, 3269 sp->sd_provider_session->ps_session, old_pin, old_pin_len, 3270 new_pin, new_pin_len, NULL, NULL, real_provider); 3271 3272 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 3273 3274 out: 3275 CRYPTO_SESSION_RELE(sp); 3276 3277 release_minor: 3278 crypto_release_minor(cm); 3279 3280 if (old_pin != NULL) { 3281 bzero(old_pin, old_pin_len); 3282 kmem_free(old_pin, old_pin_len); 3283 } 3284 3285 if (new_pin != NULL) { 3286 bzero(new_pin, new_pin_len); 3287 kmem_free(new_pin, new_pin_len); 3288 } 3289 3290 if (error != 0) 3291 return (error); 3292 3293 STRUCT_FSET(set_pin, sp_return_value, rv); 3294 if (copyout(STRUCT_BUF(set_pin), arg, STRUCT_SIZE(set_pin)) != 0) { 3295 return (EFAULT); 3296 } 3297 return (0); 3298 } 3299 3300 /* ARGSUSED */ 3301 static int 3302 login(dev_t dev, caddr_t arg, int mode, int *rval) 3303 { 3304 STRUCT_DECL(crypto_login, login); 3305 kcf_provider_desc_t *real_provider; 3306 kcf_req_params_t params; 3307 crypto_minor_t *cm; 3308 crypto_session_data_t *sp; 3309 size_t pin_len; 3310 char *pin; 3311 uint_t user_type; 3312 int error = 0; 3313 int rv; 3314 3315 STRUCT_INIT(login, mode); 3316 3317 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3318 cmn_err(CE_WARN, "login: failed holding minor"); 3319 return (ENXIO); 3320 } 3321 3322 if (copyin(arg, STRUCT_BUF(login), STRUCT_SIZE(login)) != 0) { 3323 crypto_release_minor(cm); 3324 return (EFAULT); 3325 } 3326 3327 user_type = STRUCT_FGET(login, co_user_type); 3328 3329 pin_len = STRUCT_FGET(login, co_pin_len); 3330 3331 if (get_pin_and_session_ptr(STRUCT_FGETP(login, co_pin), 3332 &pin, pin_len, cm, STRUCT_FGET(login, co_session), 3333 &sp, &rv, &error) != 0) { 3334 if (rv == CRYPTO_PIN_LEN_RANGE) 3335 rv = CRYPTO_PIN_INCORRECT; 3336 goto release_minor; 3337 } 3338 3339 if ((rv = kcf_get_hardware_provider_nomech( 3340 CRYPTO_OPS_OFFSET(session_ops), 3341 CRYPTO_SESSION_OFFSET(session_login), 3342 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 3343 goto out; 3344 } 3345 3346 KCF_WRAP_SESSION_OPS_PARAMS(¶ms, KCF_OP_SESSION_LOGIN, NULL, 3347 sp->sd_provider_session->ps_session, user_type, pin, pin_len, 3348 real_provider); 3349 3350 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 3351 3352 out: 3353 CRYPTO_SESSION_RELE(sp); 3354 3355 release_minor: 3356 crypto_release_minor(cm); 3357 3358 if (pin != NULL) { 3359 bzero(pin, pin_len); 3360 kmem_free(pin, pin_len); 3361 } 3362 3363 if (error != 0) 3364 return (error); 3365 3366 STRUCT_FSET(login, co_return_value, rv); 3367 if (copyout(STRUCT_BUF(login), arg, STRUCT_SIZE(login)) != 0) { 3368 return (EFAULT); 3369 } 3370 return (0); 3371 } 3372 3373 /* ARGSUSED */ 3374 static int 3375 logout(dev_t dev, caddr_t arg, int mode, int *rval) 3376 { 3377 crypto_logout_t logout; 3378 kcf_provider_desc_t *real_provider; 3379 kcf_req_params_t params; 3380 crypto_minor_t *cm; 3381 crypto_session_data_t *sp; 3382 int error = 0; 3383 int rv; 3384 3385 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3386 cmn_err(CE_WARN, "logout: failed holding minor"); 3387 return (ENXIO); 3388 } 3389 3390 if (copyin(arg, &logout, sizeof (logout)) != 0) { 3391 crypto_release_minor(cm); 3392 return (EFAULT); 3393 } 3394 3395 if (!get_session_ptr(logout.cl_session, cm, &sp, &error, &rv)) { 3396 goto release_minor; 3397 } 3398 3399 if ((rv = kcf_get_hardware_provider_nomech( 3400 CRYPTO_OPS_OFFSET(session_ops), 3401 CRYPTO_SESSION_OFFSET(session_logout), 3402 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 3403 goto out; 3404 } 3405 3406 KCF_WRAP_SESSION_OPS_PARAMS(¶ms, KCF_OP_SESSION_LOGOUT, NULL, 3407 sp->sd_provider_session->ps_session, 0, NULL, 0, real_provider); 3408 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 3409 3410 out: 3411 CRYPTO_SESSION_RELE(sp); 3412 3413 release_minor: 3414 crypto_release_minor(cm); 3415 3416 if (error != 0) 3417 return (error); 3418 3419 logout.cl_return_value = rv; 3420 if (copyout(&logout, arg, sizeof (logout)) != 0) { 3421 return (EFAULT); 3422 } 3423 return (0); 3424 } 3425 3426 /* ARGSUSED */ 3427 static int 3428 sign_init(dev_t dev, caddr_t arg, int mode, int *rval) 3429 { 3430 return (sign_verify_init(dev, arg, mode, crypto_sign_init_prov)); 3431 } 3432 3433 /* ARGSUSED */ 3434 static int 3435 sign_recover_init(dev_t dev, caddr_t arg, int mode, int *rval) 3436 { 3437 return (sign_verify_init(dev, arg, mode, 3438 crypto_sign_recover_init_prov)); 3439 } 3440 3441 /* ARGSUSED */ 3442 static int 3443 verify_init(dev_t dev, caddr_t arg, int mode, int *rval) 3444 { 3445 return (sign_verify_init(dev, arg, mode, crypto_verify_init_prov)); 3446 } 3447 3448 /* ARGSUSED */ 3449 static int 3450 verify_recover_init(dev_t dev, caddr_t arg, int mode, int *rval) 3451 { 3452 return (sign_verify_init(dev, arg, mode, 3453 crypto_verify_recover_init_prov)); 3454 } 3455 3456 /* 3457 * ASSUMPTION: crypto_sign_init, crypto_verify_init, crypto_sign_recover_init, 3458 * and crypto_verify_recover_init structures are identical 3459 * except for field names. 3460 */ 3461 static int 3462 sign_verify_init(dev_t dev, caddr_t arg, int mode, 3463 int (*init)(kcf_provider_desc_t *, crypto_session_id_t, 3464 crypto_mechanism_t *, crypto_key_t *, crypto_ctx_template_t, 3465 crypto_context_t *, crypto_call_req_t *)) 3466 { 3467 STRUCT_DECL(crypto_sign_init, sign_init); 3468 kproject_t *mech_projp, *key_projp; 3469 kcf_provider_desc_t *real_provider; 3470 crypto_session_id_t session_id; 3471 crypto_mechanism_t mech; 3472 crypto_key_t key; 3473 crypto_minor_t *cm; 3474 crypto_session_data_t *sp; 3475 crypto_context_t cc; 3476 crypto_ctx_t **ctxpp; 3477 size_t mech_rctl_bytes = 0; 3478 size_t key_rctl_bytes = 0; 3479 size_t carry; 3480 offset_t offset_1, offset_2; 3481 int error = 0; 3482 int rv; 3483 3484 STRUCT_INIT(sign_init, mode); 3485 3486 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3487 cmn_err(CE_WARN, "sign_verify_init: failed holding minor"); 3488 return (ENXIO); 3489 } 3490 3491 if (copyin(arg, STRUCT_BUF(sign_init), STRUCT_SIZE(sign_init)) != 0) { 3492 crypto_release_minor(cm); 3493 return (EFAULT); 3494 } 3495 3496 mech.cm_param = NULL; 3497 bzero(&key, sizeof (key)); 3498 3499 session_id = STRUCT_FGET(sign_init, si_session); 3500 3501 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 3502 goto release_minor; 3503 } 3504 3505 if (!copyin_mech(mode, STRUCT_FADDR(sign_init, si_mech), &mech, 3506 &mech_rctl_bytes, &carry, &rv, &error, &mech_projp)) { 3507 goto out; 3508 } 3509 3510 ASSERT(init == crypto_sign_init_prov || 3511 init == crypto_verify_init_prov || 3512 init == crypto_sign_recover_init_prov || 3513 init == crypto_verify_recover_init_prov); 3514 3515 if (init == crypto_sign_init_prov) { 3516 offset_1 = CRYPTO_OPS_OFFSET(sign_ops); 3517 offset_2 = CRYPTO_SIGN_OFFSET(sign_init); 3518 ctxpp = &sp->sd_sign_ctx; 3519 } else if (init == crypto_verify_init_prov) { 3520 offset_1 = CRYPTO_OPS_OFFSET(verify_ops); 3521 offset_2 = CRYPTO_VERIFY_OFFSET(verify_init); 3522 ctxpp = &sp->sd_verify_ctx; 3523 } else if (init == crypto_sign_recover_init_prov) { 3524 offset_1 = CRYPTO_OPS_OFFSET(sign_ops); 3525 offset_2 = CRYPTO_SIGN_OFFSET(sign_recover_init); 3526 ctxpp = &sp->sd_sign_recover_ctx; 3527 } else { 3528 offset_1 = CRYPTO_OPS_OFFSET(verify_ops); 3529 offset_2 = CRYPTO_VERIFY_OFFSET(verify_recover_init); 3530 ctxpp = &sp->sd_verify_recover_ctx; 3531 } 3532 3533 if ((rv = kcf_get_hardware_provider(mech.cm_type, offset_1, 3534 offset_2, sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 3535 goto out; 3536 } 3537 3538 if (!copyin_key(mode, STRUCT_FADDR(sign_init, si_key), &key, 3539 &key_rctl_bytes, &rv, &error, carry, &key_projp)) { 3540 goto out; 3541 } 3542 3543 rv = (init)(real_provider, sp->sd_provider_session->ps_session, 3544 &mech, &key, NULL, &cc, NULL); 3545 3546 /* 3547 * Check if a context already exists. If so, it means it is being 3548 * abandoned. So, cancel it to avoid leaking it. 3549 */ 3550 if (*ctxpp != NULL) 3551 CRYPTO_CANCEL_CTX(ctxpp); 3552 *ctxpp = (rv == CRYPTO_SUCCESS) ? cc : NULL; 3553 3554 out: 3555 CRYPTO_SESSION_RELE(sp); 3556 3557 release_minor: 3558 mutex_enter(&crypto_rctl_lock); 3559 if (mech_rctl_bytes != 0) 3560 CRYPTO_DECREMENT_RCTL(mech_rctl_bytes, mech_projp); 3561 if (key_rctl_bytes != 0) 3562 CRYPTO_DECREMENT_RCTL(key_rctl_bytes, key_projp); 3563 mutex_exit(&crypto_rctl_lock); 3564 crypto_release_minor(cm); 3565 3566 if (mech.cm_param != NULL) 3567 kmem_free(mech.cm_param, mech.cm_param_len); 3568 3569 free_crypto_key(&key); 3570 3571 if (error != 0) 3572 return (error); 3573 3574 STRUCT_FSET(sign_init, si_return_value, rv); 3575 if (copyout(STRUCT_BUF(sign_init), arg, STRUCT_SIZE(sign_init)) != 0) { 3576 return (EFAULT); 3577 } 3578 return (0); 3579 } 3580 3581 /* ARGSUSED */ 3582 static int 3583 sign(dev_t dev, caddr_t arg, int mode, int *rval) 3584 { 3585 return (common_digest(dev, arg, mode, crypto_sign_single)); 3586 } 3587 3588 /* ARGSUSED */ 3589 static int 3590 sign_recover(dev_t dev, caddr_t arg, int mode, int *rval) 3591 { 3592 return (common_digest(dev, arg, mode, crypto_sign_recover_single)); 3593 } 3594 3595 /* ARGSUSED */ 3596 static int 3597 verify(dev_t dev, caddr_t arg, int mode, int *rval) 3598 { 3599 STRUCT_DECL(crypto_verify, verify); 3600 kproject_t *projp; 3601 crypto_session_id_t session_id; 3602 crypto_minor_t *cm; 3603 crypto_session_data_t *sp; 3604 crypto_data_t data, sign; 3605 size_t datalen, signlen, need = 0; 3606 int error = 0; 3607 int rv; 3608 3609 STRUCT_INIT(verify, mode); 3610 3611 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3612 cmn_err(CE_WARN, "verify: failed holding minor"); 3613 return (ENXIO); 3614 } 3615 3616 if (copyin(arg, STRUCT_BUF(verify), STRUCT_SIZE(verify)) != 0) { 3617 crypto_release_minor(cm); 3618 return (EFAULT); 3619 } 3620 3621 data.cd_raw.iov_base = NULL; 3622 sign.cd_raw.iov_base = NULL; 3623 3624 datalen = STRUCT_FGET(verify, cv_datalen); 3625 signlen = STRUCT_FGET(verify, cv_signlen); 3626 if (datalen > crypto_max_buffer_len || 3627 signlen > crypto_max_buffer_len) { 3628 cmn_err(CE_NOTE, "verify: buffer greater than %ld bytes, " 3629 "pid = %d", crypto_max_buffer_len, curproc->p_pid); 3630 rv = CRYPTO_ARGUMENTS_BAD; 3631 goto release_minor; 3632 } 3633 3634 need = datalen + signlen; 3635 if ((rv = crypto_buffer_check(need, &projp)) != CRYPTO_SUCCESS) { 3636 need = 0; 3637 goto release_minor; 3638 } 3639 3640 INIT_RAW_CRYPTO_DATA(data, datalen); 3641 INIT_RAW_CRYPTO_DATA(sign, signlen); 3642 3643 if (datalen != 0 && copyin(STRUCT_FGETP(verify, cv_databuf), 3644 data.cd_raw.iov_base, datalen) != 0) { 3645 error = EFAULT; 3646 goto release_minor; 3647 } 3648 3649 if (signlen != 0 && copyin(STRUCT_FGETP(verify, cv_signbuf), 3650 sign.cd_raw.iov_base, signlen) != 0) { 3651 error = EFAULT; 3652 goto release_minor; 3653 } 3654 session_id = STRUCT_FGET(verify, cv_session); 3655 3656 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 3657 goto release_minor; 3658 } 3659 3660 rv = crypto_verify_single(sp->sd_verify_ctx, &data, &sign, NULL); 3661 if (KCF_CONTEXT_DONE(rv)) 3662 sp->sd_verify_ctx = NULL; 3663 3664 CRYPTO_SESSION_RELE(sp); 3665 3666 release_minor: 3667 if (need != 0) { 3668 mutex_enter(&crypto_rctl_lock); 3669 CRYPTO_DECREMENT_RCTL(need, projp); 3670 mutex_exit(&crypto_rctl_lock); 3671 } 3672 crypto_release_minor(cm); 3673 3674 if (data.cd_raw.iov_base != NULL) 3675 kmem_free(data.cd_raw.iov_base, datalen); 3676 3677 if (sign.cd_raw.iov_base != NULL) 3678 kmem_free(sign.cd_raw.iov_base, signlen); 3679 3680 if (error != 0) 3681 return (error); 3682 3683 STRUCT_FSET(verify, cv_return_value, rv); 3684 if (copyout(STRUCT_BUF(verify), arg, STRUCT_SIZE(verify)) != 0) { 3685 return (EFAULT); 3686 } 3687 return (0); 3688 } 3689 3690 /* ARGSUSED */ 3691 static int 3692 verify_recover(dev_t dev, caddr_t arg, int mode, int *rval) 3693 { 3694 return (common_digest(dev, arg, mode, crypto_verify_recover_single)); 3695 } 3696 3697 /* ARGSUSED */ 3698 static int 3699 sign_update(dev_t dev, caddr_t arg, int mode, int *rval) 3700 { 3701 return (sign_verify_update(dev, arg, mode, crypto_sign_update)); 3702 } 3703 3704 /* ARGSUSED */ 3705 static int 3706 verify_update(dev_t dev, caddr_t arg, int mode, int *rval) 3707 { 3708 return (sign_verify_update(dev, arg, mode, crypto_verify_update)); 3709 } 3710 3711 /* 3712 * ASSUMPTION: crypto_sign_update and crypto_verify_update structures 3713 * are identical except for field names. 3714 */ 3715 static int 3716 sign_verify_update(dev_t dev, caddr_t arg, int mode, 3717 int (*update)(crypto_context_t, crypto_data_t *, crypto_call_req_t *)) 3718 { 3719 STRUCT_DECL(crypto_sign_update, sign_update); 3720 kproject_t *projp; 3721 crypto_session_id_t session_id; 3722 crypto_minor_t *cm; 3723 crypto_session_data_t *sp; 3724 crypto_ctx_t **ctxpp; 3725 crypto_data_t data; 3726 size_t datalen, need = 0; 3727 int error = 0; 3728 int rv; 3729 3730 STRUCT_INIT(sign_update, mode); 3731 3732 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3733 cmn_err(CE_WARN, "sign_verify_update: failed holding minor"); 3734 return (ENXIO); 3735 } 3736 3737 if (copyin(arg, STRUCT_BUF(sign_update), 3738 STRUCT_SIZE(sign_update)) != 0) { 3739 crypto_release_minor(cm); 3740 return (EFAULT); 3741 } 3742 3743 data.cd_raw.iov_base = NULL; 3744 3745 datalen = STRUCT_FGET(sign_update, su_datalen); 3746 if (datalen > crypto_max_buffer_len) { 3747 cmn_err(CE_NOTE, "sign_verify_update: buffer greater than %ld " 3748 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 3749 rv = CRYPTO_ARGUMENTS_BAD; 3750 goto release_minor; 3751 } 3752 3753 if ((rv = crypto_buffer_check(datalen, &projp)) != CRYPTO_SUCCESS) { 3754 goto release_minor; 3755 } 3756 need = datalen; 3757 3758 INIT_RAW_CRYPTO_DATA(data, datalen); 3759 3760 if (datalen != 0 && copyin(STRUCT_FGETP(sign_update, su_databuf), 3761 data.cd_raw.iov_base, datalen) != 0) { 3762 error = EFAULT; 3763 goto release_minor; 3764 } 3765 3766 session_id = STRUCT_FGET(sign_update, su_session); 3767 3768 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 3769 goto release_minor; 3770 } 3771 3772 ctxpp = (update == crypto_sign_update) ? 3773 &sp->sd_sign_ctx : &sp->sd_verify_ctx; 3774 3775 rv = (update)(*ctxpp, &data, NULL); 3776 if (rv != CRYPTO_SUCCESS) 3777 CRYPTO_CANCEL_CTX(ctxpp); 3778 CRYPTO_SESSION_RELE(sp); 3779 3780 release_minor: 3781 if (need != 0) { 3782 mutex_enter(&crypto_rctl_lock); 3783 CRYPTO_DECREMENT_RCTL(need, projp); 3784 mutex_exit(&crypto_rctl_lock); 3785 } 3786 crypto_release_minor(cm); 3787 3788 if (data.cd_raw.iov_base != NULL) 3789 kmem_free(data.cd_raw.iov_base, datalen); 3790 3791 if (error != 0) 3792 return (error); 3793 3794 STRUCT_FSET(sign_update, su_return_value, rv); 3795 if (copyout(STRUCT_BUF(sign_update), arg, 3796 STRUCT_SIZE(sign_update)) != 0) { 3797 return (EFAULT); 3798 } 3799 return (0); 3800 } 3801 3802 /* ARGSUSED */ 3803 static int 3804 sign_final(dev_t dev, caddr_t arg, int mode, int *rval) 3805 { 3806 return (common_final(dev, arg, mode, crypto_sign_final)); 3807 } 3808 3809 /* 3810 * Can't use the common final because it does a copyout of 3811 * the final part. 3812 */ 3813 /* ARGSUSED */ 3814 static int 3815 verify_final(dev_t dev, caddr_t arg, int mode, int *rval) 3816 { 3817 STRUCT_DECL(crypto_verify_final, verify_final); 3818 kproject_t *projp; 3819 crypto_session_id_t session_id; 3820 crypto_minor_t *cm; 3821 crypto_session_data_t *sp; 3822 crypto_data_t sign; 3823 size_t signlen, need = 0; 3824 int error = 0; 3825 int rv; 3826 3827 STRUCT_INIT(verify_final, mode); 3828 3829 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3830 cmn_err(CE_WARN, "verify_final: failed holding minor"); 3831 return (ENXIO); 3832 } 3833 3834 if (copyin(arg, STRUCT_BUF(verify_final), 3835 STRUCT_SIZE(verify_final)) != 0) { 3836 crypto_release_minor(cm); 3837 return (EFAULT); 3838 } 3839 3840 sign.cd_raw.iov_base = NULL; 3841 3842 signlen = STRUCT_FGET(verify_final, vf_signlen); 3843 if (signlen > crypto_max_buffer_len) { 3844 cmn_err(CE_NOTE, "verify_final: buffer greater than %ld " 3845 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 3846 rv = CRYPTO_ARGUMENTS_BAD; 3847 goto release_minor; 3848 } 3849 3850 if ((rv = crypto_buffer_check(signlen, &projp)) != CRYPTO_SUCCESS) { 3851 goto release_minor; 3852 } 3853 need = signlen; 3854 3855 INIT_RAW_CRYPTO_DATA(sign, signlen); 3856 3857 if (signlen != 0 && copyin(STRUCT_FGETP(verify_final, vf_signbuf), 3858 sign.cd_raw.iov_base, signlen) != 0) { 3859 error = EFAULT; 3860 goto release_minor; 3861 } 3862 3863 session_id = STRUCT_FGET(verify_final, vf_session); 3864 3865 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 3866 goto release_minor; 3867 } 3868 3869 rv = crypto_verify_final(sp->sd_verify_ctx, &sign, NULL); 3870 if (KCF_CONTEXT_DONE(rv)) 3871 sp->sd_verify_ctx = NULL; 3872 3873 CRYPTO_SESSION_RELE(sp); 3874 3875 release_minor: 3876 if (need != 0) { 3877 mutex_enter(&crypto_rctl_lock); 3878 CRYPTO_DECREMENT_RCTL(need, projp); 3879 mutex_exit(&crypto_rctl_lock); 3880 } 3881 crypto_release_minor(cm); 3882 3883 if (sign.cd_raw.iov_base != NULL) 3884 kmem_free(sign.cd_raw.iov_base, signlen); 3885 3886 if (error != 0) 3887 return (error); 3888 3889 STRUCT_FSET(verify_final, vf_return_value, rv); 3890 if (copyout(STRUCT_BUF(verify_final), arg, 3891 STRUCT_SIZE(verify_final)) != 0) { 3892 return (EFAULT); 3893 } 3894 return (0); 3895 } 3896 3897 /* ARGSUSED */ 3898 static int 3899 seed_random(dev_t dev, caddr_t arg, int mode, int *rval) 3900 { 3901 STRUCT_DECL(crypto_seed_random, seed_random); 3902 kproject_t *projp; 3903 kcf_provider_desc_t *real_provider; 3904 kcf_req_params_t params; 3905 crypto_session_id_t session_id; 3906 crypto_minor_t *cm; 3907 crypto_session_data_t *sp; 3908 uchar_t *seed_buffer = NULL; 3909 size_t seed_len; 3910 size_t need = 0; 3911 int error = 0; 3912 int rv; 3913 3914 STRUCT_INIT(seed_random, mode); 3915 3916 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 3917 cmn_err(CE_WARN, "seed_random: failed holding minor"); 3918 return (ENXIO); 3919 } 3920 3921 if (copyin(arg, STRUCT_BUF(seed_random), 3922 STRUCT_SIZE(seed_random)) != 0) { 3923 crypto_release_minor(cm); 3924 return (EFAULT); 3925 } 3926 3927 seed_len = STRUCT_FGET(seed_random, sr_seedlen); 3928 if (seed_len > crypto_max_buffer_len) { 3929 cmn_err(CE_NOTE, "seed_random: buffer greater than %ld " 3930 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 3931 rv = CRYPTO_ARGUMENTS_BAD; 3932 goto release_minor; 3933 } 3934 3935 if ((rv = crypto_buffer_check(seed_len, &projp)) != CRYPTO_SUCCESS) { 3936 goto release_minor; 3937 } 3938 need = seed_len; 3939 seed_buffer = kmem_alloc(seed_len, KM_SLEEP); 3940 3941 if (seed_len != 0 && copyin(STRUCT_FGETP(seed_random, sr_seedbuf), 3942 seed_buffer, seed_len) != 0) { 3943 error = EFAULT; 3944 goto release_minor; 3945 } 3946 3947 session_id = STRUCT_FGET(seed_random, sr_session); 3948 3949 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 3950 goto release_minor; 3951 } 3952 3953 if (random_mech == CRYPTO_MECH_INVALID) 3954 random_mech = crypto_mech2id_common(SUN_RANDOM, B_FALSE); 3955 3956 if ((rv = kcf_get_hardware_provider(random_mech, 3957 CRYPTO_OPS_OFFSET(random_ops), 3958 CRYPTO_RANDOM_OFFSET(seed_random), 3959 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 3960 goto out; 3961 } 3962 3963 KCF_WRAP_RANDOM_OPS_PARAMS(¶ms, KCF_OP_RANDOM_SEED, 3964 sp->sd_provider_session->ps_session, seed_buffer, seed_len); 3965 3966 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 3967 3968 out: 3969 CRYPTO_SESSION_RELE(sp); 3970 3971 release_minor: 3972 if (need != 0) { 3973 mutex_enter(&crypto_rctl_lock); 3974 CRYPTO_DECREMENT_RCTL(need, projp); 3975 mutex_exit(&crypto_rctl_lock); 3976 } 3977 crypto_release_minor(cm); 3978 3979 if (seed_buffer != NULL) 3980 kmem_free(seed_buffer, seed_len); 3981 3982 if (error != 0) 3983 return (error); 3984 3985 STRUCT_FSET(seed_random, sr_return_value, rv); 3986 if (copyout(STRUCT_BUF(seed_random), arg, 3987 STRUCT_SIZE(seed_random)) != 0) { 3988 return (EFAULT); 3989 } 3990 return (0); 3991 } 3992 3993 /* ARGSUSED */ 3994 static int 3995 generate_random(dev_t dev, caddr_t arg, int mode, int *rval) 3996 { 3997 STRUCT_DECL(crypto_generate_random, generate_random); 3998 kproject_t *projp; 3999 kcf_provider_desc_t *real_provider; 4000 kcf_req_params_t params; 4001 crypto_session_id_t session_id; 4002 crypto_minor_t *cm; 4003 crypto_session_data_t *sp; 4004 uchar_t *buffer = NULL; 4005 size_t len; 4006 size_t need = 0; 4007 int error = 0; 4008 int rv; 4009 4010 STRUCT_INIT(generate_random, mode); 4011 4012 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4013 cmn_err(CE_WARN, "generate_random: failed holding minor"); 4014 return (ENXIO); 4015 } 4016 4017 if (copyin(arg, STRUCT_BUF(generate_random), 4018 STRUCT_SIZE(generate_random)) != 0) { 4019 crypto_release_minor(cm); 4020 return (EFAULT); 4021 } 4022 4023 len = STRUCT_FGET(generate_random, gr_buflen); 4024 if (len > crypto_max_buffer_len) { 4025 cmn_err(CE_NOTE, "generate_random: buffer greater than %ld " 4026 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 4027 rv = CRYPTO_ARGUMENTS_BAD; 4028 goto release_minor; 4029 } 4030 4031 if ((rv = crypto_buffer_check(len, &projp)) != CRYPTO_SUCCESS) { 4032 goto release_minor; 4033 } 4034 need = len; 4035 buffer = kmem_alloc(len, KM_SLEEP); 4036 4037 session_id = STRUCT_FGET(generate_random, gr_session); 4038 4039 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4040 goto release_minor; 4041 } 4042 4043 if (random_mech == CRYPTO_MECH_INVALID) 4044 random_mech = crypto_mech2id_common(SUN_RANDOM, B_FALSE); 4045 4046 if ((rv = kcf_get_hardware_provider(random_mech, 4047 CRYPTO_OPS_OFFSET(random_ops), 4048 CRYPTO_RANDOM_OFFSET(generate_random), 4049 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 4050 goto out; 4051 } 4052 4053 KCF_WRAP_RANDOM_OPS_PARAMS(¶ms, KCF_OP_RANDOM_GENERATE, 4054 sp->sd_provider_session->ps_session, buffer, len); 4055 4056 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4057 4058 out: 4059 CRYPTO_SESSION_RELE(sp); 4060 4061 if (rv == CRYPTO_SUCCESS) { 4062 if (len != 0 && copyout(buffer, 4063 STRUCT_FGETP(generate_random, gr_buf), len) != 0) { 4064 error = EFAULT; 4065 } 4066 } 4067 4068 release_minor: 4069 if (need != 0) { 4070 mutex_enter(&crypto_rctl_lock); 4071 CRYPTO_DECREMENT_RCTL(need, projp); 4072 mutex_exit(&crypto_rctl_lock); 4073 } 4074 crypto_release_minor(cm); 4075 4076 if (buffer != NULL) { 4077 /* random numbers are often used to create keys */ 4078 bzero(buffer, len); 4079 kmem_free(buffer, len); 4080 } 4081 4082 if (error != 0) 4083 return (error); 4084 4085 STRUCT_FSET(generate_random, gr_return_value, rv); 4086 if (copyout(STRUCT_BUF(generate_random), arg, 4087 STRUCT_SIZE(generate_random)) != 0) { 4088 return (EFAULT); 4089 } 4090 return (0); 4091 } 4092 4093 /* 4094 * Copyout a kernel array of attributes to user space. 4095 * u_attrs is the corresponding user space array containing 4096 * user space pointers necessary for the copyout. 4097 */ 4098 /* ARGSUSED */ 4099 static int 4100 copyout_attributes(int mode, caddr_t out, uint_t count, 4101 crypto_object_attribute_t *k_attrs, caddr_t u_attrs) 4102 { 4103 STRUCT_DECL(crypto_object_attribute, oa); 4104 caddr_t p, valuep; 4105 size_t value_len; 4106 size_t len; 4107 int i; 4108 int error = 0; 4109 4110 if (count == 0) 4111 return (0); 4112 4113 STRUCT_INIT(oa, mode); 4114 4115 len = count * STRUCT_SIZE(oa); 4116 4117 ASSERT(u_attrs != NULL); 4118 p = u_attrs; 4119 for (i = 0; i < count; i++) { 4120 /* can this bcopy be eliminated? */ 4121 bcopy(p, STRUCT_BUF(oa), STRUCT_SIZE(oa)); 4122 value_len = k_attrs[i].oa_value_len; 4123 STRUCT_FSET(oa, oa_type, k_attrs[i].oa_type); 4124 STRUCT_FSET(oa, oa_value_len, value_len); 4125 valuep = STRUCT_FGETP(oa, oa_value); 4126 if (valuep != NULL && value_len != -1) { 4127 if (copyout(k_attrs[i].oa_value, 4128 valuep, value_len) != 0) { 4129 error = EFAULT; 4130 goto out; 4131 } 4132 } 4133 bcopy(STRUCT_BUF(oa), p, STRUCT_SIZE(oa)); 4134 p += STRUCT_SIZE(oa); 4135 } 4136 if (copyout(u_attrs, out, len)) { 4137 error = EFAULT; 4138 } 4139 out: 4140 return (error); 4141 } 4142 4143 4144 /* ARGSUSED */ 4145 static int 4146 object_create(dev_t dev, caddr_t arg, int mode, int *rval) 4147 { 4148 STRUCT_DECL(crypto_object_create, object_create); 4149 kproject_t *projp; 4150 kcf_provider_desc_t *real_provider; 4151 kcf_req_params_t params; 4152 crypto_object_attribute_t *k_attrs = NULL; 4153 crypto_session_id_t session_id; 4154 crypto_minor_t *cm; 4155 crypto_session_data_t *sp = NULL; 4156 crypto_object_id_t object_handle; 4157 caddr_t oc_attributes; 4158 size_t k_attrs_size; 4159 size_t rctl_bytes = 0; 4160 int error = 0; 4161 int rv; 4162 uint_t count; 4163 4164 STRUCT_INIT(object_create, mode); 4165 4166 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4167 cmn_err(CE_WARN, "object_create: failed holding minor"); 4168 return (ENXIO); 4169 } 4170 4171 if (copyin(arg, STRUCT_BUF(object_create), 4172 STRUCT_SIZE(object_create)) != 0) { 4173 crypto_release_minor(cm); 4174 return (EFAULT); 4175 } 4176 4177 count = STRUCT_FGET(object_create, oc_count); 4178 oc_attributes = STRUCT_FGETP(object_create, oc_attributes); 4179 if (!copyin_attributes(mode, count, oc_attributes, &k_attrs, 4180 &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 0, B_TRUE, &projp)) { 4181 goto release_minor; 4182 } 4183 4184 session_id = STRUCT_FGET(object_create, oc_session); 4185 4186 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4187 goto release_minor; 4188 } 4189 4190 if ((rv = kcf_get_hardware_provider_nomech( 4191 CRYPTO_OPS_OFFSET(object_ops), 4192 CRYPTO_OBJECT_OFFSET(object_create), 4193 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 4194 goto release_minor; 4195 } 4196 4197 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_CREATE, 4198 sp->sd_provider_session->ps_session, 0, k_attrs, count, 4199 &object_handle, 0, NULL, NULL, 0, NULL); 4200 4201 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4202 4203 if (rv == CRYPTO_SUCCESS) 4204 STRUCT_FSET(object_create, oc_handle, object_handle); 4205 4206 release_minor: 4207 if (rctl_bytes != 0) { 4208 mutex_enter(&crypto_rctl_lock); 4209 CRYPTO_DECREMENT_RCTL(rctl_bytes, projp); 4210 mutex_exit(&crypto_rctl_lock); 4211 } 4212 4213 if (k_attrs != NULL) 4214 kmem_free(k_attrs, k_attrs_size); 4215 4216 if (error != 0) 4217 goto out; 4218 4219 STRUCT_FSET(object_create, oc_return_value, rv); 4220 if (copyout(STRUCT_BUF(object_create), arg, 4221 STRUCT_SIZE(object_create)) != 0) { 4222 if (rv == CRYPTO_SUCCESS) { 4223 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 4224 KCF_OP_OBJECT_DESTROY, 4225 sp->sd_provider_session->ps_session, object_handle, 4226 NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 4227 4228 (void) kcf_submit_request(real_provider, NULL, 4229 NULL, ¶ms, B_FALSE); 4230 4231 error = EFAULT; 4232 } 4233 } 4234 out: 4235 if (sp != NULL) 4236 CRYPTO_SESSION_RELE(sp); 4237 crypto_release_minor(cm); 4238 return (error); 4239 } 4240 4241 /* ARGSUSED */ 4242 static int 4243 object_copy(dev_t dev, caddr_t arg, int mode, int *rval) 4244 { 4245 STRUCT_DECL(crypto_object_copy, object_copy); 4246 kproject_t *projp; 4247 kcf_provider_desc_t *real_provider; 4248 kcf_req_params_t params; 4249 crypto_object_attribute_t *k_attrs = NULL; 4250 crypto_session_id_t session_id; 4251 crypto_minor_t *cm; 4252 crypto_session_data_t *sp = NULL; 4253 crypto_object_id_t handle, new_handle; 4254 caddr_t oc_new_attributes; 4255 size_t k_attrs_size; 4256 size_t rctl_bytes = 0; 4257 int error = 0; 4258 int rv; 4259 uint_t count; 4260 4261 STRUCT_INIT(object_copy, mode); 4262 4263 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4264 cmn_err(CE_WARN, "object_copy: failed holding minor"); 4265 return (ENXIO); 4266 } 4267 4268 if (copyin(arg, STRUCT_BUF(object_copy), 4269 STRUCT_SIZE(object_copy)) != 0) { 4270 crypto_release_minor(cm); 4271 return (EFAULT); 4272 } 4273 4274 count = STRUCT_FGET(object_copy, oc_count); 4275 oc_new_attributes = STRUCT_FGETP(object_copy, oc_new_attributes); 4276 if (!copyin_attributes(mode, count, oc_new_attributes, &k_attrs, 4277 &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 0, B_TRUE, &projp)) { 4278 goto release_minor; 4279 } 4280 4281 session_id = STRUCT_FGET(object_copy, oc_session); 4282 4283 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4284 goto release_minor; 4285 } 4286 4287 if ((rv = kcf_get_hardware_provider_nomech( 4288 CRYPTO_OPS_OFFSET(object_ops), 4289 CRYPTO_OBJECT_OFFSET(object_copy), 4290 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 4291 goto release_minor; 4292 } 4293 4294 handle = STRUCT_FGET(object_copy, oc_handle); 4295 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_COPY, 4296 sp->sd_provider_session->ps_session, handle, k_attrs, count, 4297 &new_handle, 0, NULL, NULL, 0, NULL); 4298 4299 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4300 4301 if (rv == CRYPTO_SUCCESS) 4302 STRUCT_FSET(object_copy, oc_new_handle, new_handle); 4303 4304 release_minor: 4305 if (rctl_bytes != 0) { 4306 mutex_enter(&crypto_rctl_lock); 4307 CRYPTO_DECREMENT_RCTL(rctl_bytes, projp); 4308 mutex_exit(&crypto_rctl_lock); 4309 } 4310 4311 if (k_attrs != NULL) 4312 kmem_free(k_attrs, k_attrs_size); 4313 4314 if (error != 0) 4315 goto out; 4316 4317 STRUCT_FSET(object_copy, oc_return_value, rv); 4318 if (copyout(STRUCT_BUF(object_copy), arg, 4319 STRUCT_SIZE(object_copy)) != 0) { 4320 if (rv == CRYPTO_SUCCESS) { 4321 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 4322 KCF_OP_OBJECT_DESTROY, 4323 sp->sd_provider_session->ps_session, new_handle, 4324 NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 4325 4326 (void) kcf_submit_request(real_provider, NULL, 4327 NULL, ¶ms, B_FALSE); 4328 4329 error = EFAULT; 4330 } 4331 } 4332 out: 4333 if (sp != NULL) 4334 CRYPTO_SESSION_RELE(sp); 4335 crypto_release_minor(cm); 4336 return (error); 4337 } 4338 4339 /* ARGSUSED */ 4340 static int 4341 object_destroy(dev_t dev, caddr_t arg, int mode, int *rval) 4342 { 4343 STRUCT_DECL(crypto_object_destroy, object_destroy); 4344 kcf_provider_desc_t *real_provider; 4345 kcf_req_params_t params; 4346 crypto_session_id_t session_id; 4347 crypto_minor_t *cm; 4348 crypto_session_data_t *sp; 4349 crypto_object_id_t handle; 4350 int error = 0; 4351 int rv; 4352 4353 STRUCT_INIT(object_destroy, mode); 4354 4355 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4356 cmn_err(CE_WARN, "object_destroy: failed holding minor"); 4357 return (ENXIO); 4358 } 4359 4360 if (copyin(arg, STRUCT_BUF(object_destroy), 4361 STRUCT_SIZE(object_destroy)) != 0) { 4362 crypto_release_minor(cm); 4363 return (EFAULT); 4364 } 4365 4366 session_id = STRUCT_FGET(object_destroy, od_session); 4367 4368 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4369 goto release_minor; 4370 } 4371 4372 if ((rv = kcf_get_hardware_provider_nomech( 4373 CRYPTO_OPS_OFFSET(object_ops), 4374 CRYPTO_OBJECT_OFFSET(object_destroy), 4375 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 4376 goto out; 4377 } 4378 4379 handle = STRUCT_FGET(object_destroy, od_handle); 4380 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_DESTROY, 4381 sp->sd_provider_session->ps_session, handle, NULL, 0, NULL, 0, 4382 NULL, NULL, 0, NULL); 4383 4384 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4385 4386 out: 4387 CRYPTO_SESSION_RELE(sp); 4388 4389 release_minor: 4390 crypto_release_minor(cm); 4391 4392 if (error != 0) 4393 return (error); 4394 4395 STRUCT_FSET(object_destroy, od_return_value, rv); 4396 4397 if (copyout(STRUCT_BUF(object_destroy), arg, 4398 STRUCT_SIZE(object_destroy)) != 0) { 4399 return (EFAULT); 4400 } 4401 return (0); 4402 } 4403 4404 /* ARGSUSED */ 4405 static int 4406 object_get_attribute_value(dev_t dev, caddr_t arg, int mode, int *rval) 4407 { 4408 STRUCT_DECL(crypto_object_get_attribute_value, get_attribute_value); 4409 /* LINTED E_FUNC_SET_NOT_USED */ 4410 STRUCT_DECL(crypto_object_attribute, oa); 4411 kproject_t *projp; 4412 kcf_provider_desc_t *real_provider; 4413 kcf_req_params_t params; 4414 crypto_object_attribute_t *k_attrs = NULL; 4415 crypto_session_id_t session_id; 4416 crypto_minor_t *cm; 4417 crypto_session_data_t *sp; 4418 crypto_object_id_t handle; 4419 caddr_t og_attributes; 4420 caddr_t u_attrs; 4421 size_t k_attrs_size; 4422 size_t rctl_bytes = 0; 4423 int error = 0; 4424 int rv; 4425 uint_t count; 4426 4427 STRUCT_INIT(get_attribute_value, mode); 4428 STRUCT_INIT(oa, mode); 4429 4430 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4431 cmn_err(CE_WARN, 4432 "object_get_attribute_value: failed holding minor"); 4433 return (ENXIO); 4434 } 4435 4436 if (copyin(arg, STRUCT_BUF(get_attribute_value), 4437 STRUCT_SIZE(get_attribute_value)) != 0) { 4438 crypto_release_minor(cm); 4439 return (EFAULT); 4440 } 4441 4442 count = STRUCT_FGET(get_attribute_value, og_count); 4443 og_attributes = STRUCT_FGETP(get_attribute_value, og_attributes); 4444 if (!copyin_attributes(mode, count, og_attributes, &k_attrs, 4445 &k_attrs_size, &u_attrs, &rv, &error, &rctl_bytes, 0, B_FALSE, 4446 &projp)) { 4447 goto release_minor; 4448 } 4449 4450 session_id = STRUCT_FGET(get_attribute_value, og_session); 4451 4452 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4453 goto release_minor; 4454 } 4455 4456 if ((rv = kcf_get_hardware_provider_nomech( 4457 CRYPTO_OPS_OFFSET(object_ops), 4458 CRYPTO_OBJECT_OFFSET(object_get_attribute_value), 4459 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 4460 goto out; 4461 } 4462 4463 handle = STRUCT_FGET(get_attribute_value, og_handle); 4464 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_GET_ATTRIBUTE_VALUE, 4465 sp->sd_provider_session->ps_session, handle, k_attrs, count, NULL, 4466 0, NULL, NULL, 0, NULL); 4467 4468 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4469 4470 out: 4471 CRYPTO_SESSION_RELE(sp); 4472 4473 if (rv == CRYPTO_SUCCESS || rv == CRYPTO_ATTRIBUTE_SENSITIVE || 4474 rv == CRYPTO_ATTRIBUTE_TYPE_INVALID || 4475 rv == CRYPTO_BUFFER_TOO_SMALL) { 4476 error = copyout_attributes(mode, 4477 STRUCT_FGETP(get_attribute_value, og_attributes), 4478 count, k_attrs, u_attrs); 4479 } 4480 4481 release_minor: 4482 if (rctl_bytes != 0) { 4483 mutex_enter(&crypto_rctl_lock); 4484 CRYPTO_DECREMENT_RCTL(rctl_bytes, projp); 4485 mutex_exit(&crypto_rctl_lock); 4486 } 4487 crypto_release_minor(cm); 4488 4489 if (k_attrs != NULL) 4490 kmem_free(k_attrs, k_attrs_size); 4491 4492 if (u_attrs != NULL) 4493 kmem_free(u_attrs, count * STRUCT_SIZE(oa)); 4494 4495 if (error != 0) 4496 return (error); 4497 4498 STRUCT_FSET(get_attribute_value, og_return_value, rv); 4499 if (copyout(STRUCT_BUF(get_attribute_value), arg, 4500 STRUCT_SIZE(get_attribute_value)) != 0) { 4501 return (EFAULT); 4502 } 4503 return (0); 4504 } 4505 4506 /* ARGSUSED */ 4507 static int 4508 object_get_size(dev_t dev, caddr_t arg, int mode, int *rval) 4509 { 4510 STRUCT_DECL(crypto_object_get_size, object_get_size); 4511 kcf_provider_desc_t *real_provider; 4512 kcf_req_params_t params; 4513 crypto_session_id_t session_id; 4514 crypto_minor_t *cm; 4515 crypto_session_data_t *sp; 4516 crypto_object_id_t handle; 4517 size_t size; 4518 int error = 0; 4519 int rv; 4520 4521 STRUCT_INIT(object_get_size, mode); 4522 4523 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4524 cmn_err(CE_WARN, "object_get_size: failed holding minor"); 4525 return (ENXIO); 4526 } 4527 4528 if (copyin(arg, STRUCT_BUF(object_get_size), 4529 STRUCT_SIZE(object_get_size)) != 0) { 4530 crypto_release_minor(cm); 4531 return (EFAULT); 4532 } 4533 4534 session_id = STRUCT_FGET(object_get_size, gs_session); 4535 4536 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4537 goto release_minor; 4538 } 4539 4540 if ((rv = kcf_get_hardware_provider_nomech( 4541 CRYPTO_OPS_OFFSET(object_ops), 4542 CRYPTO_OBJECT_OFFSET(object_get_size), 4543 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 4544 goto out; 4545 } 4546 4547 handle = STRUCT_FGET(object_get_size, gs_handle); 4548 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_GET_SIZE, 4549 sp->sd_provider_session->ps_session, handle, NULL, 0, NULL, &size, 4550 NULL, NULL, 0, NULL); 4551 4552 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4553 4554 out: 4555 CRYPTO_SESSION_RELE(sp); 4556 4557 if (rv == CRYPTO_SUCCESS) { 4558 STRUCT_FSET(object_get_size, gs_size, size); 4559 } 4560 release_minor: 4561 crypto_release_minor(cm); 4562 4563 if (error != 0) 4564 return (error); 4565 4566 STRUCT_FSET(object_get_size, gs_return_value, rv); 4567 if (copyout(STRUCT_BUF(object_get_size), arg, 4568 STRUCT_SIZE(object_get_size)) != 0) { 4569 return (EFAULT); 4570 } 4571 return (0); 4572 } 4573 4574 /* ARGSUSED */ 4575 static int 4576 object_set_attribute_value(dev_t dev, caddr_t arg, int mode, int *rval) 4577 { 4578 STRUCT_DECL(crypto_object_set_attribute_value, set_attribute_value); 4579 kproject_t *projp; 4580 kcf_provider_desc_t *real_provider; 4581 kcf_req_params_t params; 4582 crypto_object_attribute_t *k_attrs = NULL; 4583 crypto_session_id_t session_id; 4584 crypto_minor_t *cm; 4585 crypto_session_data_t *sp; 4586 crypto_object_id_t object_handle; 4587 caddr_t sa_attributes; 4588 size_t k_attrs_size; 4589 size_t rctl_bytes = 0; 4590 int error = 0; 4591 int rv; 4592 uint_t count; 4593 4594 STRUCT_INIT(set_attribute_value, mode); 4595 4596 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4597 cmn_err(CE_WARN, 4598 "object_set_attribute_value: failed holding minor"); 4599 return (ENXIO); 4600 } 4601 4602 if (copyin(arg, STRUCT_BUF(set_attribute_value), 4603 STRUCT_SIZE(set_attribute_value)) != 0) { 4604 crypto_release_minor(cm); 4605 return (EFAULT); 4606 } 4607 4608 count = STRUCT_FGET(set_attribute_value, sa_count); 4609 sa_attributes = STRUCT_FGETP(set_attribute_value, sa_attributes); 4610 if (!copyin_attributes(mode, count, sa_attributes, &k_attrs, 4611 &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 0, B_TRUE, &projp)) { 4612 goto release_minor; 4613 } 4614 4615 session_id = STRUCT_FGET(set_attribute_value, sa_session); 4616 4617 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4618 goto release_minor; 4619 } 4620 4621 if ((rv = kcf_get_hardware_provider_nomech( 4622 CRYPTO_OPS_OFFSET(object_ops), 4623 CRYPTO_OBJECT_OFFSET(object_set_attribute_value), 4624 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 4625 goto out; 4626 } 4627 4628 object_handle = STRUCT_FGET(set_attribute_value, sa_handle); 4629 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_SET_ATTRIBUTE_VALUE, 4630 sp->sd_provider_session->ps_session, object_handle, k_attrs, count, 4631 NULL, 0, NULL, NULL, 0, NULL); 4632 4633 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4634 4635 out: 4636 CRYPTO_SESSION_RELE(sp); 4637 4638 release_minor: 4639 if (rctl_bytes != 0) { 4640 mutex_enter(&crypto_rctl_lock); 4641 CRYPTO_DECREMENT_RCTL(rctl_bytes, projp); 4642 mutex_exit(&crypto_rctl_lock); 4643 } 4644 crypto_release_minor(cm); 4645 4646 if (k_attrs != NULL) 4647 kmem_free(k_attrs, k_attrs_size); 4648 4649 if (error != 0) 4650 return (error); 4651 4652 STRUCT_FSET(set_attribute_value, sa_return_value, rv); 4653 if (copyout(STRUCT_BUF(set_attribute_value), arg, 4654 STRUCT_SIZE(set_attribute_value)) != 0) { 4655 return (EFAULT); 4656 } 4657 return (0); 4658 } 4659 4660 /* ARGSUSED */ 4661 static int 4662 object_find_init(dev_t dev, caddr_t arg, int mode, int *rval) 4663 { 4664 STRUCT_DECL(crypto_object_find_init, find_init); 4665 kproject_t *projp; 4666 kcf_provider_desc_t *real_provider; 4667 kcf_req_params_t params; 4668 crypto_object_attribute_t *k_attrs = NULL; 4669 crypto_session_id_t session_id; 4670 crypto_minor_t *cm; 4671 crypto_session_data_t *sp; 4672 caddr_t attributes; 4673 size_t k_attrs_size; 4674 size_t rctl_bytes = 0; 4675 int error = 0; 4676 int rv; 4677 uint_t count; 4678 void *cookie; 4679 4680 STRUCT_INIT(find_init, mode); 4681 4682 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4683 cmn_err(CE_WARN, "object_find_init: failed holding minor"); 4684 return (ENXIO); 4685 } 4686 4687 if (copyin(arg, STRUCT_BUF(find_init), STRUCT_SIZE(find_init)) != 0) { 4688 crypto_release_minor(cm); 4689 return (EFAULT); 4690 } 4691 4692 count = STRUCT_FGET(find_init, fi_count); 4693 attributes = STRUCT_FGETP(find_init, fi_attributes); 4694 if (!copyin_attributes(mode, count, attributes, &k_attrs, 4695 &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 0, B_TRUE, &projp)) { 4696 goto release_minor; 4697 } 4698 4699 session_id = STRUCT_FGET(find_init, fi_session); 4700 4701 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4702 goto release_minor; 4703 } 4704 4705 if ((rv = kcf_get_hardware_provider_nomech( 4706 CRYPTO_OPS_OFFSET(object_ops), 4707 CRYPTO_OBJECT_OFFSET(object_find_init), 4708 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 4709 goto out; 4710 } 4711 4712 /* check for an active find */ 4713 if (sp->sd_find_init_cookie != NULL) { 4714 rv = CRYPTO_OPERATION_IS_ACTIVE; 4715 CRYPTO_SESSION_RELE(sp); 4716 goto release_minor; 4717 } 4718 4719 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_FIND_INIT, 4720 sp->sd_provider_session->ps_session, 0, k_attrs, count, NULL, 0, 4721 &cookie, NULL, 0, NULL); 4722 4723 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4724 4725 if (rv == CRYPTO_SUCCESS) { 4726 /* 4727 * The cookie is allocated by a provider at the start of an 4728 * object search. It is freed when the search is terminated 4729 * by a final operation, or when the session is closed. 4730 * It contains state information about which object handles 4731 * have been returned to the caller. 4732 */ 4733 sp->sd_find_init_cookie = cookie; 4734 } 4735 4736 out: 4737 CRYPTO_SESSION_RELE(sp); 4738 4739 release_minor: 4740 if (rctl_bytes != 0) { 4741 mutex_enter(&crypto_rctl_lock); 4742 CRYPTO_DECREMENT_RCTL(rctl_bytes, projp); 4743 mutex_exit(&crypto_rctl_lock); 4744 } 4745 crypto_release_minor(cm); 4746 4747 if (k_attrs != NULL) 4748 kmem_free(k_attrs, k_attrs_size); 4749 4750 if (error != 0) 4751 return (error); 4752 4753 STRUCT_FSET(find_init, fi_return_value, rv); 4754 if (copyout(STRUCT_BUF(find_init), arg, STRUCT_SIZE(find_init)) != 0) { 4755 return (EFAULT); 4756 } 4757 return (0); 4758 } 4759 4760 /* ARGSUSED */ 4761 static int 4762 object_find_update(dev_t dev, caddr_t arg, int mode, int *rval) 4763 { 4764 STRUCT_DECL(crypto_object_find_update, find_update); 4765 kproject_t *projp; 4766 kcf_provider_desc_t *real_provider; 4767 kcf_req_params_t params; 4768 crypto_minor_t *cm; 4769 crypto_session_data_t *sp; 4770 crypto_object_id_t *buffer = NULL; 4771 crypto_session_id_t session_id; 4772 size_t len, rctl_bytes = 0; 4773 uint_t count, max_count; 4774 int rv, error = 0; 4775 4776 STRUCT_INIT(find_update, mode); 4777 4778 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4779 cmn_err(CE_WARN, "object_find_update: failed holding minor"); 4780 return (ENXIO); 4781 } 4782 4783 if (copyin(arg, STRUCT_BUF(find_update), 4784 STRUCT_SIZE(find_update)) != 0) { 4785 crypto_release_minor(cm); 4786 return (EFAULT); 4787 } 4788 4789 max_count = STRUCT_FGET(find_update, fu_max_count); 4790 if (max_count > CRYPTO_MAX_FIND_COUNT) { 4791 cmn_err(CE_NOTE, "object_find_update: count greater than %d, " 4792 "pid = %d", CRYPTO_MAX_FIND_COUNT, curproc->p_pid); 4793 rv = CRYPTO_ARGUMENTS_BAD; 4794 goto release_minor; 4795 } 4796 len = max_count * sizeof (crypto_object_id_t); 4797 if ((rv = crypto_buffer_check(len, &projp)) != CRYPTO_SUCCESS) { 4798 goto release_minor; 4799 } 4800 rctl_bytes = len; 4801 buffer = kmem_alloc(len, KM_SLEEP); 4802 4803 session_id = STRUCT_FGET(find_update, fu_session); 4804 4805 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4806 goto release_minor; 4807 } 4808 4809 if ((rv = kcf_get_hardware_provider_nomech( 4810 CRYPTO_OPS_OFFSET(object_ops), 4811 CRYPTO_OBJECT_OFFSET(object_find), 4812 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 4813 goto out; 4814 } 4815 4816 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_FIND, 4817 sp->sd_provider_session->ps_session, 0, NULL, 0, buffer, 0, 4818 NULL, sp->sd_find_init_cookie, max_count, &count); 4819 4820 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4821 4822 out: 4823 CRYPTO_SESSION_RELE(sp); 4824 if (rv == CRYPTO_SUCCESS) { 4825 if (count > max_count) { 4826 /* bad bad provider */ 4827 rv = CRYPTO_FAILED; 4828 goto release_minor; 4829 } 4830 if (count != 0) { 4831 /* copyout handles */ 4832 if (copyout(buffer, 4833 STRUCT_FGETP(find_update, fu_handles), 4834 count * sizeof (crypto_object_id_t)) != 0) { 4835 error = EFAULT; 4836 } 4837 } 4838 STRUCT_FSET(find_update, fu_count, count); 4839 } 4840 4841 release_minor: 4842 if (rctl_bytes != 0) { 4843 mutex_enter(&crypto_rctl_lock); 4844 CRYPTO_DECREMENT_RCTL(rctl_bytes, projp); 4845 mutex_exit(&crypto_rctl_lock); 4846 } 4847 crypto_release_minor(cm); 4848 4849 if (buffer != NULL) 4850 kmem_free(buffer, len); 4851 4852 if (error != 0) 4853 return (error); 4854 4855 STRUCT_FSET(find_update, fu_return_value, rv); 4856 if (copyout(STRUCT_BUF(find_update), arg, 4857 STRUCT_SIZE(find_update)) != 0) { 4858 return (EFAULT); 4859 } 4860 4861 return (0); 4862 } 4863 4864 /* 4865 * Free provider-allocated storage used for find object searches. 4866 */ 4867 static int 4868 crypto_free_find_ctx(crypto_session_data_t *sp) 4869 { 4870 kcf_provider_desc_t *real_provider; 4871 kcf_req_params_t params; 4872 int rv; 4873 4874 if ((rv = kcf_get_hardware_provider_nomech( 4875 CRYPTO_OPS_OFFSET(object_ops), 4876 CRYPTO_OBJECT_OFFSET(object_find_final), 4877 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 4878 return (rv); 4879 } 4880 4881 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_FIND_FINAL, 4882 sp->sd_provider_session->ps_session, 0, NULL, 0, NULL, 0, 4883 NULL, sp->sd_find_init_cookie, 0, NULL); 4884 4885 return (kcf_submit_request(real_provider, 4886 NULL, NULL, ¶ms, B_FALSE)); 4887 } 4888 4889 /* ARGSUSED */ 4890 static int 4891 object_find_final(dev_t dev, caddr_t arg, int mode, int *rval) 4892 { 4893 STRUCT_DECL(crypto_object_find_final, object_find_final); 4894 crypto_session_id_t session_id; 4895 crypto_minor_t *cm; 4896 crypto_session_data_t *sp; 4897 int error = 0; 4898 int rv; 4899 4900 STRUCT_INIT(object_find_final, mode); 4901 4902 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4903 cmn_err(CE_WARN, "object_find_final: failed holding minor"); 4904 return (ENXIO); 4905 } 4906 4907 if (copyin(arg, STRUCT_BUF(object_find_final), 4908 STRUCT_SIZE(object_find_final)) != 0) { 4909 crypto_release_minor(cm); 4910 return (EFAULT); 4911 } 4912 4913 session_id = STRUCT_FGET(object_find_final, ff_session); 4914 4915 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4916 goto release_minor; 4917 } 4918 4919 if ((rv = crypto_free_find_ctx(sp)) == CRYPTO_SUCCESS) { 4920 sp->sd_find_init_cookie = NULL; 4921 } 4922 4923 CRYPTO_SESSION_RELE(sp); 4924 4925 release_minor: 4926 crypto_release_minor(cm); 4927 4928 if (error != 0) 4929 return (error); 4930 4931 STRUCT_FSET(object_find_final, ff_return_value, rv); 4932 4933 if (copyout(STRUCT_BUF(object_find_final), arg, 4934 STRUCT_SIZE(object_find_final)) != 0) { 4935 return (EFAULT); 4936 } 4937 return (0); 4938 } 4939 4940 /* ARGSUSED */ 4941 static int 4942 object_generate_key(dev_t dev, caddr_t arg, int mode, int *rval) 4943 { 4944 STRUCT_DECL(crypto_object_generate_key, generate_key); 4945 kproject_t *mech_projp, *key_projp; 4946 kcf_provider_desc_t *real_provider; 4947 kcf_req_params_t params; 4948 crypto_mechanism_t mech; 4949 crypto_object_attribute_t *k_attrs = NULL; 4950 crypto_session_id_t session_id; 4951 crypto_minor_t *cm; 4952 crypto_session_data_t *sp = NULL; 4953 crypto_object_id_t key_handle; 4954 caddr_t attributes; 4955 size_t k_attrs_size; 4956 size_t mech_rctl_bytes = 0, key_rctl_bytes = 0; 4957 size_t carry; 4958 uint_t count; 4959 int error = 0; 4960 int rv; 4961 4962 STRUCT_INIT(generate_key, mode); 4963 4964 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 4965 cmn_err(CE_WARN, "object_generate_key: failed holding minor"); 4966 return (ENXIO); 4967 } 4968 4969 if (copyin(arg, STRUCT_BUF(generate_key), 4970 STRUCT_SIZE(generate_key)) != 0) { 4971 crypto_release_minor(cm); 4972 return (EFAULT); 4973 } 4974 4975 session_id = STRUCT_FGET(generate_key, gk_session); 4976 4977 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 4978 goto release_minor; 4979 } 4980 4981 if (!copyin_mech(mode, STRUCT_FADDR(generate_key, gk_mechanism), 4982 &mech, &mech_rctl_bytes, &carry, &rv, &error, &mech_projp)) { 4983 goto release_minor; 4984 } 4985 4986 if ((rv = kcf_get_hardware_provider(mech.cm_type, 4987 CRYPTO_OPS_OFFSET(key_ops), 4988 CRYPTO_KEY_OFFSET(key_generate), sp->sd_provider, 4989 &real_provider)) != CRYPTO_SUCCESS) { 4990 goto release_minor; 4991 } 4992 4993 count = STRUCT_FGET(generate_key, gk_count); 4994 attributes = STRUCT_FGETP(generate_key, gk_attributes); 4995 if (!copyin_attributes(mode, count, attributes, &k_attrs, 4996 &k_attrs_size, NULL, &rv, &error, &key_rctl_bytes, carry, B_TRUE, 4997 &key_projp)) { 4998 goto release_minor; 4999 } 5000 5001 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_GENERATE, 5002 sp->sd_provider_session->ps_session, &mech, k_attrs, count, 5003 &key_handle, NULL, 0, NULL, NULL, NULL, 0); 5004 5005 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5006 5007 if (rv == CRYPTO_SUCCESS) 5008 STRUCT_FSET(generate_key, gk_handle, key_handle); 5009 5010 release_minor: 5011 mutex_enter(&crypto_rctl_lock); 5012 if (mech_rctl_bytes != 0) 5013 CRYPTO_DECREMENT_RCTL(mech_rctl_bytes, mech_projp); 5014 if (key_rctl_bytes != 0) 5015 CRYPTO_DECREMENT_RCTL(key_rctl_bytes, key_projp); 5016 mutex_exit(&crypto_rctl_lock); 5017 5018 if (k_attrs != NULL) 5019 kmem_free(k_attrs, k_attrs_size); 5020 5021 if (error != 0) 5022 goto out; 5023 5024 STRUCT_FSET(generate_key, gk_return_value, rv); 5025 if (copyout(STRUCT_BUF(generate_key), arg, 5026 STRUCT_SIZE(generate_key)) != 0) { 5027 if (rv == CRYPTO_SUCCESS) { 5028 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 5029 KCF_OP_OBJECT_DESTROY, 5030 sp->sd_provider_session->ps_session, key_handle, 5031 NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 5032 5033 (void) kcf_submit_request(real_provider, NULL, 5034 NULL, ¶ms, B_FALSE); 5035 5036 error = EFAULT; 5037 } 5038 } 5039 out: 5040 if (sp != NULL) 5041 CRYPTO_SESSION_RELE(sp); 5042 crypto_release_minor(cm); 5043 return (error); 5044 } 5045 5046 /* ARGSUSED */ 5047 static int 5048 object_generate_key_pair(dev_t dev, caddr_t arg, int mode, int *rval) 5049 { 5050 STRUCT_DECL(crypto_object_generate_key_pair, generate_key_pair); 5051 kproject_t *pub_projp, *pri_projp, *mech_projp; 5052 kcf_provider_desc_t *real_provider; 5053 kcf_req_params_t params; 5054 crypto_mechanism_t mech; 5055 crypto_object_attribute_t *k_pub_attrs = NULL; 5056 crypto_object_attribute_t *k_pri_attrs = NULL; 5057 crypto_session_id_t session_id; 5058 crypto_minor_t *cm; 5059 crypto_session_data_t *sp = NULL; 5060 crypto_object_id_t pub_handle; 5061 crypto_object_id_t pri_handle; 5062 caddr_t pri_attributes; 5063 caddr_t pub_attributes; 5064 size_t k_pub_attrs_size, k_pri_attrs_size; 5065 size_t mech_rctl_bytes = 0; 5066 size_t pub_rctl_bytes = 0; 5067 size_t pri_rctl_bytes = 0; 5068 size_t carry; 5069 uint_t pub_count; 5070 uint_t pri_count; 5071 int error = 0; 5072 int rv; 5073 5074 STRUCT_INIT(generate_key_pair, mode); 5075 5076 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 5077 cmn_err(CE_WARN, 5078 "object_generate_key_pair: failed holding minor"); 5079 return (ENXIO); 5080 } 5081 5082 if (copyin(arg, STRUCT_BUF(generate_key_pair), 5083 STRUCT_SIZE(generate_key_pair)) != 0) { 5084 crypto_release_minor(cm); 5085 return (EFAULT); 5086 } 5087 5088 session_id = STRUCT_FGET(generate_key_pair, kp_session); 5089 5090 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 5091 goto release_minor; 5092 } 5093 5094 if (!copyin_mech(mode, STRUCT_FADDR(generate_key_pair, kp_mechanism), 5095 &mech, &mech_rctl_bytes, &carry, &rv, &error, &mech_projp)) { 5096 goto release_minor; 5097 } 5098 5099 if ((rv = kcf_get_hardware_provider(mech.cm_type, 5100 CRYPTO_OPS_OFFSET(key_ops), 5101 CRYPTO_KEY_OFFSET(key_generate_pair), sp->sd_provider, 5102 &real_provider)) != CRYPTO_SUCCESS) { 5103 goto release_minor; 5104 } 5105 5106 pub_count = STRUCT_FGET(generate_key_pair, kp_public_count); 5107 pri_count = STRUCT_FGET(generate_key_pair, kp_private_count); 5108 5109 pub_attributes = STRUCT_FGETP(generate_key_pair, kp_public_attributes); 5110 if (!copyin_attributes(mode, pub_count, pub_attributes, &k_pub_attrs, 5111 &k_pub_attrs_size, NULL, &rv, &error, &pub_rctl_bytes, carry, 5112 B_TRUE, &pub_projp)) { 5113 goto release_minor; 5114 } 5115 5116 pri_attributes = STRUCT_FGETP(generate_key_pair, kp_private_attributes); 5117 if (!copyin_attributes(mode, pri_count, pri_attributes, &k_pri_attrs, 5118 &k_pri_attrs_size, NULL, &rv, &error, &pri_rctl_bytes, 0, 5119 B_TRUE, &pri_projp)) { 5120 goto release_minor; 5121 } 5122 5123 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_GENERATE_PAIR, 5124 sp->sd_provider_session->ps_session, &mech, k_pub_attrs, 5125 pub_count, &pub_handle, k_pri_attrs, pri_count, &pri_handle, 5126 NULL, NULL, 0); 5127 5128 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5129 5130 if (rv == CRYPTO_SUCCESS) { 5131 STRUCT_FSET(generate_key_pair, kp_public_handle, pub_handle); 5132 STRUCT_FSET(generate_key_pair, kp_private_handle, pri_handle); 5133 } 5134 5135 release_minor: 5136 mutex_enter(&crypto_rctl_lock); 5137 if (mech_rctl_bytes != 0) 5138 CRYPTO_DECREMENT_RCTL(mech_rctl_bytes, mech_projp); 5139 if (pub_rctl_bytes != 0) 5140 CRYPTO_DECREMENT_RCTL(pub_rctl_bytes, pub_projp); 5141 if (pri_rctl_bytes != 0) 5142 CRYPTO_DECREMENT_RCTL(pri_rctl_bytes, pri_projp); 5143 mutex_exit(&crypto_rctl_lock); 5144 5145 if (k_pub_attrs != NULL) 5146 kmem_free(k_pub_attrs, k_pub_attrs_size); 5147 5148 if (k_pri_attrs != NULL) 5149 kmem_free(k_pri_attrs, k_pri_attrs_size); 5150 5151 if (error != 0) 5152 goto out; 5153 5154 STRUCT_FSET(generate_key_pair, kp_return_value, rv); 5155 if (copyout(STRUCT_BUF(generate_key_pair), arg, 5156 STRUCT_SIZE(generate_key_pair)) != 0) { 5157 if (rv == CRYPTO_SUCCESS) { 5158 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 5159 KCF_OP_OBJECT_DESTROY, 5160 sp->sd_provider_session->ps_session, pub_handle, 5161 NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 5162 5163 (void) kcf_submit_request(real_provider, NULL, 5164 NULL, ¶ms, B_FALSE); 5165 5166 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 5167 KCF_OP_OBJECT_DESTROY, 5168 sp->sd_provider_session->ps_session, pri_handle, 5169 NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 5170 5171 (void) kcf_submit_request(real_provider, NULL, 5172 NULL, ¶ms, B_FALSE); 5173 5174 error = EFAULT; 5175 } 5176 } 5177 out: 5178 if (sp != NULL) 5179 CRYPTO_SESSION_RELE(sp); 5180 crypto_release_minor(cm); 5181 return (error); 5182 } 5183 5184 /* ARGSUSED */ 5185 static int 5186 object_wrap_key(dev_t dev, caddr_t arg, int mode, int *rval) 5187 { 5188 STRUCT_DECL(crypto_object_wrap_key, wrap_key); 5189 kproject_t *mech_projp, *key_projp, *wrapped_key_projp; 5190 kcf_provider_desc_t *real_provider; 5191 kcf_req_params_t params; 5192 crypto_mechanism_t mech; 5193 crypto_key_t key; 5194 crypto_session_id_t session_id; 5195 crypto_minor_t *cm; 5196 crypto_session_data_t *sp; 5197 crypto_object_id_t handle; 5198 size_t mech_rctl_bytes = 0, key_rctl_bytes = 0; 5199 size_t wrapped_key_rctl_bytes = 0; 5200 size_t carry; 5201 size_t wrapped_key_len, new_wrapped_key_len; 5202 uchar_t *wrapped_key = NULL; 5203 char *wrapped_key_buffer; 5204 int error = 0; 5205 int rv; 5206 5207 STRUCT_INIT(wrap_key, mode); 5208 5209 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 5210 cmn_err(CE_WARN, "object_wrap_key: failed holding minor"); 5211 return (ENXIO); 5212 } 5213 5214 if (copyin(arg, STRUCT_BUF(wrap_key), STRUCT_SIZE(wrap_key)) != 0) { 5215 crypto_release_minor(cm); 5216 return (EFAULT); 5217 } 5218 5219 bzero(&key, sizeof (crypto_key_t)); 5220 5221 session_id = STRUCT_FGET(wrap_key, wk_session); 5222 5223 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 5224 goto release_minor; 5225 } 5226 5227 if (!copyin_mech(mode, STRUCT_FADDR(wrap_key, wk_mechanism), 5228 &mech, &mech_rctl_bytes, &carry, &rv, &error, &mech_projp)) { 5229 goto out; 5230 } 5231 5232 if ((rv = kcf_get_hardware_provider(mech.cm_type, 5233 CRYPTO_OPS_OFFSET(key_ops), 5234 CRYPTO_KEY_OFFSET(key_wrap), sp->sd_provider, 5235 &real_provider)) != CRYPTO_SUCCESS) { 5236 goto out; 5237 } 5238 5239 if (!copyin_key(mode, STRUCT_FADDR(wrap_key, wk_wrapping_key), &key, 5240 &key_rctl_bytes, &rv, &error, carry, &key_projp)) { 5241 goto out; 5242 } 5243 5244 wrapped_key_len = STRUCT_FGET(wrap_key, wk_wrapped_key_len); 5245 5246 /* 5247 * Don't allocate output buffer unless both buffer pointer and 5248 * buffer length are not NULL or 0 (length). 5249 */ 5250 wrapped_key_buffer = STRUCT_FGETP(wrap_key, wk_wrapped_key); 5251 if (wrapped_key_buffer == NULL || wrapped_key_len == 0) { 5252 wrapped_key_len = 0; 5253 } 5254 5255 if (wrapped_key_len > crypto_max_buffer_len) { 5256 cmn_err(CE_NOTE, "object_wrap_key: buffer greater than %ld " 5257 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 5258 rv = CRYPTO_ARGUMENTS_BAD; 5259 goto out; 5260 } 5261 5262 if ((rv = crypto_buffer_check(wrapped_key_len, 5263 &wrapped_key_projp)) != CRYPTO_SUCCESS) { 5264 goto out; 5265 } 5266 5267 /* new_wrapped_key_len can be modified by the provider */ 5268 wrapped_key_rctl_bytes = new_wrapped_key_len = wrapped_key_len; 5269 wrapped_key = kmem_alloc(wrapped_key_len, KM_SLEEP); 5270 5271 handle = STRUCT_FGET(wrap_key, wk_object_handle); 5272 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_WRAP, 5273 sp->sd_provider_session->ps_session, &mech, NULL, 0, &handle, 5274 NULL, 0, NULL, &key, wrapped_key, &new_wrapped_key_len); 5275 5276 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5277 5278 if (rv == CRYPTO_SUCCESS) { 5279 if (wrapped_key_len != 0 && copyout(wrapped_key, 5280 wrapped_key_buffer, new_wrapped_key_len) != 0) { 5281 error = EFAULT; 5282 } 5283 STRUCT_FSET(wrap_key, wk_wrapped_key_len, new_wrapped_key_len); 5284 } 5285 5286 if (rv == CRYPTO_BUFFER_TOO_SMALL) { 5287 /* 5288 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1 5289 * of section 11.2 of the pkcs11 spec. We catch it here and 5290 * provide the correct pkcs11 return value. 5291 */ 5292 if (STRUCT_FGETP(wrap_key, wk_wrapped_key) == NULL) 5293 rv = CRYPTO_SUCCESS; 5294 STRUCT_FSET(wrap_key, wk_wrapped_key_len, new_wrapped_key_len); 5295 } 5296 out: 5297 CRYPTO_SESSION_RELE(sp); 5298 5299 release_minor: 5300 mutex_enter(&crypto_rctl_lock); 5301 if (mech_rctl_bytes != 0) 5302 CRYPTO_DECREMENT_RCTL(mech_rctl_bytes, mech_projp); 5303 if (key_rctl_bytes != 0) 5304 CRYPTO_DECREMENT_RCTL(key_rctl_bytes, key_projp); 5305 if (wrapped_key_rctl_bytes != 0) 5306 CRYPTO_DECREMENT_RCTL(wrapped_key_rctl_bytes, 5307 wrapped_key_projp); 5308 mutex_exit(&crypto_rctl_lock); 5309 crypto_release_minor(cm); 5310 5311 if (wrapped_key != NULL) 5312 kmem_free(wrapped_key, wrapped_key_len); 5313 5314 free_crypto_key(&key); 5315 5316 if (error != 0) 5317 return (error); 5318 5319 STRUCT_FSET(wrap_key, wk_return_value, rv); 5320 if (copyout(STRUCT_BUF(wrap_key), arg, STRUCT_SIZE(wrap_key)) != 0) { 5321 return (EFAULT); 5322 } 5323 return (0); 5324 } 5325 5326 /* ARGSUSED */ 5327 static int 5328 object_unwrap_key(dev_t dev, caddr_t arg, int mode, int *rval) 5329 { 5330 STRUCT_DECL(crypto_object_unwrap_key, unwrap_key); 5331 kproject_t *mech_projp, *unwrapping_key_projp, *wrapped_key_projp, 5332 *k_attrs_projp; 5333 kcf_provider_desc_t *real_provider; 5334 kcf_req_params_t params; 5335 crypto_mechanism_t mech; 5336 crypto_key_t unwrapping_key; 5337 crypto_session_id_t session_id; 5338 crypto_minor_t *cm; 5339 crypto_session_data_t *sp = NULL; 5340 crypto_object_id_t handle; 5341 crypto_object_attribute_t *k_attrs = NULL; 5342 size_t k_attrs_size; 5343 size_t mech_rctl_bytes = 0, unwrapping_key_rctl_bytes = 0; 5344 size_t wrapped_key_rctl_bytes = 0, k_attrs_rctl_bytes = 0; 5345 size_t carry; 5346 size_t wrapped_key_len; 5347 uchar_t *wrapped_key = NULL; 5348 int error = 0; 5349 int rv; 5350 uint_t count; 5351 caddr_t uk_attributes; 5352 5353 STRUCT_INIT(unwrap_key, mode); 5354 5355 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 5356 cmn_err(CE_WARN, "object_unwrap_key: failed holding minor"); 5357 return (ENXIO); 5358 } 5359 5360 if (copyin(arg, STRUCT_BUF(unwrap_key), STRUCT_SIZE(unwrap_key)) != 0) { 5361 crypto_release_minor(cm); 5362 return (EFAULT); 5363 } 5364 5365 bzero(&unwrapping_key, sizeof (unwrapping_key)); 5366 5367 session_id = STRUCT_FGET(unwrap_key, uk_session); 5368 5369 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 5370 goto release_minor; 5371 } 5372 5373 if (!copyin_mech(mode, STRUCT_FADDR(unwrap_key, uk_mechanism), 5374 &mech, &mech_rctl_bytes, &carry, &rv, &error, &mech_projp)) { 5375 goto release_minor; 5376 } 5377 5378 if ((rv = kcf_get_hardware_provider(mech.cm_type, 5379 CRYPTO_OPS_OFFSET(key_ops), 5380 CRYPTO_KEY_OFFSET(key_unwrap), sp->sd_provider, 5381 &real_provider)) != CRYPTO_SUCCESS) { 5382 goto release_minor; 5383 } 5384 5385 if (!copyin_key(mode, STRUCT_FADDR(unwrap_key, uk_unwrapping_key), 5386 &unwrapping_key, &unwrapping_key_rctl_bytes, &rv, &error, carry, 5387 &unwrapping_key_projp)) { 5388 goto release_minor; 5389 } 5390 5391 count = STRUCT_FGET(unwrap_key, uk_count); 5392 uk_attributes = STRUCT_FGETP(unwrap_key, uk_attributes); 5393 if (!copyin_attributes(mode, count, uk_attributes, &k_attrs, 5394 &k_attrs_size, NULL, &rv, &error, &k_attrs_rctl_bytes, 0, B_TRUE, 5395 &k_attrs_projp)) { 5396 goto release_minor; 5397 } 5398 5399 wrapped_key_len = STRUCT_FGET(unwrap_key, uk_wrapped_key_len); 5400 if (wrapped_key_len > crypto_max_buffer_len) { 5401 cmn_err(CE_NOTE, "object_unwrap_key: buffer greater than %ld " 5402 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 5403 rv = CRYPTO_ARGUMENTS_BAD; 5404 goto release_minor; 5405 } 5406 5407 if ((rv = crypto_buffer_check(wrapped_key_len, &wrapped_key_projp)) 5408 != CRYPTO_SUCCESS) { 5409 goto release_minor; 5410 } 5411 wrapped_key_rctl_bytes = wrapped_key_len; 5412 wrapped_key = kmem_alloc(wrapped_key_len, KM_SLEEP); 5413 5414 if (wrapped_key_len != 0 && copyin(STRUCT_FGETP(unwrap_key, 5415 uk_wrapped_key), wrapped_key, wrapped_key_len) != 0) { 5416 error = EFAULT; 5417 goto release_minor; 5418 } 5419 5420 /* wrapped_key_len is not modified by the unwrap operation */ 5421 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_UNWRAP, 5422 sp->sd_provider_session->ps_session, &mech, k_attrs, count, &handle, 5423 NULL, 0, NULL, &unwrapping_key, wrapped_key, &wrapped_key_len); 5424 5425 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5426 5427 if (rv == CRYPTO_SUCCESS) 5428 STRUCT_FSET(unwrap_key, uk_object_handle, handle); 5429 5430 release_minor: 5431 mutex_enter(&crypto_rctl_lock); 5432 if (mech_rctl_bytes != 0) 5433 CRYPTO_DECREMENT_RCTL(mech_rctl_bytes, mech_projp); 5434 if (unwrapping_key_rctl_bytes != 0) 5435 CRYPTO_DECREMENT_RCTL(unwrapping_key_rctl_bytes, 5436 unwrapping_key_projp); 5437 if (wrapped_key_rctl_bytes != 0) 5438 CRYPTO_DECREMENT_RCTL(wrapped_key_rctl_bytes, 5439 wrapped_key_projp); 5440 if (k_attrs_rctl_bytes != 0) 5441 CRYPTO_DECREMENT_RCTL(k_attrs_rctl_bytes, k_attrs_projp); 5442 mutex_exit(&crypto_rctl_lock); 5443 5444 if (k_attrs != NULL) 5445 kmem_free(k_attrs, k_attrs_size); 5446 5447 if (wrapped_key != NULL) 5448 kmem_free(wrapped_key, wrapped_key_len); 5449 5450 free_crypto_key(&unwrapping_key); 5451 5452 if (error != 0) 5453 goto out; 5454 5455 STRUCT_FSET(unwrap_key, uk_return_value, rv); 5456 if (copyout(STRUCT_BUF(unwrap_key), arg, 5457 STRUCT_SIZE(unwrap_key)) != 0) { 5458 if (rv == CRYPTO_SUCCESS) { 5459 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 5460 KCF_OP_OBJECT_DESTROY, 5461 sp->sd_provider_session->ps_session, handle, 5462 NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 5463 5464 (void) kcf_submit_request(real_provider, NULL, 5465 NULL, ¶ms, B_FALSE); 5466 5467 error = EFAULT; 5468 } 5469 } 5470 out: 5471 if (sp != NULL) 5472 CRYPTO_SESSION_RELE(sp); 5473 crypto_release_minor(cm); 5474 return (error); 5475 } 5476 5477 /* ARGSUSED */ 5478 static int 5479 object_derive_key(dev_t dev, caddr_t arg, int mode, int *rval) 5480 { 5481 STRUCT_DECL(crypto_derive_key, derive_key); 5482 kproject_t *key_projp, *mech_projp, *attributes_projp; 5483 kcf_provider_desc_t *real_provider; 5484 kcf_req_params_t params; 5485 crypto_object_attribute_t *k_attrs = NULL; 5486 crypto_mechanism_t mech; 5487 crypto_key_t base_key; 5488 crypto_session_id_t session_id; 5489 crypto_minor_t *cm; 5490 crypto_session_data_t *sp = NULL; 5491 crypto_object_id_t handle; 5492 size_t k_attrs_size; 5493 size_t key_rctl_bytes = 0, mech_rctl_bytes = 0; 5494 size_t attributes_rctl_bytes = 0; 5495 size_t carry; 5496 caddr_t attributes; 5497 uint_t count; 5498 int error = 0; 5499 int rv; 5500 5501 STRUCT_INIT(derive_key, mode); 5502 5503 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 5504 cmn_err(CE_WARN, "object_derive_key: failed holding minor"); 5505 return (ENXIO); 5506 } 5507 5508 if (copyin(arg, STRUCT_BUF(derive_key), STRUCT_SIZE(derive_key)) != 0) { 5509 crypto_release_minor(cm); 5510 return (EFAULT); 5511 } 5512 5513 bzero(&base_key, sizeof (base_key)); 5514 5515 session_id = STRUCT_FGET(derive_key, dk_session); 5516 5517 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 5518 goto release_minor; 5519 } 5520 5521 if (!copyin_mech(mode, STRUCT_FADDR(derive_key, dk_mechanism), 5522 &mech, &mech_rctl_bytes, &carry, &rv, &error, &mech_projp)) { 5523 goto release_minor; 5524 } 5525 5526 if ((rv = kcf_get_hardware_provider(mech.cm_type, 5527 CRYPTO_OPS_OFFSET(key_ops), 5528 CRYPTO_KEY_OFFSET(key_derive), sp->sd_provider, 5529 &real_provider)) != CRYPTO_SUCCESS) { 5530 goto release_minor; 5531 } 5532 5533 if (!copyin_key(mode, STRUCT_FADDR(derive_key, dk_base_key), 5534 &base_key, &key_rctl_bytes, &rv, &error, carry, &key_projp)) { 5535 goto release_minor; 5536 } 5537 5538 count = STRUCT_FGET(derive_key, dk_count); 5539 5540 attributes = STRUCT_FGETP(derive_key, dk_attributes); 5541 if (!copyin_attributes(mode, count, attributes, &k_attrs, 5542 &k_attrs_size, NULL, &rv, &error, &attributes_rctl_bytes, 0, B_TRUE, 5543 &attributes_projp)) { 5544 goto release_minor; 5545 } 5546 5547 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_DERIVE, 5548 sp->sd_provider_session->ps_session, &mech, k_attrs, count, 5549 &handle, NULL, 0, NULL, &base_key, NULL, NULL); 5550 5551 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5552 5553 if (rv == CRYPTO_SUCCESS) 5554 STRUCT_FSET(derive_key, dk_object_handle, handle); 5555 5556 release_minor: 5557 mutex_enter(&crypto_rctl_lock); 5558 if (mech_rctl_bytes != 0) 5559 CRYPTO_DECREMENT_RCTL(mech_rctl_bytes, mech_projp); 5560 if (key_rctl_bytes != 0) 5561 CRYPTO_DECREMENT_RCTL(key_rctl_bytes, key_projp); 5562 if (attributes_rctl_bytes != 0) 5563 CRYPTO_DECREMENT_RCTL(attributes_rctl_bytes, attributes_projp); 5564 mutex_exit(&crypto_rctl_lock); 5565 5566 if (k_attrs != NULL) 5567 kmem_free(k_attrs, k_attrs_size); 5568 5569 free_crypto_key(&base_key); 5570 5571 if (error != 0) 5572 goto out; 5573 5574 STRUCT_FSET(derive_key, dk_return_value, rv); 5575 if (copyout(STRUCT_BUF(derive_key), arg, 5576 STRUCT_SIZE(derive_key)) != 0) { 5577 if (rv == CRYPTO_SUCCESS) { 5578 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 5579 KCF_OP_OBJECT_DESTROY, 5580 sp->sd_provider_session->ps_session, handle, 5581 NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 5582 5583 (void) kcf_submit_request(real_provider, NULL, 5584 NULL, ¶ms, B_FALSE); 5585 5586 error = EFAULT; 5587 } 5588 } 5589 out: 5590 if (sp != NULL) 5591 CRYPTO_SESSION_RELE(sp); 5592 crypto_release_minor(cm); 5593 return (error); 5594 } 5595 5596 /* ARGSUSED */ 5597 static int 5598 crypto_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c, 5599 int *rval) 5600 { 5601 #define ARG ((caddr_t)arg) 5602 5603 switch (cmd) { 5604 case CRYPTO_GET_FUNCTION_LIST: 5605 return (get_function_list(dev, ARG, mode, rval)); 5606 5607 case CRYPTO_GET_MECHANISM_NUMBER: 5608 return (get_mechanism_number(dev, ARG, mode, rval)); 5609 5610 case CRYPTO_GET_PROVIDER_LIST: 5611 return (get_provider_list(dev, ARG, mode, rval)); 5612 5613 case CRYPTO_GET_PROVIDER_INFO: 5614 return (get_provider_info(dev, ARG, mode, rval)); 5615 5616 case CRYPTO_GET_PROVIDER_MECHANISMS: 5617 return (get_provider_mechanisms(dev, ARG, mode, rval)); 5618 5619 case CRYPTO_GET_PROVIDER_MECHANISM_INFO: 5620 return (get_provider_mechanism_info(dev, ARG, mode, rval)); 5621 5622 case CRYPTO_OPEN_SESSION: 5623 return (open_session(dev, ARG, mode, rval)); 5624 5625 case CRYPTO_CLOSE_SESSION: 5626 return (close_session(dev, ARG, mode, rval)); 5627 5628 case CRYPTO_ENCRYPT_INIT: 5629 return (encrypt_init(dev, ARG, mode, rval)); 5630 5631 case CRYPTO_DECRYPT_INIT: 5632 return (decrypt_init(dev, ARG, mode, rval)); 5633 5634 case CRYPTO_ENCRYPT: 5635 return (encrypt(dev, ARG, mode, rval)); 5636 5637 case CRYPTO_DECRYPT: 5638 return (decrypt(dev, ARG, mode, rval)); 5639 5640 case CRYPTO_ENCRYPT_UPDATE: 5641 return (encrypt_update(dev, ARG, mode, rval)); 5642 5643 case CRYPTO_DECRYPT_UPDATE: 5644 return (decrypt_update(dev, ARG, mode, rval)); 5645 5646 case CRYPTO_ENCRYPT_FINAL: 5647 return (encrypt_final(dev, ARG, mode, rval)); 5648 5649 case CRYPTO_DECRYPT_FINAL: 5650 return (decrypt_final(dev, ARG, mode, rval)); 5651 5652 case CRYPTO_DIGEST_INIT: 5653 return (digest_init(dev, ARG, mode, rval)); 5654 5655 case CRYPTO_DIGEST: 5656 return (digest(dev, ARG, mode, rval)); 5657 5658 case CRYPTO_DIGEST_UPDATE: 5659 return (digest_update(dev, ARG, mode, rval)); 5660 5661 case CRYPTO_DIGEST_KEY: 5662 return (digest_key(dev, ARG, mode, rval)); 5663 5664 case CRYPTO_DIGEST_FINAL: 5665 return (digest_final(dev, ARG, mode, rval)); 5666 5667 case CRYPTO_SIGN_INIT: 5668 return (sign_init(dev, ARG, mode, rval)); 5669 5670 case CRYPTO_SIGN: 5671 return (sign(dev, ARG, mode, rval)); 5672 5673 case CRYPTO_SIGN_UPDATE: 5674 return (sign_update(dev, ARG, mode, rval)); 5675 5676 case CRYPTO_SIGN_FINAL: 5677 return (sign_final(dev, ARG, mode, rval)); 5678 5679 case CRYPTO_SIGN_RECOVER_INIT: 5680 return (sign_recover_init(dev, ARG, mode, rval)); 5681 5682 case CRYPTO_SIGN_RECOVER: 5683 return (sign_recover(dev, ARG, mode, rval)); 5684 5685 case CRYPTO_VERIFY_INIT: 5686 return (verify_init(dev, ARG, mode, rval)); 5687 5688 case CRYPTO_VERIFY: 5689 return (verify(dev, ARG, mode, rval)); 5690 5691 case CRYPTO_VERIFY_UPDATE: 5692 return (verify_update(dev, ARG, mode, rval)); 5693 5694 case CRYPTO_VERIFY_FINAL: 5695 return (verify_final(dev, ARG, mode, rval)); 5696 5697 case CRYPTO_VERIFY_RECOVER_INIT: 5698 return (verify_recover_init(dev, ARG, mode, rval)); 5699 5700 case CRYPTO_VERIFY_RECOVER: 5701 return (verify_recover(dev, ARG, mode, rval)); 5702 5703 case CRYPTO_SET_PIN: 5704 return (set_pin(dev, ARG, mode, rval)); 5705 5706 case CRYPTO_LOGIN: 5707 return (login(dev, ARG, mode, rval)); 5708 5709 case CRYPTO_LOGOUT: 5710 return (logout(dev, ARG, mode, rval)); 5711 5712 case CRYPTO_SEED_RANDOM: 5713 return (seed_random(dev, ARG, mode, rval)); 5714 5715 case CRYPTO_GENERATE_RANDOM: 5716 return (generate_random(dev, ARG, mode, rval)); 5717 5718 case CRYPTO_OBJECT_CREATE: 5719 return (object_create(dev, ARG, mode, rval)); 5720 5721 case CRYPTO_OBJECT_COPY: 5722 return (object_copy(dev, ARG, mode, rval)); 5723 5724 case CRYPTO_OBJECT_DESTROY: 5725 return (object_destroy(dev, ARG, mode, rval)); 5726 5727 case CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE: 5728 return (object_get_attribute_value(dev, ARG, mode, rval)); 5729 5730 case CRYPTO_OBJECT_GET_SIZE: 5731 return (object_get_size(dev, ARG, mode, rval)); 5732 5733 case CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE: 5734 return (object_set_attribute_value(dev, ARG, mode, rval)); 5735 5736 case CRYPTO_OBJECT_FIND_INIT: 5737 return (object_find_init(dev, ARG, mode, rval)); 5738 5739 case CRYPTO_OBJECT_FIND_UPDATE: 5740 return (object_find_update(dev, ARG, mode, rval)); 5741 5742 case CRYPTO_OBJECT_FIND_FINAL: 5743 return (object_find_final(dev, ARG, mode, rval)); 5744 5745 case CRYPTO_GENERATE_KEY: 5746 return (object_generate_key(dev, ARG, mode, rval)); 5747 5748 case CRYPTO_GENERATE_KEY_PAIR: 5749 return (object_generate_key_pair(dev, ARG, mode, rval)); 5750 5751 case CRYPTO_WRAP_KEY: 5752 return (object_wrap_key(dev, ARG, mode, rval)); 5753 5754 case CRYPTO_UNWRAP_KEY: 5755 return (object_unwrap_key(dev, ARG, mode, rval)); 5756 5757 case CRYPTO_DERIVE_KEY: 5758 return (object_derive_key(dev, ARG, mode, rval)); 5759 } 5760 return (EINVAL); 5761 } 5762 5763 /* 5764 * Check for the project.max-crypto-memory resource control. 5765 */ 5766 static int 5767 crypto_buffer_check(size_t need, kproject_t **projp) 5768 { 5769 ASSERT(projp != NULL); 5770 5771 if (need == 0) 5772 return (CRYPTO_SUCCESS); 5773 5774 mutex_enter(&curproc->p_lock); 5775 mutex_enter(&crypto_rctl_lock); 5776 if (rctl_test(rc_project_crypto_mem, 5777 curproc->p_task->tk_proj->kpj_rctls, curproc, need, 0) & RCT_DENY) { 5778 mutex_exit(&crypto_rctl_lock); 5779 mutex_exit(&curproc->p_lock); 5780 return (CRYPTO_HOST_MEMORY); 5781 } 5782 5783 curproc->p_task->tk_proj->kpj_data.kpd_crypto_mem += need; 5784 mutex_exit(&crypto_rctl_lock); 5785 5786 (void) project_hold(curproc->p_task->tk_proj); 5787 *projp = curproc->p_task->tk_proj; 5788 mutex_exit(&curproc->p_lock); 5789 return (CRYPTO_SUCCESS); 5790 } 5791