1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or https://opensource.org/licenses/CDDL-1.0. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/zfs_context.h> 27 #include <sys/crypto/common.h> 28 #include <sys/crypto/api.h> 29 #include <sys/crypto/impl.h> 30 31 /* Cryptographic mechanisms tables and their access functions */ 32 33 /* 34 * Internal numbers assigned to mechanisms are coded as follows: 35 * 36 * +----------------+----------------+ 37 * | mech. class | mech. index | 38 * <--- 32-bits --->+<--- 32-bits ---> 39 * 40 * the mech_class identifies the table the mechanism belongs to. 41 * mech_index is the index for that mechanism in the table. 42 * A mechanism belongs to exactly 1 table. 43 * The tables are: 44 * . cipher_mechs_tab[] for encrypt/decrypt and wrap/unwrap mechs. 45 * . mac_mechs_tab[] for MAC mechs. 46 * . sign_mechs_tab[] for sign & verify mechs. 47 * . keyops_mechs_tab[] for key/key pair generation, and key derivation. 48 * . misc_mechs_tab[] for mechs that don't belong to any of the above. 49 * 50 * There are no holes in the tables. 51 */ 52 53 /* 54 * Locking conventions: 55 * -------------------- 56 * A mutex is associated with every entry of the tables. 57 * The mutex is acquired whenever the entry is accessed for 58 * 1) retrieving the mech_id (comparing the mech name) 59 * 2) finding a provider for an xxx_init() or atomic operation. 60 * 3) altering the mechs entry to add or remove a provider. 61 * 62 * In 2), after a provider is chosen, its prov_desc is held and the 63 * entry's mutex must be dropped. The provider's working function (SPI) is 64 * called outside the mech_entry's mutex. 65 * 66 * The number of providers for a particular mechanism is not expected to be 67 * long enough to justify the cost of using rwlocks, so the per-mechanism 68 * entry mutex won't be very *hot*. 69 * 70 */ 71 72 /* Mechanisms tables */ 73 74 75 /* RFE 4687834 Will deal with the extensibility of these tables later */ 76 77 static kcf_mech_entry_t kcf_cipher_mechs_tab[KCF_MAXCIPHER]; 78 static kcf_mech_entry_t kcf_mac_mechs_tab[KCF_MAXMAC]; 79 80 const kcf_mech_entry_tab_t kcf_mech_tabs_tab[KCF_LAST_OPSCLASS + 1] = { 81 {0, NULL}, /* No class zero */ 82 {KCF_MAXCIPHER, kcf_cipher_mechs_tab}, 83 {KCF_MAXMAC, kcf_mac_mechs_tab}, 84 }; 85 86 static avl_tree_t kcf_mech_hash; 87 88 static int 89 kcf_mech_hash_compar(const void *lhs, const void *rhs) 90 { 91 const kcf_mech_entry_t *l = lhs, *r = rhs; 92 int cmp = strncmp(l->me_name, r->me_name, CRYPTO_MAX_MECH_NAME); 93 return ((0 < cmp) - (cmp < 0)); 94 } 95 96 void 97 kcf_destroy_mech_tabs(void) 98 { 99 for (void *cookie = NULL; avl_destroy_nodes(&kcf_mech_hash, &cookie); ) 100 ; 101 avl_destroy(&kcf_mech_hash); 102 } 103 104 /* 105 * kcf_init_mech_tabs() 106 * 107 * Called by the misc/kcf's _init() routine to initialize the tables 108 * of mech_entry's. 109 */ 110 void 111 kcf_init_mech_tabs(void) 112 { 113 avl_create(&kcf_mech_hash, kcf_mech_hash_compar, 114 sizeof (kcf_mech_entry_t), offsetof(kcf_mech_entry_t, me_node)); 115 } 116 117 /* 118 * kcf_create_mech_entry() 119 * 120 * Arguments: 121 * . The class of mechanism. 122 * . the name of the new mechanism. 123 * 124 * Description: 125 * Creates a new mech_entry for a mechanism not yet known to the 126 * framework. 127 * This routine is called by kcf_add_mech_provider, which is 128 * in turn invoked for each mechanism supported by a provider. 129 * The'class' argument depends on the crypto_func_group_t bitmask 130 * in the registering provider's mech_info struct for this mechanism. 131 * When there is ambiguity in the mapping between the crypto_func_group_t 132 * and a class (dual ops, ...) the KCF_MISC_CLASS should be used. 133 * 134 * Context: 135 * User context only. 136 * 137 * Returns: 138 * KCF_INVALID_MECH_CLASS or KCF_INVALID_MECH_NAME if the class or 139 * the mechname is bogus. 140 * KCF_MECH_TAB_FULL when there is no room left in the mech. tabs. 141 * KCF_SUCCESS otherwise. 142 */ 143 static int 144 kcf_create_mech_entry(kcf_ops_class_t class, const char *mechname) 145 { 146 if ((class < KCF_FIRST_OPSCLASS) || (class > KCF_LAST_OPSCLASS)) 147 return (KCF_INVALID_MECH_CLASS); 148 149 if ((mechname == NULL) || (mechname[0] == 0)) 150 return (KCF_INVALID_MECH_NAME); 151 /* 152 * First check if the mechanism is already in one of the tables. 153 * The mech_entry could be in another class. 154 */ 155 avl_index_t where = 0; 156 kcf_mech_entry_t tmptab; 157 strlcpy(tmptab.me_name, mechname, CRYPTO_MAX_MECH_NAME); 158 if (avl_find(&kcf_mech_hash, &tmptab, &where) != NULL) 159 return (KCF_SUCCESS); 160 /* Now take the next unused mech entry in the class's tab */ 161 kcf_mech_entry_t *me_tab = kcf_mech_tabs_tab[class].met_tab; 162 int size = kcf_mech_tabs_tab[class].met_size; 163 164 for (int i = 0; i < size; ++i) 165 if (me_tab[i].me_name[0] == 0) { 166 /* Found an empty spot */ 167 strlcpy(me_tab[i].me_name, mechname, 168 CRYPTO_MAX_MECH_NAME); 169 me_tab[i].me_mechid = KCF_MECHID(class, i); 170 171 /* Add the new mechanism to the hash table */ 172 avl_insert(&kcf_mech_hash, &me_tab[i], where); 173 return (KCF_SUCCESS); 174 } 175 176 return (KCF_MECH_TAB_FULL); 177 } 178 179 /* 180 * kcf_add_mech_provider() 181 * 182 * Arguments: 183 * . An index in to the provider mechanism array 184 * . A pointer to the provider descriptor 185 * . A storage for the kcf_prov_mech_desc_t the entry was added at. 186 * 187 * Description: 188 * Adds a new provider of a mechanism to the mechanism's mech_entry 189 * chain. 190 * 191 * Context: 192 * User context only. 193 * 194 * Returns 195 * KCF_SUCCESS on success 196 * KCF_MECH_TAB_FULL otherwise. 197 */ 198 int 199 kcf_add_mech_provider(short mech_indx, 200 kcf_provider_desc_t *prov_desc, kcf_prov_mech_desc_t **pmdpp) 201 { 202 int error; 203 kcf_mech_entry_t *mech_entry = NULL; 204 const crypto_mech_info_t *mech_info; 205 crypto_mech_type_t kcf_mech_type; 206 kcf_prov_mech_desc_t *prov_mech; 207 208 mech_info = &prov_desc->pd_mechanisms[mech_indx]; 209 210 /* 211 * A mechanism belongs to exactly one mechanism table. 212 * Find the class corresponding to the function group flag of 213 * the mechanism. 214 */ 215 kcf_mech_type = crypto_mech2id(mech_info->cm_mech_name); 216 if (kcf_mech_type == CRYPTO_MECH_INVALID) { 217 crypto_func_group_t fg = mech_info->cm_func_group_mask; 218 kcf_ops_class_t class; 219 220 if (fg & CRYPTO_FG_ENCRYPT_ATOMIC || 221 fg & CRYPTO_FG_DECRYPT_ATOMIC) 222 class = KCF_CIPHER_CLASS; 223 else if (fg & CRYPTO_FG_MAC || fg & CRYPTO_FG_MAC_ATOMIC) 224 class = KCF_MAC_CLASS; 225 else 226 __builtin_unreachable(); 227 228 /* 229 * Attempt to create a new mech_entry for the specified 230 * mechanism. kcf_create_mech_entry() can handle the case 231 * where such an entry already exists. 232 */ 233 if ((error = kcf_create_mech_entry(class, 234 mech_info->cm_mech_name)) != KCF_SUCCESS) { 235 return (error); 236 } 237 /* get the KCF mech type that was assigned to the mechanism */ 238 kcf_mech_type = crypto_mech2id(mech_info->cm_mech_name); 239 ASSERT(kcf_mech_type != CRYPTO_MECH_INVALID); 240 } 241 242 error = kcf_get_mech_entry(kcf_mech_type, &mech_entry); 243 ASSERT(error == KCF_SUCCESS); 244 245 /* allocate and initialize new kcf_prov_mech_desc */ 246 prov_mech = kmem_zalloc(sizeof (kcf_prov_mech_desc_t), KM_SLEEP); 247 memcpy(&prov_mech->pm_mech_info, mech_info, 248 sizeof (crypto_mech_info_t)); 249 prov_mech->pm_prov_desc = prov_desc; 250 prov_desc->pd_mech_indx[KCF_MECH2CLASS(kcf_mech_type)] 251 [KCF_MECH2INDEX(kcf_mech_type)] = mech_indx; 252 253 KCF_PROV_REFHOLD(prov_desc); 254 KCF_PROV_IREFHOLD(prov_desc); 255 256 /* 257 * Add new kcf_prov_mech_desc at the front of HW providers 258 * chain. 259 */ 260 if (mech_entry->me_sw_prov != NULL) { 261 /* 262 * There is already a provider for this mechanism. 263 * Since we allow only one provider per mechanism, 264 * report this condition. 265 */ 266 cmn_err(CE_WARN, "The cryptographic provider " 267 "\"%s\" will not be used for %s. The provider " 268 "\"%s\" will be used for this mechanism " 269 "instead.", prov_desc->pd_description, 270 mech_info->cm_mech_name, 271 mech_entry->me_sw_prov->pm_prov_desc-> 272 pd_description); 273 KCF_PROV_REFRELE(prov_desc); 274 kmem_free(prov_mech, sizeof (kcf_prov_mech_desc_t)); 275 prov_mech = NULL; 276 } else { 277 /* 278 * Set the provider as the provider for 279 * this mechanism. 280 */ 281 mech_entry->me_sw_prov = prov_mech; 282 } 283 284 *pmdpp = prov_mech; 285 286 return (KCF_SUCCESS); 287 } 288 289 /* 290 * kcf_remove_mech_provider() 291 * 292 * Arguments: 293 * . mech_name: the name of the mechanism. 294 * . prov_desc: The provider descriptor 295 * 296 * Description: 297 * Removes a provider from chain of provider descriptors. 298 * The provider is made unavailable to kernel consumers for the specified 299 * mechanism. 300 * 301 * Context: 302 * User context only. 303 */ 304 void 305 kcf_remove_mech_provider(const char *mech_name, kcf_provider_desc_t *prov_desc) 306 { 307 crypto_mech_type_t mech_type; 308 kcf_prov_mech_desc_t *prov_mech = NULL; 309 kcf_mech_entry_t *mech_entry; 310 311 /* get the KCF mech type that was assigned to the mechanism */ 312 if ((mech_type = crypto_mech2id(mech_name)) == 313 CRYPTO_MECH_INVALID) { 314 /* 315 * Provider was not allowed for this mech due to policy or 316 * configuration. 317 */ 318 return; 319 } 320 321 /* get a ptr to the mech_entry that was created */ 322 if (kcf_get_mech_entry(mech_type, &mech_entry) != KCF_SUCCESS) { 323 /* 324 * Provider was not allowed for this mech due to policy or 325 * configuration. 326 */ 327 return; 328 } 329 330 if (mech_entry->me_sw_prov == NULL || 331 mech_entry->me_sw_prov->pm_prov_desc != prov_desc) { 332 /* not the provider for this mechanism */ 333 return; 334 } 335 prov_mech = mech_entry->me_sw_prov; 336 mech_entry->me_sw_prov = NULL; 337 338 /* free entry */ 339 KCF_PROV_IREFRELE(prov_mech->pm_prov_desc); 340 KCF_PROV_REFRELE(prov_mech->pm_prov_desc); 341 kmem_free(prov_mech, sizeof (kcf_prov_mech_desc_t)); 342 } 343 344 /* 345 * kcf_get_mech_entry() 346 * 347 * Arguments: 348 * . The framework mechanism type 349 * . Storage for the mechanism entry 350 * 351 * Description: 352 * Retrieves the mechanism entry for the mech. 353 * 354 * Context: 355 * User and interrupt contexts. 356 * 357 * Returns: 358 * KCF_MECHANISM_XXX appropriate error code. 359 * KCF_SUCCESS otherwise. 360 */ 361 int 362 kcf_get_mech_entry(crypto_mech_type_t mech_type, kcf_mech_entry_t **mep) 363 { 364 kcf_ops_class_t class; 365 int index; 366 const kcf_mech_entry_tab_t *me_tab; 367 368 ASSERT(mep != NULL); 369 370 class = KCF_MECH2CLASS(mech_type); 371 372 if ((class < KCF_FIRST_OPSCLASS) || (class > KCF_LAST_OPSCLASS)) { 373 /* the caller won't need to know it's an invalid class */ 374 return (KCF_INVALID_MECH_NUMBER); 375 } 376 377 me_tab = &kcf_mech_tabs_tab[class]; 378 index = KCF_MECH2INDEX(mech_type); 379 380 if ((index < 0) || (index >= me_tab->met_size)) { 381 return (KCF_INVALID_MECH_NUMBER); 382 } 383 384 *mep = &((me_tab->met_tab)[index]); 385 386 return (KCF_SUCCESS); 387 } 388 389 /* 390 * crypto_mech2id() 391 * 392 * Arguments: 393 * . mechname: A null-terminated string identifying the mechanism name. 394 * 395 * Description: 396 * Walks the mechanisms tables, looking for an entry that matches the 397 * mechname. Once it find it, it builds the 64-bit mech_type and returns 398 * it. 399 * 400 * Context: 401 * Process and interruption. 402 * 403 * Returns: 404 * The unique mechanism identified by 'mechname', if found. 405 * CRYPTO_MECH_INVALID otherwise. 406 */ 407 /* 408 * Lookup the hash table for an entry that matches the mechname. 409 * If there are no providers for the mechanism, 410 * but there is an unloaded provider, this routine will attempt 411 * to load it. 412 */ 413 crypto_mech_type_t 414 crypto_mech2id(const char *mechname) 415 { 416 kcf_mech_entry_t tmptab, *found; 417 strlcpy(tmptab.me_name, mechname, CRYPTO_MAX_MECH_NAME); 418 419 if ((found = avl_find(&kcf_mech_hash, &tmptab, NULL))) { 420 ASSERT(found->me_mechid != CRYPTO_MECH_INVALID); 421 return (found->me_mechid); 422 } 423 424 return (CRYPTO_MECH_INVALID); 425 } 426 427 #if defined(_KERNEL) 428 EXPORT_SYMBOL(crypto_mech2id); 429 #endif 430