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