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 * This file is part of the core Kernel Cryptographic Framework. 31*0Sstevel@tonic-gate * It implements the SPI functions exported to cryptographic 32*0Sstevel@tonic-gate * providers. 33*0Sstevel@tonic-gate */ 34*0Sstevel@tonic-gate 35*0Sstevel@tonic-gate #include <sys/ksynch.h> 36*0Sstevel@tonic-gate #include <sys/cmn_err.h> 37*0Sstevel@tonic-gate #include <sys/ddi.h> 38*0Sstevel@tonic-gate #include <sys/sunddi.h> 39*0Sstevel@tonic-gate #include <sys/modctl.h> 40*0Sstevel@tonic-gate #include <sys/crypto/common.h> 41*0Sstevel@tonic-gate #include <sys/crypto/impl.h> 42*0Sstevel@tonic-gate #include <sys/crypto/sched_impl.h> 43*0Sstevel@tonic-gate #include <sys/crypto/spi.h> 44*0Sstevel@tonic-gate #include <sys/taskq.h> 45*0Sstevel@tonic-gate #include <sys/disp.h> 46*0Sstevel@tonic-gate #include <sys/kstat.h> 47*0Sstevel@tonic-gate #include <sys/policy.h> 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate /* 50*0Sstevel@tonic-gate * minalloc and maxalloc values to be used for taskq_create(). 51*0Sstevel@tonic-gate */ 52*0Sstevel@tonic-gate int crypto_taskq_minalloc = CYRPTO_TASKQ_MIN; 53*0Sstevel@tonic-gate int crypto_taskq_maxalloc = CRYPTO_TASKQ_MAX; 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate static void free_provider_list(kcf_provider_list_t *); 56*0Sstevel@tonic-gate static void remove_provider(kcf_provider_desc_t *); 57*0Sstevel@tonic-gate static void process_logical_providers(crypto_provider_info_t *, 58*0Sstevel@tonic-gate kcf_provider_desc_t *); 59*0Sstevel@tonic-gate static void copy_ops_vector(crypto_ops_t *, crypto_ops_t *); 60*0Sstevel@tonic-gate static int init_prov_mechs(crypto_provider_info_t *, kcf_provider_desc_t *); 61*0Sstevel@tonic-gate static int kcf_prov_kstat_update(kstat_t *, int); 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate static kcf_prov_stats_t kcf_stats_ks_data_template = { 64*0Sstevel@tonic-gate { "kcf_ops_total", KSTAT_DATA_UINT64 }, 65*0Sstevel@tonic-gate { "kcf_ops_passed", KSTAT_DATA_UINT64 }, 66*0Sstevel@tonic-gate { "kcf_ops_failed", KSTAT_DATA_UINT64 }, 67*0Sstevel@tonic-gate { "kcf_ops_returned_busy", KSTAT_DATA_UINT64 } 68*0Sstevel@tonic-gate }; 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate #define KCF_SPI_COPY_OPS(src, dst, ops) if ((src)->ops != NULL) \ 71*0Sstevel@tonic-gate *((dst)->ops) = *((src)->ops); 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate /* 74*0Sstevel@tonic-gate * This routine is used to add cryptographic providers to the KEF framework. 75*0Sstevel@tonic-gate * Providers pass a crypto_provider_info structure to crypto_register_provider() 76*0Sstevel@tonic-gate * and get back a handle. The crypto_provider_info structure contains a 77*0Sstevel@tonic-gate * list of mechanisms supported by the provider and an ops vector containing 78*0Sstevel@tonic-gate * provider entry points. Hardware providers call this routine in their attach 79*0Sstevel@tonic-gate * routines. Software providers call this routine in their _init() routine. 80*0Sstevel@tonic-gate */ 81*0Sstevel@tonic-gate int 82*0Sstevel@tonic-gate crypto_register_provider(crypto_provider_info_t *info, 83*0Sstevel@tonic-gate crypto_kcf_provider_handle_t *handle) 84*0Sstevel@tonic-gate { 85*0Sstevel@tonic-gate int i; 86*0Sstevel@tonic-gate int vstatus = 0; 87*0Sstevel@tonic-gate struct modctl *mcp; 88*0Sstevel@tonic-gate char *name; 89*0Sstevel@tonic-gate char ks_name[KSTAT_STRLEN]; 90*0Sstevel@tonic-gate crypto_notify_event_change_t ec; 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate kcf_provider_desc_t *prov_desc = NULL; 93*0Sstevel@tonic-gate int ret = CRYPTO_ARGUMENTS_BAD; 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate if (info->pi_interface_version != CRYPTO_SPI_VERSION_1) 96*0Sstevel@tonic-gate return (CRYPTO_VERSION_MISMATCH); 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate /* 99*0Sstevel@tonic-gate * Check provider type, must be software, hardware, or logical. 100*0Sstevel@tonic-gate */ 101*0Sstevel@tonic-gate if (info->pi_provider_type != CRYPTO_HW_PROVIDER && 102*0Sstevel@tonic-gate info->pi_provider_type != CRYPTO_SW_PROVIDER && 103*0Sstevel@tonic-gate info->pi_provider_type != CRYPTO_LOGICAL_PROVIDER) 104*0Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate /* 107*0Sstevel@tonic-gate * Allocate and initialize a new provider descriptor. We also 108*0Sstevel@tonic-gate * hold it and release it when done. 109*0Sstevel@tonic-gate */ 110*0Sstevel@tonic-gate prov_desc = kcf_alloc_provider_desc(info); 111*0Sstevel@tonic-gate KCF_PROV_REFHOLD(prov_desc); 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate prov_desc->pd_prov_type = info->pi_provider_type; 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate /* provider-private handle, opaque to KCF */ 116*0Sstevel@tonic-gate prov_desc->pd_prov_handle = info->pi_provider_handle; 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate /* copy provider description string */ 119*0Sstevel@tonic-gate if (info->pi_provider_description != NULL) { 120*0Sstevel@tonic-gate /* 121*0Sstevel@tonic-gate * pi_provider_descriptor is a string that can contain 122*0Sstevel@tonic-gate * up to CRYPTO_PROVIDER_DESCR_MAX_LEN + 1 characters 123*0Sstevel@tonic-gate * INCLUDING the terminating null character. A bcopy() 124*0Sstevel@tonic-gate * is necessary here as pd_description should not have 125*0Sstevel@tonic-gate * a null character. See comments in kcf_alloc_provider_desc() 126*0Sstevel@tonic-gate * for details on pd_description field. 127*0Sstevel@tonic-gate */ 128*0Sstevel@tonic-gate bcopy(info->pi_provider_description, prov_desc->pd_description, 129*0Sstevel@tonic-gate min(strlen(info->pi_provider_description), 130*0Sstevel@tonic-gate CRYPTO_PROVIDER_DESCR_MAX_LEN)); 131*0Sstevel@tonic-gate } 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate if (info->pi_provider_type != CRYPTO_LOGICAL_PROVIDER) { 134*0Sstevel@tonic-gate if (info->pi_ops_vector == NULL) { 135*0Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 136*0Sstevel@tonic-gate } 137*0Sstevel@tonic-gate copy_ops_vector(info->pi_ops_vector, prov_desc->pd_ops_vector); 138*0Sstevel@tonic-gate } 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate /* 141*0Sstevel@tonic-gate * For software providers, copy the module name and module ID. 142*0Sstevel@tonic-gate * For hardware providers, copy the driver name and instance. 143*0Sstevel@tonic-gate */ 144*0Sstevel@tonic-gate switch (info->pi_provider_type) { 145*0Sstevel@tonic-gate case CRYPTO_SW_PROVIDER: 146*0Sstevel@tonic-gate if (info->pi_provider_dev.pd_sw == NULL) 147*0Sstevel@tonic-gate goto bail; 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate if ((mcp = mod_getctl(info->pi_provider_dev.pd_sw)) == NULL) 150*0Sstevel@tonic-gate goto bail; 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate prov_desc->pd_module_id = mcp->mod_id; 153*0Sstevel@tonic-gate name = mcp->mod_modname; 154*0Sstevel@tonic-gate break; 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate case CRYPTO_HW_PROVIDER: 157*0Sstevel@tonic-gate case CRYPTO_LOGICAL_PROVIDER: 158*0Sstevel@tonic-gate if (info->pi_provider_dev.pd_hw == NULL) 159*0Sstevel@tonic-gate goto bail; 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate prov_desc->pd_instance = 162*0Sstevel@tonic-gate ddi_get_instance(info->pi_provider_dev.pd_hw); 163*0Sstevel@tonic-gate name = (char *)ddi_driver_name(info->pi_provider_dev.pd_hw); 164*0Sstevel@tonic-gate break; 165*0Sstevel@tonic-gate } 166*0Sstevel@tonic-gate if (name == NULL) 167*0Sstevel@tonic-gate goto bail; 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gate prov_desc->pd_name = kmem_alloc(strlen(name) + 1, KM_SLEEP); 170*0Sstevel@tonic-gate (void) strcpy(prov_desc->pd_name, name); 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate if ((prov_desc->pd_mctlp = kcf_get_modctl(info)) == NULL) 173*0Sstevel@tonic-gate goto bail; 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate /* process the mechanisms supported by the provider */ 176*0Sstevel@tonic-gate if ((ret = init_prov_mechs(info, prov_desc)) != CRYPTO_SUCCESS) 177*0Sstevel@tonic-gate goto bail; 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate /* 180*0Sstevel@tonic-gate * Add provider to providers tables, also sets the descriptor 181*0Sstevel@tonic-gate * pd_prov_id field. 182*0Sstevel@tonic-gate */ 183*0Sstevel@tonic-gate if ((ret = kcf_prov_tab_add_provider(prov_desc)) != CRYPTO_SUCCESS) { 184*0Sstevel@tonic-gate undo_register_provider(prov_desc, B_FALSE); 185*0Sstevel@tonic-gate goto bail; 186*0Sstevel@tonic-gate } 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate if (info->pi_provider_type != CRYPTO_LOGICAL_PROVIDER) { 189*0Sstevel@tonic-gate if ((vstatus = kcf_verify_signature(prov_desc)) == 190*0Sstevel@tonic-gate CRYPTO_MODVERIFICATION_FAILED) { 191*0Sstevel@tonic-gate undo_register_provider(prov_desc, B_TRUE); 192*0Sstevel@tonic-gate ret = CRYPTO_MODVERIFICATION_FAILED; 193*0Sstevel@tonic-gate goto bail; 194*0Sstevel@tonic-gate } 195*0Sstevel@tonic-gate } 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate /* 198*0Sstevel@tonic-gate * We create a taskq only for a hardware provider. The global 199*0Sstevel@tonic-gate * software queue is used for software providers. The taskq 200*0Sstevel@tonic-gate * is limited to one thread since tasks are guaranteed to be 201*0Sstevel@tonic-gate * executed in the order they are scheduled, if nthreads == 1. We 202*0Sstevel@tonic-gate * pass TASKQ_PREPOPULATE flag to keep some entries cached to 203*0Sstevel@tonic-gate * improve performance. 204*0Sstevel@tonic-gate */ 205*0Sstevel@tonic-gate if (prov_desc->pd_prov_type == CRYPTO_HW_PROVIDER) 206*0Sstevel@tonic-gate prov_desc->pd_sched_info.ks_taskq = taskq_create("kcf_taskq", 207*0Sstevel@tonic-gate 1, minclsyspri, crypto_taskq_minalloc, 208*0Sstevel@tonic-gate crypto_taskq_maxalloc, TASKQ_PREPOPULATE); 209*0Sstevel@tonic-gate else 210*0Sstevel@tonic-gate prov_desc->pd_sched_info.ks_taskq = NULL; 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate /* no kernel session to logical providers */ 213*0Sstevel@tonic-gate if (prov_desc->pd_prov_type != CRYPTO_LOGICAL_PROVIDER) { 214*0Sstevel@tonic-gate /* 215*0Sstevel@tonic-gate * Open a session for session-oriented providers. This session 216*0Sstevel@tonic-gate * is used for all kernel consumers. This is fine as a provider 217*0Sstevel@tonic-gate * is required to support multiple thread access to a session. 218*0Sstevel@tonic-gate * We can do this only after the taskq has been created as we 219*0Sstevel@tonic-gate * do a kcf_submit_request() to open the session. 220*0Sstevel@tonic-gate */ 221*0Sstevel@tonic-gate if (KCF_PROV_SESSION_OPS(prov_desc) != NULL) { 222*0Sstevel@tonic-gate kcf_req_params_t params; 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gate KCF_WRAP_SESSION_OPS_PARAMS(¶ms, 225*0Sstevel@tonic-gate KCF_OP_SESSION_OPEN, &prov_desc->pd_sid, 0, 226*0Sstevel@tonic-gate CRYPTO_USER, NULL, 0, prov_desc); 227*0Sstevel@tonic-gate ret = kcf_submit_request(prov_desc, NULL, NULL, ¶ms, 228*0Sstevel@tonic-gate B_FALSE); 229*0Sstevel@tonic-gate 230*0Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS) { 231*0Sstevel@tonic-gate undo_register_provider(prov_desc, B_TRUE); 232*0Sstevel@tonic-gate ret = CRYPTO_FAILED; 233*0Sstevel@tonic-gate goto bail; 234*0Sstevel@tonic-gate } 235*0Sstevel@tonic-gate } 236*0Sstevel@tonic-gate } 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate if (prov_desc->pd_prov_type != CRYPTO_LOGICAL_PROVIDER) { 239*0Sstevel@tonic-gate /* 240*0Sstevel@tonic-gate * Create the kstat for this provider. There is a kstat 241*0Sstevel@tonic-gate * installed for each successfully registered provider. 242*0Sstevel@tonic-gate * This kstat is deleted, when the provider unregisters. 243*0Sstevel@tonic-gate */ 244*0Sstevel@tonic-gate if (prov_desc->pd_prov_type == CRYPTO_SW_PROVIDER) { 245*0Sstevel@tonic-gate (void) snprintf(ks_name, KSTAT_STRLEN, "%s_%s", 246*0Sstevel@tonic-gate prov_desc->pd_name, "provider_stats"); 247*0Sstevel@tonic-gate } else { 248*0Sstevel@tonic-gate (void) snprintf(ks_name, KSTAT_STRLEN, "%s_%d_%u_%s", 249*0Sstevel@tonic-gate prov_desc->pd_name, prov_desc->pd_instance, 250*0Sstevel@tonic-gate prov_desc->pd_prov_id, "provider_stats"); 251*0Sstevel@tonic-gate } 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate prov_desc->pd_kstat = kstat_create("kcf", 0, ks_name, "crypto", 254*0Sstevel@tonic-gate KSTAT_TYPE_NAMED, sizeof (kcf_prov_stats_t) / 255*0Sstevel@tonic-gate sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL); 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gate if (prov_desc->pd_kstat != NULL) { 258*0Sstevel@tonic-gate bcopy(&kcf_stats_ks_data_template, 259*0Sstevel@tonic-gate &prov_desc->pd_ks_data, 260*0Sstevel@tonic-gate sizeof (kcf_stats_ks_data_template)); 261*0Sstevel@tonic-gate prov_desc->pd_kstat->ks_data = &prov_desc->pd_ks_data; 262*0Sstevel@tonic-gate KCF_PROV_REFHOLD(prov_desc); 263*0Sstevel@tonic-gate KCF_PROV_IREFHOLD(prov_desc); 264*0Sstevel@tonic-gate prov_desc->pd_kstat->ks_private = prov_desc; 265*0Sstevel@tonic-gate prov_desc->pd_kstat->ks_update = kcf_prov_kstat_update; 266*0Sstevel@tonic-gate kstat_install(prov_desc->pd_kstat); 267*0Sstevel@tonic-gate } 268*0Sstevel@tonic-gate } 269*0Sstevel@tonic-gate 270*0Sstevel@tonic-gate if (prov_desc->pd_prov_type == CRYPTO_HW_PROVIDER) 271*0Sstevel@tonic-gate process_logical_providers(info, prov_desc); 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate /* 274*0Sstevel@tonic-gate * Inform interested kernel clients of the event. 275*0Sstevel@tonic-gate * Logical providers are not visible to kernel clients. 276*0Sstevel@tonic-gate */ 277*0Sstevel@tonic-gate if (prov_desc->pd_prov_type != CRYPTO_LOGICAL_PROVIDER) { 278*0Sstevel@tonic-gate ec.ec_provider_type = prov_desc->pd_prov_type; 279*0Sstevel@tonic-gate ec.ec_change = CRYPTO_EVENT_CHANGE_ADDED; 280*0Sstevel@tonic-gate for (i = 0; i < prov_desc->pd_mech_list_count; i++) { 281*0Sstevel@tonic-gate /* Skip any mechanisms not allowed by the policy */ 282*0Sstevel@tonic-gate if (is_mech_disabled(prov_desc, 283*0Sstevel@tonic-gate prov_desc->pd_mechanisms[i].cm_mech_name)) 284*0Sstevel@tonic-gate continue; 285*0Sstevel@tonic-gate 286*0Sstevel@tonic-gate (void) strncpy(ec.ec_mech_name, 287*0Sstevel@tonic-gate prov_desc->pd_mechanisms[i].cm_mech_name, 288*0Sstevel@tonic-gate CRYPTO_MAX_MECH_NAME); 289*0Sstevel@tonic-gate kcf_walk_ntfylist(CRYPTO_EVENT_PROVIDERS_CHANGE, &ec); 290*0Sstevel@tonic-gate } 291*0Sstevel@tonic-gate } 292*0Sstevel@tonic-gate 293*0Sstevel@tonic-gate mutex_enter(&prov_desc->pd_lock); 294*0Sstevel@tonic-gate prov_desc->pd_state = (vstatus == 0) ? KCF_PROV_READY : 295*0Sstevel@tonic-gate KCF_PROV_UNVERIFIED; 296*0Sstevel@tonic-gate mutex_exit(&prov_desc->pd_lock); 297*0Sstevel@tonic-gate 298*0Sstevel@tonic-gate *handle = prov_desc->pd_kcf_prov_handle; 299*0Sstevel@tonic-gate KCF_PROV_REFRELE(prov_desc); 300*0Sstevel@tonic-gate return (CRYPTO_SUCCESS); 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gate bail: 303*0Sstevel@tonic-gate KCF_PROV_REFRELE(prov_desc); 304*0Sstevel@tonic-gate return (ret); 305*0Sstevel@tonic-gate } 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate /* 308*0Sstevel@tonic-gate * This routine is used to notify the framework when a provider is being 309*0Sstevel@tonic-gate * removed. Hardware providers call this routine in their detach routines. 310*0Sstevel@tonic-gate * Software providers call this routine in their _fini() routine. 311*0Sstevel@tonic-gate */ 312*0Sstevel@tonic-gate int 313*0Sstevel@tonic-gate crypto_unregister_provider(crypto_kcf_provider_handle_t handle) 314*0Sstevel@tonic-gate { 315*0Sstevel@tonic-gate int i; 316*0Sstevel@tonic-gate uint_t mech_idx; 317*0Sstevel@tonic-gate kcf_provider_desc_t *desc; 318*0Sstevel@tonic-gate crypto_notify_event_change_t ec; 319*0Sstevel@tonic-gate kcf_prov_state_t saved_state; 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate /* lookup provider descriptor */ 322*0Sstevel@tonic-gate if ((desc = kcf_prov_tab_lookup((crypto_provider_id_t)handle)) == NULL) 323*0Sstevel@tonic-gate return (CRYPTO_UNKNOWN_PROVIDER); 324*0Sstevel@tonic-gate 325*0Sstevel@tonic-gate mutex_enter(&desc->pd_lock); 326*0Sstevel@tonic-gate /* 327*0Sstevel@tonic-gate * Check if any other thread is disabling or removing 328*0Sstevel@tonic-gate * this provider. We return if this is the case. 329*0Sstevel@tonic-gate */ 330*0Sstevel@tonic-gate if (desc->pd_state >= KCF_PROV_DISABLED) { 331*0Sstevel@tonic-gate mutex_exit(&desc->pd_lock); 332*0Sstevel@tonic-gate /* Release reference held by kcf_prov_tab_lookup(). */ 333*0Sstevel@tonic-gate KCF_PROV_REFRELE(desc); 334*0Sstevel@tonic-gate return (CRYPTO_BUSY); 335*0Sstevel@tonic-gate } 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gate saved_state = desc->pd_state; 338*0Sstevel@tonic-gate desc->pd_state = KCF_PROV_REMOVED; 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate if (saved_state == KCF_PROV_BUSY) { 341*0Sstevel@tonic-gate /* 342*0Sstevel@tonic-gate * The per-provider taskq thread may be waiting. We 343*0Sstevel@tonic-gate * signal it so that it can start failing requests. 344*0Sstevel@tonic-gate * Note that we do not need a cv_broadcast() as we keep 345*0Sstevel@tonic-gate * only a single thread per taskq. 346*0Sstevel@tonic-gate */ 347*0Sstevel@tonic-gate cv_signal(&desc->pd_resume_cv); 348*0Sstevel@tonic-gate } 349*0Sstevel@tonic-gate 350*0Sstevel@tonic-gate if (desc->pd_prov_type == CRYPTO_SW_PROVIDER) { 351*0Sstevel@tonic-gate /* 352*0Sstevel@tonic-gate * Check if this provider is currently being used. 353*0Sstevel@tonic-gate * pd_irefcnt is the number of holds from the internal 354*0Sstevel@tonic-gate * structures. We add one to account for the above lookup. 355*0Sstevel@tonic-gate */ 356*0Sstevel@tonic-gate if (desc->pd_refcnt > desc->pd_irefcnt + 1) { 357*0Sstevel@tonic-gate desc->pd_state = saved_state; 358*0Sstevel@tonic-gate mutex_exit(&desc->pd_lock); 359*0Sstevel@tonic-gate /* Release reference held by kcf_prov_tab_lookup(). */ 360*0Sstevel@tonic-gate KCF_PROV_REFRELE(desc); 361*0Sstevel@tonic-gate /* 362*0Sstevel@tonic-gate * The administrator presumably will stop the clients 363*0Sstevel@tonic-gate * thus removing the holds, when they get the busy 364*0Sstevel@tonic-gate * return value. Any retry will succeed then. 365*0Sstevel@tonic-gate */ 366*0Sstevel@tonic-gate return (CRYPTO_BUSY); 367*0Sstevel@tonic-gate } 368*0Sstevel@tonic-gate } 369*0Sstevel@tonic-gate mutex_exit(&desc->pd_lock); 370*0Sstevel@tonic-gate 371*0Sstevel@tonic-gate if (desc->pd_prov_type != CRYPTO_SW_PROVIDER) { 372*0Sstevel@tonic-gate remove_provider(desc); 373*0Sstevel@tonic-gate } 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gate if (desc->pd_prov_type != CRYPTO_LOGICAL_PROVIDER) { 376*0Sstevel@tonic-gate /* remove the provider from the mechanisms tables */ 377*0Sstevel@tonic-gate for (mech_idx = 0; mech_idx < desc->pd_mech_list_count; 378*0Sstevel@tonic-gate mech_idx++) { 379*0Sstevel@tonic-gate kcf_remove_mech_provider( 380*0Sstevel@tonic-gate desc->pd_mechanisms[mech_idx].cm_mech_name, desc); 381*0Sstevel@tonic-gate } 382*0Sstevel@tonic-gate } 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate /* remove provider from providers table */ 385*0Sstevel@tonic-gate if (kcf_prov_tab_rem_provider((crypto_provider_id_t)handle) != 386*0Sstevel@tonic-gate CRYPTO_SUCCESS) { 387*0Sstevel@tonic-gate /* Release reference held by kcf_prov_tab_lookup(). */ 388*0Sstevel@tonic-gate KCF_PROV_REFRELE(desc); 389*0Sstevel@tonic-gate return (CRYPTO_UNKNOWN_PROVIDER); 390*0Sstevel@tonic-gate } 391*0Sstevel@tonic-gate 392*0Sstevel@tonic-gate /* destroy the kstat created for this provider */ 393*0Sstevel@tonic-gate if (desc->pd_kstat != NULL) { 394*0Sstevel@tonic-gate kcf_provider_desc_t *kspd = desc->pd_kstat->ks_private; 395*0Sstevel@tonic-gate 396*0Sstevel@tonic-gate /* release reference held by desc->pd_kstat->ks_private */ 397*0Sstevel@tonic-gate ASSERT(desc == kspd); 398*0Sstevel@tonic-gate kstat_delete(kspd->pd_kstat); 399*0Sstevel@tonic-gate KCF_PROV_REFRELE(kspd); 400*0Sstevel@tonic-gate KCF_PROV_IREFRELE(kspd); 401*0Sstevel@tonic-gate } 402*0Sstevel@tonic-gate 403*0Sstevel@tonic-gate if (desc->pd_prov_type == CRYPTO_SW_PROVIDER) { 404*0Sstevel@tonic-gate /* Release reference held by kcf_prov_tab_lookup(). */ 405*0Sstevel@tonic-gate KCF_PROV_REFRELE(desc); 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate /* 408*0Sstevel@tonic-gate * Wait till the existing requests complete. 409*0Sstevel@tonic-gate */ 410*0Sstevel@tonic-gate mutex_enter(&desc->pd_lock); 411*0Sstevel@tonic-gate while (desc->pd_state != KCF_PROV_FREED) 412*0Sstevel@tonic-gate cv_wait(&desc->pd_remove_cv, &desc->pd_lock); 413*0Sstevel@tonic-gate mutex_exit(&desc->pd_lock); 414*0Sstevel@tonic-gate } else { 415*0Sstevel@tonic-gate /* 416*0Sstevel@tonic-gate * Wait until requests that have been sent to the provider 417*0Sstevel@tonic-gate * complete. 418*0Sstevel@tonic-gate */ 419*0Sstevel@tonic-gate mutex_enter(&desc->pd_lock); 420*0Sstevel@tonic-gate while (desc->pd_irefcnt > 0) 421*0Sstevel@tonic-gate cv_wait(&desc->pd_remove_cv, &desc->pd_lock); 422*0Sstevel@tonic-gate mutex_exit(&desc->pd_lock); 423*0Sstevel@tonic-gate } 424*0Sstevel@tonic-gate 425*0Sstevel@tonic-gate /* 426*0Sstevel@tonic-gate * Inform interested kernel clients of the event. 427*0Sstevel@tonic-gate * Logical providers are not visible to kernel clients. 428*0Sstevel@tonic-gate */ 429*0Sstevel@tonic-gate if (desc->pd_prov_type != CRYPTO_LOGICAL_PROVIDER) { 430*0Sstevel@tonic-gate ec.ec_provider_type = desc->pd_prov_type; 431*0Sstevel@tonic-gate ec.ec_change = CRYPTO_EVENT_CHANGE_REMOVED; 432*0Sstevel@tonic-gate for (i = 0; i < desc->pd_mech_list_count; i++) { 433*0Sstevel@tonic-gate /* Skip any mechanisms not allowed by the policy */ 434*0Sstevel@tonic-gate if (is_mech_disabled(desc, 435*0Sstevel@tonic-gate desc->pd_mechanisms[i].cm_mech_name)) 436*0Sstevel@tonic-gate continue; 437*0Sstevel@tonic-gate 438*0Sstevel@tonic-gate (void) strncpy(ec.ec_mech_name, 439*0Sstevel@tonic-gate desc->pd_mechanisms[i].cm_mech_name, 440*0Sstevel@tonic-gate CRYPTO_MAX_MECH_NAME); 441*0Sstevel@tonic-gate kcf_walk_ntfylist(CRYPTO_EVENT_PROVIDERS_CHANGE, &ec); 442*0Sstevel@tonic-gate } 443*0Sstevel@tonic-gate } 444*0Sstevel@tonic-gate 445*0Sstevel@tonic-gate if (desc->pd_prov_type == CRYPTO_SW_PROVIDER) { 446*0Sstevel@tonic-gate /* 447*0Sstevel@tonic-gate * This is the only place where kcf_free_provider_desc() 448*0Sstevel@tonic-gate * is called directly. KCF_PROV_REFRELE() should free the 449*0Sstevel@tonic-gate * structure in all other places. 450*0Sstevel@tonic-gate */ 451*0Sstevel@tonic-gate ASSERT(desc->pd_state == KCF_PROV_FREED && 452*0Sstevel@tonic-gate desc->pd_refcnt == 0); 453*0Sstevel@tonic-gate kcf_free_provider_desc(desc); 454*0Sstevel@tonic-gate } else { 455*0Sstevel@tonic-gate KCF_PROV_REFRELE(desc); 456*0Sstevel@tonic-gate } 457*0Sstevel@tonic-gate 458*0Sstevel@tonic-gate return (CRYPTO_SUCCESS); 459*0Sstevel@tonic-gate } 460*0Sstevel@tonic-gate 461*0Sstevel@tonic-gate /* 462*0Sstevel@tonic-gate * This routine is used to notify the framework that the state of 463*0Sstevel@tonic-gate * a cryptographic provider has changed. Valid state codes are: 464*0Sstevel@tonic-gate * 465*0Sstevel@tonic-gate * CRYPTO_PROVIDER_READY 466*0Sstevel@tonic-gate * The provider indicates that it can process more requests. A provider 467*0Sstevel@tonic-gate * will notify with this event if it previously has notified us with a 468*0Sstevel@tonic-gate * CRYPTO_PROVIDER_BUSY. 469*0Sstevel@tonic-gate * 470*0Sstevel@tonic-gate * CRYPTO_PROVIDER_BUSY 471*0Sstevel@tonic-gate * The provider can not take more requests. 472*0Sstevel@tonic-gate * 473*0Sstevel@tonic-gate * CRYPTO_PROVIDER_FAILED 474*0Sstevel@tonic-gate * The provider encountered an internal error. The framework will not 475*0Sstevel@tonic-gate * be sending any more requests to the provider. The provider may notify 476*0Sstevel@tonic-gate * with a CRYPTO_PROVIDER_READY, if it is able to recover from the error. 477*0Sstevel@tonic-gate * 478*0Sstevel@tonic-gate * This routine can be called from user or interrupt context. 479*0Sstevel@tonic-gate */ 480*0Sstevel@tonic-gate void 481*0Sstevel@tonic-gate crypto_provider_notification(crypto_kcf_provider_handle_t handle, uint_t state) 482*0Sstevel@tonic-gate { 483*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 484*0Sstevel@tonic-gate 485*0Sstevel@tonic-gate /* lookup the provider from the given handle */ 486*0Sstevel@tonic-gate if ((pd = kcf_prov_tab_lookup((crypto_provider_id_t)handle)) == NULL) 487*0Sstevel@tonic-gate return; 488*0Sstevel@tonic-gate 489*0Sstevel@tonic-gate mutex_enter(&pd->pd_lock); 490*0Sstevel@tonic-gate 491*0Sstevel@tonic-gate if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 492*0Sstevel@tonic-gate cmn_err(CE_WARN, "crypto_provider_notification: " 493*0Sstevel@tonic-gate "logical provider (%x) ignored\n", handle); 494*0Sstevel@tonic-gate goto out; 495*0Sstevel@tonic-gate } 496*0Sstevel@tonic-gate switch (state) { 497*0Sstevel@tonic-gate case CRYPTO_PROVIDER_READY: 498*0Sstevel@tonic-gate switch (pd->pd_state) { 499*0Sstevel@tonic-gate case KCF_PROV_BUSY: 500*0Sstevel@tonic-gate pd->pd_state = KCF_PROV_READY; 501*0Sstevel@tonic-gate /* 502*0Sstevel@tonic-gate * Signal the per-provider taskq thread that it 503*0Sstevel@tonic-gate * can start submitting requests. Note that we do 504*0Sstevel@tonic-gate * not need a cv_broadcast() as we keep only a 505*0Sstevel@tonic-gate * single thread per taskq. 506*0Sstevel@tonic-gate */ 507*0Sstevel@tonic-gate cv_signal(&pd->pd_resume_cv); 508*0Sstevel@tonic-gate break; 509*0Sstevel@tonic-gate 510*0Sstevel@tonic-gate case KCF_PROV_FAILED: 511*0Sstevel@tonic-gate /* 512*0Sstevel@tonic-gate * The provider recovered from the error. Let us 513*0Sstevel@tonic-gate * use it now. 514*0Sstevel@tonic-gate */ 515*0Sstevel@tonic-gate pd->pd_state = KCF_PROV_READY; 516*0Sstevel@tonic-gate break; 517*0Sstevel@tonic-gate } 518*0Sstevel@tonic-gate break; 519*0Sstevel@tonic-gate 520*0Sstevel@tonic-gate case CRYPTO_PROVIDER_BUSY: 521*0Sstevel@tonic-gate switch (pd->pd_state) { 522*0Sstevel@tonic-gate case KCF_PROV_READY: 523*0Sstevel@tonic-gate pd->pd_state = KCF_PROV_BUSY; 524*0Sstevel@tonic-gate break; 525*0Sstevel@tonic-gate } 526*0Sstevel@tonic-gate break; 527*0Sstevel@tonic-gate 528*0Sstevel@tonic-gate case CRYPTO_PROVIDER_FAILED: 529*0Sstevel@tonic-gate /* 530*0Sstevel@tonic-gate * We note the failure and return. The per-provider taskq 531*0Sstevel@tonic-gate * thread checks this flag and starts failing the 532*0Sstevel@tonic-gate * requests, if it is set. See process_req_hwp() for details. 533*0Sstevel@tonic-gate */ 534*0Sstevel@tonic-gate switch (pd->pd_state) { 535*0Sstevel@tonic-gate case KCF_PROV_READY: 536*0Sstevel@tonic-gate pd->pd_state = KCF_PROV_FAILED; 537*0Sstevel@tonic-gate break; 538*0Sstevel@tonic-gate 539*0Sstevel@tonic-gate case KCF_PROV_BUSY: 540*0Sstevel@tonic-gate pd->pd_state = KCF_PROV_FAILED; 541*0Sstevel@tonic-gate /* 542*0Sstevel@tonic-gate * The per-provider taskq thread may be waiting. We 543*0Sstevel@tonic-gate * signal it so that it can start failing requests. 544*0Sstevel@tonic-gate */ 545*0Sstevel@tonic-gate cv_signal(&pd->pd_resume_cv); 546*0Sstevel@tonic-gate break; 547*0Sstevel@tonic-gate } 548*0Sstevel@tonic-gate break; 549*0Sstevel@tonic-gate } 550*0Sstevel@tonic-gate out: 551*0Sstevel@tonic-gate mutex_exit(&pd->pd_lock); 552*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 553*0Sstevel@tonic-gate } 554*0Sstevel@tonic-gate 555*0Sstevel@tonic-gate /* 556*0Sstevel@tonic-gate * This routine is used to notify the framework the result of 557*0Sstevel@tonic-gate * an asynchronous request handled by a provider. Valid error 558*0Sstevel@tonic-gate * codes are the same as the CRYPTO_* errors defined in common.h. 559*0Sstevel@tonic-gate * 560*0Sstevel@tonic-gate * This routine can be called from user or interrupt context. 561*0Sstevel@tonic-gate */ 562*0Sstevel@tonic-gate void 563*0Sstevel@tonic-gate crypto_op_notification(crypto_req_handle_t handle, int error) 564*0Sstevel@tonic-gate { 565*0Sstevel@tonic-gate kcf_call_type_t ctype; 566*0Sstevel@tonic-gate 567*0Sstevel@tonic-gate if ((ctype = GET_REQ_TYPE(handle)) == CRYPTO_SYNCH) { 568*0Sstevel@tonic-gate kcf_sreq_node_t *sreq = (kcf_sreq_node_t *)handle; 569*0Sstevel@tonic-gate 570*0Sstevel@tonic-gate if (error != CRYPTO_SUCCESS) 571*0Sstevel@tonic-gate sreq->sn_provider->pd_sched_info.ks_nfails++; 572*0Sstevel@tonic-gate KCF_PROV_IREFRELE(sreq->sn_provider); 573*0Sstevel@tonic-gate kcf_sop_done(sreq, error); 574*0Sstevel@tonic-gate } else { 575*0Sstevel@tonic-gate kcf_areq_node_t *areq = (kcf_areq_node_t *)handle; 576*0Sstevel@tonic-gate 577*0Sstevel@tonic-gate ASSERT(ctype == CRYPTO_ASYNCH); 578*0Sstevel@tonic-gate if (error != CRYPTO_SUCCESS) 579*0Sstevel@tonic-gate areq->an_provider->pd_sched_info.ks_nfails++; 580*0Sstevel@tonic-gate KCF_PROV_IREFRELE(areq->an_provider); 581*0Sstevel@tonic-gate kcf_aop_done(areq, error); 582*0Sstevel@tonic-gate } 583*0Sstevel@tonic-gate } 584*0Sstevel@tonic-gate 585*0Sstevel@tonic-gate /* 586*0Sstevel@tonic-gate * This routine is used by software providers to determine 587*0Sstevel@tonic-gate * whether to use KM_SLEEP or KM_NOSLEEP during memory allocation. 588*0Sstevel@tonic-gate * Note that hardware providers can always use KM_SLEEP. So, 589*0Sstevel@tonic-gate * they do not need to call this routine. 590*0Sstevel@tonic-gate * 591*0Sstevel@tonic-gate * This routine can be called from user or interrupt context. 592*0Sstevel@tonic-gate */ 593*0Sstevel@tonic-gate int 594*0Sstevel@tonic-gate crypto_kmflag(crypto_req_handle_t handle) 595*0Sstevel@tonic-gate { 596*0Sstevel@tonic-gate return (REQHNDL2_KMFLAG(handle)); 597*0Sstevel@tonic-gate } 598*0Sstevel@tonic-gate 599*0Sstevel@tonic-gate 600*0Sstevel@tonic-gate /* 601*0Sstevel@tonic-gate * Copy an ops vector from src to dst. Used during provider registration 602*0Sstevel@tonic-gate * to copy the ops vector from the provider info structure to the 603*0Sstevel@tonic-gate * provider descriptor maintained by KCF. 604*0Sstevel@tonic-gate * Copying the ops vector specified by the provider is needed since the 605*0Sstevel@tonic-gate * framework does not require the provider info structure to be 606*0Sstevel@tonic-gate * persistent. 607*0Sstevel@tonic-gate */ 608*0Sstevel@tonic-gate static void 609*0Sstevel@tonic-gate copy_ops_vector(crypto_ops_t *src_ops, crypto_ops_t *dst_ops) 610*0Sstevel@tonic-gate { 611*0Sstevel@tonic-gate KCF_SPI_COPY_OPS(src_ops, dst_ops, control_ops); 612*0Sstevel@tonic-gate KCF_SPI_COPY_OPS(src_ops, dst_ops, digest_ops); 613*0Sstevel@tonic-gate KCF_SPI_COPY_OPS(src_ops, dst_ops, cipher_ops); 614*0Sstevel@tonic-gate KCF_SPI_COPY_OPS(src_ops, dst_ops, mac_ops); 615*0Sstevel@tonic-gate KCF_SPI_COPY_OPS(src_ops, dst_ops, sign_ops); 616*0Sstevel@tonic-gate KCF_SPI_COPY_OPS(src_ops, dst_ops, verify_ops); 617*0Sstevel@tonic-gate KCF_SPI_COPY_OPS(src_ops, dst_ops, dual_ops); 618*0Sstevel@tonic-gate KCF_SPI_COPY_OPS(src_ops, dst_ops, dual_cipher_mac_ops); 619*0Sstevel@tonic-gate KCF_SPI_COPY_OPS(src_ops, dst_ops, random_ops); 620*0Sstevel@tonic-gate KCF_SPI_COPY_OPS(src_ops, dst_ops, session_ops); 621*0Sstevel@tonic-gate KCF_SPI_COPY_OPS(src_ops, dst_ops, object_ops); 622*0Sstevel@tonic-gate KCF_SPI_COPY_OPS(src_ops, dst_ops, key_ops); 623*0Sstevel@tonic-gate KCF_SPI_COPY_OPS(src_ops, dst_ops, provider_ops); 624*0Sstevel@tonic-gate KCF_SPI_COPY_OPS(src_ops, dst_ops, ctx_ops); 625*0Sstevel@tonic-gate } 626*0Sstevel@tonic-gate 627*0Sstevel@tonic-gate /* 628*0Sstevel@tonic-gate * Process the mechanism info structures specified by the provider 629*0Sstevel@tonic-gate * during registration. A NULL crypto_provider_info_t indicates 630*0Sstevel@tonic-gate * an already initialized provider descriptor. 631*0Sstevel@tonic-gate * 632*0Sstevel@tonic-gate * Mechanisms are not added to the kernel's mechanism table if the 633*0Sstevel@tonic-gate * provider is a logical provider. 634*0Sstevel@tonic-gate * 635*0Sstevel@tonic-gate * Returns CRYPTO_SUCCESS on success, CRYPTO_ARGUMENTS if one 636*0Sstevel@tonic-gate * of the specified mechanisms was malformed, or CRYPTO_HOST_MEMORY 637*0Sstevel@tonic-gate * if the table of mechanisms is full. 638*0Sstevel@tonic-gate */ 639*0Sstevel@tonic-gate static int 640*0Sstevel@tonic-gate init_prov_mechs(crypto_provider_info_t *info, kcf_provider_desc_t *desc) 641*0Sstevel@tonic-gate { 642*0Sstevel@tonic-gate uint_t mech_idx; 643*0Sstevel@tonic-gate uint_t cleanup_idx; 644*0Sstevel@tonic-gate int err = CRYPTO_SUCCESS; 645*0Sstevel@tonic-gate kcf_prov_mech_desc_t *pmd; 646*0Sstevel@tonic-gate int desc_use_count = 0; 647*0Sstevel@tonic-gate int mcount = desc->pd_mech_list_count; 648*0Sstevel@tonic-gate 649*0Sstevel@tonic-gate if (desc->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 650*0Sstevel@tonic-gate if (info != NULL) { 651*0Sstevel@tonic-gate ASSERT(info->pi_mechanisms != NULL); 652*0Sstevel@tonic-gate bcopy(info->pi_mechanisms, desc->pd_mechanisms, 653*0Sstevel@tonic-gate sizeof (crypto_mech_info_t) * mcount); 654*0Sstevel@tonic-gate } 655*0Sstevel@tonic-gate return (CRYPTO_SUCCESS); 656*0Sstevel@tonic-gate } 657*0Sstevel@tonic-gate 658*0Sstevel@tonic-gate /* 659*0Sstevel@tonic-gate * Copy the mechanism list from the provider info to the provider 660*0Sstevel@tonic-gate * descriptor. desc->pd_mechanisms has an extra crypto_mech_info_t 661*0Sstevel@tonic-gate * element if the provider has random_ops since we keep an internal 662*0Sstevel@tonic-gate * mechanism, SUN_RANDOM, in this case. 663*0Sstevel@tonic-gate */ 664*0Sstevel@tonic-gate if (info != NULL) { 665*0Sstevel@tonic-gate if (info->pi_ops_vector->random_ops != NULL) { 666*0Sstevel@tonic-gate crypto_mech_info_t *rand_mi; 667*0Sstevel@tonic-gate 668*0Sstevel@tonic-gate /* 669*0Sstevel@tonic-gate * Need the following check as it is possible to have 670*0Sstevel@tonic-gate * a provider that implements just random_ops and has 671*0Sstevel@tonic-gate * pi_mechanisms == NULL. 672*0Sstevel@tonic-gate */ 673*0Sstevel@tonic-gate if (info->pi_mechanisms != NULL) { 674*0Sstevel@tonic-gate bcopy(info->pi_mechanisms, desc->pd_mechanisms, 675*0Sstevel@tonic-gate sizeof (crypto_mech_info_t) * (mcount - 1)); 676*0Sstevel@tonic-gate } 677*0Sstevel@tonic-gate rand_mi = &desc->pd_mechanisms[mcount - 1]; 678*0Sstevel@tonic-gate 679*0Sstevel@tonic-gate bzero(rand_mi, sizeof (crypto_mech_info_t)); 680*0Sstevel@tonic-gate (void) strncpy(rand_mi->cm_mech_name, SUN_RANDOM, 681*0Sstevel@tonic-gate CRYPTO_MAX_MECH_NAME); 682*0Sstevel@tonic-gate rand_mi->cm_func_group_mask = CRYPTO_FG_RANDOM; 683*0Sstevel@tonic-gate /* 684*0Sstevel@tonic-gate * What we really need here is a 685*0Sstevel@tonic-gate * CRYPTO_KEYSIZE_NOT_APPLICABLE. We make do with the 686*0Sstevel@tonic-gate * following for now. 687*0Sstevel@tonic-gate */ 688*0Sstevel@tonic-gate rand_mi->cm_keysize_unit = CRYPTO_KEYSIZE_UNIT_IN_BITS; 689*0Sstevel@tonic-gate } else { 690*0Sstevel@tonic-gate ASSERT(info->pi_mechanisms != NULL); 691*0Sstevel@tonic-gate bcopy(info->pi_mechanisms, desc->pd_mechanisms, 692*0Sstevel@tonic-gate sizeof (crypto_mech_info_t) * mcount); 693*0Sstevel@tonic-gate } 694*0Sstevel@tonic-gate } 695*0Sstevel@tonic-gate 696*0Sstevel@tonic-gate /* 697*0Sstevel@tonic-gate * For each mechanism support by the provider, add the provider 698*0Sstevel@tonic-gate * to the corresponding KCF mechanism mech_entry chain. 699*0Sstevel@tonic-gate */ 700*0Sstevel@tonic-gate for (mech_idx = 0; mech_idx < desc->pd_mech_list_count; mech_idx++) { 701*0Sstevel@tonic-gate crypto_mech_info_t *mi = &desc->pd_mechanisms[mech_idx]; 702*0Sstevel@tonic-gate 703*0Sstevel@tonic-gate if (mi->cm_keysize_unit != CRYPTO_KEYSIZE_UNIT_IN_BITS && 704*0Sstevel@tonic-gate mi->cm_keysize_unit != CRYPTO_KEYSIZE_UNIT_IN_BYTES) { 705*0Sstevel@tonic-gate err = CRYPTO_ARGUMENTS_BAD; 706*0Sstevel@tonic-gate break; 707*0Sstevel@tonic-gate } 708*0Sstevel@tonic-gate 709*0Sstevel@tonic-gate if (kcf_add_mech_provider(mi, desc, &pmd) != KCF_SUCCESS) 710*0Sstevel@tonic-gate break; 711*0Sstevel@tonic-gate 712*0Sstevel@tonic-gate if (pmd == NULL) 713*0Sstevel@tonic-gate continue; 714*0Sstevel@tonic-gate 715*0Sstevel@tonic-gate /* The provider will be used for this mechanism */ 716*0Sstevel@tonic-gate desc_use_count++; 717*0Sstevel@tonic-gate } 718*0Sstevel@tonic-gate 719*0Sstevel@tonic-gate /* 720*0Sstevel@tonic-gate * The provider will not be used for any mechanism. So, we fail its 721*0Sstevel@tonic-gate * registration. Note that if at least one of the mechanisms from the 722*0Sstevel@tonic-gate * provider can be used, we do it. This means there can be a overlap 723*0Sstevel@tonic-gate * between the mechanisms offered by providers. The first one to 724*0Sstevel@tonic-gate * register is used. Also, a policy to disable mechanisms of a provider 725*0Sstevel@tonic-gate * will cause the provider to be not used for those mechanisms. 726*0Sstevel@tonic-gate */ 727*0Sstevel@tonic-gate if (desc_use_count == 0) 728*0Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 729*0Sstevel@tonic-gate 730*0Sstevel@tonic-gate if (err == KCF_SUCCESS) 731*0Sstevel@tonic-gate return (CRYPTO_SUCCESS); 732*0Sstevel@tonic-gate 733*0Sstevel@tonic-gate /* 734*0Sstevel@tonic-gate * An error occurred while adding the mechanism, cleanup 735*0Sstevel@tonic-gate * and bail. 736*0Sstevel@tonic-gate */ 737*0Sstevel@tonic-gate for (cleanup_idx = 0; cleanup_idx < mech_idx; cleanup_idx++) { 738*0Sstevel@tonic-gate kcf_remove_mech_provider( 739*0Sstevel@tonic-gate desc->pd_mechanisms[cleanup_idx].cm_mech_name, desc); 740*0Sstevel@tonic-gate } 741*0Sstevel@tonic-gate 742*0Sstevel@tonic-gate if (err == KCF_MECH_TAB_FULL) 743*0Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 744*0Sstevel@tonic-gate 745*0Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 746*0Sstevel@tonic-gate } 747*0Sstevel@tonic-gate 748*0Sstevel@tonic-gate /* 749*0Sstevel@tonic-gate * Update routine for kstat. Only privileged users are allowed to 750*0Sstevel@tonic-gate * access this information, since this information is sensitive. 751*0Sstevel@tonic-gate * There are some cryptographic attacks (e.g. traffic analysis) 752*0Sstevel@tonic-gate * which can use this information. 753*0Sstevel@tonic-gate */ 754*0Sstevel@tonic-gate static int 755*0Sstevel@tonic-gate kcf_prov_kstat_update(kstat_t *ksp, int rw) 756*0Sstevel@tonic-gate { 757*0Sstevel@tonic-gate kcf_prov_stats_t *ks_data; 758*0Sstevel@tonic-gate kcf_provider_desc_t *pd = (kcf_provider_desc_t *)ksp->ks_private; 759*0Sstevel@tonic-gate 760*0Sstevel@tonic-gate if (rw == KSTAT_WRITE) 761*0Sstevel@tonic-gate return (EACCES); 762*0Sstevel@tonic-gate 763*0Sstevel@tonic-gate ks_data = ksp->ks_data; 764*0Sstevel@tonic-gate 765*0Sstevel@tonic-gate if (secpolicy_sys_config(CRED(), B_TRUE) != 0) { 766*0Sstevel@tonic-gate ks_data->ps_ops_total.value.ui64 = 0; 767*0Sstevel@tonic-gate ks_data->ps_ops_passed.value.ui64 = 0; 768*0Sstevel@tonic-gate ks_data->ps_ops_failed.value.ui64 = 0; 769*0Sstevel@tonic-gate ks_data->ps_ops_busy_rval.value.ui64 = 0; 770*0Sstevel@tonic-gate } else { 771*0Sstevel@tonic-gate ks_data->ps_ops_total.value.ui64 = 772*0Sstevel@tonic-gate pd->pd_sched_info.ks_ndispatches; 773*0Sstevel@tonic-gate ks_data->ps_ops_failed.value.ui64 = 774*0Sstevel@tonic-gate pd->pd_sched_info.ks_nfails; 775*0Sstevel@tonic-gate ks_data->ps_ops_busy_rval.value.ui64 = 776*0Sstevel@tonic-gate pd->pd_sched_info.ks_nbusy_rval; 777*0Sstevel@tonic-gate ks_data->ps_ops_passed.value.ui64 = 778*0Sstevel@tonic-gate pd->pd_sched_info.ks_ndispatches - 779*0Sstevel@tonic-gate pd->pd_sched_info.ks_nfails - 780*0Sstevel@tonic-gate pd->pd_sched_info.ks_nbusy_rval; 781*0Sstevel@tonic-gate } 782*0Sstevel@tonic-gate 783*0Sstevel@tonic-gate return (0); 784*0Sstevel@tonic-gate } 785*0Sstevel@tonic-gate 786*0Sstevel@tonic-gate 787*0Sstevel@tonic-gate /* 788*0Sstevel@tonic-gate * Utility routine called from failure paths in crypto_register_provider() 789*0Sstevel@tonic-gate * and from crypto_load_soft_disabled(). 790*0Sstevel@tonic-gate */ 791*0Sstevel@tonic-gate void 792*0Sstevel@tonic-gate undo_register_provider(kcf_provider_desc_t *desc, boolean_t remove_prov) 793*0Sstevel@tonic-gate { 794*0Sstevel@tonic-gate uint_t mech_idx; 795*0Sstevel@tonic-gate 796*0Sstevel@tonic-gate /* remove the provider from the mechanisms tables */ 797*0Sstevel@tonic-gate for (mech_idx = 0; mech_idx < desc->pd_mech_list_count; 798*0Sstevel@tonic-gate mech_idx++) { 799*0Sstevel@tonic-gate kcf_remove_mech_provider( 800*0Sstevel@tonic-gate desc->pd_mechanisms[mech_idx].cm_mech_name, desc); 801*0Sstevel@tonic-gate } 802*0Sstevel@tonic-gate 803*0Sstevel@tonic-gate /* remove provider from providers table */ 804*0Sstevel@tonic-gate if (remove_prov) 805*0Sstevel@tonic-gate (void) kcf_prov_tab_rem_provider(desc->pd_prov_id); 806*0Sstevel@tonic-gate } 807*0Sstevel@tonic-gate 808*0Sstevel@tonic-gate /* 809*0Sstevel@tonic-gate * Utility routine called from crypto_load_soft_disabled(). Callers 810*0Sstevel@tonic-gate * should have done a prior undo_register_provider(). 811*0Sstevel@tonic-gate */ 812*0Sstevel@tonic-gate void 813*0Sstevel@tonic-gate redo_register_provider(kcf_provider_desc_t *pd) 814*0Sstevel@tonic-gate { 815*0Sstevel@tonic-gate /* process the mechanisms supported by the provider */ 816*0Sstevel@tonic-gate (void) init_prov_mechs(NULL, pd); 817*0Sstevel@tonic-gate 818*0Sstevel@tonic-gate /* 819*0Sstevel@tonic-gate * Hold provider in providers table. We should not call 820*0Sstevel@tonic-gate * kcf_prov_tab_add_provider() here as the provider descriptor 821*0Sstevel@tonic-gate * is still valid which means it has an entry in the provider 822*0Sstevel@tonic-gate * table. 823*0Sstevel@tonic-gate */ 824*0Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 825*0Sstevel@tonic-gate KCF_PROV_IREFHOLD(pd); 826*0Sstevel@tonic-gate } 827*0Sstevel@tonic-gate 828*0Sstevel@tonic-gate /* 829*0Sstevel@tonic-gate * Add provider (p1) to another provider's array of providers (p2). 830*0Sstevel@tonic-gate * Hardware and logical providers use this array to cross-reference 831*0Sstevel@tonic-gate * each other. 832*0Sstevel@tonic-gate */ 833*0Sstevel@tonic-gate static void 834*0Sstevel@tonic-gate add_provider_to_array(kcf_provider_desc_t *p1, kcf_provider_desc_t *p2) 835*0Sstevel@tonic-gate { 836*0Sstevel@tonic-gate kcf_provider_list_t *new; 837*0Sstevel@tonic-gate 838*0Sstevel@tonic-gate new = kmem_alloc(sizeof (kcf_provider_list_t), KM_SLEEP); 839*0Sstevel@tonic-gate mutex_enter(&p2->pd_lock); 840*0Sstevel@tonic-gate new->pl_next = p2->pd_provider_list; 841*0Sstevel@tonic-gate p2->pd_provider_list = new; 842*0Sstevel@tonic-gate KCF_PROV_IREFHOLD(p1); 843*0Sstevel@tonic-gate new->pl_provider = p1; 844*0Sstevel@tonic-gate mutex_exit(&p2->pd_lock); 845*0Sstevel@tonic-gate } 846*0Sstevel@tonic-gate 847*0Sstevel@tonic-gate /* 848*0Sstevel@tonic-gate * Remove provider (p1) from another provider's array of providers (p2). 849*0Sstevel@tonic-gate * Hardware and logical providers use this array to cross-reference 850*0Sstevel@tonic-gate * each other. 851*0Sstevel@tonic-gate */ 852*0Sstevel@tonic-gate static void 853*0Sstevel@tonic-gate remove_provider_from_array(kcf_provider_desc_t *p1, kcf_provider_desc_t *p2) 854*0Sstevel@tonic-gate { 855*0Sstevel@tonic-gate 856*0Sstevel@tonic-gate kcf_provider_list_t *pl = NULL, **prev; 857*0Sstevel@tonic-gate 858*0Sstevel@tonic-gate mutex_enter(&p2->pd_lock); 859*0Sstevel@tonic-gate for (pl = p2->pd_provider_list, prev = &p2->pd_provider_list; 860*0Sstevel@tonic-gate pl != NULL; prev = &pl->pl_next, pl = pl->pl_next) { 861*0Sstevel@tonic-gate if (pl->pl_provider == p1) { 862*0Sstevel@tonic-gate break; 863*0Sstevel@tonic-gate } 864*0Sstevel@tonic-gate } 865*0Sstevel@tonic-gate 866*0Sstevel@tonic-gate if (p1 == NULL) { 867*0Sstevel@tonic-gate mutex_exit(&p2->pd_lock); 868*0Sstevel@tonic-gate return; 869*0Sstevel@tonic-gate } 870*0Sstevel@tonic-gate 871*0Sstevel@tonic-gate /* detach and free kcf_provider_list structure */ 872*0Sstevel@tonic-gate KCF_PROV_IREFRELE(p1); 873*0Sstevel@tonic-gate *prev = pl->pl_next; 874*0Sstevel@tonic-gate kmem_free(pl, sizeof (*pl)); 875*0Sstevel@tonic-gate mutex_exit(&p2->pd_lock); 876*0Sstevel@tonic-gate } 877*0Sstevel@tonic-gate 878*0Sstevel@tonic-gate /* 879*0Sstevel@tonic-gate * Convert an array of logical provider handles (crypto_provider_id) 880*0Sstevel@tonic-gate * stored in a crypto_provider_info structure into an array of provider 881*0Sstevel@tonic-gate * descriptors (kcf_provider_desc_t) attached to a logical provider. 882*0Sstevel@tonic-gate */ 883*0Sstevel@tonic-gate static void 884*0Sstevel@tonic-gate process_logical_providers(crypto_provider_info_t *info, kcf_provider_desc_t *hp) 885*0Sstevel@tonic-gate { 886*0Sstevel@tonic-gate kcf_provider_desc_t *lp; 887*0Sstevel@tonic-gate crypto_provider_id_t handle; 888*0Sstevel@tonic-gate int count = info->pi_logical_provider_count; 889*0Sstevel@tonic-gate int i; 890*0Sstevel@tonic-gate 891*0Sstevel@tonic-gate /* add hardware provider to each logical provider */ 892*0Sstevel@tonic-gate for (i = 0; i < count; i++) { 893*0Sstevel@tonic-gate handle = info->pi_logical_providers[i]; 894*0Sstevel@tonic-gate lp = kcf_prov_tab_lookup((crypto_provider_id_t)handle); 895*0Sstevel@tonic-gate if (lp == NULL) { 896*0Sstevel@tonic-gate continue; 897*0Sstevel@tonic-gate } 898*0Sstevel@tonic-gate add_provider_to_array(hp, lp); 899*0Sstevel@tonic-gate 900*0Sstevel@tonic-gate /* 901*0Sstevel@tonic-gate * A hardware provider has to have the provider descriptor of 902*0Sstevel@tonic-gate * every logical provider it belongs to, so it can be removed 903*0Sstevel@tonic-gate * from the logical provider if the hardware provider 904*0Sstevel@tonic-gate * unregisters from the framework. 905*0Sstevel@tonic-gate */ 906*0Sstevel@tonic-gate add_provider_to_array(lp, hp); 907*0Sstevel@tonic-gate KCF_PROV_REFRELE(lp); 908*0Sstevel@tonic-gate } 909*0Sstevel@tonic-gate } 910*0Sstevel@tonic-gate 911*0Sstevel@tonic-gate /* 912*0Sstevel@tonic-gate * This routine removes a provider from all of the logical or 913*0Sstevel@tonic-gate * hardware providers it belongs to, and frees the provider's 914*0Sstevel@tonic-gate * array of pointers to providers. 915*0Sstevel@tonic-gate */ 916*0Sstevel@tonic-gate static void 917*0Sstevel@tonic-gate remove_provider(kcf_provider_desc_t *pp) 918*0Sstevel@tonic-gate { 919*0Sstevel@tonic-gate kcf_provider_desc_t *p; 920*0Sstevel@tonic-gate kcf_provider_list_t *e, *next; 921*0Sstevel@tonic-gate 922*0Sstevel@tonic-gate mutex_enter(&pp->pd_lock); 923*0Sstevel@tonic-gate for (e = pp->pd_provider_list; e != NULL; e = next) { 924*0Sstevel@tonic-gate p = e->pl_provider; 925*0Sstevel@tonic-gate remove_provider_from_array(pp, p); 926*0Sstevel@tonic-gate KCF_PROV_IREFRELE(p); 927*0Sstevel@tonic-gate next = e->pl_next; 928*0Sstevel@tonic-gate kmem_free(e, sizeof (*e)); 929*0Sstevel@tonic-gate } 930*0Sstevel@tonic-gate pp->pd_provider_list = NULL; 931*0Sstevel@tonic-gate mutex_exit(&pp->pd_lock); 932*0Sstevel@tonic-gate } 933