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