xref: /illumos-gate/usr/src/uts/common/crypto/core/kcf_policy.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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