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