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