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