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