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 2004 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 #include <sys/types.h> 30*0Sstevel@tonic-gate #include <sys/sunddi.h> 31*0Sstevel@tonic-gate #include <sys/disp.h> 32*0Sstevel@tonic-gate #include <sys/modctl.h> 33*0Sstevel@tonic-gate #include <sys/crypto/common.h> 34*0Sstevel@tonic-gate #include <sys/crypto/api.h> 35*0Sstevel@tonic-gate #include <sys/crypto/impl.h> 36*0Sstevel@tonic-gate #include <sys/crypto/sched_impl.h> 37*0Sstevel@tonic-gate 38*0Sstevel@tonic-gate /* Miscellaneous exported entry points */ 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gate /* 41*0Sstevel@tonic-gate * All event subscribers are put on a list. kcf_notify_list_lock 42*0Sstevel@tonic-gate * protects changes to this list. 43*0Sstevel@tonic-gate * 44*0Sstevel@tonic-gate * The following locking order is maintained in the code - The 45*0Sstevel@tonic-gate * global kcf_notify_list_lock followed by the individual lock 46*0Sstevel@tonic-gate * in a kcf_ntfy_elem structure (kn_lock). 47*0Sstevel@tonic-gate */ 48*0Sstevel@tonic-gate kmutex_t ntfy_list_lock; 49*0Sstevel@tonic-gate kcondvar_t ntfy_list_cv; /* cv the service thread waits on */ 50*0Sstevel@tonic-gate static kcf_ntfy_elem_t *ntfy_list_head; 51*0Sstevel@tonic-gate static kcf_ntfy_elem_t *ntfy_list_tail; 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate /* count all the hardware and software providers */ 54*0Sstevel@tonic-gate #define PROV_COUNT(me) \ 55*0Sstevel@tonic-gate (((me)->me_sw_prov != NULL ? 1 : 0) + (me)->me_num_hwprov) 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate /* 58*0Sstevel@tonic-gate * crypto_mech2id() 59*0Sstevel@tonic-gate * 60*0Sstevel@tonic-gate * Arguments: 61*0Sstevel@tonic-gate * . mechname: A null-terminated string identifying the mechanism name. 62*0Sstevel@tonic-gate * 63*0Sstevel@tonic-gate * Description: 64*0Sstevel@tonic-gate * Walks the mechanisms tables, looking for an entry that matches the 65*0Sstevel@tonic-gate * mechname. Once it find it, it builds the 64-bit mech_type and returns 66*0Sstevel@tonic-gate * it. If there are no hardware or software providers for the mechanism, 67*0Sstevel@tonic-gate * but there is an unloaded software provider, this routine will attempt 68*0Sstevel@tonic-gate * to load it. 69*0Sstevel@tonic-gate * 70*0Sstevel@tonic-gate * Context: 71*0Sstevel@tonic-gate * Process and interruption. 72*0Sstevel@tonic-gate * 73*0Sstevel@tonic-gate * Returns: 74*0Sstevel@tonic-gate * The unique mechanism identified by 'mechname', if found. 75*0Sstevel@tonic-gate * CRYPTO_MECH_INVALID otherwise. 76*0Sstevel@tonic-gate */ 77*0Sstevel@tonic-gate crypto_mech_type_t 78*0Sstevel@tonic-gate crypto_mech2id(char *mechname) 79*0Sstevel@tonic-gate { 80*0Sstevel@tonic-gate return (crypto_mech2id_common(mechname, B_TRUE)); 81*0Sstevel@tonic-gate } 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate /* 84*0Sstevel@tonic-gate * crypto_get_mech_list() 85*0Sstevel@tonic-gate * 86*0Sstevel@tonic-gate * Arguments: 87*0Sstevel@tonic-gate * . countp: pointer to contain the number of mech names returned 88*0Sstevel@tonic-gate * . kmflag: memory allocation flag. 89*0Sstevel@tonic-gate * 90*0Sstevel@tonic-gate * Description: 91*0Sstevel@tonic-gate * Allocates an array of crypto_mech_name_t containing all the mechanisms 92*0Sstevel@tonic-gate * currently available on the system. Sets *countp with the number of 93*0Sstevel@tonic-gate * mechanism names returned. 94*0Sstevel@tonic-gate * 95*0Sstevel@tonic-gate * We get a list of mech names which have a hardware provider by walking 96*0Sstevel@tonic-gate * all the mechanism tables. We merge them with mech names obtained from 97*0Sstevel@tonic-gate * the hint list. A mech name in the hint list is considered only if it 98*0Sstevel@tonic-gate * is not disabled for the provider. Note that the hint list contains only 99*0Sstevel@tonic-gate * software providers and the mech names supported by them. 100*0Sstevel@tonic-gate * 101*0Sstevel@tonic-gate * Context: 102*0Sstevel@tonic-gate * Process and interruption. kmflag should be KM_NOSLEEP when called 103*0Sstevel@tonic-gate * from an interruption context. 104*0Sstevel@tonic-gate * 105*0Sstevel@tonic-gate * Returns: 106*0Sstevel@tonic-gate * The array of the crypto_mech_t allocated. 107*0Sstevel@tonic-gate * NULL otherwise. 108*0Sstevel@tonic-gate */ 109*0Sstevel@tonic-gate crypto_mech_name_t * 110*0Sstevel@tonic-gate crypto_get_mech_list(uint_t *countp, int kmflag) 111*0Sstevel@tonic-gate { 112*0Sstevel@tonic-gate uint_t count = 0, me_tab_size, i, j; 113*0Sstevel@tonic-gate kcf_ops_class_t cl; 114*0Sstevel@tonic-gate kcf_mech_entry_t *me, *me_tab; 115*0Sstevel@tonic-gate crypto_mech_name_t *mech_name_tab, *tmp_mech_name_tab; 116*0Sstevel@tonic-gate char *mech_name, *hint_mech, *end; 117*0Sstevel@tonic-gate kcf_soft_conf_entry_t *p; 118*0Sstevel@tonic-gate size_t n; 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate /* 121*0Sstevel@tonic-gate * Count the maximum possible mechanisms that can come from the 122*0Sstevel@tonic-gate * hint list. 123*0Sstevel@tonic-gate */ 124*0Sstevel@tonic-gate mutex_enter(&soft_config_mutex); 125*0Sstevel@tonic-gate p = soft_config_list; 126*0Sstevel@tonic-gate while (p != NULL) { 127*0Sstevel@tonic-gate count += p->ce_count; 128*0Sstevel@tonic-gate p = p->ce_next; 129*0Sstevel@tonic-gate } 130*0Sstevel@tonic-gate mutex_exit(&soft_config_mutex); 131*0Sstevel@tonic-gate 132*0Sstevel@tonic-gate /* First let's count'em, for mem allocation */ 133*0Sstevel@tonic-gate for (cl = KCF_FIRST_OPSCLASS; cl <= KCF_LAST_OPSCLASS; cl++) { 134*0Sstevel@tonic-gate me_tab_size = kcf_mech_tabs_tab[cl].met_size; 135*0Sstevel@tonic-gate me_tab = kcf_mech_tabs_tab[cl].met_tab; 136*0Sstevel@tonic-gate for (i = 0; i < me_tab_size; i++) { 137*0Sstevel@tonic-gate me = &me_tab[i]; 138*0Sstevel@tonic-gate mutex_enter(&(me->me_mutex)); 139*0Sstevel@tonic-gate if ((me->me_name[0] != 0) && (me->me_num_hwprov >= 1)) { 140*0Sstevel@tonic-gate ASSERT(me->me_hw_prov_chain != NULL); 141*0Sstevel@tonic-gate count++; 142*0Sstevel@tonic-gate } 143*0Sstevel@tonic-gate mutex_exit(&(me->me_mutex)); 144*0Sstevel@tonic-gate } 145*0Sstevel@tonic-gate } 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate /* 148*0Sstevel@tonic-gate * Allocate a buffer to hold the mechanisms from 149*0Sstevel@tonic-gate * mech tabs and mechanisms from the hint list. 150*0Sstevel@tonic-gate */ 151*0Sstevel@tonic-gate n = count * CRYPTO_MAX_MECH_NAME; 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate again: 154*0Sstevel@tonic-gate count = 0; 155*0Sstevel@tonic-gate tmp_mech_name_tab = kmem_zalloc(n, kmflag); 156*0Sstevel@tonic-gate if (tmp_mech_name_tab == NULL) { 157*0Sstevel@tonic-gate *countp = 0; 158*0Sstevel@tonic-gate return (NULL); 159*0Sstevel@tonic-gate } 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate /* 162*0Sstevel@tonic-gate * Second round, fill in the table 163*0Sstevel@tonic-gate */ 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate mech_name = (char *)tmp_mech_name_tab; 166*0Sstevel@tonic-gate end = mech_name + n; 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate for (cl = KCF_FIRST_OPSCLASS; cl <= KCF_LAST_OPSCLASS; cl++) { 169*0Sstevel@tonic-gate me_tab_size = kcf_mech_tabs_tab[cl].met_size; 170*0Sstevel@tonic-gate me_tab = kcf_mech_tabs_tab[cl].met_tab; 171*0Sstevel@tonic-gate for (i = 0; i < me_tab_size; i++) { 172*0Sstevel@tonic-gate me = &me_tab[i]; 173*0Sstevel@tonic-gate mutex_enter(&(me->me_mutex)); 174*0Sstevel@tonic-gate if ((me->me_name[0] != 0) && (me->me_num_hwprov >= 1)) { 175*0Sstevel@tonic-gate ASSERT(me->me_hw_prov_chain != NULL); 176*0Sstevel@tonic-gate if ((mech_name + CRYPTO_MAX_MECH_NAME) > end) { 177*0Sstevel@tonic-gate mutex_exit(&(me->me_mutex)); 178*0Sstevel@tonic-gate kmem_free(tmp_mech_name_tab, n); 179*0Sstevel@tonic-gate n = n << 1; 180*0Sstevel@tonic-gate goto again; 181*0Sstevel@tonic-gate } 182*0Sstevel@tonic-gate (void) strncpy(mech_name, me->me_name, 183*0Sstevel@tonic-gate CRYPTO_MAX_MECH_NAME); 184*0Sstevel@tonic-gate 185*0Sstevel@tonic-gate mech_name += CRYPTO_MAX_MECH_NAME; 186*0Sstevel@tonic-gate count++; 187*0Sstevel@tonic-gate } 188*0Sstevel@tonic-gate mutex_exit(&(me->me_mutex)); 189*0Sstevel@tonic-gate } 190*0Sstevel@tonic-gate } 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate /* 193*0Sstevel@tonic-gate * Search tmp_mech_name_tab for each mechanism in the hint list. We 194*0Sstevel@tonic-gate * have to add any new mechanisms found in the hint list. Note that we 195*0Sstevel@tonic-gate * should not modload the providers here as it will be too early. It 196*0Sstevel@tonic-gate * may be the case that the caller never uses a provider. 197*0Sstevel@tonic-gate */ 198*0Sstevel@tonic-gate mutex_enter(&soft_config_mutex); 199*0Sstevel@tonic-gate p = soft_config_list; 200*0Sstevel@tonic-gate while (p != NULL) { 201*0Sstevel@tonic-gate for (i = 0; i < p->ce_count; i++) { 202*0Sstevel@tonic-gate hint_mech = p->ce_mechs[i]; 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate /* Do not consider the mechanism if it is disabled. */ 205*0Sstevel@tonic-gate if (is_mech_disabled_byname(CRYPTO_SW_PROVIDER, 206*0Sstevel@tonic-gate p->ce_name, 0, hint_mech)) 207*0Sstevel@tonic-gate continue; 208*0Sstevel@tonic-gate 209*0Sstevel@tonic-gate /* 210*0Sstevel@tonic-gate * There may be duplicate mechanisms in the hint list. 211*0Sstevel@tonic-gate * So, we need to search all the entries that have been 212*0Sstevel@tonic-gate * added so far. That number would be count. 213*0Sstevel@tonic-gate */ 214*0Sstevel@tonic-gate for (j = 0; j < count; j++) { 215*0Sstevel@tonic-gate if (strcmp(hint_mech, 216*0Sstevel@tonic-gate tmp_mech_name_tab[j]) == 0) 217*0Sstevel@tonic-gate break; 218*0Sstevel@tonic-gate } 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gate if (j == count) { /* This is a new one. Add it. */ 221*0Sstevel@tonic-gate ASSERT((char *)&tmp_mech_name_tab[count] == 222*0Sstevel@tonic-gate mech_name); 223*0Sstevel@tonic-gate if ((mech_name + CRYPTO_MAX_MECH_NAME) > end) { 224*0Sstevel@tonic-gate mutex_exit(&soft_config_mutex); 225*0Sstevel@tonic-gate kmem_free(tmp_mech_name_tab, n); 226*0Sstevel@tonic-gate n = n << 1; 227*0Sstevel@tonic-gate goto again; 228*0Sstevel@tonic-gate } 229*0Sstevel@tonic-gate (void) strncpy(tmp_mech_name_tab[count], 230*0Sstevel@tonic-gate hint_mech, CRYPTO_MAX_MECH_NAME); 231*0Sstevel@tonic-gate mech_name += CRYPTO_MAX_MECH_NAME; 232*0Sstevel@tonic-gate count++; 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate } 235*0Sstevel@tonic-gate p = p->ce_next; 236*0Sstevel@tonic-gate } 237*0Sstevel@tonic-gate mutex_exit(&soft_config_mutex); 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gate /* 240*0Sstevel@tonic-gate * Check if we have consumed all of the space. We are done if 241*0Sstevel@tonic-gate * this is the case. 242*0Sstevel@tonic-gate */ 243*0Sstevel@tonic-gate ASSERT(mech_name <= end); 244*0Sstevel@tonic-gate if (mech_name == end) { 245*0Sstevel@tonic-gate mech_name_tab = tmp_mech_name_tab; 246*0Sstevel@tonic-gate goto done; 247*0Sstevel@tonic-gate } 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate /* 250*0Sstevel@tonic-gate * Allocate a buffer of the right size now that we have the 251*0Sstevel@tonic-gate * correct count. 252*0Sstevel@tonic-gate */ 253*0Sstevel@tonic-gate mech_name_tab = kmem_zalloc(count * CRYPTO_MAX_MECH_NAME, kmflag); 254*0Sstevel@tonic-gate if (mech_name_tab == NULL) { 255*0Sstevel@tonic-gate kmem_free(tmp_mech_name_tab, n); 256*0Sstevel@tonic-gate *countp = 0; 257*0Sstevel@tonic-gate return (NULL); 258*0Sstevel@tonic-gate } 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate bcopy(tmp_mech_name_tab, mech_name_tab, count * CRYPTO_MAX_MECH_NAME); 261*0Sstevel@tonic-gate kmem_free(tmp_mech_name_tab, n); 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gate done: 264*0Sstevel@tonic-gate *countp = count; 265*0Sstevel@tonic-gate return (mech_name_tab); 266*0Sstevel@tonic-gate } 267*0Sstevel@tonic-gate 268*0Sstevel@tonic-gate /* 269*0Sstevel@tonic-gate * crypto_free_mech_list() 270*0Sstevel@tonic-gate * 271*0Sstevel@tonic-gate * Arguments: 272*0Sstevel@tonic-gate * . mech_names: An array of crypto_mech_name_t previously allocated by 273*0Sstevel@tonic-gate * crypto_get_mech_list. 274*0Sstevel@tonic-gate * . count: the number of mech names in mech_names 275*0Sstevel@tonic-gate * 276*0Sstevel@tonic-gate * Description: 277*0Sstevel@tonic-gate * Frees the the mech_names array. 278*0Sstevel@tonic-gate * 279*0Sstevel@tonic-gate * Context: 280*0Sstevel@tonic-gate * Process and interruption. 281*0Sstevel@tonic-gate */ 282*0Sstevel@tonic-gate void 283*0Sstevel@tonic-gate crypto_free_mech_list(crypto_mech_name_t *mech_names, uint_t count) 284*0Sstevel@tonic-gate { 285*0Sstevel@tonic-gate if ((mech_names != NULL) && (count > 0)) 286*0Sstevel@tonic-gate kmem_free(mech_names, count * CRYPTO_MAX_MECH_NAME); 287*0Sstevel@tonic-gate } 288*0Sstevel@tonic-gate 289*0Sstevel@tonic-gate /* 290*0Sstevel@tonic-gate * crypto_notify_events() 291*0Sstevel@tonic-gate * 292*0Sstevel@tonic-gate * Arguments: 293*0Sstevel@tonic-gate * . nf: Callback function to invoke when event occurs. 294*0Sstevel@tonic-gate * . event_mask: Mask of events. 295*0Sstevel@tonic-gate * 296*0Sstevel@tonic-gate * Description: 297*0Sstevel@tonic-gate * Allocates a new element and inserts it in to the notification 298*0Sstevel@tonic-gate * list. 299*0Sstevel@tonic-gate * 300*0Sstevel@tonic-gate * Context: 301*0Sstevel@tonic-gate * Process context. 302*0Sstevel@tonic-gate * 303*0Sstevel@tonic-gate * Returns: 304*0Sstevel@tonic-gate * A handle is returned if the client is put on the notification list. 305*0Sstevel@tonic-gate * NULL is returned otherwise. 306*0Sstevel@tonic-gate */ 307*0Sstevel@tonic-gate crypto_notify_handle_t 308*0Sstevel@tonic-gate crypto_notify_events(crypto_notify_callback_t nf, uint32_t event_mask) 309*0Sstevel@tonic-gate { 310*0Sstevel@tonic-gate kcf_ntfy_elem_t *nep; 311*0Sstevel@tonic-gate crypto_notify_handle_t hndl; 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate /* 314*0Sstevel@tonic-gate * The only valid value for event_mask is CRYPTO_EVENT_PROVIDERS_CHANGE. 315*0Sstevel@tonic-gate */ 316*0Sstevel@tonic-gate if (nf == NULL || !(event_mask & CRYPTO_EVENT_PROVIDERS_CHANGE)) { 317*0Sstevel@tonic-gate return (NULL); 318*0Sstevel@tonic-gate } 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate nep = kmem_zalloc(sizeof (kcf_ntfy_elem_t), KM_SLEEP); 321*0Sstevel@tonic-gate mutex_init(&nep->kn_lock, NULL, MUTEX_DEFAULT, NULL); 322*0Sstevel@tonic-gate cv_init(&nep->kn_cv, NULL, CV_DEFAULT, NULL); 323*0Sstevel@tonic-gate nep->kn_state = NTFY_WAITING; 324*0Sstevel@tonic-gate nep->kn_func = nf; 325*0Sstevel@tonic-gate nep->kn_event_mask = event_mask; 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate mutex_enter(&ntfy_list_lock); 328*0Sstevel@tonic-gate if (ntfy_list_head == NULL) { 329*0Sstevel@tonic-gate ntfy_list_head = ntfy_list_tail = nep; 330*0Sstevel@tonic-gate } else { 331*0Sstevel@tonic-gate ntfy_list_tail->kn_next = nep; 332*0Sstevel@tonic-gate nep->kn_prev = ntfy_list_tail; 333*0Sstevel@tonic-gate ntfy_list_tail = nep; 334*0Sstevel@tonic-gate } 335*0Sstevel@tonic-gate 336*0Sstevel@tonic-gate hndl = (crypto_notify_handle_t)nep; 337*0Sstevel@tonic-gate mutex_exit(&ntfy_list_lock); 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate return (hndl); 340*0Sstevel@tonic-gate } 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate /* 343*0Sstevel@tonic-gate * crypto_unnotify_events() 344*0Sstevel@tonic-gate * 345*0Sstevel@tonic-gate * Arguments: 346*0Sstevel@tonic-gate * . hndl - Handle returned from an earlier crypto_notify_events(). 347*0Sstevel@tonic-gate * 348*0Sstevel@tonic-gate * Description: 349*0Sstevel@tonic-gate * Removes the element specified by hndl from the notification list. 350*0Sstevel@tonic-gate * We wait for the notification routine to complete, if the routine 351*0Sstevel@tonic-gate * is currently being called. We also free the element. 352*0Sstevel@tonic-gate * 353*0Sstevel@tonic-gate * Context: 354*0Sstevel@tonic-gate * Process context. 355*0Sstevel@tonic-gate */ 356*0Sstevel@tonic-gate void 357*0Sstevel@tonic-gate crypto_unnotify_events(crypto_notify_handle_t hndl) 358*0Sstevel@tonic-gate { 359*0Sstevel@tonic-gate kcf_ntfy_elem_t *nep = (kcf_ntfy_elem_t *)hndl; 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate if (hndl == NULL) 362*0Sstevel@tonic-gate return; 363*0Sstevel@tonic-gate 364*0Sstevel@tonic-gate retry: 365*0Sstevel@tonic-gate mutex_enter(&ntfy_list_lock); 366*0Sstevel@tonic-gate mutex_enter(&nep->kn_lock); 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate if (nep->kn_state == NTFY_WAITING) { 369*0Sstevel@tonic-gate kcf_ntfy_elem_t *nextp = nep->kn_next; 370*0Sstevel@tonic-gate kcf_ntfy_elem_t *prevp = nep->kn_prev; 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate if (nextp != NULL) 373*0Sstevel@tonic-gate nextp->kn_prev = prevp; 374*0Sstevel@tonic-gate else 375*0Sstevel@tonic-gate ntfy_list_tail = prevp; 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gate if (prevp != NULL) 378*0Sstevel@tonic-gate prevp->kn_next = nextp; 379*0Sstevel@tonic-gate else 380*0Sstevel@tonic-gate ntfy_list_head = nextp; 381*0Sstevel@tonic-gate } else { 382*0Sstevel@tonic-gate ASSERT(nep->kn_state == NTFY_RUNNING); 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate /* 385*0Sstevel@tonic-gate * We have to drop this lock as the client might call 386*0Sstevel@tonic-gate * crypto_notify_events() in the callback routine resulting 387*0Sstevel@tonic-gate * in a deadlock. 388*0Sstevel@tonic-gate */ 389*0Sstevel@tonic-gate mutex_exit(&ntfy_list_lock); 390*0Sstevel@tonic-gate 391*0Sstevel@tonic-gate /* 392*0Sstevel@tonic-gate * Another thread is working on this element. We will wait 393*0Sstevel@tonic-gate * for that thread to signal us when done. No other thread 394*0Sstevel@tonic-gate * will free this element. So, we can be sure it stays valid 395*0Sstevel@tonic-gate * after the wait. 396*0Sstevel@tonic-gate */ 397*0Sstevel@tonic-gate while (nep->kn_state == NTFY_RUNNING) 398*0Sstevel@tonic-gate cv_wait(&nep->kn_cv, &nep->kn_lock); 399*0Sstevel@tonic-gate mutex_exit(&nep->kn_lock); 400*0Sstevel@tonic-gate 401*0Sstevel@tonic-gate /* 402*0Sstevel@tonic-gate * We have to remove the element from the notification list. 403*0Sstevel@tonic-gate * So, start over and do the work (acquire locks etc.). This is 404*0Sstevel@tonic-gate * safe (i.e. We won't be in this routine forever) as the 405*0Sstevel@tonic-gate * CRYPTO_EVENT_PROVIDERS_CHANGE event does not happen 406*0Sstevel@tonic-gate * frequently. We have to revisit this code if we 407*0Sstevel@tonic-gate * add a new event that happens often. 408*0Sstevel@tonic-gate */ 409*0Sstevel@tonic-gate goto retry; 410*0Sstevel@tonic-gate } 411*0Sstevel@tonic-gate 412*0Sstevel@tonic-gate mutex_exit(&nep->kn_lock); 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate /* Free the element */ 415*0Sstevel@tonic-gate mutex_destroy(&nep->kn_lock); 416*0Sstevel@tonic-gate cv_destroy(&nep->kn_cv); 417*0Sstevel@tonic-gate kmem_free(nep, sizeof (kcf_ntfy_elem_t)); 418*0Sstevel@tonic-gate 419*0Sstevel@tonic-gate mutex_exit(&ntfy_list_lock); 420*0Sstevel@tonic-gate } 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate /* 423*0Sstevel@tonic-gate * This routine is called from crypto_register_provider() and 424*0Sstevel@tonic-gate * crypto_unregister_provider() with the CRYPTO_EVENT_PROVIDERS_CHANGE event. 425*0Sstevel@tonic-gate * 426*0Sstevel@tonic-gate * We walk the notification list and do the callbacks. 427*0Sstevel@tonic-gate */ 428*0Sstevel@tonic-gate void 429*0Sstevel@tonic-gate kcf_walk_ntfylist(uint32_t event, void *event_arg) 430*0Sstevel@tonic-gate { 431*0Sstevel@tonic-gate kcf_ntfy_elem_t *nep; 432*0Sstevel@tonic-gate int nelem = 0; 433*0Sstevel@tonic-gate 434*0Sstevel@tonic-gate mutex_enter(&ntfy_list_lock); 435*0Sstevel@tonic-gate 436*0Sstevel@tonic-gate /* 437*0Sstevel@tonic-gate * Count how many clients are on the notification list. We need 438*0Sstevel@tonic-gate * this count to ensure that clients which joined the list after we 439*0Sstevel@tonic-gate * have started this walk, are not wrongly notified. 440*0Sstevel@tonic-gate */ 441*0Sstevel@tonic-gate for (nep = ntfy_list_head; nep != NULL; nep = nep->kn_next) 442*0Sstevel@tonic-gate nelem++; 443*0Sstevel@tonic-gate 444*0Sstevel@tonic-gate for (nep = ntfy_list_head; (nep != NULL && nelem); nep = nep->kn_next) { 445*0Sstevel@tonic-gate nelem--; 446*0Sstevel@tonic-gate 447*0Sstevel@tonic-gate /* 448*0Sstevel@tonic-gate * Check if this client is interested in the 449*0Sstevel@tonic-gate * event. 450*0Sstevel@tonic-gate */ 451*0Sstevel@tonic-gate if (!(nep->kn_event_mask & event)) 452*0Sstevel@tonic-gate continue; 453*0Sstevel@tonic-gate 454*0Sstevel@tonic-gate mutex_enter(&nep->kn_lock); 455*0Sstevel@tonic-gate nep->kn_state = NTFY_RUNNING; 456*0Sstevel@tonic-gate mutex_exit(&nep->kn_lock); 457*0Sstevel@tonic-gate mutex_exit(&ntfy_list_lock); 458*0Sstevel@tonic-gate 459*0Sstevel@tonic-gate /* 460*0Sstevel@tonic-gate * We invoke the callback routine with no locks held. Another 461*0Sstevel@tonic-gate * client could have joined the list meanwhile. This is fine 462*0Sstevel@tonic-gate * as we maintain nelem as stated above. The NULL check in the 463*0Sstevel@tonic-gate * for loop guards against shrinkage. Also, any callers of 464*0Sstevel@tonic-gate * crypto_unnotify_events() at this point cv_wait till kn_state 465*0Sstevel@tonic-gate * changes to NTFY_WAITING. Hence, nep is assured to be valid. 466*0Sstevel@tonic-gate */ 467*0Sstevel@tonic-gate (*nep->kn_func)(event, event_arg); 468*0Sstevel@tonic-gate 469*0Sstevel@tonic-gate mutex_enter(&nep->kn_lock); 470*0Sstevel@tonic-gate nep->kn_state = NTFY_WAITING; 471*0Sstevel@tonic-gate cv_broadcast(&nep->kn_cv); 472*0Sstevel@tonic-gate mutex_exit(&nep->kn_lock); 473*0Sstevel@tonic-gate 474*0Sstevel@tonic-gate mutex_enter(&ntfy_list_lock); 475*0Sstevel@tonic-gate } 476*0Sstevel@tonic-gate 477*0Sstevel@tonic-gate mutex_exit(&ntfy_list_lock); 478*0Sstevel@tonic-gate } 479*0Sstevel@tonic-gate 480*0Sstevel@tonic-gate /* 481*0Sstevel@tonic-gate * crypto_key_check() 482*0Sstevel@tonic-gate * 483*0Sstevel@tonic-gate * Arguments: 484*0Sstevel@tonic-gate * . mech: the mechanism to check the key with. 485*0Sstevel@tonic-gate * . key: the key to check for validity and weakness. 486*0Sstevel@tonic-gate * 487*0Sstevel@tonic-gate * Description: 488*0Sstevel@tonic-gate * Checks the validity and strength of the key for the mechanism. 489*0Sstevel@tonic-gate * CRYPTO_KEY_REFERENCE is not supported for this routine. 490*0Sstevel@tonic-gate * If more than one provider is capable of key checking for the mechanism, 491*0Sstevel@tonic-gate * then run the key through them all. 492*0Sstevel@tonic-gate * A conservative approach is adopted here: New weak keys may be 493*0Sstevel@tonic-gate * discovered with more recent providers. If at least one provider is 494*0Sstevel@tonic-gate * not happy with a key, then it is no good. 495*0Sstevel@tonic-gate * 496*0Sstevel@tonic-gate * Context: 497*0Sstevel@tonic-gate * Process and interruption. 498*0Sstevel@tonic-gate */ 499*0Sstevel@tonic-gate int 500*0Sstevel@tonic-gate crypto_key_check(crypto_mechanism_t *mech, crypto_key_t *key) 501*0Sstevel@tonic-gate { 502*0Sstevel@tonic-gate int error; 503*0Sstevel@tonic-gate kcf_mech_entry_t *me; 504*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 505*0Sstevel@tonic-gate kcf_prov_mech_desc_t *prov_chain; 506*0Sstevel@tonic-gate 507*0Sstevel@tonic-gate /* when mech is a valid mechanism, me will be its mech_entry */ 508*0Sstevel@tonic-gate if ((mech == NULL) || (key == NULL) || 509*0Sstevel@tonic-gate (key->ck_format == CRYPTO_KEY_REFERENCE)) 510*0Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 511*0Sstevel@tonic-gate 512*0Sstevel@tonic-gate if ((error = kcf_get_mech_entry(mech->cm_type, &me)) != KCF_SUCCESS) { 513*0Sstevel@tonic-gate /* error is one of the KCF_INVALID_MECH_XXX's */ 514*0Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 515*0Sstevel@tonic-gate } 516*0Sstevel@tonic-gate 517*0Sstevel@tonic-gate mutex_enter(&me->me_mutex); 518*0Sstevel@tonic-gate 519*0Sstevel@tonic-gate /* First let the software provider check this key */ 520*0Sstevel@tonic-gate if (me->me_sw_prov != NULL) { 521*0Sstevel@tonic-gate pd = me->me_sw_prov->pm_prov_desc; 522*0Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 523*0Sstevel@tonic-gate 524*0Sstevel@tonic-gate if ((KCF_PROV_KEY_OPS(pd) != NULL) && 525*0Sstevel@tonic-gate (KCF_PROV_KEY_OPS(pd)->key_check != NULL)) { 526*0Sstevel@tonic-gate crypto_mechanism_t lmech; 527*0Sstevel@tonic-gate 528*0Sstevel@tonic-gate mutex_exit(&me->me_mutex); 529*0Sstevel@tonic-gate lmech = *mech; 530*0Sstevel@tonic-gate KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech); 531*0Sstevel@tonic-gate error = KCF_PROV_KEY_CHECK(pd, &lmech, key); 532*0Sstevel@tonic-gate 533*0Sstevel@tonic-gate if (error != CRYPTO_SUCCESS) { 534*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 535*0Sstevel@tonic-gate return (error); 536*0Sstevel@tonic-gate } 537*0Sstevel@tonic-gate 538*0Sstevel@tonic-gate mutex_enter(&me->me_mutex); 539*0Sstevel@tonic-gate } 540*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 541*0Sstevel@tonic-gate } 542*0Sstevel@tonic-gate 543*0Sstevel@tonic-gate prov_chain = me->me_hw_prov_chain; 544*0Sstevel@tonic-gate while (prov_chain != NULL) { 545*0Sstevel@tonic-gate pd = prov_chain->pm_prov_desc; 546*0Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 547*0Sstevel@tonic-gate 548*0Sstevel@tonic-gate if ((KCF_PROV_KEY_OPS(pd) != NULL) && 549*0Sstevel@tonic-gate (KCF_PROV_KEY_OPS(pd)->key_check != NULL)) { 550*0Sstevel@tonic-gate crypto_mechanism_t lmech; 551*0Sstevel@tonic-gate 552*0Sstevel@tonic-gate mutex_exit(&me->me_mutex); 553*0Sstevel@tonic-gate lmech = *mech; 554*0Sstevel@tonic-gate KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, 555*0Sstevel@tonic-gate &lmech); 556*0Sstevel@tonic-gate error = KCF_PROV_KEY_CHECK(pd, &lmech, key); 557*0Sstevel@tonic-gate 558*0Sstevel@tonic-gate if (error != CRYPTO_SUCCESS) { 559*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 560*0Sstevel@tonic-gate return (error); 561*0Sstevel@tonic-gate } 562*0Sstevel@tonic-gate mutex_enter(&me->me_mutex); 563*0Sstevel@tonic-gate } 564*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 565*0Sstevel@tonic-gate prov_chain = prov_chain->pm_next; 566*0Sstevel@tonic-gate } 567*0Sstevel@tonic-gate 568*0Sstevel@tonic-gate mutex_exit(&me->me_mutex); 569*0Sstevel@tonic-gate 570*0Sstevel@tonic-gate /* All are happy with this key */ 571*0Sstevel@tonic-gate return (CRYPTO_SUCCESS); 572*0Sstevel@tonic-gate } 573*0Sstevel@tonic-gate 574*0Sstevel@tonic-gate /* 575*0Sstevel@tonic-gate * Initialize the specified crypto_mechanism_info_t structure for 576*0Sstevel@tonic-gate * the specified mechanism provider descriptor. Used by 577*0Sstevel@tonic-gate * crypto_get_all_mech_info(). 578*0Sstevel@tonic-gate */ 579*0Sstevel@tonic-gate static void 580*0Sstevel@tonic-gate init_mechanism_info(crypto_mechanism_info_t *mech_info, 581*0Sstevel@tonic-gate kcf_prov_mech_desc_t *pmd) 582*0Sstevel@tonic-gate { 583*0Sstevel@tonic-gate crypto_func_group_t fg = pmd->pm_mech_info.cm_func_group_mask; 584*0Sstevel@tonic-gate 585*0Sstevel@tonic-gate /* min/max key sizes */ 586*0Sstevel@tonic-gate mech_info->mi_keysize_unit = 587*0Sstevel@tonic-gate pmd->pm_mech_info.cm_keysize_unit; 588*0Sstevel@tonic-gate mech_info->mi_min_key_size = 589*0Sstevel@tonic-gate (size_t)pmd->pm_mech_info.cm_min_key_length; 590*0Sstevel@tonic-gate mech_info->mi_max_key_size = 591*0Sstevel@tonic-gate (size_t)pmd->pm_mech_info.cm_max_key_length; 592*0Sstevel@tonic-gate 593*0Sstevel@tonic-gate /* usage flag */ 594*0Sstevel@tonic-gate mech_info->mi_usage = 0; 595*0Sstevel@tonic-gate if (fg & (CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC)) 596*0Sstevel@tonic-gate mech_info->mi_usage |= CRYPTO_MECH_USAGE_ENCRYPT; 597*0Sstevel@tonic-gate if (fg & (CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC)) 598*0Sstevel@tonic-gate mech_info->mi_usage |= CRYPTO_MECH_USAGE_DECRYPT; 599*0Sstevel@tonic-gate if (fg & (CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC)) 600*0Sstevel@tonic-gate mech_info->mi_usage |= CRYPTO_MECH_USAGE_MAC; 601*0Sstevel@tonic-gate } 602*0Sstevel@tonic-gate 603*0Sstevel@tonic-gate /* 604*0Sstevel@tonic-gate * Return the mechanism info for the specified mechanism. 605*0Sstevel@tonic-gate */ 606*0Sstevel@tonic-gate int 607*0Sstevel@tonic-gate crypto_get_all_mech_info(crypto_mech_type_t mech_type, 608*0Sstevel@tonic-gate crypto_mechanism_info_t **mech_infos, uint_t *num_mech_infos, 609*0Sstevel@tonic-gate int km_flag) 610*0Sstevel@tonic-gate { 611*0Sstevel@tonic-gate uint_t ninfos, cur_info; 612*0Sstevel@tonic-gate kcf_mech_entry_t *me; 613*0Sstevel@tonic-gate int rv; 614*0Sstevel@tonic-gate kcf_prov_mech_desc_t *hwp; 615*0Sstevel@tonic-gate crypto_mechanism_info_t *infos; 616*0Sstevel@tonic-gate size_t infos_size; 617*0Sstevel@tonic-gate 618*0Sstevel@tonic-gate /* get to the mech entry corresponding to the specified mech type */ 619*0Sstevel@tonic-gate if ((rv = kcf_get_mech_entry(mech_type, &me)) != CRYPTO_SUCCESS) { 620*0Sstevel@tonic-gate return (rv); 621*0Sstevel@tonic-gate } 622*0Sstevel@tonic-gate 623*0Sstevel@tonic-gate /* compute the number of key size ranges to return */ 624*0Sstevel@tonic-gate mutex_enter(&me->me_mutex); 625*0Sstevel@tonic-gate again: 626*0Sstevel@tonic-gate ninfos = PROV_COUNT(me); 627*0Sstevel@tonic-gate mutex_exit(&me->me_mutex); 628*0Sstevel@tonic-gate 629*0Sstevel@tonic-gate if (ninfos == 0) { 630*0Sstevel@tonic-gate infos = NULL; 631*0Sstevel@tonic-gate rv = CRYPTO_SUCCESS; 632*0Sstevel@tonic-gate goto bail; 633*0Sstevel@tonic-gate } 634*0Sstevel@tonic-gate infos_size = ninfos * sizeof (crypto_mechanism_info_t); 635*0Sstevel@tonic-gate infos = kmem_alloc(infos_size, km_flag); 636*0Sstevel@tonic-gate if (infos == NULL) { 637*0Sstevel@tonic-gate rv = CRYPTO_HOST_MEMORY; 638*0Sstevel@tonic-gate goto bail; 639*0Sstevel@tonic-gate } 640*0Sstevel@tonic-gate 641*0Sstevel@tonic-gate mutex_enter(&me->me_mutex); 642*0Sstevel@tonic-gate if (ninfos != PROV_COUNT(me)) { 643*0Sstevel@tonic-gate kmem_free(infos, infos_size); 644*0Sstevel@tonic-gate goto again; 645*0Sstevel@tonic-gate } 646*0Sstevel@tonic-gate 647*0Sstevel@tonic-gate /* populate array of crypto mechanism infos */ 648*0Sstevel@tonic-gate cur_info = 0; 649*0Sstevel@tonic-gate 650*0Sstevel@tonic-gate /* software provider, if present */ 651*0Sstevel@tonic-gate if (me->me_sw_prov != NULL) 652*0Sstevel@tonic-gate init_mechanism_info(&infos[cur_info++], me->me_sw_prov); 653*0Sstevel@tonic-gate 654*0Sstevel@tonic-gate /* hardware providers */ 655*0Sstevel@tonic-gate for (hwp = me->me_hw_prov_chain; hwp != NULL; hwp = hwp->pm_next) 656*0Sstevel@tonic-gate init_mechanism_info(&infos[cur_info++], hwp); 657*0Sstevel@tonic-gate 658*0Sstevel@tonic-gate mutex_exit(&me->me_mutex); 659*0Sstevel@tonic-gate ASSERT(cur_info == ninfos); 660*0Sstevel@tonic-gate bail: 661*0Sstevel@tonic-gate *mech_infos = infos; 662*0Sstevel@tonic-gate *num_mech_infos = ninfos; 663*0Sstevel@tonic-gate return (rv); 664*0Sstevel@tonic-gate } 665