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