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