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