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 http://www.opensolaris.org/os/licensing. 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 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * This file is part of the core Kernel Cryptographic Framework. 28 * It implements the management of the policy table. Entries are 29 * added and removed by administrative ioctls. 30 * 31 * Each element of the policy table contains a pointer to a 32 * policy descriptor, or NULL if the entry is free. 33 */ 34 35 #include <sys/types.h> 36 #include <sys/kmem.h> 37 #include <sys/cmn_err.h> 38 #include <sys/ddi.h> 39 #include <sys/sunddi.h> 40 #include <sys/ksynch.h> 41 #include <sys/crypto/common.h> 42 #include <sys/crypto/impl.h> 43 44 #define KCF_MAX_POLICY 512 /* max number of policy entries */ 45 46 static kmutex_t policy_tab_mutex; /* ensure exclusive access to the table */ 47 static kcf_policy_desc_t **policy_tab = NULL; 48 static uint_t policy_tab_num = 0; /* number of providers in table */ 49 static uint_t policy_tab_max = KCF_MAX_POLICY; 50 51 static int kcf_policy_add_entry(kcf_policy_desc_t *); 52 static kcf_policy_desc_t *kcf_policy_alloc_desc(int); 53 54 /* 55 * Initialize the policy table. The policy table is dynamically 56 * allocated with policy_tab_max entries. 57 */ 58 void 59 kcf_policy_tab_init(void) 60 { 61 mutex_init(&policy_tab_mutex, NULL, MUTEX_DRIVER, NULL); 62 63 policy_tab = kmem_zalloc(policy_tab_max * sizeof (kcf_policy_desc_t *), 64 KM_SLEEP); 65 } 66 67 /* 68 * Add entry to the policy table. If no free slot can be found 69 * return CRYPTO_HOST_MEMORY, otherwise CRYPTO_SUCCESS. 70 * 71 * policy_tab_mutex must already be held. 72 */ 73 static int 74 kcf_policy_add_entry(kcf_policy_desc_t *policy_desc) 75 { 76 uint_t i = 0; 77 78 ASSERT(policy_tab != NULL); 79 ASSERT(MUTEX_HELD(&policy_tab_mutex)); 80 81 /* find free slot in policy table */ 82 while (i < KCF_MAX_POLICY && policy_tab[i] != NULL) 83 i++; 84 85 if (i == KCF_MAX_POLICY) { 86 /* ran out of policy entries */ 87 cmn_err(CE_WARN, "out of policy entries"); 88 return (CRYPTO_HOST_MEMORY); 89 } 90 91 /* initialize entry */ 92 policy_tab[i] = policy_desc; 93 KCF_POLICY_REFHOLD(policy_desc); 94 policy_tab_num++; 95 96 return (CRYPTO_SUCCESS); 97 } 98 99 /* 100 * Remove policy descriptor for the specified software module. 101 */ 102 void 103 kcf_policy_remove_by_name(char *module_name, uint_t *count, 104 crypto_mech_name_t **array) 105 { 106 kcf_policy_desc_t *policy_desc; 107 int i; 108 109 ASSERT(policy_tab != NULL); 110 ASSERT(policy_tab_num != (uint_t)-1); /* underflow */ 111 112 mutex_enter(&policy_tab_mutex); 113 114 for (i = 0; i < KCF_MAX_POLICY; i++) { 115 if ((policy_desc = policy_tab[i]) != NULL && 116 policy_desc->pd_prov_type == CRYPTO_SW_PROVIDER) { 117 ASSERT(policy_desc->pd_name != NULL); 118 if (strncmp(module_name, policy_desc->pd_name, 119 MAXNAMELEN) == 0) { 120 *count = policy_desc->pd_disabled_count; 121 *array = policy_desc->pd_disabled_mechs; 122 mutex_destroy(&policy_desc->pd_mutex); 123 kmem_free(policy_desc->pd_name, 124 strlen(policy_desc->pd_name) + 1); 125 kmem_free(policy_desc, 126 sizeof (kcf_policy_desc_t)); 127 policy_tab[i] = NULL; 128 policy_tab_num--; 129 break; 130 } 131 } 132 } 133 if (i == KCF_MAX_POLICY) { 134 *count = 0; 135 *array = NULL; 136 } 137 138 mutex_exit(&policy_tab_mutex); 139 } 140 141 /* 142 * Remove policy descriptor for the specified device. 143 */ 144 void 145 kcf_policy_remove_by_dev(char *name, uint_t instance, uint_t *count, 146 crypto_mech_name_t **array) 147 { 148 kcf_policy_desc_t *policy_desc; 149 int i; 150 151 ASSERT(policy_tab != NULL); 152 ASSERT(policy_tab_num != (uint_t)-1); /* underflow */ 153 154 mutex_enter(&policy_tab_mutex); 155 156 for (i = 0; i < KCF_MAX_POLICY; i++) { 157 if ((policy_desc = policy_tab[i]) != NULL && 158 policy_desc->pd_prov_type == CRYPTO_HW_PROVIDER && 159 strncmp(policy_desc->pd_name, name, MAXNAMELEN) == 0 && 160 policy_desc->pd_instance == instance) { 161 *count = policy_desc->pd_disabled_count; 162 *array = policy_desc->pd_disabled_mechs; 163 mutex_destroy(&policy_desc->pd_mutex); 164 kmem_free(policy_desc->pd_name, 165 strlen(policy_desc->pd_name) + 1); 166 kmem_free(policy_desc, sizeof (kcf_policy_desc_t)); 167 policy_tab[i] = NULL; 168 policy_tab_num--; 169 break; 170 } 171 } 172 if (i == KCF_MAX_POLICY) { 173 *count = 0; 174 *array = NULL; 175 } 176 177 mutex_exit(&policy_tab_mutex); 178 } 179 180 /* 181 * Returns policy descriptor for the specified software module. 182 */ 183 kcf_policy_desc_t * 184 kcf_policy_lookup_by_name(char *module_name) 185 { 186 kcf_policy_desc_t *policy_desc; 187 uint_t i; 188 189 mutex_enter(&policy_tab_mutex); 190 191 for (i = 0; i < KCF_MAX_POLICY; i++) { 192 if ((policy_desc = policy_tab[i]) != NULL && 193 policy_desc->pd_prov_type == CRYPTO_SW_PROVIDER) { 194 ASSERT(policy_desc->pd_name != NULL); 195 if (strncmp(module_name, policy_desc->pd_name, 196 MAXNAMELEN) == 0) { 197 KCF_POLICY_REFHOLD(policy_desc); 198 mutex_exit(&policy_tab_mutex); 199 return (policy_desc); 200 } 201 } 202 } 203 204 mutex_exit(&policy_tab_mutex); 205 return (NULL); 206 } 207 208 /* 209 * Returns policy descriptor for the specified device. 210 */ 211 kcf_policy_desc_t * 212 kcf_policy_lookup_by_dev(char *name, uint_t instance) 213 { 214 kcf_policy_desc_t *policy_desc; 215 uint_t i; 216 217 mutex_enter(&policy_tab_mutex); 218 219 for (i = 0; i < KCF_MAX_POLICY; i++) { 220 if ((policy_desc = policy_tab[i]) != NULL && 221 policy_desc->pd_prov_type == CRYPTO_HW_PROVIDER && 222 strncmp(policy_desc->pd_name, name, MAXNAMELEN) == 0 && 223 policy_desc->pd_instance == instance) { 224 KCF_POLICY_REFHOLD(policy_desc); 225 mutex_exit(&policy_tab_mutex); 226 return (policy_desc); 227 } 228 } 229 230 mutex_exit(&policy_tab_mutex); 231 return (NULL); 232 } 233 234 /* 235 * Loads disabled mechanism array for specified software provider, and 236 * creates a policy descriptor if one does not already exist. 237 * Important note: new_array is consumed. 238 */ 239 int 240 kcf_policy_load_soft_disabled(char *module_name, uint_t new_count, 241 crypto_mech_name_t *new_array, uint_t *prev_count, 242 crypto_mech_name_t **prev_array) 243 { 244 kcf_policy_desc_t *new_desc, *policy_desc = NULL; 245 uint_t i; 246 int rv; 247 248 /* 249 * Allocate storage for a new entry. 250 * Free new entry if a policy descriptor already exists. 251 */ 252 new_desc = kcf_policy_alloc_desc(KM_SLEEP); 253 new_desc->pd_prov_type = CRYPTO_SW_PROVIDER; 254 new_desc->pd_name = kmem_alloc(strlen(module_name) + 1, KM_SLEEP); 255 (void) strcpy(new_desc->pd_name, module_name); 256 257 mutex_enter(&policy_tab_mutex); 258 259 /* 260 * Search for an existing entry. 261 */ 262 for (i = 0; i < KCF_MAX_POLICY; i++) { 263 if (policy_tab[i] != NULL && 264 policy_tab[i]->pd_prov_type == CRYPTO_SW_PROVIDER) { 265 ASSERT(policy_tab[i]->pd_name != NULL); 266 if (strncmp(policy_tab[i]->pd_name, module_name, 267 MAXNAMELEN) == 0) { 268 policy_desc = policy_tab[i]; 269 break; 270 } 271 } 272 } 273 if (policy_desc == NULL) { 274 rv = kcf_policy_add_entry(new_desc); 275 if (rv != CRYPTO_SUCCESS) { 276 mutex_exit(&policy_tab_mutex); 277 kcf_policy_free_desc(new_desc); 278 return (rv); 279 } 280 policy_desc = new_desc; 281 } else { 282 kcf_policy_free_desc(new_desc); 283 } 284 285 mutex_enter(&policy_desc->pd_mutex); 286 *prev_count = policy_desc->pd_disabled_count; 287 288 /* prev_array is freed by the caller */ 289 *prev_array = policy_desc->pd_disabled_mechs; 290 policy_desc->pd_disabled_count = new_count; 291 policy_desc->pd_disabled_mechs = new_array; 292 mutex_exit(&policy_desc->pd_mutex); 293 mutex_exit(&policy_tab_mutex); 294 return (CRYPTO_SUCCESS); 295 } 296 297 /* 298 * Loads disabled mechanism array for specified device, and 299 * creates a policy descriptor if one does not already exist. 300 * Important note: new_array is consumed. 301 */ 302 int 303 kcf_policy_load_dev_disabled(char *name, uint_t instance, uint_t new_count, 304 crypto_mech_name_t *new_array, uint_t *prev_count, 305 crypto_mech_name_t **prev_array) 306 { 307 kcf_policy_desc_t *new_desc, *policy_desc = NULL; 308 uint_t i; 309 int rv; 310 311 /* 312 * Allocate storage for a new entry. 313 * Free new entry if a policy descriptor already exists. 314 */ 315 new_desc = kcf_policy_alloc_desc(KM_SLEEP); 316 new_desc->pd_prov_type = CRYPTO_HW_PROVIDER; 317 new_desc->pd_name = kmem_alloc(strlen(name) + 1, KM_SLEEP); 318 (void) strcpy(new_desc->pd_name, name); 319 new_desc->pd_instance = instance; 320 321 mutex_enter(&policy_tab_mutex); 322 323 /* 324 * Search for an existing entry. 325 */ 326 for (i = 0; i < KCF_MAX_POLICY; i++) { 327 if (policy_tab[i] != NULL && 328 policy_tab[i]->pd_prov_type == CRYPTO_HW_PROVIDER && 329 strncmp(policy_tab[i]->pd_name, name, MAXNAMELEN) == 0 && 330 policy_tab[i]->pd_instance == instance) { 331 policy_desc = policy_tab[i]; 332 break; 333 } 334 } 335 if (policy_desc == NULL) { 336 rv = kcf_policy_add_entry(new_desc); 337 if (rv != CRYPTO_SUCCESS) { 338 mutex_exit(&policy_tab_mutex); 339 kcf_policy_free_desc(new_desc); 340 return (rv); 341 } 342 policy_desc = new_desc; 343 } else { 344 kcf_policy_free_desc(new_desc); 345 } 346 347 mutex_enter(&policy_desc->pd_mutex); 348 *prev_count = policy_desc->pd_disabled_count; 349 350 /* prev_array is freed by the caller */ 351 *prev_array = policy_desc->pd_disabled_mechs; 352 policy_desc->pd_disabled_count = new_count; 353 policy_desc->pd_disabled_mechs = new_array; 354 mutex_exit(&policy_desc->pd_mutex); 355 mutex_exit(&policy_tab_mutex); 356 return (CRYPTO_SUCCESS); 357 } 358 359 /* 360 * Allocate a policy descriptor. 361 */ 362 static kcf_policy_desc_t * 363 kcf_policy_alloc_desc(int km_flag) 364 { 365 kcf_policy_desc_t *desc; 366 367 if ((desc = kmem_zalloc(sizeof (kcf_policy_desc_t), km_flag)) == NULL) 368 return (NULL); 369 370 mutex_init(&desc->pd_mutex, NULL, MUTEX_DEFAULT, NULL); 371 372 return (desc); 373 } 374 375 /* 376 * Free a policy descriptor. 377 */ 378 void 379 kcf_policy_free_desc(kcf_policy_desc_t *desc) 380 { 381 if (desc == NULL) 382 return; 383 384 mutex_destroy(&desc->pd_mutex); 385 386 ASSERT(desc->pd_name != NULL); 387 kmem_free(desc->pd_name, strlen(desc->pd_name) + 1); 388 389 if (desc->pd_disabled_mechs != NULL) 390 kmem_free(desc->pd_disabled_mechs, sizeof (crypto_mech_name_t) * 391 desc->pd_disabled_count); 392 393 kmem_free(desc, sizeof (kcf_policy_desc_t)); 394 } 395