17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 572eff6e2Smcpowers * Common Development and Distribution License (the "License"). 672eff6e2Smcpowers * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22c630c2c5SVladimir Kotal * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * The ioctl interface for cryptographic commands. 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <sys/types.h> 317c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 327c478bd9Sstevel@tonic-gate #include <sys/conf.h> 337c478bd9Sstevel@tonic-gate #include <sys/stat.h> 347c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 357c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 367c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 377c478bd9Sstevel@tonic-gate #include <sys/errno.h> 387c478bd9Sstevel@tonic-gate #include <sys/ksynch.h> 397c478bd9Sstevel@tonic-gate #include <sys/file.h> 407c478bd9Sstevel@tonic-gate #include <sys/open.h> 417c478bd9Sstevel@tonic-gate #include <sys/cred.h> 427c478bd9Sstevel@tonic-gate #include <sys/proc.h> 437c478bd9Sstevel@tonic-gate #include <sys/task.h> 447c478bd9Sstevel@tonic-gate #include <sys/mkdev.h> 457c478bd9Sstevel@tonic-gate #include <sys/model.h> 467c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 477c478bd9Sstevel@tonic-gate #include <sys/crypto/common.h> 487c478bd9Sstevel@tonic-gate #include <sys/crypto/api.h> 497c478bd9Sstevel@tonic-gate #include <sys/crypto/impl.h> 507c478bd9Sstevel@tonic-gate #include <sys/crypto/sched_impl.h> 517c478bd9Sstevel@tonic-gate #include <sys/crypto/ioctl.h> 527c478bd9Sstevel@tonic-gate 534a5b2e70Shaimay extern int kcf_des3_threshold; 544a5b2e70Shaimay extern int kcf_aes_threshold; 554a5b2e70Shaimay extern int kcf_rc4_threshold; 564a5b2e70Shaimay extern int kcf_md5_threshold; 574a5b2e70Shaimay extern int kcf_sha1_threshold; 584a5b2e70Shaimay 597c478bd9Sstevel@tonic-gate /* 607c478bd9Sstevel@tonic-gate * Locking notes: 617c478bd9Sstevel@tonic-gate * 62ef56a3c5SKrishna Yenduri * crypto_locks protects the global array of minor structures. 63ef56a3c5SKrishna Yenduri * crypto_locks is an array of locks indexed by the cpuid. A reader needs 64ef56a3c5SKrishna Yenduri * to hold a single lock while a writer needs to hold all locks. 65ef56a3c5SKrishna Yenduri * krwlock_t is not an option here because the hold time 66ef56a3c5SKrishna Yenduri * is very small for these locks. 677c478bd9Sstevel@tonic-gate * 68ef56a3c5SKrishna Yenduri * The fields in the minor structure are protected by the cm_lock member 69ef56a3c5SKrishna Yenduri * of the minor structure. The cm_cv is used to signal decrements 70ef56a3c5SKrishna Yenduri * in the cm_refcnt, and is used with the cm_lock. 71ef56a3c5SKrishna Yenduri * 72ef56a3c5SKrishna Yenduri * The locking order is crypto_locks followed by cm_lock. 737c478bd9Sstevel@tonic-gate */ 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate /* 767c478bd9Sstevel@tonic-gate * DDI entry points. 777c478bd9Sstevel@tonic-gate */ 787c478bd9Sstevel@tonic-gate static int crypto_attach(dev_info_t *, ddi_attach_cmd_t); 797c478bd9Sstevel@tonic-gate static int crypto_detach(dev_info_t *, ddi_detach_cmd_t); 807c478bd9Sstevel@tonic-gate static int crypto_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 817c478bd9Sstevel@tonic-gate static int crypto_open(dev_t *, int, int, cred_t *); 827c478bd9Sstevel@tonic-gate static int crypto_close(dev_t, int, int, cred_t *); 837c478bd9Sstevel@tonic-gate static int crypto_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 847c478bd9Sstevel@tonic-gate 85894b2776Smcpowers static int cipher_init(dev_t, caddr_t, int, int (*)(crypto_provider_t, 867c478bd9Sstevel@tonic-gate crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, 877c478bd9Sstevel@tonic-gate crypto_ctx_template_t, crypto_context_t *, crypto_call_req_t *)); 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate static int common_digest(dev_t, caddr_t, int, int (*)(crypto_context_t, 907c478bd9Sstevel@tonic-gate crypto_data_t *, crypto_data_t *, crypto_call_req_t *)); 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate static int cipher(dev_t, caddr_t, int, int (*)(crypto_context_t, 937c478bd9Sstevel@tonic-gate crypto_data_t *, crypto_data_t *, crypto_call_req_t *)); 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate static int cipher_update(dev_t, caddr_t, int, int (*)(crypto_context_t, 967c478bd9Sstevel@tonic-gate crypto_data_t *, crypto_data_t *, crypto_call_req_t *)); 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate static int common_final(dev_t, caddr_t, int, int (*)(crypto_context_t, 997c478bd9Sstevel@tonic-gate crypto_data_t *, crypto_call_req_t *)); 1007c478bd9Sstevel@tonic-gate 101894b2776Smcpowers static int sign_verify_init(dev_t, caddr_t, int, int (*)(crypto_provider_t, 1027c478bd9Sstevel@tonic-gate crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, 1037c478bd9Sstevel@tonic-gate crypto_ctx_template_t, crypto_context_t *, crypto_call_req_t *)); 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate static int sign_verify_update(dev_t dev, caddr_t arg, int mode, 1067c478bd9Sstevel@tonic-gate int (*)(crypto_context_t, crypto_data_t *, crypto_call_req_t *)); 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate static void crypto_release_provider_session(crypto_minor_t *, 1097c478bd9Sstevel@tonic-gate crypto_provider_session_t *); 110c1a9a9c3Skrishna static int crypto_buffer_check(size_t); 1117c478bd9Sstevel@tonic-gate static int crypto_free_find_ctx(crypto_session_data_t *); 1127c478bd9Sstevel@tonic-gate static int crypto_get_provider_list(crypto_minor_t *, uint_t *, 1137c478bd9Sstevel@tonic-gate crypto_provider_entry_t **, boolean_t); 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /* number of minor numbers to allocate at a time */ 1167c478bd9Sstevel@tonic-gate #define CRYPTO_MINOR_CHUNK 16 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate /* 1197c478bd9Sstevel@tonic-gate * There are two limits associated with kernel memory. The first, 1207c478bd9Sstevel@tonic-gate * CRYPTO_MAX_BUFFER_LEN, is the maximum number of bytes that can be 1217c478bd9Sstevel@tonic-gate * allocated for a single copyin/copyout buffer. The second limit is 1227c478bd9Sstevel@tonic-gate * the total number of bytes that can be allocated by a process 1237c478bd9Sstevel@tonic-gate * for copyin/copyout buffers. The latter is enforced by the 1247c478bd9Sstevel@tonic-gate * project.max-crypto-memory resource control. 1257c478bd9Sstevel@tonic-gate */ 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate #define CRYPTO_MAX_BUFFER_LEN (2 * 1024 * 1024) 1287c478bd9Sstevel@tonic-gate #define CRYPTO_MAX_FIND_COUNT 512 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate /* 1312d794da1Skrishna * We preapprove some bytes for each session to avoid making the costly 1322d794da1Skrishna * crypto_buffer_check() calls. The preapproval is done when a new session 1332d794da1Skrishna * is created and that cost is amortized over later crypto calls. 1342d794da1Skrishna * Most applications create a session and then do a bunch of crypto calls 1352d794da1Skrishna * in that session. So, they benefit from this optimization. 1362d794da1Skrishna * 1372d794da1Skrishna * Note that we may hit the project.max-crypto-memory limit a bit sooner 1382d794da1Skrishna * because of this preapproval. But it is acceptable since the preapproved 1392d794da1Skrishna * amount is insignificant compared to the default max-crypto-memory limit 1402d794da1Skrishna * which is quarter of the machine's memory. The preapproved amount is 1412d794da1Skrishna * roughly 2 * 16K(maximum SSL record size). 1427c478bd9Sstevel@tonic-gate */ 1432d794da1Skrishna #define CRYPTO_PRE_APPROVED_LIMIT (32 * 1024) 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate /* The session table grows by CRYPTO_SESSION_CHUNK increments */ 1467c478bd9Sstevel@tonic-gate #define CRYPTO_SESSION_CHUNK 100 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate size_t crypto_max_buffer_len = CRYPTO_MAX_BUFFER_LEN; 1492d794da1Skrishna size_t crypto_pre_approved_limit = CRYPTO_PRE_APPROVED_LIMIT; 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate #define INIT_RAW_CRYPTO_DATA(data, len) \ 1527c478bd9Sstevel@tonic-gate (data).cd_format = CRYPTO_DATA_RAW; \ 1537c478bd9Sstevel@tonic-gate (data).cd_raw.iov_base = kmem_alloc(len, KM_SLEEP); \ 1547c478bd9Sstevel@tonic-gate (data).cd_raw.iov_len = len; \ 1557c478bd9Sstevel@tonic-gate (data).cd_offset = 0; \ 1567c478bd9Sstevel@tonic-gate (data).cd_length = len; 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate static struct kmem_cache *crypto_session_cache; 1597c478bd9Sstevel@tonic-gate static crypto_minor_t **crypto_minors = NULL; 1607c478bd9Sstevel@tonic-gate static dev_info_t *crypto_dip = NULL; 1617c478bd9Sstevel@tonic-gate static minor_t crypto_minor_chunk = CRYPTO_MINOR_CHUNK; 1627c478bd9Sstevel@tonic-gate static minor_t crypto_minors_table_count = 0; 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate /* 1657c478bd9Sstevel@tonic-gate * Minors are started from 1 because vmem_alloc() 1667c478bd9Sstevel@tonic-gate * returns 0 in case of failure. 1677c478bd9Sstevel@tonic-gate */ 1687c478bd9Sstevel@tonic-gate static vmem_t *crypto_arena = NULL; /* Arena for device minors */ 1697c478bd9Sstevel@tonic-gate static minor_t crypto_minors_count = 0; 170ef56a3c5SKrishna Yenduri static kcf_lock_withpad_t *crypto_locks; 171ef56a3c5SKrishna Yenduri 172ef56a3c5SKrishna Yenduri #define CRYPTO_ENTER_ALL_LOCKS() \ 173ef56a3c5SKrishna Yenduri for (i = 0; i < max_ncpus; i++) \ 174ef56a3c5SKrishna Yenduri mutex_enter(&crypto_locks[i].kl_lock); 175ef56a3c5SKrishna Yenduri 176ef56a3c5SKrishna Yenduri #define CRYPTO_EXIT_ALL_LOCKS() \ 177ef56a3c5SKrishna Yenduri for (i = 0; i < max_ncpus; i++) \ 178ef56a3c5SKrishna Yenduri mutex_exit(&crypto_locks[i].kl_lock); 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate #define RETURN_LIST B_TRUE 1817c478bd9Sstevel@tonic-gate #define DONT_RETURN_LIST B_FALSE 1827c478bd9Sstevel@tonic-gate 183894b2776Smcpowers #define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f) 1847c478bd9Sstevel@tonic-gate #define CRYPTO_RANDOM_OFFSET(f) offsetof(crypto_random_number_ops_t, f) 1857c478bd9Sstevel@tonic-gate #define CRYPTO_SESSION_OFFSET(f) offsetof(crypto_session_ops_t, f) 1867c478bd9Sstevel@tonic-gate #define CRYPTO_OBJECT_OFFSET(f) offsetof(crypto_object_ops_t, f) 1877c478bd9Sstevel@tonic-gate #define CRYPTO_PROVIDER_OFFSET(f) \ 1887c478bd9Sstevel@tonic-gate offsetof(crypto_provider_management_ops_t, f) 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate #define CRYPTO_CANCEL_CTX(spp) { \ 1917c478bd9Sstevel@tonic-gate crypto_cancel_ctx(*(spp)); \ 1927c478bd9Sstevel@tonic-gate *(spp) = NULL; \ 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate #define CRYPTO_CANCEL_ALL_CTX(sp) { \ 1967c478bd9Sstevel@tonic-gate if ((sp)->sd_digest_ctx != NULL) { \ 1977c478bd9Sstevel@tonic-gate crypto_cancel_ctx((sp)->sd_digest_ctx); \ 1987c478bd9Sstevel@tonic-gate (sp)->sd_digest_ctx = NULL; \ 1997c478bd9Sstevel@tonic-gate } \ 2007c478bd9Sstevel@tonic-gate if ((sp)->sd_encr_ctx != NULL) { \ 2017c478bd9Sstevel@tonic-gate crypto_cancel_ctx((sp)->sd_encr_ctx); \ 2027c478bd9Sstevel@tonic-gate (sp)->sd_encr_ctx = NULL; \ 2037c478bd9Sstevel@tonic-gate } \ 2047c478bd9Sstevel@tonic-gate if ((sp)->sd_decr_ctx != NULL) { \ 2057c478bd9Sstevel@tonic-gate crypto_cancel_ctx((sp)->sd_decr_ctx); \ 2067c478bd9Sstevel@tonic-gate (sp)->sd_decr_ctx = NULL; \ 2077c478bd9Sstevel@tonic-gate } \ 2087c478bd9Sstevel@tonic-gate if ((sp)->sd_sign_ctx != NULL) { \ 2097c478bd9Sstevel@tonic-gate crypto_cancel_ctx((sp)->sd_sign_ctx); \ 2107c478bd9Sstevel@tonic-gate (sp)->sd_sign_ctx = NULL; \ 2117c478bd9Sstevel@tonic-gate } \ 2127c478bd9Sstevel@tonic-gate if ((sp)->sd_verify_ctx != NULL) { \ 2137c478bd9Sstevel@tonic-gate crypto_cancel_ctx((sp)->sd_verify_ctx); \ 2147c478bd9Sstevel@tonic-gate (sp)->sd_verify_ctx = NULL; \ 2157c478bd9Sstevel@tonic-gate } \ 2167c478bd9Sstevel@tonic-gate if ((sp)->sd_sign_recover_ctx != NULL) { \ 2177c478bd9Sstevel@tonic-gate crypto_cancel_ctx((sp)->sd_sign_recover_ctx); \ 2187c478bd9Sstevel@tonic-gate (sp)->sd_sign_recover_ctx = NULL; \ 2197c478bd9Sstevel@tonic-gate } \ 2207c478bd9Sstevel@tonic-gate if ((sp)->sd_verify_recover_ctx != NULL) { \ 2217c478bd9Sstevel@tonic-gate crypto_cancel_ctx((sp)->sd_verify_recover_ctx); \ 2227c478bd9Sstevel@tonic-gate (sp)->sd_verify_recover_ctx = NULL; \ 2237c478bd9Sstevel@tonic-gate } \ 2247c478bd9Sstevel@tonic-gate } 2257c478bd9Sstevel@tonic-gate 2262d794da1Skrishna #define CRYPTO_DECREMENT_RCTL(val) if ((val) != 0) { \ 227c1a9a9c3Skrishna kproject_t *projp; \ 228c1a9a9c3Skrishna mutex_enter(&curproc->p_lock); \ 229c1a9a9c3Skrishna projp = curproc->p_task->tk_proj; \ 2307c478bd9Sstevel@tonic-gate ASSERT(projp != NULL); \ 231c1a9a9c3Skrishna mutex_enter(&(projp->kpj_data.kpd_crypto_lock)); \ 232c1a9a9c3Skrishna projp->kpj_data.kpd_crypto_mem -= (val); \ 233c1a9a9c3Skrishna mutex_exit(&(projp->kpj_data.kpd_crypto_lock)); \ 234c1a9a9c3Skrishna curproc->p_crypto_mem -= (val); \ 235c1a9a9c3Skrishna mutex_exit(&curproc->p_lock); \ 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate /* 2392d794da1Skrishna * We do not need to hold sd_lock in the macros below 2402d794da1Skrishna * as they are called after doing a get_session_ptr() which 2412d794da1Skrishna * sets the CRYPTO_SESSION_IS_BUSY flag. 2422d794da1Skrishna */ 2432d794da1Skrishna #define CRYPTO_DECREMENT_RCTL_SESSION(sp, val, rctl_chk) \ 24466761628Skrishna if (((val) != 0) && ((sp) != NULL)) { \ 2452d794da1Skrishna ASSERT(((sp)->sd_flags & CRYPTO_SESSION_IS_BUSY) != 0); \ 2462d794da1Skrishna if (rctl_chk) { \ 2472d794da1Skrishna CRYPTO_DECREMENT_RCTL(val); \ 2482d794da1Skrishna } else { \ 2492d794da1Skrishna (sp)->sd_pre_approved_amount += (val); \ 2502d794da1Skrishna } \ 2512d794da1Skrishna } 2522d794da1Skrishna 2532d794da1Skrishna #define CRYPTO_BUFFER_CHECK(sp, need, rctl_chk) \ 2542d794da1Skrishna ((sp->sd_pre_approved_amount >= need) ? \ 2552d794da1Skrishna (sp->sd_pre_approved_amount -= need, \ 2562d794da1Skrishna rctl_chk = B_FALSE, CRYPTO_SUCCESS) : \ 2572d794da1Skrishna (rctl_chk = B_TRUE, crypto_buffer_check(need))) 2582d794da1Skrishna 2592d794da1Skrishna /* 2607c478bd9Sstevel@tonic-gate * Module linkage. 2617c478bd9Sstevel@tonic-gate */ 2627c478bd9Sstevel@tonic-gate static struct cb_ops cbops = { 2637c478bd9Sstevel@tonic-gate crypto_open, /* cb_open */ 2647c478bd9Sstevel@tonic-gate crypto_close, /* cb_close */ 2657c478bd9Sstevel@tonic-gate nodev, /* cb_strategy */ 2667c478bd9Sstevel@tonic-gate nodev, /* cb_print */ 2677c478bd9Sstevel@tonic-gate nodev, /* cb_dump */ 2687c478bd9Sstevel@tonic-gate nodev, /* cb_read */ 2697c478bd9Sstevel@tonic-gate nodev, /* cb_write */ 2707c478bd9Sstevel@tonic-gate crypto_ioctl, /* cb_ioctl */ 2717c478bd9Sstevel@tonic-gate nodev, /* cb_devmap */ 2727c478bd9Sstevel@tonic-gate nodev, /* cb_mmap */ 2737c478bd9Sstevel@tonic-gate nodev, /* cb_segmap */ 2747c478bd9Sstevel@tonic-gate nochpoll, /* cb_chpoll */ 2757c478bd9Sstevel@tonic-gate ddi_prop_op, /* cb_prop_op */ 2767c478bd9Sstevel@tonic-gate NULL, /* cb_streamtab */ 2777c478bd9Sstevel@tonic-gate D_MP, /* cb_flag */ 2787c478bd9Sstevel@tonic-gate CB_REV, /* cb_rev */ 2797c478bd9Sstevel@tonic-gate nodev, /* cb_aread */ 2807c478bd9Sstevel@tonic-gate nodev, /* cb_awrite */ 2817c478bd9Sstevel@tonic-gate }; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate static struct dev_ops devops = { 2847c478bd9Sstevel@tonic-gate DEVO_REV, /* devo_rev */ 2857c478bd9Sstevel@tonic-gate 0, /* devo_refcnt */ 2867c478bd9Sstevel@tonic-gate crypto_getinfo, /* devo_getinfo */ 2877c478bd9Sstevel@tonic-gate nulldev, /* devo_identify */ 2887c478bd9Sstevel@tonic-gate nulldev, /* devo_probe */ 2897c478bd9Sstevel@tonic-gate crypto_attach, /* devo_attach */ 2907c478bd9Sstevel@tonic-gate crypto_detach, /* devo_detach */ 2917c478bd9Sstevel@tonic-gate nodev, /* devo_reset */ 2927c478bd9Sstevel@tonic-gate &cbops, /* devo_cb_ops */ 2937c478bd9Sstevel@tonic-gate NULL, /* devo_bus_ops */ 2947c478bd9Sstevel@tonic-gate NULL, /* devo_power */ 29519397407SSherry Moore ddi_quiesce_not_needed, /* devo_quiesce */ 2967c478bd9Sstevel@tonic-gate }; 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate static struct modldrv modldrv = { 2997c478bd9Sstevel@tonic-gate &mod_driverops, /* drv_modops */ 300d2b32306Smcpowers "Cryptographic Library Interface", /* drv_linkinfo */ 3017c478bd9Sstevel@tonic-gate &devops, 3027c478bd9Sstevel@tonic-gate }; 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 3057c478bd9Sstevel@tonic-gate MODREV_1, /* ml_rev */ 3067c478bd9Sstevel@tonic-gate &modldrv, /* ml_linkage */ 3077c478bd9Sstevel@tonic-gate NULL 3087c478bd9Sstevel@tonic-gate }; 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate /* 3117c478bd9Sstevel@tonic-gate * DDI entry points. 3127c478bd9Sstevel@tonic-gate */ 3137c478bd9Sstevel@tonic-gate int 3147c478bd9Sstevel@tonic-gate _init(void) 3157c478bd9Sstevel@tonic-gate { 3167c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage)); 3177c478bd9Sstevel@tonic-gate } 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate int 3207c478bd9Sstevel@tonic-gate _fini(void) 3217c478bd9Sstevel@tonic-gate { 3227c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage)); 3237c478bd9Sstevel@tonic-gate } 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate int 3267c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 3277c478bd9Sstevel@tonic-gate { 3287c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate /* ARGSUSED */ 3327c478bd9Sstevel@tonic-gate static int 3337c478bd9Sstevel@tonic-gate crypto_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 3347c478bd9Sstevel@tonic-gate { 3357c478bd9Sstevel@tonic-gate switch (cmd) { 3367c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 3377c478bd9Sstevel@tonic-gate *result = crypto_dip; 3387c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 3417c478bd9Sstevel@tonic-gate *result = (void *)0; 3427c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 3437c478bd9Sstevel@tonic-gate } 3447c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate static int 3487c478bd9Sstevel@tonic-gate crypto_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 3497c478bd9Sstevel@tonic-gate { 350ef56a3c5SKrishna Yenduri int i; 351ef56a3c5SKrishna Yenduri 3527c478bd9Sstevel@tonic-gate if (cmd != DDI_ATTACH) { 3537c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate if (ddi_get_instance(dip) != 0) { 3577c478bd9Sstevel@tonic-gate /* we only allow instance 0 to attach */ 3587c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 3597c478bd9Sstevel@tonic-gate } 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate crypto_session_cache = kmem_cache_create("crypto_session_cache", 3627c478bd9Sstevel@tonic-gate sizeof (crypto_session_data_t), 0, NULL, NULL, NULL, NULL, NULL, 0); 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate if (crypto_session_cache == NULL) 3657c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate /* create the minor node */ 3687c478bd9Sstevel@tonic-gate if (ddi_create_minor_node(dip, "crypto", S_IFCHR, 0, 3697c478bd9Sstevel@tonic-gate DDI_PSEUDO, 0) != DDI_SUCCESS) { 3707c478bd9Sstevel@tonic-gate kmem_cache_destroy(crypto_session_cache); 3717c478bd9Sstevel@tonic-gate crypto_session_cache = NULL; 3727c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "crypto_attach: failed creating minor node"); 3737c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL); 3747c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate 377ef56a3c5SKrishna Yenduri crypto_locks = kmem_zalloc(max_ncpus * sizeof (kcf_lock_withpad_t), 378ef56a3c5SKrishna Yenduri KM_SLEEP); 379ef56a3c5SKrishna Yenduri for (i = 0; i < max_ncpus; i++) 380ef56a3c5SKrishna Yenduri mutex_init(&crypto_locks[i].kl_lock, NULL, MUTEX_DRIVER, NULL); 381ef56a3c5SKrishna Yenduri 3827c478bd9Sstevel@tonic-gate crypto_dip = dip; 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate /* allocate integer space for minor numbers */ 3857c478bd9Sstevel@tonic-gate crypto_arena = vmem_create("crypto", (void *)1, 3867c478bd9Sstevel@tonic-gate CRYPTO_MINOR_CHUNK, 1, NULL, NULL, NULL, 0, 3877c478bd9Sstevel@tonic-gate VM_SLEEP | VMC_IDENTIFIER); 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 3907c478bd9Sstevel@tonic-gate } 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate static int 3937c478bd9Sstevel@tonic-gate crypto_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 3947c478bd9Sstevel@tonic-gate { 3957c478bd9Sstevel@tonic-gate minor_t i; 396ef56a3c5SKrishna Yenduri kcf_lock_withpad_t *mp; 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate if (cmd != DDI_DETACH) 3997c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 4007c478bd9Sstevel@tonic-gate 401ef56a3c5SKrishna Yenduri mp = &crypto_locks[CPU_SEQID]; 402ef56a3c5SKrishna Yenduri mutex_enter(&mp->kl_lock); 403ef56a3c5SKrishna Yenduri 4047c478bd9Sstevel@tonic-gate /* check if device is open */ 4057c478bd9Sstevel@tonic-gate for (i = 0; i < crypto_minors_table_count; i++) { 4067c478bd9Sstevel@tonic-gate if (crypto_minors[i] != NULL) { 407ef56a3c5SKrishna Yenduri mutex_exit(&mp->kl_lock); 4087c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate } 411ef56a3c5SKrishna Yenduri mutex_exit(&mp->kl_lock); 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate crypto_dip = NULL; 4147c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL); 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate kmem_cache_destroy(crypto_session_cache); 4177c478bd9Sstevel@tonic-gate crypto_session_cache = NULL; 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate kmem_free(crypto_minors, 4207c478bd9Sstevel@tonic-gate sizeof (crypto_minor_t *) * crypto_minors_table_count); 4217c478bd9Sstevel@tonic-gate crypto_minors = NULL; 4227c478bd9Sstevel@tonic-gate crypto_minors_table_count = 0; 423ef56a3c5SKrishna Yenduri for (i = 0; i < max_ncpus; i++) 424ef56a3c5SKrishna Yenduri mutex_destroy(&crypto_locks[i].kl_lock); 4258326c110SKrishna Yenduri kmem_free(crypto_locks, max_ncpus * sizeof (kcf_lock_withpad_t)); 4268326c110SKrishna Yenduri crypto_locks = NULL; 427ef56a3c5SKrishna Yenduri 4287c478bd9Sstevel@tonic-gate vmem_destroy(crypto_arena); 4297c478bd9Sstevel@tonic-gate crypto_arena = NULL; 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate 43495014fbbSDan OpenSolaris Anderson /* ARGSUSED3 */ 4357c478bd9Sstevel@tonic-gate static int 4367c478bd9Sstevel@tonic-gate crypto_open(dev_t *devp, int flag, int otyp, cred_t *credp) 4377c478bd9Sstevel@tonic-gate { 4387c478bd9Sstevel@tonic-gate crypto_minor_t *cm = NULL; 4397c478bd9Sstevel@tonic-gate minor_t mn; 440ef56a3c5SKrishna Yenduri kcf_lock_withpad_t *mp; 441ef56a3c5SKrishna Yenduri int i; 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate if (otyp != OTYP_CHR) 4447c478bd9Sstevel@tonic-gate return (ENXIO); 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate if (crypto_dip == NULL) 4477c478bd9Sstevel@tonic-gate return (ENXIO); 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate /* exclusive opens are not supported */ 4507c478bd9Sstevel@tonic-gate if (flag & FEXCL) 4517c478bd9Sstevel@tonic-gate return (ENOTSUP); 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate again: 454ef56a3c5SKrishna Yenduri mp = &crypto_locks[CPU_SEQID]; 455ef56a3c5SKrishna Yenduri mutex_enter(&mp->kl_lock); 456ef56a3c5SKrishna Yenduri 4577c478bd9Sstevel@tonic-gate /* grow the minors table if needed */ 4587c478bd9Sstevel@tonic-gate if (crypto_minors_count >= crypto_minors_table_count) { 4597c478bd9Sstevel@tonic-gate crypto_minor_t **newtable; 4607c478bd9Sstevel@tonic-gate minor_t chunk = crypto_minor_chunk; 4617c478bd9Sstevel@tonic-gate minor_t saved_count; 4627c478bd9Sstevel@tonic-gate size_t new_size; 4637c478bd9Sstevel@tonic-gate ulong_t big_count; 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate big_count = crypto_minors_count + chunk; 4667c478bd9Sstevel@tonic-gate if (big_count > MAXMIN) { 467ef56a3c5SKrishna Yenduri mutex_exit(&mp->kl_lock); 4687c478bd9Sstevel@tonic-gate return (ENOMEM); 4697c478bd9Sstevel@tonic-gate } 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate saved_count = crypto_minors_table_count; 4727c478bd9Sstevel@tonic-gate new_size = sizeof (crypto_minor_t *) * 4737c478bd9Sstevel@tonic-gate (crypto_minors_table_count + chunk); 4747c478bd9Sstevel@tonic-gate 475ef56a3c5SKrishna Yenduri mutex_exit(&mp->kl_lock); 4767c478bd9Sstevel@tonic-gate 477ef56a3c5SKrishna Yenduri newtable = kmem_zalloc(new_size, KM_SLEEP); 478ef56a3c5SKrishna Yenduri CRYPTO_ENTER_ALL_LOCKS(); 4797c478bd9Sstevel@tonic-gate /* 4807c478bd9Sstevel@tonic-gate * Check if table grew while we were sleeping. 4817c478bd9Sstevel@tonic-gate * The minors table never shrinks. 4827c478bd9Sstevel@tonic-gate */ 4837c478bd9Sstevel@tonic-gate if (crypto_minors_table_count > saved_count) { 484ef56a3c5SKrishna Yenduri CRYPTO_EXIT_ALL_LOCKS(); 4857c478bd9Sstevel@tonic-gate kmem_free(newtable, new_size); 4867c478bd9Sstevel@tonic-gate goto again; 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate /* we assume that bcopy() will return if count is 0 */ 4907c478bd9Sstevel@tonic-gate bcopy(crypto_minors, newtable, 4917c478bd9Sstevel@tonic-gate sizeof (crypto_minor_t *) * crypto_minors_table_count); 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate kmem_free(crypto_minors, 4947c478bd9Sstevel@tonic-gate sizeof (crypto_minor_t *) * crypto_minors_table_count); 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate /* grow the minors number space */ 4977c478bd9Sstevel@tonic-gate if (crypto_minors_table_count != 0) { 4987c478bd9Sstevel@tonic-gate (void) vmem_add(crypto_arena, 4997c478bd9Sstevel@tonic-gate (void *)(uintptr_t)(crypto_minors_table_count + 1), 5007c478bd9Sstevel@tonic-gate crypto_minor_chunk, VM_SLEEP); 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate crypto_minors = newtable; 5047c478bd9Sstevel@tonic-gate crypto_minors_table_count += chunk; 505ef56a3c5SKrishna Yenduri CRYPTO_EXIT_ALL_LOCKS(); 506ef56a3c5SKrishna Yenduri } else { 507ef56a3c5SKrishna Yenduri mutex_exit(&mp->kl_lock); 5087c478bd9Sstevel@tonic-gate } 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate /* allocate a new minor number starting with 1 */ 5117c478bd9Sstevel@tonic-gate mn = (minor_t)(uintptr_t)vmem_alloc(crypto_arena, 1, VM_SLEEP); 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate cm = kmem_zalloc(sizeof (crypto_minor_t), KM_SLEEP); 5147c478bd9Sstevel@tonic-gate mutex_init(&cm->cm_lock, NULL, MUTEX_DRIVER, NULL); 5157c478bd9Sstevel@tonic-gate cv_init(&cm->cm_cv, NULL, CV_DRIVER, NULL); 5167c478bd9Sstevel@tonic-gate 517ef56a3c5SKrishna Yenduri CRYPTO_ENTER_ALL_LOCKS(); 518ac129f9eSKrishna Yenduri cm->cm_refcnt = 1; 5197c478bd9Sstevel@tonic-gate crypto_minors[mn - 1] = cm; 5207c478bd9Sstevel@tonic-gate crypto_minors_count++; 521ef56a3c5SKrishna Yenduri CRYPTO_EXIT_ALL_LOCKS(); 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate *devp = makedevice(getmajor(*devp), mn); 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate return (0); 5267c478bd9Sstevel@tonic-gate } 5277c478bd9Sstevel@tonic-gate 52895014fbbSDan OpenSolaris Anderson /* ARGSUSED1 */ 5297c478bd9Sstevel@tonic-gate static int 5307c478bd9Sstevel@tonic-gate crypto_close(dev_t dev, int flag, int otyp, cred_t *credp) 5317c478bd9Sstevel@tonic-gate { 5327c478bd9Sstevel@tonic-gate crypto_minor_t *cm = NULL; 5337c478bd9Sstevel@tonic-gate crypto_session_data_t *sp; 5347c478bd9Sstevel@tonic-gate minor_t mn = getminor(dev); 5357c478bd9Sstevel@tonic-gate uint_t i; 5362d794da1Skrishna size_t total = 0; 537ef56a3c5SKrishna Yenduri kcf_lock_withpad_t *mp; 5387c478bd9Sstevel@tonic-gate 539ef56a3c5SKrishna Yenduri mp = &crypto_locks[CPU_SEQID]; 540ef56a3c5SKrishna Yenduri mutex_enter(&mp->kl_lock); 541ef56a3c5SKrishna Yenduri 5427c478bd9Sstevel@tonic-gate if (mn > crypto_minors_table_count) { 543ef56a3c5SKrishna Yenduri mutex_exit(&mp->kl_lock); 5447c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "crypto_close: bad minor (too big) %d", mn); 5457c478bd9Sstevel@tonic-gate return (ENODEV); 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate 548ac129f9eSKrishna Yenduri cm = crypto_minors[mn - 1]; 5497c478bd9Sstevel@tonic-gate if (cm == NULL) { 550ef56a3c5SKrishna Yenduri mutex_exit(&mp->kl_lock); 5517c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "crypto_close: duplicate close of minor %d", 5527c478bd9Sstevel@tonic-gate getminor(dev)); 5537c478bd9Sstevel@tonic-gate return (ENODEV); 5547c478bd9Sstevel@tonic-gate } 5557c478bd9Sstevel@tonic-gate 556ef56a3c5SKrishna Yenduri mutex_exit(&mp->kl_lock); 557ac129f9eSKrishna Yenduri 558ef56a3c5SKrishna Yenduri CRYPTO_ENTER_ALL_LOCKS(); 559ef56a3c5SKrishna Yenduri /* 560ef56a3c5SKrishna Yenduri * We free the minor number, mn, from the crypto_arena 561ef56a3c5SKrishna Yenduri * only later. This ensures that we won't race with another 562ef56a3c5SKrishna Yenduri * thread in crypto_open with the same minor number. 563ef56a3c5SKrishna Yenduri */ 5647c478bd9Sstevel@tonic-gate crypto_minors[mn - 1] = NULL; 5657c478bd9Sstevel@tonic-gate crypto_minors_count--; 566ef56a3c5SKrishna Yenduri CRYPTO_EXIT_ALL_LOCKS(); 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate mutex_enter(&cm->cm_lock); 569ef56a3c5SKrishna Yenduri cm->cm_refcnt --; /* decrement refcnt held in open */ 570ef56a3c5SKrishna Yenduri while (cm->cm_refcnt > 0) { 571ef56a3c5SKrishna Yenduri cv_wait(&cm->cm_cv, &cm->cm_lock); 572ef56a3c5SKrishna Yenduri } 573ef56a3c5SKrishna Yenduri 574ef56a3c5SKrishna Yenduri vmem_free(crypto_arena, (void *)(uintptr_t)mn, 1); 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate /* free all session table entries starting with 1 */ 5777c478bd9Sstevel@tonic-gate for (i = 1; i < cm->cm_session_table_count; i++) { 5787c478bd9Sstevel@tonic-gate if (cm->cm_session_table[i] == NULL) 5797c478bd9Sstevel@tonic-gate continue; 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate sp = cm->cm_session_table[i]; 5827c478bd9Sstevel@tonic-gate ASSERT((sp->sd_flags & CRYPTO_SESSION_IS_BUSY) == 0); 5832d794da1Skrishna ASSERT(sp->sd_pre_approved_amount == 0 || 5842d794da1Skrishna sp->sd_pre_approved_amount == crypto_pre_approved_limit); 5852d794da1Skrishna total += sp->sd_pre_approved_amount; 5867c478bd9Sstevel@tonic-gate if (sp->sd_find_init_cookie != NULL) { 5877c478bd9Sstevel@tonic-gate (void) crypto_free_find_ctx(sp); 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate crypto_release_provider_session(cm, sp->sd_provider_session); 5907c478bd9Sstevel@tonic-gate KCF_PROV_REFRELE(sp->sd_provider); 5917c478bd9Sstevel@tonic-gate CRYPTO_CANCEL_ALL_CTX(sp); 5927c478bd9Sstevel@tonic-gate mutex_destroy(&sp->sd_lock); 5937c478bd9Sstevel@tonic-gate cv_destroy(&sp->sd_cv); 5947c478bd9Sstevel@tonic-gate kmem_cache_free(crypto_session_cache, sp); 5957c478bd9Sstevel@tonic-gate cm->cm_session_table[i] = NULL; 5967c478bd9Sstevel@tonic-gate } 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate /* free the session table */ 5997c478bd9Sstevel@tonic-gate if (cm->cm_session_table != NULL && cm->cm_session_table_count > 0) 6007c478bd9Sstevel@tonic-gate kmem_free(cm->cm_session_table, cm->cm_session_table_count * 6017c478bd9Sstevel@tonic-gate sizeof (void *)); 6027c478bd9Sstevel@tonic-gate 6032d794da1Skrishna total += (cm->cm_session_table_count * sizeof (void *)); 6042d794da1Skrishna CRYPTO_DECREMENT_RCTL(total); 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate kcf_free_provider_tab(cm->cm_provider_count, 6077c478bd9Sstevel@tonic-gate cm->cm_provider_array); 6087c478bd9Sstevel@tonic-gate 609ef56a3c5SKrishna Yenduri mutex_exit(&cm->cm_lock); 6107c478bd9Sstevel@tonic-gate mutex_destroy(&cm->cm_lock); 6117c478bd9Sstevel@tonic-gate cv_destroy(&cm->cm_cv); 6127c478bd9Sstevel@tonic-gate kmem_free(cm, sizeof (crypto_minor_t)); 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate return (0); 6157c478bd9Sstevel@tonic-gate } 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate static crypto_minor_t * 6187c478bd9Sstevel@tonic-gate crypto_hold_minor(minor_t minor) 6197c478bd9Sstevel@tonic-gate { 620ac129f9eSKrishna Yenduri crypto_minor_t *cm; 621ef56a3c5SKrishna Yenduri kcf_lock_withpad_t *mp; 622ac129f9eSKrishna Yenduri 623ac129f9eSKrishna Yenduri if (minor > crypto_minors_table_count) 624ac129f9eSKrishna Yenduri return (NULL); 6257c478bd9Sstevel@tonic-gate 626ef56a3c5SKrishna Yenduri mp = &crypto_locks[CPU_SEQID]; 627ef56a3c5SKrishna Yenduri mutex_enter(&mp->kl_lock); 628ef56a3c5SKrishna Yenduri 629ac129f9eSKrishna Yenduri if ((cm = crypto_minors[minor - 1]) != NULL) { 630*1a5e258fSJosef 'Jeff' Sipek atomic_inc_32(&cm->cm_refcnt); 6317c478bd9Sstevel@tonic-gate } 632ef56a3c5SKrishna Yenduri mutex_exit(&mp->kl_lock); 6337c478bd9Sstevel@tonic-gate return (cm); 6347c478bd9Sstevel@tonic-gate } 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate static void 6377c478bd9Sstevel@tonic-gate crypto_release_minor(crypto_minor_t *cm) 6387c478bd9Sstevel@tonic-gate { 639*1a5e258fSJosef 'Jeff' Sipek if (atomic_dec_32_nv(&cm->cm_refcnt) == 0) { 640ac129f9eSKrishna Yenduri cv_signal(&cm->cm_cv); 6417c478bd9Sstevel@tonic-gate } 6427c478bd9Sstevel@tonic-gate } 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate /* 645ba5f469cSkrishna * Build a list of functions and other information for the provider, pd. 6467c478bd9Sstevel@tonic-gate */ 6477c478bd9Sstevel@tonic-gate static void 6487c478bd9Sstevel@tonic-gate crypto_build_function_list(crypto_function_list_t *fl, kcf_provider_desc_t *pd) 6497c478bd9Sstevel@tonic-gate { 6507c478bd9Sstevel@tonic-gate crypto_ops_t *ops; 6517c478bd9Sstevel@tonic-gate crypto_digest_ops_t *digest_ops; 6527c478bd9Sstevel@tonic-gate crypto_cipher_ops_t *cipher_ops; 6537c478bd9Sstevel@tonic-gate crypto_mac_ops_t *mac_ops; 6547c478bd9Sstevel@tonic-gate crypto_sign_ops_t *sign_ops; 6557c478bd9Sstevel@tonic-gate crypto_verify_ops_t *verify_ops; 6567c478bd9Sstevel@tonic-gate crypto_dual_ops_t *dual_ops; 6577c478bd9Sstevel@tonic-gate crypto_random_number_ops_t *random_number_ops; 6587c478bd9Sstevel@tonic-gate crypto_session_ops_t *session_ops; 6597c478bd9Sstevel@tonic-gate crypto_object_ops_t *object_ops; 6607c478bd9Sstevel@tonic-gate crypto_key_ops_t *key_ops; 6617c478bd9Sstevel@tonic-gate crypto_provider_management_ops_t *provider_ops; 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate if ((ops = pd->pd_ops_vector) == NULL) 6647c478bd9Sstevel@tonic-gate return; 6657c478bd9Sstevel@tonic-gate 666894b2776Smcpowers if ((digest_ops = ops->co_digest_ops) != NULL) { 6677c478bd9Sstevel@tonic-gate if (digest_ops->digest_init != NULL) 6687c478bd9Sstevel@tonic-gate fl->fl_digest_init = B_TRUE; 6697c478bd9Sstevel@tonic-gate if (digest_ops->digest != NULL) 6707c478bd9Sstevel@tonic-gate fl->fl_digest = B_TRUE; 6717c478bd9Sstevel@tonic-gate if (digest_ops->digest_update != NULL) 6727c478bd9Sstevel@tonic-gate fl->fl_digest_update = B_TRUE; 6737c478bd9Sstevel@tonic-gate if (digest_ops->digest_key != NULL) 6747c478bd9Sstevel@tonic-gate fl->fl_digest_key = B_TRUE; 6757c478bd9Sstevel@tonic-gate if (digest_ops->digest_final != NULL) 6767c478bd9Sstevel@tonic-gate fl->fl_digest_final = B_TRUE; 6777c478bd9Sstevel@tonic-gate } 678894b2776Smcpowers if ((cipher_ops = ops->co_cipher_ops) != NULL) { 6797c478bd9Sstevel@tonic-gate if (cipher_ops->encrypt_init != NULL) 6807c478bd9Sstevel@tonic-gate fl->fl_encrypt_init = B_TRUE; 6817c478bd9Sstevel@tonic-gate if (cipher_ops->encrypt != NULL) 6827c478bd9Sstevel@tonic-gate fl->fl_encrypt = B_TRUE; 6837c478bd9Sstevel@tonic-gate if (cipher_ops->encrypt_update != NULL) 6847c478bd9Sstevel@tonic-gate fl->fl_encrypt_update = B_TRUE; 6857c478bd9Sstevel@tonic-gate if (cipher_ops->encrypt_final != NULL) 6867c478bd9Sstevel@tonic-gate fl->fl_encrypt_final = B_TRUE; 6877c478bd9Sstevel@tonic-gate if (cipher_ops->decrypt_init != NULL) 6887c478bd9Sstevel@tonic-gate fl->fl_decrypt_init = B_TRUE; 6897c478bd9Sstevel@tonic-gate if (cipher_ops->decrypt != NULL) 6907c478bd9Sstevel@tonic-gate fl->fl_decrypt = B_TRUE; 6917c478bd9Sstevel@tonic-gate if (cipher_ops->decrypt_update != NULL) 6927c478bd9Sstevel@tonic-gate fl->fl_decrypt_update = B_TRUE; 6937c478bd9Sstevel@tonic-gate if (cipher_ops->decrypt_final != NULL) 6947c478bd9Sstevel@tonic-gate fl->fl_decrypt_final = B_TRUE; 6957c478bd9Sstevel@tonic-gate } 696894b2776Smcpowers if ((mac_ops = ops->co_mac_ops) != NULL) { 6977c478bd9Sstevel@tonic-gate if (mac_ops->mac_init != NULL) 6987c478bd9Sstevel@tonic-gate fl->fl_mac_init = B_TRUE; 6997c478bd9Sstevel@tonic-gate if (mac_ops->mac != NULL) 7007c478bd9Sstevel@tonic-gate fl->fl_mac = B_TRUE; 7017c478bd9Sstevel@tonic-gate if (mac_ops->mac_update != NULL) 7027c478bd9Sstevel@tonic-gate fl->fl_mac_update = B_TRUE; 7037c478bd9Sstevel@tonic-gate if (mac_ops->mac_final != NULL) 7047c478bd9Sstevel@tonic-gate fl->fl_mac_final = B_TRUE; 7057c478bd9Sstevel@tonic-gate } 706894b2776Smcpowers if ((sign_ops = ops->co_sign_ops) != NULL) { 7077c478bd9Sstevel@tonic-gate if (sign_ops->sign_init != NULL) 7087c478bd9Sstevel@tonic-gate fl->fl_sign_init = B_TRUE; 7097c478bd9Sstevel@tonic-gate if (sign_ops->sign != NULL) 7107c478bd9Sstevel@tonic-gate fl->fl_sign = B_TRUE; 7117c478bd9Sstevel@tonic-gate if (sign_ops->sign_update != NULL) 7127c478bd9Sstevel@tonic-gate fl->fl_sign_update = B_TRUE; 7137c478bd9Sstevel@tonic-gate if (sign_ops->sign_final != NULL) 7147c478bd9Sstevel@tonic-gate fl->fl_sign_final = B_TRUE; 7157c478bd9Sstevel@tonic-gate if (sign_ops->sign_recover_init != NULL) 7167c478bd9Sstevel@tonic-gate fl->fl_sign_recover_init = B_TRUE; 7177c478bd9Sstevel@tonic-gate if (sign_ops->sign_recover != NULL) 7187c478bd9Sstevel@tonic-gate fl->fl_sign_recover = B_TRUE; 7197c478bd9Sstevel@tonic-gate } 720894b2776Smcpowers if ((verify_ops = ops->co_verify_ops) != NULL) { 7217c478bd9Sstevel@tonic-gate if (verify_ops->verify_init != NULL) 7227c478bd9Sstevel@tonic-gate fl->fl_verify_init = B_TRUE; 7237c478bd9Sstevel@tonic-gate if (verify_ops->verify != NULL) 7247c478bd9Sstevel@tonic-gate fl->fl_verify = B_TRUE; 7257c478bd9Sstevel@tonic-gate if (verify_ops->verify_update != NULL) 7267c478bd9Sstevel@tonic-gate fl->fl_verify_update = B_TRUE; 7277c478bd9Sstevel@tonic-gate if (verify_ops->verify_final != NULL) 7287c478bd9Sstevel@tonic-gate fl->fl_verify_final = B_TRUE; 7297c478bd9Sstevel@tonic-gate if (verify_ops->verify_recover_init != NULL) 7307c478bd9Sstevel@tonic-gate fl->fl_verify_recover_init = B_TRUE; 7317c478bd9Sstevel@tonic-gate if (verify_ops->verify_recover != NULL) 7327c478bd9Sstevel@tonic-gate fl->fl_verify_recover = B_TRUE; 7337c478bd9Sstevel@tonic-gate } 734894b2776Smcpowers if ((dual_ops = ops->co_dual_ops) != NULL) { 7357c478bd9Sstevel@tonic-gate if (dual_ops->digest_encrypt_update != NULL) 7367c478bd9Sstevel@tonic-gate fl->fl_digest_encrypt_update = B_TRUE; 7377c478bd9Sstevel@tonic-gate if (dual_ops->decrypt_digest_update != NULL) 7387c478bd9Sstevel@tonic-gate fl->fl_decrypt_digest_update = B_TRUE; 7397c478bd9Sstevel@tonic-gate if (dual_ops->sign_encrypt_update != NULL) 7407c478bd9Sstevel@tonic-gate fl->fl_sign_encrypt_update = B_TRUE; 7417c478bd9Sstevel@tonic-gate if (dual_ops->decrypt_verify_update != NULL) 7427c478bd9Sstevel@tonic-gate fl->fl_decrypt_verify_update = B_TRUE; 7437c478bd9Sstevel@tonic-gate } 744894b2776Smcpowers if ((random_number_ops = ops->co_random_ops) != NULL) { 7457c478bd9Sstevel@tonic-gate if (random_number_ops->seed_random != NULL) 7467c478bd9Sstevel@tonic-gate fl->fl_seed_random = B_TRUE; 7477c478bd9Sstevel@tonic-gate if (random_number_ops->generate_random != NULL) 7487c478bd9Sstevel@tonic-gate fl->fl_generate_random = B_TRUE; 7497c478bd9Sstevel@tonic-gate } 750894b2776Smcpowers if ((session_ops = ops->co_session_ops) != NULL) { 7517c478bd9Sstevel@tonic-gate if (session_ops->session_open != NULL) 7527c478bd9Sstevel@tonic-gate fl->fl_session_open = B_TRUE; 7537c478bd9Sstevel@tonic-gate if (session_ops->session_close != NULL) 7547c478bd9Sstevel@tonic-gate fl->fl_session_close = B_TRUE; 7557c478bd9Sstevel@tonic-gate if (session_ops->session_login != NULL) 7567c478bd9Sstevel@tonic-gate fl->fl_session_login = B_TRUE; 7577c478bd9Sstevel@tonic-gate if (session_ops->session_logout != NULL) 7587c478bd9Sstevel@tonic-gate fl->fl_session_logout = B_TRUE; 7597c478bd9Sstevel@tonic-gate } 760894b2776Smcpowers if ((object_ops = ops->co_object_ops) != NULL) { 7617c478bd9Sstevel@tonic-gate if (object_ops->object_create != NULL) 7627c478bd9Sstevel@tonic-gate fl->fl_object_create = B_TRUE; 7637c478bd9Sstevel@tonic-gate if (object_ops->object_copy != NULL) 7647c478bd9Sstevel@tonic-gate fl->fl_object_copy = B_TRUE; 7657c478bd9Sstevel@tonic-gate if (object_ops->object_destroy != NULL) 7667c478bd9Sstevel@tonic-gate fl->fl_object_destroy = B_TRUE; 7677c478bd9Sstevel@tonic-gate if (object_ops->object_get_size != NULL) 7687c478bd9Sstevel@tonic-gate fl->fl_object_get_size = B_TRUE; 7697c478bd9Sstevel@tonic-gate if (object_ops->object_get_attribute_value != NULL) 7707c478bd9Sstevel@tonic-gate fl->fl_object_get_attribute_value = B_TRUE; 7717c478bd9Sstevel@tonic-gate if (object_ops->object_set_attribute_value != NULL) 7727c478bd9Sstevel@tonic-gate fl->fl_object_set_attribute_value = B_TRUE; 7737c478bd9Sstevel@tonic-gate if (object_ops->object_find_init != NULL) 7747c478bd9Sstevel@tonic-gate fl->fl_object_find_init = B_TRUE; 7757c478bd9Sstevel@tonic-gate if (object_ops->object_find != NULL) 7767c478bd9Sstevel@tonic-gate fl->fl_object_find = B_TRUE; 7777c478bd9Sstevel@tonic-gate if (object_ops->object_find_final != NULL) 7787c478bd9Sstevel@tonic-gate fl->fl_object_find_final = B_TRUE; 7797c478bd9Sstevel@tonic-gate } 780894b2776Smcpowers if ((key_ops = ops->co_key_ops) != NULL) { 7817c478bd9Sstevel@tonic-gate if (key_ops->key_generate != NULL) 7827c478bd9Sstevel@tonic-gate fl->fl_key_generate = B_TRUE; 7837c478bd9Sstevel@tonic-gate if (key_ops->key_generate_pair != NULL) 7847c478bd9Sstevel@tonic-gate fl->fl_key_generate_pair = B_TRUE; 7857c478bd9Sstevel@tonic-gate if (key_ops->key_wrap != NULL) 7867c478bd9Sstevel@tonic-gate fl->fl_key_wrap = B_TRUE; 7877c478bd9Sstevel@tonic-gate if (key_ops->key_unwrap != NULL) 7887c478bd9Sstevel@tonic-gate fl->fl_key_unwrap = B_TRUE; 7897c478bd9Sstevel@tonic-gate if (key_ops->key_derive != NULL) 7907c478bd9Sstevel@tonic-gate fl->fl_key_derive = B_TRUE; 7917c478bd9Sstevel@tonic-gate } 792894b2776Smcpowers if ((provider_ops = ops->co_provider_ops) != NULL) { 7937c478bd9Sstevel@tonic-gate if (provider_ops->init_token != NULL) 7947c478bd9Sstevel@tonic-gate fl->fl_init_token = B_TRUE; 7957c478bd9Sstevel@tonic-gate if (provider_ops->init_pin != NULL) 7967c478bd9Sstevel@tonic-gate fl->fl_init_pin = B_TRUE; 7977c478bd9Sstevel@tonic-gate if (provider_ops->set_pin != NULL) 7987c478bd9Sstevel@tonic-gate fl->fl_set_pin = B_TRUE; 7997c478bd9Sstevel@tonic-gate } 800ba5f469cSkrishna 8014df55fdeSJanie Lu fl->prov_is_hash_limited = pd->pd_flags & CRYPTO_HASH_NO_UPDATE; 8024df55fdeSJanie Lu if (fl->prov_is_hash_limited) { 803ba5f469cSkrishna fl->prov_hash_limit = min(pd->pd_hash_limit, 804ba5f469cSkrishna min(CRYPTO_MAX_BUFFER_LEN, 805ba5f469cSkrishna curproc->p_task->tk_proj->kpj_data.kpd_crypto_mem_ctl)); 806ba5f469cSkrishna } 8074a5b2e70Shaimay 8084df55fdeSJanie Lu fl->prov_is_hmac_limited = pd->pd_flags & CRYPTO_HMAC_NO_UPDATE; 8094df55fdeSJanie Lu if (fl->prov_is_hmac_limited) { 8104df55fdeSJanie Lu fl->prov_hmac_limit = min(pd->pd_hmac_limit, 8114df55fdeSJanie Lu min(CRYPTO_MAX_BUFFER_LEN, 8124df55fdeSJanie Lu curproc->p_task->tk_proj->kpj_data.kpd_crypto_mem_ctl)); 8134df55fdeSJanie Lu } 8144df55fdeSJanie Lu 8154df55fdeSJanie Lu if (fl->prov_is_hash_limited || fl->prov_is_hmac_limited) { 8164df55fdeSJanie Lu /* 8174df55fdeSJanie Lu * XXX - The threshold should ideally be per hash/HMAC 8184df55fdeSJanie Lu * mechanism. For now, we use the same value for all 8194df55fdeSJanie Lu * hash/HMAC mechanisms. Empirical evidence suggests this 8204df55fdeSJanie Lu * is fine. 8214df55fdeSJanie Lu */ 8224df55fdeSJanie Lu fl->prov_hash_threshold = kcf_md5_threshold; 8234df55fdeSJanie Lu } 8244df55fdeSJanie Lu 8254a5b2e70Shaimay fl->total_threshold_count = MAX_NUM_THRESHOLD; 8264a5b2e70Shaimay fl->fl_threshold[0].mech_type = CKM_DES3_CBC; 8274a5b2e70Shaimay fl->fl_threshold[0].mech_threshold = kcf_des3_threshold; 8284a5b2e70Shaimay fl->fl_threshold[1].mech_type = CKM_DES3_ECB; 8294a5b2e70Shaimay fl->fl_threshold[1].mech_threshold = kcf_des3_threshold; 8304a5b2e70Shaimay fl->fl_threshold[2].mech_type = CKM_AES_CBC; 8314a5b2e70Shaimay fl->fl_threshold[2].mech_threshold = kcf_aes_threshold; 8324a5b2e70Shaimay fl->fl_threshold[3].mech_type = CKM_AES_ECB; 8334a5b2e70Shaimay fl->fl_threshold[3].mech_threshold = kcf_aes_threshold; 8344a5b2e70Shaimay fl->fl_threshold[4].mech_type = CKM_RC4; 8354a5b2e70Shaimay fl->fl_threshold[4].mech_threshold = kcf_rc4_threshold; 8364a5b2e70Shaimay fl->fl_threshold[5].mech_type = CKM_MD5; 8374a5b2e70Shaimay fl->fl_threshold[5].mech_threshold = kcf_md5_threshold; 8384a5b2e70Shaimay fl->fl_threshold[6].mech_type = CKM_SHA_1; 8394a5b2e70Shaimay fl->fl_threshold[6].mech_threshold = kcf_sha1_threshold; 8407c478bd9Sstevel@tonic-gate } 8417c478bd9Sstevel@tonic-gate 8427c478bd9Sstevel@tonic-gate /* ARGSUSED */ 8437c478bd9Sstevel@tonic-gate static int 8447c478bd9Sstevel@tonic-gate get_function_list(dev_t dev, caddr_t arg, int mode, int *rval) 8457c478bd9Sstevel@tonic-gate { 8467c478bd9Sstevel@tonic-gate crypto_get_function_list_t get_function_list; 8477c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 8487c478bd9Sstevel@tonic-gate crypto_provider_id_t provider_id; 8497c478bd9Sstevel@tonic-gate crypto_function_list_t *fl; 8507c478bd9Sstevel@tonic-gate kcf_provider_desc_t *provider; 8517c478bd9Sstevel@tonic-gate int rv; 8527c478bd9Sstevel@tonic-gate 8537c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 8547c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "get_function_list: failed holding minor"); 8557c478bd9Sstevel@tonic-gate return (ENXIO); 8567c478bd9Sstevel@tonic-gate } 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate if (copyin(arg, &get_function_list, sizeof (get_function_list)) != 0) { 8597c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 8607c478bd9Sstevel@tonic-gate return (EFAULT); 8617c478bd9Sstevel@tonic-gate } 8627c478bd9Sstevel@tonic-gate 8637c478bd9Sstevel@tonic-gate /* initialize provider_array */ 8647c478bd9Sstevel@tonic-gate if (cm->cm_provider_array == NULL) { 8657c478bd9Sstevel@tonic-gate rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST); 8667c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) { 8677c478bd9Sstevel@tonic-gate goto release_minor; 8687c478bd9Sstevel@tonic-gate } 8697c478bd9Sstevel@tonic-gate } 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate provider_id = get_function_list.fl_provider_id; 8727c478bd9Sstevel@tonic-gate mutex_enter(&cm->cm_lock); 8737c478bd9Sstevel@tonic-gate /* index must be less than count of providers */ 8747c478bd9Sstevel@tonic-gate if (provider_id >= cm->cm_provider_count) { 8757c478bd9Sstevel@tonic-gate mutex_exit(&cm->cm_lock); 8767c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 8777c478bd9Sstevel@tonic-gate goto release_minor; 8787c478bd9Sstevel@tonic-gate } 8797c478bd9Sstevel@tonic-gate 8807c478bd9Sstevel@tonic-gate ASSERT(cm->cm_provider_array != NULL); 8817c478bd9Sstevel@tonic-gate provider = cm->cm_provider_array[provider_id]; 8827c478bd9Sstevel@tonic-gate mutex_exit(&cm->cm_lock); 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate fl = &get_function_list.fl_list; 8857c478bd9Sstevel@tonic-gate bzero(fl, sizeof (crypto_function_list_t)); 8867c478bd9Sstevel@tonic-gate 8877c478bd9Sstevel@tonic-gate if (provider->pd_prov_type != CRYPTO_LOGICAL_PROVIDER) { 8887c478bd9Sstevel@tonic-gate crypto_build_function_list(fl, provider); 8897c478bd9Sstevel@tonic-gate } else { 8907c478bd9Sstevel@tonic-gate kcf_provider_desc_t *prev = NULL, *pd; 8917c478bd9Sstevel@tonic-gate 8927c478bd9Sstevel@tonic-gate mutex_enter(&provider->pd_lock); 8937c478bd9Sstevel@tonic-gate while (kcf_get_next_logical_provider_member(provider, 8947c478bd9Sstevel@tonic-gate prev, &pd)) { 8957c478bd9Sstevel@tonic-gate prev = pd; 8967c478bd9Sstevel@tonic-gate crypto_build_function_list(fl, pd); 8977c478bd9Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 8987c478bd9Sstevel@tonic-gate } 8997c478bd9Sstevel@tonic-gate mutex_exit(&provider->pd_lock); 9007c478bd9Sstevel@tonic-gate } 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate rv = CRYPTO_SUCCESS; 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate release_minor: 9057c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 9067c478bd9Sstevel@tonic-gate 9077c478bd9Sstevel@tonic-gate get_function_list.fl_return_value = rv; 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate if (copyout(&get_function_list, arg, sizeof (get_function_list)) != 0) { 9107c478bd9Sstevel@tonic-gate return (EFAULT); 9117c478bd9Sstevel@tonic-gate } 9127c478bd9Sstevel@tonic-gate return (0); 9137c478bd9Sstevel@tonic-gate } 9147c478bd9Sstevel@tonic-gate 9157c478bd9Sstevel@tonic-gate /* 9167c478bd9Sstevel@tonic-gate * This ioctl maps a PKCS#11 mechanism string into an internal number 9177c478bd9Sstevel@tonic-gate * that is used by the kernel. pn_internal_number is set to the 9187c478bd9Sstevel@tonic-gate * internal number. 9197c478bd9Sstevel@tonic-gate */ 9207c478bd9Sstevel@tonic-gate /* ARGSUSED */ 9217c478bd9Sstevel@tonic-gate static int 9227c478bd9Sstevel@tonic-gate get_mechanism_number(dev_t dev, caddr_t arg, int mode, int *rval) 9237c478bd9Sstevel@tonic-gate { 9247c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_get_mechanism_number, get_number); 9257c478bd9Sstevel@tonic-gate crypto_mech_type_t number; 9267c478bd9Sstevel@tonic-gate size_t len; 9277c478bd9Sstevel@tonic-gate char *mechanism_name; 9287c478bd9Sstevel@tonic-gate int rv; 9297c478bd9Sstevel@tonic-gate 9307c478bd9Sstevel@tonic-gate STRUCT_INIT(get_number, mode); 9317c478bd9Sstevel@tonic-gate 9327c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(get_number), STRUCT_SIZE(get_number)) != 0) 9337c478bd9Sstevel@tonic-gate return (EFAULT); 9347c478bd9Sstevel@tonic-gate 9357c478bd9Sstevel@tonic-gate len = STRUCT_FGET(get_number, pn_mechanism_len); 9367c478bd9Sstevel@tonic-gate if (len == 0 || len > CRYPTO_MAX_MECH_NAME) { 9377c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 9387c478bd9Sstevel@tonic-gate goto out; 9397c478bd9Sstevel@tonic-gate } 9407c478bd9Sstevel@tonic-gate mechanism_name = kmem_alloc(len, KM_SLEEP); 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate if (copyin(STRUCT_FGETP(get_number, pn_mechanism_string), 9437c478bd9Sstevel@tonic-gate mechanism_name, len) != 0) { 9447c478bd9Sstevel@tonic-gate kmem_free(mechanism_name, len); 9457c478bd9Sstevel@tonic-gate return (EFAULT); 9467c478bd9Sstevel@tonic-gate } 9477c478bd9Sstevel@tonic-gate 9486f3f1c68Skrishna /* 9496f3f1c68Skrishna * Get mechanism number from kcf. We set the load_module 9506f3f1c68Skrishna * flag to false since we use only hardware providers. 9516f3f1c68Skrishna */ 9526f3f1c68Skrishna number = crypto_mech2id_common(mechanism_name, B_FALSE); 9537c478bd9Sstevel@tonic-gate kmem_free(mechanism_name, len); 9547c478bd9Sstevel@tonic-gate if (number == CRYPTO_MECH_INVALID) { 9557c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 9567c478bd9Sstevel@tonic-gate goto out; 9577c478bd9Sstevel@tonic-gate } 9587c478bd9Sstevel@tonic-gate 9597c478bd9Sstevel@tonic-gate bcopy((char *)&number, (char *)STRUCT_FADDR(get_number, 9607c478bd9Sstevel@tonic-gate pn_internal_number), sizeof (number)); 9617c478bd9Sstevel@tonic-gate 9627c478bd9Sstevel@tonic-gate rv = CRYPTO_SUCCESS; 9637c478bd9Sstevel@tonic-gate out: 9647c478bd9Sstevel@tonic-gate STRUCT_FSET(get_number, pn_return_value, rv); 9657c478bd9Sstevel@tonic-gate 9667c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(get_number), arg, 9677c478bd9Sstevel@tonic-gate STRUCT_SIZE(get_number)) != 0) { 9687c478bd9Sstevel@tonic-gate return (EFAULT); 9697c478bd9Sstevel@tonic-gate } 9707c478bd9Sstevel@tonic-gate return (0); 9717c478bd9Sstevel@tonic-gate } 9727c478bd9Sstevel@tonic-gate 9737c478bd9Sstevel@tonic-gate /* 9747d82f0f8SDina K Nimeh * This ioctl returns an array of crypto_mech_name_t entries. 9757d82f0f8SDina K Nimeh * It lists all the PKCS#11 mechanisms available in the kernel. 9767d82f0f8SDina K Nimeh */ 9777d82f0f8SDina K Nimeh /* ARGSUSED */ 9787d82f0f8SDina K Nimeh static int 9797d82f0f8SDina K Nimeh get_mechanism_list(dev_t dev, caddr_t arg, int mode, int *rval) 9807d82f0f8SDina K Nimeh { 9817d82f0f8SDina K Nimeh STRUCT_DECL(crypto_get_mechanism_list, get_list); 9827d82f0f8SDina K Nimeh crypto_mech_name_t *entries; 9837d82f0f8SDina K Nimeh size_t copyout_size; 9847d82f0f8SDina K Nimeh uint_t req_count; 9857d82f0f8SDina K Nimeh uint_t count; 9867d82f0f8SDina K Nimeh ulong_t offset; 9877d82f0f8SDina K Nimeh int error = 0; 9887d82f0f8SDina K Nimeh 9897d82f0f8SDina K Nimeh STRUCT_INIT(get_list, mode); 9907d82f0f8SDina K Nimeh 9917d82f0f8SDina K Nimeh if (copyin(arg, STRUCT_BUF(get_list), STRUCT_SIZE(get_list)) != 0) { 9927d82f0f8SDina K Nimeh return (EFAULT); 9937d82f0f8SDina K Nimeh } 9947d82f0f8SDina K Nimeh 9957d82f0f8SDina K Nimeh entries = crypto_get_mech_list(&count, KM_SLEEP); 9967d82f0f8SDina K Nimeh 9977d82f0f8SDina K Nimeh /* Number of entries caller thinks we have */ 9987d82f0f8SDina K Nimeh req_count = STRUCT_FGET(get_list, ml_count); 9997d82f0f8SDina K Nimeh 10007d82f0f8SDina K Nimeh STRUCT_FSET(get_list, ml_count, count); 10017d82f0f8SDina K Nimeh STRUCT_FSET(get_list, ml_return_value, CRYPTO_SUCCESS); 10027d82f0f8SDina K Nimeh 10037d82f0f8SDina K Nimeh /* check if buffer is too small */ 10047d82f0f8SDina K Nimeh if (count > req_count) { 10057d82f0f8SDina K Nimeh STRUCT_FSET(get_list, ml_return_value, CRYPTO_BUFFER_TOO_SMALL); 10067d82f0f8SDina K Nimeh } 10077d82f0f8SDina K Nimeh 10087d82f0f8SDina K Nimeh /* copyout the first stuff */ 10097d82f0f8SDina K Nimeh if (copyout(STRUCT_BUF(get_list), arg, STRUCT_SIZE(get_list)) != 0) { 10107d82f0f8SDina K Nimeh error = EFAULT; 10117d82f0f8SDina K Nimeh } 10127d82f0f8SDina K Nimeh 10137d82f0f8SDina K Nimeh /* 10147d82f0f8SDina K Nimeh * If only requesting number of entries or buffer too small or an 10157d82f0f8SDina K Nimeh * error occurred, stop here 10167d82f0f8SDina K Nimeh */ 10177d82f0f8SDina K Nimeh if (req_count == 0 || count > req_count || error != 0) { 10187d82f0f8SDina K Nimeh goto out; 10197d82f0f8SDina K Nimeh } 10207d82f0f8SDina K Nimeh 10217d82f0f8SDina K Nimeh copyout_size = count * sizeof (crypto_mech_name_t); 10227d82f0f8SDina K Nimeh 10237d82f0f8SDina K Nimeh /* copyout entries */ 10247d82f0f8SDina K Nimeh offset = (ulong_t)STRUCT_FADDR(get_list, ml_list); 10257d82f0f8SDina K Nimeh offset -= (ulong_t)STRUCT_BUF(get_list); 10267d82f0f8SDina K Nimeh if (copyout(entries, arg + offset, copyout_size) != 0) { 10277d82f0f8SDina K Nimeh error = EFAULT; 10287d82f0f8SDina K Nimeh } 10297d82f0f8SDina K Nimeh 10307d82f0f8SDina K Nimeh out: 10317d82f0f8SDina K Nimeh crypto_free_mech_list(entries, count); 10327d82f0f8SDina K Nimeh return (error); 10337d82f0f8SDina K Nimeh } 10347d82f0f8SDina K Nimeh 10357d82f0f8SDina K Nimeh /* 10367d82f0f8SDina K Nimeh * Copyout kernel array of mech_infos to user space. 10377d82f0f8SDina K Nimeh */ 10387d82f0f8SDina K Nimeh /* ARGSUSED */ 10397d82f0f8SDina K Nimeh static int 10407d82f0f8SDina K Nimeh copyout_mechinfos(int mode, caddr_t out, uint_t count, 10417d82f0f8SDina K Nimeh crypto_mechanism_info_t *k_minfos, caddr_t u_minfos) 10427d82f0f8SDina K Nimeh { 10437d82f0f8SDina K Nimeh STRUCT_DECL(crypto_mechanism_info, mi); 10447d82f0f8SDina K Nimeh caddr_t p; 10457d82f0f8SDina K Nimeh size_t len; 10467d82f0f8SDina K Nimeh int i; 10477d82f0f8SDina K Nimeh 10487d82f0f8SDina K Nimeh if (count == 0) 10497d82f0f8SDina K Nimeh return (0); 10507d82f0f8SDina K Nimeh 10517d82f0f8SDina K Nimeh STRUCT_INIT(mi, mode); 10527d82f0f8SDina K Nimeh 10537d82f0f8SDina K Nimeh len = count * STRUCT_SIZE(mi); 10547d82f0f8SDina K Nimeh 10557d82f0f8SDina K Nimeh ASSERT(u_minfos != NULL); 10567d82f0f8SDina K Nimeh p = u_minfos; 10577d82f0f8SDina K Nimeh for (i = 0; i < count; i++) { 10587d82f0f8SDina K Nimeh STRUCT_FSET(mi, mi_min_key_size, k_minfos[i].mi_min_key_size); 10597d82f0f8SDina K Nimeh STRUCT_FSET(mi, mi_max_key_size, k_minfos[i].mi_max_key_size); 10607d82f0f8SDina K Nimeh STRUCT_FSET(mi, mi_keysize_unit, k_minfos[i].mi_keysize_unit); 10617d82f0f8SDina K Nimeh STRUCT_FSET(mi, mi_usage, k_minfos[i].mi_usage); 10627d82f0f8SDina K Nimeh bcopy(STRUCT_BUF(mi), p, STRUCT_SIZE(mi)); 10637d82f0f8SDina K Nimeh p += STRUCT_SIZE(mi); 10647d82f0f8SDina K Nimeh } 10657d82f0f8SDina K Nimeh 10667d82f0f8SDina K Nimeh if (copyout(u_minfos, out, len) != 0) 10677d82f0f8SDina K Nimeh return (EFAULT); 10687d82f0f8SDina K Nimeh 10697d82f0f8SDina K Nimeh return (0); 10707d82f0f8SDina K Nimeh } 10717d82f0f8SDina K Nimeh 10727d82f0f8SDina K Nimeh /* 10737d82f0f8SDina K Nimeh * This ioctl returns information for the specified mechanism. 10747d82f0f8SDina K Nimeh */ 10757d82f0f8SDina K Nimeh /* ARGSUSED */ 10767d82f0f8SDina K Nimeh static int 10777d82f0f8SDina K Nimeh get_all_mechanism_info(dev_t dev, caddr_t arg, int mode, int *rval) 10787d82f0f8SDina K Nimeh { 10797d82f0f8SDina K Nimeh STRUCT_DECL(crypto_get_all_mechanism_info, get_all_mech); 108095014fbbSDan OpenSolaris Anderson #ifdef _LP64 108195014fbbSDan OpenSolaris Anderson STRUCT_DECL(crypto_mechanism_info, mi); 108295014fbbSDan OpenSolaris Anderson #else 10831a010143SDina K Nimeh /* LINTED E_FUNC_SET_NOT_USED */ 10847d82f0f8SDina K Nimeh STRUCT_DECL(crypto_mechanism_info, mi); 108595014fbbSDan OpenSolaris Anderson #endif 10867d82f0f8SDina K Nimeh crypto_mech_name_t mech_name; 10877d82f0f8SDina K Nimeh crypto_mech_type_t mech_type; 10887d82f0f8SDina K Nimeh crypto_mechanism_info_t *mech_infos = NULL; 10897d82f0f8SDina K Nimeh uint_t num_mech_infos = 0; 10907d82f0f8SDina K Nimeh uint_t req_count; 10917d82f0f8SDina K Nimeh caddr_t u_minfos; 10927d82f0f8SDina K Nimeh ulong_t offset; 10937d82f0f8SDina K Nimeh int error = 0; 10947d82f0f8SDina K Nimeh int rv; 10957d82f0f8SDina K Nimeh 10967d82f0f8SDina K Nimeh STRUCT_INIT(get_all_mech, mode); 10977d82f0f8SDina K Nimeh STRUCT_INIT(mi, mode); 10987d82f0f8SDina K Nimeh 10997d82f0f8SDina K Nimeh if (copyin(arg, STRUCT_BUF(get_all_mech), 11007d82f0f8SDina K Nimeh STRUCT_SIZE(get_all_mech)) != 0) { 11017d82f0f8SDina K Nimeh return (EFAULT); 11027d82f0f8SDina K Nimeh } 11037d82f0f8SDina K Nimeh 11047d82f0f8SDina K Nimeh (void) strncpy(mech_name, STRUCT_FGET(get_all_mech, mi_mechanism_name), 11057d82f0f8SDina K Nimeh CRYPTO_MAX_MECH_NAME); 11067d82f0f8SDina K Nimeh mech_type = crypto_mech2id(mech_name); 11077d82f0f8SDina K Nimeh 11087d82f0f8SDina K Nimeh if (mech_type == CRYPTO_MECH_INVALID) { 11097d82f0f8SDina K Nimeh rv = CRYPTO_ARGUMENTS_BAD; 11107d82f0f8SDina K Nimeh goto out1; 11117d82f0f8SDina K Nimeh } 11127d82f0f8SDina K Nimeh 11137d82f0f8SDina K Nimeh rv = crypto_get_all_mech_info(mech_type, &mech_infos, &num_mech_infos, 11147d82f0f8SDina K Nimeh KM_SLEEP); 11157d82f0f8SDina K Nimeh if (rv != CRYPTO_SUCCESS) { 11167d82f0f8SDina K Nimeh goto out1; 11177d82f0f8SDina K Nimeh } 11187d82f0f8SDina K Nimeh /* rv is CRYPTO_SUCCESS at this point */ 11197d82f0f8SDina K Nimeh 11207d82f0f8SDina K Nimeh /* Number of entries caller thinks we have */ 11217d82f0f8SDina K Nimeh req_count = STRUCT_FGET(get_all_mech, mi_count); 11227d82f0f8SDina K Nimeh 11237d82f0f8SDina K Nimeh STRUCT_FSET(get_all_mech, mi_count, num_mech_infos); 11247d82f0f8SDina K Nimeh 11257d82f0f8SDina K Nimeh /* check if buffer is too small */ 11267d82f0f8SDina K Nimeh if (num_mech_infos > req_count) { 11277d82f0f8SDina K Nimeh rv = CRYPTO_BUFFER_TOO_SMALL; 11287d82f0f8SDina K Nimeh } 11297d82f0f8SDina K Nimeh 11307d82f0f8SDina K Nimeh out1: 11317d82f0f8SDina K Nimeh STRUCT_FSET(get_all_mech, mi_return_value, rv); 11327d82f0f8SDina K Nimeh 11337d82f0f8SDina K Nimeh /* copy the first part */ 11347d82f0f8SDina K Nimeh if (copyout(STRUCT_BUF(get_all_mech), arg, 11357d82f0f8SDina K Nimeh STRUCT_SIZE(get_all_mech)) != 0) { 11367d82f0f8SDina K Nimeh error = EFAULT; 11377d82f0f8SDina K Nimeh } 11387d82f0f8SDina K Nimeh 11397d82f0f8SDina K Nimeh /* 11407d82f0f8SDina K Nimeh * If only requesting number of entries, or there are no entries, 11417d82f0f8SDina K Nimeh * or rv is not CRYPTO_SUCCESS due to buffer too small or some other 11427d82f0f8SDina K Nimeh * crypto error, or an error occurred with copyout, stop here 11437d82f0f8SDina K Nimeh */ 11447d82f0f8SDina K Nimeh if (req_count == 0 || num_mech_infos == 0 || rv != CRYPTO_SUCCESS || 11457d82f0f8SDina K Nimeh error != 0) { 11467d82f0f8SDina K Nimeh goto out2; 11477d82f0f8SDina K Nimeh } 11487d82f0f8SDina K Nimeh 11497d82f0f8SDina K Nimeh /* copyout mech_infos */ 11507d82f0f8SDina K Nimeh offset = (ulong_t)STRUCT_FADDR(get_all_mech, mi_list); 11517d82f0f8SDina K Nimeh offset -= (ulong_t)STRUCT_BUF(get_all_mech); 11527d82f0f8SDina K Nimeh 11537d82f0f8SDina K Nimeh u_minfos = kmem_alloc(num_mech_infos * STRUCT_SIZE(mi), KM_SLEEP); 11547d82f0f8SDina K Nimeh error = copyout_mechinfos(mode, arg + offset, num_mech_infos, 11557d82f0f8SDina K Nimeh mech_infos, u_minfos); 11567d82f0f8SDina K Nimeh kmem_free(u_minfos, num_mech_infos * STRUCT_SIZE(mi)); 11577d82f0f8SDina K Nimeh out2: 11587d82f0f8SDina K Nimeh if (mech_infos != NULL) 11597d82f0f8SDina K Nimeh crypto_free_all_mech_info(mech_infos, num_mech_infos); 11607d82f0f8SDina K Nimeh return (error); 11617d82f0f8SDina K Nimeh } 11627d82f0f8SDina K Nimeh 11637d82f0f8SDina K Nimeh /* 11647c478bd9Sstevel@tonic-gate * Side-effects: 11657c478bd9Sstevel@tonic-gate * 1. This routine stores provider descriptor pointers in an array 11667c478bd9Sstevel@tonic-gate * and increments each descriptor's reference count. The array 11677c478bd9Sstevel@tonic-gate * is stored in per-minor number storage. 11687c478bd9Sstevel@tonic-gate * 2. Destroys the old array and creates a new one every time 11697c478bd9Sstevel@tonic-gate * this routine is called. 11707c478bd9Sstevel@tonic-gate */ 11717c478bd9Sstevel@tonic-gate int 11727c478bd9Sstevel@tonic-gate crypto_get_provider_list(crypto_minor_t *cm, uint_t *count, 11737c478bd9Sstevel@tonic-gate crypto_provider_entry_t **array, boolean_t return_slot_list) 11747c478bd9Sstevel@tonic-gate { 11757c478bd9Sstevel@tonic-gate kcf_provider_desc_t **provider_array; 11767c478bd9Sstevel@tonic-gate crypto_provider_entry_t *p = NULL; 11777c478bd9Sstevel@tonic-gate uint_t provider_count; 11787c478bd9Sstevel@tonic-gate int rval; 11797c478bd9Sstevel@tonic-gate int i; 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate /* 11827c478bd9Sstevel@tonic-gate * Take snapshot of provider table returning only HW entries 11837c478bd9Sstevel@tonic-gate * that are in a usable state. Also returns logical provider entries. 11847c478bd9Sstevel@tonic-gate */ 11857c478bd9Sstevel@tonic-gate rval = kcf_get_slot_list(&provider_count, &provider_array, B_FALSE); 11867c478bd9Sstevel@tonic-gate if (rval != CRYPTO_SUCCESS) 11877c478bd9Sstevel@tonic-gate return (rval); 11887c478bd9Sstevel@tonic-gate 11897c478bd9Sstevel@tonic-gate /* allocate memory before taking cm->cm_lock */ 11907c478bd9Sstevel@tonic-gate if (return_slot_list) { 11917c478bd9Sstevel@tonic-gate if (provider_count != 0) { 11927c478bd9Sstevel@tonic-gate p = kmem_alloc(provider_count * 11937c478bd9Sstevel@tonic-gate sizeof (crypto_provider_entry_t), KM_SLEEP); 11947c478bd9Sstevel@tonic-gate for (i = 0; i < provider_count; i++) { 11957c478bd9Sstevel@tonic-gate p[i].pe_provider_id = i; 11967c478bd9Sstevel@tonic-gate p[i].pe_mechanism_count = 11977c478bd9Sstevel@tonic-gate provider_array[i]->pd_mech_list_count; 11987c478bd9Sstevel@tonic-gate } 11997c478bd9Sstevel@tonic-gate } 12007c478bd9Sstevel@tonic-gate *array = p; 12017c478bd9Sstevel@tonic-gate *count = provider_count; 12027c478bd9Sstevel@tonic-gate } 12037c478bd9Sstevel@tonic-gate 12047c478bd9Sstevel@tonic-gate /* 12057c478bd9Sstevel@tonic-gate * Free existing array of providers and replace with new list. 12067c478bd9Sstevel@tonic-gate */ 12077c478bd9Sstevel@tonic-gate mutex_enter(&cm->cm_lock); 12087c478bd9Sstevel@tonic-gate if (cm->cm_provider_array != NULL) { 12097c478bd9Sstevel@tonic-gate ASSERT(cm->cm_provider_count > 0); 12107c478bd9Sstevel@tonic-gate kcf_free_provider_tab(cm->cm_provider_count, 12117c478bd9Sstevel@tonic-gate cm->cm_provider_array); 12127c478bd9Sstevel@tonic-gate } 12137c478bd9Sstevel@tonic-gate 12147c478bd9Sstevel@tonic-gate cm->cm_provider_array = provider_array; 12157c478bd9Sstevel@tonic-gate cm->cm_provider_count = provider_count; 12167c478bd9Sstevel@tonic-gate mutex_exit(&cm->cm_lock); 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 12197c478bd9Sstevel@tonic-gate } 12207c478bd9Sstevel@tonic-gate 12217c478bd9Sstevel@tonic-gate /* 12227c478bd9Sstevel@tonic-gate * This ioctl returns an array of crypto_provider_entry_t entries. 12237c478bd9Sstevel@tonic-gate * This is how consumers learn which hardware providers are available. 12247c478bd9Sstevel@tonic-gate */ 12257c478bd9Sstevel@tonic-gate /* ARGSUSED */ 12267c478bd9Sstevel@tonic-gate static int 12277c478bd9Sstevel@tonic-gate get_provider_list(dev_t dev, caddr_t arg, int mode, int *rval) 12287c478bd9Sstevel@tonic-gate { 12297c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_get_provider_list, get_list); 12307c478bd9Sstevel@tonic-gate crypto_provider_entry_t *entries; 12317c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 12327c478bd9Sstevel@tonic-gate size_t copyout_size; 12337c478bd9Sstevel@tonic-gate uint_t req_count; 12347c478bd9Sstevel@tonic-gate uint_t count; 12357c478bd9Sstevel@tonic-gate ulong_t offset; 12367c478bd9Sstevel@tonic-gate int rv; 12377c478bd9Sstevel@tonic-gate 12387c478bd9Sstevel@tonic-gate STRUCT_INIT(get_list, mode); 12397c478bd9Sstevel@tonic-gate 12407c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 12417c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "get_provider_list: failed holding minor"); 12427c478bd9Sstevel@tonic-gate return (ENXIO); 12437c478bd9Sstevel@tonic-gate } 12447c478bd9Sstevel@tonic-gate 12457c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(get_list), STRUCT_SIZE(get_list)) != 0) { 12467c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 12477c478bd9Sstevel@tonic-gate return (EFAULT); 12487c478bd9Sstevel@tonic-gate } 12497c478bd9Sstevel@tonic-gate 12507c478bd9Sstevel@tonic-gate rv = crypto_get_provider_list(cm, &count, &entries, RETURN_LIST); 12517c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) { 12527c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 12537c478bd9Sstevel@tonic-gate STRUCT_FSET(get_list, pl_return_value, rv); 12547c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(get_list), arg, 12557c478bd9Sstevel@tonic-gate STRUCT_SIZE(get_list)) != 0) { 12567c478bd9Sstevel@tonic-gate return (EFAULT); 12577c478bd9Sstevel@tonic-gate } 12587c478bd9Sstevel@tonic-gate return (0); 12597c478bd9Sstevel@tonic-gate } 12607c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 12617c478bd9Sstevel@tonic-gate 12627c478bd9Sstevel@tonic-gate /* Number of slots caller thinks we have */ 12637c478bd9Sstevel@tonic-gate req_count = STRUCT_FGET(get_list, pl_count); 12647c478bd9Sstevel@tonic-gate 12657c478bd9Sstevel@tonic-gate /* Check if only requesting number of slots */ 12667c478bd9Sstevel@tonic-gate if (req_count == 0) { 12677c478bd9Sstevel@tonic-gate 12687c478bd9Sstevel@tonic-gate STRUCT_FSET(get_list, pl_count, count); 12697c478bd9Sstevel@tonic-gate STRUCT_FSET(get_list, pl_return_value, CRYPTO_SUCCESS); 12707c478bd9Sstevel@tonic-gate 12717c478bd9Sstevel@tonic-gate crypto_free_provider_list(entries, count); 12727c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(get_list), arg, 12737c478bd9Sstevel@tonic-gate STRUCT_SIZE(get_list)) != 0) { 12747c478bd9Sstevel@tonic-gate return (EFAULT); 12757c478bd9Sstevel@tonic-gate } 12767c478bd9Sstevel@tonic-gate return (0); 12777c478bd9Sstevel@tonic-gate } 12787c478bd9Sstevel@tonic-gate 12797c478bd9Sstevel@tonic-gate /* check if buffer is too small */ 12807c478bd9Sstevel@tonic-gate req_count = STRUCT_FGET(get_list, pl_count); 12817c478bd9Sstevel@tonic-gate if (count > req_count) { 12827c478bd9Sstevel@tonic-gate STRUCT_FSET(get_list, pl_count, count); 12837c478bd9Sstevel@tonic-gate STRUCT_FSET(get_list, pl_return_value, CRYPTO_BUFFER_TOO_SMALL); 12847c478bd9Sstevel@tonic-gate crypto_free_provider_list(entries, count); 12857c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(get_list), arg, 12867c478bd9Sstevel@tonic-gate STRUCT_SIZE(get_list)) != 0) { 12877c478bd9Sstevel@tonic-gate return (EFAULT); 12887c478bd9Sstevel@tonic-gate } 12897c478bd9Sstevel@tonic-gate return (0); 12907c478bd9Sstevel@tonic-gate } 12917c478bd9Sstevel@tonic-gate 12927c478bd9Sstevel@tonic-gate STRUCT_FSET(get_list, pl_count, count); 12937c478bd9Sstevel@tonic-gate STRUCT_FSET(get_list, pl_return_value, CRYPTO_SUCCESS); 12947c478bd9Sstevel@tonic-gate 12957c478bd9Sstevel@tonic-gate copyout_size = count * sizeof (crypto_provider_entry_t); 12967c478bd9Sstevel@tonic-gate 12977c478bd9Sstevel@tonic-gate /* copyout the first stuff */ 12987c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(get_list), arg, STRUCT_SIZE(get_list)) != 0) { 12997c478bd9Sstevel@tonic-gate crypto_free_provider_list(entries, count); 13007c478bd9Sstevel@tonic-gate return (EFAULT); 13017c478bd9Sstevel@tonic-gate } 13027c478bd9Sstevel@tonic-gate 13037c478bd9Sstevel@tonic-gate if (count == 0) { 13047c478bd9Sstevel@tonic-gate crypto_free_provider_list(entries, count); 13057c478bd9Sstevel@tonic-gate return (0); 13067c478bd9Sstevel@tonic-gate } 13077c478bd9Sstevel@tonic-gate 13087c478bd9Sstevel@tonic-gate /* copyout entries */ 13097c478bd9Sstevel@tonic-gate offset = (ulong_t)STRUCT_FADDR(get_list, pl_list); 13107c478bd9Sstevel@tonic-gate offset -= (ulong_t)STRUCT_BUF(get_list); 13117c478bd9Sstevel@tonic-gate if (copyout(entries, arg + offset, copyout_size) != 0) { 13127c478bd9Sstevel@tonic-gate crypto_free_provider_list(entries, count); 13137c478bd9Sstevel@tonic-gate return (EFAULT); 13147c478bd9Sstevel@tonic-gate } 13157c478bd9Sstevel@tonic-gate 13167c478bd9Sstevel@tonic-gate crypto_free_provider_list(entries, count); 13177c478bd9Sstevel@tonic-gate return (0); 13187c478bd9Sstevel@tonic-gate } 13197c478bd9Sstevel@tonic-gate 13207c478bd9Sstevel@tonic-gate static void 13217c478bd9Sstevel@tonic-gate ext_to_provider_data(int mode, kcf_provider_desc_t *provider, 13227c478bd9Sstevel@tonic-gate crypto_provider_ext_info_t *ei, void *out) 13237c478bd9Sstevel@tonic-gate { 13247c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_provider_data, pd); 13257c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_version, version); 13267c478bd9Sstevel@tonic-gate 13277c478bd9Sstevel@tonic-gate STRUCT_INIT(pd, mode); 13287c478bd9Sstevel@tonic-gate STRUCT_INIT(version, mode); 13297c478bd9Sstevel@tonic-gate 13307c478bd9Sstevel@tonic-gate bcopy(provider->pd_description, STRUCT_FGET(pd, pd_prov_desc), 13317c478bd9Sstevel@tonic-gate CRYPTO_PROVIDER_DESCR_MAX_LEN); 13327c478bd9Sstevel@tonic-gate 13337c478bd9Sstevel@tonic-gate bcopy(ei->ei_label, STRUCT_FGET(pd, pd_label), CRYPTO_EXT_SIZE_LABEL); 13347c478bd9Sstevel@tonic-gate bcopy(ei->ei_manufacturerID, STRUCT_FGET(pd, pd_manufacturerID), 13357c478bd9Sstevel@tonic-gate CRYPTO_EXT_SIZE_MANUF); 13367c478bd9Sstevel@tonic-gate bcopy(ei->ei_model, STRUCT_FGET(pd, pd_model), CRYPTO_EXT_SIZE_MODEL); 13377c478bd9Sstevel@tonic-gate bcopy(ei->ei_serial_number, STRUCT_FGET(pd, pd_serial_number), 13387c478bd9Sstevel@tonic-gate CRYPTO_EXT_SIZE_SERIAL); 13397c478bd9Sstevel@tonic-gate /* 13407c478bd9Sstevel@tonic-gate * We do not support ioctls for dual-function crypto operations yet. 13417c478bd9Sstevel@tonic-gate * So, we clear this flag as it might have been set by a provider. 13427c478bd9Sstevel@tonic-gate */ 13437c478bd9Sstevel@tonic-gate ei->ei_flags &= ~CRYPTO_EXTF_DUAL_CRYPTO_OPERATIONS; 13447c478bd9Sstevel@tonic-gate 13457c478bd9Sstevel@tonic-gate STRUCT_FSET(pd, pd_flags, ei->ei_flags); 13467c478bd9Sstevel@tonic-gate STRUCT_FSET(pd, pd_max_session_count, ei->ei_max_session_count); 13477c478bd9Sstevel@tonic-gate STRUCT_FSET(pd, pd_session_count, (int)CRYPTO_UNAVAILABLE_INFO); 13487c478bd9Sstevel@tonic-gate STRUCT_FSET(pd, pd_max_rw_session_count, ei->ei_max_session_count); 13497c478bd9Sstevel@tonic-gate STRUCT_FSET(pd, pd_rw_session_count, (int)CRYPTO_UNAVAILABLE_INFO); 13507c478bd9Sstevel@tonic-gate STRUCT_FSET(pd, pd_max_pin_len, ei->ei_max_pin_len); 13517c478bd9Sstevel@tonic-gate STRUCT_FSET(pd, pd_min_pin_len, ei->ei_min_pin_len); 13527c478bd9Sstevel@tonic-gate STRUCT_FSET(pd, pd_total_public_memory, ei->ei_total_public_memory); 13537c478bd9Sstevel@tonic-gate STRUCT_FSET(pd, pd_free_public_memory, ei->ei_free_public_memory); 13547c478bd9Sstevel@tonic-gate STRUCT_FSET(pd, pd_total_private_memory, ei->ei_total_private_memory); 13557c478bd9Sstevel@tonic-gate STRUCT_FSET(pd, pd_free_private_memory, ei->ei_free_private_memory); 13567c478bd9Sstevel@tonic-gate STRUCT_FSET(version, cv_major, ei->ei_hardware_version.cv_major); 13577c478bd9Sstevel@tonic-gate STRUCT_FSET(version, cv_minor, ei->ei_hardware_version.cv_minor); 13587c478bd9Sstevel@tonic-gate bcopy(STRUCT_BUF(version), STRUCT_FADDR(pd, pd_hardware_version), 13597c478bd9Sstevel@tonic-gate STRUCT_SIZE(version)); 1360a398035bSWyllys Ingersoll STRUCT_FSET(version, cv_major, ei->ei_firmware_version.cv_major); 1361a398035bSWyllys Ingersoll STRUCT_FSET(version, cv_minor, ei->ei_firmware_version.cv_minor); 13627c478bd9Sstevel@tonic-gate bcopy(STRUCT_BUF(version), STRUCT_FADDR(pd, pd_firmware_version), 13637c478bd9Sstevel@tonic-gate STRUCT_SIZE(version)); 13647c478bd9Sstevel@tonic-gate bcopy(ei->ei_time, STRUCT_FGET(pd, pd_time), CRYPTO_EXT_SIZE_TIME); 13657c478bd9Sstevel@tonic-gate bcopy(STRUCT_BUF(pd), out, STRUCT_SIZE(pd)); 13667c478bd9Sstevel@tonic-gate } 13677c478bd9Sstevel@tonic-gate 13687c478bd9Sstevel@tonic-gate /* 13697c478bd9Sstevel@tonic-gate * Utility routine to construct a crypto_provider_ext_info structure. Some 13707c478bd9Sstevel@tonic-gate * of the fields are constructed from information in the provider structure. 13717c478bd9Sstevel@tonic-gate * The rest of the fields have default values. We need to do this for 13727c478bd9Sstevel@tonic-gate * providers which do not support crypto_provider_management_ops routines. 13737c478bd9Sstevel@tonic-gate */ 13747c478bd9Sstevel@tonic-gate static void 13757c478bd9Sstevel@tonic-gate fabricate_ext_info(kcf_provider_desc_t *provider, 13767c478bd9Sstevel@tonic-gate crypto_provider_ext_info_t *ei) 13777c478bd9Sstevel@tonic-gate { 13787c478bd9Sstevel@tonic-gate /* empty label */ 13797c478bd9Sstevel@tonic-gate (void) memset(ei->ei_label, ' ', CRYPTO_EXT_SIZE_LABEL); 13807c478bd9Sstevel@tonic-gate 13817c478bd9Sstevel@tonic-gate (void) memset(ei->ei_manufacturerID, ' ', CRYPTO_EXT_SIZE_MANUF); 13827c478bd9Sstevel@tonic-gate (void) strncpy((char *)ei->ei_manufacturerID, "Unknown", 7); 13837c478bd9Sstevel@tonic-gate 13847c478bd9Sstevel@tonic-gate (void) memset(ei->ei_model, ' ', CRYPTO_EXT_SIZE_MODEL); 13857c478bd9Sstevel@tonic-gate (void) strncpy((char *)ei->ei_model, "Unknown", 7); 13867c478bd9Sstevel@tonic-gate 13877c478bd9Sstevel@tonic-gate (void) memset(ei->ei_serial_number, ' ', CRYPTO_EXT_SIZE_SERIAL); 13887c478bd9Sstevel@tonic-gate (void) strncpy((char *)ei->ei_serial_number, "Unknown", 7); 13897c478bd9Sstevel@tonic-gate 13907c478bd9Sstevel@tonic-gate if (KCF_PROV_RANDOM_OPS(provider) != NULL) 13917c478bd9Sstevel@tonic-gate ei->ei_flags |= CRYPTO_EXTF_RNG; 13927c478bd9Sstevel@tonic-gate if (KCF_PROV_DUAL_OPS(provider) != NULL) 13937c478bd9Sstevel@tonic-gate ei->ei_flags |= CRYPTO_EXTF_DUAL_CRYPTO_OPERATIONS; 13947c478bd9Sstevel@tonic-gate 13957c478bd9Sstevel@tonic-gate ei->ei_max_session_count = CRYPTO_UNAVAILABLE_INFO; 13967c478bd9Sstevel@tonic-gate ei->ei_max_pin_len = 0; 13977c478bd9Sstevel@tonic-gate ei->ei_min_pin_len = 0; 13987c478bd9Sstevel@tonic-gate ei->ei_total_public_memory = CRYPTO_UNAVAILABLE_INFO; 13997c478bd9Sstevel@tonic-gate ei->ei_free_public_memory = CRYPTO_UNAVAILABLE_INFO; 14007c478bd9Sstevel@tonic-gate ei->ei_total_private_memory = CRYPTO_UNAVAILABLE_INFO; 14017c478bd9Sstevel@tonic-gate ei->ei_free_private_memory = CRYPTO_UNAVAILABLE_INFO; 14027c478bd9Sstevel@tonic-gate ei->ei_hardware_version.cv_major = 1; 14037c478bd9Sstevel@tonic-gate ei->ei_hardware_version.cv_minor = 0; 14047c478bd9Sstevel@tonic-gate ei->ei_firmware_version.cv_major = 1; 14057c478bd9Sstevel@tonic-gate ei->ei_firmware_version.cv_minor = 0; 14067c478bd9Sstevel@tonic-gate } 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate /* ARGSUSED */ 14097c478bd9Sstevel@tonic-gate static int 14107c478bd9Sstevel@tonic-gate get_provider_info(dev_t dev, caddr_t arg, int mode, int *rval) 14117c478bd9Sstevel@tonic-gate { 14127c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_get_provider_info, get_info); 14137c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 14147c478bd9Sstevel@tonic-gate crypto_provider_id_t provider_id; 14157c478bd9Sstevel@tonic-gate kcf_provider_desc_t *provider, *real_provider; 14167c478bd9Sstevel@tonic-gate crypto_provider_ext_info_t *ext_info = NULL; 14177c478bd9Sstevel@tonic-gate size_t need; 14187c478bd9Sstevel@tonic-gate int error = 0; 14197c478bd9Sstevel@tonic-gate int rv; 14207c478bd9Sstevel@tonic-gate kcf_req_params_t params; 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate STRUCT_INIT(get_info, mode); 14237c478bd9Sstevel@tonic-gate 14247c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 14257c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "get_provider_info: failed holding minor"); 14267c478bd9Sstevel@tonic-gate return (ENXIO); 14277c478bd9Sstevel@tonic-gate } 14287c478bd9Sstevel@tonic-gate 14297c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(get_info), STRUCT_SIZE(get_info)) != 0) { 14307c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 14317c478bd9Sstevel@tonic-gate return (EFAULT); 14327c478bd9Sstevel@tonic-gate } 14337c478bd9Sstevel@tonic-gate 14347c478bd9Sstevel@tonic-gate need = sizeof (crypto_provider_ext_info_t); 1435c1a9a9c3Skrishna if ((rv = crypto_buffer_check(need)) != CRYPTO_SUCCESS) { 14367c478bd9Sstevel@tonic-gate need = 0; 14377c478bd9Sstevel@tonic-gate goto release_minor; 14387c478bd9Sstevel@tonic-gate } 14397c478bd9Sstevel@tonic-gate 14407c478bd9Sstevel@tonic-gate /* initialize provider_array */ 14417c478bd9Sstevel@tonic-gate if (cm->cm_provider_array == NULL) { 14427c478bd9Sstevel@tonic-gate rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST); 14437c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) { 14447c478bd9Sstevel@tonic-gate goto release_minor; 14457c478bd9Sstevel@tonic-gate } 14467c478bd9Sstevel@tonic-gate } 14477c478bd9Sstevel@tonic-gate 14487c478bd9Sstevel@tonic-gate ext_info = kmem_zalloc(need, KM_SLEEP); 14497c478bd9Sstevel@tonic-gate 14507c478bd9Sstevel@tonic-gate provider_id = STRUCT_FGET(get_info, gi_provider_id); 14517c478bd9Sstevel@tonic-gate mutex_enter(&cm->cm_lock); 14527c478bd9Sstevel@tonic-gate /* index must be less than count of providers */ 14537c478bd9Sstevel@tonic-gate if (provider_id >= cm->cm_provider_count) { 14547c478bd9Sstevel@tonic-gate mutex_exit(&cm->cm_lock); 14557c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 14567c478bd9Sstevel@tonic-gate goto release_minor; 14577c478bd9Sstevel@tonic-gate } 14587c478bd9Sstevel@tonic-gate 14597c478bd9Sstevel@tonic-gate ASSERT(cm->cm_provider_array != NULL); 14607c478bd9Sstevel@tonic-gate provider = cm->cm_provider_array[provider_id]; 14617c478bd9Sstevel@tonic-gate KCF_PROV_REFHOLD(provider); 14627c478bd9Sstevel@tonic-gate mutex_exit(&cm->cm_lock); 14637c478bd9Sstevel@tonic-gate 14647c478bd9Sstevel@tonic-gate (void) kcf_get_hardware_provider_nomech( 14657c478bd9Sstevel@tonic-gate CRYPTO_OPS_OFFSET(provider_ops), CRYPTO_PROVIDER_OFFSET(ext_info), 14669b009fc1SValerie Bubb Fenwick provider, &real_provider); 14677c478bd9Sstevel@tonic-gate 14687c478bd9Sstevel@tonic-gate if (real_provider != NULL) { 14697c478bd9Sstevel@tonic-gate ASSERT(real_provider == provider || 14707c478bd9Sstevel@tonic-gate provider->pd_prov_type == CRYPTO_LOGICAL_PROVIDER); 14717c478bd9Sstevel@tonic-gate KCF_WRAP_PROVMGMT_OPS_PARAMS(¶ms, KCF_OP_MGMT_EXTINFO, 14727c478bd9Sstevel@tonic-gate 0, NULL, 0, NULL, 0, NULL, ext_info, provider); 14737c478bd9Sstevel@tonic-gate rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, 14747c478bd9Sstevel@tonic-gate B_FALSE); 14757c478bd9Sstevel@tonic-gate ASSERT(rv != CRYPTO_NOT_SUPPORTED); 1476894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 14777c478bd9Sstevel@tonic-gate } else { 14787c478bd9Sstevel@tonic-gate /* do the best we can */ 14797c478bd9Sstevel@tonic-gate fabricate_ext_info(provider, ext_info); 14807c478bd9Sstevel@tonic-gate rv = CRYPTO_SUCCESS; 14817c478bd9Sstevel@tonic-gate } 14827c478bd9Sstevel@tonic-gate KCF_PROV_REFRELE(provider); 14837c478bd9Sstevel@tonic-gate 14847c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) { 14857c478bd9Sstevel@tonic-gate ext_to_provider_data(mode, provider, ext_info, 14867c478bd9Sstevel@tonic-gate STRUCT_FADDR(get_info, gi_provider_data)); 14877c478bd9Sstevel@tonic-gate } 14887c478bd9Sstevel@tonic-gate 14897c478bd9Sstevel@tonic-gate release_minor: 1490c1a9a9c3Skrishna CRYPTO_DECREMENT_RCTL(need); 14917c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 14927c478bd9Sstevel@tonic-gate 14937c478bd9Sstevel@tonic-gate if (ext_info != NULL) 14947c478bd9Sstevel@tonic-gate kmem_free(ext_info, sizeof (crypto_provider_ext_info_t)); 14957c478bd9Sstevel@tonic-gate 14967c478bd9Sstevel@tonic-gate if (error != 0) 14977c478bd9Sstevel@tonic-gate return (error); 14987c478bd9Sstevel@tonic-gate 14997c478bd9Sstevel@tonic-gate STRUCT_FSET(get_info, gi_return_value, rv); 15007c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(get_info), arg, STRUCT_SIZE(get_info)) != 0) { 15017c478bd9Sstevel@tonic-gate return (EFAULT); 15027c478bd9Sstevel@tonic-gate } 15037c478bd9Sstevel@tonic-gate return (0); 15047c478bd9Sstevel@tonic-gate } 15057c478bd9Sstevel@tonic-gate 15067c478bd9Sstevel@tonic-gate /* 15077c478bd9Sstevel@tonic-gate * This ioctl returns an array of crypto_mech_name_t entries. 15087c478bd9Sstevel@tonic-gate * This is how consumers learn which mechanisms are permitted 15097c478bd9Sstevel@tonic-gate * by a provider. 15107c478bd9Sstevel@tonic-gate */ 15117c478bd9Sstevel@tonic-gate /* ARGSUSED */ 15127c478bd9Sstevel@tonic-gate static int 15137c478bd9Sstevel@tonic-gate get_provider_mechanisms(dev_t dev, caddr_t arg, int mode, int *rval) 15147c478bd9Sstevel@tonic-gate { 15157c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_get_provider_mechanisms, get_mechanisms); 15167c478bd9Sstevel@tonic-gate crypto_mech_name_t *entries; 15177c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 15187c478bd9Sstevel@tonic-gate size_t copyout_size; 15197c478bd9Sstevel@tonic-gate uint_t req_count; 15207c478bd9Sstevel@tonic-gate uint_t count; 15217c478bd9Sstevel@tonic-gate ulong_t offset; 15227c478bd9Sstevel@tonic-gate int err; 15237c478bd9Sstevel@tonic-gate 15247c478bd9Sstevel@tonic-gate STRUCT_INIT(get_mechanisms, mode); 15257c478bd9Sstevel@tonic-gate 15267c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 15277c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 15287c478bd9Sstevel@tonic-gate "get_provider_mechanisms: failed holding minor"); 15297c478bd9Sstevel@tonic-gate return (ENXIO); 15307c478bd9Sstevel@tonic-gate } 15317c478bd9Sstevel@tonic-gate 15327c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(get_mechanisms), 15337c478bd9Sstevel@tonic-gate STRUCT_SIZE(get_mechanisms)) != 0) { 15347c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 15357c478bd9Sstevel@tonic-gate return (EFAULT); 15367c478bd9Sstevel@tonic-gate } 15377c478bd9Sstevel@tonic-gate 15387c478bd9Sstevel@tonic-gate /* get array of mechanisms from the core module */ 15397c478bd9Sstevel@tonic-gate if ((err = crypto_get_provider_mechanisms(cm, 15407c478bd9Sstevel@tonic-gate STRUCT_FGET(get_mechanisms, pm_provider_id), 15417c478bd9Sstevel@tonic-gate &count, &entries)) != 0) { 15427c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 15437c478bd9Sstevel@tonic-gate STRUCT_FSET(get_mechanisms, pm_return_value, err); 15447c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(get_mechanisms), arg, 15457c478bd9Sstevel@tonic-gate STRUCT_SIZE(get_mechanisms)) != 0) { 15467c478bd9Sstevel@tonic-gate return (EFAULT); 15477c478bd9Sstevel@tonic-gate } 15487c478bd9Sstevel@tonic-gate return (0); 15497c478bd9Sstevel@tonic-gate } 15507c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 15517c478bd9Sstevel@tonic-gate /* Number of mechs caller thinks we have */ 15527c478bd9Sstevel@tonic-gate req_count = STRUCT_FGET(get_mechanisms, pm_count); 15537c478bd9Sstevel@tonic-gate 15547c478bd9Sstevel@tonic-gate /* Check if caller is just requesting a count of mechanisms */ 15557c478bd9Sstevel@tonic-gate if (req_count == 0) { 15567c478bd9Sstevel@tonic-gate STRUCT_FSET(get_mechanisms, pm_count, count); 15577c478bd9Sstevel@tonic-gate STRUCT_FSET(get_mechanisms, pm_return_value, CRYPTO_SUCCESS); 15587c478bd9Sstevel@tonic-gate 15597c478bd9Sstevel@tonic-gate crypto_free_mech_list(entries, count); 15607c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(get_mechanisms), arg, 15617c478bd9Sstevel@tonic-gate STRUCT_SIZE(get_mechanisms)) != 0) { 15627c478bd9Sstevel@tonic-gate return (EFAULT); 15637c478bd9Sstevel@tonic-gate } 15647c478bd9Sstevel@tonic-gate return (0); 15657c478bd9Sstevel@tonic-gate } 15667c478bd9Sstevel@tonic-gate 15677c478bd9Sstevel@tonic-gate /* check if buffer is too small */ 15687c478bd9Sstevel@tonic-gate if (count > req_count) { 15697c478bd9Sstevel@tonic-gate STRUCT_FSET(get_mechanisms, pm_count, count); 15707c478bd9Sstevel@tonic-gate STRUCT_FSET(get_mechanisms, pm_return_value, 15717c478bd9Sstevel@tonic-gate CRYPTO_BUFFER_TOO_SMALL); 15727c478bd9Sstevel@tonic-gate crypto_free_mech_list(entries, count); 15737c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(get_mechanisms), arg, 15747c478bd9Sstevel@tonic-gate STRUCT_SIZE(get_mechanisms)) != 0) { 15757c478bd9Sstevel@tonic-gate return (EFAULT); 15767c478bd9Sstevel@tonic-gate } 15777c478bd9Sstevel@tonic-gate return (0); 15787c478bd9Sstevel@tonic-gate } 15797c478bd9Sstevel@tonic-gate 15807c478bd9Sstevel@tonic-gate STRUCT_FSET(get_mechanisms, pm_count, count); 15817c478bd9Sstevel@tonic-gate STRUCT_FSET(get_mechanisms, pm_return_value, CRYPTO_SUCCESS); 15827c478bd9Sstevel@tonic-gate 15837c478bd9Sstevel@tonic-gate copyout_size = count * sizeof (crypto_mech_name_t); 15847c478bd9Sstevel@tonic-gate 15857c478bd9Sstevel@tonic-gate /* copyout the first stuff */ 15867c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(get_mechanisms), arg, 15877c478bd9Sstevel@tonic-gate STRUCT_SIZE(get_mechanisms)) != 0) { 15887c478bd9Sstevel@tonic-gate crypto_free_mech_list(entries, count); 15897c478bd9Sstevel@tonic-gate return (EFAULT); 15907c478bd9Sstevel@tonic-gate } 15917c478bd9Sstevel@tonic-gate 15927c478bd9Sstevel@tonic-gate if (count == 0) { 15937c478bd9Sstevel@tonic-gate return (0); 15947c478bd9Sstevel@tonic-gate } 15957c478bd9Sstevel@tonic-gate 15967c478bd9Sstevel@tonic-gate /* copyout entries */ 15977c478bd9Sstevel@tonic-gate offset = (ulong_t)STRUCT_FADDR(get_mechanisms, pm_list); 15987c478bd9Sstevel@tonic-gate offset -= (ulong_t)STRUCT_BUF(get_mechanisms); 15997c478bd9Sstevel@tonic-gate if (copyout(entries, arg + offset, copyout_size) != 0) { 16007c478bd9Sstevel@tonic-gate crypto_free_mech_list(entries, count); 16017c478bd9Sstevel@tonic-gate return (EFAULT); 16027c478bd9Sstevel@tonic-gate } 16037c478bd9Sstevel@tonic-gate 16047c478bd9Sstevel@tonic-gate crypto_free_mech_list(entries, count); 16057c478bd9Sstevel@tonic-gate return (0); 16067c478bd9Sstevel@tonic-gate } 16077c478bd9Sstevel@tonic-gate 16087c478bd9Sstevel@tonic-gate /* 16097c478bd9Sstevel@tonic-gate * This ioctl returns information about a provider's mechanism. 16107c478bd9Sstevel@tonic-gate */ 16117c478bd9Sstevel@tonic-gate /* ARGSUSED */ 16127c478bd9Sstevel@tonic-gate static int 16137c478bd9Sstevel@tonic-gate get_provider_mechanism_info(dev_t dev, caddr_t arg, int mode, int *rval) 16147c478bd9Sstevel@tonic-gate { 16157c478bd9Sstevel@tonic-gate crypto_get_provider_mechanism_info_t mechanism_info; 16167c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 16177c478bd9Sstevel@tonic-gate kcf_provider_desc_t *pd; 16187c478bd9Sstevel@tonic-gate crypto_mech_info_t *mi = NULL; 16197c478bd9Sstevel@tonic-gate int rv = CRYPTO_SUCCESS; 16207c478bd9Sstevel@tonic-gate int i; 16217c478bd9Sstevel@tonic-gate 16227c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 16237c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 16247c478bd9Sstevel@tonic-gate "get_provider_mechanism_info: failed holding minor"); 16257c478bd9Sstevel@tonic-gate return (ENXIO); 16267c478bd9Sstevel@tonic-gate } 16277c478bd9Sstevel@tonic-gate 16287c478bd9Sstevel@tonic-gate if (copyin(arg, &mechanism_info, sizeof (mechanism_info)) != 0) { 16297c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 16307c478bd9Sstevel@tonic-gate return (EFAULT); 16317c478bd9Sstevel@tonic-gate } 16327c478bd9Sstevel@tonic-gate 16337c478bd9Sstevel@tonic-gate /* initialize provider table */ 16347c478bd9Sstevel@tonic-gate if (cm->cm_provider_array == NULL) { 16357c478bd9Sstevel@tonic-gate rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST); 16367c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) { 16377c478bd9Sstevel@tonic-gate mutex_enter(&cm->cm_lock); 16387c478bd9Sstevel@tonic-gate goto fail; 16397c478bd9Sstevel@tonic-gate } 16407c478bd9Sstevel@tonic-gate } 16417c478bd9Sstevel@tonic-gate 16427c478bd9Sstevel@tonic-gate /* 16437c478bd9Sstevel@tonic-gate * Provider ID must be less than the count of providers 16447c478bd9Sstevel@tonic-gate * obtained by calling get_provider_list(). 16457c478bd9Sstevel@tonic-gate */ 16467c478bd9Sstevel@tonic-gate mutex_enter(&cm->cm_lock); 16477c478bd9Sstevel@tonic-gate if (mechanism_info.mi_provider_id >= cm->cm_provider_count) { 16487c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 16497c478bd9Sstevel@tonic-gate goto fail; 16507c478bd9Sstevel@tonic-gate } 16517c478bd9Sstevel@tonic-gate 16527c478bd9Sstevel@tonic-gate pd = cm->cm_provider_array[mechanism_info.mi_provider_id]; 16537c478bd9Sstevel@tonic-gate 1654c630c2c5SVladimir Kotal /* First check if the provider supports the mechanism. */ 16557c478bd9Sstevel@tonic-gate for (i = 0; i < pd->pd_mech_list_count; i++) { 16567c478bd9Sstevel@tonic-gate if (strncmp(pd->pd_mechanisms[i].cm_mech_name, 16577c478bd9Sstevel@tonic-gate mechanism_info.mi_mechanism_name, 16587c478bd9Sstevel@tonic-gate CRYPTO_MAX_MECH_NAME) == 0) { 16597c478bd9Sstevel@tonic-gate mi = &pd->pd_mechanisms[i]; 1660c630c2c5SVladimir Kotal break; 16617c478bd9Sstevel@tonic-gate } 16627c478bd9Sstevel@tonic-gate } 16637c478bd9Sstevel@tonic-gate 16647c478bd9Sstevel@tonic-gate if (mi == NULL) { 16657c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 16667c478bd9Sstevel@tonic-gate goto fail; 16677c478bd9Sstevel@tonic-gate } 16687c478bd9Sstevel@tonic-gate 1669c630c2c5SVladimir Kotal /* Now check if the mechanism is enabled for the provider. */ 1670c630c2c5SVladimir Kotal if (is_mech_disabled(pd, mechanism_info.mi_mechanism_name)) { 1671c630c2c5SVladimir Kotal rv = CRYPTO_MECHANISM_INVALID; 1672c630c2c5SVladimir Kotal goto fail; 1673c630c2c5SVladimir Kotal } 1674c630c2c5SVladimir Kotal 16757c478bd9Sstevel@tonic-gate mechanism_info.mi_min_key_size = mi->cm_min_key_length; 16767c478bd9Sstevel@tonic-gate mechanism_info.mi_max_key_size = mi->cm_max_key_length; 16777c478bd9Sstevel@tonic-gate mechanism_info.mi_flags = mi->cm_func_group_mask; 16787c478bd9Sstevel@tonic-gate 16797c478bd9Sstevel@tonic-gate fail: 16807c478bd9Sstevel@tonic-gate mutex_exit(&cm->cm_lock); 16817c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 16827c478bd9Sstevel@tonic-gate mechanism_info.mi_return_value = rv; 16837c478bd9Sstevel@tonic-gate if (copyout(&mechanism_info, arg, sizeof (mechanism_info)) != 0) { 16847c478bd9Sstevel@tonic-gate return (EFAULT); 16857c478bd9Sstevel@tonic-gate } 16867c478bd9Sstevel@tonic-gate 16877c478bd9Sstevel@tonic-gate return (0); 16887c478bd9Sstevel@tonic-gate } 16897c478bd9Sstevel@tonic-gate 16907c478bd9Sstevel@tonic-gate /* 16917c478bd9Sstevel@tonic-gate * Every open of /dev/crypto multiplexes all PKCS#11 sessions across 16927c478bd9Sstevel@tonic-gate * a single session to each provider. Calls to open and close session 16937c478bd9Sstevel@tonic-gate * are not made to providers that do not support sessions. For these 16947c478bd9Sstevel@tonic-gate * providers, a session number of 0 is passed during subsequent operations, 16957c478bd9Sstevel@tonic-gate * and it is ignored by the provider. 16967c478bd9Sstevel@tonic-gate */ 16977c478bd9Sstevel@tonic-gate static int 16987c478bd9Sstevel@tonic-gate crypto_get_provider_session(crypto_minor_t *cm, 16997c478bd9Sstevel@tonic-gate crypto_provider_id_t provider_index, crypto_provider_session_t **output_ps) 17007c478bd9Sstevel@tonic-gate { 17017c478bd9Sstevel@tonic-gate kcf_provider_desc_t *pd, *real_provider; 17027c478bd9Sstevel@tonic-gate kcf_req_params_t params; 17037c478bd9Sstevel@tonic-gate crypto_provider_session_t *ps, *new_ps; 17047c478bd9Sstevel@tonic-gate crypto_session_id_t provider_session_id = 0; 17057c478bd9Sstevel@tonic-gate int rv; 17067c478bd9Sstevel@tonic-gate 17077c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cm->cm_lock)); 17087c478bd9Sstevel@tonic-gate 17097c478bd9Sstevel@tonic-gate /* pd may be a logical provider */ 17107c478bd9Sstevel@tonic-gate pd = cm->cm_provider_array[provider_index]; 17117c478bd9Sstevel@tonic-gate 17127c478bd9Sstevel@tonic-gate again: 17137c478bd9Sstevel@tonic-gate /* 17147c478bd9Sstevel@tonic-gate * Check if there is already a session to the provider. 17157c478bd9Sstevel@tonic-gate * Sessions may be to a logical provider or a real provider. 17167c478bd9Sstevel@tonic-gate */ 17177c478bd9Sstevel@tonic-gate for (ps = cm->cm_provider_session; ps != NULL; ps = ps->ps_next) { 17187c478bd9Sstevel@tonic-gate if (ps->ps_provider == pd) 17197c478bd9Sstevel@tonic-gate break; 17207c478bd9Sstevel@tonic-gate } 17217c478bd9Sstevel@tonic-gate 17227c478bd9Sstevel@tonic-gate /* found existing session */ 17237c478bd9Sstevel@tonic-gate if (ps != NULL) { 17247c478bd9Sstevel@tonic-gate ps->ps_refcnt++; 17257c478bd9Sstevel@tonic-gate *output_ps = ps; 17267c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 17277c478bd9Sstevel@tonic-gate } 17287c478bd9Sstevel@tonic-gate mutex_exit(&cm->cm_lock); 17297c478bd9Sstevel@tonic-gate 17307c478bd9Sstevel@tonic-gate /* find a hardware provider that supports session ops */ 17317c478bd9Sstevel@tonic-gate (void) kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(session_ops), 17329b009fc1SValerie Bubb Fenwick CRYPTO_SESSION_OFFSET(session_open), pd, &real_provider); 17337c478bd9Sstevel@tonic-gate 17347c478bd9Sstevel@tonic-gate if (real_provider != NULL) { 17357c478bd9Sstevel@tonic-gate ASSERT(real_provider == pd || 17367c478bd9Sstevel@tonic-gate pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER); 17377c478bd9Sstevel@tonic-gate /* open session to provider */ 17387c478bd9Sstevel@tonic-gate KCF_WRAP_SESSION_OPS_PARAMS(¶ms, KCF_OP_SESSION_OPEN, 17397c478bd9Sstevel@tonic-gate &provider_session_id, 0, CRYPTO_USER, NULL, 0, pd); 17407c478bd9Sstevel@tonic-gate rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, 17417c478bd9Sstevel@tonic-gate B_FALSE); 17427c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) { 17437c478bd9Sstevel@tonic-gate mutex_enter(&cm->cm_lock); 1744894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 17457c478bd9Sstevel@tonic-gate return (rv); 17467c478bd9Sstevel@tonic-gate } 17477c478bd9Sstevel@tonic-gate } 17487c478bd9Sstevel@tonic-gate 17497c478bd9Sstevel@tonic-gate /* allocate crypto_provider_session structure */ 17507c478bd9Sstevel@tonic-gate new_ps = kmem_zalloc(sizeof (crypto_provider_session_t), KM_SLEEP); 17517c478bd9Sstevel@tonic-gate 17527c478bd9Sstevel@tonic-gate /* 17537c478bd9Sstevel@tonic-gate * Check if someone opened a session to the provider 17547c478bd9Sstevel@tonic-gate * while we dropped the lock. 17557c478bd9Sstevel@tonic-gate */ 17567c478bd9Sstevel@tonic-gate mutex_enter(&cm->cm_lock); 17577c478bd9Sstevel@tonic-gate for (ps = cm->cm_provider_session; ps != NULL; ps = ps->ps_next) { 17587c478bd9Sstevel@tonic-gate if (ps->ps_provider == pd) { 17597c478bd9Sstevel@tonic-gate mutex_exit(&cm->cm_lock); 17607c478bd9Sstevel@tonic-gate kmem_free(new_ps, sizeof (crypto_provider_session_t)); 17617c478bd9Sstevel@tonic-gate if (real_provider != NULL) { 17627c478bd9Sstevel@tonic-gate KCF_WRAP_SESSION_OPS_PARAMS(¶ms, 17637c478bd9Sstevel@tonic-gate KCF_OP_SESSION_CLOSE, NULL, 17647c478bd9Sstevel@tonic-gate provider_session_id, CRYPTO_USER, NULL, 0, 17657c478bd9Sstevel@tonic-gate pd); 17667c478bd9Sstevel@tonic-gate (void) kcf_submit_request(real_provider, NULL, 17677c478bd9Sstevel@tonic-gate NULL, ¶ms, B_FALSE); 1768894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 17697c478bd9Sstevel@tonic-gate } 17707c478bd9Sstevel@tonic-gate mutex_enter(&cm->cm_lock); 17717c478bd9Sstevel@tonic-gate goto again; 17727c478bd9Sstevel@tonic-gate 17737c478bd9Sstevel@tonic-gate } 17747c478bd9Sstevel@tonic-gate } 17757c478bd9Sstevel@tonic-gate 17767c478bd9Sstevel@tonic-gate /* increment refcnt and attach to crypto_minor structure */ 17777c478bd9Sstevel@tonic-gate new_ps->ps_session = provider_session_id; 17787c478bd9Sstevel@tonic-gate new_ps->ps_refcnt = 1; 17797c478bd9Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 17807c478bd9Sstevel@tonic-gate new_ps->ps_provider = pd; 17817c478bd9Sstevel@tonic-gate if (real_provider != NULL) { 17827c478bd9Sstevel@tonic-gate new_ps->ps_real_provider = real_provider; 17837c478bd9Sstevel@tonic-gate } 17847c478bd9Sstevel@tonic-gate new_ps->ps_next = cm->cm_provider_session; 17857c478bd9Sstevel@tonic-gate cm->cm_provider_session = new_ps; 17867c478bd9Sstevel@tonic-gate 17877c478bd9Sstevel@tonic-gate *output_ps = new_ps; 17887c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 17897c478bd9Sstevel@tonic-gate } 17907c478bd9Sstevel@tonic-gate 17917c478bd9Sstevel@tonic-gate /* 17927c478bd9Sstevel@tonic-gate * Release a provider session. 17937c478bd9Sstevel@tonic-gate * If the reference count goes to zero, then close the session 17947c478bd9Sstevel@tonic-gate * to the provider. 17957c478bd9Sstevel@tonic-gate */ 17967c478bd9Sstevel@tonic-gate static void 17977c478bd9Sstevel@tonic-gate crypto_release_provider_session(crypto_minor_t *cm, 17987c478bd9Sstevel@tonic-gate crypto_provider_session_t *provider_session) 17997c478bd9Sstevel@tonic-gate { 18007c478bd9Sstevel@tonic-gate kcf_req_params_t params; 18017c478bd9Sstevel@tonic-gate crypto_provider_session_t *ps = NULL, **prev; 18027c478bd9Sstevel@tonic-gate 18037c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cm->cm_lock)); 18047c478bd9Sstevel@tonic-gate 18057c478bd9Sstevel@tonic-gate /* verify that provider_session is valid */ 18067c478bd9Sstevel@tonic-gate for (ps = cm->cm_provider_session, prev = &cm->cm_provider_session; 18077c478bd9Sstevel@tonic-gate ps != NULL; prev = &ps->ps_next, ps = ps->ps_next) { 18087c478bd9Sstevel@tonic-gate if (ps == provider_session) { 18097c478bd9Sstevel@tonic-gate break; 18107c478bd9Sstevel@tonic-gate } 18117c478bd9Sstevel@tonic-gate } 18127c478bd9Sstevel@tonic-gate 18137c478bd9Sstevel@tonic-gate if (ps == NULL) 18147c478bd9Sstevel@tonic-gate return; 18157c478bd9Sstevel@tonic-gate 18167c478bd9Sstevel@tonic-gate ps->ps_refcnt--; 18177c478bd9Sstevel@tonic-gate 18187c478bd9Sstevel@tonic-gate if (ps->ps_refcnt > 0) 18197c478bd9Sstevel@tonic-gate return; 18207c478bd9Sstevel@tonic-gate 18217c478bd9Sstevel@tonic-gate if (ps->ps_real_provider != NULL) { 18227c478bd9Sstevel@tonic-gate /* close session with provider */ 18237c478bd9Sstevel@tonic-gate KCF_WRAP_SESSION_OPS_PARAMS(¶ms, KCF_OP_SESSION_CLOSE, NULL, 18247c478bd9Sstevel@tonic-gate ps->ps_session, CRYPTO_USER, NULL, 0, ps->ps_provider); 18257c478bd9Sstevel@tonic-gate (void) kcf_submit_request(ps->ps_real_provider, 18267c478bd9Sstevel@tonic-gate NULL, NULL, ¶ms, B_FALSE); 18277c478bd9Sstevel@tonic-gate KCF_PROV_REFRELE(ps->ps_real_provider); 18287c478bd9Sstevel@tonic-gate } 18297c478bd9Sstevel@tonic-gate KCF_PROV_REFRELE(ps->ps_provider); 18307c478bd9Sstevel@tonic-gate *prev = ps->ps_next; 18317c478bd9Sstevel@tonic-gate kmem_free(ps, sizeof (*ps)); 18327c478bd9Sstevel@tonic-gate } 18337c478bd9Sstevel@tonic-gate 18347c478bd9Sstevel@tonic-gate static int 18357c478bd9Sstevel@tonic-gate grow_session_table(crypto_minor_t *cm) 18367c478bd9Sstevel@tonic-gate { 18377c478bd9Sstevel@tonic-gate crypto_session_data_t **session_table; 18387c478bd9Sstevel@tonic-gate crypto_session_data_t **new; 18397c478bd9Sstevel@tonic-gate uint_t session_table_count; 18407c478bd9Sstevel@tonic-gate uint_t need; 18417c478bd9Sstevel@tonic-gate size_t current_allocation; 18427c478bd9Sstevel@tonic-gate size_t new_allocation; 1843c1a9a9c3Skrishna int rv; 18447c478bd9Sstevel@tonic-gate 18457c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cm->cm_lock)); 18467c478bd9Sstevel@tonic-gate 18477c478bd9Sstevel@tonic-gate session_table_count = cm->cm_session_table_count; 18487c478bd9Sstevel@tonic-gate session_table = cm->cm_session_table; 18497c478bd9Sstevel@tonic-gate need = session_table_count + CRYPTO_SESSION_CHUNK; 18507c478bd9Sstevel@tonic-gate 18517c478bd9Sstevel@tonic-gate current_allocation = session_table_count * sizeof (void *); 18527c478bd9Sstevel@tonic-gate new_allocation = need * sizeof (void *); 18537c478bd9Sstevel@tonic-gate 18547c478bd9Sstevel@tonic-gate /* 18557c478bd9Sstevel@tonic-gate * Memory needed to grow the session table is checked 18567c478bd9Sstevel@tonic-gate * against the project.max-crypto-memory resource control. 18577c478bd9Sstevel@tonic-gate */ 1858c1a9a9c3Skrishna if ((rv = crypto_buffer_check(new_allocation - current_allocation)) != 1859c1a9a9c3Skrishna CRYPTO_SUCCESS) { 1860c1a9a9c3Skrishna return (rv); 18617c478bd9Sstevel@tonic-gate } 18627c478bd9Sstevel@tonic-gate 18637c478bd9Sstevel@tonic-gate /* drop lock while we allocate memory */ 18647c478bd9Sstevel@tonic-gate mutex_exit(&cm->cm_lock); 18657c478bd9Sstevel@tonic-gate new = kmem_zalloc(new_allocation, KM_SLEEP); 18667c478bd9Sstevel@tonic-gate mutex_enter(&cm->cm_lock); 18677c478bd9Sstevel@tonic-gate 18687c478bd9Sstevel@tonic-gate /* check if another thread increased the table size */ 18697c478bd9Sstevel@tonic-gate if (session_table_count != cm->cm_session_table_count) { 18707c478bd9Sstevel@tonic-gate kmem_free(new, new_allocation); 18717c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 18727c478bd9Sstevel@tonic-gate } 18737c478bd9Sstevel@tonic-gate 18747c478bd9Sstevel@tonic-gate bcopy(session_table, new, current_allocation); 18757c478bd9Sstevel@tonic-gate kmem_free(session_table, current_allocation); 18767c478bd9Sstevel@tonic-gate cm->cm_session_table = new; 18777c478bd9Sstevel@tonic-gate cm->cm_session_table_count += CRYPTO_SESSION_CHUNK; 18787c478bd9Sstevel@tonic-gate 18797c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 18807c478bd9Sstevel@tonic-gate } 18817c478bd9Sstevel@tonic-gate 18827c478bd9Sstevel@tonic-gate /* 18837c478bd9Sstevel@tonic-gate * Find unused entry in session table and return it's index. 18847c478bd9Sstevel@tonic-gate * Initialize session table entry. 18857c478bd9Sstevel@tonic-gate */ 18867c478bd9Sstevel@tonic-gate /* ARGSUSED */ 18877c478bd9Sstevel@tonic-gate static int 18887c478bd9Sstevel@tonic-gate crypto_open_session(dev_t dev, uint_t flags, crypto_session_id_t *session_index, 18897c478bd9Sstevel@tonic-gate crypto_provider_id_t provider_id) 18907c478bd9Sstevel@tonic-gate { 18917c478bd9Sstevel@tonic-gate crypto_session_data_t **session_table; 18927c478bd9Sstevel@tonic-gate crypto_session_data_t *sp; 18937c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 18947c478bd9Sstevel@tonic-gate uint_t session_table_count; 18957c478bd9Sstevel@tonic-gate uint_t i; 18967c478bd9Sstevel@tonic-gate int rv; 18977c478bd9Sstevel@tonic-gate crypto_provider_session_t *ps; 18987c478bd9Sstevel@tonic-gate kcf_provider_desc_t *provider; 18997c478bd9Sstevel@tonic-gate 19007c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 19017c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "crypto_open_session: failed holding minor"); 19027c478bd9Sstevel@tonic-gate return (CRYPTO_FAILED); 19037c478bd9Sstevel@tonic-gate } 19047c478bd9Sstevel@tonic-gate 19057c478bd9Sstevel@tonic-gate /* initialize provider_array */ 19067c478bd9Sstevel@tonic-gate if (cm->cm_provider_array == NULL) { 19077c478bd9Sstevel@tonic-gate rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST); 19087c478bd9Sstevel@tonic-gate if (rv != 0) { 19097c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 19107c478bd9Sstevel@tonic-gate return (rv); 19117c478bd9Sstevel@tonic-gate } 19127c478bd9Sstevel@tonic-gate } 19137c478bd9Sstevel@tonic-gate 19147c478bd9Sstevel@tonic-gate mutex_enter(&cm->cm_lock); 19157c478bd9Sstevel@tonic-gate /* index must be less than count of providers */ 19167c478bd9Sstevel@tonic-gate if (provider_id >= cm->cm_provider_count) { 19177c478bd9Sstevel@tonic-gate mutex_exit(&cm->cm_lock); 19187c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 19197c478bd9Sstevel@tonic-gate return (CRYPTO_INVALID_PROVIDER_ID); 19207c478bd9Sstevel@tonic-gate } 19217c478bd9Sstevel@tonic-gate ASSERT(cm->cm_provider_array != NULL); 19227c478bd9Sstevel@tonic-gate 19237c478bd9Sstevel@tonic-gate rv = crypto_get_provider_session(cm, provider_id, &ps); 19247c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) { 19257c478bd9Sstevel@tonic-gate mutex_exit(&cm->cm_lock); 19267c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 19277c478bd9Sstevel@tonic-gate return (rv); 19287c478bd9Sstevel@tonic-gate } 19297c478bd9Sstevel@tonic-gate provider = cm->cm_provider_array[provider_id]; 19307c478bd9Sstevel@tonic-gate 19317c478bd9Sstevel@tonic-gate again: 19327c478bd9Sstevel@tonic-gate session_table_count = cm->cm_session_table_count; 19337c478bd9Sstevel@tonic-gate session_table = cm->cm_session_table; 19347c478bd9Sstevel@tonic-gate 19357c478bd9Sstevel@tonic-gate /* session handles start with 1 */ 19367c478bd9Sstevel@tonic-gate for (i = 1; i < session_table_count; i++) { 19377c478bd9Sstevel@tonic-gate if (session_table[i] == NULL) 19387c478bd9Sstevel@tonic-gate break; 19397c478bd9Sstevel@tonic-gate } 19407c478bd9Sstevel@tonic-gate 19417c478bd9Sstevel@tonic-gate if (i == session_table_count || session_table_count == 0) { 19427c478bd9Sstevel@tonic-gate if ((rv = grow_session_table(cm)) != CRYPTO_SUCCESS) { 19437c478bd9Sstevel@tonic-gate crypto_release_provider_session(cm, ps); 19447c478bd9Sstevel@tonic-gate mutex_exit(&cm->cm_lock); 19457c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 19467c478bd9Sstevel@tonic-gate return (rv); 19477c478bd9Sstevel@tonic-gate } 19487c478bd9Sstevel@tonic-gate goto again; 19497c478bd9Sstevel@tonic-gate } 19507c478bd9Sstevel@tonic-gate 19517c478bd9Sstevel@tonic-gate sp = kmem_cache_alloc(crypto_session_cache, KM_SLEEP); 19527c478bd9Sstevel@tonic-gate sp->sd_flags = 0; 19537c478bd9Sstevel@tonic-gate sp->sd_find_init_cookie = NULL; 19547c478bd9Sstevel@tonic-gate sp->sd_digest_ctx = NULL; 19557c478bd9Sstevel@tonic-gate sp->sd_encr_ctx = NULL; 19567c478bd9Sstevel@tonic-gate sp->sd_decr_ctx = NULL; 19577c478bd9Sstevel@tonic-gate sp->sd_sign_ctx = NULL; 19587c478bd9Sstevel@tonic-gate sp->sd_verify_ctx = NULL; 19597c478bd9Sstevel@tonic-gate sp->sd_sign_recover_ctx = NULL; 19607c478bd9Sstevel@tonic-gate sp->sd_verify_recover_ctx = NULL; 19617c478bd9Sstevel@tonic-gate mutex_init(&sp->sd_lock, NULL, MUTEX_DRIVER, NULL); 19627c478bd9Sstevel@tonic-gate cv_init(&sp->sd_cv, NULL, CV_DRIVER, NULL); 19637c478bd9Sstevel@tonic-gate KCF_PROV_REFHOLD(provider); 19647c478bd9Sstevel@tonic-gate sp->sd_provider = provider; 19657c478bd9Sstevel@tonic-gate sp->sd_provider_session = ps; 19662d794da1Skrishna 19672d794da1Skrishna /* See the comment for CRYPTO_PRE_APPROVED_LIMIT. */ 19682d794da1Skrishna if ((rv = crypto_buffer_check(crypto_pre_approved_limit)) != 19692d794da1Skrishna CRYPTO_SUCCESS) { 19702d794da1Skrishna sp->sd_pre_approved_amount = 0; 19712d794da1Skrishna } else { 197295014fbbSDan OpenSolaris Anderson sp->sd_pre_approved_amount = (int)crypto_pre_approved_limit; 19732d794da1Skrishna } 19742d794da1Skrishna 19757c478bd9Sstevel@tonic-gate cm->cm_session_table[i] = sp; 19767c478bd9Sstevel@tonic-gate mutex_exit(&cm->cm_lock); 19777c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 19787c478bd9Sstevel@tonic-gate *session_index = i; 19797c478bd9Sstevel@tonic-gate 19807c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 19817c478bd9Sstevel@tonic-gate } 19827c478bd9Sstevel@tonic-gate 19837c478bd9Sstevel@tonic-gate /* 19847c478bd9Sstevel@tonic-gate * Close a session. 19857c478bd9Sstevel@tonic-gate */ 19867c478bd9Sstevel@tonic-gate static int 19877c478bd9Sstevel@tonic-gate crypto_close_session(dev_t dev, crypto_session_id_t session_index) 19887c478bd9Sstevel@tonic-gate { 19897c478bd9Sstevel@tonic-gate crypto_session_data_t **session_table; 19907c478bd9Sstevel@tonic-gate crypto_session_data_t *sp; 19917c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 19927c478bd9Sstevel@tonic-gate 19937c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 19947c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "crypto_close_session: failed holding minor"); 19957c478bd9Sstevel@tonic-gate return (CRYPTO_FAILED); 19967c478bd9Sstevel@tonic-gate } 19977c478bd9Sstevel@tonic-gate 19987c478bd9Sstevel@tonic-gate mutex_enter(&cm->cm_lock); 19997c478bd9Sstevel@tonic-gate session_table = cm->cm_session_table; 20007c478bd9Sstevel@tonic-gate 20017c478bd9Sstevel@tonic-gate if ((session_index) == 0 || 20027c478bd9Sstevel@tonic-gate (session_index >= cm->cm_session_table_count)) { 20037c478bd9Sstevel@tonic-gate mutex_exit(&cm->cm_lock); 20047c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 20057c478bd9Sstevel@tonic-gate return (CRYPTO_SESSION_HANDLE_INVALID); 20067c478bd9Sstevel@tonic-gate } 20077c478bd9Sstevel@tonic-gate 20087c478bd9Sstevel@tonic-gate sp = session_table[session_index]; 20097c478bd9Sstevel@tonic-gate if (sp == NULL) { 20107c478bd9Sstevel@tonic-gate mutex_exit(&cm->cm_lock); 20117c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 20127c478bd9Sstevel@tonic-gate return (CRYPTO_SESSION_HANDLE_INVALID); 20137c478bd9Sstevel@tonic-gate } 20147c478bd9Sstevel@tonic-gate /* 20157c478bd9Sstevel@tonic-gate * If session is in use, free it when the thread 20167c478bd9Sstevel@tonic-gate * finishes with the session. 20177c478bd9Sstevel@tonic-gate */ 20187c478bd9Sstevel@tonic-gate mutex_enter(&sp->sd_lock); 20197c478bd9Sstevel@tonic-gate if (sp->sd_flags & CRYPTO_SESSION_IS_BUSY) { 20207c478bd9Sstevel@tonic-gate sp->sd_flags |= CRYPTO_SESSION_IS_CLOSED; 20217c478bd9Sstevel@tonic-gate mutex_exit(&sp->sd_lock); 20227c478bd9Sstevel@tonic-gate } else { 20232d794da1Skrishna ASSERT(sp->sd_pre_approved_amount == 0 || 20242d794da1Skrishna sp->sd_pre_approved_amount == crypto_pre_approved_limit); 20252d794da1Skrishna CRYPTO_DECREMENT_RCTL(sp->sd_pre_approved_amount); 20262d794da1Skrishna 20277c478bd9Sstevel@tonic-gate if (sp->sd_find_init_cookie != NULL) { 20287c478bd9Sstevel@tonic-gate (void) crypto_free_find_ctx(sp); 20297c478bd9Sstevel@tonic-gate } 20307c478bd9Sstevel@tonic-gate 20317c478bd9Sstevel@tonic-gate crypto_release_provider_session(cm, sp->sd_provider_session); 20327c478bd9Sstevel@tonic-gate KCF_PROV_REFRELE(sp->sd_provider); 20337c478bd9Sstevel@tonic-gate CRYPTO_CANCEL_ALL_CTX(sp); 20347c478bd9Sstevel@tonic-gate mutex_destroy(&sp->sd_lock); 20357c478bd9Sstevel@tonic-gate cv_destroy(&sp->sd_cv); 20367c478bd9Sstevel@tonic-gate kmem_cache_free(crypto_session_cache, sp); 20377c478bd9Sstevel@tonic-gate session_table[session_index] = NULL; 20387c478bd9Sstevel@tonic-gate } 20397c478bd9Sstevel@tonic-gate 20407c478bd9Sstevel@tonic-gate mutex_exit(&cm->cm_lock); 20417c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 20427c478bd9Sstevel@tonic-gate 20437c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 20447c478bd9Sstevel@tonic-gate } 20457c478bd9Sstevel@tonic-gate 20467c478bd9Sstevel@tonic-gate /* 20477c478bd9Sstevel@tonic-gate * This ioctl opens a session and returns the session ID in os_session. 20487c478bd9Sstevel@tonic-gate */ 20497c478bd9Sstevel@tonic-gate /* ARGSUSED */ 20507c478bd9Sstevel@tonic-gate static int 20517c478bd9Sstevel@tonic-gate open_session(dev_t dev, caddr_t arg, int mode, int *rval) 20527c478bd9Sstevel@tonic-gate { 20537c478bd9Sstevel@tonic-gate crypto_open_session_t open_session; 20547c478bd9Sstevel@tonic-gate crypto_session_id_t session; 20557c478bd9Sstevel@tonic-gate int rv; 20567c478bd9Sstevel@tonic-gate 20577c478bd9Sstevel@tonic-gate if (copyin(arg, &open_session, sizeof (open_session)) != 0) 20587c478bd9Sstevel@tonic-gate return (EFAULT); 20597c478bd9Sstevel@tonic-gate 20607c478bd9Sstevel@tonic-gate rv = crypto_open_session(dev, open_session.os_flags, 20617c478bd9Sstevel@tonic-gate &session, open_session.os_provider_id); 20627c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) { 20637c478bd9Sstevel@tonic-gate open_session.os_return_value = rv; 20647c478bd9Sstevel@tonic-gate if (copyout(&open_session, arg, sizeof (open_session)) != 0) { 20657c478bd9Sstevel@tonic-gate return (EFAULT); 20667c478bd9Sstevel@tonic-gate } 20677c478bd9Sstevel@tonic-gate return (0); 20687c478bd9Sstevel@tonic-gate } 20697c478bd9Sstevel@tonic-gate 20707c478bd9Sstevel@tonic-gate open_session.os_session = session; 20717c478bd9Sstevel@tonic-gate open_session.os_return_value = CRYPTO_SUCCESS; 20727c478bd9Sstevel@tonic-gate 20737c478bd9Sstevel@tonic-gate if (copyout(&open_session, arg, sizeof (open_session)) != 0) { 20747c478bd9Sstevel@tonic-gate return (EFAULT); 20757c478bd9Sstevel@tonic-gate } 20767c478bd9Sstevel@tonic-gate return (0); 20777c478bd9Sstevel@tonic-gate } 20787c478bd9Sstevel@tonic-gate 20797c478bd9Sstevel@tonic-gate /* 20807c478bd9Sstevel@tonic-gate * This ioctl closes a session. 20817c478bd9Sstevel@tonic-gate */ 20827c478bd9Sstevel@tonic-gate /* ARGSUSED */ 20837c478bd9Sstevel@tonic-gate static int 20847c478bd9Sstevel@tonic-gate close_session(dev_t dev, caddr_t arg, int mode, int *rval) 20857c478bd9Sstevel@tonic-gate { 20867c478bd9Sstevel@tonic-gate crypto_close_session_t close_session; 20877c478bd9Sstevel@tonic-gate int rv; 20887c478bd9Sstevel@tonic-gate 20897c478bd9Sstevel@tonic-gate if (copyin(arg, &close_session, sizeof (close_session)) != 0) 20907c478bd9Sstevel@tonic-gate return (EFAULT); 20917c478bd9Sstevel@tonic-gate 20927c478bd9Sstevel@tonic-gate rv = crypto_close_session(dev, close_session.cs_session); 20937c478bd9Sstevel@tonic-gate close_session.cs_return_value = rv; 20947c478bd9Sstevel@tonic-gate if (copyout(&close_session, arg, sizeof (close_session)) != 0) { 20957c478bd9Sstevel@tonic-gate return (EFAULT); 20967c478bd9Sstevel@tonic-gate } 20977c478bd9Sstevel@tonic-gate return (0); 20987c478bd9Sstevel@tonic-gate } 20997c478bd9Sstevel@tonic-gate 21007c478bd9Sstevel@tonic-gate /* 21017c478bd9Sstevel@tonic-gate * Copy data model dependent mechanism structure into a kernel mechanism 21027c478bd9Sstevel@tonic-gate * structure. Allocate param storage if necessary. 21037c478bd9Sstevel@tonic-gate */ 21047c478bd9Sstevel@tonic-gate static boolean_t 21052d794da1Skrishna copyin_mech(int mode, crypto_session_data_t *sp, crypto_mechanism_t *in_mech, 21062d794da1Skrishna crypto_mechanism_t *out_mech, size_t *out_rctl_bytes, 21072d794da1Skrishna boolean_t *out_rctl_chk, int *out_rv, int *out_error) 21087c478bd9Sstevel@tonic-gate { 21097c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_mechanism, mech); 21107c478bd9Sstevel@tonic-gate caddr_t param; 21117c478bd9Sstevel@tonic-gate size_t param_len; 21122d794da1Skrishna size_t rctl_bytes = 0; 21137c478bd9Sstevel@tonic-gate int error = 0; 21147c478bd9Sstevel@tonic-gate int rv = 0; 21157c478bd9Sstevel@tonic-gate 21167c478bd9Sstevel@tonic-gate STRUCT_INIT(mech, mode); 21177c478bd9Sstevel@tonic-gate bcopy(in_mech, STRUCT_BUF(mech), STRUCT_SIZE(mech)); 21187c478bd9Sstevel@tonic-gate param = STRUCT_FGETP(mech, cm_param); 21197c478bd9Sstevel@tonic-gate param_len = STRUCT_FGET(mech, cm_param_len); 21207c478bd9Sstevel@tonic-gate out_mech->cm_type = STRUCT_FGET(mech, cm_type); 21217c478bd9Sstevel@tonic-gate out_mech->cm_param = NULL; 21227c478bd9Sstevel@tonic-gate out_mech->cm_param_len = 0; 21237c478bd9Sstevel@tonic-gate if (param != NULL && param_len != 0) { 21247c478bd9Sstevel@tonic-gate if (param_len > crypto_max_buffer_len) { 21257c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "copyin_mech: buffer greater than " 21267c478bd9Sstevel@tonic-gate "%ld bytes, pid = %d", crypto_max_buffer_len, 21277c478bd9Sstevel@tonic-gate curproc->p_pid); 21287c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 21297c478bd9Sstevel@tonic-gate goto out; 21307c478bd9Sstevel@tonic-gate } 21317c478bd9Sstevel@tonic-gate 21322d794da1Skrishna rv = CRYPTO_BUFFER_CHECK(sp, param_len, *out_rctl_chk); 21337c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) { 21347c478bd9Sstevel@tonic-gate goto out; 21357c478bd9Sstevel@tonic-gate } 21367c478bd9Sstevel@tonic-gate rctl_bytes = param_len; 21372d794da1Skrishna 21387c478bd9Sstevel@tonic-gate out_mech->cm_param = kmem_alloc(param_len, KM_SLEEP); 21397c478bd9Sstevel@tonic-gate if (copyin((char *)param, out_mech->cm_param, param_len) != 0) { 21407c478bd9Sstevel@tonic-gate kmem_free(out_mech->cm_param, param_len); 21417c478bd9Sstevel@tonic-gate out_mech->cm_param = NULL; 21427c478bd9Sstevel@tonic-gate error = EFAULT; 21437c478bd9Sstevel@tonic-gate goto out; 21447c478bd9Sstevel@tonic-gate } 21457c478bd9Sstevel@tonic-gate out_mech->cm_param_len = param_len; 21467c478bd9Sstevel@tonic-gate } 21477c478bd9Sstevel@tonic-gate out: 21487c478bd9Sstevel@tonic-gate *out_rctl_bytes = rctl_bytes; 21497c478bd9Sstevel@tonic-gate *out_rv = rv; 21507c478bd9Sstevel@tonic-gate *out_error = error; 21517c478bd9Sstevel@tonic-gate return ((rv | error) ? B_FALSE : B_TRUE); 21527c478bd9Sstevel@tonic-gate } 21537c478bd9Sstevel@tonic-gate 21547c478bd9Sstevel@tonic-gate /* 21557c478bd9Sstevel@tonic-gate * Free key attributes when key type is CRYPTO_KEY_ATTR_LIST. 21567c478bd9Sstevel@tonic-gate * The crypto_key structure is not freed. 21577c478bd9Sstevel@tonic-gate */ 21587c478bd9Sstevel@tonic-gate static void 21597c478bd9Sstevel@tonic-gate crypto_free_key_attributes(crypto_key_t *key) 21607c478bd9Sstevel@tonic-gate { 21617c478bd9Sstevel@tonic-gate crypto_object_attribute_t *attrs; 21627c478bd9Sstevel@tonic-gate size_t len = 0; 21637c478bd9Sstevel@tonic-gate int i; 21647c478bd9Sstevel@tonic-gate 21657c478bd9Sstevel@tonic-gate ASSERT(key->ck_format == CRYPTO_KEY_ATTR_LIST); 21667c478bd9Sstevel@tonic-gate if (key->ck_count == 0 || key->ck_attrs == NULL) 21677c478bd9Sstevel@tonic-gate return; 21687c478bd9Sstevel@tonic-gate 21697c478bd9Sstevel@tonic-gate /* compute the size of the container */ 21707c478bd9Sstevel@tonic-gate len = key->ck_count * sizeof (crypto_object_attribute_t); 21717c478bd9Sstevel@tonic-gate 21727c478bd9Sstevel@tonic-gate /* total up the size of all attributes in the container */ 21737c478bd9Sstevel@tonic-gate for (i = 0; i < key->ck_count; i++) { 21747c478bd9Sstevel@tonic-gate attrs = &key->ck_attrs[i]; 21757c478bd9Sstevel@tonic-gate if (attrs->oa_value_len != 0 && 21767c478bd9Sstevel@tonic-gate attrs->oa_value != NULL) { 21777c478bd9Sstevel@tonic-gate len += roundup(attrs->oa_value_len, sizeof (caddr_t)); 21787c478bd9Sstevel@tonic-gate } 21797c478bd9Sstevel@tonic-gate } 21807c478bd9Sstevel@tonic-gate 21817c478bd9Sstevel@tonic-gate bzero(key->ck_attrs, len); 21827c478bd9Sstevel@tonic-gate kmem_free(key->ck_attrs, len); 21837c478bd9Sstevel@tonic-gate } 21847c478bd9Sstevel@tonic-gate 21857c478bd9Sstevel@tonic-gate /* 21867c478bd9Sstevel@tonic-gate * Frees allocated storage in the key structure, but doesn't free 21877c478bd9Sstevel@tonic-gate * the key structure. 21887c478bd9Sstevel@tonic-gate */ 21897c478bd9Sstevel@tonic-gate static void 21907c478bd9Sstevel@tonic-gate free_crypto_key(crypto_key_t *key) 21917c478bd9Sstevel@tonic-gate { 21927c478bd9Sstevel@tonic-gate switch (key->ck_format) { 21937c478bd9Sstevel@tonic-gate case CRYPTO_KEY_RAW: { 21947c478bd9Sstevel@tonic-gate size_t len; 21957c478bd9Sstevel@tonic-gate 21967c478bd9Sstevel@tonic-gate if (key->ck_length == 0 || key->ck_data == NULL) 21977c478bd9Sstevel@tonic-gate break; 21987c478bd9Sstevel@tonic-gate 21997c478bd9Sstevel@tonic-gate len = CRYPTO_BITS2BYTES(key->ck_length); 22007c478bd9Sstevel@tonic-gate bzero(key->ck_data, len); 22017c478bd9Sstevel@tonic-gate kmem_free(key->ck_data, len); 22027c478bd9Sstevel@tonic-gate break; 22037c478bd9Sstevel@tonic-gate } 22047c478bd9Sstevel@tonic-gate 22057c478bd9Sstevel@tonic-gate case CRYPTO_KEY_ATTR_LIST: 22067c478bd9Sstevel@tonic-gate crypto_free_key_attributes(key); 22077c478bd9Sstevel@tonic-gate break; 22087c478bd9Sstevel@tonic-gate 22097c478bd9Sstevel@tonic-gate default: 22107c478bd9Sstevel@tonic-gate break; 22117c478bd9Sstevel@tonic-gate } 22127c478bd9Sstevel@tonic-gate } 22137c478bd9Sstevel@tonic-gate 22147c478bd9Sstevel@tonic-gate /* 22157c478bd9Sstevel@tonic-gate * Copy in an array of crypto_object_attribute structures from user-space. 22167c478bd9Sstevel@tonic-gate * Kernel memory is allocated for the array and the value of each attribute 22177c478bd9Sstevel@tonic-gate * in the array. Since unprivileged users can specify the size of attributes, 22187c478bd9Sstevel@tonic-gate * the amount of memory needed is charged against the 22197c478bd9Sstevel@tonic-gate * project.max-crypto-memory resource control. 22207c478bd9Sstevel@tonic-gate * 22217c478bd9Sstevel@tonic-gate * Attribute values are copied in from user-space if copyin_value is set to 22227c478bd9Sstevel@tonic-gate * B_TRUE. This routine returns B_TRUE if the copyin was successful. 22237c478bd9Sstevel@tonic-gate */ 22247c478bd9Sstevel@tonic-gate static boolean_t 22252d794da1Skrishna copyin_attributes(int mode, crypto_session_data_t *sp, 22262d794da1Skrishna uint_t count, caddr_t oc_attributes, 22277c478bd9Sstevel@tonic-gate crypto_object_attribute_t **k_attrs_out, size_t *k_attrs_size_out, 22287c478bd9Sstevel@tonic-gate caddr_t *u_attrs_out, int *out_rv, int *out_error, size_t *out_rctl_bytes, 22292d794da1Skrishna boolean_t *out_rctl_chk, boolean_t copyin_value) 22307c478bd9Sstevel@tonic-gate { 22317c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_object_attribute, oa); 22327c478bd9Sstevel@tonic-gate crypto_object_attribute_t *k_attrs = NULL; 22337c478bd9Sstevel@tonic-gate caddr_t attrs = NULL, ap, p, value; 22347c478bd9Sstevel@tonic-gate caddr_t k_attrs_buf; 22357c478bd9Sstevel@tonic-gate size_t k_attrs_len; 22367c478bd9Sstevel@tonic-gate size_t k_attrs_buf_len = 0; 22377c478bd9Sstevel@tonic-gate size_t k_attrs_total_len = 0; 22387c478bd9Sstevel@tonic-gate size_t tmp_len; 22397c478bd9Sstevel@tonic-gate size_t rctl_bytes = 0; 22407c478bd9Sstevel@tonic-gate size_t len = 0; 22417c478bd9Sstevel@tonic-gate size_t value_len; 22427c478bd9Sstevel@tonic-gate int error = 0; 22437c478bd9Sstevel@tonic-gate int rv = 0; 22447c478bd9Sstevel@tonic-gate int i; 22457c478bd9Sstevel@tonic-gate 22467c478bd9Sstevel@tonic-gate STRUCT_INIT(oa, mode); 22477c478bd9Sstevel@tonic-gate 22487c478bd9Sstevel@tonic-gate if (count == 0) { 22497c478bd9Sstevel@tonic-gate rv = CRYPTO_SUCCESS; 22507c478bd9Sstevel@tonic-gate goto out; 22517c478bd9Sstevel@tonic-gate } 22527c478bd9Sstevel@tonic-gate 22537c478bd9Sstevel@tonic-gate if (count > CRYPTO_MAX_ATTRIBUTE_COUNT) { 22547c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 22557c478bd9Sstevel@tonic-gate goto out; 22567c478bd9Sstevel@tonic-gate } 22577c478bd9Sstevel@tonic-gate 22587c478bd9Sstevel@tonic-gate /* compute size of crypto_object_attribute array */ 22597c478bd9Sstevel@tonic-gate len = count * STRUCT_SIZE(oa); 22607c478bd9Sstevel@tonic-gate 22617c478bd9Sstevel@tonic-gate /* this allocation is not charged against the user's resource limit */ 22627c478bd9Sstevel@tonic-gate attrs = kmem_alloc(len, KM_SLEEP); 22637c478bd9Sstevel@tonic-gate if (copyin(oc_attributes, attrs, len) != 0) { 22647c478bd9Sstevel@tonic-gate error = EFAULT; 22657c478bd9Sstevel@tonic-gate goto out; 22667c478bd9Sstevel@tonic-gate } 22677c478bd9Sstevel@tonic-gate 22687c478bd9Sstevel@tonic-gate /* figure out how much memory to allocate for all of the attributes */ 22697c478bd9Sstevel@tonic-gate ap = attrs; 22707c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++) { 22717c478bd9Sstevel@tonic-gate bcopy(ap, STRUCT_BUF(oa), STRUCT_SIZE(oa)); 22727c478bd9Sstevel@tonic-gate tmp_len = roundup(STRUCT_FGET(oa, oa_value_len), 22737c478bd9Sstevel@tonic-gate sizeof (caddr_t)); 22747c478bd9Sstevel@tonic-gate if (tmp_len > crypto_max_buffer_len) { 22757c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "copyin_attributes: buffer greater " 22767c478bd9Sstevel@tonic-gate "than %ld bytes, pid = %d", crypto_max_buffer_len, 22777c478bd9Sstevel@tonic-gate curproc->p_pid); 22787c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 22797c478bd9Sstevel@tonic-gate goto out; 22807c478bd9Sstevel@tonic-gate } 22817c478bd9Sstevel@tonic-gate if (STRUCT_FGETP(oa, oa_value) != NULL) 22827c478bd9Sstevel@tonic-gate k_attrs_buf_len += tmp_len; 22837c478bd9Sstevel@tonic-gate ap += STRUCT_SIZE(oa); 22847c478bd9Sstevel@tonic-gate } 22857c478bd9Sstevel@tonic-gate 22867c478bd9Sstevel@tonic-gate k_attrs_len = count * sizeof (crypto_object_attribute_t); 22877c478bd9Sstevel@tonic-gate k_attrs_total_len = k_attrs_buf_len + k_attrs_len; 22882d794da1Skrishna 22892d794da1Skrishna rv = CRYPTO_BUFFER_CHECK(sp, k_attrs_total_len, *out_rctl_chk); 22907c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) { 22917c478bd9Sstevel@tonic-gate goto out; 22927c478bd9Sstevel@tonic-gate } 22932d794da1Skrishna rctl_bytes = k_attrs_total_len; 22947c478bd9Sstevel@tonic-gate 22957c478bd9Sstevel@tonic-gate /* one big allocation for everything */ 22967c478bd9Sstevel@tonic-gate k_attrs = kmem_alloc(k_attrs_total_len, KM_SLEEP); 22977c478bd9Sstevel@tonic-gate k_attrs_buf = (char *)k_attrs + k_attrs_len; 22987c478bd9Sstevel@tonic-gate 22997c478bd9Sstevel@tonic-gate ap = attrs; 23007c478bd9Sstevel@tonic-gate p = k_attrs_buf; 23017c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++) { 23027c478bd9Sstevel@tonic-gate bcopy(ap, STRUCT_BUF(oa), STRUCT_SIZE(oa)); 23037c478bd9Sstevel@tonic-gate k_attrs[i].oa_type = STRUCT_FGET(oa, oa_type); 23047c478bd9Sstevel@tonic-gate value = STRUCT_FGETP(oa, oa_value); 23057c478bd9Sstevel@tonic-gate value_len = STRUCT_FGET(oa, oa_value_len); 23067c478bd9Sstevel@tonic-gate if (value != NULL && value_len != 0 && copyin_value) { 23077c478bd9Sstevel@tonic-gate if (copyin(value, p, value_len) != 0) { 23087c478bd9Sstevel@tonic-gate kmem_free(k_attrs, k_attrs_total_len); 23097c478bd9Sstevel@tonic-gate k_attrs = NULL; 23107c478bd9Sstevel@tonic-gate error = EFAULT; 23117c478bd9Sstevel@tonic-gate goto out; 23127c478bd9Sstevel@tonic-gate } 23137c478bd9Sstevel@tonic-gate } 23147c478bd9Sstevel@tonic-gate 23155c2306d7Smcpowers if (value != NULL) { 23165c2306d7Smcpowers k_attrs[i].oa_value = p; 23175c2306d7Smcpowers p += roundup(value_len, sizeof (caddr_t)); 23185c2306d7Smcpowers } else { 23195c2306d7Smcpowers k_attrs[i].oa_value = NULL; 23205c2306d7Smcpowers } 23217c478bd9Sstevel@tonic-gate k_attrs[i].oa_value_len = value_len; 23227c478bd9Sstevel@tonic-gate ap += STRUCT_SIZE(oa); 23237c478bd9Sstevel@tonic-gate } 23247c478bd9Sstevel@tonic-gate out: 23257c478bd9Sstevel@tonic-gate if (attrs != NULL) { 23267c478bd9Sstevel@tonic-gate /* 23277c478bd9Sstevel@tonic-gate * Free the array if there is a failure or the caller 23287c478bd9Sstevel@tonic-gate * doesn't want the array to be returned. 23297c478bd9Sstevel@tonic-gate */ 23307c478bd9Sstevel@tonic-gate if (error != 0 || rv != CRYPTO_SUCCESS || u_attrs_out == NULL) { 23317c478bd9Sstevel@tonic-gate kmem_free(attrs, len); 23327c478bd9Sstevel@tonic-gate attrs = NULL; 23337c478bd9Sstevel@tonic-gate } 23347c478bd9Sstevel@tonic-gate } 23357c478bd9Sstevel@tonic-gate 23367c478bd9Sstevel@tonic-gate if (u_attrs_out != NULL) 23377c478bd9Sstevel@tonic-gate *u_attrs_out = attrs; 23387c478bd9Sstevel@tonic-gate if (k_attrs_size_out != NULL) 23397c478bd9Sstevel@tonic-gate *k_attrs_size_out = k_attrs_total_len; 23407c478bd9Sstevel@tonic-gate *k_attrs_out = k_attrs; 23417c478bd9Sstevel@tonic-gate *out_rctl_bytes = rctl_bytes; 23427c478bd9Sstevel@tonic-gate *out_rv = rv; 23437c478bd9Sstevel@tonic-gate *out_error = error; 23447c478bd9Sstevel@tonic-gate return ((rv | error) ? B_FALSE : B_TRUE); 23457c478bd9Sstevel@tonic-gate } 23467c478bd9Sstevel@tonic-gate 23477c478bd9Sstevel@tonic-gate /* 23487c478bd9Sstevel@tonic-gate * Copy data model dependent raw key into a kernel key 23497c478bd9Sstevel@tonic-gate * structure. Checks key length or attribute lengths against 23507c478bd9Sstevel@tonic-gate * resource controls before allocating memory. Returns B_TRUE 23517c478bd9Sstevel@tonic-gate * if both error and rv are set to 0. 23527c478bd9Sstevel@tonic-gate */ 23537c478bd9Sstevel@tonic-gate static boolean_t 23542d794da1Skrishna copyin_key(int mode, crypto_session_data_t *sp, crypto_key_t *in_key, 23552d794da1Skrishna crypto_key_t *out_key, size_t *out_rctl_bytes, 23562d794da1Skrishna boolean_t *out_rctl_chk, int *out_rv, int *out_error) 23577c478bd9Sstevel@tonic-gate { 23587c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_key, key); 23597c478bd9Sstevel@tonic-gate crypto_object_attribute_t *k_attrs = NULL; 23607c478bd9Sstevel@tonic-gate size_t key_bits; 23617c478bd9Sstevel@tonic-gate size_t key_bytes = 0; 23627c478bd9Sstevel@tonic-gate size_t rctl_bytes = 0; 23637c478bd9Sstevel@tonic-gate int count; 23647c478bd9Sstevel@tonic-gate int error = 0; 23657c478bd9Sstevel@tonic-gate int rv = CRYPTO_SUCCESS; 23667c478bd9Sstevel@tonic-gate 23677c478bd9Sstevel@tonic-gate STRUCT_INIT(key, mode); 23687c478bd9Sstevel@tonic-gate bcopy(in_key, STRUCT_BUF(key), STRUCT_SIZE(key)); 23697c478bd9Sstevel@tonic-gate out_key->ck_format = STRUCT_FGET(key, ck_format); 23707c478bd9Sstevel@tonic-gate switch (out_key->ck_format) { 23717c478bd9Sstevel@tonic-gate case CRYPTO_KEY_RAW: 23727c478bd9Sstevel@tonic-gate key_bits = STRUCT_FGET(key, ck_length); 23737c478bd9Sstevel@tonic-gate if (key_bits != 0) { 237495014fbbSDan OpenSolaris Anderson if (key_bits > 237595014fbbSDan OpenSolaris Anderson (CRYPTO_BYTES2BITS(crypto_max_buffer_len))) { 23767c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "copyin_key: buffer greater " 23777c478bd9Sstevel@tonic-gate "than %ld bytes, pid = %d", 23787c478bd9Sstevel@tonic-gate crypto_max_buffer_len, curproc->p_pid); 23797c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 23807c478bd9Sstevel@tonic-gate goto out; 23817c478bd9Sstevel@tonic-gate } 238295014fbbSDan OpenSolaris Anderson key_bytes = CRYPTO_BITS2BYTES(key_bits); 23837c478bd9Sstevel@tonic-gate 23842d794da1Skrishna rv = CRYPTO_BUFFER_CHECK(sp, key_bytes, 23852d794da1Skrishna *out_rctl_chk); 23867c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) { 23877c478bd9Sstevel@tonic-gate goto out; 23887c478bd9Sstevel@tonic-gate } 23892d794da1Skrishna rctl_bytes = key_bytes; 23907c478bd9Sstevel@tonic-gate 23917c478bd9Sstevel@tonic-gate out_key->ck_data = kmem_alloc(key_bytes, KM_SLEEP); 23927c478bd9Sstevel@tonic-gate 23937c478bd9Sstevel@tonic-gate if (copyin((char *)STRUCT_FGETP(key, ck_data), 23947c478bd9Sstevel@tonic-gate out_key->ck_data, key_bytes) != 0) { 23957c478bd9Sstevel@tonic-gate kmem_free(out_key->ck_data, key_bytes); 23967c478bd9Sstevel@tonic-gate out_key->ck_data = NULL; 23977c478bd9Sstevel@tonic-gate out_key->ck_length = 0; 23987c478bd9Sstevel@tonic-gate error = EFAULT; 23997c478bd9Sstevel@tonic-gate goto out; 24007c478bd9Sstevel@tonic-gate } 24017c478bd9Sstevel@tonic-gate } 240295014fbbSDan OpenSolaris Anderson out_key->ck_length = (ulong_t)key_bits; 24037c478bd9Sstevel@tonic-gate break; 24047c478bd9Sstevel@tonic-gate 24057c478bd9Sstevel@tonic-gate case CRYPTO_KEY_ATTR_LIST: 24067c478bd9Sstevel@tonic-gate count = STRUCT_FGET(key, ck_count); 24077c478bd9Sstevel@tonic-gate 24082d794da1Skrishna if (copyin_attributes(mode, sp, count, 24097c478bd9Sstevel@tonic-gate (caddr_t)STRUCT_FGETP(key, ck_attrs), &k_attrs, NULL, NULL, 24102d794da1Skrishna &rv, &error, &rctl_bytes, out_rctl_chk, B_TRUE)) { 24117c478bd9Sstevel@tonic-gate out_key->ck_count = count; 24127c478bd9Sstevel@tonic-gate out_key->ck_attrs = k_attrs; 24137c478bd9Sstevel@tonic-gate k_attrs = NULL; 24147c478bd9Sstevel@tonic-gate } else { 24157c478bd9Sstevel@tonic-gate out_key->ck_count = 0; 24167c478bd9Sstevel@tonic-gate out_key->ck_attrs = NULL; 24177c478bd9Sstevel@tonic-gate } 24187c478bd9Sstevel@tonic-gate break; 24197c478bd9Sstevel@tonic-gate 24207c478bd9Sstevel@tonic-gate case CRYPTO_KEY_REFERENCE: 24217c478bd9Sstevel@tonic-gate out_key->ck_obj_id = STRUCT_FGET(key, ck_obj_id); 24227c478bd9Sstevel@tonic-gate break; 24237c478bd9Sstevel@tonic-gate 24247c478bd9Sstevel@tonic-gate default: 24257c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 24267c478bd9Sstevel@tonic-gate } 24277c478bd9Sstevel@tonic-gate 24287c478bd9Sstevel@tonic-gate out: 24297c478bd9Sstevel@tonic-gate *out_rctl_bytes = rctl_bytes; 24307c478bd9Sstevel@tonic-gate *out_rv = rv; 24317c478bd9Sstevel@tonic-gate *out_error = error; 24327c478bd9Sstevel@tonic-gate return ((rv | error) ? B_FALSE : B_TRUE); 24337c478bd9Sstevel@tonic-gate } 24347c478bd9Sstevel@tonic-gate 24357c478bd9Sstevel@tonic-gate /* 24367c478bd9Sstevel@tonic-gate * This routine does two things: 24377c478bd9Sstevel@tonic-gate * 1. Given a crypto_minor structure and a session ID, it returns 24387c478bd9Sstevel@tonic-gate * a valid session pointer. 24397c478bd9Sstevel@tonic-gate * 2. It checks that the provider, to which the session has been opened, 24407c478bd9Sstevel@tonic-gate * has not been removed. 24417c478bd9Sstevel@tonic-gate */ 24427c478bd9Sstevel@tonic-gate static boolean_t 24437c478bd9Sstevel@tonic-gate get_session_ptr(crypto_session_id_t i, crypto_minor_t *cm, 24447c478bd9Sstevel@tonic-gate crypto_session_data_t **session_ptr, int *out_error, int *out_rv) 24457c478bd9Sstevel@tonic-gate { 24467c478bd9Sstevel@tonic-gate crypto_session_data_t *sp = NULL; 24477c478bd9Sstevel@tonic-gate int rv = CRYPTO_SESSION_HANDLE_INVALID; 24487c478bd9Sstevel@tonic-gate int error = 0; 24497c478bd9Sstevel@tonic-gate 24507c478bd9Sstevel@tonic-gate mutex_enter(&cm->cm_lock); 24517c478bd9Sstevel@tonic-gate if ((i < cm->cm_session_table_count) && 24527c478bd9Sstevel@tonic-gate (cm->cm_session_table[i] != NULL)) { 24537c478bd9Sstevel@tonic-gate sp = cm->cm_session_table[i]; 24547c478bd9Sstevel@tonic-gate mutex_enter(&sp->sd_lock); 24557c478bd9Sstevel@tonic-gate mutex_exit(&cm->cm_lock); 24567c478bd9Sstevel@tonic-gate while (sp->sd_flags & CRYPTO_SESSION_IS_BUSY) { 24577c478bd9Sstevel@tonic-gate if (cv_wait_sig(&sp->sd_cv, &sp->sd_lock) == 0) { 24587c478bd9Sstevel@tonic-gate mutex_exit(&sp->sd_lock); 24597c478bd9Sstevel@tonic-gate sp = NULL; 24607c478bd9Sstevel@tonic-gate error = EINTR; 24617c478bd9Sstevel@tonic-gate goto out; 24627c478bd9Sstevel@tonic-gate } 24637c478bd9Sstevel@tonic-gate } 24647c478bd9Sstevel@tonic-gate 24657c478bd9Sstevel@tonic-gate if (sp->sd_flags & CRYPTO_SESSION_IS_CLOSED) { 24667c478bd9Sstevel@tonic-gate mutex_exit(&sp->sd_lock); 24677c478bd9Sstevel@tonic-gate sp = NULL; 24687c478bd9Sstevel@tonic-gate goto out; 24697c478bd9Sstevel@tonic-gate } 24707c478bd9Sstevel@tonic-gate 24717c478bd9Sstevel@tonic-gate if (KCF_IS_PROV_REMOVED(sp->sd_provider)) { 24727c478bd9Sstevel@tonic-gate mutex_exit(&sp->sd_lock); 24737c478bd9Sstevel@tonic-gate sp = NULL; 24747c478bd9Sstevel@tonic-gate rv = CRYPTO_DEVICE_ERROR; 24757c478bd9Sstevel@tonic-gate goto out; 24767c478bd9Sstevel@tonic-gate } 24777c478bd9Sstevel@tonic-gate 24787c478bd9Sstevel@tonic-gate rv = CRYPTO_SUCCESS; 24797c478bd9Sstevel@tonic-gate sp->sd_flags |= CRYPTO_SESSION_IS_BUSY; 24807c478bd9Sstevel@tonic-gate mutex_exit(&sp->sd_lock); 24817c478bd9Sstevel@tonic-gate } else { 24827c478bd9Sstevel@tonic-gate mutex_exit(&cm->cm_lock); 24837c478bd9Sstevel@tonic-gate } 24847c478bd9Sstevel@tonic-gate out: 24857c478bd9Sstevel@tonic-gate *session_ptr = sp; 24867c478bd9Sstevel@tonic-gate *out_error = error; 24877c478bd9Sstevel@tonic-gate *out_rv = rv; 24887c478bd9Sstevel@tonic-gate return ((rv == CRYPTO_SUCCESS && error == 0) ? B_TRUE : B_FALSE); 24897c478bd9Sstevel@tonic-gate } 24907c478bd9Sstevel@tonic-gate 24912d794da1Skrishna #define CRYPTO_SESSION_RELE(s) if ((s) != NULL) { \ 24927c478bd9Sstevel@tonic-gate mutex_enter(&((s)->sd_lock)); \ 24937c478bd9Sstevel@tonic-gate (s)->sd_flags &= ~CRYPTO_SESSION_IS_BUSY; \ 24947c478bd9Sstevel@tonic-gate cv_broadcast(&(s)->sd_cv); \ 24957c478bd9Sstevel@tonic-gate mutex_exit(&((s)->sd_lock)); \ 24967c478bd9Sstevel@tonic-gate } 24977c478bd9Sstevel@tonic-gate 24987c478bd9Sstevel@tonic-gate /* ARGSUSED */ 24997c478bd9Sstevel@tonic-gate static int 25007c478bd9Sstevel@tonic-gate encrypt_init(dev_t dev, caddr_t arg, int mode, int *rval) 25017c478bd9Sstevel@tonic-gate { 25027c478bd9Sstevel@tonic-gate return (cipher_init(dev, arg, mode, crypto_encrypt_init_prov)); 25037c478bd9Sstevel@tonic-gate } 25047c478bd9Sstevel@tonic-gate 25057c478bd9Sstevel@tonic-gate /* ARGSUSED */ 25067c478bd9Sstevel@tonic-gate static int 25077c478bd9Sstevel@tonic-gate decrypt_init(dev_t dev, caddr_t arg, int mode, int *rval) 25087c478bd9Sstevel@tonic-gate { 25097c478bd9Sstevel@tonic-gate return (cipher_init(dev, arg, mode, crypto_decrypt_init_prov)); 25107c478bd9Sstevel@tonic-gate } 25117c478bd9Sstevel@tonic-gate 25127c478bd9Sstevel@tonic-gate /* 2513894b2776Smcpowers * umech is a mechanism structure that has been copied from user address 2514894b2776Smcpowers * space into kernel address space. Only one copyin has been done. 2515894b2776Smcpowers * The mechanism parameter, if non-null, still points to user address space. 2516894b2776Smcpowers * If the mechanism parameter contains pointers, they are pointers into 2517894b2776Smcpowers * user address space. 2518894b2776Smcpowers * 2519894b2776Smcpowers * kmech is a umech with all pointers and structures in kernel address space. 2520894b2776Smcpowers * 2521894b2776Smcpowers * This routine calls the provider's entry point to copy a umech parameter 2522894b2776Smcpowers * into kernel address space. Kernel memory is allocated by the provider. 2523894b2776Smcpowers */ 2524894b2776Smcpowers static int 2525894b2776Smcpowers crypto_provider_copyin_mech_param(kcf_provider_desc_t *pd, 2526894b2776Smcpowers crypto_mechanism_t *umech, crypto_mechanism_t *kmech, int mode, int *error) 2527894b2776Smcpowers { 2528894b2776Smcpowers crypto_mech_type_t provider_mech_type; 2529894b2776Smcpowers int rv; 2530894b2776Smcpowers 2531894b2776Smcpowers /* get the provider's mech number */ 25326a1073f8Skrishna provider_mech_type = KCF_TO_PROV_MECHNUM(pd, umech->cm_type); 2533894b2776Smcpowers 2534894b2776Smcpowers kmech->cm_param = NULL; 2535894b2776Smcpowers kmech->cm_param_len = 0; 2536894b2776Smcpowers kmech->cm_type = provider_mech_type; 2537894b2776Smcpowers rv = KCF_PROV_COPYIN_MECH(pd, umech, kmech, error, mode); 2538894b2776Smcpowers kmech->cm_type = umech->cm_type; 2539894b2776Smcpowers 2540894b2776Smcpowers return (rv); 2541894b2776Smcpowers } 2542894b2776Smcpowers 2543894b2776Smcpowers /* 2544894b2776Smcpowers * umech is a mechanism structure that has been copied from user address 2545894b2776Smcpowers * space into kernel address space. Only one copyin has been done. 2546894b2776Smcpowers * The mechanism parameter, if non-null, still points to user address space. 2547894b2776Smcpowers * If the mechanism parameter contains pointers, they are pointers into 2548894b2776Smcpowers * user address space. 2549894b2776Smcpowers * 2550894b2776Smcpowers * kmech is a umech with all pointers and structures in kernel address space. 2551894b2776Smcpowers * 2552894b2776Smcpowers * This routine calls the provider's entry point to copy a kmech parameter 2553894b2776Smcpowers * into user address space using umech as a template containing 2554894b2776Smcpowers * user address pointers. 2555894b2776Smcpowers */ 2556894b2776Smcpowers static int 2557894b2776Smcpowers crypto_provider_copyout_mech_param(kcf_provider_desc_t *pd, 2558894b2776Smcpowers crypto_mechanism_t *kmech, crypto_mechanism_t *umech, int mode, int *error) 2559894b2776Smcpowers { 2560894b2776Smcpowers crypto_mech_type_t provider_mech_type; 2561894b2776Smcpowers int rv; 2562894b2776Smcpowers 2563894b2776Smcpowers /* get the provider's mech number */ 25646a1073f8Skrishna provider_mech_type = KCF_TO_PROV_MECHNUM(pd, umech->cm_type); 2565894b2776Smcpowers 2566894b2776Smcpowers kmech->cm_type = provider_mech_type; 2567894b2776Smcpowers rv = KCF_PROV_COPYOUT_MECH(pd, kmech, umech, error, mode); 2568894b2776Smcpowers kmech->cm_type = umech->cm_type; 2569894b2776Smcpowers 2570894b2776Smcpowers return (rv); 2571894b2776Smcpowers } 2572894b2776Smcpowers 2573894b2776Smcpowers /* 2574894b2776Smcpowers * Call the provider's entry point to free kernel memory that has been 2575894b2776Smcpowers * allocated for the mechanism's parameter. 2576894b2776Smcpowers */ 2577894b2776Smcpowers static void 2578894b2776Smcpowers crypto_free_mech(kcf_provider_desc_t *pd, boolean_t allocated_by_crypto_module, 2579894b2776Smcpowers crypto_mechanism_t *mech) 2580894b2776Smcpowers { 2581894b2776Smcpowers crypto_mech_type_t provider_mech_type; 2582894b2776Smcpowers 2583894b2776Smcpowers if (allocated_by_crypto_module) { 2584894b2776Smcpowers if (mech->cm_param != NULL) 2585894b2776Smcpowers kmem_free(mech->cm_param, mech->cm_param_len); 2586894b2776Smcpowers } else { 2587894b2776Smcpowers /* get the provider's mech number */ 25886a1073f8Skrishna provider_mech_type = KCF_TO_PROV_MECHNUM(pd, mech->cm_type); 2589894b2776Smcpowers 2590894b2776Smcpowers if (mech->cm_param != NULL && mech->cm_param_len != 0) { 2591894b2776Smcpowers mech->cm_type = provider_mech_type; 2592894b2776Smcpowers (void) KCF_PROV_FREE_MECH(pd, mech); 2593894b2776Smcpowers } 2594894b2776Smcpowers } 2595894b2776Smcpowers } 2596894b2776Smcpowers 2597894b2776Smcpowers /* 25987c478bd9Sstevel@tonic-gate * ASSUMPTION: crypto_encrypt_init and crypto_decrypt_init 25997c478bd9Sstevel@tonic-gate * structures are identical except for field names. 26007c478bd9Sstevel@tonic-gate */ 26017c478bd9Sstevel@tonic-gate static int 2602894b2776Smcpowers cipher_init(dev_t dev, caddr_t arg, int mode, int (*init)(crypto_provider_t, 26037c478bd9Sstevel@tonic-gate crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, 26047c478bd9Sstevel@tonic-gate crypto_ctx_template_t, crypto_context_t *, crypto_call_req_t *)) 26057c478bd9Sstevel@tonic-gate { 26067c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_encrypt_init, encrypt_init); 2607894b2776Smcpowers kcf_provider_desc_t *real_provider = NULL; 26087c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 26097c478bd9Sstevel@tonic-gate crypto_mechanism_t mech; 26107c478bd9Sstevel@tonic-gate crypto_key_t key; 26117c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 26122d794da1Skrishna crypto_session_data_t *sp = NULL; 26137c478bd9Sstevel@tonic-gate crypto_context_t cc; 26147c478bd9Sstevel@tonic-gate crypto_ctx_t **ctxpp; 26157c478bd9Sstevel@tonic-gate size_t mech_rctl_bytes = 0; 26162d794da1Skrishna boolean_t mech_rctl_chk = B_FALSE; 26177c478bd9Sstevel@tonic-gate size_t key_rctl_bytes = 0; 26182d794da1Skrishna boolean_t key_rctl_chk = B_FALSE; 26197c478bd9Sstevel@tonic-gate int error = 0; 26207c478bd9Sstevel@tonic-gate int rv; 2621894b2776Smcpowers boolean_t allocated_by_crypto_module = B_FALSE; 262272eff6e2Smcpowers crypto_func_group_t fg; 26237c478bd9Sstevel@tonic-gate 26247c478bd9Sstevel@tonic-gate STRUCT_INIT(encrypt_init, mode); 26257c478bd9Sstevel@tonic-gate 26267c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 26277c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "cipher_init: failed holding minor"); 26287c478bd9Sstevel@tonic-gate return (ENXIO); 26297c478bd9Sstevel@tonic-gate } 26307c478bd9Sstevel@tonic-gate 26317c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(encrypt_init), 26327c478bd9Sstevel@tonic-gate STRUCT_SIZE(encrypt_init)) != 0) { 26337c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 26347c478bd9Sstevel@tonic-gate return (EFAULT); 26357c478bd9Sstevel@tonic-gate } 26367c478bd9Sstevel@tonic-gate 26377c478bd9Sstevel@tonic-gate mech.cm_param = NULL; 26387c478bd9Sstevel@tonic-gate bzero(&key, sizeof (crypto_key_t)); 26397c478bd9Sstevel@tonic-gate 26407c478bd9Sstevel@tonic-gate session_id = STRUCT_FGET(encrypt_init, ei_session); 26417c478bd9Sstevel@tonic-gate 26427c478bd9Sstevel@tonic-gate if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 26432d794da1Skrishna goto out; 26447c478bd9Sstevel@tonic-gate } 26457c478bd9Sstevel@tonic-gate 2646894b2776Smcpowers bcopy(STRUCT_FADDR(encrypt_init, ei_mech), &mech.cm_type, 2647894b2776Smcpowers sizeof (crypto_mech_type_t)); 26487c478bd9Sstevel@tonic-gate 264972eff6e2Smcpowers if (init == crypto_encrypt_init_prov) { 265072eff6e2Smcpowers fg = CRYPTO_FG_ENCRYPT; 265172eff6e2Smcpowers } else { 265272eff6e2Smcpowers fg = CRYPTO_FG_DECRYPT; 265372eff6e2Smcpowers } 26547c478bd9Sstevel@tonic-gate 2655436935a1SVladimir Kotal /* We need the key length for provider selection so copy it in now. */ 2656436935a1SVladimir Kotal if (!copyin_key(mode, sp, STRUCT_FADDR(encrypt_init, ei_key), &key, 2657436935a1SVladimir Kotal &key_rctl_bytes, &key_rctl_chk, &rv, &error)) { 2658436935a1SVladimir Kotal goto out; 2659436935a1SVladimir Kotal } 2660436935a1SVladimir Kotal 2661436935a1SVladimir Kotal if ((rv = kcf_get_hardware_provider(mech.cm_type, &key, 26629b009fc1SValerie Bubb Fenwick CRYPTO_MECH_INVALID, NULL, sp->sd_provider, &real_provider, fg)) 266372eff6e2Smcpowers != CRYPTO_SUCCESS) { 26647c478bd9Sstevel@tonic-gate goto out; 26657c478bd9Sstevel@tonic-gate } 26667c478bd9Sstevel@tonic-gate 2667894b2776Smcpowers rv = crypto_provider_copyin_mech_param(real_provider, 2668894b2776Smcpowers STRUCT_FADDR(encrypt_init, ei_mech), &mech, mode, &error); 2669894b2776Smcpowers 2670894b2776Smcpowers if (rv == CRYPTO_NOT_SUPPORTED) { 2671894b2776Smcpowers allocated_by_crypto_module = B_TRUE; 26722d794da1Skrishna if (!copyin_mech(mode, sp, STRUCT_FADDR(encrypt_init, ei_mech), 26732d794da1Skrishna &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) { 2674894b2776Smcpowers goto out; 2675894b2776Smcpowers } 2676894b2776Smcpowers } else { 2677894b2776Smcpowers if (rv != CRYPTO_SUCCESS) 2678894b2776Smcpowers goto out; 2679894b2776Smcpowers } 2680894b2776Smcpowers 26817c478bd9Sstevel@tonic-gate rv = (init)(real_provider, sp->sd_provider_session->ps_session, 26827c478bd9Sstevel@tonic-gate &mech, &key, NULL, &cc, NULL); 26837c478bd9Sstevel@tonic-gate 26847c478bd9Sstevel@tonic-gate /* 26857c478bd9Sstevel@tonic-gate * Check if a context already exists. If so, it means it is being 26867c478bd9Sstevel@tonic-gate * abandoned. So, cancel it to avoid leaking it. 26877c478bd9Sstevel@tonic-gate */ 26887c478bd9Sstevel@tonic-gate ctxpp = (init == crypto_encrypt_init_prov) ? 26897c478bd9Sstevel@tonic-gate &sp->sd_encr_ctx : &sp->sd_decr_ctx; 26907c478bd9Sstevel@tonic-gate 26917c478bd9Sstevel@tonic-gate if (*ctxpp != NULL) 26927c478bd9Sstevel@tonic-gate CRYPTO_CANCEL_CTX(ctxpp); 26937c478bd9Sstevel@tonic-gate *ctxpp = (rv == CRYPTO_SUCCESS) ? cc : NULL; 2694894b2776Smcpowers 26957c478bd9Sstevel@tonic-gate out: 26962d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk); 26972d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk); 26987c478bd9Sstevel@tonic-gate CRYPTO_SESSION_RELE(sp); 26997c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 27007c478bd9Sstevel@tonic-gate 2701894b2776Smcpowers if (real_provider != NULL) { 2702894b2776Smcpowers crypto_free_mech(real_provider, 2703894b2776Smcpowers allocated_by_crypto_module, &mech); 2704894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 2705894b2776Smcpowers } 27067c478bd9Sstevel@tonic-gate 27077c478bd9Sstevel@tonic-gate free_crypto_key(&key); 27087c478bd9Sstevel@tonic-gate 27097c478bd9Sstevel@tonic-gate if (error != 0) 2710894b2776Smcpowers /* XXX free context */ 27117c478bd9Sstevel@tonic-gate return (error); 27127c478bd9Sstevel@tonic-gate 27137c478bd9Sstevel@tonic-gate STRUCT_FSET(encrypt_init, ei_return_value, rv); 27147c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(encrypt_init), arg, 27157c478bd9Sstevel@tonic-gate STRUCT_SIZE(encrypt_init)) != 0) { 2716894b2776Smcpowers /* XXX free context */ 27177c478bd9Sstevel@tonic-gate return (EFAULT); 27187c478bd9Sstevel@tonic-gate } 27197c478bd9Sstevel@tonic-gate return (0); 27207c478bd9Sstevel@tonic-gate } 27217c478bd9Sstevel@tonic-gate 27227c478bd9Sstevel@tonic-gate /* ARGSUSED */ 27237c478bd9Sstevel@tonic-gate static int 27247c478bd9Sstevel@tonic-gate encrypt(dev_t dev, caddr_t arg, int mode, int *rval) 27257c478bd9Sstevel@tonic-gate { 27267c478bd9Sstevel@tonic-gate return (cipher(dev, arg, mode, crypto_encrypt_single)); 27277c478bd9Sstevel@tonic-gate } 27287c478bd9Sstevel@tonic-gate 27297c478bd9Sstevel@tonic-gate /* ARGSUSED */ 27307c478bd9Sstevel@tonic-gate static int 27317c478bd9Sstevel@tonic-gate decrypt(dev_t dev, caddr_t arg, int mode, int *rval) 27327c478bd9Sstevel@tonic-gate { 27337c478bd9Sstevel@tonic-gate return (cipher(dev, arg, mode, crypto_decrypt_single)); 27347c478bd9Sstevel@tonic-gate } 27357c478bd9Sstevel@tonic-gate 27367c478bd9Sstevel@tonic-gate /* 27377c478bd9Sstevel@tonic-gate * ASSUMPTION: crypto_encrypt and crypto_decrypt structures 27387c478bd9Sstevel@tonic-gate * are identical except for field names. 27397c478bd9Sstevel@tonic-gate */ 27407c478bd9Sstevel@tonic-gate static int 27417c478bd9Sstevel@tonic-gate cipher(dev_t dev, caddr_t arg, int mode, 27427c478bd9Sstevel@tonic-gate int (*single)(crypto_context_t, crypto_data_t *, crypto_data_t *, 27437c478bd9Sstevel@tonic-gate crypto_call_req_t *)) 27447c478bd9Sstevel@tonic-gate { 27457c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_encrypt, encrypt); 27467c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 27477c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 27482d794da1Skrishna crypto_session_data_t *sp = NULL; 27497c478bd9Sstevel@tonic-gate crypto_ctx_t **ctxpp; 27507c478bd9Sstevel@tonic-gate crypto_data_t data, encr; 27517c478bd9Sstevel@tonic-gate size_t datalen, encrlen, need = 0; 275287fa5c53Smcpowers boolean_t do_inplace; 27537c478bd9Sstevel@tonic-gate char *encrbuf; 27547c478bd9Sstevel@tonic-gate int error = 0; 27557c478bd9Sstevel@tonic-gate int rv; 27562d794da1Skrishna boolean_t rctl_chk = B_FALSE; 27577c478bd9Sstevel@tonic-gate 27587c478bd9Sstevel@tonic-gate STRUCT_INIT(encrypt, mode); 27597c478bd9Sstevel@tonic-gate 27607c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 27617c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "cipher: failed holding minor"); 27627c478bd9Sstevel@tonic-gate return (ENXIO); 27637c478bd9Sstevel@tonic-gate } 27647c478bd9Sstevel@tonic-gate 27657c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(encrypt), STRUCT_SIZE(encrypt)) != 0) { 27667c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 27677c478bd9Sstevel@tonic-gate return (EFAULT); 27687c478bd9Sstevel@tonic-gate } 27697c478bd9Sstevel@tonic-gate 27707c478bd9Sstevel@tonic-gate data.cd_raw.iov_base = NULL; 27717c478bd9Sstevel@tonic-gate encr.cd_raw.iov_base = NULL; 27727c478bd9Sstevel@tonic-gate 27737c478bd9Sstevel@tonic-gate datalen = STRUCT_FGET(encrypt, ce_datalen); 27747c478bd9Sstevel@tonic-gate encrlen = STRUCT_FGET(encrypt, ce_encrlen); 27757c478bd9Sstevel@tonic-gate 27767c478bd9Sstevel@tonic-gate /* 27777c478bd9Sstevel@tonic-gate * Don't allocate output buffer unless both buffer pointer and 27787c478bd9Sstevel@tonic-gate * buffer length are not NULL or 0 (length). 27797c478bd9Sstevel@tonic-gate */ 27807c478bd9Sstevel@tonic-gate encrbuf = STRUCT_FGETP(encrypt, ce_encrbuf); 27817c478bd9Sstevel@tonic-gate if (encrbuf == NULL || encrlen == 0) { 27827c478bd9Sstevel@tonic-gate encrlen = 0; 27837c478bd9Sstevel@tonic-gate } 27847c478bd9Sstevel@tonic-gate 27857c478bd9Sstevel@tonic-gate if (datalen > crypto_max_buffer_len || 27867c478bd9Sstevel@tonic-gate encrlen > crypto_max_buffer_len) { 27877c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "cipher: buffer greater than %ld bytes, " 27887c478bd9Sstevel@tonic-gate "pid = %d", crypto_max_buffer_len, curproc->p_pid); 27897c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 27907c478bd9Sstevel@tonic-gate goto release_minor; 27917c478bd9Sstevel@tonic-gate } 27927c478bd9Sstevel@tonic-gate 27932d794da1Skrishna session_id = STRUCT_FGET(encrypt, ce_session); 27942d794da1Skrishna 27952d794da1Skrishna if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 27962d794da1Skrishna goto release_minor; 27972d794da1Skrishna } 279866761628Skrishna 279966761628Skrishna do_inplace = (STRUCT_FGET(encrypt, ce_flags) & 280066761628Skrishna CRYPTO_INPLACE_OPERATION) != 0; 280166761628Skrishna need = do_inplace ? datalen : datalen + encrlen; 280266761628Skrishna 28032d794da1Skrishna if ((rv = CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)) != 28042d794da1Skrishna CRYPTO_SUCCESS) { 28057c478bd9Sstevel@tonic-gate need = 0; 28067c478bd9Sstevel@tonic-gate goto release_minor; 28077c478bd9Sstevel@tonic-gate } 28087c478bd9Sstevel@tonic-gate 28097c478bd9Sstevel@tonic-gate INIT_RAW_CRYPTO_DATA(data, datalen); 28107c478bd9Sstevel@tonic-gate data.cd_miscdata = NULL; 28117c478bd9Sstevel@tonic-gate 28127c478bd9Sstevel@tonic-gate if (datalen != 0 && copyin(STRUCT_FGETP(encrypt, ce_databuf), 28137c478bd9Sstevel@tonic-gate data.cd_raw.iov_base, datalen) != 0) { 28147c478bd9Sstevel@tonic-gate error = EFAULT; 28157c478bd9Sstevel@tonic-gate goto release_minor; 28167c478bd9Sstevel@tonic-gate } 28177c478bd9Sstevel@tonic-gate 281887fa5c53Smcpowers if (do_inplace) { 281987fa5c53Smcpowers /* set out = in for in-place */ 282087fa5c53Smcpowers encr = data; 282187fa5c53Smcpowers } else { 28227c478bd9Sstevel@tonic-gate INIT_RAW_CRYPTO_DATA(encr, encrlen); 282387fa5c53Smcpowers } 28247c478bd9Sstevel@tonic-gate 28257c478bd9Sstevel@tonic-gate ctxpp = (single == crypto_encrypt_single) ? 28267c478bd9Sstevel@tonic-gate &sp->sd_encr_ctx : &sp->sd_decr_ctx; 28277c478bd9Sstevel@tonic-gate 282887fa5c53Smcpowers if (do_inplace) 28296d2259e1SDan OpenSolaris Anderson /* specify in-place buffers with output = NULL */ 283087fa5c53Smcpowers rv = (single)(*ctxpp, &encr, NULL, NULL); 283187fa5c53Smcpowers else 28327c478bd9Sstevel@tonic-gate rv = (single)(*ctxpp, &data, &encr, NULL); 28336d2259e1SDan OpenSolaris Anderson 28347c478bd9Sstevel@tonic-gate if (KCF_CONTEXT_DONE(rv)) 28357c478bd9Sstevel@tonic-gate *ctxpp = NULL; 28367c478bd9Sstevel@tonic-gate 28377c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) { 28387c478bd9Sstevel@tonic-gate ASSERT(encr.cd_length <= encrlen); 28397c478bd9Sstevel@tonic-gate if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base, 28407c478bd9Sstevel@tonic-gate encrbuf, encr.cd_length) != 0) { 28417c478bd9Sstevel@tonic-gate error = EFAULT; 28427c478bd9Sstevel@tonic-gate goto release_minor; 28437c478bd9Sstevel@tonic-gate } 284495014fbbSDan OpenSolaris Anderson STRUCT_FSET(encrypt, ce_encrlen, 284595014fbbSDan OpenSolaris Anderson (ulong_t)encr.cd_length); 28467c478bd9Sstevel@tonic-gate } 28477c478bd9Sstevel@tonic-gate 28487c478bd9Sstevel@tonic-gate if (rv == CRYPTO_BUFFER_TOO_SMALL) { 28497c478bd9Sstevel@tonic-gate /* 28507c478bd9Sstevel@tonic-gate * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1 28517c478bd9Sstevel@tonic-gate * of section 11.2 of the pkcs11 spec. We catch it here and 28527c478bd9Sstevel@tonic-gate * provide the correct pkcs11 return value. 28537c478bd9Sstevel@tonic-gate */ 28547c478bd9Sstevel@tonic-gate if (STRUCT_FGETP(encrypt, ce_encrbuf) == NULL) 28557c478bd9Sstevel@tonic-gate rv = CRYPTO_SUCCESS; 285695014fbbSDan OpenSolaris Anderson STRUCT_FSET(encrypt, ce_encrlen, 285795014fbbSDan OpenSolaris Anderson (ulong_t)encr.cd_length); 28587c478bd9Sstevel@tonic-gate } 28597c478bd9Sstevel@tonic-gate 28607c478bd9Sstevel@tonic-gate release_minor: 28612d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk); 28622d794da1Skrishna CRYPTO_SESSION_RELE(sp); 28637c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 28647c478bd9Sstevel@tonic-gate 28657c478bd9Sstevel@tonic-gate if (data.cd_raw.iov_base != NULL) 28667c478bd9Sstevel@tonic-gate kmem_free(data.cd_raw.iov_base, datalen); 28677c478bd9Sstevel@tonic-gate 286887fa5c53Smcpowers if (!do_inplace && encr.cd_raw.iov_base != NULL) 28697c478bd9Sstevel@tonic-gate kmem_free(encr.cd_raw.iov_base, encrlen); 28707c478bd9Sstevel@tonic-gate 28717c478bd9Sstevel@tonic-gate if (error != 0) 28727c478bd9Sstevel@tonic-gate return (error); 28737c478bd9Sstevel@tonic-gate 28747c478bd9Sstevel@tonic-gate STRUCT_FSET(encrypt, ce_return_value, rv); 28757c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(encrypt), arg, STRUCT_SIZE(encrypt)) != 0) { 28767c478bd9Sstevel@tonic-gate return (EFAULT); 28777c478bd9Sstevel@tonic-gate } 28787c478bd9Sstevel@tonic-gate return (0); 28797c478bd9Sstevel@tonic-gate } 28807c478bd9Sstevel@tonic-gate 28817c478bd9Sstevel@tonic-gate /* ARGSUSED */ 28827c478bd9Sstevel@tonic-gate static int 28837c478bd9Sstevel@tonic-gate encrypt_update(dev_t dev, caddr_t arg, int mode, int *rval) 28847c478bd9Sstevel@tonic-gate { 28857c478bd9Sstevel@tonic-gate return (cipher_update(dev, arg, mode, crypto_encrypt_update)); 28867c478bd9Sstevel@tonic-gate } 28877c478bd9Sstevel@tonic-gate 28887c478bd9Sstevel@tonic-gate /* ARGSUSED */ 28897c478bd9Sstevel@tonic-gate static int 28907c478bd9Sstevel@tonic-gate decrypt_update(dev_t dev, caddr_t arg, int mode, int *rval) 28917c478bd9Sstevel@tonic-gate { 28927c478bd9Sstevel@tonic-gate return (cipher_update(dev, arg, mode, crypto_decrypt_update)); 28937c478bd9Sstevel@tonic-gate } 28947c478bd9Sstevel@tonic-gate 28957c478bd9Sstevel@tonic-gate /* 28967c478bd9Sstevel@tonic-gate * ASSUMPTION: crypto_encrypt_update and crypto_decrypt_update 28977c478bd9Sstevel@tonic-gate * structures are identical except for field names. 28987c478bd9Sstevel@tonic-gate */ 28997c478bd9Sstevel@tonic-gate static int 29007c478bd9Sstevel@tonic-gate cipher_update(dev_t dev, caddr_t arg, int mode, 29017c478bd9Sstevel@tonic-gate int (*update)(crypto_context_t, crypto_data_t *, crypto_data_t *, 29027c478bd9Sstevel@tonic-gate crypto_call_req_t *)) 29037c478bd9Sstevel@tonic-gate { 29047c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_encrypt_update, encrypt_update); 29057c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 29067c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 29072d794da1Skrishna crypto_session_data_t *sp = NULL; 29087c478bd9Sstevel@tonic-gate crypto_ctx_t **ctxpp; 29097c478bd9Sstevel@tonic-gate crypto_data_t data, encr; 29107c478bd9Sstevel@tonic-gate size_t datalen, encrlen, need = 0; 29116d2259e1SDan OpenSolaris Anderson boolean_t do_inplace; 29127c478bd9Sstevel@tonic-gate char *encrbuf; 29137c478bd9Sstevel@tonic-gate int error = 0; 29147c478bd9Sstevel@tonic-gate int rv; 29152d794da1Skrishna boolean_t rctl_chk = B_FALSE; 29167c478bd9Sstevel@tonic-gate 29177c478bd9Sstevel@tonic-gate STRUCT_INIT(encrypt_update, mode); 29187c478bd9Sstevel@tonic-gate 29197c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 29207c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "cipher_update: failed holding minor"); 29217c478bd9Sstevel@tonic-gate return (ENXIO); 29227c478bd9Sstevel@tonic-gate } 29237c478bd9Sstevel@tonic-gate 29247c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(encrypt_update), 29257c478bd9Sstevel@tonic-gate STRUCT_SIZE(encrypt_update)) != 0) { 29267c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 29277c478bd9Sstevel@tonic-gate return (EFAULT); 29287c478bd9Sstevel@tonic-gate } 29297c478bd9Sstevel@tonic-gate 29307c478bd9Sstevel@tonic-gate data.cd_raw.iov_base = NULL; 29317c478bd9Sstevel@tonic-gate encr.cd_raw.iov_base = NULL; 29327c478bd9Sstevel@tonic-gate 29337c478bd9Sstevel@tonic-gate datalen = STRUCT_FGET(encrypt_update, eu_datalen); 29347c478bd9Sstevel@tonic-gate encrlen = STRUCT_FGET(encrypt_update, eu_encrlen); 29357c478bd9Sstevel@tonic-gate 29367c478bd9Sstevel@tonic-gate /* 29377c478bd9Sstevel@tonic-gate * Don't allocate output buffer unless both buffer pointer and 29387c478bd9Sstevel@tonic-gate * buffer length are not NULL or 0 (length). 29397c478bd9Sstevel@tonic-gate */ 29407c478bd9Sstevel@tonic-gate encrbuf = STRUCT_FGETP(encrypt_update, eu_encrbuf); 29417c478bd9Sstevel@tonic-gate if (encrbuf == NULL || encrlen == 0) { 29427c478bd9Sstevel@tonic-gate encrlen = 0; 29437c478bd9Sstevel@tonic-gate } 29447c478bd9Sstevel@tonic-gate 29457c478bd9Sstevel@tonic-gate if (datalen > crypto_max_buffer_len || 29467c478bd9Sstevel@tonic-gate encrlen > crypto_max_buffer_len) { 29477c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "cipher_update: buffer greater than %ld " 29487c478bd9Sstevel@tonic-gate "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 29497c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 29502d794da1Skrishna goto out; 29512d794da1Skrishna } 29522d794da1Skrishna 29532d794da1Skrishna session_id = STRUCT_FGET(encrypt_update, eu_session); 29542d794da1Skrishna 29552d794da1Skrishna if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 29562d794da1Skrishna goto out; 29577c478bd9Sstevel@tonic-gate } 29587c478bd9Sstevel@tonic-gate 29596d2259e1SDan OpenSolaris Anderson do_inplace = (STRUCT_FGET(encrypt_update, eu_flags) & 29606d2259e1SDan OpenSolaris Anderson CRYPTO_INPLACE_OPERATION) != 0; 29616d2259e1SDan OpenSolaris Anderson need = do_inplace ? datalen : datalen + encrlen; 29622d794da1Skrishna 29632d794da1Skrishna if ((rv = CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)) != 29642d794da1Skrishna CRYPTO_SUCCESS) { 29657c478bd9Sstevel@tonic-gate need = 0; 29662d794da1Skrishna goto out; 29677c478bd9Sstevel@tonic-gate } 29687c478bd9Sstevel@tonic-gate 29697c478bd9Sstevel@tonic-gate INIT_RAW_CRYPTO_DATA(data, datalen); 29707c478bd9Sstevel@tonic-gate data.cd_miscdata = NULL; 29717c478bd9Sstevel@tonic-gate 29727c478bd9Sstevel@tonic-gate if (datalen != 0 && copyin(STRUCT_FGETP(encrypt_update, eu_databuf), 29737c478bd9Sstevel@tonic-gate data.cd_raw.iov_base, datalen) != 0) { 29747c478bd9Sstevel@tonic-gate error = EFAULT; 29752d794da1Skrishna goto out; 29767c478bd9Sstevel@tonic-gate } 29777c478bd9Sstevel@tonic-gate 29786d2259e1SDan OpenSolaris Anderson if (do_inplace) { 29796d2259e1SDan OpenSolaris Anderson /* specify in-place buffers with output = input */ 29806d2259e1SDan OpenSolaris Anderson encr = data; 29816d2259e1SDan OpenSolaris Anderson } else { 29827c478bd9Sstevel@tonic-gate INIT_RAW_CRYPTO_DATA(encr, encrlen); 29836d2259e1SDan OpenSolaris Anderson } 29847c478bd9Sstevel@tonic-gate 29857c478bd9Sstevel@tonic-gate ctxpp = (update == crypto_encrypt_update) ? 29867c478bd9Sstevel@tonic-gate &sp->sd_encr_ctx : &sp->sd_decr_ctx; 29877c478bd9Sstevel@tonic-gate 29886d2259e1SDan OpenSolaris Anderson if (do_inplace) 29896d2259e1SDan OpenSolaris Anderson /* specify in-place buffers with output = NULL */ 29906d2259e1SDan OpenSolaris Anderson rv = (update)(*ctxpp, &encr, NULL, NULL); 29916d2259e1SDan OpenSolaris Anderson else 29927c478bd9Sstevel@tonic-gate rv = (update)(*ctxpp, &data, &encr, NULL); 29937c478bd9Sstevel@tonic-gate 29947c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS || rv == CRYPTO_BUFFER_TOO_SMALL) { 29957c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) { 29967c478bd9Sstevel@tonic-gate ASSERT(encr.cd_length <= encrlen); 29977c478bd9Sstevel@tonic-gate if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base, 29987c478bd9Sstevel@tonic-gate encrbuf, encr.cd_length) != 0) { 29997c478bd9Sstevel@tonic-gate error = EFAULT; 30007c478bd9Sstevel@tonic-gate goto out; 30017c478bd9Sstevel@tonic-gate } 30027c478bd9Sstevel@tonic-gate } else { 30037c478bd9Sstevel@tonic-gate /* 30047c478bd9Sstevel@tonic-gate * The providers return CRYPTO_BUFFER_TOO_SMALL even 30057c478bd9Sstevel@tonic-gate * for case 1 of section 11.2 of the pkcs11 spec. 30067c478bd9Sstevel@tonic-gate * We catch it here and provide the correct pkcs11 30077c478bd9Sstevel@tonic-gate * return value. 30087c478bd9Sstevel@tonic-gate */ 30097c478bd9Sstevel@tonic-gate if (STRUCT_FGETP(encrypt_update, eu_encrbuf) == NULL) 30107c478bd9Sstevel@tonic-gate rv = CRYPTO_SUCCESS; 30117c478bd9Sstevel@tonic-gate } 301295014fbbSDan OpenSolaris Anderson STRUCT_FSET(encrypt_update, eu_encrlen, 301395014fbbSDan OpenSolaris Anderson (ulong_t)encr.cd_length); 30147c478bd9Sstevel@tonic-gate } else { 30157c478bd9Sstevel@tonic-gate CRYPTO_CANCEL_CTX(ctxpp); 30167c478bd9Sstevel@tonic-gate } 30177c478bd9Sstevel@tonic-gate out: 30182d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk); 30197c478bd9Sstevel@tonic-gate CRYPTO_SESSION_RELE(sp); 30207c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 30217c478bd9Sstevel@tonic-gate 30227c478bd9Sstevel@tonic-gate if (data.cd_raw.iov_base != NULL) 30237c478bd9Sstevel@tonic-gate kmem_free(data.cd_raw.iov_base, datalen); 30247c478bd9Sstevel@tonic-gate 30256d2259e1SDan OpenSolaris Anderson if (!do_inplace && (encr.cd_raw.iov_base != NULL)) 30267c478bd9Sstevel@tonic-gate kmem_free(encr.cd_raw.iov_base, encrlen); 30277c478bd9Sstevel@tonic-gate 30287c478bd9Sstevel@tonic-gate if (error != 0) 30297c478bd9Sstevel@tonic-gate return (error); 30307c478bd9Sstevel@tonic-gate 30317c478bd9Sstevel@tonic-gate STRUCT_FSET(encrypt_update, eu_return_value, rv); 30327c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(encrypt_update), arg, 30337c478bd9Sstevel@tonic-gate STRUCT_SIZE(encrypt_update)) != 0) { 30347c478bd9Sstevel@tonic-gate return (EFAULT); 30357c478bd9Sstevel@tonic-gate } 30367c478bd9Sstevel@tonic-gate return (0); 30377c478bd9Sstevel@tonic-gate } 30387c478bd9Sstevel@tonic-gate 30397c478bd9Sstevel@tonic-gate /* ARGSUSED */ 30407c478bd9Sstevel@tonic-gate static int 30417c478bd9Sstevel@tonic-gate encrypt_final(dev_t dev, caddr_t arg, int mode, int *rval) 30427c478bd9Sstevel@tonic-gate { 30437c478bd9Sstevel@tonic-gate return (common_final(dev, arg, mode, crypto_encrypt_final)); 30447c478bd9Sstevel@tonic-gate } 30457c478bd9Sstevel@tonic-gate 30467c478bd9Sstevel@tonic-gate /* ARGSUSED */ 30477c478bd9Sstevel@tonic-gate static int 30487c478bd9Sstevel@tonic-gate decrypt_final(dev_t dev, caddr_t arg, int mode, int *rval) 30497c478bd9Sstevel@tonic-gate { 30507c478bd9Sstevel@tonic-gate return (common_final(dev, arg, mode, crypto_decrypt_final)); 30517c478bd9Sstevel@tonic-gate } 30527c478bd9Sstevel@tonic-gate 30537c478bd9Sstevel@tonic-gate /* 30547c478bd9Sstevel@tonic-gate * ASSUMPTION: crypto_encrypt_final, crypto_decrypt_final, crypto_sign_final, 30557c478bd9Sstevel@tonic-gate * and crypto_digest_final structures are identical except for field names. 30567c478bd9Sstevel@tonic-gate */ 30577c478bd9Sstevel@tonic-gate static int 30587c478bd9Sstevel@tonic-gate common_final(dev_t dev, caddr_t arg, int mode, 30597c478bd9Sstevel@tonic-gate int (*final)(crypto_context_t, crypto_data_t *, crypto_call_req_t *)) 30607c478bd9Sstevel@tonic-gate { 30617c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_encrypt_final, encrypt_final); 30627c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 30637c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 30642d794da1Skrishna crypto_session_data_t *sp = NULL; 30657c478bd9Sstevel@tonic-gate crypto_ctx_t **ctxpp; 30667c478bd9Sstevel@tonic-gate crypto_data_t encr; 30677c478bd9Sstevel@tonic-gate size_t encrlen, need = 0; 30687c478bd9Sstevel@tonic-gate char *encrbuf; 30697c478bd9Sstevel@tonic-gate int error = 0; 30707c478bd9Sstevel@tonic-gate int rv; 30712d794da1Skrishna boolean_t rctl_chk = B_FALSE; 30727c478bd9Sstevel@tonic-gate 30737c478bd9Sstevel@tonic-gate STRUCT_INIT(encrypt_final, mode); 30747c478bd9Sstevel@tonic-gate 30757c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 30767c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "common_final: failed holding minor"); 30777c478bd9Sstevel@tonic-gate return (ENXIO); 30787c478bd9Sstevel@tonic-gate } 30797c478bd9Sstevel@tonic-gate 30807c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(encrypt_final), 30817c478bd9Sstevel@tonic-gate STRUCT_SIZE(encrypt_final)) != 0) { 30827c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 30837c478bd9Sstevel@tonic-gate return (EFAULT); 30847c478bd9Sstevel@tonic-gate } 30857c478bd9Sstevel@tonic-gate 30867c478bd9Sstevel@tonic-gate encr.cd_format = CRYPTO_DATA_RAW; 30877c478bd9Sstevel@tonic-gate encr.cd_raw.iov_base = NULL; 30887c478bd9Sstevel@tonic-gate 30897c478bd9Sstevel@tonic-gate encrlen = STRUCT_FGET(encrypt_final, ef_encrlen); 30907c478bd9Sstevel@tonic-gate 30917c478bd9Sstevel@tonic-gate /* 30927c478bd9Sstevel@tonic-gate * Don't allocate output buffer unless both buffer pointer and 30937c478bd9Sstevel@tonic-gate * buffer length are not NULL or 0 (length). 30947c478bd9Sstevel@tonic-gate */ 30957c478bd9Sstevel@tonic-gate encrbuf = STRUCT_FGETP(encrypt_final, ef_encrbuf); 30967c478bd9Sstevel@tonic-gate if (encrbuf == NULL || encrlen == 0) { 30977c478bd9Sstevel@tonic-gate encrlen = 0; 30987c478bd9Sstevel@tonic-gate } 30997c478bd9Sstevel@tonic-gate 31007c478bd9Sstevel@tonic-gate if (encrlen > crypto_max_buffer_len) { 31017c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "common_final: buffer greater than %ld " 31027c478bd9Sstevel@tonic-gate "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 31037c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 31047c478bd9Sstevel@tonic-gate goto release_minor; 31057c478bd9Sstevel@tonic-gate } 31067c478bd9Sstevel@tonic-gate 31072d794da1Skrishna session_id = STRUCT_FGET(encrypt_final, ef_session); 31082d794da1Skrishna 31092d794da1Skrishna if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 31102d794da1Skrishna goto release_minor; 31112d794da1Skrishna } 31122d794da1Skrishna 31132d794da1Skrishna if ((rv = CRYPTO_BUFFER_CHECK(sp, encrlen, rctl_chk)) != 31142d794da1Skrishna CRYPTO_SUCCESS) { 31157c478bd9Sstevel@tonic-gate goto release_minor; 31167c478bd9Sstevel@tonic-gate } 31177c478bd9Sstevel@tonic-gate need = encrlen; 31187c478bd9Sstevel@tonic-gate encr.cd_raw.iov_base = kmem_alloc(encrlen, KM_SLEEP); 31197c478bd9Sstevel@tonic-gate encr.cd_raw.iov_len = encrlen; 31207c478bd9Sstevel@tonic-gate 31217c478bd9Sstevel@tonic-gate encr.cd_offset = 0; 31227c478bd9Sstevel@tonic-gate encr.cd_length = encrlen; 31237c478bd9Sstevel@tonic-gate 31247c478bd9Sstevel@tonic-gate ASSERT(final == crypto_encrypt_final || 31257c478bd9Sstevel@tonic-gate final == crypto_decrypt_final || final == crypto_sign_final || 31267c478bd9Sstevel@tonic-gate final == crypto_digest_final); 31277c478bd9Sstevel@tonic-gate 31287c478bd9Sstevel@tonic-gate if (final == crypto_encrypt_final) { 31297c478bd9Sstevel@tonic-gate ctxpp = &sp->sd_encr_ctx; 31307c478bd9Sstevel@tonic-gate } else if (final == crypto_decrypt_final) { 31317c478bd9Sstevel@tonic-gate ctxpp = &sp->sd_decr_ctx; 31327c478bd9Sstevel@tonic-gate } else if (final == crypto_sign_final) { 31337c478bd9Sstevel@tonic-gate ctxpp = &sp->sd_sign_ctx; 31347c478bd9Sstevel@tonic-gate } else { 31357c478bd9Sstevel@tonic-gate ctxpp = &sp->sd_digest_ctx; 31367c478bd9Sstevel@tonic-gate } 31377c478bd9Sstevel@tonic-gate 31387c478bd9Sstevel@tonic-gate rv = (final)(*ctxpp, &encr, NULL); 31397c478bd9Sstevel@tonic-gate if (KCF_CONTEXT_DONE(rv)) 31407c478bd9Sstevel@tonic-gate *ctxpp = NULL; 31417c478bd9Sstevel@tonic-gate 31427c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) { 31437c478bd9Sstevel@tonic-gate ASSERT(encr.cd_length <= encrlen); 31447c478bd9Sstevel@tonic-gate if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base, 31457c478bd9Sstevel@tonic-gate encrbuf, encr.cd_length) != 0) { 31467c478bd9Sstevel@tonic-gate error = EFAULT; 31477c478bd9Sstevel@tonic-gate goto release_minor; 31487c478bd9Sstevel@tonic-gate } 314995014fbbSDan OpenSolaris Anderson STRUCT_FSET(encrypt_final, ef_encrlen, 315095014fbbSDan OpenSolaris Anderson (ulong_t)encr.cd_length); 31517c478bd9Sstevel@tonic-gate } 31527c478bd9Sstevel@tonic-gate 31537c478bd9Sstevel@tonic-gate if (rv == CRYPTO_BUFFER_TOO_SMALL) { 31547c478bd9Sstevel@tonic-gate /* 31557c478bd9Sstevel@tonic-gate * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1 31567c478bd9Sstevel@tonic-gate * of section 11.2 of the pkcs11 spec. We catch it here and 31577c478bd9Sstevel@tonic-gate * provide the correct pkcs11 return value. 31587c478bd9Sstevel@tonic-gate */ 31597c478bd9Sstevel@tonic-gate if (STRUCT_FGETP(encrypt_final, ef_encrbuf) == NULL) 31607c478bd9Sstevel@tonic-gate rv = CRYPTO_SUCCESS; 316195014fbbSDan OpenSolaris Anderson STRUCT_FSET(encrypt_final, ef_encrlen, 316295014fbbSDan OpenSolaris Anderson (ulong_t)encr.cd_length); 31637c478bd9Sstevel@tonic-gate } 31647c478bd9Sstevel@tonic-gate 31657c478bd9Sstevel@tonic-gate release_minor: 31662d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk); 31672d794da1Skrishna CRYPTO_SESSION_RELE(sp); 31687c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 31697c478bd9Sstevel@tonic-gate 31707c478bd9Sstevel@tonic-gate if (encr.cd_raw.iov_base != NULL) 31717c478bd9Sstevel@tonic-gate kmem_free(encr.cd_raw.iov_base, encrlen); 31727c478bd9Sstevel@tonic-gate 31737c478bd9Sstevel@tonic-gate if (error != 0) 31747c478bd9Sstevel@tonic-gate return (error); 31757c478bd9Sstevel@tonic-gate 31767c478bd9Sstevel@tonic-gate STRUCT_FSET(encrypt_final, ef_return_value, rv); 31777c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(encrypt_final), arg, 31787c478bd9Sstevel@tonic-gate STRUCT_SIZE(encrypt_final)) != 0) { 31797c478bd9Sstevel@tonic-gate return (EFAULT); 31807c478bd9Sstevel@tonic-gate } 31817c478bd9Sstevel@tonic-gate return (0); 31827c478bd9Sstevel@tonic-gate } 31837c478bd9Sstevel@tonic-gate 31847c478bd9Sstevel@tonic-gate /* ARGSUSED */ 31857c478bd9Sstevel@tonic-gate static int 31867c478bd9Sstevel@tonic-gate digest_init(dev_t dev, caddr_t arg, int mode, int *rval) 31877c478bd9Sstevel@tonic-gate { 31887c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_digest_init, digest_init); 3189894b2776Smcpowers kcf_provider_desc_t *real_provider = NULL; 31907c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 31917c478bd9Sstevel@tonic-gate crypto_mechanism_t mech; 31927c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 31932d794da1Skrishna crypto_session_data_t *sp = NULL; 31947c478bd9Sstevel@tonic-gate crypto_context_t cc; 31957c478bd9Sstevel@tonic-gate size_t rctl_bytes = 0; 31962d794da1Skrishna boolean_t rctl_chk = B_FALSE; 31977c478bd9Sstevel@tonic-gate int error = 0; 31987c478bd9Sstevel@tonic-gate int rv; 31997c478bd9Sstevel@tonic-gate 32007c478bd9Sstevel@tonic-gate STRUCT_INIT(digest_init, mode); 32017c478bd9Sstevel@tonic-gate 32027c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 32037c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "digest_init: failed holding minor"); 32047c478bd9Sstevel@tonic-gate return (ENXIO); 32057c478bd9Sstevel@tonic-gate } 32067c478bd9Sstevel@tonic-gate 32077c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(digest_init), 32087c478bd9Sstevel@tonic-gate STRUCT_SIZE(digest_init)) != 0) { 32097c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 32107c478bd9Sstevel@tonic-gate return (EFAULT); 32117c478bd9Sstevel@tonic-gate } 32127c478bd9Sstevel@tonic-gate 32137c478bd9Sstevel@tonic-gate mech.cm_param = NULL; 32147c478bd9Sstevel@tonic-gate 32157c478bd9Sstevel@tonic-gate session_id = STRUCT_FGET(digest_init, di_session); 32167c478bd9Sstevel@tonic-gate 32177c478bd9Sstevel@tonic-gate if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 32182d794da1Skrishna goto out; 32197c478bd9Sstevel@tonic-gate } 32207c478bd9Sstevel@tonic-gate 32212d794da1Skrishna if (!copyin_mech(mode, sp, STRUCT_FADDR(digest_init, di_mech), &mech, 32222d794da1Skrishna &rctl_bytes, &rctl_chk, &rv, &error)) { 32237c478bd9Sstevel@tonic-gate goto out; 32247c478bd9Sstevel@tonic-gate } 32257c478bd9Sstevel@tonic-gate 3226436935a1SVladimir Kotal if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL, 32279b009fc1SValerie Bubb Fenwick CRYPTO_MECH_INVALID, NULL, sp->sd_provider, &real_provider, 32289b009fc1SValerie Bubb Fenwick CRYPTO_FG_DIGEST)) != CRYPTO_SUCCESS) { 32297c478bd9Sstevel@tonic-gate goto out; 32307c478bd9Sstevel@tonic-gate } 32317c478bd9Sstevel@tonic-gate 32327c478bd9Sstevel@tonic-gate rv = crypto_digest_init_prov(real_provider, 32337c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, &mech, &cc, NULL); 32347c478bd9Sstevel@tonic-gate 32357c478bd9Sstevel@tonic-gate /* 32367c478bd9Sstevel@tonic-gate * Check if a context already exists. If so, it means it is being 32377c478bd9Sstevel@tonic-gate * abandoned. So, cancel it to avoid leaking it. 32387c478bd9Sstevel@tonic-gate */ 32397c478bd9Sstevel@tonic-gate if (sp->sd_digest_ctx != NULL) 32407c478bd9Sstevel@tonic-gate CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx); 32417c478bd9Sstevel@tonic-gate sp->sd_digest_ctx = (rv == CRYPTO_SUCCESS) ? cc : NULL; 32427c478bd9Sstevel@tonic-gate out: 32432d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk); 32447c478bd9Sstevel@tonic-gate CRYPTO_SESSION_RELE(sp); 32457c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 32467c478bd9Sstevel@tonic-gate 3247894b2776Smcpowers if (real_provider != NULL) 3248894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 3249894b2776Smcpowers 32507c478bd9Sstevel@tonic-gate if (mech.cm_param != NULL) 32517c478bd9Sstevel@tonic-gate kmem_free(mech.cm_param, mech.cm_param_len); 32527c478bd9Sstevel@tonic-gate 32537c478bd9Sstevel@tonic-gate if (error != 0) 32547c478bd9Sstevel@tonic-gate return (error); 32557c478bd9Sstevel@tonic-gate 32567c478bd9Sstevel@tonic-gate STRUCT_FSET(digest_init, di_return_value, rv); 32577c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(digest_init), arg, 32587c478bd9Sstevel@tonic-gate STRUCT_SIZE(digest_init)) != 0) { 32597c478bd9Sstevel@tonic-gate return (EFAULT); 32607c478bd9Sstevel@tonic-gate } 32617c478bd9Sstevel@tonic-gate return (0); 32627c478bd9Sstevel@tonic-gate } 32637c478bd9Sstevel@tonic-gate 32647c478bd9Sstevel@tonic-gate /* ARGSUSED */ 32657c478bd9Sstevel@tonic-gate static int 32667c478bd9Sstevel@tonic-gate digest_update(dev_t dev, caddr_t arg, int mode, int *rval) 32677c478bd9Sstevel@tonic-gate { 32687c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_digest_update, digest_update); 32697c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 32707c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 32712d794da1Skrishna crypto_session_data_t *sp = NULL; 32727c478bd9Sstevel@tonic-gate crypto_data_t data; 32737c478bd9Sstevel@tonic-gate size_t datalen, need = 0; 32747c478bd9Sstevel@tonic-gate int error = 0; 32757c478bd9Sstevel@tonic-gate int rv; 32762d794da1Skrishna boolean_t rctl_chk = B_FALSE; 32777c478bd9Sstevel@tonic-gate 32787c478bd9Sstevel@tonic-gate STRUCT_INIT(digest_update, mode); 32797c478bd9Sstevel@tonic-gate 32807c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 32817c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "digest_update: failed holding minor"); 32827c478bd9Sstevel@tonic-gate return (ENXIO); 32837c478bd9Sstevel@tonic-gate } 32847c478bd9Sstevel@tonic-gate 32857c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(digest_update), 32867c478bd9Sstevel@tonic-gate STRUCT_SIZE(digest_update)) != 0) { 32877c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 32887c478bd9Sstevel@tonic-gate return (EFAULT); 32897c478bd9Sstevel@tonic-gate } 32907c478bd9Sstevel@tonic-gate 32917c478bd9Sstevel@tonic-gate data.cd_format = CRYPTO_DATA_RAW; 32927c478bd9Sstevel@tonic-gate data.cd_raw.iov_base = NULL; 32937c478bd9Sstevel@tonic-gate 32947c478bd9Sstevel@tonic-gate datalen = STRUCT_FGET(digest_update, du_datalen); 32957c478bd9Sstevel@tonic-gate if (datalen > crypto_max_buffer_len) { 32967c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "digest_update: buffer greater than %ld " 32977c478bd9Sstevel@tonic-gate "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 32987c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 32997c478bd9Sstevel@tonic-gate goto release_minor; 33007c478bd9Sstevel@tonic-gate } 33017c478bd9Sstevel@tonic-gate 33022d794da1Skrishna session_id = STRUCT_FGET(digest_update, du_session); 33032d794da1Skrishna 33042d794da1Skrishna if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 33057c478bd9Sstevel@tonic-gate goto release_minor; 33067c478bd9Sstevel@tonic-gate } 33072d794da1Skrishna 33082d794da1Skrishna if ((rv = CRYPTO_BUFFER_CHECK(sp, datalen, rctl_chk)) != 33092d794da1Skrishna CRYPTO_SUCCESS) { 33102d794da1Skrishna goto release_minor; 33112d794da1Skrishna } 33122d794da1Skrishna 33137c478bd9Sstevel@tonic-gate need = datalen; 33147c478bd9Sstevel@tonic-gate data.cd_raw.iov_base = kmem_alloc(datalen, KM_SLEEP); 33157c478bd9Sstevel@tonic-gate data.cd_raw.iov_len = datalen; 33167c478bd9Sstevel@tonic-gate 33177c478bd9Sstevel@tonic-gate if (datalen != 0 && copyin(STRUCT_FGETP(digest_update, du_databuf), 33187c478bd9Sstevel@tonic-gate data.cd_raw.iov_base, datalen) != 0) { 33197c478bd9Sstevel@tonic-gate error = EFAULT; 33207c478bd9Sstevel@tonic-gate goto release_minor; 33217c478bd9Sstevel@tonic-gate } 33227c478bd9Sstevel@tonic-gate 33237c478bd9Sstevel@tonic-gate data.cd_offset = 0; 33247c478bd9Sstevel@tonic-gate data.cd_length = datalen; 33257c478bd9Sstevel@tonic-gate 33267c478bd9Sstevel@tonic-gate rv = crypto_digest_update(sp->sd_digest_ctx, &data, NULL); 33277c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) 33287c478bd9Sstevel@tonic-gate CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx); 33297c478bd9Sstevel@tonic-gate 33307c478bd9Sstevel@tonic-gate release_minor: 33312d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk); 33322d794da1Skrishna CRYPTO_SESSION_RELE(sp); 33337c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 33347c478bd9Sstevel@tonic-gate 33357c478bd9Sstevel@tonic-gate if (data.cd_raw.iov_base != NULL) 33367c478bd9Sstevel@tonic-gate kmem_free(data.cd_raw.iov_base, datalen); 33377c478bd9Sstevel@tonic-gate 33387c478bd9Sstevel@tonic-gate if (error != 0) 33397c478bd9Sstevel@tonic-gate return (error); 33407c478bd9Sstevel@tonic-gate 33417c478bd9Sstevel@tonic-gate STRUCT_FSET(digest_update, du_return_value, rv); 33427c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(digest_update), arg, 33437c478bd9Sstevel@tonic-gate STRUCT_SIZE(digest_update)) != 0) { 33447c478bd9Sstevel@tonic-gate return (EFAULT); 33457c478bd9Sstevel@tonic-gate } 33467c478bd9Sstevel@tonic-gate return (0); 33477c478bd9Sstevel@tonic-gate } 33487c478bd9Sstevel@tonic-gate 33497c478bd9Sstevel@tonic-gate /* ARGSUSED */ 33507c478bd9Sstevel@tonic-gate static int 33517c478bd9Sstevel@tonic-gate digest_key(dev_t dev, caddr_t arg, int mode, int *rval) 33527c478bd9Sstevel@tonic-gate { 33537c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_digest_key, digest_key); 33547c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 33557c478bd9Sstevel@tonic-gate crypto_key_t key; 33567c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 33572d794da1Skrishna crypto_session_data_t *sp = NULL; 33587c478bd9Sstevel@tonic-gate size_t rctl_bytes = 0; 33592d794da1Skrishna boolean_t key_rctl_chk = B_FALSE; 33607c478bd9Sstevel@tonic-gate int error = 0; 33617c478bd9Sstevel@tonic-gate int rv; 33627c478bd9Sstevel@tonic-gate 33637c478bd9Sstevel@tonic-gate STRUCT_INIT(digest_key, mode); 33647c478bd9Sstevel@tonic-gate 33657c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 33667c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "digest_key: failed holding minor"); 33677c478bd9Sstevel@tonic-gate return (ENXIO); 33687c478bd9Sstevel@tonic-gate } 33697c478bd9Sstevel@tonic-gate 33707c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(digest_key), STRUCT_SIZE(digest_key)) != 0) { 33717c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 33727c478bd9Sstevel@tonic-gate return (EFAULT); 33737c478bd9Sstevel@tonic-gate } 33747c478bd9Sstevel@tonic-gate 33757c478bd9Sstevel@tonic-gate bzero(&key, sizeof (crypto_key_t)); 33767c478bd9Sstevel@tonic-gate 33777c478bd9Sstevel@tonic-gate session_id = STRUCT_FGET(digest_key, dk_session); 33787c478bd9Sstevel@tonic-gate 33797c478bd9Sstevel@tonic-gate if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 33802d794da1Skrishna goto out; 33817c478bd9Sstevel@tonic-gate } 33827c478bd9Sstevel@tonic-gate 33832d794da1Skrishna if (!copyin_key(mode, sp, STRUCT_FADDR(digest_key, dk_key), &key, 33842d794da1Skrishna &rctl_bytes, &key_rctl_chk, &rv, &error)) { 33857c478bd9Sstevel@tonic-gate goto out; 33867c478bd9Sstevel@tonic-gate } 33877c478bd9Sstevel@tonic-gate 33887c478bd9Sstevel@tonic-gate rv = crypto_digest_key_prov(sp->sd_digest_ctx, &key, NULL); 33897c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) 33907c478bd9Sstevel@tonic-gate CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx); 33917c478bd9Sstevel@tonic-gate out: 33922d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, key_rctl_chk); 33937c478bd9Sstevel@tonic-gate CRYPTO_SESSION_RELE(sp); 33947c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 33957c478bd9Sstevel@tonic-gate 33967c478bd9Sstevel@tonic-gate free_crypto_key(&key); 33977c478bd9Sstevel@tonic-gate 33987c478bd9Sstevel@tonic-gate if (error != 0) 33997c478bd9Sstevel@tonic-gate return (error); 34007c478bd9Sstevel@tonic-gate 34017c478bd9Sstevel@tonic-gate STRUCT_FSET(digest_key, dk_return_value, rv); 34027c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(digest_key), arg, 34037c478bd9Sstevel@tonic-gate STRUCT_SIZE(digest_key)) != 0) { 34047c478bd9Sstevel@tonic-gate return (EFAULT); 34057c478bd9Sstevel@tonic-gate } 34067c478bd9Sstevel@tonic-gate return (0); 34077c478bd9Sstevel@tonic-gate } 34087c478bd9Sstevel@tonic-gate 34097c478bd9Sstevel@tonic-gate /* ARGSUSED */ 34107c478bd9Sstevel@tonic-gate static int 34117c478bd9Sstevel@tonic-gate digest_final(dev_t dev, caddr_t arg, int mode, int *rval) 34127c478bd9Sstevel@tonic-gate { 34137c478bd9Sstevel@tonic-gate return (common_final(dev, arg, mode, crypto_digest_final)); 34147c478bd9Sstevel@tonic-gate } 34157c478bd9Sstevel@tonic-gate 34167c478bd9Sstevel@tonic-gate /* ARGSUSED */ 34177c478bd9Sstevel@tonic-gate static int 34187c478bd9Sstevel@tonic-gate digest(dev_t dev, caddr_t arg, int mode, int *rval) 34197c478bd9Sstevel@tonic-gate { 34207c478bd9Sstevel@tonic-gate return (common_digest(dev, arg, mode, crypto_digest_single)); 34217c478bd9Sstevel@tonic-gate } 34227c478bd9Sstevel@tonic-gate 34237c478bd9Sstevel@tonic-gate /* 34247c478bd9Sstevel@tonic-gate * ASSUMPTION: crypto_digest, crypto_sign, crypto_sign_recover, 34257c478bd9Sstevel@tonic-gate * and crypto_verify_recover are identical except for field names. 34267c478bd9Sstevel@tonic-gate */ 34277c478bd9Sstevel@tonic-gate static int 34287c478bd9Sstevel@tonic-gate common_digest(dev_t dev, caddr_t arg, int mode, 34297c478bd9Sstevel@tonic-gate int (*single)(crypto_context_t, crypto_data_t *, crypto_data_t *, 34307c478bd9Sstevel@tonic-gate crypto_call_req_t *)) 34317c478bd9Sstevel@tonic-gate { 34327c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_digest, crypto_digest); 34337c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 34347c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 34352d794da1Skrishna crypto_session_data_t *sp = NULL; 34367c478bd9Sstevel@tonic-gate crypto_data_t data, digest; 34377c478bd9Sstevel@tonic-gate crypto_ctx_t **ctxpp; 34387c478bd9Sstevel@tonic-gate size_t datalen, digestlen, need = 0; 34397c478bd9Sstevel@tonic-gate char *digestbuf; 34407c478bd9Sstevel@tonic-gate int error = 0; 34417c478bd9Sstevel@tonic-gate int rv; 34422d794da1Skrishna boolean_t rctl_chk = B_FALSE; 34437c478bd9Sstevel@tonic-gate 34447c478bd9Sstevel@tonic-gate STRUCT_INIT(crypto_digest, mode); 34457c478bd9Sstevel@tonic-gate 34467c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 34477c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "common_digest: failed holding minor"); 34487c478bd9Sstevel@tonic-gate return (ENXIO); 34497c478bd9Sstevel@tonic-gate } 34507c478bd9Sstevel@tonic-gate 34517c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(crypto_digest), 34527c478bd9Sstevel@tonic-gate STRUCT_SIZE(crypto_digest)) != 0) { 34537c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 34547c478bd9Sstevel@tonic-gate return (EFAULT); 34557c478bd9Sstevel@tonic-gate } 34567c478bd9Sstevel@tonic-gate 34577c478bd9Sstevel@tonic-gate data.cd_raw.iov_base = NULL; 34587c478bd9Sstevel@tonic-gate digest.cd_raw.iov_base = NULL; 34597c478bd9Sstevel@tonic-gate 34607c478bd9Sstevel@tonic-gate datalen = STRUCT_FGET(crypto_digest, cd_datalen); 34617c478bd9Sstevel@tonic-gate digestlen = STRUCT_FGET(crypto_digest, cd_digestlen); 34627c478bd9Sstevel@tonic-gate 34637c478bd9Sstevel@tonic-gate /* 34647c478bd9Sstevel@tonic-gate * Don't allocate output buffer unless both buffer pointer and 34657c478bd9Sstevel@tonic-gate * buffer length are not NULL or 0 (length). 34667c478bd9Sstevel@tonic-gate */ 34677c478bd9Sstevel@tonic-gate digestbuf = STRUCT_FGETP(crypto_digest, cd_digestbuf); 34687c478bd9Sstevel@tonic-gate if (digestbuf == NULL || digestlen == 0) { 34697c478bd9Sstevel@tonic-gate digestlen = 0; 34707c478bd9Sstevel@tonic-gate } 34717c478bd9Sstevel@tonic-gate 34727c478bd9Sstevel@tonic-gate if (datalen > crypto_max_buffer_len || 34737c478bd9Sstevel@tonic-gate digestlen > crypto_max_buffer_len) { 34747c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "common_digest: buffer greater than %ld " 34757c478bd9Sstevel@tonic-gate "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 34767c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 34777c478bd9Sstevel@tonic-gate goto release_minor; 34787c478bd9Sstevel@tonic-gate } 34797c478bd9Sstevel@tonic-gate 34802d794da1Skrishna session_id = STRUCT_FGET(crypto_digest, cd_session); 34812d794da1Skrishna 34822d794da1Skrishna if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 34832d794da1Skrishna goto release_minor; 34842d794da1Skrishna } 34852d794da1Skrishna 34867c478bd9Sstevel@tonic-gate need = datalen + digestlen; 34872d794da1Skrishna if ((rv = CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)) != 34882d794da1Skrishna CRYPTO_SUCCESS) { 34897c478bd9Sstevel@tonic-gate need = 0; 34907c478bd9Sstevel@tonic-gate goto release_minor; 34917c478bd9Sstevel@tonic-gate } 34927c478bd9Sstevel@tonic-gate 34937c478bd9Sstevel@tonic-gate INIT_RAW_CRYPTO_DATA(data, datalen); 34947c478bd9Sstevel@tonic-gate 34957c478bd9Sstevel@tonic-gate if (datalen != 0 && copyin(STRUCT_FGETP(crypto_digest, cd_databuf), 34967c478bd9Sstevel@tonic-gate data.cd_raw.iov_base, datalen) != 0) { 34977c478bd9Sstevel@tonic-gate error = EFAULT; 34987c478bd9Sstevel@tonic-gate goto release_minor; 34997c478bd9Sstevel@tonic-gate } 35007c478bd9Sstevel@tonic-gate 35017c478bd9Sstevel@tonic-gate INIT_RAW_CRYPTO_DATA(digest, digestlen); 35027c478bd9Sstevel@tonic-gate 35037c478bd9Sstevel@tonic-gate ASSERT(single == crypto_digest_single || 35047c478bd9Sstevel@tonic-gate single == crypto_sign_single || 35057c478bd9Sstevel@tonic-gate single == crypto_verify_recover_single || 35067c478bd9Sstevel@tonic-gate single == crypto_sign_recover_single); 35077c478bd9Sstevel@tonic-gate 35087c478bd9Sstevel@tonic-gate if (single == crypto_digest_single) { 35097c478bd9Sstevel@tonic-gate ctxpp = &sp->sd_digest_ctx; 35107c478bd9Sstevel@tonic-gate } else if (single == crypto_sign_single) { 35117c478bd9Sstevel@tonic-gate ctxpp = &sp->sd_sign_ctx; 35127c478bd9Sstevel@tonic-gate } else if (single == crypto_verify_recover_single) { 35137c478bd9Sstevel@tonic-gate ctxpp = &sp->sd_verify_recover_ctx; 35147c478bd9Sstevel@tonic-gate } else { 35157c478bd9Sstevel@tonic-gate ctxpp = &sp->sd_sign_recover_ctx; 35167c478bd9Sstevel@tonic-gate } 35177c478bd9Sstevel@tonic-gate rv = (single)(*ctxpp, &data, &digest, NULL); 35187c478bd9Sstevel@tonic-gate if (KCF_CONTEXT_DONE(rv)) 35197c478bd9Sstevel@tonic-gate *ctxpp = NULL; 35207c478bd9Sstevel@tonic-gate 35217c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) { 35227c478bd9Sstevel@tonic-gate ASSERT(digest.cd_length <= digestlen); 35237c478bd9Sstevel@tonic-gate if (digest.cd_length != 0 && copyout(digest.cd_raw.iov_base, 35247c478bd9Sstevel@tonic-gate digestbuf, digest.cd_length) != 0) { 35257c478bd9Sstevel@tonic-gate error = EFAULT; 35267c478bd9Sstevel@tonic-gate goto release_minor; 35277c478bd9Sstevel@tonic-gate } 352895014fbbSDan OpenSolaris Anderson STRUCT_FSET(crypto_digest, cd_digestlen, 352995014fbbSDan OpenSolaris Anderson (ulong_t)digest.cd_length); 35307c478bd9Sstevel@tonic-gate } 35317c478bd9Sstevel@tonic-gate 35327c478bd9Sstevel@tonic-gate if (rv == CRYPTO_BUFFER_TOO_SMALL) { 35337c478bd9Sstevel@tonic-gate /* 35347c478bd9Sstevel@tonic-gate * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1 35357c478bd9Sstevel@tonic-gate * of section 11.2 of the pkcs11 spec. We catch it here and 35367c478bd9Sstevel@tonic-gate * provide the correct pkcs11 return value. 35377c478bd9Sstevel@tonic-gate */ 35387c478bd9Sstevel@tonic-gate if (STRUCT_FGETP(crypto_digest, cd_digestbuf) == NULL) 35397c478bd9Sstevel@tonic-gate rv = CRYPTO_SUCCESS; 354095014fbbSDan OpenSolaris Anderson STRUCT_FSET(crypto_digest, cd_digestlen, 354195014fbbSDan OpenSolaris Anderson (ulong_t)digest.cd_length); 35427c478bd9Sstevel@tonic-gate } 35437c478bd9Sstevel@tonic-gate 35447c478bd9Sstevel@tonic-gate release_minor: 35452d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk); 35462d794da1Skrishna CRYPTO_SESSION_RELE(sp); 35477c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 35487c478bd9Sstevel@tonic-gate 35497c478bd9Sstevel@tonic-gate if (data.cd_raw.iov_base != NULL) 35507c478bd9Sstevel@tonic-gate kmem_free(data.cd_raw.iov_base, datalen); 35517c478bd9Sstevel@tonic-gate 35527c478bd9Sstevel@tonic-gate if (digest.cd_raw.iov_base != NULL) 35537c478bd9Sstevel@tonic-gate kmem_free(digest.cd_raw.iov_base, digestlen); 35547c478bd9Sstevel@tonic-gate 35557c478bd9Sstevel@tonic-gate if (error != 0) 35567c478bd9Sstevel@tonic-gate return (error); 35577c478bd9Sstevel@tonic-gate 35587c478bd9Sstevel@tonic-gate STRUCT_FSET(crypto_digest, cd_return_value, rv); 35597c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(crypto_digest), arg, 35607c478bd9Sstevel@tonic-gate STRUCT_SIZE(crypto_digest)) != 0) { 35617c478bd9Sstevel@tonic-gate return (EFAULT); 35627c478bd9Sstevel@tonic-gate } 35637c478bd9Sstevel@tonic-gate return (0); 35647c478bd9Sstevel@tonic-gate } 35657c478bd9Sstevel@tonic-gate 35667c478bd9Sstevel@tonic-gate /* 35677c478bd9Sstevel@tonic-gate * A helper function that does what the name suggests. 35687c478bd9Sstevel@tonic-gate * Returns 0 on success and non-zero otherwise. 35697c478bd9Sstevel@tonic-gate * On failure, out_pin is set to 0. 35707c478bd9Sstevel@tonic-gate */ 35717c478bd9Sstevel@tonic-gate int 35727c478bd9Sstevel@tonic-gate get_pin_and_session_ptr(char *in_pin, char **out_pin, size_t pin_len, 35737c478bd9Sstevel@tonic-gate crypto_minor_t *cm, crypto_session_id_t sid, crypto_session_data_t **sp, 35747c478bd9Sstevel@tonic-gate int *rv, int *error) 35757c478bd9Sstevel@tonic-gate { 35767c478bd9Sstevel@tonic-gate char *tmp_pin = NULL; 35777c478bd9Sstevel@tonic-gate int tmp_error = 0, tmp_rv = 0; 35787c478bd9Sstevel@tonic-gate 35797c478bd9Sstevel@tonic-gate if (pin_len > KCF_MAX_PIN_LEN) { 35807c478bd9Sstevel@tonic-gate tmp_rv = CRYPTO_PIN_LEN_RANGE; 35817c478bd9Sstevel@tonic-gate goto out; 35827c478bd9Sstevel@tonic-gate } 35837c478bd9Sstevel@tonic-gate tmp_pin = kmem_alloc(pin_len, KM_SLEEP); 35847c478bd9Sstevel@tonic-gate 35857c478bd9Sstevel@tonic-gate if (pin_len != 0 && copyin(in_pin, tmp_pin, pin_len) != 0) { 35867c478bd9Sstevel@tonic-gate tmp_error = EFAULT; 35877c478bd9Sstevel@tonic-gate goto out; 35887c478bd9Sstevel@tonic-gate } 35897c478bd9Sstevel@tonic-gate 35907c478bd9Sstevel@tonic-gate (void) get_session_ptr(sid, cm, sp, &tmp_error, &tmp_rv); 35917c478bd9Sstevel@tonic-gate out: 35927c478bd9Sstevel@tonic-gate *out_pin = tmp_pin; 35937c478bd9Sstevel@tonic-gate *rv = tmp_rv; 35947c478bd9Sstevel@tonic-gate *error = tmp_error; 35957c478bd9Sstevel@tonic-gate return (tmp_rv | tmp_error); 35967c478bd9Sstevel@tonic-gate } 35977c478bd9Sstevel@tonic-gate 35987c478bd9Sstevel@tonic-gate /* ARGSUSED */ 35997c478bd9Sstevel@tonic-gate static int 36007c478bd9Sstevel@tonic-gate set_pin(dev_t dev, caddr_t arg, int mode, int *rval) 36017c478bd9Sstevel@tonic-gate { 36027c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_set_pin, set_pin); 36037c478bd9Sstevel@tonic-gate kcf_provider_desc_t *real_provider; 36047c478bd9Sstevel@tonic-gate kcf_req_params_t params; 36057c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 36067c478bd9Sstevel@tonic-gate crypto_session_data_t *sp; 36077c478bd9Sstevel@tonic-gate char *old_pin = NULL; 36087c478bd9Sstevel@tonic-gate char *new_pin = NULL; 36097c478bd9Sstevel@tonic-gate size_t old_pin_len; 36107c478bd9Sstevel@tonic-gate size_t new_pin_len; 36117c478bd9Sstevel@tonic-gate int error = 0; 36127c478bd9Sstevel@tonic-gate int rv; 36137c478bd9Sstevel@tonic-gate 36147c478bd9Sstevel@tonic-gate STRUCT_INIT(set_pin, mode); 36157c478bd9Sstevel@tonic-gate 36167c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 36177c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "set_pin: failed holding minor"); 36187c478bd9Sstevel@tonic-gate return (ENXIO); 36197c478bd9Sstevel@tonic-gate } 36207c478bd9Sstevel@tonic-gate 36217c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(set_pin), 36227c478bd9Sstevel@tonic-gate STRUCT_SIZE(set_pin)) != 0) { 36237c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 36247c478bd9Sstevel@tonic-gate return (EFAULT); 36257c478bd9Sstevel@tonic-gate } 36267c478bd9Sstevel@tonic-gate 36277c478bd9Sstevel@tonic-gate old_pin_len = STRUCT_FGET(set_pin, sp_old_len); 36287c478bd9Sstevel@tonic-gate 36297c478bd9Sstevel@tonic-gate if (get_pin_and_session_ptr(STRUCT_FGETP(set_pin, sp_old_pin), 36307c478bd9Sstevel@tonic-gate &old_pin, old_pin_len, cm, STRUCT_FGET(set_pin, sp_session), 36317c478bd9Sstevel@tonic-gate &sp, &rv, &error) != 0) 36327c478bd9Sstevel@tonic-gate goto release_minor; 36337c478bd9Sstevel@tonic-gate 36347c478bd9Sstevel@tonic-gate new_pin_len = STRUCT_FGET(set_pin, sp_new_len); 36357c478bd9Sstevel@tonic-gate if (new_pin_len > KCF_MAX_PIN_LEN) { 36367c478bd9Sstevel@tonic-gate rv = CRYPTO_PIN_LEN_RANGE; 36377c478bd9Sstevel@tonic-gate goto out; 36387c478bd9Sstevel@tonic-gate } 36397c478bd9Sstevel@tonic-gate new_pin = kmem_alloc(new_pin_len, KM_SLEEP); 36407c478bd9Sstevel@tonic-gate 36417c478bd9Sstevel@tonic-gate if (new_pin_len != 0 && copyin(STRUCT_FGETP(set_pin, sp_new_pin), 36427c478bd9Sstevel@tonic-gate new_pin, new_pin_len) != 0) { 36437c478bd9Sstevel@tonic-gate error = EFAULT; 36447c478bd9Sstevel@tonic-gate goto out; 36457c478bd9Sstevel@tonic-gate } 36467c478bd9Sstevel@tonic-gate 36477c478bd9Sstevel@tonic-gate if ((rv = kcf_get_hardware_provider_nomech( 36487c478bd9Sstevel@tonic-gate CRYPTO_OPS_OFFSET(provider_ops), CRYPTO_PROVIDER_OFFSET(set_pin), 36499b009fc1SValerie Bubb Fenwick sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 36507c478bd9Sstevel@tonic-gate goto out; 36517c478bd9Sstevel@tonic-gate } 36527c478bd9Sstevel@tonic-gate 36537c478bd9Sstevel@tonic-gate KCF_WRAP_PROVMGMT_OPS_PARAMS(¶ms, KCF_OP_MGMT_SETPIN, 36547c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, old_pin, old_pin_len, 36557c478bd9Sstevel@tonic-gate new_pin, new_pin_len, NULL, NULL, real_provider); 36567c478bd9Sstevel@tonic-gate 36577c478bd9Sstevel@tonic-gate rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 3658894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 36597c478bd9Sstevel@tonic-gate 36607c478bd9Sstevel@tonic-gate out: 36617c478bd9Sstevel@tonic-gate CRYPTO_SESSION_RELE(sp); 36627c478bd9Sstevel@tonic-gate 36637c478bd9Sstevel@tonic-gate release_minor: 36647c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 36657c478bd9Sstevel@tonic-gate 36667c478bd9Sstevel@tonic-gate if (old_pin != NULL) { 36677c478bd9Sstevel@tonic-gate bzero(old_pin, old_pin_len); 36687c478bd9Sstevel@tonic-gate kmem_free(old_pin, old_pin_len); 36697c478bd9Sstevel@tonic-gate } 36707c478bd9Sstevel@tonic-gate 36717c478bd9Sstevel@tonic-gate if (new_pin != NULL) { 36727c478bd9Sstevel@tonic-gate bzero(new_pin, new_pin_len); 36737c478bd9Sstevel@tonic-gate kmem_free(new_pin, new_pin_len); 36747c478bd9Sstevel@tonic-gate } 36757c478bd9Sstevel@tonic-gate 36767c478bd9Sstevel@tonic-gate if (error != 0) 36777c478bd9Sstevel@tonic-gate return (error); 36787c478bd9Sstevel@tonic-gate 36797c478bd9Sstevel@tonic-gate STRUCT_FSET(set_pin, sp_return_value, rv); 36807c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(set_pin), arg, STRUCT_SIZE(set_pin)) != 0) { 36817c478bd9Sstevel@tonic-gate return (EFAULT); 36827c478bd9Sstevel@tonic-gate } 36837c478bd9Sstevel@tonic-gate return (0); 36847c478bd9Sstevel@tonic-gate } 36857c478bd9Sstevel@tonic-gate 36867c478bd9Sstevel@tonic-gate /* ARGSUSED */ 36877c478bd9Sstevel@tonic-gate static int 36887c478bd9Sstevel@tonic-gate login(dev_t dev, caddr_t arg, int mode, int *rval) 36897c478bd9Sstevel@tonic-gate { 36907c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_login, login); 36917c478bd9Sstevel@tonic-gate kcf_provider_desc_t *real_provider; 36927c478bd9Sstevel@tonic-gate kcf_req_params_t params; 36937c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 36947c478bd9Sstevel@tonic-gate crypto_session_data_t *sp; 36957c478bd9Sstevel@tonic-gate size_t pin_len; 36967c478bd9Sstevel@tonic-gate char *pin; 36977c478bd9Sstevel@tonic-gate uint_t user_type; 36987c478bd9Sstevel@tonic-gate int error = 0; 36997c478bd9Sstevel@tonic-gate int rv; 37007c478bd9Sstevel@tonic-gate 37017c478bd9Sstevel@tonic-gate STRUCT_INIT(login, mode); 37027c478bd9Sstevel@tonic-gate 37037c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 37047c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "login: failed holding minor"); 37057c478bd9Sstevel@tonic-gate return (ENXIO); 37067c478bd9Sstevel@tonic-gate } 37077c478bd9Sstevel@tonic-gate 37087c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(login), STRUCT_SIZE(login)) != 0) { 37097c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 37107c478bd9Sstevel@tonic-gate return (EFAULT); 37117c478bd9Sstevel@tonic-gate } 37127c478bd9Sstevel@tonic-gate 37137c478bd9Sstevel@tonic-gate user_type = STRUCT_FGET(login, co_user_type); 37147c478bd9Sstevel@tonic-gate 37157c478bd9Sstevel@tonic-gate pin_len = STRUCT_FGET(login, co_pin_len); 37167c478bd9Sstevel@tonic-gate 37177c478bd9Sstevel@tonic-gate if (get_pin_and_session_ptr(STRUCT_FGETP(login, co_pin), 37187c478bd9Sstevel@tonic-gate &pin, pin_len, cm, STRUCT_FGET(login, co_session), 37197c478bd9Sstevel@tonic-gate &sp, &rv, &error) != 0) { 37207c478bd9Sstevel@tonic-gate if (rv == CRYPTO_PIN_LEN_RANGE) 37217c478bd9Sstevel@tonic-gate rv = CRYPTO_PIN_INCORRECT; 37227c478bd9Sstevel@tonic-gate goto release_minor; 37237c478bd9Sstevel@tonic-gate } 37247c478bd9Sstevel@tonic-gate 37257c478bd9Sstevel@tonic-gate if ((rv = kcf_get_hardware_provider_nomech( 37267c478bd9Sstevel@tonic-gate CRYPTO_OPS_OFFSET(session_ops), 37279b009fc1SValerie Bubb Fenwick CRYPTO_SESSION_OFFSET(session_login), sp->sd_provider, 37289b009fc1SValerie Bubb Fenwick &real_provider)) != CRYPTO_SUCCESS) { 37297c478bd9Sstevel@tonic-gate goto out; 37307c478bd9Sstevel@tonic-gate } 37317c478bd9Sstevel@tonic-gate 37327c478bd9Sstevel@tonic-gate KCF_WRAP_SESSION_OPS_PARAMS(¶ms, KCF_OP_SESSION_LOGIN, NULL, 37337c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, user_type, pin, pin_len, 37347c478bd9Sstevel@tonic-gate real_provider); 37357c478bd9Sstevel@tonic-gate 37367c478bd9Sstevel@tonic-gate rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 3737894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 37387c478bd9Sstevel@tonic-gate 37397c478bd9Sstevel@tonic-gate out: 37407c478bd9Sstevel@tonic-gate CRYPTO_SESSION_RELE(sp); 37417c478bd9Sstevel@tonic-gate 37427c478bd9Sstevel@tonic-gate release_minor: 37437c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 37447c478bd9Sstevel@tonic-gate 37457c478bd9Sstevel@tonic-gate if (pin != NULL) { 37467c478bd9Sstevel@tonic-gate bzero(pin, pin_len); 37477c478bd9Sstevel@tonic-gate kmem_free(pin, pin_len); 37487c478bd9Sstevel@tonic-gate } 37497c478bd9Sstevel@tonic-gate 37507c478bd9Sstevel@tonic-gate if (error != 0) 37517c478bd9Sstevel@tonic-gate return (error); 37527c478bd9Sstevel@tonic-gate 37537c478bd9Sstevel@tonic-gate STRUCT_FSET(login, co_return_value, rv); 37547c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(login), arg, STRUCT_SIZE(login)) != 0) { 37557c478bd9Sstevel@tonic-gate return (EFAULT); 37567c478bd9Sstevel@tonic-gate } 37577c478bd9Sstevel@tonic-gate return (0); 37587c478bd9Sstevel@tonic-gate } 37597c478bd9Sstevel@tonic-gate 37607c478bd9Sstevel@tonic-gate /* ARGSUSED */ 37617c478bd9Sstevel@tonic-gate static int 37627c478bd9Sstevel@tonic-gate logout(dev_t dev, caddr_t arg, int mode, int *rval) 37637c478bd9Sstevel@tonic-gate { 37647c478bd9Sstevel@tonic-gate crypto_logout_t logout; 37657c478bd9Sstevel@tonic-gate kcf_provider_desc_t *real_provider; 37667c478bd9Sstevel@tonic-gate kcf_req_params_t params; 37677c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 37687c478bd9Sstevel@tonic-gate crypto_session_data_t *sp; 37697c478bd9Sstevel@tonic-gate int error = 0; 37707c478bd9Sstevel@tonic-gate int rv; 37717c478bd9Sstevel@tonic-gate 37727c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 37737c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "logout: failed holding minor"); 37747c478bd9Sstevel@tonic-gate return (ENXIO); 37757c478bd9Sstevel@tonic-gate } 37767c478bd9Sstevel@tonic-gate 37777c478bd9Sstevel@tonic-gate if (copyin(arg, &logout, sizeof (logout)) != 0) { 37787c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 37797c478bd9Sstevel@tonic-gate return (EFAULT); 37807c478bd9Sstevel@tonic-gate } 37817c478bd9Sstevel@tonic-gate 37827c478bd9Sstevel@tonic-gate if (!get_session_ptr(logout.cl_session, cm, &sp, &error, &rv)) { 37837c478bd9Sstevel@tonic-gate goto release_minor; 37847c478bd9Sstevel@tonic-gate } 37857c478bd9Sstevel@tonic-gate 37867c478bd9Sstevel@tonic-gate if ((rv = kcf_get_hardware_provider_nomech( 37877c478bd9Sstevel@tonic-gate CRYPTO_OPS_OFFSET(session_ops), 37889b009fc1SValerie Bubb Fenwick CRYPTO_SESSION_OFFSET(session_logout), sp->sd_provider, 37899b009fc1SValerie Bubb Fenwick &real_provider)) != CRYPTO_SUCCESS) { 37907c478bd9Sstevel@tonic-gate goto out; 37917c478bd9Sstevel@tonic-gate } 37927c478bd9Sstevel@tonic-gate 37937c478bd9Sstevel@tonic-gate KCF_WRAP_SESSION_OPS_PARAMS(¶ms, KCF_OP_SESSION_LOGOUT, NULL, 37947c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, 0, NULL, 0, real_provider); 37957c478bd9Sstevel@tonic-gate rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 3796894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 37977c478bd9Sstevel@tonic-gate 37987c478bd9Sstevel@tonic-gate out: 37997c478bd9Sstevel@tonic-gate CRYPTO_SESSION_RELE(sp); 38007c478bd9Sstevel@tonic-gate 38017c478bd9Sstevel@tonic-gate release_minor: 38027c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 38037c478bd9Sstevel@tonic-gate 38047c478bd9Sstevel@tonic-gate if (error != 0) 38057c478bd9Sstevel@tonic-gate return (error); 38067c478bd9Sstevel@tonic-gate 38077c478bd9Sstevel@tonic-gate logout.cl_return_value = rv; 38087c478bd9Sstevel@tonic-gate if (copyout(&logout, arg, sizeof (logout)) != 0) { 38097c478bd9Sstevel@tonic-gate return (EFAULT); 38107c478bd9Sstevel@tonic-gate } 38117c478bd9Sstevel@tonic-gate return (0); 38127c478bd9Sstevel@tonic-gate } 38137c478bd9Sstevel@tonic-gate 38147c478bd9Sstevel@tonic-gate /* ARGSUSED */ 38157c478bd9Sstevel@tonic-gate static int 38167c478bd9Sstevel@tonic-gate sign_init(dev_t dev, caddr_t arg, int mode, int *rval) 38177c478bd9Sstevel@tonic-gate { 38187c478bd9Sstevel@tonic-gate return (sign_verify_init(dev, arg, mode, crypto_sign_init_prov)); 38197c478bd9Sstevel@tonic-gate } 38207c478bd9Sstevel@tonic-gate 38217c478bd9Sstevel@tonic-gate /* ARGSUSED */ 38227c478bd9Sstevel@tonic-gate static int 38237c478bd9Sstevel@tonic-gate sign_recover_init(dev_t dev, caddr_t arg, int mode, int *rval) 38247c478bd9Sstevel@tonic-gate { 38257c478bd9Sstevel@tonic-gate return (sign_verify_init(dev, arg, mode, 38267c478bd9Sstevel@tonic-gate crypto_sign_recover_init_prov)); 38277c478bd9Sstevel@tonic-gate } 38287c478bd9Sstevel@tonic-gate 38297c478bd9Sstevel@tonic-gate /* ARGSUSED */ 38307c478bd9Sstevel@tonic-gate static int 38317c478bd9Sstevel@tonic-gate verify_init(dev_t dev, caddr_t arg, int mode, int *rval) 38327c478bd9Sstevel@tonic-gate { 38337c478bd9Sstevel@tonic-gate return (sign_verify_init(dev, arg, mode, crypto_verify_init_prov)); 38347c478bd9Sstevel@tonic-gate } 38357c478bd9Sstevel@tonic-gate 38367c478bd9Sstevel@tonic-gate /* ARGSUSED */ 38377c478bd9Sstevel@tonic-gate static int 38387c478bd9Sstevel@tonic-gate verify_recover_init(dev_t dev, caddr_t arg, int mode, int *rval) 38397c478bd9Sstevel@tonic-gate { 38407c478bd9Sstevel@tonic-gate return (sign_verify_init(dev, arg, mode, 38417c478bd9Sstevel@tonic-gate crypto_verify_recover_init_prov)); 38427c478bd9Sstevel@tonic-gate } 38437c478bd9Sstevel@tonic-gate 38447c478bd9Sstevel@tonic-gate /* 38457c478bd9Sstevel@tonic-gate * ASSUMPTION: crypto_sign_init, crypto_verify_init, crypto_sign_recover_init, 38467c478bd9Sstevel@tonic-gate * and crypto_verify_recover_init structures are identical 38477c478bd9Sstevel@tonic-gate * except for field names. 38487c478bd9Sstevel@tonic-gate */ 38497c478bd9Sstevel@tonic-gate static int 38507c478bd9Sstevel@tonic-gate sign_verify_init(dev_t dev, caddr_t arg, int mode, 3851894b2776Smcpowers int (*init)(crypto_provider_t, crypto_session_id_t, 38527c478bd9Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_ctx_template_t, 38537c478bd9Sstevel@tonic-gate crypto_context_t *, crypto_call_req_t *)) 38547c478bd9Sstevel@tonic-gate { 38557c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_sign_init, sign_init); 3856894b2776Smcpowers kcf_provider_desc_t *real_provider = NULL; 38577c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 38587c478bd9Sstevel@tonic-gate crypto_mechanism_t mech; 38597c478bd9Sstevel@tonic-gate crypto_key_t key; 38607c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 38612d794da1Skrishna crypto_session_data_t *sp = NULL; 38627c478bd9Sstevel@tonic-gate crypto_context_t cc; 38637c478bd9Sstevel@tonic-gate crypto_ctx_t **ctxpp; 38647c478bd9Sstevel@tonic-gate size_t mech_rctl_bytes = 0; 38652d794da1Skrishna boolean_t mech_rctl_chk = B_FALSE; 38667c478bd9Sstevel@tonic-gate size_t key_rctl_bytes = 0; 38672d794da1Skrishna boolean_t key_rctl_chk = B_FALSE; 38687c478bd9Sstevel@tonic-gate int error = 0; 38697c478bd9Sstevel@tonic-gate int rv; 3870894b2776Smcpowers boolean_t allocated_by_crypto_module = B_FALSE; 387172eff6e2Smcpowers crypto_func_group_t fg; 38727c478bd9Sstevel@tonic-gate 38737c478bd9Sstevel@tonic-gate STRUCT_INIT(sign_init, mode); 38747c478bd9Sstevel@tonic-gate 38757c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 38767c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "sign_verify_init: failed holding minor"); 38777c478bd9Sstevel@tonic-gate return (ENXIO); 38787c478bd9Sstevel@tonic-gate } 38797c478bd9Sstevel@tonic-gate 38807c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(sign_init), STRUCT_SIZE(sign_init)) != 0) { 38817c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 38827c478bd9Sstevel@tonic-gate return (EFAULT); 38837c478bd9Sstevel@tonic-gate } 38847c478bd9Sstevel@tonic-gate 38857c478bd9Sstevel@tonic-gate mech.cm_param = NULL; 38867c478bd9Sstevel@tonic-gate bzero(&key, sizeof (key)); 38877c478bd9Sstevel@tonic-gate 38887c478bd9Sstevel@tonic-gate session_id = STRUCT_FGET(sign_init, si_session); 38897c478bd9Sstevel@tonic-gate 38907c478bd9Sstevel@tonic-gate if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 38912d794da1Skrishna goto out; 38927c478bd9Sstevel@tonic-gate } 38937c478bd9Sstevel@tonic-gate 3894894b2776Smcpowers bcopy(STRUCT_FADDR(sign_init, si_mech), &mech.cm_type, 3895894b2776Smcpowers sizeof (crypto_mech_type_t)); 38967c478bd9Sstevel@tonic-gate 38977c478bd9Sstevel@tonic-gate ASSERT(init == crypto_sign_init_prov || 38987c478bd9Sstevel@tonic-gate init == crypto_verify_init_prov || 38997c478bd9Sstevel@tonic-gate init == crypto_sign_recover_init_prov || 39007c478bd9Sstevel@tonic-gate init == crypto_verify_recover_init_prov); 39017c478bd9Sstevel@tonic-gate 39027c478bd9Sstevel@tonic-gate if (init == crypto_sign_init_prov) { 390372eff6e2Smcpowers fg = CRYPTO_FG_SIGN; 39047c478bd9Sstevel@tonic-gate ctxpp = &sp->sd_sign_ctx; 39057c478bd9Sstevel@tonic-gate } else if (init == crypto_verify_init_prov) { 390672eff6e2Smcpowers fg = CRYPTO_FG_VERIFY; 39077c478bd9Sstevel@tonic-gate ctxpp = &sp->sd_verify_ctx; 39087c478bd9Sstevel@tonic-gate } else if (init == crypto_sign_recover_init_prov) { 390972eff6e2Smcpowers fg = CRYPTO_FG_SIGN_RECOVER; 39107c478bd9Sstevel@tonic-gate ctxpp = &sp->sd_sign_recover_ctx; 39117c478bd9Sstevel@tonic-gate } else { 391272eff6e2Smcpowers fg = CRYPTO_FG_VERIFY_RECOVER; 39137c478bd9Sstevel@tonic-gate ctxpp = &sp->sd_verify_recover_ctx; 39147c478bd9Sstevel@tonic-gate } 39157c478bd9Sstevel@tonic-gate 3916436935a1SVladimir Kotal /* We need the key length for provider selection so copy it in now. */ 3917436935a1SVladimir Kotal if (!copyin_key(mode, sp, STRUCT_FADDR(sign_init, si_key), &key, 3918436935a1SVladimir Kotal &key_rctl_bytes, &key_rctl_chk, &rv, &error)) { 3919436935a1SVladimir Kotal goto out; 3920436935a1SVladimir Kotal } 3921436935a1SVladimir Kotal 3922436935a1SVladimir Kotal if ((rv = kcf_get_hardware_provider(mech.cm_type, &key, 39239b009fc1SValerie Bubb Fenwick CRYPTO_MECH_INVALID, NULL, sp->sd_provider, &real_provider, 39249b009fc1SValerie Bubb Fenwick fg)) != CRYPTO_SUCCESS) { 3925894b2776Smcpowers goto out; 3926894b2776Smcpowers } 3927894b2776Smcpowers 3928894b2776Smcpowers rv = crypto_provider_copyin_mech_param(real_provider, 3929894b2776Smcpowers STRUCT_FADDR(sign_init, si_mech), &mech, mode, &error); 3930894b2776Smcpowers 3931894b2776Smcpowers if (rv == CRYPTO_NOT_SUPPORTED) { 3932894b2776Smcpowers allocated_by_crypto_module = B_TRUE; 39332d794da1Skrishna if (!copyin_mech(mode, sp, STRUCT_FADDR(sign_init, si_mech), 39342d794da1Skrishna &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) { 3935894b2776Smcpowers goto out; 3936894b2776Smcpowers } 3937894b2776Smcpowers } else { 3938894b2776Smcpowers if (rv != CRYPTO_SUCCESS) 39397c478bd9Sstevel@tonic-gate goto out; 39407c478bd9Sstevel@tonic-gate } 39417c478bd9Sstevel@tonic-gate 39427c478bd9Sstevel@tonic-gate rv = (init)(real_provider, sp->sd_provider_session->ps_session, 39437c478bd9Sstevel@tonic-gate &mech, &key, NULL, &cc, NULL); 39447c478bd9Sstevel@tonic-gate 39457c478bd9Sstevel@tonic-gate /* 39467c478bd9Sstevel@tonic-gate * Check if a context already exists. If so, it means it is being 39477c478bd9Sstevel@tonic-gate * abandoned. So, cancel it to avoid leaking it. 39487c478bd9Sstevel@tonic-gate */ 39497c478bd9Sstevel@tonic-gate if (*ctxpp != NULL) 39507c478bd9Sstevel@tonic-gate CRYPTO_CANCEL_CTX(ctxpp); 39517c478bd9Sstevel@tonic-gate *ctxpp = (rv == CRYPTO_SUCCESS) ? cc : NULL; 39527c478bd9Sstevel@tonic-gate 39537c478bd9Sstevel@tonic-gate out: 39542d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk); 39552d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk); 39567c478bd9Sstevel@tonic-gate CRYPTO_SESSION_RELE(sp); 39577c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 39587c478bd9Sstevel@tonic-gate 3959894b2776Smcpowers if (real_provider != NULL) { 3960894b2776Smcpowers crypto_free_mech(real_provider, 3961894b2776Smcpowers allocated_by_crypto_module, &mech); 3962894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 3963894b2776Smcpowers } 39647c478bd9Sstevel@tonic-gate 39657c478bd9Sstevel@tonic-gate free_crypto_key(&key); 39667c478bd9Sstevel@tonic-gate 39677c478bd9Sstevel@tonic-gate if (error != 0) 39687c478bd9Sstevel@tonic-gate return (error); 39697c478bd9Sstevel@tonic-gate 39707c478bd9Sstevel@tonic-gate STRUCT_FSET(sign_init, si_return_value, rv); 39717c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(sign_init), arg, STRUCT_SIZE(sign_init)) != 0) { 39727c478bd9Sstevel@tonic-gate return (EFAULT); 39737c478bd9Sstevel@tonic-gate } 39747c478bd9Sstevel@tonic-gate return (0); 39757c478bd9Sstevel@tonic-gate } 39767c478bd9Sstevel@tonic-gate 39777c478bd9Sstevel@tonic-gate /* ARGSUSED */ 39787c478bd9Sstevel@tonic-gate static int 39797c478bd9Sstevel@tonic-gate sign(dev_t dev, caddr_t arg, int mode, int *rval) 39807c478bd9Sstevel@tonic-gate { 39817c478bd9Sstevel@tonic-gate return (common_digest(dev, arg, mode, crypto_sign_single)); 39827c478bd9Sstevel@tonic-gate } 39837c478bd9Sstevel@tonic-gate 39847c478bd9Sstevel@tonic-gate /* ARGSUSED */ 39857c478bd9Sstevel@tonic-gate static int 39867c478bd9Sstevel@tonic-gate sign_recover(dev_t dev, caddr_t arg, int mode, int *rval) 39877c478bd9Sstevel@tonic-gate { 39887c478bd9Sstevel@tonic-gate return (common_digest(dev, arg, mode, crypto_sign_recover_single)); 39897c478bd9Sstevel@tonic-gate } 39907c478bd9Sstevel@tonic-gate 39917c478bd9Sstevel@tonic-gate /* ARGSUSED */ 39927c478bd9Sstevel@tonic-gate static int 39937c478bd9Sstevel@tonic-gate verify(dev_t dev, caddr_t arg, int mode, int *rval) 39947c478bd9Sstevel@tonic-gate { 39957c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_verify, verify); 39967c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 39977c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 39982d794da1Skrishna crypto_session_data_t *sp = NULL; 39997c478bd9Sstevel@tonic-gate crypto_data_t data, sign; 40007c478bd9Sstevel@tonic-gate size_t datalen, signlen, need = 0; 40017c478bd9Sstevel@tonic-gate int error = 0; 40027c478bd9Sstevel@tonic-gate int rv; 40032d794da1Skrishna boolean_t rctl_chk = B_FALSE; 40047c478bd9Sstevel@tonic-gate 40057c478bd9Sstevel@tonic-gate STRUCT_INIT(verify, mode); 40067c478bd9Sstevel@tonic-gate 40077c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 40087c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "verify: failed holding minor"); 40097c478bd9Sstevel@tonic-gate return (ENXIO); 40107c478bd9Sstevel@tonic-gate } 40117c478bd9Sstevel@tonic-gate 40127c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(verify), STRUCT_SIZE(verify)) != 0) { 40137c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 40147c478bd9Sstevel@tonic-gate return (EFAULT); 40157c478bd9Sstevel@tonic-gate } 40167c478bd9Sstevel@tonic-gate 40177c478bd9Sstevel@tonic-gate data.cd_raw.iov_base = NULL; 40187c478bd9Sstevel@tonic-gate sign.cd_raw.iov_base = NULL; 40197c478bd9Sstevel@tonic-gate 40207c478bd9Sstevel@tonic-gate datalen = STRUCT_FGET(verify, cv_datalen); 40217c478bd9Sstevel@tonic-gate signlen = STRUCT_FGET(verify, cv_signlen); 40227c478bd9Sstevel@tonic-gate if (datalen > crypto_max_buffer_len || 40237c478bd9Sstevel@tonic-gate signlen > crypto_max_buffer_len) { 40247c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "verify: buffer greater than %ld bytes, " 40257c478bd9Sstevel@tonic-gate "pid = %d", crypto_max_buffer_len, curproc->p_pid); 40267c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 40277c478bd9Sstevel@tonic-gate goto release_minor; 40287c478bd9Sstevel@tonic-gate } 40297c478bd9Sstevel@tonic-gate 40302d794da1Skrishna session_id = STRUCT_FGET(verify, cv_session); 40312d794da1Skrishna 40322d794da1Skrishna if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 40332d794da1Skrishna goto release_minor; 40342d794da1Skrishna } 40352d794da1Skrishna 40367c478bd9Sstevel@tonic-gate need = datalen + signlen; 40372d794da1Skrishna if ((rv = CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)) != 40382d794da1Skrishna CRYPTO_SUCCESS) { 40397c478bd9Sstevel@tonic-gate need = 0; 40407c478bd9Sstevel@tonic-gate goto release_minor; 40417c478bd9Sstevel@tonic-gate } 40427c478bd9Sstevel@tonic-gate 40437c478bd9Sstevel@tonic-gate INIT_RAW_CRYPTO_DATA(data, datalen); 40447c478bd9Sstevel@tonic-gate INIT_RAW_CRYPTO_DATA(sign, signlen); 40457c478bd9Sstevel@tonic-gate 40467c478bd9Sstevel@tonic-gate if (datalen != 0 && copyin(STRUCT_FGETP(verify, cv_databuf), 40477c478bd9Sstevel@tonic-gate data.cd_raw.iov_base, datalen) != 0) { 40487c478bd9Sstevel@tonic-gate error = EFAULT; 40497c478bd9Sstevel@tonic-gate goto release_minor; 40507c478bd9Sstevel@tonic-gate } 40517c478bd9Sstevel@tonic-gate 40527c478bd9Sstevel@tonic-gate if (signlen != 0 && copyin(STRUCT_FGETP(verify, cv_signbuf), 40537c478bd9Sstevel@tonic-gate sign.cd_raw.iov_base, signlen) != 0) { 40547c478bd9Sstevel@tonic-gate error = EFAULT; 40557c478bd9Sstevel@tonic-gate goto release_minor; 40567c478bd9Sstevel@tonic-gate } 40577c478bd9Sstevel@tonic-gate 40587c478bd9Sstevel@tonic-gate rv = crypto_verify_single(sp->sd_verify_ctx, &data, &sign, NULL); 40597c478bd9Sstevel@tonic-gate if (KCF_CONTEXT_DONE(rv)) 40607c478bd9Sstevel@tonic-gate sp->sd_verify_ctx = NULL; 40617c478bd9Sstevel@tonic-gate 40627c478bd9Sstevel@tonic-gate release_minor: 40632d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk); 40642d794da1Skrishna CRYPTO_SESSION_RELE(sp); 40657c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 40667c478bd9Sstevel@tonic-gate 40677c478bd9Sstevel@tonic-gate if (data.cd_raw.iov_base != NULL) 40687c478bd9Sstevel@tonic-gate kmem_free(data.cd_raw.iov_base, datalen); 40697c478bd9Sstevel@tonic-gate 40707c478bd9Sstevel@tonic-gate if (sign.cd_raw.iov_base != NULL) 40717c478bd9Sstevel@tonic-gate kmem_free(sign.cd_raw.iov_base, signlen); 40727c478bd9Sstevel@tonic-gate 40737c478bd9Sstevel@tonic-gate if (error != 0) 40747c478bd9Sstevel@tonic-gate return (error); 40757c478bd9Sstevel@tonic-gate 40767c478bd9Sstevel@tonic-gate STRUCT_FSET(verify, cv_return_value, rv); 40777c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(verify), arg, STRUCT_SIZE(verify)) != 0) { 40787c478bd9Sstevel@tonic-gate return (EFAULT); 40797c478bd9Sstevel@tonic-gate } 40807c478bd9Sstevel@tonic-gate return (0); 40817c478bd9Sstevel@tonic-gate } 40827c478bd9Sstevel@tonic-gate 40837c478bd9Sstevel@tonic-gate /* ARGSUSED */ 40847c478bd9Sstevel@tonic-gate static int 40857c478bd9Sstevel@tonic-gate verify_recover(dev_t dev, caddr_t arg, int mode, int *rval) 40867c478bd9Sstevel@tonic-gate { 40877c478bd9Sstevel@tonic-gate return (common_digest(dev, arg, mode, crypto_verify_recover_single)); 40887c478bd9Sstevel@tonic-gate } 40897c478bd9Sstevel@tonic-gate 40907c478bd9Sstevel@tonic-gate /* ARGSUSED */ 40917c478bd9Sstevel@tonic-gate static int 40927c478bd9Sstevel@tonic-gate sign_update(dev_t dev, caddr_t arg, int mode, int *rval) 40937c478bd9Sstevel@tonic-gate { 40947c478bd9Sstevel@tonic-gate return (sign_verify_update(dev, arg, mode, crypto_sign_update)); 40957c478bd9Sstevel@tonic-gate } 40967c478bd9Sstevel@tonic-gate 40977c478bd9Sstevel@tonic-gate /* ARGSUSED */ 40987c478bd9Sstevel@tonic-gate static int 40997c478bd9Sstevel@tonic-gate verify_update(dev_t dev, caddr_t arg, int mode, int *rval) 41007c478bd9Sstevel@tonic-gate { 41017c478bd9Sstevel@tonic-gate return (sign_verify_update(dev, arg, mode, crypto_verify_update)); 41027c478bd9Sstevel@tonic-gate } 41037c478bd9Sstevel@tonic-gate 41047c478bd9Sstevel@tonic-gate /* 41057c478bd9Sstevel@tonic-gate * ASSUMPTION: crypto_sign_update and crypto_verify_update structures 41067c478bd9Sstevel@tonic-gate * are identical except for field names. 41077c478bd9Sstevel@tonic-gate */ 41087c478bd9Sstevel@tonic-gate static int 41097c478bd9Sstevel@tonic-gate sign_verify_update(dev_t dev, caddr_t arg, int mode, 41107c478bd9Sstevel@tonic-gate int (*update)(crypto_context_t, crypto_data_t *, crypto_call_req_t *)) 41117c478bd9Sstevel@tonic-gate { 41127c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_sign_update, sign_update); 41137c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 41147c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 41152d794da1Skrishna crypto_session_data_t *sp = NULL; 41167c478bd9Sstevel@tonic-gate crypto_ctx_t **ctxpp; 41177c478bd9Sstevel@tonic-gate crypto_data_t data; 41187c478bd9Sstevel@tonic-gate size_t datalen, need = 0; 41197c478bd9Sstevel@tonic-gate int error = 0; 41207c478bd9Sstevel@tonic-gate int rv; 41212d794da1Skrishna boolean_t rctl_chk = B_FALSE; 41227c478bd9Sstevel@tonic-gate 41237c478bd9Sstevel@tonic-gate STRUCT_INIT(sign_update, mode); 41247c478bd9Sstevel@tonic-gate 41257c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 41267c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "sign_verify_update: failed holding minor"); 41277c478bd9Sstevel@tonic-gate return (ENXIO); 41287c478bd9Sstevel@tonic-gate } 41297c478bd9Sstevel@tonic-gate 41307c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(sign_update), 41317c478bd9Sstevel@tonic-gate STRUCT_SIZE(sign_update)) != 0) { 41327c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 41337c478bd9Sstevel@tonic-gate return (EFAULT); 41347c478bd9Sstevel@tonic-gate } 41357c478bd9Sstevel@tonic-gate 41367c478bd9Sstevel@tonic-gate data.cd_raw.iov_base = NULL; 41377c478bd9Sstevel@tonic-gate 41387c478bd9Sstevel@tonic-gate datalen = STRUCT_FGET(sign_update, su_datalen); 41397c478bd9Sstevel@tonic-gate if (datalen > crypto_max_buffer_len) { 41407c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "sign_verify_update: buffer greater than %ld " 41417c478bd9Sstevel@tonic-gate "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 41427c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 41437c478bd9Sstevel@tonic-gate goto release_minor; 41447c478bd9Sstevel@tonic-gate } 41457c478bd9Sstevel@tonic-gate 41462d794da1Skrishna session_id = STRUCT_FGET(sign_update, su_session); 41472d794da1Skrishna 41482d794da1Skrishna if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 41492d794da1Skrishna goto release_minor; 41502d794da1Skrishna } 41512d794da1Skrishna 41522d794da1Skrishna if ((rv = CRYPTO_BUFFER_CHECK(sp, datalen, rctl_chk)) != 41532d794da1Skrishna CRYPTO_SUCCESS) { 41547c478bd9Sstevel@tonic-gate goto release_minor; 41557c478bd9Sstevel@tonic-gate } 41567c478bd9Sstevel@tonic-gate need = datalen; 41577c478bd9Sstevel@tonic-gate 41587c478bd9Sstevel@tonic-gate INIT_RAW_CRYPTO_DATA(data, datalen); 41597c478bd9Sstevel@tonic-gate 41607c478bd9Sstevel@tonic-gate if (datalen != 0 && copyin(STRUCT_FGETP(sign_update, su_databuf), 41617c478bd9Sstevel@tonic-gate data.cd_raw.iov_base, datalen) != 0) { 41627c478bd9Sstevel@tonic-gate error = EFAULT; 41637c478bd9Sstevel@tonic-gate goto release_minor; 41647c478bd9Sstevel@tonic-gate } 41657c478bd9Sstevel@tonic-gate 41667c478bd9Sstevel@tonic-gate ctxpp = (update == crypto_sign_update) ? 41677c478bd9Sstevel@tonic-gate &sp->sd_sign_ctx : &sp->sd_verify_ctx; 41687c478bd9Sstevel@tonic-gate 41697c478bd9Sstevel@tonic-gate rv = (update)(*ctxpp, &data, NULL); 41707c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) 41717c478bd9Sstevel@tonic-gate CRYPTO_CANCEL_CTX(ctxpp); 41727c478bd9Sstevel@tonic-gate 41737c478bd9Sstevel@tonic-gate release_minor: 41742d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk); 41752d794da1Skrishna CRYPTO_SESSION_RELE(sp); 41767c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 41777c478bd9Sstevel@tonic-gate 41787c478bd9Sstevel@tonic-gate if (data.cd_raw.iov_base != NULL) 41797c478bd9Sstevel@tonic-gate kmem_free(data.cd_raw.iov_base, datalen); 41807c478bd9Sstevel@tonic-gate 41817c478bd9Sstevel@tonic-gate if (error != 0) 41827c478bd9Sstevel@tonic-gate return (error); 41837c478bd9Sstevel@tonic-gate 41847c478bd9Sstevel@tonic-gate STRUCT_FSET(sign_update, su_return_value, rv); 41857c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(sign_update), arg, 41867c478bd9Sstevel@tonic-gate STRUCT_SIZE(sign_update)) != 0) { 41877c478bd9Sstevel@tonic-gate return (EFAULT); 41887c478bd9Sstevel@tonic-gate } 41897c478bd9Sstevel@tonic-gate return (0); 41907c478bd9Sstevel@tonic-gate } 41917c478bd9Sstevel@tonic-gate 41927c478bd9Sstevel@tonic-gate /* ARGSUSED */ 41937c478bd9Sstevel@tonic-gate static int 41947c478bd9Sstevel@tonic-gate sign_final(dev_t dev, caddr_t arg, int mode, int *rval) 41957c478bd9Sstevel@tonic-gate { 41967c478bd9Sstevel@tonic-gate return (common_final(dev, arg, mode, crypto_sign_final)); 41977c478bd9Sstevel@tonic-gate } 41987c478bd9Sstevel@tonic-gate 41997c478bd9Sstevel@tonic-gate /* 42007c478bd9Sstevel@tonic-gate * Can't use the common final because it does a copyout of 42017c478bd9Sstevel@tonic-gate * the final part. 42027c478bd9Sstevel@tonic-gate */ 42037c478bd9Sstevel@tonic-gate /* ARGSUSED */ 42047c478bd9Sstevel@tonic-gate static int 42057c478bd9Sstevel@tonic-gate verify_final(dev_t dev, caddr_t arg, int mode, int *rval) 42067c478bd9Sstevel@tonic-gate { 42077c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_verify_final, verify_final); 42087c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 42097c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 42102d794da1Skrishna crypto_session_data_t *sp = NULL; 42117c478bd9Sstevel@tonic-gate crypto_data_t sign; 42127c478bd9Sstevel@tonic-gate size_t signlen, need = 0; 42137c478bd9Sstevel@tonic-gate int error = 0; 42147c478bd9Sstevel@tonic-gate int rv; 42152d794da1Skrishna boolean_t rctl_chk = B_FALSE; 42167c478bd9Sstevel@tonic-gate 42177c478bd9Sstevel@tonic-gate STRUCT_INIT(verify_final, mode); 42187c478bd9Sstevel@tonic-gate 42197c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 42207c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "verify_final: failed holding minor"); 42217c478bd9Sstevel@tonic-gate return (ENXIO); 42227c478bd9Sstevel@tonic-gate } 42237c478bd9Sstevel@tonic-gate 42247c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(verify_final), 42257c478bd9Sstevel@tonic-gate STRUCT_SIZE(verify_final)) != 0) { 42267c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 42277c478bd9Sstevel@tonic-gate return (EFAULT); 42287c478bd9Sstevel@tonic-gate } 42297c478bd9Sstevel@tonic-gate 42307c478bd9Sstevel@tonic-gate sign.cd_raw.iov_base = NULL; 42317c478bd9Sstevel@tonic-gate 42327c478bd9Sstevel@tonic-gate signlen = STRUCT_FGET(verify_final, vf_signlen); 42337c478bd9Sstevel@tonic-gate if (signlen > crypto_max_buffer_len) { 42347c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "verify_final: buffer greater than %ld " 42357c478bd9Sstevel@tonic-gate "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 42367c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 42377c478bd9Sstevel@tonic-gate goto release_minor; 42387c478bd9Sstevel@tonic-gate } 42397c478bd9Sstevel@tonic-gate 42402d794da1Skrishna session_id = STRUCT_FGET(verify_final, vf_session); 42412d794da1Skrishna 42422d794da1Skrishna if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 42432d794da1Skrishna goto release_minor; 42442d794da1Skrishna } 42452d794da1Skrishna 42462d794da1Skrishna if ((rv = CRYPTO_BUFFER_CHECK(sp, signlen, rctl_chk)) != 42472d794da1Skrishna CRYPTO_SUCCESS) { 42487c478bd9Sstevel@tonic-gate goto release_minor; 42497c478bd9Sstevel@tonic-gate } 42507c478bd9Sstevel@tonic-gate need = signlen; 42517c478bd9Sstevel@tonic-gate 42527c478bd9Sstevel@tonic-gate INIT_RAW_CRYPTO_DATA(sign, signlen); 42537c478bd9Sstevel@tonic-gate 42547c478bd9Sstevel@tonic-gate if (signlen != 0 && copyin(STRUCT_FGETP(verify_final, vf_signbuf), 42557c478bd9Sstevel@tonic-gate sign.cd_raw.iov_base, signlen) != 0) { 42567c478bd9Sstevel@tonic-gate error = EFAULT; 42577c478bd9Sstevel@tonic-gate goto release_minor; 42587c478bd9Sstevel@tonic-gate } 42597c478bd9Sstevel@tonic-gate 42607c478bd9Sstevel@tonic-gate rv = crypto_verify_final(sp->sd_verify_ctx, &sign, NULL); 42617c478bd9Sstevel@tonic-gate if (KCF_CONTEXT_DONE(rv)) 42627c478bd9Sstevel@tonic-gate sp->sd_verify_ctx = NULL; 42637c478bd9Sstevel@tonic-gate 42647c478bd9Sstevel@tonic-gate release_minor: 42652d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk); 42662d794da1Skrishna CRYPTO_SESSION_RELE(sp); 42677c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 42687c478bd9Sstevel@tonic-gate 42697c478bd9Sstevel@tonic-gate if (sign.cd_raw.iov_base != NULL) 42707c478bd9Sstevel@tonic-gate kmem_free(sign.cd_raw.iov_base, signlen); 42717c478bd9Sstevel@tonic-gate 42727c478bd9Sstevel@tonic-gate if (error != 0) 42737c478bd9Sstevel@tonic-gate return (error); 42747c478bd9Sstevel@tonic-gate 42757c478bd9Sstevel@tonic-gate STRUCT_FSET(verify_final, vf_return_value, rv); 42767c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(verify_final), arg, 42777c478bd9Sstevel@tonic-gate STRUCT_SIZE(verify_final)) != 0) { 42787c478bd9Sstevel@tonic-gate return (EFAULT); 42797c478bd9Sstevel@tonic-gate } 42807c478bd9Sstevel@tonic-gate return (0); 42817c478bd9Sstevel@tonic-gate } 42827c478bd9Sstevel@tonic-gate 42837c478bd9Sstevel@tonic-gate /* ARGSUSED */ 42847c478bd9Sstevel@tonic-gate static int 42857c478bd9Sstevel@tonic-gate seed_random(dev_t dev, caddr_t arg, int mode, int *rval) 42867c478bd9Sstevel@tonic-gate { 42877c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_seed_random, seed_random); 4288894b2776Smcpowers kcf_provider_desc_t *real_provider = NULL; 42897c478bd9Sstevel@tonic-gate kcf_req_params_t params; 42907c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 42917c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 42922d794da1Skrishna crypto_session_data_t *sp = NULL; 42937c478bd9Sstevel@tonic-gate uchar_t *seed_buffer = NULL; 42947c478bd9Sstevel@tonic-gate size_t seed_len; 42957c478bd9Sstevel@tonic-gate size_t need = 0; 42967c478bd9Sstevel@tonic-gate int error = 0; 42977c478bd9Sstevel@tonic-gate int rv; 42982d794da1Skrishna boolean_t rctl_chk = B_FALSE; 42997c478bd9Sstevel@tonic-gate 43007c478bd9Sstevel@tonic-gate STRUCT_INIT(seed_random, mode); 43017c478bd9Sstevel@tonic-gate 43027c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 43037c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "seed_random: failed holding minor"); 43047c478bd9Sstevel@tonic-gate return (ENXIO); 43057c478bd9Sstevel@tonic-gate } 43067c478bd9Sstevel@tonic-gate 43077c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(seed_random), 43087c478bd9Sstevel@tonic-gate STRUCT_SIZE(seed_random)) != 0) { 43097c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 43107c478bd9Sstevel@tonic-gate return (EFAULT); 43117c478bd9Sstevel@tonic-gate } 43127c478bd9Sstevel@tonic-gate 43137c478bd9Sstevel@tonic-gate seed_len = STRUCT_FGET(seed_random, sr_seedlen); 43147c478bd9Sstevel@tonic-gate if (seed_len > crypto_max_buffer_len) { 43157c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "seed_random: buffer greater than %ld " 43167c478bd9Sstevel@tonic-gate "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 43177c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 43187c478bd9Sstevel@tonic-gate goto release_minor; 43197c478bd9Sstevel@tonic-gate } 43207c478bd9Sstevel@tonic-gate 43212d794da1Skrishna session_id = STRUCT_FGET(seed_random, sr_session); 43222d794da1Skrishna 43232d794da1Skrishna if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 43242d794da1Skrishna goto release_minor; 43252d794da1Skrishna } 43262d794da1Skrishna 43272d794da1Skrishna if ((rv = CRYPTO_BUFFER_CHECK(sp, seed_len, rctl_chk)) != 43282d794da1Skrishna CRYPTO_SUCCESS) { 43297c478bd9Sstevel@tonic-gate goto release_minor; 43307c478bd9Sstevel@tonic-gate } 43317c478bd9Sstevel@tonic-gate need = seed_len; 43327c478bd9Sstevel@tonic-gate seed_buffer = kmem_alloc(seed_len, KM_SLEEP); 43337c478bd9Sstevel@tonic-gate 43347c478bd9Sstevel@tonic-gate if (seed_len != 0 && copyin(STRUCT_FGETP(seed_random, sr_seedbuf), 43357c478bd9Sstevel@tonic-gate seed_buffer, seed_len) != 0) { 43367c478bd9Sstevel@tonic-gate error = EFAULT; 43377c478bd9Sstevel@tonic-gate goto release_minor; 43387c478bd9Sstevel@tonic-gate } 43397c478bd9Sstevel@tonic-gate 434072eff6e2Smcpowers if ((rv = kcf_get_hardware_provider_nomech( 4341894b2776Smcpowers CRYPTO_OPS_OFFSET(random_ops), CRYPTO_RANDOM_OFFSET(seed_random), 43429b009fc1SValerie Bubb Fenwick sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 43432d794da1Skrishna goto release_minor; 43447c478bd9Sstevel@tonic-gate } 43457c478bd9Sstevel@tonic-gate 43467c478bd9Sstevel@tonic-gate KCF_WRAP_RANDOM_OPS_PARAMS(¶ms, KCF_OP_RANDOM_SEED, 43478047c9fbSmcpowers sp->sd_provider_session->ps_session, seed_buffer, seed_len, 0, 43488047c9fbSmcpowers CRYPTO_SEED_NOW); 43497c478bd9Sstevel@tonic-gate 43507c478bd9Sstevel@tonic-gate rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 43517c478bd9Sstevel@tonic-gate 43527c478bd9Sstevel@tonic-gate release_minor: 43532d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk); 43542d794da1Skrishna CRYPTO_SESSION_RELE(sp); 43557c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 43567c478bd9Sstevel@tonic-gate 4357894b2776Smcpowers if (real_provider != NULL) 4358894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 4359894b2776Smcpowers 43607c478bd9Sstevel@tonic-gate if (seed_buffer != NULL) 43617c478bd9Sstevel@tonic-gate kmem_free(seed_buffer, seed_len); 43627c478bd9Sstevel@tonic-gate 43637c478bd9Sstevel@tonic-gate if (error != 0) 43647c478bd9Sstevel@tonic-gate return (error); 43657c478bd9Sstevel@tonic-gate 43667c478bd9Sstevel@tonic-gate STRUCT_FSET(seed_random, sr_return_value, rv); 43677c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(seed_random), arg, 43687c478bd9Sstevel@tonic-gate STRUCT_SIZE(seed_random)) != 0) { 43697c478bd9Sstevel@tonic-gate return (EFAULT); 43707c478bd9Sstevel@tonic-gate } 43717c478bd9Sstevel@tonic-gate return (0); 43727c478bd9Sstevel@tonic-gate } 43737c478bd9Sstevel@tonic-gate 43747c478bd9Sstevel@tonic-gate /* ARGSUSED */ 43757c478bd9Sstevel@tonic-gate static int 43767c478bd9Sstevel@tonic-gate generate_random(dev_t dev, caddr_t arg, int mode, int *rval) 43777c478bd9Sstevel@tonic-gate { 43787c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_generate_random, generate_random); 4379894b2776Smcpowers kcf_provider_desc_t *real_provider = NULL; 43807c478bd9Sstevel@tonic-gate kcf_req_params_t params; 43817c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 43827c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 43832d794da1Skrishna crypto_session_data_t *sp = NULL; 43847c478bd9Sstevel@tonic-gate uchar_t *buffer = NULL; 43857c478bd9Sstevel@tonic-gate size_t len; 43867c478bd9Sstevel@tonic-gate size_t need = 0; 43877c478bd9Sstevel@tonic-gate int error = 0; 43887c478bd9Sstevel@tonic-gate int rv; 43892d794da1Skrishna boolean_t rctl_chk = B_FALSE; 43907c478bd9Sstevel@tonic-gate 43917c478bd9Sstevel@tonic-gate STRUCT_INIT(generate_random, mode); 43927c478bd9Sstevel@tonic-gate 43937c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 43947c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "generate_random: failed holding minor"); 43957c478bd9Sstevel@tonic-gate return (ENXIO); 43967c478bd9Sstevel@tonic-gate } 43977c478bd9Sstevel@tonic-gate 43987c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(generate_random), 43997c478bd9Sstevel@tonic-gate STRUCT_SIZE(generate_random)) != 0) { 44007c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 44017c478bd9Sstevel@tonic-gate return (EFAULT); 44027c478bd9Sstevel@tonic-gate } 44037c478bd9Sstevel@tonic-gate 44047c478bd9Sstevel@tonic-gate len = STRUCT_FGET(generate_random, gr_buflen); 44057c478bd9Sstevel@tonic-gate if (len > crypto_max_buffer_len) { 44067c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "generate_random: buffer greater than %ld " 44077c478bd9Sstevel@tonic-gate "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 44087c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 44097c478bd9Sstevel@tonic-gate goto release_minor; 44107c478bd9Sstevel@tonic-gate } 44117c478bd9Sstevel@tonic-gate 44127c478bd9Sstevel@tonic-gate session_id = STRUCT_FGET(generate_random, gr_session); 44137c478bd9Sstevel@tonic-gate 44147c478bd9Sstevel@tonic-gate if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 44157c478bd9Sstevel@tonic-gate goto release_minor; 44167c478bd9Sstevel@tonic-gate } 44177c478bd9Sstevel@tonic-gate 44182d794da1Skrishna if ((rv = CRYPTO_BUFFER_CHECK(sp, len, rctl_chk)) != 44192d794da1Skrishna CRYPTO_SUCCESS) { 44202d794da1Skrishna goto release_minor; 44212d794da1Skrishna } 44222d794da1Skrishna need = len; 44232d794da1Skrishna buffer = kmem_alloc(len, KM_SLEEP); 44242d794da1Skrishna 442572eff6e2Smcpowers if ((rv = kcf_get_hardware_provider_nomech( 44267c478bd9Sstevel@tonic-gate CRYPTO_OPS_OFFSET(random_ops), 44279b009fc1SValerie Bubb Fenwick CRYPTO_RANDOM_OFFSET(generate_random), sp->sd_provider, 44289b009fc1SValerie Bubb Fenwick &real_provider)) != CRYPTO_SUCCESS) { 44292d794da1Skrishna goto release_minor; 44307c478bd9Sstevel@tonic-gate } 44317c478bd9Sstevel@tonic-gate 44327c478bd9Sstevel@tonic-gate KCF_WRAP_RANDOM_OPS_PARAMS(¶ms, KCF_OP_RANDOM_GENERATE, 44338047c9fbSmcpowers sp->sd_provider_session->ps_session, buffer, len, 0, 0); 44347c478bd9Sstevel@tonic-gate 44357c478bd9Sstevel@tonic-gate rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 44367c478bd9Sstevel@tonic-gate 44377c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) { 44387c478bd9Sstevel@tonic-gate if (len != 0 && copyout(buffer, 44397c478bd9Sstevel@tonic-gate STRUCT_FGETP(generate_random, gr_buf), len) != 0) { 44407c478bd9Sstevel@tonic-gate error = EFAULT; 44417c478bd9Sstevel@tonic-gate } 44427c478bd9Sstevel@tonic-gate } 44437c478bd9Sstevel@tonic-gate 44447c478bd9Sstevel@tonic-gate release_minor: 44452d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk); 44462d794da1Skrishna CRYPTO_SESSION_RELE(sp); 44477c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 44487c478bd9Sstevel@tonic-gate 4449894b2776Smcpowers if (real_provider != NULL) 4450894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 4451894b2776Smcpowers 44527c478bd9Sstevel@tonic-gate if (buffer != NULL) { 44537c478bd9Sstevel@tonic-gate /* random numbers are often used to create keys */ 44547c478bd9Sstevel@tonic-gate bzero(buffer, len); 44557c478bd9Sstevel@tonic-gate kmem_free(buffer, len); 44567c478bd9Sstevel@tonic-gate } 44577c478bd9Sstevel@tonic-gate 44587c478bd9Sstevel@tonic-gate if (error != 0) 44597c478bd9Sstevel@tonic-gate return (error); 44607c478bd9Sstevel@tonic-gate 44617c478bd9Sstevel@tonic-gate STRUCT_FSET(generate_random, gr_return_value, rv); 44627c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(generate_random), arg, 44637c478bd9Sstevel@tonic-gate STRUCT_SIZE(generate_random)) != 0) { 44647c478bd9Sstevel@tonic-gate return (EFAULT); 44657c478bd9Sstevel@tonic-gate } 44667c478bd9Sstevel@tonic-gate return (0); 44677c478bd9Sstevel@tonic-gate } 44687c478bd9Sstevel@tonic-gate 44697c478bd9Sstevel@tonic-gate /* 44707c478bd9Sstevel@tonic-gate * Copyout a kernel array of attributes to user space. 44717c478bd9Sstevel@tonic-gate * u_attrs is the corresponding user space array containing 44727c478bd9Sstevel@tonic-gate * user space pointers necessary for the copyout. 44737c478bd9Sstevel@tonic-gate */ 44747c478bd9Sstevel@tonic-gate /* ARGSUSED */ 44757c478bd9Sstevel@tonic-gate static int 44767c478bd9Sstevel@tonic-gate copyout_attributes(int mode, caddr_t out, uint_t count, 44777c478bd9Sstevel@tonic-gate crypto_object_attribute_t *k_attrs, caddr_t u_attrs) 44787c478bd9Sstevel@tonic-gate { 44797c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_object_attribute, oa); 44807c478bd9Sstevel@tonic-gate caddr_t p, valuep; 44817c478bd9Sstevel@tonic-gate size_t value_len; 44827c478bd9Sstevel@tonic-gate size_t len; 44837c478bd9Sstevel@tonic-gate int i; 44847c478bd9Sstevel@tonic-gate int error = 0; 44857c478bd9Sstevel@tonic-gate 44867c478bd9Sstevel@tonic-gate if (count == 0) 44877c478bd9Sstevel@tonic-gate return (0); 44887c478bd9Sstevel@tonic-gate 44897c478bd9Sstevel@tonic-gate STRUCT_INIT(oa, mode); 44907c478bd9Sstevel@tonic-gate 44917c478bd9Sstevel@tonic-gate len = count * STRUCT_SIZE(oa); 44927c478bd9Sstevel@tonic-gate 44937c478bd9Sstevel@tonic-gate ASSERT(u_attrs != NULL); 44947c478bd9Sstevel@tonic-gate p = u_attrs; 44957c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++) { 44967c478bd9Sstevel@tonic-gate /* can this bcopy be eliminated? */ 44977c478bd9Sstevel@tonic-gate bcopy(p, STRUCT_BUF(oa), STRUCT_SIZE(oa)); 44987c478bd9Sstevel@tonic-gate value_len = k_attrs[i].oa_value_len; 44997c478bd9Sstevel@tonic-gate STRUCT_FSET(oa, oa_type, k_attrs[i].oa_type); 450095014fbbSDan OpenSolaris Anderson STRUCT_FSET(oa, oa_value_len, (ssize_t)value_len); 45017c478bd9Sstevel@tonic-gate valuep = STRUCT_FGETP(oa, oa_value); 450295014fbbSDan OpenSolaris Anderson if ((valuep != NULL) && (value_len != (size_t)-1)) { 45037c478bd9Sstevel@tonic-gate if (copyout(k_attrs[i].oa_value, 45047c478bd9Sstevel@tonic-gate valuep, value_len) != 0) { 45057c478bd9Sstevel@tonic-gate error = EFAULT; 45067c478bd9Sstevel@tonic-gate goto out; 45077c478bd9Sstevel@tonic-gate } 45087c478bd9Sstevel@tonic-gate } 45097c478bd9Sstevel@tonic-gate bcopy(STRUCT_BUF(oa), p, STRUCT_SIZE(oa)); 45107c478bd9Sstevel@tonic-gate p += STRUCT_SIZE(oa); 45117c478bd9Sstevel@tonic-gate } 45127c478bd9Sstevel@tonic-gate if (copyout(u_attrs, out, len)) { 45137c478bd9Sstevel@tonic-gate error = EFAULT; 45147c478bd9Sstevel@tonic-gate } 45157c478bd9Sstevel@tonic-gate out: 45167c478bd9Sstevel@tonic-gate return (error); 45177c478bd9Sstevel@tonic-gate } 45187c478bd9Sstevel@tonic-gate 45197c478bd9Sstevel@tonic-gate 45207c478bd9Sstevel@tonic-gate /* ARGSUSED */ 45217c478bd9Sstevel@tonic-gate static int 45227c478bd9Sstevel@tonic-gate object_create(dev_t dev, caddr_t arg, int mode, int *rval) 45237c478bd9Sstevel@tonic-gate { 45247c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_object_create, object_create); 4525894b2776Smcpowers kcf_provider_desc_t *real_provider = NULL; 45267c478bd9Sstevel@tonic-gate kcf_req_params_t params; 45277c478bd9Sstevel@tonic-gate crypto_object_attribute_t *k_attrs = NULL; 45287c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 45297c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 45307c478bd9Sstevel@tonic-gate crypto_session_data_t *sp = NULL; 45317c478bd9Sstevel@tonic-gate crypto_object_id_t object_handle; 45327c478bd9Sstevel@tonic-gate caddr_t oc_attributes; 45337c478bd9Sstevel@tonic-gate size_t k_attrs_size; 45347c478bd9Sstevel@tonic-gate size_t rctl_bytes = 0; 45352d794da1Skrishna boolean_t rctl_chk = B_FALSE; 45367c478bd9Sstevel@tonic-gate int error = 0; 45377c478bd9Sstevel@tonic-gate int rv; 45387c478bd9Sstevel@tonic-gate uint_t count; 45397c478bd9Sstevel@tonic-gate 45407c478bd9Sstevel@tonic-gate STRUCT_INIT(object_create, mode); 45417c478bd9Sstevel@tonic-gate 45427c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 45437c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "object_create: failed holding minor"); 45447c478bd9Sstevel@tonic-gate return (ENXIO); 45457c478bd9Sstevel@tonic-gate } 45467c478bd9Sstevel@tonic-gate 45477c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(object_create), 45487c478bd9Sstevel@tonic-gate STRUCT_SIZE(object_create)) != 0) { 45497c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 45507c478bd9Sstevel@tonic-gate return (EFAULT); 45517c478bd9Sstevel@tonic-gate } 45527c478bd9Sstevel@tonic-gate 45537c478bd9Sstevel@tonic-gate count = STRUCT_FGET(object_create, oc_count); 45547c478bd9Sstevel@tonic-gate oc_attributes = STRUCT_FGETP(object_create, oc_attributes); 45557c478bd9Sstevel@tonic-gate 45567c478bd9Sstevel@tonic-gate session_id = STRUCT_FGET(object_create, oc_session); 45577c478bd9Sstevel@tonic-gate if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 45587c478bd9Sstevel@tonic-gate goto release_minor; 45597c478bd9Sstevel@tonic-gate } 45602d794da1Skrishna if (!copyin_attributes(mode, sp, count, oc_attributes, &k_attrs, 45612d794da1Skrishna &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 45622d794da1Skrishna &rctl_chk, B_TRUE)) { 45632d794da1Skrishna goto release_minor; 45642d794da1Skrishna } 45657c478bd9Sstevel@tonic-gate 45667c478bd9Sstevel@tonic-gate if ((rv = kcf_get_hardware_provider_nomech( 45677c478bd9Sstevel@tonic-gate CRYPTO_OPS_OFFSET(object_ops), 45689b009fc1SValerie Bubb Fenwick CRYPTO_OBJECT_OFFSET(object_create), sp->sd_provider, 45699b009fc1SValerie Bubb Fenwick &real_provider)) != CRYPTO_SUCCESS) { 45707c478bd9Sstevel@tonic-gate goto release_minor; 45717c478bd9Sstevel@tonic-gate } 45727c478bd9Sstevel@tonic-gate 45737c478bd9Sstevel@tonic-gate KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_CREATE, 45747c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, 0, k_attrs, count, 45757c478bd9Sstevel@tonic-gate &object_handle, 0, NULL, NULL, 0, NULL); 45767c478bd9Sstevel@tonic-gate 45777c478bd9Sstevel@tonic-gate rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 45787c478bd9Sstevel@tonic-gate 45797c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) 45807c478bd9Sstevel@tonic-gate STRUCT_FSET(object_create, oc_handle, object_handle); 45817c478bd9Sstevel@tonic-gate 45827c478bd9Sstevel@tonic-gate release_minor: 45832d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk); 45847c478bd9Sstevel@tonic-gate 45857c478bd9Sstevel@tonic-gate if (k_attrs != NULL) 45867c478bd9Sstevel@tonic-gate kmem_free(k_attrs, k_attrs_size); 45877c478bd9Sstevel@tonic-gate 45887c478bd9Sstevel@tonic-gate if (error != 0) 45897c478bd9Sstevel@tonic-gate goto out; 45907c478bd9Sstevel@tonic-gate 45917c478bd9Sstevel@tonic-gate STRUCT_FSET(object_create, oc_return_value, rv); 45927c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(object_create), arg, 45937c478bd9Sstevel@tonic-gate STRUCT_SIZE(object_create)) != 0) { 45947c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) { 45957c478bd9Sstevel@tonic-gate KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 45967c478bd9Sstevel@tonic-gate KCF_OP_OBJECT_DESTROY, 45977c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, object_handle, 45987c478bd9Sstevel@tonic-gate NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 45997c478bd9Sstevel@tonic-gate 46007c478bd9Sstevel@tonic-gate (void) kcf_submit_request(real_provider, NULL, 46017c478bd9Sstevel@tonic-gate NULL, ¶ms, B_FALSE); 46027c478bd9Sstevel@tonic-gate 46037c478bd9Sstevel@tonic-gate error = EFAULT; 46047c478bd9Sstevel@tonic-gate } 46057c478bd9Sstevel@tonic-gate } 46067c478bd9Sstevel@tonic-gate out: 46077c478bd9Sstevel@tonic-gate CRYPTO_SESSION_RELE(sp); 46087c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 4609894b2776Smcpowers if (real_provider != NULL) 4610894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 46117c478bd9Sstevel@tonic-gate return (error); 46127c478bd9Sstevel@tonic-gate } 46137c478bd9Sstevel@tonic-gate 46147c478bd9Sstevel@tonic-gate /* ARGSUSED */ 46157c478bd9Sstevel@tonic-gate static int 46167c478bd9Sstevel@tonic-gate object_copy(dev_t dev, caddr_t arg, int mode, int *rval) 46177c478bd9Sstevel@tonic-gate { 46187c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_object_copy, object_copy); 4619894b2776Smcpowers kcf_provider_desc_t *real_provider = NULL; 46207c478bd9Sstevel@tonic-gate kcf_req_params_t params; 46217c478bd9Sstevel@tonic-gate crypto_object_attribute_t *k_attrs = NULL; 46227c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 46237c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 46247c478bd9Sstevel@tonic-gate crypto_session_data_t *sp = NULL; 46257c478bd9Sstevel@tonic-gate crypto_object_id_t handle, new_handle; 46267c478bd9Sstevel@tonic-gate caddr_t oc_new_attributes; 46277c478bd9Sstevel@tonic-gate size_t k_attrs_size; 46287c478bd9Sstevel@tonic-gate size_t rctl_bytes = 0; 46292d794da1Skrishna boolean_t rctl_chk = B_FALSE; 46307c478bd9Sstevel@tonic-gate int error = 0; 46317c478bd9Sstevel@tonic-gate int rv; 46327c478bd9Sstevel@tonic-gate uint_t count; 46337c478bd9Sstevel@tonic-gate 46347c478bd9Sstevel@tonic-gate STRUCT_INIT(object_copy, mode); 46357c478bd9Sstevel@tonic-gate 46367c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 46377c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "object_copy: failed holding minor"); 46387c478bd9Sstevel@tonic-gate return (ENXIO); 46397c478bd9Sstevel@tonic-gate } 46407c478bd9Sstevel@tonic-gate 46417c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(object_copy), 46427c478bd9Sstevel@tonic-gate STRUCT_SIZE(object_copy)) != 0) { 46437c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 46447c478bd9Sstevel@tonic-gate return (EFAULT); 46457c478bd9Sstevel@tonic-gate } 46467c478bd9Sstevel@tonic-gate 46477c478bd9Sstevel@tonic-gate count = STRUCT_FGET(object_copy, oc_count); 46487c478bd9Sstevel@tonic-gate oc_new_attributes = STRUCT_FGETP(object_copy, oc_new_attributes); 46497c478bd9Sstevel@tonic-gate 46507c478bd9Sstevel@tonic-gate session_id = STRUCT_FGET(object_copy, oc_session); 46517c478bd9Sstevel@tonic-gate 46527c478bd9Sstevel@tonic-gate if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 46537c478bd9Sstevel@tonic-gate goto release_minor; 46547c478bd9Sstevel@tonic-gate } 46552d794da1Skrishna if (!copyin_attributes(mode, sp, count, oc_new_attributes, &k_attrs, 46562d794da1Skrishna &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 46572d794da1Skrishna &rctl_chk, B_TRUE)) { 46582d794da1Skrishna goto release_minor; 46592d794da1Skrishna } 46607c478bd9Sstevel@tonic-gate 46617c478bd9Sstevel@tonic-gate if ((rv = kcf_get_hardware_provider_nomech( 46627c478bd9Sstevel@tonic-gate CRYPTO_OPS_OFFSET(object_ops), 46639b009fc1SValerie Bubb Fenwick CRYPTO_OBJECT_OFFSET(object_copy), sp->sd_provider, 46649b009fc1SValerie Bubb Fenwick &real_provider)) != CRYPTO_SUCCESS) { 46657c478bd9Sstevel@tonic-gate goto release_minor; 46667c478bd9Sstevel@tonic-gate } 46677c478bd9Sstevel@tonic-gate 46687c478bd9Sstevel@tonic-gate handle = STRUCT_FGET(object_copy, oc_handle); 46697c478bd9Sstevel@tonic-gate KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_COPY, 46707c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, handle, k_attrs, count, 46717c478bd9Sstevel@tonic-gate &new_handle, 0, NULL, NULL, 0, NULL); 46727c478bd9Sstevel@tonic-gate 46737c478bd9Sstevel@tonic-gate rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 46747c478bd9Sstevel@tonic-gate 46757c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) 46767c478bd9Sstevel@tonic-gate STRUCT_FSET(object_copy, oc_new_handle, new_handle); 46777c478bd9Sstevel@tonic-gate 46787c478bd9Sstevel@tonic-gate release_minor: 46792d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk); 46807c478bd9Sstevel@tonic-gate 46817c478bd9Sstevel@tonic-gate if (k_attrs != NULL) 46827c478bd9Sstevel@tonic-gate kmem_free(k_attrs, k_attrs_size); 46837c478bd9Sstevel@tonic-gate 46847c478bd9Sstevel@tonic-gate if (error != 0) 46857c478bd9Sstevel@tonic-gate goto out; 46867c478bd9Sstevel@tonic-gate 46877c478bd9Sstevel@tonic-gate STRUCT_FSET(object_copy, oc_return_value, rv); 46887c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(object_copy), arg, 46897c478bd9Sstevel@tonic-gate STRUCT_SIZE(object_copy)) != 0) { 46907c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) { 46917c478bd9Sstevel@tonic-gate KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 46927c478bd9Sstevel@tonic-gate KCF_OP_OBJECT_DESTROY, 46937c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, new_handle, 46947c478bd9Sstevel@tonic-gate NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 46957c478bd9Sstevel@tonic-gate 46967c478bd9Sstevel@tonic-gate (void) kcf_submit_request(real_provider, NULL, 46977c478bd9Sstevel@tonic-gate NULL, ¶ms, B_FALSE); 46987c478bd9Sstevel@tonic-gate 46997c478bd9Sstevel@tonic-gate error = EFAULT; 47007c478bd9Sstevel@tonic-gate } 47017c478bd9Sstevel@tonic-gate } 47027c478bd9Sstevel@tonic-gate out: 47037c478bd9Sstevel@tonic-gate CRYPTO_SESSION_RELE(sp); 47047c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 4705894b2776Smcpowers if (real_provider != NULL) 4706894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 47077c478bd9Sstevel@tonic-gate return (error); 47087c478bd9Sstevel@tonic-gate } 47097c478bd9Sstevel@tonic-gate 47107c478bd9Sstevel@tonic-gate /* ARGSUSED */ 47117c478bd9Sstevel@tonic-gate static int 47127c478bd9Sstevel@tonic-gate object_destroy(dev_t dev, caddr_t arg, int mode, int *rval) 47137c478bd9Sstevel@tonic-gate { 47147c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_object_destroy, object_destroy); 47157c478bd9Sstevel@tonic-gate kcf_provider_desc_t *real_provider; 47167c478bd9Sstevel@tonic-gate kcf_req_params_t params; 47177c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 47187c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 47197c478bd9Sstevel@tonic-gate crypto_session_data_t *sp; 47207c478bd9Sstevel@tonic-gate crypto_object_id_t handle; 47217c478bd9Sstevel@tonic-gate int error = 0; 47227c478bd9Sstevel@tonic-gate int rv; 47237c478bd9Sstevel@tonic-gate 47247c478bd9Sstevel@tonic-gate STRUCT_INIT(object_destroy, mode); 47257c478bd9Sstevel@tonic-gate 47267c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 47277c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "object_destroy: failed holding minor"); 47287c478bd9Sstevel@tonic-gate return (ENXIO); 47297c478bd9Sstevel@tonic-gate } 47307c478bd9Sstevel@tonic-gate 47317c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(object_destroy), 47327c478bd9Sstevel@tonic-gate STRUCT_SIZE(object_destroy)) != 0) { 47337c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 47347c478bd9Sstevel@tonic-gate return (EFAULT); 47357c478bd9Sstevel@tonic-gate } 47367c478bd9Sstevel@tonic-gate 47377c478bd9Sstevel@tonic-gate session_id = STRUCT_FGET(object_destroy, od_session); 47387c478bd9Sstevel@tonic-gate 47397c478bd9Sstevel@tonic-gate if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 47407c478bd9Sstevel@tonic-gate goto release_minor; 47417c478bd9Sstevel@tonic-gate } 47427c478bd9Sstevel@tonic-gate 47437c478bd9Sstevel@tonic-gate if ((rv = kcf_get_hardware_provider_nomech( 47447c478bd9Sstevel@tonic-gate CRYPTO_OPS_OFFSET(object_ops), 47459b009fc1SValerie Bubb Fenwick CRYPTO_OBJECT_OFFSET(object_destroy), sp->sd_provider, 47469b009fc1SValerie Bubb Fenwick &real_provider)) != CRYPTO_SUCCESS) { 47477c478bd9Sstevel@tonic-gate goto out; 47487c478bd9Sstevel@tonic-gate } 47497c478bd9Sstevel@tonic-gate 47507c478bd9Sstevel@tonic-gate handle = STRUCT_FGET(object_destroy, od_handle); 47517c478bd9Sstevel@tonic-gate KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_DESTROY, 47527c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, handle, NULL, 0, NULL, 0, 47537c478bd9Sstevel@tonic-gate NULL, NULL, 0, NULL); 47547c478bd9Sstevel@tonic-gate 47557c478bd9Sstevel@tonic-gate rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4756894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 47577c478bd9Sstevel@tonic-gate 47587c478bd9Sstevel@tonic-gate out: 47597c478bd9Sstevel@tonic-gate CRYPTO_SESSION_RELE(sp); 47607c478bd9Sstevel@tonic-gate 47617c478bd9Sstevel@tonic-gate release_minor: 47627c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 47637c478bd9Sstevel@tonic-gate 47647c478bd9Sstevel@tonic-gate if (error != 0) 47657c478bd9Sstevel@tonic-gate return (error); 47667c478bd9Sstevel@tonic-gate 47677c478bd9Sstevel@tonic-gate STRUCT_FSET(object_destroy, od_return_value, rv); 47687c478bd9Sstevel@tonic-gate 47697c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(object_destroy), arg, 47707c478bd9Sstevel@tonic-gate STRUCT_SIZE(object_destroy)) != 0) { 47717c478bd9Sstevel@tonic-gate return (EFAULT); 47727c478bd9Sstevel@tonic-gate } 47737c478bd9Sstevel@tonic-gate return (0); 47747c478bd9Sstevel@tonic-gate } 47757c478bd9Sstevel@tonic-gate 47767c478bd9Sstevel@tonic-gate /* ARGSUSED */ 47777c478bd9Sstevel@tonic-gate static int 47787c478bd9Sstevel@tonic-gate object_get_attribute_value(dev_t dev, caddr_t arg, int mode, int *rval) 47797c478bd9Sstevel@tonic-gate { 47807c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_object_get_attribute_value, get_attribute_value); 478195014fbbSDan OpenSolaris Anderson #ifdef _LP64 478295014fbbSDan OpenSolaris Anderson STRUCT_DECL(crypto_object_attribute, oa); 478395014fbbSDan OpenSolaris Anderson #else 47847c478bd9Sstevel@tonic-gate /* LINTED E_FUNC_SET_NOT_USED */ 47857c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_object_attribute, oa); 478695014fbbSDan OpenSolaris Anderson #endif 47877c478bd9Sstevel@tonic-gate kcf_provider_desc_t *real_provider; 47887c478bd9Sstevel@tonic-gate kcf_req_params_t params; 47897c478bd9Sstevel@tonic-gate crypto_object_attribute_t *k_attrs = NULL; 47907c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 47917c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 47922d794da1Skrishna crypto_session_data_t *sp = NULL; 47937c478bd9Sstevel@tonic-gate crypto_object_id_t handle; 47947c478bd9Sstevel@tonic-gate caddr_t og_attributes; 4795fdd76261SMark Powers caddr_t u_attrs = NULL; 47967c478bd9Sstevel@tonic-gate size_t k_attrs_size; 47977c478bd9Sstevel@tonic-gate size_t rctl_bytes = 0; 47982d794da1Skrishna boolean_t rctl_chk = B_FALSE; 47997c478bd9Sstevel@tonic-gate int error = 0; 48007c478bd9Sstevel@tonic-gate int rv; 48017c478bd9Sstevel@tonic-gate uint_t count; 48027c478bd9Sstevel@tonic-gate 48037c478bd9Sstevel@tonic-gate STRUCT_INIT(get_attribute_value, mode); 48047c478bd9Sstevel@tonic-gate STRUCT_INIT(oa, mode); 48057c478bd9Sstevel@tonic-gate 48067c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 48077c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 48087c478bd9Sstevel@tonic-gate "object_get_attribute_value: failed holding minor"); 48097c478bd9Sstevel@tonic-gate return (ENXIO); 48107c478bd9Sstevel@tonic-gate } 48117c478bd9Sstevel@tonic-gate 48127c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(get_attribute_value), 48137c478bd9Sstevel@tonic-gate STRUCT_SIZE(get_attribute_value)) != 0) { 48147c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 48157c478bd9Sstevel@tonic-gate return (EFAULT); 48167c478bd9Sstevel@tonic-gate } 48177c478bd9Sstevel@tonic-gate 48187c478bd9Sstevel@tonic-gate count = STRUCT_FGET(get_attribute_value, og_count); 48197c478bd9Sstevel@tonic-gate og_attributes = STRUCT_FGETP(get_attribute_value, og_attributes); 48207c478bd9Sstevel@tonic-gate 48217c478bd9Sstevel@tonic-gate session_id = STRUCT_FGET(get_attribute_value, og_session); 48227c478bd9Sstevel@tonic-gate 48237c478bd9Sstevel@tonic-gate if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 48247c478bd9Sstevel@tonic-gate goto release_minor; 48257c478bd9Sstevel@tonic-gate } 48262d794da1Skrishna if (!copyin_attributes(mode, sp, count, og_attributes, &k_attrs, 48272d794da1Skrishna &k_attrs_size, &u_attrs, &rv, &error, &rctl_bytes, 48282d794da1Skrishna &rctl_chk, B_FALSE)) { 48292d794da1Skrishna goto release_minor; 48302d794da1Skrishna } 48317c478bd9Sstevel@tonic-gate 48327c478bd9Sstevel@tonic-gate if ((rv = kcf_get_hardware_provider_nomech( 48337c478bd9Sstevel@tonic-gate CRYPTO_OPS_OFFSET(object_ops), 48347c478bd9Sstevel@tonic-gate CRYPTO_OBJECT_OFFSET(object_get_attribute_value), 48359b009fc1SValerie Bubb Fenwick sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 48367c478bd9Sstevel@tonic-gate goto out; 48377c478bd9Sstevel@tonic-gate } 48387c478bd9Sstevel@tonic-gate 48397c478bd9Sstevel@tonic-gate handle = STRUCT_FGET(get_attribute_value, og_handle); 48407c478bd9Sstevel@tonic-gate KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_GET_ATTRIBUTE_VALUE, 48417c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, handle, k_attrs, count, NULL, 48427c478bd9Sstevel@tonic-gate 0, NULL, NULL, 0, NULL); 48437c478bd9Sstevel@tonic-gate 48447c478bd9Sstevel@tonic-gate rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4845894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 48467c478bd9Sstevel@tonic-gate 48477c478bd9Sstevel@tonic-gate out: 48487c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS || rv == CRYPTO_ATTRIBUTE_SENSITIVE || 48497c478bd9Sstevel@tonic-gate rv == CRYPTO_ATTRIBUTE_TYPE_INVALID || 48507c478bd9Sstevel@tonic-gate rv == CRYPTO_BUFFER_TOO_SMALL) { 48517c478bd9Sstevel@tonic-gate error = copyout_attributes(mode, 48527c478bd9Sstevel@tonic-gate STRUCT_FGETP(get_attribute_value, og_attributes), 48537c478bd9Sstevel@tonic-gate count, k_attrs, u_attrs); 48547c478bd9Sstevel@tonic-gate } 48557c478bd9Sstevel@tonic-gate 48567c478bd9Sstevel@tonic-gate release_minor: 48572d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk); 48582d794da1Skrishna CRYPTO_SESSION_RELE(sp); 48597c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 48607c478bd9Sstevel@tonic-gate 48617c478bd9Sstevel@tonic-gate if (k_attrs != NULL) 48627c478bd9Sstevel@tonic-gate kmem_free(k_attrs, k_attrs_size); 48637c478bd9Sstevel@tonic-gate 48647c478bd9Sstevel@tonic-gate if (u_attrs != NULL) 48657c478bd9Sstevel@tonic-gate kmem_free(u_attrs, count * STRUCT_SIZE(oa)); 48667c478bd9Sstevel@tonic-gate 48677c478bd9Sstevel@tonic-gate if (error != 0) 48687c478bd9Sstevel@tonic-gate return (error); 48697c478bd9Sstevel@tonic-gate 48707c478bd9Sstevel@tonic-gate STRUCT_FSET(get_attribute_value, og_return_value, rv); 48717c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(get_attribute_value), arg, 48727c478bd9Sstevel@tonic-gate STRUCT_SIZE(get_attribute_value)) != 0) { 48737c478bd9Sstevel@tonic-gate return (EFAULT); 48747c478bd9Sstevel@tonic-gate } 48757c478bd9Sstevel@tonic-gate return (0); 48767c478bd9Sstevel@tonic-gate } 48777c478bd9Sstevel@tonic-gate 48787c478bd9Sstevel@tonic-gate /* ARGSUSED */ 48797c478bd9Sstevel@tonic-gate static int 48807c478bd9Sstevel@tonic-gate object_get_size(dev_t dev, caddr_t arg, int mode, int *rval) 48817c478bd9Sstevel@tonic-gate { 48827c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_object_get_size, object_get_size); 48837c478bd9Sstevel@tonic-gate kcf_provider_desc_t *real_provider; 48847c478bd9Sstevel@tonic-gate kcf_req_params_t params; 48857c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 48867c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 48872d794da1Skrishna crypto_session_data_t *sp = NULL; 48887c478bd9Sstevel@tonic-gate crypto_object_id_t handle; 48897c478bd9Sstevel@tonic-gate size_t size; 48907c478bd9Sstevel@tonic-gate int error = 0; 48917c478bd9Sstevel@tonic-gate int rv; 48927c478bd9Sstevel@tonic-gate 48937c478bd9Sstevel@tonic-gate STRUCT_INIT(object_get_size, mode); 48947c478bd9Sstevel@tonic-gate 48957c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 48967c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "object_get_size: failed holding minor"); 48977c478bd9Sstevel@tonic-gate return (ENXIO); 48987c478bd9Sstevel@tonic-gate } 48997c478bd9Sstevel@tonic-gate 49007c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(object_get_size), 49017c478bd9Sstevel@tonic-gate STRUCT_SIZE(object_get_size)) != 0) { 49027c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 49037c478bd9Sstevel@tonic-gate return (EFAULT); 49047c478bd9Sstevel@tonic-gate } 49057c478bd9Sstevel@tonic-gate 49067c478bd9Sstevel@tonic-gate session_id = STRUCT_FGET(object_get_size, gs_session); 49077c478bd9Sstevel@tonic-gate 49087c478bd9Sstevel@tonic-gate if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 49097c478bd9Sstevel@tonic-gate goto release_minor; 49107c478bd9Sstevel@tonic-gate } 49117c478bd9Sstevel@tonic-gate 49127c478bd9Sstevel@tonic-gate if ((rv = kcf_get_hardware_provider_nomech( 49137c478bd9Sstevel@tonic-gate CRYPTO_OPS_OFFSET(object_ops), 49149b009fc1SValerie Bubb Fenwick CRYPTO_OBJECT_OFFSET(object_get_size), 49157c478bd9Sstevel@tonic-gate sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 49162d794da1Skrishna goto release_minor; 49177c478bd9Sstevel@tonic-gate } 49187c478bd9Sstevel@tonic-gate 49197c478bd9Sstevel@tonic-gate handle = STRUCT_FGET(object_get_size, gs_handle); 49207c478bd9Sstevel@tonic-gate KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_GET_SIZE, 49217c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, handle, NULL, 0, NULL, &size, 49227c478bd9Sstevel@tonic-gate NULL, NULL, 0, NULL); 49237c478bd9Sstevel@tonic-gate 49247c478bd9Sstevel@tonic-gate rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 4925894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 49267c478bd9Sstevel@tonic-gate 49277c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) { 492895014fbbSDan OpenSolaris Anderson STRUCT_FSET(object_get_size, gs_size, (ulong_t)size); 49297c478bd9Sstevel@tonic-gate } 49302d794da1Skrishna 49317c478bd9Sstevel@tonic-gate release_minor: 49327c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 49332d794da1Skrishna CRYPTO_SESSION_RELE(sp); 49347c478bd9Sstevel@tonic-gate 49357c478bd9Sstevel@tonic-gate if (error != 0) 49367c478bd9Sstevel@tonic-gate return (error); 49377c478bd9Sstevel@tonic-gate 49387c478bd9Sstevel@tonic-gate STRUCT_FSET(object_get_size, gs_return_value, rv); 49397c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(object_get_size), arg, 49407c478bd9Sstevel@tonic-gate STRUCT_SIZE(object_get_size)) != 0) { 49417c478bd9Sstevel@tonic-gate return (EFAULT); 49427c478bd9Sstevel@tonic-gate } 49437c478bd9Sstevel@tonic-gate return (0); 49447c478bd9Sstevel@tonic-gate } 49457c478bd9Sstevel@tonic-gate 49467c478bd9Sstevel@tonic-gate /* ARGSUSED */ 49477c478bd9Sstevel@tonic-gate static int 49487c478bd9Sstevel@tonic-gate object_set_attribute_value(dev_t dev, caddr_t arg, int mode, int *rval) 49497c478bd9Sstevel@tonic-gate { 49507c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_object_set_attribute_value, set_attribute_value); 49517c478bd9Sstevel@tonic-gate kcf_provider_desc_t *real_provider; 49527c478bd9Sstevel@tonic-gate kcf_req_params_t params; 49537c478bd9Sstevel@tonic-gate crypto_object_attribute_t *k_attrs = NULL; 49547c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 49557c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 49562d794da1Skrishna crypto_session_data_t *sp = NULL; 49577c478bd9Sstevel@tonic-gate crypto_object_id_t object_handle; 49587c478bd9Sstevel@tonic-gate caddr_t sa_attributes; 49597c478bd9Sstevel@tonic-gate size_t k_attrs_size; 49607c478bd9Sstevel@tonic-gate size_t rctl_bytes = 0; 49612d794da1Skrishna boolean_t rctl_chk = B_FALSE; 49627c478bd9Sstevel@tonic-gate int error = 0; 49637c478bd9Sstevel@tonic-gate int rv; 49647c478bd9Sstevel@tonic-gate uint_t count; 49657c478bd9Sstevel@tonic-gate 49667c478bd9Sstevel@tonic-gate STRUCT_INIT(set_attribute_value, mode); 49677c478bd9Sstevel@tonic-gate 49687c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 49697c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 49707c478bd9Sstevel@tonic-gate "object_set_attribute_value: failed holding minor"); 49717c478bd9Sstevel@tonic-gate return (ENXIO); 49727c478bd9Sstevel@tonic-gate } 49737c478bd9Sstevel@tonic-gate 49747c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(set_attribute_value), 49757c478bd9Sstevel@tonic-gate STRUCT_SIZE(set_attribute_value)) != 0) { 49767c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 49777c478bd9Sstevel@tonic-gate return (EFAULT); 49787c478bd9Sstevel@tonic-gate } 49797c478bd9Sstevel@tonic-gate 49807c478bd9Sstevel@tonic-gate count = STRUCT_FGET(set_attribute_value, sa_count); 49817c478bd9Sstevel@tonic-gate sa_attributes = STRUCT_FGETP(set_attribute_value, sa_attributes); 49827c478bd9Sstevel@tonic-gate 49837c478bd9Sstevel@tonic-gate session_id = STRUCT_FGET(set_attribute_value, sa_session); 49847c478bd9Sstevel@tonic-gate 49857c478bd9Sstevel@tonic-gate if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 49867c478bd9Sstevel@tonic-gate goto release_minor; 49877c478bd9Sstevel@tonic-gate } 49882d794da1Skrishna if (!copyin_attributes(mode, sp, count, sa_attributes, &k_attrs, 49892d794da1Skrishna &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 49902d794da1Skrishna &rctl_chk, B_TRUE)) { 49912d794da1Skrishna goto release_minor; 49922d794da1Skrishna } 49937c478bd9Sstevel@tonic-gate 49947c478bd9Sstevel@tonic-gate if ((rv = kcf_get_hardware_provider_nomech( 49957c478bd9Sstevel@tonic-gate CRYPTO_OPS_OFFSET(object_ops), 49967c478bd9Sstevel@tonic-gate CRYPTO_OBJECT_OFFSET(object_set_attribute_value), 49979b009fc1SValerie Bubb Fenwick sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 49982d794da1Skrishna goto release_minor; 49997c478bd9Sstevel@tonic-gate } 50007c478bd9Sstevel@tonic-gate 50017c478bd9Sstevel@tonic-gate object_handle = STRUCT_FGET(set_attribute_value, sa_handle); 50027c478bd9Sstevel@tonic-gate KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_SET_ATTRIBUTE_VALUE, 50037c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, object_handle, k_attrs, count, 50047c478bd9Sstevel@tonic-gate NULL, 0, NULL, NULL, 0, NULL); 50057c478bd9Sstevel@tonic-gate 50067c478bd9Sstevel@tonic-gate rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5007894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 50087c478bd9Sstevel@tonic-gate 50097c478bd9Sstevel@tonic-gate release_minor: 50102d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk); 50112d794da1Skrishna CRYPTO_SESSION_RELE(sp); 50127c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 50137c478bd9Sstevel@tonic-gate 50147c478bd9Sstevel@tonic-gate if (k_attrs != NULL) 50157c478bd9Sstevel@tonic-gate kmem_free(k_attrs, k_attrs_size); 50167c478bd9Sstevel@tonic-gate 50177c478bd9Sstevel@tonic-gate if (error != 0) 50187c478bd9Sstevel@tonic-gate return (error); 50197c478bd9Sstevel@tonic-gate 50207c478bd9Sstevel@tonic-gate STRUCT_FSET(set_attribute_value, sa_return_value, rv); 50217c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(set_attribute_value), arg, 50227c478bd9Sstevel@tonic-gate STRUCT_SIZE(set_attribute_value)) != 0) { 50237c478bd9Sstevel@tonic-gate return (EFAULT); 50247c478bd9Sstevel@tonic-gate } 50257c478bd9Sstevel@tonic-gate return (0); 50267c478bd9Sstevel@tonic-gate } 50277c478bd9Sstevel@tonic-gate 50287c478bd9Sstevel@tonic-gate /* ARGSUSED */ 50297c478bd9Sstevel@tonic-gate static int 50307c478bd9Sstevel@tonic-gate object_find_init(dev_t dev, caddr_t arg, int mode, int *rval) 50317c478bd9Sstevel@tonic-gate { 50327c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_object_find_init, find_init); 5033894b2776Smcpowers kcf_provider_desc_t *real_provider = NULL; 50347c478bd9Sstevel@tonic-gate kcf_req_params_t params; 50357c478bd9Sstevel@tonic-gate crypto_object_attribute_t *k_attrs = NULL; 50367c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 50377c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 50382d794da1Skrishna crypto_session_data_t *sp = NULL; 50397c478bd9Sstevel@tonic-gate caddr_t attributes; 50407c478bd9Sstevel@tonic-gate size_t k_attrs_size; 50417c478bd9Sstevel@tonic-gate size_t rctl_bytes = 0; 50422d794da1Skrishna boolean_t rctl_chk = B_FALSE; 50437c478bd9Sstevel@tonic-gate int error = 0; 50447c478bd9Sstevel@tonic-gate int rv; 50457c478bd9Sstevel@tonic-gate uint_t count; 50467c478bd9Sstevel@tonic-gate void *cookie; 50477c478bd9Sstevel@tonic-gate 50487c478bd9Sstevel@tonic-gate STRUCT_INIT(find_init, mode); 50497c478bd9Sstevel@tonic-gate 50507c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 50517c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "object_find_init: failed holding minor"); 50527c478bd9Sstevel@tonic-gate return (ENXIO); 50537c478bd9Sstevel@tonic-gate } 50547c478bd9Sstevel@tonic-gate 50557c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(find_init), STRUCT_SIZE(find_init)) != 0) { 50567c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 50577c478bd9Sstevel@tonic-gate return (EFAULT); 50587c478bd9Sstevel@tonic-gate } 50597c478bd9Sstevel@tonic-gate 50607c478bd9Sstevel@tonic-gate count = STRUCT_FGET(find_init, fi_count); 50617c478bd9Sstevel@tonic-gate attributes = STRUCT_FGETP(find_init, fi_attributes); 50627c478bd9Sstevel@tonic-gate 50637c478bd9Sstevel@tonic-gate session_id = STRUCT_FGET(find_init, fi_session); 50647c478bd9Sstevel@tonic-gate 50657c478bd9Sstevel@tonic-gate if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 50667c478bd9Sstevel@tonic-gate goto release_minor; 50677c478bd9Sstevel@tonic-gate } 50682d794da1Skrishna if (!copyin_attributes(mode, sp, count, attributes, &k_attrs, 50692d794da1Skrishna &k_attrs_size, NULL, &rv, &error, &rctl_bytes, 50702d794da1Skrishna &rctl_chk, B_TRUE)) { 50712d794da1Skrishna goto release_minor; 50722d794da1Skrishna } 50737c478bd9Sstevel@tonic-gate 50747c478bd9Sstevel@tonic-gate if ((rv = kcf_get_hardware_provider_nomech( 50757c478bd9Sstevel@tonic-gate CRYPTO_OPS_OFFSET(object_ops), 50769b009fc1SValerie Bubb Fenwick CRYPTO_OBJECT_OFFSET(object_find_init), 50777c478bd9Sstevel@tonic-gate sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 50782d794da1Skrishna goto release_minor; 50797c478bd9Sstevel@tonic-gate } 50807c478bd9Sstevel@tonic-gate 50817c478bd9Sstevel@tonic-gate /* check for an active find */ 50827c478bd9Sstevel@tonic-gate if (sp->sd_find_init_cookie != NULL) { 50837c478bd9Sstevel@tonic-gate rv = CRYPTO_OPERATION_IS_ACTIVE; 50847c478bd9Sstevel@tonic-gate goto release_minor; 50857c478bd9Sstevel@tonic-gate } 50867c478bd9Sstevel@tonic-gate 50877c478bd9Sstevel@tonic-gate KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_FIND_INIT, 50887c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, 0, k_attrs, count, NULL, 0, 50897c478bd9Sstevel@tonic-gate &cookie, NULL, 0, NULL); 50907c478bd9Sstevel@tonic-gate 50917c478bd9Sstevel@tonic-gate rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 50927c478bd9Sstevel@tonic-gate 50937c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) { 50947c478bd9Sstevel@tonic-gate /* 50957c478bd9Sstevel@tonic-gate * The cookie is allocated by a provider at the start of an 50967c478bd9Sstevel@tonic-gate * object search. It is freed when the search is terminated 50977c478bd9Sstevel@tonic-gate * by a final operation, or when the session is closed. 50987c478bd9Sstevel@tonic-gate * It contains state information about which object handles 50997c478bd9Sstevel@tonic-gate * have been returned to the caller. 51007c478bd9Sstevel@tonic-gate */ 51017c478bd9Sstevel@tonic-gate sp->sd_find_init_cookie = cookie; 51027c478bd9Sstevel@tonic-gate } 51037c478bd9Sstevel@tonic-gate 51047c478bd9Sstevel@tonic-gate release_minor: 51052d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk); 51062d794da1Skrishna CRYPTO_SESSION_RELE(sp); 51077c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 51087c478bd9Sstevel@tonic-gate 5109894b2776Smcpowers if (real_provider != NULL) 5110894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 5111894b2776Smcpowers 51127c478bd9Sstevel@tonic-gate if (k_attrs != NULL) 51137c478bd9Sstevel@tonic-gate kmem_free(k_attrs, k_attrs_size); 51147c478bd9Sstevel@tonic-gate 51157c478bd9Sstevel@tonic-gate if (error != 0) 51167c478bd9Sstevel@tonic-gate return (error); 51177c478bd9Sstevel@tonic-gate 51187c478bd9Sstevel@tonic-gate STRUCT_FSET(find_init, fi_return_value, rv); 51197c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(find_init), arg, STRUCT_SIZE(find_init)) != 0) { 51207c478bd9Sstevel@tonic-gate return (EFAULT); 51217c478bd9Sstevel@tonic-gate } 51227c478bd9Sstevel@tonic-gate return (0); 51237c478bd9Sstevel@tonic-gate } 51247c478bd9Sstevel@tonic-gate 51257c478bd9Sstevel@tonic-gate /* ARGSUSED */ 51267c478bd9Sstevel@tonic-gate static int 51277c478bd9Sstevel@tonic-gate object_find_update(dev_t dev, caddr_t arg, int mode, int *rval) 51287c478bd9Sstevel@tonic-gate { 51297c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_object_find_update, find_update); 51307c478bd9Sstevel@tonic-gate kcf_provider_desc_t *real_provider; 51317c478bd9Sstevel@tonic-gate kcf_req_params_t params; 51327c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 51332d794da1Skrishna crypto_session_data_t *sp = NULL; 51347c478bd9Sstevel@tonic-gate crypto_object_id_t *buffer = NULL; 51357c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 51367c478bd9Sstevel@tonic-gate size_t len, rctl_bytes = 0; 51377c478bd9Sstevel@tonic-gate uint_t count, max_count; 51387c478bd9Sstevel@tonic-gate int rv, error = 0; 51392d794da1Skrishna boolean_t rctl_chk = B_FALSE; 51407c478bd9Sstevel@tonic-gate 51417c478bd9Sstevel@tonic-gate STRUCT_INIT(find_update, mode); 51427c478bd9Sstevel@tonic-gate 51437c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 51447c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "object_find_update: failed holding minor"); 51457c478bd9Sstevel@tonic-gate return (ENXIO); 51467c478bd9Sstevel@tonic-gate } 51477c478bd9Sstevel@tonic-gate 51487c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(find_update), 51497c478bd9Sstevel@tonic-gate STRUCT_SIZE(find_update)) != 0) { 51507c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 51517c478bd9Sstevel@tonic-gate return (EFAULT); 51527c478bd9Sstevel@tonic-gate } 51537c478bd9Sstevel@tonic-gate 51547c478bd9Sstevel@tonic-gate max_count = STRUCT_FGET(find_update, fu_max_count); 51557c478bd9Sstevel@tonic-gate if (max_count > CRYPTO_MAX_FIND_COUNT) { 51567c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "object_find_update: count greater than %d, " 51577c478bd9Sstevel@tonic-gate "pid = %d", CRYPTO_MAX_FIND_COUNT, curproc->p_pid); 51587c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 51597c478bd9Sstevel@tonic-gate goto release_minor; 51607c478bd9Sstevel@tonic-gate } 51617c478bd9Sstevel@tonic-gate len = max_count * sizeof (crypto_object_id_t); 51627c478bd9Sstevel@tonic-gate session_id = STRUCT_FGET(find_update, fu_session); 51637c478bd9Sstevel@tonic-gate 51647c478bd9Sstevel@tonic-gate if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 51657c478bd9Sstevel@tonic-gate goto release_minor; 51667c478bd9Sstevel@tonic-gate } 51672d794da1Skrishna if ((rv = CRYPTO_BUFFER_CHECK(sp, len, rctl_chk)) != 51682d794da1Skrishna CRYPTO_SUCCESS) { 51692d794da1Skrishna goto release_minor; 51702d794da1Skrishna } 51712d794da1Skrishna rctl_bytes = len; 51722d794da1Skrishna buffer = kmem_alloc(len, KM_SLEEP); 51737c478bd9Sstevel@tonic-gate 51747c478bd9Sstevel@tonic-gate if ((rv = kcf_get_hardware_provider_nomech( 51757c478bd9Sstevel@tonic-gate CRYPTO_OPS_OFFSET(object_ops), 51769b009fc1SValerie Bubb Fenwick CRYPTO_OBJECT_OFFSET(object_find), sp->sd_provider, 51779b009fc1SValerie Bubb Fenwick &real_provider)) != CRYPTO_SUCCESS) { 51782d794da1Skrishna goto release_minor; 51797c478bd9Sstevel@tonic-gate } 51807c478bd9Sstevel@tonic-gate 51817c478bd9Sstevel@tonic-gate KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_FIND, 51827c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, 0, NULL, 0, buffer, 0, 51837c478bd9Sstevel@tonic-gate NULL, sp->sd_find_init_cookie, max_count, &count); 51847c478bd9Sstevel@tonic-gate 51857c478bd9Sstevel@tonic-gate rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5186894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 51877c478bd9Sstevel@tonic-gate 51887c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) { 51897c478bd9Sstevel@tonic-gate if (count > max_count) { 51907c478bd9Sstevel@tonic-gate /* bad bad provider */ 51917c478bd9Sstevel@tonic-gate rv = CRYPTO_FAILED; 51927c478bd9Sstevel@tonic-gate goto release_minor; 51937c478bd9Sstevel@tonic-gate } 51947c478bd9Sstevel@tonic-gate if (count != 0) { 51957c478bd9Sstevel@tonic-gate /* copyout handles */ 51967c478bd9Sstevel@tonic-gate if (copyout(buffer, 51977c478bd9Sstevel@tonic-gate STRUCT_FGETP(find_update, fu_handles), 51987c478bd9Sstevel@tonic-gate count * sizeof (crypto_object_id_t)) != 0) { 51997c478bd9Sstevel@tonic-gate error = EFAULT; 52007c478bd9Sstevel@tonic-gate } 52017c478bd9Sstevel@tonic-gate } 52027c478bd9Sstevel@tonic-gate STRUCT_FSET(find_update, fu_count, count); 52037c478bd9Sstevel@tonic-gate } 52047c478bd9Sstevel@tonic-gate 52057c478bd9Sstevel@tonic-gate release_minor: 52062d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk); 52072d794da1Skrishna CRYPTO_SESSION_RELE(sp); 52087c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 52097c478bd9Sstevel@tonic-gate 52107c478bd9Sstevel@tonic-gate if (buffer != NULL) 52117c478bd9Sstevel@tonic-gate kmem_free(buffer, len); 52127c478bd9Sstevel@tonic-gate 52137c478bd9Sstevel@tonic-gate if (error != 0) 52147c478bd9Sstevel@tonic-gate return (error); 52157c478bd9Sstevel@tonic-gate 52167c478bd9Sstevel@tonic-gate STRUCT_FSET(find_update, fu_return_value, rv); 52177c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(find_update), arg, 52187c478bd9Sstevel@tonic-gate STRUCT_SIZE(find_update)) != 0) { 52197c478bd9Sstevel@tonic-gate return (EFAULT); 52207c478bd9Sstevel@tonic-gate } 52217c478bd9Sstevel@tonic-gate 52227c478bd9Sstevel@tonic-gate return (0); 52237c478bd9Sstevel@tonic-gate } 52247c478bd9Sstevel@tonic-gate 52257c478bd9Sstevel@tonic-gate /* 52267c478bd9Sstevel@tonic-gate * Free provider-allocated storage used for find object searches. 52277c478bd9Sstevel@tonic-gate */ 52287c478bd9Sstevel@tonic-gate static int 52297c478bd9Sstevel@tonic-gate crypto_free_find_ctx(crypto_session_data_t *sp) 52307c478bd9Sstevel@tonic-gate { 52317c478bd9Sstevel@tonic-gate kcf_provider_desc_t *real_provider; 52327c478bd9Sstevel@tonic-gate kcf_req_params_t params; 52337c478bd9Sstevel@tonic-gate int rv; 52347c478bd9Sstevel@tonic-gate 52357c478bd9Sstevel@tonic-gate if ((rv = kcf_get_hardware_provider_nomech( 52367c478bd9Sstevel@tonic-gate CRYPTO_OPS_OFFSET(object_ops), 52379b009fc1SValerie Bubb Fenwick CRYPTO_OBJECT_OFFSET(object_find_final), 52387c478bd9Sstevel@tonic-gate sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) { 52397c478bd9Sstevel@tonic-gate return (rv); 52407c478bd9Sstevel@tonic-gate } 52417c478bd9Sstevel@tonic-gate 52427c478bd9Sstevel@tonic-gate KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_FIND_FINAL, 52437c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, 0, NULL, 0, NULL, 0, 52447c478bd9Sstevel@tonic-gate NULL, sp->sd_find_init_cookie, 0, NULL); 52457c478bd9Sstevel@tonic-gate 5246894b2776Smcpowers rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5247894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 5248894b2776Smcpowers return (rv); 52497c478bd9Sstevel@tonic-gate } 52507c478bd9Sstevel@tonic-gate 52517c478bd9Sstevel@tonic-gate /* ARGSUSED */ 52527c478bd9Sstevel@tonic-gate static int 52537c478bd9Sstevel@tonic-gate object_find_final(dev_t dev, caddr_t arg, int mode, int *rval) 52547c478bd9Sstevel@tonic-gate { 52557c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_object_find_final, object_find_final); 52567c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 52577c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 52587c478bd9Sstevel@tonic-gate crypto_session_data_t *sp; 52597c478bd9Sstevel@tonic-gate int error = 0; 52607c478bd9Sstevel@tonic-gate int rv; 52617c478bd9Sstevel@tonic-gate 52627c478bd9Sstevel@tonic-gate STRUCT_INIT(object_find_final, mode); 52637c478bd9Sstevel@tonic-gate 52647c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 52657c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "object_find_final: failed holding minor"); 52667c478bd9Sstevel@tonic-gate return (ENXIO); 52677c478bd9Sstevel@tonic-gate } 52687c478bd9Sstevel@tonic-gate 52697c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(object_find_final), 52707c478bd9Sstevel@tonic-gate STRUCT_SIZE(object_find_final)) != 0) { 52717c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 52727c478bd9Sstevel@tonic-gate return (EFAULT); 52737c478bd9Sstevel@tonic-gate } 52747c478bd9Sstevel@tonic-gate 52757c478bd9Sstevel@tonic-gate session_id = STRUCT_FGET(object_find_final, ff_session); 52767c478bd9Sstevel@tonic-gate 52777c478bd9Sstevel@tonic-gate if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 52787c478bd9Sstevel@tonic-gate goto release_minor; 52797c478bd9Sstevel@tonic-gate } 52807c478bd9Sstevel@tonic-gate 52817c478bd9Sstevel@tonic-gate if ((rv = crypto_free_find_ctx(sp)) == CRYPTO_SUCCESS) { 52827c478bd9Sstevel@tonic-gate sp->sd_find_init_cookie = NULL; 52837c478bd9Sstevel@tonic-gate } 52847c478bd9Sstevel@tonic-gate 52857c478bd9Sstevel@tonic-gate CRYPTO_SESSION_RELE(sp); 52867c478bd9Sstevel@tonic-gate 52877c478bd9Sstevel@tonic-gate release_minor: 52887c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 52897c478bd9Sstevel@tonic-gate 52907c478bd9Sstevel@tonic-gate if (error != 0) 52917c478bd9Sstevel@tonic-gate return (error); 52927c478bd9Sstevel@tonic-gate 52937c478bd9Sstevel@tonic-gate STRUCT_FSET(object_find_final, ff_return_value, rv); 52947c478bd9Sstevel@tonic-gate 52957c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(object_find_final), arg, 52967c478bd9Sstevel@tonic-gate STRUCT_SIZE(object_find_final)) != 0) { 52977c478bd9Sstevel@tonic-gate return (EFAULT); 52987c478bd9Sstevel@tonic-gate } 52997c478bd9Sstevel@tonic-gate return (0); 53007c478bd9Sstevel@tonic-gate } 53017c478bd9Sstevel@tonic-gate 53027c478bd9Sstevel@tonic-gate /* ARGSUSED */ 53037c478bd9Sstevel@tonic-gate static int 53047c478bd9Sstevel@tonic-gate object_generate_key(dev_t dev, caddr_t arg, int mode, int *rval) 53057c478bd9Sstevel@tonic-gate { 53067c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_object_generate_key, generate_key); 5307894b2776Smcpowers kcf_provider_desc_t *real_provider = NULL; 53087c478bd9Sstevel@tonic-gate kcf_req_params_t params; 53097c478bd9Sstevel@tonic-gate crypto_mechanism_t mech; 53107c478bd9Sstevel@tonic-gate crypto_object_attribute_t *k_attrs = NULL; 53117c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 53127c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 53137c478bd9Sstevel@tonic-gate crypto_session_data_t *sp = NULL; 53147c478bd9Sstevel@tonic-gate crypto_object_id_t key_handle; 53157c478bd9Sstevel@tonic-gate caddr_t attributes; 53167c478bd9Sstevel@tonic-gate size_t k_attrs_size; 53177c478bd9Sstevel@tonic-gate size_t mech_rctl_bytes = 0, key_rctl_bytes = 0; 53182d794da1Skrishna boolean_t mech_rctl_chk = B_FALSE; 53192d794da1Skrishna boolean_t key_rctl_chk = B_FALSE; 53207c478bd9Sstevel@tonic-gate uint_t count; 53217c478bd9Sstevel@tonic-gate int error = 0; 53227c478bd9Sstevel@tonic-gate int rv; 5323894b2776Smcpowers boolean_t allocated_by_crypto_module = B_FALSE; 53247c478bd9Sstevel@tonic-gate 53257c478bd9Sstevel@tonic-gate STRUCT_INIT(generate_key, mode); 53267c478bd9Sstevel@tonic-gate 53277c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 53287c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "object_generate_key: failed holding minor"); 53297c478bd9Sstevel@tonic-gate return (ENXIO); 53307c478bd9Sstevel@tonic-gate } 53317c478bd9Sstevel@tonic-gate 53327c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(generate_key), 53337c478bd9Sstevel@tonic-gate STRUCT_SIZE(generate_key)) != 0) { 53347c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 53357c478bd9Sstevel@tonic-gate return (EFAULT); 53367c478bd9Sstevel@tonic-gate } 53377c478bd9Sstevel@tonic-gate 53387c478bd9Sstevel@tonic-gate session_id = STRUCT_FGET(generate_key, gk_session); 53397c478bd9Sstevel@tonic-gate 53407c478bd9Sstevel@tonic-gate if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 53417c478bd9Sstevel@tonic-gate goto release_minor; 53427c478bd9Sstevel@tonic-gate } 53437c478bd9Sstevel@tonic-gate 5344894b2776Smcpowers bcopy(STRUCT_FADDR(generate_key, gk_mechanism), &mech.cm_type, 5345894b2776Smcpowers sizeof (crypto_mech_type_t)); 5346894b2776Smcpowers 5347436935a1SVladimir Kotal if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL, 53489b009fc1SValerie Bubb Fenwick CRYPTO_MECH_INVALID, NULL, sp->sd_provider, 5349436935a1SVladimir Kotal &real_provider, CRYPTO_FG_GENERATE)) != CRYPTO_SUCCESS) { 53507c478bd9Sstevel@tonic-gate goto release_minor; 53517c478bd9Sstevel@tonic-gate } 53527c478bd9Sstevel@tonic-gate 5353894b2776Smcpowers rv = crypto_provider_copyin_mech_param(real_provider, 5354894b2776Smcpowers STRUCT_FADDR(generate_key, gk_mechanism), &mech, mode, &error); 5355894b2776Smcpowers 5356894b2776Smcpowers if (rv == CRYPTO_NOT_SUPPORTED) { 5357894b2776Smcpowers allocated_by_crypto_module = B_TRUE; 53582d794da1Skrishna if (!copyin_mech(mode, sp, 53592d794da1Skrishna STRUCT_FADDR(generate_key, gk_mechanism), 53602d794da1Skrishna &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) { 5361894b2776Smcpowers goto release_minor; 5362894b2776Smcpowers } 5363894b2776Smcpowers } else { 5364894b2776Smcpowers if (rv != CRYPTO_SUCCESS) 53657c478bd9Sstevel@tonic-gate goto release_minor; 53667c478bd9Sstevel@tonic-gate } 53677c478bd9Sstevel@tonic-gate 53687c478bd9Sstevel@tonic-gate count = STRUCT_FGET(generate_key, gk_count); 53697c478bd9Sstevel@tonic-gate attributes = STRUCT_FGETP(generate_key, gk_attributes); 53702d794da1Skrishna if (!copyin_attributes(mode, sp, count, attributes, &k_attrs, 53712d794da1Skrishna &k_attrs_size, NULL, &rv, &error, &key_rctl_bytes, 53722d794da1Skrishna &key_rctl_chk, B_TRUE)) { 53737c478bd9Sstevel@tonic-gate goto release_minor; 53747c478bd9Sstevel@tonic-gate } 53757c478bd9Sstevel@tonic-gate 53767c478bd9Sstevel@tonic-gate KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_GENERATE, 53777c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, &mech, k_attrs, count, 53787c478bd9Sstevel@tonic-gate &key_handle, NULL, 0, NULL, NULL, NULL, 0); 53797c478bd9Sstevel@tonic-gate 53807c478bd9Sstevel@tonic-gate rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 53817c478bd9Sstevel@tonic-gate 53827c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) 53837c478bd9Sstevel@tonic-gate STRUCT_FSET(generate_key, gk_handle, key_handle); 53847c478bd9Sstevel@tonic-gate 53857c478bd9Sstevel@tonic-gate release_minor: 53862d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk); 53872d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk); 53887c478bd9Sstevel@tonic-gate 53897c478bd9Sstevel@tonic-gate if (k_attrs != NULL) 53907c478bd9Sstevel@tonic-gate kmem_free(k_attrs, k_attrs_size); 53917c478bd9Sstevel@tonic-gate 53927c478bd9Sstevel@tonic-gate if (error != 0) 53937c478bd9Sstevel@tonic-gate goto out; 53947c478bd9Sstevel@tonic-gate 53957c478bd9Sstevel@tonic-gate STRUCT_FSET(generate_key, gk_return_value, rv); 53967c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(generate_key), arg, 53977c478bd9Sstevel@tonic-gate STRUCT_SIZE(generate_key)) != 0) { 53987c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) { 53997c478bd9Sstevel@tonic-gate KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 54007c478bd9Sstevel@tonic-gate KCF_OP_OBJECT_DESTROY, 54017c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, key_handle, 54027c478bd9Sstevel@tonic-gate NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 54037c478bd9Sstevel@tonic-gate 54047c478bd9Sstevel@tonic-gate (void) kcf_submit_request(real_provider, NULL, 54057c478bd9Sstevel@tonic-gate NULL, ¶ms, B_FALSE); 54067c478bd9Sstevel@tonic-gate 54077c478bd9Sstevel@tonic-gate error = EFAULT; 54087c478bd9Sstevel@tonic-gate } 54097c478bd9Sstevel@tonic-gate } 54107c478bd9Sstevel@tonic-gate out: 54117c478bd9Sstevel@tonic-gate CRYPTO_SESSION_RELE(sp); 54127c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 5413894b2776Smcpowers 5414894b2776Smcpowers if (real_provider != NULL) { 5415894b2776Smcpowers crypto_free_mech(real_provider, 5416894b2776Smcpowers allocated_by_crypto_module, &mech); 5417894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 5418894b2776Smcpowers } 54197c478bd9Sstevel@tonic-gate return (error); 54207c478bd9Sstevel@tonic-gate } 54217c478bd9Sstevel@tonic-gate 54227c478bd9Sstevel@tonic-gate /* ARGSUSED */ 54237c478bd9Sstevel@tonic-gate static int 5424034448feSmcpowers nostore_generate_key(dev_t dev, caddr_t arg, int mode, int *rval) 5425034448feSmcpowers { 5426034448feSmcpowers STRUCT_DECL(crypto_nostore_generate_key, generate_key); 542795014fbbSDan OpenSolaris Anderson #ifdef _LP64 542895014fbbSDan OpenSolaris Anderson STRUCT_DECL(crypto_object_attribute, oa); 542995014fbbSDan OpenSolaris Anderson #else 5430034448feSmcpowers /* LINTED E_FUNC_SET_NOT_USED */ 5431034448feSmcpowers STRUCT_DECL(crypto_object_attribute, oa); 543295014fbbSDan OpenSolaris Anderson #endif 5433034448feSmcpowers kcf_provider_desc_t *real_provider = NULL; 5434034448feSmcpowers kcf_req_params_t params; 5435034448feSmcpowers crypto_mechanism_t mech; 5436034448feSmcpowers crypto_object_attribute_t *k_in_attrs = NULL; 5437034448feSmcpowers crypto_object_attribute_t *k_out_attrs = NULL; 5438034448feSmcpowers crypto_session_id_t session_id; 5439034448feSmcpowers crypto_minor_t *cm; 5440034448feSmcpowers crypto_session_data_t *sp = NULL; 5441034448feSmcpowers caddr_t in_attributes; 5442034448feSmcpowers caddr_t out_attributes; 5443034448feSmcpowers size_t k_in_attrs_size; 5444034448feSmcpowers size_t k_out_attrs_size; 5445034448feSmcpowers size_t mech_rctl_bytes = 0; 54462d794da1Skrishna boolean_t mech_rctl_chk = B_FALSE; 5447034448feSmcpowers size_t in_key_rctl_bytes = 0, out_key_rctl_bytes = 0; 54482d794da1Skrishna boolean_t in_key_rctl_chk = B_FALSE; 54492d794da1Skrishna boolean_t out_key_rctl_chk = B_FALSE; 5450034448feSmcpowers uint_t in_count; 5451034448feSmcpowers uint_t out_count; 5452034448feSmcpowers int error = 0; 5453034448feSmcpowers int rv; 5454034448feSmcpowers boolean_t allocated_by_crypto_module = B_FALSE; 5455034448feSmcpowers caddr_t u_attrs = NULL; 5456034448feSmcpowers 5457034448feSmcpowers STRUCT_INIT(generate_key, mode); 5458034448feSmcpowers STRUCT_INIT(oa, mode); 5459034448feSmcpowers 5460034448feSmcpowers if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 5461034448feSmcpowers cmn_err(CE_WARN, "nostore_generate_key: failed holding minor"); 5462034448feSmcpowers return (ENXIO); 5463034448feSmcpowers } 5464034448feSmcpowers 5465034448feSmcpowers if (copyin(arg, STRUCT_BUF(generate_key), 5466034448feSmcpowers STRUCT_SIZE(generate_key)) != 0) { 5467034448feSmcpowers crypto_release_minor(cm); 5468034448feSmcpowers return (EFAULT); 5469034448feSmcpowers } 5470034448feSmcpowers 5471034448feSmcpowers session_id = STRUCT_FGET(generate_key, ngk_session); 5472034448feSmcpowers 5473034448feSmcpowers if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 5474034448feSmcpowers goto release_minor; 5475034448feSmcpowers } 5476034448feSmcpowers 5477034448feSmcpowers bcopy(STRUCT_FADDR(generate_key, ngk_mechanism), &mech.cm_type, 5478034448feSmcpowers sizeof (crypto_mech_type_t)); 5479034448feSmcpowers 5480436935a1SVladimir Kotal if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL, 54819b009fc1SValerie Bubb Fenwick CRYPTO_MECH_INVALID, NULL, sp->sd_provider, 5482436935a1SVladimir Kotal &real_provider, CRYPTO_FG_GENERATE)) != CRYPTO_SUCCESS) { 5483034448feSmcpowers goto release_minor; 5484034448feSmcpowers } 5485034448feSmcpowers 5486034448feSmcpowers rv = crypto_provider_copyin_mech_param(real_provider, 5487034448feSmcpowers STRUCT_FADDR(generate_key, ngk_mechanism), &mech, mode, &error); 5488034448feSmcpowers 5489034448feSmcpowers if (rv == CRYPTO_NOT_SUPPORTED) { 5490034448feSmcpowers allocated_by_crypto_module = B_TRUE; 54912d794da1Skrishna if (!copyin_mech(mode, sp, STRUCT_FADDR(generate_key, 54922d794da1Skrishna ngk_mechanism), &mech, &mech_rctl_bytes, 54932d794da1Skrishna &mech_rctl_chk, &rv, &error)) { 5494034448feSmcpowers goto release_minor; 5495034448feSmcpowers } 5496034448feSmcpowers } else { 5497034448feSmcpowers if (rv != CRYPTO_SUCCESS) 5498034448feSmcpowers goto release_minor; 5499034448feSmcpowers } 5500034448feSmcpowers 5501034448feSmcpowers in_count = STRUCT_FGET(generate_key, ngk_in_count); 5502034448feSmcpowers in_attributes = STRUCT_FGETP(generate_key, ngk_in_attributes); 55032d794da1Skrishna if (!copyin_attributes(mode, sp, in_count, in_attributes, &k_in_attrs, 5504034448feSmcpowers &k_in_attrs_size, NULL, &rv, &error, &in_key_rctl_bytes, 55052d794da1Skrishna &in_key_rctl_chk, B_TRUE)) { 5506034448feSmcpowers goto release_minor; 5507034448feSmcpowers } 5508034448feSmcpowers 5509034448feSmcpowers out_count = STRUCT_FGET(generate_key, ngk_out_count); 5510034448feSmcpowers out_attributes = STRUCT_FGETP(generate_key, ngk_out_attributes); 55112d794da1Skrishna if (!copyin_attributes(mode, sp, out_count, out_attributes, 55122d794da1Skrishna &k_out_attrs, 5513034448feSmcpowers &k_out_attrs_size, &u_attrs, &rv, &error, &out_key_rctl_bytes, 55142d794da1Skrishna &out_key_rctl_chk, B_FALSE)) { 5515034448feSmcpowers goto release_minor; 5516034448feSmcpowers } 5517034448feSmcpowers 5518034448feSmcpowers KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_GENERATE, 5519034448feSmcpowers sp->sd_provider_session->ps_session, &mech, k_in_attrs, in_count, 5520034448feSmcpowers NULL, 0, NULL, k_out_attrs, out_count, NULL, 0); 5521034448feSmcpowers 5522034448feSmcpowers rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5523034448feSmcpowers 5524034448feSmcpowers if (rv == CRYPTO_SUCCESS) { 5525034448feSmcpowers error = copyout_attributes(mode, out_attributes, 5526034448feSmcpowers out_count, k_out_attrs, u_attrs); 5527034448feSmcpowers } 5528034448feSmcpowers release_minor: 55292d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk); 55302d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, in_key_rctl_bytes, in_key_rctl_chk); 55312d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, out_key_rctl_bytes, 55322d794da1Skrishna out_key_rctl_chk); 5533034448feSmcpowers 5534034448feSmcpowers if (k_in_attrs != NULL) 5535034448feSmcpowers kmem_free(k_in_attrs, k_in_attrs_size); 5536034448feSmcpowers if (k_out_attrs != NULL) { 5537034448feSmcpowers bzero(k_out_attrs, k_out_attrs_size); 5538034448feSmcpowers kmem_free(k_out_attrs, k_out_attrs_size); 5539034448feSmcpowers } 5540034448feSmcpowers 5541034448feSmcpowers if (u_attrs != NULL) 5542034448feSmcpowers kmem_free(u_attrs, out_count * STRUCT_SIZE(oa)); 5543034448feSmcpowers 5544034448feSmcpowers if (error != 0) 5545034448feSmcpowers goto out; 5546034448feSmcpowers 5547034448feSmcpowers STRUCT_FSET(generate_key, ngk_return_value, rv); 5548034448feSmcpowers if (copyout(STRUCT_BUF(generate_key), arg, 5549034448feSmcpowers STRUCT_SIZE(generate_key)) != 0) { 5550034448feSmcpowers error = EFAULT; 5551034448feSmcpowers } 5552034448feSmcpowers out: 5553034448feSmcpowers CRYPTO_SESSION_RELE(sp); 5554034448feSmcpowers crypto_release_minor(cm); 5555034448feSmcpowers 5556034448feSmcpowers if (real_provider != NULL) { 5557034448feSmcpowers crypto_free_mech(real_provider, 5558034448feSmcpowers allocated_by_crypto_module, &mech); 5559034448feSmcpowers KCF_PROV_REFRELE(real_provider); 5560034448feSmcpowers } 5561034448feSmcpowers return (error); 5562034448feSmcpowers } 5563034448feSmcpowers 5564034448feSmcpowers /* ARGSUSED */ 5565034448feSmcpowers static int 55667c478bd9Sstevel@tonic-gate object_generate_key_pair(dev_t dev, caddr_t arg, int mode, int *rval) 55677c478bd9Sstevel@tonic-gate { 55687c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_object_generate_key_pair, generate_key_pair); 5569894b2776Smcpowers kcf_provider_desc_t *real_provider = NULL; 55707c478bd9Sstevel@tonic-gate kcf_req_params_t params; 55717c478bd9Sstevel@tonic-gate crypto_mechanism_t mech; 55727c478bd9Sstevel@tonic-gate crypto_object_attribute_t *k_pub_attrs = NULL; 55737c478bd9Sstevel@tonic-gate crypto_object_attribute_t *k_pri_attrs = NULL; 55747c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 55757c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 55767c478bd9Sstevel@tonic-gate crypto_session_data_t *sp = NULL; 55777c478bd9Sstevel@tonic-gate crypto_object_id_t pub_handle; 55787c478bd9Sstevel@tonic-gate crypto_object_id_t pri_handle; 55797c478bd9Sstevel@tonic-gate caddr_t pri_attributes; 55807c478bd9Sstevel@tonic-gate caddr_t pub_attributes; 55817c478bd9Sstevel@tonic-gate size_t k_pub_attrs_size, k_pri_attrs_size; 55827c478bd9Sstevel@tonic-gate size_t mech_rctl_bytes = 0; 55832d794da1Skrishna boolean_t mech_rctl_chk = B_FALSE; 55847c478bd9Sstevel@tonic-gate size_t pub_rctl_bytes = 0; 55852d794da1Skrishna boolean_t pub_rctl_chk = B_FALSE; 55867c478bd9Sstevel@tonic-gate size_t pri_rctl_bytes = 0; 55872d794da1Skrishna boolean_t pri_rctl_chk = B_FALSE; 55887c478bd9Sstevel@tonic-gate uint_t pub_count; 55897c478bd9Sstevel@tonic-gate uint_t pri_count; 55907c478bd9Sstevel@tonic-gate int error = 0; 55917c478bd9Sstevel@tonic-gate int rv; 5592894b2776Smcpowers boolean_t allocated_by_crypto_module = B_FALSE; 55937c478bd9Sstevel@tonic-gate 55947c478bd9Sstevel@tonic-gate STRUCT_INIT(generate_key_pair, mode); 55957c478bd9Sstevel@tonic-gate 55967c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 55977c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 55987c478bd9Sstevel@tonic-gate "object_generate_key_pair: failed holding minor"); 55997c478bd9Sstevel@tonic-gate return (ENXIO); 56007c478bd9Sstevel@tonic-gate } 56017c478bd9Sstevel@tonic-gate 56027c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(generate_key_pair), 56037c478bd9Sstevel@tonic-gate STRUCT_SIZE(generate_key_pair)) != 0) { 56047c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 56057c478bd9Sstevel@tonic-gate return (EFAULT); 56067c478bd9Sstevel@tonic-gate } 56077c478bd9Sstevel@tonic-gate 56087c478bd9Sstevel@tonic-gate session_id = STRUCT_FGET(generate_key_pair, kp_session); 56097c478bd9Sstevel@tonic-gate 56107c478bd9Sstevel@tonic-gate if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 56117c478bd9Sstevel@tonic-gate goto release_minor; 56127c478bd9Sstevel@tonic-gate } 56137c478bd9Sstevel@tonic-gate 5614894b2776Smcpowers bcopy(STRUCT_FADDR(generate_key_pair, kp_mechanism), &mech.cm_type, 5615894b2776Smcpowers sizeof (crypto_mech_type_t)); 5616894b2776Smcpowers 5617436935a1SVladimir Kotal if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL, 56189b009fc1SValerie Bubb Fenwick CRYPTO_MECH_INVALID, NULL, sp->sd_provider, 5619436935a1SVladimir Kotal &real_provider, CRYPTO_FG_GENERATE_KEY_PAIR)) != CRYPTO_SUCCESS) { 56207c478bd9Sstevel@tonic-gate goto release_minor; 56217c478bd9Sstevel@tonic-gate } 56227c478bd9Sstevel@tonic-gate 5623894b2776Smcpowers rv = crypto_provider_copyin_mech_param(real_provider, 5624894b2776Smcpowers STRUCT_FADDR(generate_key_pair, kp_mechanism), &mech, mode, &error); 5625894b2776Smcpowers 5626894b2776Smcpowers if (rv == CRYPTO_NOT_SUPPORTED) { 5627894b2776Smcpowers allocated_by_crypto_module = B_TRUE; 56282d794da1Skrishna if (!copyin_mech(mode, sp, STRUCT_FADDR(generate_key_pair, 56292d794da1Skrishna kp_mechanism), &mech, &mech_rctl_bytes, 56302d794da1Skrishna &mech_rctl_chk, &rv, &error)) { 5631894b2776Smcpowers goto release_minor; 5632894b2776Smcpowers } 5633894b2776Smcpowers } else { 5634894b2776Smcpowers if (rv != CRYPTO_SUCCESS) 56357c478bd9Sstevel@tonic-gate goto release_minor; 56367c478bd9Sstevel@tonic-gate } 56377c478bd9Sstevel@tonic-gate 56387c478bd9Sstevel@tonic-gate pub_count = STRUCT_FGET(generate_key_pair, kp_public_count); 56397c478bd9Sstevel@tonic-gate pri_count = STRUCT_FGET(generate_key_pair, kp_private_count); 56407c478bd9Sstevel@tonic-gate 56417c478bd9Sstevel@tonic-gate pub_attributes = STRUCT_FGETP(generate_key_pair, kp_public_attributes); 56422d794da1Skrishna if (!copyin_attributes(mode, sp, pub_count, pub_attributes, 56432d794da1Skrishna &k_pub_attrs, &k_pub_attrs_size, NULL, &rv, &error, &pub_rctl_bytes, 56442d794da1Skrishna &pub_rctl_chk, B_TRUE)) { 56457c478bd9Sstevel@tonic-gate goto release_minor; 56467c478bd9Sstevel@tonic-gate } 56477c478bd9Sstevel@tonic-gate 56487c478bd9Sstevel@tonic-gate pri_attributes = STRUCT_FGETP(generate_key_pair, kp_private_attributes); 56492d794da1Skrishna if (!copyin_attributes(mode, sp, pri_count, pri_attributes, 56502d794da1Skrishna &k_pri_attrs, &k_pri_attrs_size, NULL, &rv, &error, 56512d794da1Skrishna &pri_rctl_bytes, &pri_rctl_chk, B_TRUE)) { 56527c478bd9Sstevel@tonic-gate goto release_minor; 56537c478bd9Sstevel@tonic-gate } 56547c478bd9Sstevel@tonic-gate 56557c478bd9Sstevel@tonic-gate KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_GENERATE_PAIR, 56567c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, &mech, k_pub_attrs, 56577c478bd9Sstevel@tonic-gate pub_count, &pub_handle, k_pri_attrs, pri_count, &pri_handle, 56587c478bd9Sstevel@tonic-gate NULL, NULL, 0); 56597c478bd9Sstevel@tonic-gate 56607c478bd9Sstevel@tonic-gate rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 56617c478bd9Sstevel@tonic-gate 56627c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) { 56637c478bd9Sstevel@tonic-gate STRUCT_FSET(generate_key_pair, kp_public_handle, pub_handle); 56647c478bd9Sstevel@tonic-gate STRUCT_FSET(generate_key_pair, kp_private_handle, pri_handle); 56657c478bd9Sstevel@tonic-gate } 56667c478bd9Sstevel@tonic-gate 56677c478bd9Sstevel@tonic-gate release_minor: 56682d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk); 56692d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, pub_rctl_bytes, pub_rctl_chk); 56702d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, pri_rctl_bytes, pri_rctl_chk); 56717c478bd9Sstevel@tonic-gate 56727c478bd9Sstevel@tonic-gate if (k_pub_attrs != NULL) 56737c478bd9Sstevel@tonic-gate kmem_free(k_pub_attrs, k_pub_attrs_size); 56747c478bd9Sstevel@tonic-gate 56757c478bd9Sstevel@tonic-gate if (k_pri_attrs != NULL) 56767c478bd9Sstevel@tonic-gate kmem_free(k_pri_attrs, k_pri_attrs_size); 56777c478bd9Sstevel@tonic-gate 56787c478bd9Sstevel@tonic-gate if (error != 0) 56797c478bd9Sstevel@tonic-gate goto out; 56807c478bd9Sstevel@tonic-gate 56817c478bd9Sstevel@tonic-gate STRUCT_FSET(generate_key_pair, kp_return_value, rv); 56827c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(generate_key_pair), arg, 56837c478bd9Sstevel@tonic-gate STRUCT_SIZE(generate_key_pair)) != 0) { 56847c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) { 56857c478bd9Sstevel@tonic-gate KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 56867c478bd9Sstevel@tonic-gate KCF_OP_OBJECT_DESTROY, 56877c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, pub_handle, 56887c478bd9Sstevel@tonic-gate NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 56897c478bd9Sstevel@tonic-gate 56907c478bd9Sstevel@tonic-gate (void) kcf_submit_request(real_provider, NULL, 56917c478bd9Sstevel@tonic-gate NULL, ¶ms, B_FALSE); 56927c478bd9Sstevel@tonic-gate 56937c478bd9Sstevel@tonic-gate KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 56947c478bd9Sstevel@tonic-gate KCF_OP_OBJECT_DESTROY, 56957c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, pri_handle, 56967c478bd9Sstevel@tonic-gate NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 56977c478bd9Sstevel@tonic-gate 56987c478bd9Sstevel@tonic-gate (void) kcf_submit_request(real_provider, NULL, 56997c478bd9Sstevel@tonic-gate NULL, ¶ms, B_FALSE); 57007c478bd9Sstevel@tonic-gate 57017c478bd9Sstevel@tonic-gate error = EFAULT; 57027c478bd9Sstevel@tonic-gate } 57037c478bd9Sstevel@tonic-gate } 57047c478bd9Sstevel@tonic-gate out: 57057c478bd9Sstevel@tonic-gate CRYPTO_SESSION_RELE(sp); 57067c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 5707894b2776Smcpowers 5708894b2776Smcpowers if (real_provider != NULL) { 5709894b2776Smcpowers crypto_free_mech(real_provider, 5710894b2776Smcpowers allocated_by_crypto_module, &mech); 5711894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 5712894b2776Smcpowers } 57137c478bd9Sstevel@tonic-gate return (error); 57147c478bd9Sstevel@tonic-gate } 57157c478bd9Sstevel@tonic-gate 57167c478bd9Sstevel@tonic-gate /* ARGSUSED */ 57177c478bd9Sstevel@tonic-gate static int 5718034448feSmcpowers nostore_generate_key_pair(dev_t dev, caddr_t arg, int mode, int *rval) 5719034448feSmcpowers { 5720034448feSmcpowers STRUCT_DECL(crypto_nostore_generate_key_pair, generate_key_pair); 572195014fbbSDan OpenSolaris Anderson #ifdef _LP64 572295014fbbSDan OpenSolaris Anderson STRUCT_DECL(crypto_object_attribute, oa); 572395014fbbSDan OpenSolaris Anderson #else 5724034448feSmcpowers /* LINTED E_FUNC_SET_NOT_USED */ 5725034448feSmcpowers STRUCT_DECL(crypto_object_attribute, oa); 572695014fbbSDan OpenSolaris Anderson #endif 5727034448feSmcpowers kcf_provider_desc_t *real_provider = NULL; 5728034448feSmcpowers kcf_req_params_t params; 5729034448feSmcpowers crypto_mechanism_t mech; 5730034448feSmcpowers crypto_object_attribute_t *k_in_pub_attrs = NULL; 5731034448feSmcpowers crypto_object_attribute_t *k_in_pri_attrs = NULL; 5732034448feSmcpowers crypto_object_attribute_t *k_out_pub_attrs = NULL; 5733034448feSmcpowers crypto_object_attribute_t *k_out_pri_attrs = NULL; 5734034448feSmcpowers crypto_session_id_t session_id; 5735034448feSmcpowers crypto_minor_t *cm; 5736034448feSmcpowers crypto_session_data_t *sp = NULL; 5737034448feSmcpowers caddr_t in_pri_attributes; 5738034448feSmcpowers caddr_t in_pub_attributes; 5739034448feSmcpowers caddr_t out_pri_attributes; 5740034448feSmcpowers caddr_t out_pub_attributes; 5741034448feSmcpowers size_t k_in_pub_attrs_size, k_in_pri_attrs_size; 5742034448feSmcpowers size_t k_out_pub_attrs_size, k_out_pri_attrs_size; 5743034448feSmcpowers size_t mech_rctl_bytes = 0; 57442d794da1Skrishna boolean_t mech_rctl_chk = B_FALSE; 5745034448feSmcpowers size_t in_pub_rctl_bytes = 0; 57462d794da1Skrishna boolean_t in_pub_rctl_chk = B_FALSE; 5747034448feSmcpowers size_t in_pri_rctl_bytes = 0; 57482d794da1Skrishna boolean_t in_pri_rctl_chk = B_FALSE; 5749034448feSmcpowers size_t out_pub_rctl_bytes = 0; 57502d794da1Skrishna boolean_t out_pub_rctl_chk = B_FALSE; 5751034448feSmcpowers size_t out_pri_rctl_bytes = 0; 57522d794da1Skrishna boolean_t out_pri_rctl_chk = B_FALSE; 5753034448feSmcpowers uint_t in_pub_count; 5754034448feSmcpowers uint_t in_pri_count; 5755034448feSmcpowers uint_t out_pub_count; 5756034448feSmcpowers uint_t out_pri_count; 5757034448feSmcpowers int error = 0; 5758034448feSmcpowers int rv; 5759034448feSmcpowers boolean_t allocated_by_crypto_module = B_FALSE; 5760034448feSmcpowers caddr_t u_pub_attrs = NULL; 5761034448feSmcpowers caddr_t u_pri_attrs = NULL; 5762034448feSmcpowers 5763034448feSmcpowers STRUCT_INIT(generate_key_pair, mode); 5764034448feSmcpowers STRUCT_INIT(oa, mode); 5765034448feSmcpowers 5766034448feSmcpowers if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 5767034448feSmcpowers cmn_err(CE_WARN, 5768034448feSmcpowers "nostore_generate_key_pair: failed holding minor"); 5769034448feSmcpowers return (ENXIO); 5770034448feSmcpowers } 5771034448feSmcpowers 5772034448feSmcpowers if (copyin(arg, STRUCT_BUF(generate_key_pair), 5773034448feSmcpowers STRUCT_SIZE(generate_key_pair)) != 0) { 5774034448feSmcpowers crypto_release_minor(cm); 5775034448feSmcpowers return (EFAULT); 5776034448feSmcpowers } 5777034448feSmcpowers 5778034448feSmcpowers session_id = STRUCT_FGET(generate_key_pair, nkp_session); 5779034448feSmcpowers 5780034448feSmcpowers if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 5781034448feSmcpowers goto release_minor; 5782034448feSmcpowers } 5783034448feSmcpowers 5784034448feSmcpowers bcopy(STRUCT_FADDR(generate_key_pair, nkp_mechanism), &mech.cm_type, 5785034448feSmcpowers sizeof (crypto_mech_type_t)); 5786034448feSmcpowers 5787436935a1SVladimir Kotal if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL, 57889b009fc1SValerie Bubb Fenwick CRYPTO_MECH_INVALID, NULL, sp->sd_provider, 5789436935a1SVladimir Kotal &real_provider, CRYPTO_FG_GENERATE_KEY_PAIR)) != CRYPTO_SUCCESS) { 5790034448feSmcpowers goto release_minor; 5791034448feSmcpowers } 5792034448feSmcpowers 5793034448feSmcpowers rv = crypto_provider_copyin_mech_param(real_provider, 5794034448feSmcpowers STRUCT_FADDR(generate_key_pair, nkp_mechanism), &mech, mode, 5795034448feSmcpowers &error); 5796034448feSmcpowers 5797034448feSmcpowers if (rv == CRYPTO_NOT_SUPPORTED) { 5798034448feSmcpowers allocated_by_crypto_module = B_TRUE; 57992d794da1Skrishna if (!copyin_mech(mode, sp, STRUCT_FADDR(generate_key_pair, 58002d794da1Skrishna nkp_mechanism), &mech, &mech_rctl_bytes, 58012d794da1Skrishna &mech_rctl_chk, &rv, &error)) { 5802034448feSmcpowers goto release_minor; 5803034448feSmcpowers } 5804034448feSmcpowers } else { 5805034448feSmcpowers if (rv != CRYPTO_SUCCESS) 5806034448feSmcpowers goto release_minor; 5807034448feSmcpowers } 5808034448feSmcpowers 5809034448feSmcpowers in_pub_count = STRUCT_FGET(generate_key_pair, nkp_in_public_count); 5810034448feSmcpowers in_pri_count = STRUCT_FGET(generate_key_pair, nkp_in_private_count); 5811034448feSmcpowers 5812034448feSmcpowers in_pub_attributes = STRUCT_FGETP(generate_key_pair, 5813034448feSmcpowers nkp_in_public_attributes); 58142d794da1Skrishna if (!copyin_attributes(mode, sp, in_pub_count, in_pub_attributes, 5815034448feSmcpowers &k_in_pub_attrs, &k_in_pub_attrs_size, NULL, &rv, &error, 58162d794da1Skrishna &in_pub_rctl_bytes, &in_pub_rctl_chk, B_TRUE)) { 5817034448feSmcpowers goto release_minor; 5818034448feSmcpowers } 5819034448feSmcpowers 5820034448feSmcpowers in_pri_attributes = STRUCT_FGETP(generate_key_pair, 5821034448feSmcpowers nkp_in_private_attributes); 58222d794da1Skrishna if (!copyin_attributes(mode, sp, in_pri_count, in_pri_attributes, 5823034448feSmcpowers &k_in_pri_attrs, &k_in_pri_attrs_size, NULL, &rv, &error, 58242d794da1Skrishna &in_pri_rctl_bytes, &in_pri_rctl_chk, B_TRUE)) { 5825034448feSmcpowers goto release_minor; 5826034448feSmcpowers } 5827034448feSmcpowers 5828034448feSmcpowers out_pub_count = STRUCT_FGET(generate_key_pair, nkp_out_public_count); 5829034448feSmcpowers out_pri_count = STRUCT_FGET(generate_key_pair, nkp_out_private_count); 5830034448feSmcpowers 5831034448feSmcpowers out_pub_attributes = STRUCT_FGETP(generate_key_pair, 5832034448feSmcpowers nkp_out_public_attributes); 58332d794da1Skrishna if (!copyin_attributes(mode, sp, out_pub_count, out_pub_attributes, 5834034448feSmcpowers &k_out_pub_attrs, &k_out_pub_attrs_size, &u_pub_attrs, &rv, &error, 58352d794da1Skrishna &out_pub_rctl_bytes, &out_pub_rctl_chk, B_FALSE)) { 5836034448feSmcpowers goto release_minor; 5837034448feSmcpowers } 5838034448feSmcpowers 5839034448feSmcpowers out_pri_attributes = STRUCT_FGETP(generate_key_pair, 5840034448feSmcpowers nkp_out_private_attributes); 58412d794da1Skrishna if (!copyin_attributes(mode, sp, out_pri_count, out_pri_attributes, 5842034448feSmcpowers &k_out_pri_attrs, &k_out_pri_attrs_size, &u_pri_attrs, &rv, &error, 58432d794da1Skrishna &out_pri_rctl_bytes, &out_pri_rctl_chk, B_FALSE)) { 5844034448feSmcpowers goto release_minor; 5845034448feSmcpowers } 5846034448feSmcpowers 5847034448feSmcpowers KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_GENERATE_PAIR, 5848034448feSmcpowers sp->sd_provider_session->ps_session, &mech, k_in_pub_attrs, 5849034448feSmcpowers in_pub_count, k_in_pri_attrs, in_pri_count, NULL, k_out_pub_attrs, 5850034448feSmcpowers out_pub_count, k_out_pri_attrs, out_pri_count); 5851034448feSmcpowers 5852034448feSmcpowers rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 5853034448feSmcpowers 5854034448feSmcpowers if (rv == CRYPTO_SUCCESS) { 5855034448feSmcpowers error = copyout_attributes(mode, out_pub_attributes, 5856034448feSmcpowers out_pub_count, k_out_pub_attrs, u_pub_attrs); 5857034448feSmcpowers if (error != CRYPTO_SUCCESS) 5858034448feSmcpowers goto release_minor; 5859034448feSmcpowers error = copyout_attributes(mode, out_pri_attributes, 5860034448feSmcpowers out_pri_count, k_out_pri_attrs, u_pri_attrs); 5861034448feSmcpowers } 5862034448feSmcpowers 5863034448feSmcpowers release_minor: 58642d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk); 58652d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, in_pub_rctl_bytes, in_pub_rctl_chk); 58662d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, in_pri_rctl_bytes, in_pri_rctl_chk); 58672d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, out_pub_rctl_bytes, 58682d794da1Skrishna out_pub_rctl_chk); 58692d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, out_pri_rctl_bytes, 58702d794da1Skrishna out_pri_rctl_chk); 5871034448feSmcpowers 5872034448feSmcpowers if (k_in_pub_attrs != NULL) 5873034448feSmcpowers kmem_free(k_in_pub_attrs, k_in_pub_attrs_size); 5874034448feSmcpowers 5875034448feSmcpowers if (k_in_pri_attrs != NULL) 5876034448feSmcpowers kmem_free(k_in_pri_attrs, k_in_pri_attrs_size); 5877034448feSmcpowers 5878034448feSmcpowers if (k_out_pub_attrs != NULL) 5879034448feSmcpowers kmem_free(k_out_pub_attrs, k_out_pub_attrs_size); 5880034448feSmcpowers 5881034448feSmcpowers if (k_out_pri_attrs != NULL) { 5882034448feSmcpowers bzero(k_out_pri_attrs, k_out_pri_attrs_size); 5883034448feSmcpowers kmem_free(k_out_pri_attrs, k_out_pri_attrs_size); 5884034448feSmcpowers } 5885034448feSmcpowers 5886034448feSmcpowers if (u_pub_attrs != NULL) 5887034448feSmcpowers kmem_free(u_pub_attrs, out_pub_count * STRUCT_SIZE(oa)); 5888034448feSmcpowers 5889034448feSmcpowers if (u_pri_attrs != NULL) 5890034448feSmcpowers kmem_free(u_pri_attrs, out_pri_count * STRUCT_SIZE(oa)); 5891034448feSmcpowers 5892034448feSmcpowers if (error != 0) 5893034448feSmcpowers goto out; 5894034448feSmcpowers 5895034448feSmcpowers STRUCT_FSET(generate_key_pair, nkp_return_value, rv); 5896034448feSmcpowers if (copyout(STRUCT_BUF(generate_key_pair), arg, 5897034448feSmcpowers STRUCT_SIZE(generate_key_pair)) != 0) { 5898034448feSmcpowers error = EFAULT; 5899034448feSmcpowers } 5900034448feSmcpowers out: 5901034448feSmcpowers CRYPTO_SESSION_RELE(sp); 5902034448feSmcpowers crypto_release_minor(cm); 5903034448feSmcpowers 5904034448feSmcpowers if (real_provider != NULL) { 5905034448feSmcpowers crypto_free_mech(real_provider, 5906034448feSmcpowers allocated_by_crypto_module, &mech); 5907034448feSmcpowers KCF_PROV_REFRELE(real_provider); 5908034448feSmcpowers } 5909034448feSmcpowers return (error); 5910034448feSmcpowers } 5911034448feSmcpowers 5912034448feSmcpowers /* ARGSUSED */ 5913034448feSmcpowers static int 59147c478bd9Sstevel@tonic-gate object_wrap_key(dev_t dev, caddr_t arg, int mode, int *rval) 59157c478bd9Sstevel@tonic-gate { 59167c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_object_wrap_key, wrap_key); 5917894b2776Smcpowers kcf_provider_desc_t *real_provider = NULL; 59187c478bd9Sstevel@tonic-gate kcf_req_params_t params; 59197c478bd9Sstevel@tonic-gate crypto_mechanism_t mech; 59207c478bd9Sstevel@tonic-gate crypto_key_t key; 59217c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 59227c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 59232d794da1Skrishna crypto_session_data_t *sp = NULL; 59247c478bd9Sstevel@tonic-gate crypto_object_id_t handle; 59257c478bd9Sstevel@tonic-gate size_t mech_rctl_bytes = 0, key_rctl_bytes = 0; 59262d794da1Skrishna boolean_t mech_rctl_chk = B_FALSE; 59272d794da1Skrishna boolean_t key_rctl_chk = B_FALSE; 59287c478bd9Sstevel@tonic-gate size_t wrapped_key_rctl_bytes = 0; 59292d794da1Skrishna boolean_t wrapped_key_rctl_chk = B_FALSE; 59307c478bd9Sstevel@tonic-gate size_t wrapped_key_len, new_wrapped_key_len; 59317c478bd9Sstevel@tonic-gate uchar_t *wrapped_key = NULL; 59327c478bd9Sstevel@tonic-gate char *wrapped_key_buffer; 59337c478bd9Sstevel@tonic-gate int error = 0; 59347c478bd9Sstevel@tonic-gate int rv; 5935894b2776Smcpowers boolean_t allocated_by_crypto_module = B_FALSE; 59367c478bd9Sstevel@tonic-gate 59377c478bd9Sstevel@tonic-gate STRUCT_INIT(wrap_key, mode); 59387c478bd9Sstevel@tonic-gate 59397c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 59407c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "object_wrap_key: failed holding minor"); 59417c478bd9Sstevel@tonic-gate return (ENXIO); 59427c478bd9Sstevel@tonic-gate } 59437c478bd9Sstevel@tonic-gate 59447c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(wrap_key), STRUCT_SIZE(wrap_key)) != 0) { 59457c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 59467c478bd9Sstevel@tonic-gate return (EFAULT); 59477c478bd9Sstevel@tonic-gate } 59487c478bd9Sstevel@tonic-gate 59497c478bd9Sstevel@tonic-gate bzero(&key, sizeof (crypto_key_t)); 59507c478bd9Sstevel@tonic-gate 59517c478bd9Sstevel@tonic-gate session_id = STRUCT_FGET(wrap_key, wk_session); 59527c478bd9Sstevel@tonic-gate 59537c478bd9Sstevel@tonic-gate if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 59542d794da1Skrishna goto out; 59557c478bd9Sstevel@tonic-gate } 59567c478bd9Sstevel@tonic-gate 5957894b2776Smcpowers bcopy(STRUCT_FADDR(wrap_key, wk_mechanism), &mech.cm_type, 5958894b2776Smcpowers sizeof (crypto_mech_type_t)); 5959894b2776Smcpowers 5960436935a1SVladimir Kotal /* We need the key length for provider selection so copy it in now. */ 5961436935a1SVladimir Kotal if (!copyin_key(mode, sp, STRUCT_FADDR(wrap_key, wk_wrapping_key), &key, 5962436935a1SVladimir Kotal &key_rctl_bytes, &key_rctl_chk, &rv, &error)) { 5963436935a1SVladimir Kotal goto out; 5964436935a1SVladimir Kotal } 5965436935a1SVladimir Kotal 5966436935a1SVladimir Kotal wrapped_key_len = STRUCT_FGET(wrap_key, wk_wrapped_key_len); 5967436935a1SVladimir Kotal 5968436935a1SVladimir Kotal if ((rv = kcf_get_hardware_provider(mech.cm_type, &key, 59699b009fc1SValerie Bubb Fenwick CRYPTO_MECH_INVALID, NULL, sp->sd_provider, 5970436935a1SVladimir Kotal &real_provider, CRYPTO_FG_WRAP)) != CRYPTO_SUCCESS) { 59717c478bd9Sstevel@tonic-gate goto out; 59727c478bd9Sstevel@tonic-gate } 59737c478bd9Sstevel@tonic-gate 5974894b2776Smcpowers rv = crypto_provider_copyin_mech_param(real_provider, 5975894b2776Smcpowers STRUCT_FADDR(wrap_key, wk_mechanism), &mech, mode, &error); 5976894b2776Smcpowers 5977894b2776Smcpowers if (rv == CRYPTO_NOT_SUPPORTED) { 5978894b2776Smcpowers allocated_by_crypto_module = B_TRUE; 59792d794da1Skrishna if (!copyin_mech(mode, sp, STRUCT_FADDR(wrap_key, wk_mechanism), 59802d794da1Skrishna &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) { 5981894b2776Smcpowers goto out; 5982894b2776Smcpowers } 5983894b2776Smcpowers } else { 5984894b2776Smcpowers if (rv != CRYPTO_SUCCESS) 59857c478bd9Sstevel@tonic-gate goto out; 59867c478bd9Sstevel@tonic-gate } 59877c478bd9Sstevel@tonic-gate 59887c478bd9Sstevel@tonic-gate /* 59897c478bd9Sstevel@tonic-gate * Don't allocate output buffer unless both buffer pointer and 59907c478bd9Sstevel@tonic-gate * buffer length are not NULL or 0 (length). 59917c478bd9Sstevel@tonic-gate */ 59927c478bd9Sstevel@tonic-gate wrapped_key_buffer = STRUCT_FGETP(wrap_key, wk_wrapped_key); 59937c478bd9Sstevel@tonic-gate if (wrapped_key_buffer == NULL || wrapped_key_len == 0) { 59947c478bd9Sstevel@tonic-gate wrapped_key_len = 0; 59957c478bd9Sstevel@tonic-gate } 59967c478bd9Sstevel@tonic-gate 59977c478bd9Sstevel@tonic-gate if (wrapped_key_len > crypto_max_buffer_len) { 59987c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "object_wrap_key: buffer greater than %ld " 59997c478bd9Sstevel@tonic-gate "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 60007c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 60017c478bd9Sstevel@tonic-gate goto out; 60027c478bd9Sstevel@tonic-gate } 60037c478bd9Sstevel@tonic-gate 60042d794da1Skrishna if ((rv = CRYPTO_BUFFER_CHECK(sp, wrapped_key_len, 60052d794da1Skrishna wrapped_key_rctl_chk)) != CRYPTO_SUCCESS) { 60067c478bd9Sstevel@tonic-gate goto out; 60077c478bd9Sstevel@tonic-gate } 60087c478bd9Sstevel@tonic-gate 60097c478bd9Sstevel@tonic-gate /* new_wrapped_key_len can be modified by the provider */ 60107c478bd9Sstevel@tonic-gate wrapped_key_rctl_bytes = new_wrapped_key_len = wrapped_key_len; 60117c478bd9Sstevel@tonic-gate wrapped_key = kmem_alloc(wrapped_key_len, KM_SLEEP); 60127c478bd9Sstevel@tonic-gate 60137c478bd9Sstevel@tonic-gate handle = STRUCT_FGET(wrap_key, wk_object_handle); 60147c478bd9Sstevel@tonic-gate KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_WRAP, 60157c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, &mech, NULL, 0, &handle, 60167c478bd9Sstevel@tonic-gate NULL, 0, NULL, &key, wrapped_key, &new_wrapped_key_len); 60177c478bd9Sstevel@tonic-gate 60187c478bd9Sstevel@tonic-gate rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 60197c478bd9Sstevel@tonic-gate 60207c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) { 60217c478bd9Sstevel@tonic-gate if (wrapped_key_len != 0 && copyout(wrapped_key, 60227c478bd9Sstevel@tonic-gate wrapped_key_buffer, new_wrapped_key_len) != 0) { 60237c478bd9Sstevel@tonic-gate error = EFAULT; 60247c478bd9Sstevel@tonic-gate } 602595014fbbSDan OpenSolaris Anderson STRUCT_FSET(wrap_key, wk_wrapped_key_len, 602695014fbbSDan OpenSolaris Anderson (ulong_t)new_wrapped_key_len); 60277c478bd9Sstevel@tonic-gate } 60287c478bd9Sstevel@tonic-gate 60297c478bd9Sstevel@tonic-gate if (rv == CRYPTO_BUFFER_TOO_SMALL) { 60307c478bd9Sstevel@tonic-gate /* 60317c478bd9Sstevel@tonic-gate * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1 60327c478bd9Sstevel@tonic-gate * of section 11.2 of the pkcs11 spec. We catch it here and 60337c478bd9Sstevel@tonic-gate * provide the correct pkcs11 return value. 60347c478bd9Sstevel@tonic-gate */ 60357c478bd9Sstevel@tonic-gate if (STRUCT_FGETP(wrap_key, wk_wrapped_key) == NULL) 60367c478bd9Sstevel@tonic-gate rv = CRYPTO_SUCCESS; 603795014fbbSDan OpenSolaris Anderson STRUCT_FSET(wrap_key, wk_wrapped_key_len, 603895014fbbSDan OpenSolaris Anderson (ulong_t)new_wrapped_key_len); 60397c478bd9Sstevel@tonic-gate } 60402d794da1Skrishna 60417c478bd9Sstevel@tonic-gate out: 60422d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk); 60432d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk); 60442d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, wrapped_key_rctl_bytes, 60452d794da1Skrishna wrapped_key_rctl_chk); 60467c478bd9Sstevel@tonic-gate CRYPTO_SESSION_RELE(sp); 60477c478bd9Sstevel@tonic-gate 60487c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 60497c478bd9Sstevel@tonic-gate 6050894b2776Smcpowers if (real_provider != NULL) { 6051894b2776Smcpowers crypto_free_mech(real_provider, 6052894b2776Smcpowers allocated_by_crypto_module, &mech); 6053894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 6054894b2776Smcpowers } 6055894b2776Smcpowers 60567c478bd9Sstevel@tonic-gate if (wrapped_key != NULL) 60577c478bd9Sstevel@tonic-gate kmem_free(wrapped_key, wrapped_key_len); 60587c478bd9Sstevel@tonic-gate 60597c478bd9Sstevel@tonic-gate free_crypto_key(&key); 60607c478bd9Sstevel@tonic-gate 60617c478bd9Sstevel@tonic-gate if (error != 0) 60627c478bd9Sstevel@tonic-gate return (error); 60637c478bd9Sstevel@tonic-gate 60647c478bd9Sstevel@tonic-gate STRUCT_FSET(wrap_key, wk_return_value, rv); 60657c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(wrap_key), arg, STRUCT_SIZE(wrap_key)) != 0) { 60667c478bd9Sstevel@tonic-gate return (EFAULT); 60677c478bd9Sstevel@tonic-gate } 60687c478bd9Sstevel@tonic-gate return (0); 60697c478bd9Sstevel@tonic-gate } 60707c478bd9Sstevel@tonic-gate 60717c478bd9Sstevel@tonic-gate /* ARGSUSED */ 60727c478bd9Sstevel@tonic-gate static int 60737c478bd9Sstevel@tonic-gate object_unwrap_key(dev_t dev, caddr_t arg, int mode, int *rval) 60747c478bd9Sstevel@tonic-gate { 60757c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_object_unwrap_key, unwrap_key); 6076894b2776Smcpowers kcf_provider_desc_t *real_provider = NULL; 60777c478bd9Sstevel@tonic-gate kcf_req_params_t params; 60787c478bd9Sstevel@tonic-gate crypto_mechanism_t mech; 60797c478bd9Sstevel@tonic-gate crypto_key_t unwrapping_key; 60807c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 60817c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 60827c478bd9Sstevel@tonic-gate crypto_session_data_t *sp = NULL; 60837c478bd9Sstevel@tonic-gate crypto_object_id_t handle; 60847c478bd9Sstevel@tonic-gate crypto_object_attribute_t *k_attrs = NULL; 60857c478bd9Sstevel@tonic-gate size_t k_attrs_size; 60867c478bd9Sstevel@tonic-gate size_t mech_rctl_bytes = 0, unwrapping_key_rctl_bytes = 0; 60872d794da1Skrishna boolean_t mech_rctl_chk = B_FALSE; 60882d794da1Skrishna boolean_t unwrapping_key_rctl_chk = B_FALSE; 60897c478bd9Sstevel@tonic-gate size_t wrapped_key_rctl_bytes = 0, k_attrs_rctl_bytes = 0; 60902d794da1Skrishna boolean_t wrapped_key_rctl_chk = B_FALSE; 60912d794da1Skrishna boolean_t k_attrs_rctl_chk = B_FALSE; 60927c478bd9Sstevel@tonic-gate size_t wrapped_key_len; 60937c478bd9Sstevel@tonic-gate uchar_t *wrapped_key = NULL; 60947c478bd9Sstevel@tonic-gate int error = 0; 60957c478bd9Sstevel@tonic-gate int rv; 60967c478bd9Sstevel@tonic-gate uint_t count; 60977c478bd9Sstevel@tonic-gate caddr_t uk_attributes; 6098894b2776Smcpowers boolean_t allocated_by_crypto_module = B_FALSE; 60997c478bd9Sstevel@tonic-gate 61007c478bd9Sstevel@tonic-gate STRUCT_INIT(unwrap_key, mode); 61017c478bd9Sstevel@tonic-gate 61027c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 61037c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "object_unwrap_key: failed holding minor"); 61047c478bd9Sstevel@tonic-gate return (ENXIO); 61057c478bd9Sstevel@tonic-gate } 61067c478bd9Sstevel@tonic-gate 61077c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(unwrap_key), STRUCT_SIZE(unwrap_key)) != 0) { 61087c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 61097c478bd9Sstevel@tonic-gate return (EFAULT); 61107c478bd9Sstevel@tonic-gate } 61117c478bd9Sstevel@tonic-gate 61127c478bd9Sstevel@tonic-gate bzero(&unwrapping_key, sizeof (unwrapping_key)); 61137c478bd9Sstevel@tonic-gate 61147c478bd9Sstevel@tonic-gate session_id = STRUCT_FGET(unwrap_key, uk_session); 61157c478bd9Sstevel@tonic-gate 61167c478bd9Sstevel@tonic-gate if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 61177c478bd9Sstevel@tonic-gate goto release_minor; 61187c478bd9Sstevel@tonic-gate } 61197c478bd9Sstevel@tonic-gate 6120894b2776Smcpowers bcopy(STRUCT_FADDR(unwrap_key, uk_mechanism), &mech.cm_type, 6121894b2776Smcpowers sizeof (crypto_mech_type_t)); 6122894b2776Smcpowers 6123436935a1SVladimir Kotal /* We need the key length for provider selection so copy it in now. */ 6124436935a1SVladimir Kotal if (!copyin_key(mode, sp, STRUCT_FADDR(unwrap_key, uk_unwrapping_key), 6125436935a1SVladimir Kotal &unwrapping_key, &unwrapping_key_rctl_bytes, 6126436935a1SVladimir Kotal &unwrapping_key_rctl_chk, &rv, &error)) { 6127436935a1SVladimir Kotal goto release_minor; 6128436935a1SVladimir Kotal } 6129436935a1SVladimir Kotal 6130436935a1SVladimir Kotal if ((rv = kcf_get_hardware_provider(mech.cm_type, &unwrapping_key, 61319b009fc1SValerie Bubb Fenwick CRYPTO_MECH_INVALID, NULL, sp->sd_provider, 6132436935a1SVladimir Kotal &real_provider, CRYPTO_FG_UNWRAP)) != CRYPTO_SUCCESS) { 61337c478bd9Sstevel@tonic-gate goto release_minor; 61347c478bd9Sstevel@tonic-gate } 61357c478bd9Sstevel@tonic-gate 6136894b2776Smcpowers rv = crypto_provider_copyin_mech_param(real_provider, 6137894b2776Smcpowers STRUCT_FADDR(unwrap_key, uk_mechanism), &mech, mode, &error); 6138894b2776Smcpowers 6139894b2776Smcpowers if (rv == CRYPTO_NOT_SUPPORTED) { 6140894b2776Smcpowers allocated_by_crypto_module = B_TRUE; 61412d794da1Skrishna if (!copyin_mech(mode, sp, 61422d794da1Skrishna STRUCT_FADDR(unwrap_key, uk_mechanism), 61432d794da1Skrishna &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) { 6144894b2776Smcpowers goto release_minor; 6145894b2776Smcpowers } 6146894b2776Smcpowers } else { 6147894b2776Smcpowers if (rv != CRYPTO_SUCCESS) 61487c478bd9Sstevel@tonic-gate goto release_minor; 61497c478bd9Sstevel@tonic-gate } 61507c478bd9Sstevel@tonic-gate 61517c478bd9Sstevel@tonic-gate count = STRUCT_FGET(unwrap_key, uk_count); 61527c478bd9Sstevel@tonic-gate uk_attributes = STRUCT_FGETP(unwrap_key, uk_attributes); 61532d794da1Skrishna if (!copyin_attributes(mode, sp, count, uk_attributes, &k_attrs, 61542d794da1Skrishna &k_attrs_size, NULL, &rv, &error, &k_attrs_rctl_bytes, 61552d794da1Skrishna &k_attrs_rctl_chk, B_TRUE)) { 61567c478bd9Sstevel@tonic-gate goto release_minor; 61577c478bd9Sstevel@tonic-gate } 61587c478bd9Sstevel@tonic-gate 61597c478bd9Sstevel@tonic-gate wrapped_key_len = STRUCT_FGET(unwrap_key, uk_wrapped_key_len); 61607c478bd9Sstevel@tonic-gate if (wrapped_key_len > crypto_max_buffer_len) { 61617c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "object_unwrap_key: buffer greater than %ld " 61627c478bd9Sstevel@tonic-gate "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid); 61637c478bd9Sstevel@tonic-gate rv = CRYPTO_ARGUMENTS_BAD; 61647c478bd9Sstevel@tonic-gate goto release_minor; 61657c478bd9Sstevel@tonic-gate } 61667c478bd9Sstevel@tonic-gate 61672d794da1Skrishna if ((rv = CRYPTO_BUFFER_CHECK(sp, wrapped_key_len, 61682d794da1Skrishna wrapped_key_rctl_chk)) != CRYPTO_SUCCESS) { 61697c478bd9Sstevel@tonic-gate goto release_minor; 61707c478bd9Sstevel@tonic-gate } 61717c478bd9Sstevel@tonic-gate wrapped_key_rctl_bytes = wrapped_key_len; 61727c478bd9Sstevel@tonic-gate wrapped_key = kmem_alloc(wrapped_key_len, KM_SLEEP); 61737c478bd9Sstevel@tonic-gate 61747c478bd9Sstevel@tonic-gate if (wrapped_key_len != 0 && copyin(STRUCT_FGETP(unwrap_key, 61757c478bd9Sstevel@tonic-gate uk_wrapped_key), wrapped_key, wrapped_key_len) != 0) { 61767c478bd9Sstevel@tonic-gate error = EFAULT; 61777c478bd9Sstevel@tonic-gate goto release_minor; 61787c478bd9Sstevel@tonic-gate } 61797c478bd9Sstevel@tonic-gate 61807c478bd9Sstevel@tonic-gate /* wrapped_key_len is not modified by the unwrap operation */ 61817c478bd9Sstevel@tonic-gate KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_UNWRAP, 61827c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, &mech, k_attrs, count, &handle, 61837c478bd9Sstevel@tonic-gate NULL, 0, NULL, &unwrapping_key, wrapped_key, &wrapped_key_len); 61847c478bd9Sstevel@tonic-gate 61857c478bd9Sstevel@tonic-gate rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 61867c478bd9Sstevel@tonic-gate 61877c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) 61887c478bd9Sstevel@tonic-gate STRUCT_FSET(unwrap_key, uk_object_handle, handle); 61897c478bd9Sstevel@tonic-gate 61907c478bd9Sstevel@tonic-gate release_minor: 61912d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk); 61922d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, unwrapping_key_rctl_bytes, 61932d794da1Skrishna unwrapping_key_rctl_chk); 61942d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, wrapped_key_rctl_bytes, 61952d794da1Skrishna wrapped_key_rctl_chk); 61962d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, k_attrs_rctl_bytes, 61972d794da1Skrishna k_attrs_rctl_chk); 61987c478bd9Sstevel@tonic-gate 61997c478bd9Sstevel@tonic-gate if (k_attrs != NULL) 62007c478bd9Sstevel@tonic-gate kmem_free(k_attrs, k_attrs_size); 62017c478bd9Sstevel@tonic-gate 62027c478bd9Sstevel@tonic-gate if (wrapped_key != NULL) 62037c478bd9Sstevel@tonic-gate kmem_free(wrapped_key, wrapped_key_len); 62047c478bd9Sstevel@tonic-gate 62057c478bd9Sstevel@tonic-gate free_crypto_key(&unwrapping_key); 62067c478bd9Sstevel@tonic-gate 62077c478bd9Sstevel@tonic-gate if (error != 0) 62087c478bd9Sstevel@tonic-gate goto out; 62097c478bd9Sstevel@tonic-gate 62107c478bd9Sstevel@tonic-gate STRUCT_FSET(unwrap_key, uk_return_value, rv); 62117c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(unwrap_key), arg, 62127c478bd9Sstevel@tonic-gate STRUCT_SIZE(unwrap_key)) != 0) { 62137c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) { 62147c478bd9Sstevel@tonic-gate KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, 62157c478bd9Sstevel@tonic-gate KCF_OP_OBJECT_DESTROY, 62167c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, handle, 62177c478bd9Sstevel@tonic-gate NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 62187c478bd9Sstevel@tonic-gate 62197c478bd9Sstevel@tonic-gate (void) kcf_submit_request(real_provider, NULL, 62207c478bd9Sstevel@tonic-gate NULL, ¶ms, B_FALSE); 62217c478bd9Sstevel@tonic-gate 62227c478bd9Sstevel@tonic-gate error = EFAULT; 62237c478bd9Sstevel@tonic-gate } 62247c478bd9Sstevel@tonic-gate } 62257c478bd9Sstevel@tonic-gate out: 62267c478bd9Sstevel@tonic-gate CRYPTO_SESSION_RELE(sp); 62277c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 6228894b2776Smcpowers 6229894b2776Smcpowers if (real_provider != NULL) { 6230894b2776Smcpowers crypto_free_mech(real_provider, 6231894b2776Smcpowers allocated_by_crypto_module, &mech); 6232894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 6233894b2776Smcpowers } 6234894b2776Smcpowers 62357c478bd9Sstevel@tonic-gate return (error); 62367c478bd9Sstevel@tonic-gate } 62377c478bd9Sstevel@tonic-gate 62387c478bd9Sstevel@tonic-gate /* ARGSUSED */ 62397c478bd9Sstevel@tonic-gate static int 62407c478bd9Sstevel@tonic-gate object_derive_key(dev_t dev, caddr_t arg, int mode, int *rval) 62417c478bd9Sstevel@tonic-gate { 62427c478bd9Sstevel@tonic-gate STRUCT_DECL(crypto_derive_key, derive_key); 6243894b2776Smcpowers kcf_provider_desc_t *real_provider = NULL; 62447c478bd9Sstevel@tonic-gate kcf_req_params_t params; 62457c478bd9Sstevel@tonic-gate crypto_object_attribute_t *k_attrs = NULL; 62467c478bd9Sstevel@tonic-gate crypto_mechanism_t mech; 62477c478bd9Sstevel@tonic-gate crypto_key_t base_key; 62487c478bd9Sstevel@tonic-gate crypto_session_id_t session_id; 62497c478bd9Sstevel@tonic-gate crypto_minor_t *cm; 62507c478bd9Sstevel@tonic-gate crypto_session_data_t *sp = NULL; 62517c478bd9Sstevel@tonic-gate crypto_object_id_t handle; 62527c478bd9Sstevel@tonic-gate size_t k_attrs_size; 62537c478bd9Sstevel@tonic-gate size_t key_rctl_bytes = 0, mech_rctl_bytes = 0; 62542d794da1Skrishna boolean_t mech_rctl_chk = B_FALSE; 62552d794da1Skrishna boolean_t key_rctl_chk = B_FALSE; 62567c478bd9Sstevel@tonic-gate size_t attributes_rctl_bytes = 0; 62572d794da1Skrishna boolean_t attributes_rctl_chk = B_FALSE; 62587c478bd9Sstevel@tonic-gate caddr_t attributes; 62597c478bd9Sstevel@tonic-gate uint_t count; 62607c478bd9Sstevel@tonic-gate int error = 0; 62617c478bd9Sstevel@tonic-gate int rv; 6262894b2776Smcpowers boolean_t allocated_by_crypto_module = B_FALSE; 6263894b2776Smcpowers boolean_t please_destroy_object = B_FALSE; 62647c478bd9Sstevel@tonic-gate 62657c478bd9Sstevel@tonic-gate STRUCT_INIT(derive_key, mode); 62667c478bd9Sstevel@tonic-gate 62677c478bd9Sstevel@tonic-gate if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 62687c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "object_derive_key: failed holding minor"); 62697c478bd9Sstevel@tonic-gate return (ENXIO); 62707c478bd9Sstevel@tonic-gate } 62717c478bd9Sstevel@tonic-gate 62727c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(derive_key), STRUCT_SIZE(derive_key)) != 0) { 62737c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 62747c478bd9Sstevel@tonic-gate return (EFAULT); 62757c478bd9Sstevel@tonic-gate } 62767c478bd9Sstevel@tonic-gate 62777c478bd9Sstevel@tonic-gate bzero(&base_key, sizeof (base_key)); 62787c478bd9Sstevel@tonic-gate 62797c478bd9Sstevel@tonic-gate session_id = STRUCT_FGET(derive_key, dk_session); 62807c478bd9Sstevel@tonic-gate 62817c478bd9Sstevel@tonic-gate if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 62827c478bd9Sstevel@tonic-gate goto release_minor; 62837c478bd9Sstevel@tonic-gate } 62847c478bd9Sstevel@tonic-gate 6285894b2776Smcpowers bcopy(STRUCT_FADDR(derive_key, dk_mechanism), &mech.cm_type, 6286894b2776Smcpowers sizeof (crypto_mech_type_t)); 6287894b2776Smcpowers 6288436935a1SVladimir Kotal /* We need the key length for provider selection so copy it in now. */ 6289436935a1SVladimir Kotal if (!copyin_key(mode, sp, STRUCT_FADDR(derive_key, dk_base_key), 6290436935a1SVladimir Kotal &base_key, &key_rctl_bytes, &key_rctl_chk, &rv, &error)) { 6291436935a1SVladimir Kotal goto release_minor; 6292436935a1SVladimir Kotal } 6293436935a1SVladimir Kotal 6294436935a1SVladimir Kotal if ((rv = kcf_get_hardware_provider(mech.cm_type, &base_key, 62959b009fc1SValerie Bubb Fenwick CRYPTO_MECH_INVALID, NULL, sp->sd_provider, 6296436935a1SVladimir Kotal &real_provider, CRYPTO_FG_DERIVE)) != CRYPTO_SUCCESS) { 62977c478bd9Sstevel@tonic-gate goto release_minor; 62987c478bd9Sstevel@tonic-gate } 62997c478bd9Sstevel@tonic-gate 6300894b2776Smcpowers rv = crypto_provider_copyin_mech_param(real_provider, 6301894b2776Smcpowers STRUCT_FADDR(derive_key, dk_mechanism), &mech, mode, &error); 6302894b2776Smcpowers 6303894b2776Smcpowers if (rv == CRYPTO_NOT_SUPPORTED) { 6304894b2776Smcpowers allocated_by_crypto_module = B_TRUE; 63052d794da1Skrishna if (!copyin_mech(mode, sp, 63062d794da1Skrishna STRUCT_FADDR(derive_key, dk_mechanism), 63072d794da1Skrishna &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) { 6308894b2776Smcpowers goto release_minor; 6309894b2776Smcpowers } 6310894b2776Smcpowers } else { 6311894b2776Smcpowers if (rv != CRYPTO_SUCCESS) 63127c478bd9Sstevel@tonic-gate goto release_minor; 63137c478bd9Sstevel@tonic-gate } 63147c478bd9Sstevel@tonic-gate 63157c478bd9Sstevel@tonic-gate count = STRUCT_FGET(derive_key, dk_count); 63167c478bd9Sstevel@tonic-gate 63177c478bd9Sstevel@tonic-gate attributes = STRUCT_FGETP(derive_key, dk_attributes); 63182d794da1Skrishna if (!copyin_attributes(mode, sp, count, attributes, &k_attrs, 6319c1a9a9c3Skrishna &k_attrs_size, NULL, &rv, &error, 63202d794da1Skrishna &attributes_rctl_bytes, &attributes_rctl_chk, B_TRUE)) { 63217c478bd9Sstevel@tonic-gate goto release_minor; 63227c478bd9Sstevel@tonic-gate } 63237c478bd9Sstevel@tonic-gate 63247c478bd9Sstevel@tonic-gate KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_DERIVE, 63257c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, &mech, k_attrs, count, 63267c478bd9Sstevel@tonic-gate &handle, NULL, 0, NULL, &base_key, NULL, NULL); 63277c478bd9Sstevel@tonic-gate 63287c478bd9Sstevel@tonic-gate rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 63297c478bd9Sstevel@tonic-gate 6330894b2776Smcpowers if (rv == CRYPTO_SUCCESS) { 63317c478bd9Sstevel@tonic-gate STRUCT_FSET(derive_key, dk_object_handle, handle); 63327c478bd9Sstevel@tonic-gate 6333894b2776Smcpowers rv = crypto_provider_copyout_mech_param(real_provider, 6334894b2776Smcpowers &mech, STRUCT_FADDR(derive_key, dk_mechanism), 6335894b2776Smcpowers mode, &error); 6336894b2776Smcpowers 6337894b2776Smcpowers if (rv == CRYPTO_NOT_SUPPORTED) { 6338894b2776Smcpowers rv = CRYPTO_SUCCESS; 6339894b2776Smcpowers goto release_minor; 6340894b2776Smcpowers } 6341894b2776Smcpowers 6342894b2776Smcpowers if (rv != CRYPTO_SUCCESS) 6343894b2776Smcpowers please_destroy_object = B_TRUE; 6344894b2776Smcpowers } 6345894b2776Smcpowers 63467c478bd9Sstevel@tonic-gate release_minor: 63472d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk); 63482d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk); 63492d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, attributes_rctl_bytes, 63502d794da1Skrishna attributes_rctl_chk); 63517c478bd9Sstevel@tonic-gate 63527c478bd9Sstevel@tonic-gate if (k_attrs != NULL) 63537c478bd9Sstevel@tonic-gate kmem_free(k_attrs, k_attrs_size); 63547c478bd9Sstevel@tonic-gate 63557c478bd9Sstevel@tonic-gate free_crypto_key(&base_key); 63567c478bd9Sstevel@tonic-gate 63577c478bd9Sstevel@tonic-gate if (error != 0) 63587c478bd9Sstevel@tonic-gate goto out; 63597c478bd9Sstevel@tonic-gate 63607c478bd9Sstevel@tonic-gate STRUCT_FSET(derive_key, dk_return_value, rv); 63617c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(derive_key), arg, 63627c478bd9Sstevel@tonic-gate STRUCT_SIZE(derive_key)) != 0) { 63637c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) { 6364894b2776Smcpowers please_destroy_object = B_TRUE; 6365894b2776Smcpowers error = EFAULT; 6366894b2776Smcpowers } 6367894b2776Smcpowers } 6368894b2776Smcpowers out: 6369894b2776Smcpowers if (please_destroy_object) { 6370894b2776Smcpowers KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_DESTROY, 63717c478bd9Sstevel@tonic-gate sp->sd_provider_session->ps_session, handle, 63727c478bd9Sstevel@tonic-gate NULL, 0, NULL, 0, NULL, NULL, 0, NULL); 63737c478bd9Sstevel@tonic-gate 63747c478bd9Sstevel@tonic-gate (void) kcf_submit_request(real_provider, NULL, 63757c478bd9Sstevel@tonic-gate NULL, ¶ms, B_FALSE); 6376894b2776Smcpowers } 63777c478bd9Sstevel@tonic-gate 63787c478bd9Sstevel@tonic-gate CRYPTO_SESSION_RELE(sp); 63797c478bd9Sstevel@tonic-gate crypto_release_minor(cm); 6380894b2776Smcpowers 6381894b2776Smcpowers if (real_provider != NULL) { 6382894b2776Smcpowers crypto_free_mech(real_provider, 6383894b2776Smcpowers allocated_by_crypto_module, &mech); 6384894b2776Smcpowers KCF_PROV_REFRELE(real_provider); 6385894b2776Smcpowers } 63867c478bd9Sstevel@tonic-gate return (error); 63877c478bd9Sstevel@tonic-gate } 63887c478bd9Sstevel@tonic-gate 63897c478bd9Sstevel@tonic-gate /* ARGSUSED */ 63907c478bd9Sstevel@tonic-gate static int 6391034448feSmcpowers nostore_derive_key(dev_t dev, caddr_t arg, int mode, int *rval) 6392034448feSmcpowers { 6393034448feSmcpowers STRUCT_DECL(crypto_nostore_derive_key, derive_key); 639495014fbbSDan OpenSolaris Anderson #ifdef _LP64 639595014fbbSDan OpenSolaris Anderson STRUCT_DECL(crypto_object_attribute, oa); 639695014fbbSDan OpenSolaris Anderson #else 6397034448feSmcpowers /* LINTED E_FUNC_SET_NOT_USED */ 6398034448feSmcpowers STRUCT_DECL(crypto_object_attribute, oa); 639995014fbbSDan OpenSolaris Anderson #endif 6400034448feSmcpowers kcf_provider_desc_t *real_provider = NULL; 6401034448feSmcpowers kcf_req_params_t params; 6402034448feSmcpowers crypto_object_attribute_t *k_in_attrs = NULL; 6403034448feSmcpowers crypto_object_attribute_t *k_out_attrs = NULL; 6404034448feSmcpowers crypto_mechanism_t mech; 6405034448feSmcpowers crypto_key_t base_key; 6406034448feSmcpowers crypto_session_id_t session_id; 6407034448feSmcpowers crypto_minor_t *cm; 6408034448feSmcpowers crypto_session_data_t *sp = NULL; 6409034448feSmcpowers size_t k_in_attrs_size, k_out_attrs_size; 6410034448feSmcpowers size_t key_rctl_bytes = 0, mech_rctl_bytes = 0; 64112d794da1Skrishna boolean_t mech_rctl_chk = B_FALSE; 64122d794da1Skrishna boolean_t key_rctl_chk = B_FALSE; 6413034448feSmcpowers size_t in_attributes_rctl_bytes = 0; 6414034448feSmcpowers size_t out_attributes_rctl_bytes = 0; 64152d794da1Skrishna boolean_t in_attributes_rctl_chk = B_FALSE; 64162d794da1Skrishna boolean_t out_attributes_rctl_chk = B_FALSE; 6417034448feSmcpowers caddr_t in_attributes, out_attributes; 6418034448feSmcpowers uint_t in_count, out_count; 6419034448feSmcpowers int error = 0; 6420034448feSmcpowers int rv; 6421034448feSmcpowers boolean_t allocated_by_crypto_module = B_FALSE; 6422034448feSmcpowers caddr_t u_attrs = NULL; 6423034448feSmcpowers 6424034448feSmcpowers STRUCT_INIT(derive_key, mode); 6425034448feSmcpowers STRUCT_INIT(oa, mode); 6426034448feSmcpowers 6427034448feSmcpowers if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 6428034448feSmcpowers cmn_err(CE_WARN, "nostore_derive_key: failed holding minor"); 6429034448feSmcpowers return (ENXIO); 6430034448feSmcpowers } 6431034448feSmcpowers 6432034448feSmcpowers if (copyin(arg, STRUCT_BUF(derive_key), STRUCT_SIZE(derive_key)) != 0) { 6433034448feSmcpowers crypto_release_minor(cm); 6434034448feSmcpowers return (EFAULT); 6435034448feSmcpowers } 6436034448feSmcpowers 6437034448feSmcpowers bzero(&base_key, sizeof (base_key)); 6438034448feSmcpowers 6439034448feSmcpowers session_id = STRUCT_FGET(derive_key, ndk_session); 6440034448feSmcpowers 6441034448feSmcpowers if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 6442034448feSmcpowers goto release_minor; 6443034448feSmcpowers } 6444034448feSmcpowers 6445034448feSmcpowers bcopy(STRUCT_FADDR(derive_key, ndk_mechanism), &mech.cm_type, 6446034448feSmcpowers sizeof (crypto_mech_type_t)); 6447034448feSmcpowers 6448436935a1SVladimir Kotal /* We need the key length for provider selection so copy it in now. */ 6449436935a1SVladimir Kotal if (!copyin_key(mode, sp, STRUCT_FADDR(derive_key, ndk_base_key), 6450436935a1SVladimir Kotal &base_key, &key_rctl_bytes, &key_rctl_chk, &rv, &error)) { 6451436935a1SVladimir Kotal goto release_minor; 6452436935a1SVladimir Kotal } 6453436935a1SVladimir Kotal 6454436935a1SVladimir Kotal if ((rv = kcf_get_hardware_provider(mech.cm_type, &base_key, 64559b009fc1SValerie Bubb Fenwick CRYPTO_MECH_INVALID, NULL, sp->sd_provider, 6456436935a1SVladimir Kotal &real_provider, CRYPTO_FG_DERIVE)) != CRYPTO_SUCCESS) { 6457034448feSmcpowers goto release_minor; 6458034448feSmcpowers } 6459034448feSmcpowers 6460034448feSmcpowers rv = crypto_provider_copyin_mech_param(real_provider, 6461034448feSmcpowers STRUCT_FADDR(derive_key, ndk_mechanism), &mech, mode, &error); 6462034448feSmcpowers 6463034448feSmcpowers if (rv == CRYPTO_NOT_SUPPORTED) { 6464034448feSmcpowers allocated_by_crypto_module = B_TRUE; 64652d794da1Skrishna if (!copyin_mech(mode, sp, 64662d794da1Skrishna STRUCT_FADDR(derive_key, ndk_mechanism), 64672d794da1Skrishna &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) { 6468034448feSmcpowers goto release_minor; 6469034448feSmcpowers } 6470034448feSmcpowers } else { 6471034448feSmcpowers if (rv != CRYPTO_SUCCESS) 6472034448feSmcpowers goto release_minor; 6473034448feSmcpowers } 6474034448feSmcpowers 6475034448feSmcpowers in_count = STRUCT_FGET(derive_key, ndk_in_count); 6476034448feSmcpowers out_count = STRUCT_FGET(derive_key, ndk_out_count); 6477034448feSmcpowers 6478034448feSmcpowers in_attributes = STRUCT_FGETP(derive_key, ndk_in_attributes); 64792d794da1Skrishna if (!copyin_attributes(mode, sp, in_count, in_attributes, &k_in_attrs, 6480034448feSmcpowers &k_in_attrs_size, NULL, &rv, &error, &in_attributes_rctl_bytes, 64812d794da1Skrishna &in_attributes_rctl_chk, B_TRUE)) { 6482034448feSmcpowers goto release_minor; 6483034448feSmcpowers } 6484034448feSmcpowers 6485034448feSmcpowers out_attributes = STRUCT_FGETP(derive_key, ndk_out_attributes); 64862d794da1Skrishna if (!copyin_attributes(mode, sp, out_count, out_attributes, 64872d794da1Skrishna &k_out_attrs, &k_out_attrs_size, &u_attrs, &rv, &error, 64882d794da1Skrishna &out_attributes_rctl_bytes, 64892d794da1Skrishna &out_attributes_rctl_chk, B_FALSE)) { 6490034448feSmcpowers goto release_minor; 6491034448feSmcpowers } 6492034448feSmcpowers 6493034448feSmcpowers KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_DERIVE, 6494034448feSmcpowers sp->sd_provider_session->ps_session, &mech, k_in_attrs, in_count, 6495034448feSmcpowers NULL, 0, &base_key, k_out_attrs, out_count, NULL, 0); 6496034448feSmcpowers 6497034448feSmcpowers rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); 6498034448feSmcpowers 6499034448feSmcpowers if (rv == CRYPTO_SUCCESS) { 6500034448feSmcpowers rv = crypto_provider_copyout_mech_param(real_provider, 6501034448feSmcpowers &mech, STRUCT_FADDR(derive_key, ndk_mechanism), 6502034448feSmcpowers mode, &error); 6503034448feSmcpowers 6504034448feSmcpowers if (rv == CRYPTO_NOT_SUPPORTED) { 6505034448feSmcpowers rv = CRYPTO_SUCCESS; 6506034448feSmcpowers } 6507034448feSmcpowers /* copyout the derived secret */ 6508034448feSmcpowers if (copyout_attributes(mode, out_attributes, out_count, 6509034448feSmcpowers k_out_attrs, u_attrs) != 0) 6510034448feSmcpowers error = EFAULT; 6511034448feSmcpowers } 6512034448feSmcpowers 6513034448feSmcpowers release_minor: 65142d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk); 65152d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk); 65162d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, in_attributes_rctl_bytes, 65172d794da1Skrishna in_attributes_rctl_chk); 65182d794da1Skrishna CRYPTO_DECREMENT_RCTL_SESSION(sp, out_attributes_rctl_bytes, 65192d794da1Skrishna out_attributes_rctl_chk); 6520034448feSmcpowers 6521034448feSmcpowers if (k_in_attrs != NULL) 6522034448feSmcpowers kmem_free(k_in_attrs, k_in_attrs_size); 6523034448feSmcpowers if (k_out_attrs != NULL) { 6524034448feSmcpowers bzero(k_out_attrs, k_out_attrs_size); 6525034448feSmcpowers kmem_free(k_out_attrs, k_out_attrs_size); 6526034448feSmcpowers } 6527034448feSmcpowers 6528034448feSmcpowers if (u_attrs != NULL) 6529034448feSmcpowers kmem_free(u_attrs, out_count * STRUCT_SIZE(oa)); 6530034448feSmcpowers 6531034448feSmcpowers free_crypto_key(&base_key); 6532034448feSmcpowers 6533034448feSmcpowers if (error != 0) 6534034448feSmcpowers goto out; 6535034448feSmcpowers 6536034448feSmcpowers STRUCT_FSET(derive_key, ndk_return_value, rv); 6537034448feSmcpowers if (copyout(STRUCT_BUF(derive_key), arg, 6538034448feSmcpowers STRUCT_SIZE(derive_key)) != 0) { 6539034448feSmcpowers error = EFAULT; 6540034448feSmcpowers } 6541034448feSmcpowers out: 6542034448feSmcpowers CRYPTO_SESSION_RELE(sp); 6543034448feSmcpowers crypto_release_minor(cm); 6544034448feSmcpowers 6545034448feSmcpowers if (real_provider != NULL) { 6546034448feSmcpowers crypto_free_mech(real_provider, 6547034448feSmcpowers allocated_by_crypto_module, &mech); 6548034448feSmcpowers KCF_PROV_REFRELE(real_provider); 6549034448feSmcpowers } 6550034448feSmcpowers return (error); 6551034448feSmcpowers } 6552034448feSmcpowers 6553034448feSmcpowers /* ARGSUSED */ 6554034448feSmcpowers static int 65557c478bd9Sstevel@tonic-gate crypto_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c, 65567c478bd9Sstevel@tonic-gate int *rval) 65577c478bd9Sstevel@tonic-gate { 65587c478bd9Sstevel@tonic-gate #define ARG ((caddr_t)arg) 65597c478bd9Sstevel@tonic-gate 65607c478bd9Sstevel@tonic-gate switch (cmd) { 65617c478bd9Sstevel@tonic-gate case CRYPTO_GET_FUNCTION_LIST: 65627c478bd9Sstevel@tonic-gate return (get_function_list(dev, ARG, mode, rval)); 65637c478bd9Sstevel@tonic-gate 65647c478bd9Sstevel@tonic-gate case CRYPTO_GET_MECHANISM_NUMBER: 65657c478bd9Sstevel@tonic-gate return (get_mechanism_number(dev, ARG, mode, rval)); 65667c478bd9Sstevel@tonic-gate 65677d82f0f8SDina K Nimeh case CRYPTO_GET_MECHANISM_LIST: 65687d82f0f8SDina K Nimeh return (get_mechanism_list(dev, ARG, mode, rval)); 65697d82f0f8SDina K Nimeh 65707d82f0f8SDina K Nimeh case CRYPTO_GET_ALL_MECHANISM_INFO: 65717d82f0f8SDina K Nimeh return (get_all_mechanism_info(dev, ARG, mode, rval)); 65727d82f0f8SDina K Nimeh 65737c478bd9Sstevel@tonic-gate case CRYPTO_GET_PROVIDER_LIST: 65747c478bd9Sstevel@tonic-gate return (get_provider_list(dev, ARG, mode, rval)); 65757c478bd9Sstevel@tonic-gate 65767c478bd9Sstevel@tonic-gate case CRYPTO_GET_PROVIDER_INFO: 65777c478bd9Sstevel@tonic-gate return (get_provider_info(dev, ARG, mode, rval)); 65787c478bd9Sstevel@tonic-gate 65797c478bd9Sstevel@tonic-gate case CRYPTO_GET_PROVIDER_MECHANISMS: 65807c478bd9Sstevel@tonic-gate return (get_provider_mechanisms(dev, ARG, mode, rval)); 65817c478bd9Sstevel@tonic-gate 65827c478bd9Sstevel@tonic-gate case CRYPTO_GET_PROVIDER_MECHANISM_INFO: 65837c478bd9Sstevel@tonic-gate return (get_provider_mechanism_info(dev, ARG, mode, rval)); 65847c478bd9Sstevel@tonic-gate 65857c478bd9Sstevel@tonic-gate case CRYPTO_OPEN_SESSION: 65867c478bd9Sstevel@tonic-gate return (open_session(dev, ARG, mode, rval)); 65877c478bd9Sstevel@tonic-gate 65887c478bd9Sstevel@tonic-gate case CRYPTO_CLOSE_SESSION: 65897c478bd9Sstevel@tonic-gate return (close_session(dev, ARG, mode, rval)); 65907c478bd9Sstevel@tonic-gate 65917c478bd9Sstevel@tonic-gate case CRYPTO_ENCRYPT_INIT: 65927c478bd9Sstevel@tonic-gate return (encrypt_init(dev, ARG, mode, rval)); 65937c478bd9Sstevel@tonic-gate 65947c478bd9Sstevel@tonic-gate case CRYPTO_DECRYPT_INIT: 65957c478bd9Sstevel@tonic-gate return (decrypt_init(dev, ARG, mode, rval)); 65967c478bd9Sstevel@tonic-gate 65977c478bd9Sstevel@tonic-gate case CRYPTO_ENCRYPT: 65987c478bd9Sstevel@tonic-gate return (encrypt(dev, ARG, mode, rval)); 65997c478bd9Sstevel@tonic-gate 66007c478bd9Sstevel@tonic-gate case CRYPTO_DECRYPT: 66017c478bd9Sstevel@tonic-gate return (decrypt(dev, ARG, mode, rval)); 66027c478bd9Sstevel@tonic-gate 66037c478bd9Sstevel@tonic-gate case CRYPTO_ENCRYPT_UPDATE: 66047c478bd9Sstevel@tonic-gate return (encrypt_update(dev, ARG, mode, rval)); 66057c478bd9Sstevel@tonic-gate 66067c478bd9Sstevel@tonic-gate case CRYPTO_DECRYPT_UPDATE: 66077c478bd9Sstevel@tonic-gate return (decrypt_update(dev, ARG, mode, rval)); 66087c478bd9Sstevel@tonic-gate 66097c478bd9Sstevel@tonic-gate case CRYPTO_ENCRYPT_FINAL: 66107c478bd9Sstevel@tonic-gate return (encrypt_final(dev, ARG, mode, rval)); 66117c478bd9Sstevel@tonic-gate 66127c478bd9Sstevel@tonic-gate case CRYPTO_DECRYPT_FINAL: 66137c478bd9Sstevel@tonic-gate return (decrypt_final(dev, ARG, mode, rval)); 66147c478bd9Sstevel@tonic-gate 66157c478bd9Sstevel@tonic-gate case CRYPTO_DIGEST_INIT: 66167c478bd9Sstevel@tonic-gate return (digest_init(dev, ARG, mode, rval)); 66177c478bd9Sstevel@tonic-gate 66187c478bd9Sstevel@tonic-gate case CRYPTO_DIGEST: 66197c478bd9Sstevel@tonic-gate return (digest(dev, ARG, mode, rval)); 66207c478bd9Sstevel@tonic-gate 66217c478bd9Sstevel@tonic-gate case CRYPTO_DIGEST_UPDATE: 66227c478bd9Sstevel@tonic-gate return (digest_update(dev, ARG, mode, rval)); 66237c478bd9Sstevel@tonic-gate 66247c478bd9Sstevel@tonic-gate case CRYPTO_DIGEST_KEY: 66257c478bd9Sstevel@tonic-gate return (digest_key(dev, ARG, mode, rval)); 66267c478bd9Sstevel@tonic-gate 66277c478bd9Sstevel@tonic-gate case CRYPTO_DIGEST_FINAL: 66287c478bd9Sstevel@tonic-gate return (digest_final(dev, ARG, mode, rval)); 66297c478bd9Sstevel@tonic-gate 66307c478bd9Sstevel@tonic-gate case CRYPTO_SIGN_INIT: 66317c478bd9Sstevel@tonic-gate return (sign_init(dev, ARG, mode, rval)); 66327c478bd9Sstevel@tonic-gate 66337c478bd9Sstevel@tonic-gate case CRYPTO_SIGN: 66347c478bd9Sstevel@tonic-gate return (sign(dev, ARG, mode, rval)); 66357c478bd9Sstevel@tonic-gate 66367c478bd9Sstevel@tonic-gate case CRYPTO_SIGN_UPDATE: 66377c478bd9Sstevel@tonic-gate return (sign_update(dev, ARG, mode, rval)); 66387c478bd9Sstevel@tonic-gate 66397c478bd9Sstevel@tonic-gate case CRYPTO_SIGN_FINAL: 66407c478bd9Sstevel@tonic-gate return (sign_final(dev, ARG, mode, rval)); 66417c478bd9Sstevel@tonic-gate 66427c478bd9Sstevel@tonic-gate case CRYPTO_SIGN_RECOVER_INIT: 66437c478bd9Sstevel@tonic-gate return (sign_recover_init(dev, ARG, mode, rval)); 66447c478bd9Sstevel@tonic-gate 66457c478bd9Sstevel@tonic-gate case CRYPTO_SIGN_RECOVER: 66467c478bd9Sstevel@tonic-gate return (sign_recover(dev, ARG, mode, rval)); 66477c478bd9Sstevel@tonic-gate 66487c478bd9Sstevel@tonic-gate case CRYPTO_VERIFY_INIT: 66497c478bd9Sstevel@tonic-gate return (verify_init(dev, ARG, mode, rval)); 66507c478bd9Sstevel@tonic-gate 66517c478bd9Sstevel@tonic-gate case CRYPTO_VERIFY: 66527c478bd9Sstevel@tonic-gate return (verify(dev, ARG, mode, rval)); 66537c478bd9Sstevel@tonic-gate 66547c478bd9Sstevel@tonic-gate case CRYPTO_VERIFY_UPDATE: 66557c478bd9Sstevel@tonic-gate return (verify_update(dev, ARG, mode, rval)); 66567c478bd9Sstevel@tonic-gate 66577c478bd9Sstevel@tonic-gate case CRYPTO_VERIFY_FINAL: 66587c478bd9Sstevel@tonic-gate return (verify_final(dev, ARG, mode, rval)); 66597c478bd9Sstevel@tonic-gate 66607c478bd9Sstevel@tonic-gate case CRYPTO_VERIFY_RECOVER_INIT: 66617c478bd9Sstevel@tonic-gate return (verify_recover_init(dev, ARG, mode, rval)); 66627c478bd9Sstevel@tonic-gate 66637c478bd9Sstevel@tonic-gate case CRYPTO_VERIFY_RECOVER: 66647c478bd9Sstevel@tonic-gate return (verify_recover(dev, ARG, mode, rval)); 66657c478bd9Sstevel@tonic-gate 66667c478bd9Sstevel@tonic-gate case CRYPTO_SET_PIN: 66677c478bd9Sstevel@tonic-gate return (set_pin(dev, ARG, mode, rval)); 66687c478bd9Sstevel@tonic-gate 66697c478bd9Sstevel@tonic-gate case CRYPTO_LOGIN: 66707c478bd9Sstevel@tonic-gate return (login(dev, ARG, mode, rval)); 66717c478bd9Sstevel@tonic-gate 66727c478bd9Sstevel@tonic-gate case CRYPTO_LOGOUT: 66737c478bd9Sstevel@tonic-gate return (logout(dev, ARG, mode, rval)); 66747c478bd9Sstevel@tonic-gate 66757c478bd9Sstevel@tonic-gate case CRYPTO_SEED_RANDOM: 66767c478bd9Sstevel@tonic-gate return (seed_random(dev, ARG, mode, rval)); 66777c478bd9Sstevel@tonic-gate 66787c478bd9Sstevel@tonic-gate case CRYPTO_GENERATE_RANDOM: 66797c478bd9Sstevel@tonic-gate return (generate_random(dev, ARG, mode, rval)); 66807c478bd9Sstevel@tonic-gate 66817c478bd9Sstevel@tonic-gate case CRYPTO_OBJECT_CREATE: 66827c478bd9Sstevel@tonic-gate return (object_create(dev, ARG, mode, rval)); 66837c478bd9Sstevel@tonic-gate 66847c478bd9Sstevel@tonic-gate case CRYPTO_OBJECT_COPY: 66857c478bd9Sstevel@tonic-gate return (object_copy(dev, ARG, mode, rval)); 66867c478bd9Sstevel@tonic-gate 66877c478bd9Sstevel@tonic-gate case CRYPTO_OBJECT_DESTROY: 66887c478bd9Sstevel@tonic-gate return (object_destroy(dev, ARG, mode, rval)); 66897c478bd9Sstevel@tonic-gate 66907c478bd9Sstevel@tonic-gate case CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE: 66917c478bd9Sstevel@tonic-gate return (object_get_attribute_value(dev, ARG, mode, rval)); 66927c478bd9Sstevel@tonic-gate 66937c478bd9Sstevel@tonic-gate case CRYPTO_OBJECT_GET_SIZE: 66947c478bd9Sstevel@tonic-gate return (object_get_size(dev, ARG, mode, rval)); 66957c478bd9Sstevel@tonic-gate 66967c478bd9Sstevel@tonic-gate case CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE: 66977c478bd9Sstevel@tonic-gate return (object_set_attribute_value(dev, ARG, mode, rval)); 66987c478bd9Sstevel@tonic-gate 66997c478bd9Sstevel@tonic-gate case CRYPTO_OBJECT_FIND_INIT: 67007c478bd9Sstevel@tonic-gate return (object_find_init(dev, ARG, mode, rval)); 67017c478bd9Sstevel@tonic-gate 67027c478bd9Sstevel@tonic-gate case CRYPTO_OBJECT_FIND_UPDATE: 67037c478bd9Sstevel@tonic-gate return (object_find_update(dev, ARG, mode, rval)); 67047c478bd9Sstevel@tonic-gate 67057c478bd9Sstevel@tonic-gate case CRYPTO_OBJECT_FIND_FINAL: 67067c478bd9Sstevel@tonic-gate return (object_find_final(dev, ARG, mode, rval)); 67077c478bd9Sstevel@tonic-gate 67087c478bd9Sstevel@tonic-gate case CRYPTO_GENERATE_KEY: 67097c478bd9Sstevel@tonic-gate return (object_generate_key(dev, ARG, mode, rval)); 67107c478bd9Sstevel@tonic-gate 67117c478bd9Sstevel@tonic-gate case CRYPTO_GENERATE_KEY_PAIR: 67127c478bd9Sstevel@tonic-gate return (object_generate_key_pair(dev, ARG, mode, rval)); 67137c478bd9Sstevel@tonic-gate 67147c478bd9Sstevel@tonic-gate case CRYPTO_WRAP_KEY: 67157c478bd9Sstevel@tonic-gate return (object_wrap_key(dev, ARG, mode, rval)); 67167c478bd9Sstevel@tonic-gate 67177c478bd9Sstevel@tonic-gate case CRYPTO_UNWRAP_KEY: 67187c478bd9Sstevel@tonic-gate return (object_unwrap_key(dev, ARG, mode, rval)); 67197c478bd9Sstevel@tonic-gate 67207c478bd9Sstevel@tonic-gate case CRYPTO_DERIVE_KEY: 67217c478bd9Sstevel@tonic-gate return (object_derive_key(dev, ARG, mode, rval)); 6722034448feSmcpowers 6723034448feSmcpowers case CRYPTO_NOSTORE_GENERATE_KEY: 6724034448feSmcpowers return (nostore_generate_key(dev, ARG, mode, rval)); 6725034448feSmcpowers 6726034448feSmcpowers case CRYPTO_NOSTORE_GENERATE_KEY_PAIR: 6727034448feSmcpowers return (nostore_generate_key_pair(dev, ARG, mode, rval)); 6728034448feSmcpowers 6729034448feSmcpowers case CRYPTO_NOSTORE_DERIVE_KEY: 6730034448feSmcpowers return (nostore_derive_key(dev, ARG, mode, rval)); 67317c478bd9Sstevel@tonic-gate } 67327c478bd9Sstevel@tonic-gate return (EINVAL); 67337c478bd9Sstevel@tonic-gate } 67347c478bd9Sstevel@tonic-gate 67357c478bd9Sstevel@tonic-gate /* 67367c478bd9Sstevel@tonic-gate * Check for the project.max-crypto-memory resource control. 67377c478bd9Sstevel@tonic-gate */ 67387c478bd9Sstevel@tonic-gate static int 6739c1a9a9c3Skrishna crypto_buffer_check(size_t need) 67407c478bd9Sstevel@tonic-gate { 6741db1cde31Skrishna kproject_t *kpj; 67427c478bd9Sstevel@tonic-gate 67437c478bd9Sstevel@tonic-gate if (need == 0) 67447c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 67457c478bd9Sstevel@tonic-gate 67467c478bd9Sstevel@tonic-gate mutex_enter(&curproc->p_lock); 6747db1cde31Skrishna kpj = curproc->p_task->tk_proj; 6748c1a9a9c3Skrishna mutex_enter(&(kpj->kpj_data.kpd_crypto_lock)); 6749db1cde31Skrishna 6750db1cde31Skrishna if (kpj->kpj_data.kpd_crypto_mem + need > 6751db1cde31Skrishna kpj->kpj_data.kpd_crypto_mem_ctl) { 67527c478bd9Sstevel@tonic-gate if (rctl_test(rc_project_crypto_mem, 6753db1cde31Skrishna kpj->kpj_rctls, curproc, need, 0) & RCT_DENY) { 6754c1a9a9c3Skrishna mutex_exit(&(kpj->kpj_data.kpd_crypto_lock)); 67557c478bd9Sstevel@tonic-gate mutex_exit(&curproc->p_lock); 67567c478bd9Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 67577c478bd9Sstevel@tonic-gate } 6758db1cde31Skrishna } 67597c478bd9Sstevel@tonic-gate 6760db1cde31Skrishna kpj->kpj_data.kpd_crypto_mem += need; 6761c1a9a9c3Skrishna mutex_exit(&(kpj->kpj_data.kpd_crypto_lock)); 67627c478bd9Sstevel@tonic-gate 6763c1a9a9c3Skrishna curproc->p_crypto_mem += need; 67647c478bd9Sstevel@tonic-gate mutex_exit(&curproc->p_lock); 6765db1cde31Skrishna 67667c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 67677c478bd9Sstevel@tonic-gate } 6768