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
kcf_policy_tab_init(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
kcf_policy_add_entry(kcf_policy_desc_t * policy_desc)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
kcf_policy_remove_by_name(char * module_name,uint_t * count,crypto_mech_name_t ** array)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
kcf_policy_remove_by_dev(char * name,uint_t instance,uint_t * count,crypto_mech_name_t ** array)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 *
kcf_policy_lookup_by_name(char * module_name)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 *
kcf_policy_lookup_by_dev(char * name,uint_t instance)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
kcf_policy_load_soft_disabled(char * module_name,uint_t new_count,crypto_mech_name_t * new_array,uint_t * prev_count,crypto_mech_name_t ** prev_array)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
kcf_policy_load_dev_disabled(char * name,uint_t instance,uint_t new_count,crypto_mech_name_t * new_array,uint_t * prev_count,crypto_mech_name_t ** prev_array)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 *
kcf_policy_alloc_desc(int km_flag)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
kcf_policy_free_desc(kcf_policy_desc_t * desc)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