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