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 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 /*
29 * Core KCF (Kernel Cryptographic Framework). This file implements
30 * the cryptoadm entry points.
31 */
32
33 #include <sys/systm.h>
34 #include <sys/errno.h>
35 #include <sys/cmn_err.h>
36 #include <sys/rwlock.h>
37 #include <sys/kmem.h>
38 #include <sys/modctl.h>
39 #include <sys/sunddi.h>
40 #include <sys/door.h>
41 #include <sys/crypto/common.h>
42 #include <sys/crypto/api.h>
43 #include <sys/crypto/spi.h>
44 #include <sys/crypto/impl.h>
45 #include <sys/crypto/sched_impl.h>
46
47 /* protects the the soft_config_list. */
48 kmutex_t soft_config_mutex;
49
50 /*
51 * This linked list contains software configuration entries that
52 * are loaded into the kernel by the CRYPTO_LOAD_SOFT_CONFIG ioctl.
53 * It is protected by the soft_config_mutex.
54 */
55 kcf_soft_conf_entry_t *soft_config_list;
56
57 static int add_soft_config(char *, uint_t, crypto_mech_name_t *);
58 static int dup_mech_names(kcf_provider_desc_t *, crypto_mech_name_t **,
59 uint_t *, int);
60 static void free_soft_config_entry(kcf_soft_conf_entry_t *);
61
62 #define KCF_MAX_CONFIG_ENTRIES 512 /* maximum entries in soft_config_list */
63
64 void
65 kcf_soft_config_init(void)
66 {
67 mutex_init(&soft_config_mutex, NULL, MUTEX_DRIVER, NULL);
68 }
69
70
71 /*
72 * Utility routine to identify the providers to filter out and
73 * present only one provider. This happens when a hardware provider
74 * registers multiple units of the same device instance.
75 */
76 static void
77 filter_providers(uint_t count, kcf_provider_desc_t **provider_array,
78 char *skip_providers, int *mech_counts, int *new_count)
79 {
80 int i, j;
81 kcf_provider_desc_t *prov1, *prov2;
82 int n = 0;
83
84 for (i = 0; i < count; i++) {
85 if (skip_providers[i] == 1)
86 continue;
87
88 prov1 = provider_array[i];
89 mech_counts[i] = prov1->pd_mech_list_count;
90 for (j = i + 1; j < count; j++) {
91 prov2 = provider_array[j];
92 if (strncmp(prov1->pd_name, prov2->pd_name,
93 MAXNAMELEN) == 0 &&
94 prov1->pd_instance == prov2->pd_instance) {
95 skip_providers[j] = 1;
96 mech_counts[i] += prov2->pd_mech_list_count;
97 }
98 }
99 n++;
100 }
101
102 *new_count = n;
103 }
104
105
106 /* called from the CRYPTO_GET_DEV_LIST ioctl */
107 int
108 crypto_get_dev_list(uint_t *count, crypto_dev_list_entry_t **array)
109 {
110 kcf_provider_desc_t **provider_array;
111 kcf_provider_desc_t *pd;
112 crypto_dev_list_entry_t *p;
113 size_t skip_providers_size, mech_counts_size;
114 char *skip_providers;
115 uint_t provider_count;
116 int rval, i, j, new_count, *mech_counts;
117
118 /*
119 * Take snapshot of provider table returning only hardware providers
120 * that are in a usable state. Logical providers not included.
121 */
122 rval = kcf_get_hw_prov_tab(&provider_count, &provider_array, KM_SLEEP,
123 NULL, 0, B_FALSE);
124 if (rval != CRYPTO_SUCCESS)
125 return (rval);
126
144 ASSERT(mech_counts[i] == 0);
145 continue;
146 }
147 pd = provider_array[i];
148 p[j].le_mechanism_count = mech_counts[i];
149 p[j].le_dev_instance = pd->pd_instance;
150 (void) strncpy(p[j].le_dev_name, pd->pd_name, MAXNAMELEN);
151 j++;
152 }
153
154 kcf_free_provider_tab(provider_count, provider_array);
155 kmem_free(skip_providers, skip_providers_size);
156 kmem_free(mech_counts, mech_counts_size);
157
158 *array = p;
159 *count = new_count;
160 return (CRYPTO_SUCCESS);
161 }
162
163 /*
164 * Called from the CRYPTO_GET_SOFT_LIST ioctl, this routine returns
165 * a buffer containing the null terminated names of software providers
166 * loaded by CRYPTO_LOAD_SOFT_CONFIG.
167 */
168 int
169 crypto_get_soft_list(uint_t *count, char **array, size_t *len)
170 {
171 char *names = NULL, *namep, *end;
172 kcf_soft_conf_entry_t *p;
173 uint_t n = 0, cnt = 0, final_count = 0;
174 size_t name_len, final_size = 0;
175
176 /* first estimate */
177 mutex_enter(&soft_config_mutex);
178 for (p = soft_config_list; p != NULL; p = p->ce_next) {
179 n += strlen(p->ce_name) + 1;
180 cnt++;
181 }
182 mutex_exit(&soft_config_mutex);
183
184 if (cnt == 0)
185 goto out;
186
208 mutex_exit(&soft_config_mutex);
209
210 ASSERT(final_size <= n);
211
212 /* check if buffer we allocated is too large */
213 if (final_size < n) {
214 char *final_buffer;
215
216 final_buffer = kmem_alloc(final_size, KM_SLEEP);
217 bcopy(names, final_buffer, final_size);
218 kmem_free(names, n);
219 names = final_buffer;
220 }
221 out:
222 *array = names;
223 *count = final_count;
224 *len = final_size;
225 return (CRYPTO_SUCCESS);
226 }
227
228 static boolean_t
229 duplicate(char *name, crypto_mech_name_t *array, int count)
230 {
231 int i;
232
233 for (i = 0; i < count; i++) {
234 if (strncmp(name, &array[i][0],
235 sizeof (crypto_mech_name_t)) == 0)
236 return (B_TRUE);
237 }
238 return (B_FALSE);
239 }
240
241 /* called from the CRYPTO_GET_DEV_INFO ioctl */
242 int
243 crypto_get_dev_info(char *name, uint_t instance, uint_t *count,
244 crypto_mech_name_t **array)
245 {
246 int rv;
247 crypto_mech_name_t *mech_names, *resized_array;
248 int i, j, k = 0, max_count;
249 uint_t provider_count;
250 kcf_provider_desc_t **provider_array;
251 kcf_provider_desc_t *pd;
252
253 /*
254 * Get provider table entries matching name and instance
255 * for hardware providers that are in a usable state.
256 * Logical providers not included. NULL name matches
257 * all hardware providers.
258 */
259 rv = kcf_get_hw_prov_tab(&provider_count, &provider_array, KM_SLEEP,
260 name, instance, B_FALSE);
261 if (rv != CRYPTO_SUCCESS)
294
295 /* resize */
296 if (k != max_count) {
297 resized_array =
298 kmem_alloc(k * sizeof (crypto_mech_name_t), KM_SLEEP);
299 bcopy(mech_names, resized_array,
300 k * sizeof (crypto_mech_name_t));
301 kmem_free(mech_names,
302 max_count * sizeof (crypto_mech_name_t));
303 mech_names = resized_array;
304 }
305
306 out:
307 kcf_free_provider_tab(provider_count, provider_array);
308 *count = k;
309 *array = mech_names;
310
311 return (CRYPTO_SUCCESS);
312 }
313
314 /* called from the CRYPTO_GET_SOFT_INFO ioctl */
315 int
316 crypto_get_soft_info(caddr_t name, uint_t *count, crypto_mech_name_t **array)
317 {
318 ddi_modhandle_t modh = NULL;
319 kcf_provider_desc_t *provider;
320 int rv;
321
322 provider = kcf_prov_tab_lookup_by_name(name);
323 if (provider == NULL) {
324 if (in_soft_config_list(name)) {
325 char *tmp;
326 int name_len;
327
328 /* strlen("crypto/") + NULL terminator == 8 */
329 name_len = strlen(name);
330 tmp = kmem_alloc(name_len + 8, KM_SLEEP);
331 bcopy("crypto/", tmp, 7);
332 bcopy(name, &tmp[7], name_len);
333 tmp[name_len + 7] = '\0';
334
335 modh = ddi_modopen(tmp, KRTLD_MODE_FIRST, NULL);
336 kmem_free(tmp, name_len + 8);
337
338 if (modh == NULL) {
339 return (CRYPTO_ARGUMENTS_BAD);
340 }
341
342 provider = kcf_prov_tab_lookup_by_name(name);
343 if (provider == NULL) {
344 return (CRYPTO_ARGUMENTS_BAD);
345 }
346 } else {
347 return (CRYPTO_ARGUMENTS_BAD);
348 }
349 }
350
351 rv = dup_mech_names(provider, array, count, KM_SLEEP);
352 KCF_PROV_REFRELE(provider);
353 if (modh != NULL)
354 (void) ddi_modclose(modh);
355 return (rv);
356 }
357
358 static void
359 kcf_change_mechs(kcf_provider_desc_t *provider, uint_t count,
360 crypto_mech_name_t *array, crypto_event_change_t direction)
361 {
362 crypto_notify_event_change_t ec;
363 crypto_mech_info_t *mi;
364 kcf_prov_mech_desc_t *pmd;
365 char *mech;
366 int i, j, n;
367
368 ASSERT(direction == CRYPTO_MECH_ADDED ||
369 direction == CRYPTO_MECH_REMOVED);
370
371 if (provider == NULL) {
372 /*
373 * Nothing to add or remove from the tables since
374 * the provider isn't registered.
375 */
376 return;
377 }
544
545 out:
546 if (provider != NULL) {
547 redo_register_provider(provider);
548 if (provider->pd_kstat != NULL)
549 KCF_PROV_REFHOLD(provider);
550 mutex_enter(&provider->pd_lock);
551 provider->pd_state = KCF_PROV_READY;
552 mutex_exit(&provider->pd_lock);
553 } else if (rv == CRYPTO_SUCCESS) {
554 /*
555 * There are some cases where it is useful to kCF clients
556 * to have a provider whose mechanism is enabled now to be
557 * available. So, we attempt to load it here.
558 *
559 * The check, new_count < prev_count, ensures that we do this
560 * only in the case where a mechanism(s) is now enabled.
561 * This check assumes that enable and disable are separate
562 * administrative actions and are not done in a single action.
563 */
564 if (new_count < prev_count && (in_soft_config_list(name)) &&
565 (modload("crypto", name) != -1)) {
566 struct modctl *mcp;
567 boolean_t load_again = B_FALSE;
568
569 if ((mcp = mod_hold_by_name(name)) != NULL) {
570 mcp->mod_loadflags |= MOD_NOAUTOUNLOAD;
571
572 /* memory pressure may have unloaded module */
573 if (!mcp->mod_installed)
574 load_again = B_TRUE;
575 mod_release_mod(mcp);
576
577 if (load_again)
578 (void) modload("crypto", name);
579 }
580 }
581 }
582
583 return (rv);
584 }
585
586 /* called from the CRYPTO_LOAD_SOFT_CONFIG ioctl */
587 int
588 crypto_load_soft_config(caddr_t name, uint_t count, crypto_mech_name_t *array)
589 {
590 return (add_soft_config(name, count, array));
591 }
592
593 /* called from the CRYPTO_UNLOAD_SOFT_MODULE ioctl */
594 int
595 crypto_unload_soft_module(caddr_t name)
596 {
597 int error;
598 modid_t id;
599 kcf_provider_desc_t *provider;
600 struct modctl *mcp;
601
602 /* verify that 'name' refers to a registered crypto provider */
603 if ((provider = kcf_prov_tab_lookup_by_name(name)) == NULL)
604 return (CRYPTO_UNKNOWN_PROVIDER);
605
606 /*
607 * We save the module id and release the reference. We need to
608 * do this as modunload() calls unregister which waits for the
609 * refcnt to drop to zero.
610 */
611 id = provider->pd_module_id;
612 KCF_PROV_REFRELE(provider);
613
614 if ((mcp = mod_hold_by_name(name)) != NULL) {
615 mcp->mod_loadflags &= ~(MOD_NOAUTOUNLOAD);
616 mod_release_mod(mcp);
617 }
618
619 if ((error = modunload(id)) != 0) {
620 return (error == EBUSY ? CRYPTO_BUSY : CRYPTO_FAILED);
621 }
622
623 return (CRYPTO_SUCCESS);
624 }
625
626 /* called from CRYPTO_GET_DEV_LIST ioctl */
627 void
628 crypto_free_dev_list(crypto_dev_list_entry_t *array, uint_t count)
629 {
630 if (count == 0 || array == NULL)
631 return;
632
633 kmem_free(array, count * sizeof (crypto_dev_list_entry_t));
634 }
635
636 /*
637 * Returns duplicate array of mechanisms. The array is allocated and
638 * must be freed by the caller.
639 */
640 static int
641 dup_mech_names(kcf_provider_desc_t *provider, crypto_mech_name_t **array,
642 uint_t *count, int kmflag)
643 {
644 crypto_mech_name_t *mech_names;
645 uint_t n;
646 uint_t i;
796
797 mech_names = kmem_alloc((scnt - dcnt) * sizeof (crypto_mech_name_t),
798 kmflag);
799 if (mech_names == NULL)
800 return (CRYPTO_HOST_MEMORY);
801
802 /* build array of permitted mechanisms */
803 for (i = 0, p = mech_names; i < scnt; i++) {
804 if (!is_mech_disabled(provider,
805 &provider->pd_mechanisms[i].cm_mech_name[0])) {
806 bcopy(&provider->pd_mechanisms[i].cm_mech_name[0],
807 p++, sizeof (crypto_mech_name_t));
808 }
809 }
810
811 *count = scnt - dcnt;
812 *array = mech_names;
813 return (CRYPTO_SUCCESS);
814 }
815
816 static void
817 free_soft_config_entry(kcf_soft_conf_entry_t *p)
818 {
819 kmem_free(p->ce_name, strlen(p->ce_name) + 1);
820 crypto_free_mech_list(p->ce_mechs, p->ce_count);
821 kmem_free(p, sizeof (kcf_soft_conf_entry_t));
822 }
823
824 /*
825 * Called from the CRYPTO_LOAD_SOFT_CONFIG ioctl, this routine stores
826 * configuration information for software providers in a linked list.
827 * If the list already contains an entry for the specified provider
828 * and the specified mechanism list has at least one mechanism, then
829 * the mechanism list for the provider is updated. If the mechanism list
830 * is empty, the entry for the provider is removed.
831 *
832 * Important note: the array argument is consumed.
833 */
834 static int
835 add_soft_config(char *name, uint_t count, crypto_mech_name_t *array)
836 {
837 static uint_t soft_config_count = 0;
838 kcf_soft_conf_entry_t *prev = NULL, *entry = NULL, *new_entry, *p;
839 size_t name_len;
840
841 /*
842 * Allocate storage for a new entry.
843 * Free later if an entry already exists.
844 */
845 name_len = strlen(name) + 1;
846 new_entry = kmem_zalloc(sizeof (kcf_soft_conf_entry_t), KM_SLEEP);
847 new_entry->ce_name = kmem_alloc(name_len, KM_SLEEP);
848 (void) strcpy(new_entry->ce_name, name);
849
850 mutex_enter(&soft_config_mutex);
851 p = soft_config_list;
852 if (p != NULL) {
864 if (count == 0) {
865 mutex_exit(&soft_config_mutex);
866 kmem_free(new_entry->ce_name, name_len);
867 kmem_free(new_entry, sizeof (kcf_soft_conf_entry_t));
868 return (CRYPTO_SUCCESS);
869 }
870
871 if (soft_config_count > KCF_MAX_CONFIG_ENTRIES) {
872 mutex_exit(&soft_config_mutex);
873 kmem_free(new_entry->ce_name, name_len);
874 kmem_free(new_entry, sizeof (kcf_soft_conf_entry_t));
875 cmn_err(CE_WARN, "out of soft_config_list entries");
876 return (CRYPTO_FAILED);
877 }
878
879 /* add to head of list */
880 new_entry->ce_next = soft_config_list;
881 soft_config_list = new_entry;
882 soft_config_count++;
883 entry = new_entry;
884 } else {
885 kmem_free(new_entry->ce_name, name_len);
886 kmem_free(new_entry, sizeof (kcf_soft_conf_entry_t));
887 }
888
889 /* mechanism count == 0 means remove entry from list */
890 if (count == 0) {
891 if (prev == NULL) {
892 /* remove first in list */
893 soft_config_list = entry->ce_next;
894 } else {
895 prev->ce_next = entry->ce_next;
896 }
897 soft_config_count--;
898 mutex_exit(&soft_config_mutex);
899
900 /* free entry */
901 free_soft_config_entry(entry);
902
903 return (CRYPTO_SUCCESS);
904 }
933 p = soft_config_list;
934 while (p != NULL) {
935 next = p->ce_next;
936 for (i = 0; i < p->ce_count; i++) {
937 if (strcmp(mech, &p->ce_mechs[i][0]) == 0) {
938 name_len = strlen(p->ce_name) + 1;
939 bcopy(p->ce_name, tmp_name, name_len);
940 break;
941 }
942 }
943 p = next;
944 }
945 mutex_exit(&soft_config_mutex);
946
947 if (name_len == 0)
948 return (CRYPTO_FAILED);
949
950 *name = kmem_alloc(name_len, KM_SLEEP);
951 bcopy(tmp_name, *name, name_len);
952 return (CRYPTO_SUCCESS);
953 }
954
955 /*
956 * This routine searches the soft_config_list for the specified
957 * software provider, returning B_TRUE if it is in the list.
958 */
959 boolean_t
960 in_soft_config_list(char *provider_name)
961 {
962 kcf_soft_conf_entry_t *p;
963 boolean_t rv = B_FALSE;
964
965 mutex_enter(&soft_config_mutex);
966 for (p = soft_config_list; p != NULL; p = p->ce_next) {
967 if (strcmp(provider_name, p->ce_name) == 0) {
968 rv = B_TRUE;
969 break;
970 }
971 }
972 mutex_exit(&soft_config_mutex);
973 return (rv);
974 }
|
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 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * Core KCF (Kernel Cryptographic Framework). This file implements
28 * the cryptoadm entry points.
29 */
30
31 #include <sys/systm.h>
32 #include <sys/errno.h>
33 #include <sys/cmn_err.h>
34 #include <sys/rwlock.h>
35 #include <sys/kmem.h>
36 #include <sys/modctl.h>
37 #include <sys/sunddi.h>
38 #include <sys/door.h>
39 #include <sys/crypto/common.h>
40 #include <sys/crypto/api.h>
41 #include <sys/crypto/spi.h>
42 #include <sys/crypto/impl.h>
43 #include <sys/crypto/sched_impl.h>
44
45 /* protects the the soft_config_list. */
46 kmutex_t soft_config_mutex;
47
48 /*
49 * This linked list contains software configuration entries.
50 * The initial list is just software providers loaded by kcf_soft_config_init().
51 * Additional entries may appear for both hardware and software providers
52 * from kcf.conf. These come from "cryptoadm start", which reads file kcf.conf
53 * and updates this table using the CRYPTO_LOAD_SOFT_CONFIG ioctl.
54 * Further cryptoadm commands modify this file and update this table with ioctl.
55 * This list is protected by the soft_config_mutex.
56 */
57 kcf_soft_conf_entry_t *soft_config_list;
58
59 static int add_soft_config(char *, uint_t, crypto_mech_name_t *);
60 static int dup_mech_names(kcf_provider_desc_t *, crypto_mech_name_t **,
61 uint_t *, int);
62 static void free_soft_config_entry(kcf_soft_conf_entry_t *);
63
64 #define KCF_MAX_CONFIG_ENTRIES 512 /* maximum entries in soft_config_list */
65
66 #if DEBUG
67 extern int kcf_frmwrk_debug;
68 static void kcf_soft_config_dump(char *message);
69 #endif /* DEBUG */
70
71 /*
72 * Count and return the number of mechanisms in an array of crypto_mech_name_t
73 * (excluding final NUL-character string element).
74 */
75 static int
76 count_mechanisms(crypto_mech_name_t mechs[]) {
77 int count;
78 for (count = 0; mechs[count][0] != '\0'; ++count);
79 return (count);
80 }
81
82 /*
83 * Initialize a mutex and populate soft_config_list with default entries
84 * of kernel software providers.
85 * Called from kcf module _init().
86 */
87 void
88 kcf_soft_config_init(void)
89 {
90 typedef struct {
91 char *name;
92 crypto_mech_name_t *mechs;
93 } initial_soft_config_entry_t;
94
95 /*
96 * This provides initial default values to soft_config_list.
97 * It is equivalent to these lines in /etc/crypto/kcf.conf
98 * (without line breaks and indenting):
99 *
100 * # /etc/crypto/kcf.conf
101 * des:supportedlist=CKM_DES_CBC,CKM_DES_ECB,CKM_DES3_CBC,CKM_DES3_ECB
102 * aes:supportedlist=CKM_AES_ECB,CKM_AES_CBC,CKM_AES_CTR,CKM_AES_CCM
103 * arcfour:supportedlist=CKM_RC4
104 * blowfish:supportedlist=CKM_BLOWFISH_ECB,CKM_BLOWFISH_CBC
105 * ecc:supportedlist=CKM_EC_KEY_PAIR_GEN,CKM_ECDH1_DERIVE,CKM_ECDSA,\
106 * CKM_ECDSA_SHA1
107 * sha1:supportedlist=CKM_SHA_1,CKM_SHA_1_HMAC_GENERAL,CKM_SHA_1_HMAC
108 * sha2:supportedlist=CKM_SHA256,CKM_SHA256_HMAC,
109 * CKM_SHA256_HMAC_GENERAL,CKM_SHA384,CKM_SHA384_HMAC,\
110 * CKM_SHA384_HMAC_GENERAL,CKM_SHA512,CKM_SHA512_HMAC,\
111 * CKM_SHA512_HMAC_GENERAL
112 * md4:supportedlist=CKM_MD4
113 * md5:supportedlist=CKM_MD5,CKM_MD5_HMAC_GENERAL,CKM_MD5_HMAC
114 * rsa:supportedlist=CKM_RSA_PKCS,CKM_RSA_X_509,CKM_MD5_RSA_PKCS,\
115 * CKM_SHA1_RSA_PKCS,CKM_SHA256_RSA_PKCS,CKM_SHA384_RSA_PKCS,\
116 * CKM_SHA512_RSA_PKCS
117 * swrand:supportedlist=random
118 *
119 * WARNING: If you add a new kernel crypto provider or mechanism,
120 * you must update these constants.
121 *
122 * 1. To add a new mechanism to a provider add the string to the
123 * appropriate array below.
124 *
125 * 2. To add a new provider, create a new *_mechs array listing the
126 * provider's mechanism(s). For example:
127 * sha3_mechs[SHA3_MECH_COUNT] = {"CKM_SHA_3"};
128 * Add the new *_mechs array to initial_soft_config_entry[].
129 */
130 static crypto_mech_name_t des_mechs[] = {
131 "CKM_DES_CBC", "CKM_DES_ECB", "CKM_DES3_CBC", "CKM_DES3_ECB", ""};
132 static crypto_mech_name_t aes_mechs[] = {
133 "CKM_AES_ECB", "CKM_AES_CBC", "CKM_AES_CTR", "CKM_AES_CCM", ""};
134 static crypto_mech_name_t arcfour_mechs[] = {
135 "CKM_RC4", ""};
136 static crypto_mech_name_t blowfish_mechs[] = {
137 "CKM_BLOWFISH_ECB", "CKM_BLOWFISH_CBC", ""};
138 static crypto_mech_name_t ecc_mechs[] = {
139 "CKM_EC_KEY_PAIR_GEN", "CKM_ECDH1_DERIVE", "CKM_ECDSA",
140 "CKM_ECDSA_SHA1", ""};
141 static crypto_mech_name_t sha1_mechs[] = {
142 "CKM_SHA_1", "CKM_SHA_1_HMAC_GENERAL", "CKM_SHA_1_HMAC", ""};
143 static crypto_mech_name_t sha2_mechs[] = {
144 "CKM_SHA256", "CKM_SHA256_HMAC", "CKM_SHA256_HMAC_GENERAL",
145 "CKM_SHA384", "CKM_SHA384_HMAC", "CKM_SHA384_HMAC_GENERAL",
146 "CKM_SHA512", "CKM_SHA512_HMAC", "CKM_SHA512_HMAC_GENERAL", ""};
147 static crypto_mech_name_t md4_mechs[] = {
148 "CKM_MD4", ""};
149 static crypto_mech_name_t md5_mechs[] = {
150 "CKM_MD5", "CKM_MD5_HMAC_GENERAL", "CKM_MD5_HMAC", ""};
151 static crypto_mech_name_t rsa_mechs[] = {
152 "CKM_RSA_PKCS", "CKM_RSA_X_509", "CKM_MD5_RSA_PKCS",
153 "CKM_SHA1_RSA_PKCS", "CKM_SHA256_RSA_PKCS", "CKM_SHA384_RSA_PKCS",
154 "CKM_SHA512_RSA_PKCS", ""};
155 static crypto_mech_name_t swrand_mechs[] = {
156 "random", NULL};
157 static initial_soft_config_entry_t
158 initial_soft_config_entry[] = {
159 "des", des_mechs,
160 "aes", aes_mechs,
161 "arcfour", arcfour_mechs,
162 "blowfish", blowfish_mechs,
163 "ecc", ecc_mechs,
164 "sha1", sha1_mechs,
165 "sha2", sha2_mechs,
166 "md4", md4_mechs,
167 "md5", md5_mechs,
168 "rsa", rsa_mechs,
169 "swrand", swrand_mechs
170 };
171 const int initial_soft_config_entries =
172 sizeof (initial_soft_config_entry)
173 / sizeof (initial_soft_config_entry_t);
174 int i;
175
176 mutex_init(&soft_config_mutex, NULL, MUTEX_DRIVER, NULL);
177
178 /*
179 * Initialize soft_config_list with default providers.
180 * Populate the linked list backwards so the first entry appears first.
181 */
182 for (i = initial_soft_config_entries - 1; i >= 0; --i) {
183 initial_soft_config_entry_t *p = &initial_soft_config_entry[i];
184 crypto_mech_name_t *mechsp;
185 char *namep;
186 uint_t namelen, alloc_size;
187 int mech_count, r;
188
189 /* allocate/initialize memory for name and mechanism list */
190 namelen = strlen(p->name) + 1;
191 namep = kmem_alloc(namelen, KM_SLEEP);
192 (void) strlcpy(namep, p->name, namelen);
193 mech_count = count_mechanisms(p->mechs);
194 alloc_size = mech_count * CRYPTO_MAX_MECH_NAME;
195 mechsp = kmem_alloc(alloc_size, KM_SLEEP);
196 bcopy(p->mechs, mechsp, alloc_size);
197
198 r = add_soft_config(namep, mech_count, mechsp);
199 if (r != 0)
200 cmn_err(CE_WARN,
201 "add_soft_config(%s) failed; returned %d\n",
202 namep, r);
203 }
204 #if DEBUG
205 if (kcf_frmwrk_debug >= 1)
206 kcf_soft_config_dump("kcf_soft_config_init");
207 #endif /* DEBUG */
208 }
209
210
211 #if DEBUG
212 /*
213 * Dump soft_config_list, containing a list of kernel software providers
214 * and (optionally) hardware providers, with updates from kcf.conf.
215 * Dump mechanism lists too if kcf_frmwrk_debug is >= 2.
216 */
217 static void
218 kcf_soft_config_dump(char *message)
219 {
220 kcf_soft_conf_entry_t *p;
221 uint_t i;
222
223 mutex_enter(&soft_config_mutex);
224 printf("Soft provider config list soft_config_list: %s\n",
225 message != NULL ? message : "");
226
227 for (p = soft_config_list; p != NULL; p = p->ce_next) {
228 printf("ce_name: %s, %d ce_mechs\n", p->ce_name, p->ce_count);
229 if (kcf_frmwrk_debug >= 2) {
230 printf("\tce_mechs: ");
231 for (i = 0; i < p->ce_count; i++) {
232 printf("%s ", p->ce_mechs[i]);
233 }
234 printf("\n");
235 }
236 }
237 printf("(end of soft_config_list)\n");
238
239 mutex_exit(&soft_config_mutex);
240 }
241 #endif /* DEBUG */
242
243
244 /*
245 * Utility routine to identify the providers to filter out and
246 * present only one provider. This happens when a hardware provider
247 * registers multiple units of the same device instance.
248 *
249 * Called from crypto_get_dev_list().
250 */
251 static void
252 filter_providers(uint_t count, kcf_provider_desc_t **provider_array,
253 char *skip_providers, int *mech_counts, int *new_count)
254 {
255 int i, j;
256 kcf_provider_desc_t *prov1, *prov2;
257 int n = 0;
258
259 for (i = 0; i < count; i++) {
260 if (skip_providers[i] == 1)
261 continue;
262
263 prov1 = provider_array[i];
264 mech_counts[i] = prov1->pd_mech_list_count;
265 for (j = i + 1; j < count; j++) {
266 prov2 = provider_array[j];
267 if (strncmp(prov1->pd_name, prov2->pd_name,
268 MAXNAMELEN) == 0 &&
269 prov1->pd_instance == prov2->pd_instance) {
270 skip_providers[j] = 1;
271 mech_counts[i] += prov2->pd_mech_list_count;
272 }
273 }
274 n++;
275 }
276
277 *new_count = n;
278 }
279
280
281 /*
282 * Return a list of kernel hardware providers and a count of each
283 * provider's supported mechanisms.
284 * Called from the CRYPTO_GET_DEV_LIST ioctl.
285 */
286 int
287 crypto_get_dev_list(uint_t *count, crypto_dev_list_entry_t **array)
288 {
289 kcf_provider_desc_t **provider_array;
290 kcf_provider_desc_t *pd;
291 crypto_dev_list_entry_t *p;
292 size_t skip_providers_size, mech_counts_size;
293 char *skip_providers;
294 uint_t provider_count;
295 int rval, i, j, new_count, *mech_counts;
296
297 /*
298 * Take snapshot of provider table returning only hardware providers
299 * that are in a usable state. Logical providers not included.
300 */
301 rval = kcf_get_hw_prov_tab(&provider_count, &provider_array, KM_SLEEP,
302 NULL, 0, B_FALSE);
303 if (rval != CRYPTO_SUCCESS)
304 return (rval);
305
323 ASSERT(mech_counts[i] == 0);
324 continue;
325 }
326 pd = provider_array[i];
327 p[j].le_mechanism_count = mech_counts[i];
328 p[j].le_dev_instance = pd->pd_instance;
329 (void) strncpy(p[j].le_dev_name, pd->pd_name, MAXNAMELEN);
330 j++;
331 }
332
333 kcf_free_provider_tab(provider_count, provider_array);
334 kmem_free(skip_providers, skip_providers_size);
335 kmem_free(mech_counts, mech_counts_size);
336
337 *array = p;
338 *count = new_count;
339 return (CRYPTO_SUCCESS);
340 }
341
342 /*
343 * Return a buffer containing the null terminated names of software providers
344 * loaded by CRYPTO_LOAD_SOFT_CONFIG.
345 * Called from the CRYPTO_GET_SOFT_LIST ioctl.
346 */
347 int
348 crypto_get_soft_list(uint_t *count, char **array, size_t *len)
349 {
350 char *names = NULL, *namep, *end;
351 kcf_soft_conf_entry_t *p;
352 uint_t n = 0, cnt = 0, final_count = 0;
353 size_t name_len, final_size = 0;
354
355 /* first estimate */
356 mutex_enter(&soft_config_mutex);
357 for (p = soft_config_list; p != NULL; p = p->ce_next) {
358 n += strlen(p->ce_name) + 1;
359 cnt++;
360 }
361 mutex_exit(&soft_config_mutex);
362
363 if (cnt == 0)
364 goto out;
365
387 mutex_exit(&soft_config_mutex);
388
389 ASSERT(final_size <= n);
390
391 /* check if buffer we allocated is too large */
392 if (final_size < n) {
393 char *final_buffer;
394
395 final_buffer = kmem_alloc(final_size, KM_SLEEP);
396 bcopy(names, final_buffer, final_size);
397 kmem_free(names, n);
398 names = final_buffer;
399 }
400 out:
401 *array = names;
402 *count = final_count;
403 *len = final_size;
404 return (CRYPTO_SUCCESS);
405 }
406
407 /*
408 * Check if a mechanism name is already in a mechanism name array
409 * Called by crypto_get_dev_info().
410 */
411 static boolean_t
412 duplicate(char *name, crypto_mech_name_t *array, int count)
413 {
414 int i;
415
416 for (i = 0; i < count; i++) {
417 if (strncmp(name, &array[i][0],
418 sizeof (crypto_mech_name_t)) == 0)
419 return (B_TRUE);
420 }
421 return (B_FALSE);
422 }
423
424 /*
425 * Return a list of kernel hardware providers for a given name and instance.
426 * For each entry, also return a list of their supported mechanisms.
427 * Called from the CRYPTO_GET_DEV_INFO ioctl.
428 */
429 int
430 crypto_get_dev_info(char *name, uint_t instance, uint_t *count,
431 crypto_mech_name_t **array)
432 {
433 int rv;
434 crypto_mech_name_t *mech_names, *resized_array;
435 int i, j, k = 0, max_count;
436 uint_t provider_count;
437 kcf_provider_desc_t **provider_array;
438 kcf_provider_desc_t *pd;
439
440 /*
441 * Get provider table entries matching name and instance
442 * for hardware providers that are in a usable state.
443 * Logical providers not included. NULL name matches
444 * all hardware providers.
445 */
446 rv = kcf_get_hw_prov_tab(&provider_count, &provider_array, KM_SLEEP,
447 name, instance, B_FALSE);
448 if (rv != CRYPTO_SUCCESS)
481
482 /* resize */
483 if (k != max_count) {
484 resized_array =
485 kmem_alloc(k * sizeof (crypto_mech_name_t), KM_SLEEP);
486 bcopy(mech_names, resized_array,
487 k * sizeof (crypto_mech_name_t));
488 kmem_free(mech_names,
489 max_count * sizeof (crypto_mech_name_t));
490 mech_names = resized_array;
491 }
492
493 out:
494 kcf_free_provider_tab(provider_count, provider_array);
495 *count = k;
496 *array = mech_names;
497
498 return (CRYPTO_SUCCESS);
499 }
500
501 /*
502 * Given a kernel software provider name, return a list of mechanisms
503 * it supports.
504 * Called from the CRYPTO_GET_SOFT_INFO ioctl.
505 */
506 int
507 crypto_get_soft_info(caddr_t name, uint_t *count, crypto_mech_name_t **array)
508 {
509 ddi_modhandle_t modh = NULL;
510 kcf_provider_desc_t *provider;
511 int rv;
512
513 provider = kcf_prov_tab_lookup_by_name(name);
514 if (provider == NULL) {
515 char *tmp;
516 int name_len;
517
518 /* strlen("crypto/") + NULL terminator == 8 */
519 name_len = strlen(name);
520 tmp = kmem_alloc(name_len + 8, KM_SLEEP);
521 bcopy("crypto/", tmp, 7);
522 bcopy(name, &tmp[7], name_len);
523 tmp[name_len + 7] = '\0';
524
525 modh = ddi_modopen(tmp, KRTLD_MODE_FIRST, NULL);
526 kmem_free(tmp, name_len + 8);
527
528 if (modh == NULL) {
529 return (CRYPTO_ARGUMENTS_BAD);
530 }
531
532 provider = kcf_prov_tab_lookup_by_name(name);
533 if (provider == NULL) {
534 return (CRYPTO_ARGUMENTS_BAD);
535 }
536 }
537
538 rv = dup_mech_names(provider, array, count, KM_SLEEP);
539 KCF_PROV_REFRELE(provider);
540 if (modh != NULL)
541 (void) ddi_modclose(modh);
542 return (rv);
543 }
544
545
546 /*
547 * Change the mechanism list for a provider.
548 * If "direction" is CRYPTO_MECH_ADDED, add new mechanisms.
549 * If "direction" is CRYPTO_MECH_REMOVED, remove the mechanism list.
550 * Called from crypto_load_dev_disabled().
551 */
552 static void
553 kcf_change_mechs(kcf_provider_desc_t *provider, uint_t count,
554 crypto_mech_name_t *array, crypto_event_change_t direction)
555 {
556 crypto_notify_event_change_t ec;
557 crypto_mech_info_t *mi;
558 kcf_prov_mech_desc_t *pmd;
559 char *mech;
560 int i, j, n;
561
562 ASSERT(direction == CRYPTO_MECH_ADDED ||
563 direction == CRYPTO_MECH_REMOVED);
564
565 if (provider == NULL) {
566 /*
567 * Nothing to add or remove from the tables since
568 * the provider isn't registered.
569 */
570 return;
571 }
738
739 out:
740 if (provider != NULL) {
741 redo_register_provider(provider);
742 if (provider->pd_kstat != NULL)
743 KCF_PROV_REFHOLD(provider);
744 mutex_enter(&provider->pd_lock);
745 provider->pd_state = KCF_PROV_READY;
746 mutex_exit(&provider->pd_lock);
747 } else if (rv == CRYPTO_SUCCESS) {
748 /*
749 * There are some cases where it is useful to kCF clients
750 * to have a provider whose mechanism is enabled now to be
751 * available. So, we attempt to load it here.
752 *
753 * The check, new_count < prev_count, ensures that we do this
754 * only in the case where a mechanism(s) is now enabled.
755 * This check assumes that enable and disable are separate
756 * administrative actions and are not done in a single action.
757 */
758 if ((new_count < prev_count) &&
759 (modload("crypto", name) != -1)) {
760 struct modctl *mcp;
761 boolean_t load_again = B_FALSE;
762
763 if ((mcp = mod_hold_by_name(name)) != NULL) {
764 mcp->mod_loadflags |= MOD_NOAUTOUNLOAD;
765
766 /* memory pressure may have unloaded module */
767 if (!mcp->mod_installed)
768 load_again = B_TRUE;
769 mod_release_mod(mcp);
770
771 if (load_again)
772 (void) modload("crypto", name);
773 }
774 }
775 }
776
777 return (rv);
778 }
779
780 /* called from the CRYPTO_LOAD_SOFT_CONFIG ioctl */
781 int
782 crypto_load_soft_config(caddr_t name, uint_t count, crypto_mech_name_t *array)
783 {
784 return (add_soft_config(name, count, array));
785 }
786
787 /*
788 * Unload a kernel software crypto module.
789 * Called from the CRYPTO_UNLOAD_SOFT_MODULE ioctl.
790 */
791 int
792 crypto_unload_soft_module(caddr_t name)
793 {
794 int error;
795 modid_t id;
796 kcf_provider_desc_t *provider;
797 struct modctl *mcp;
798
799 /* verify that 'name' refers to a registered crypto provider */
800 if ((provider = kcf_prov_tab_lookup_by_name(name)) == NULL)
801 return (CRYPTO_UNKNOWN_PROVIDER);
802
803 /*
804 * We save the module id and release the reference. We need to
805 * do this as modunload() calls unregister which waits for the
806 * refcnt to drop to zero.
807 */
808 id = provider->pd_module_id;
809 KCF_PROV_REFRELE(provider);
810
811 if ((mcp = mod_hold_by_name(name)) != NULL) {
812 mcp->mod_loadflags &= ~(MOD_NOAUTOUNLOAD);
813 mod_release_mod(mcp);
814 }
815
816 if ((error = modunload(id)) != 0) {
817 return (error == EBUSY ? CRYPTO_BUSY : CRYPTO_FAILED);
818 }
819
820 return (CRYPTO_SUCCESS);
821 }
822
823 /*
824 * Free the list of kernel hardware crypto providers.
825 * Called by get_dev_list() for the CRYPTO_GET_DEV_LIST ioctl.
826 */
827 void
828 crypto_free_dev_list(crypto_dev_list_entry_t *array, uint_t count)
829 {
830 if (count == 0 || array == NULL)
831 return;
832
833 kmem_free(array, count * sizeof (crypto_dev_list_entry_t));
834 }
835
836 /*
837 * Returns duplicate array of mechanisms. The array is allocated and
838 * must be freed by the caller.
839 */
840 static int
841 dup_mech_names(kcf_provider_desc_t *provider, crypto_mech_name_t **array,
842 uint_t *count, int kmflag)
843 {
844 crypto_mech_name_t *mech_names;
845 uint_t n;
846 uint_t i;
996
997 mech_names = kmem_alloc((scnt - dcnt) * sizeof (crypto_mech_name_t),
998 kmflag);
999 if (mech_names == NULL)
1000 return (CRYPTO_HOST_MEMORY);
1001
1002 /* build array of permitted mechanisms */
1003 for (i = 0, p = mech_names; i < scnt; i++) {
1004 if (!is_mech_disabled(provider,
1005 &provider->pd_mechanisms[i].cm_mech_name[0])) {
1006 bcopy(&provider->pd_mechanisms[i].cm_mech_name[0],
1007 p++, sizeof (crypto_mech_name_t));
1008 }
1009 }
1010
1011 *count = scnt - dcnt;
1012 *array = mech_names;
1013 return (CRYPTO_SUCCESS);
1014 }
1015
1016 /*
1017 * Free memory for elements in a kcf_soft_config_entry_t. This entry must
1018 * have been previously removed from the soft_config_list linked list.
1019 */
1020 static void
1021 free_soft_config_entry(kcf_soft_conf_entry_t *p)
1022 {
1023 kmem_free(p->ce_name, strlen(p->ce_name) + 1);
1024 crypto_free_mech_list(p->ce_mechs, p->ce_count);
1025 kmem_free(p, sizeof (kcf_soft_conf_entry_t));
1026 }
1027
1028 /*
1029 * Store configuration information for software providers in a linked list.
1030 * If the list already contains an entry for the specified provider
1031 * and the specified mechanism list has at least one mechanism, then
1032 * the mechanism list for the provider is updated. If the mechanism list
1033 * is empty, the entry for the provider is removed.
1034 *
1035 * Called from kcf_soft_config_init() (to initially populate the list
1036 * with default kernel providers) and from crypto_load_soft_config() for
1037 * the CRYPTO_LOAD_SOFT_CONFIG ioctl (for third-party kernel modules).
1038 *
1039 * Important note: the name and array arguments must be allocated memory
1040 * and are consumed in soft_config_list.
1041 */
1042 static int
1043 add_soft_config(char *name, uint_t count, crypto_mech_name_t *array)
1044 {
1045 static uint_t soft_config_count = 0;
1046 kcf_soft_conf_entry_t *prev = NULL, *entry = NULL, *new_entry, *p;
1047 size_t name_len;
1048
1049 /*
1050 * Allocate storage for a new entry.
1051 * Free later if an entry already exists.
1052 */
1053 name_len = strlen(name) + 1;
1054 new_entry = kmem_zalloc(sizeof (kcf_soft_conf_entry_t), KM_SLEEP);
1055 new_entry->ce_name = kmem_alloc(name_len, KM_SLEEP);
1056 (void) strcpy(new_entry->ce_name, name);
1057
1058 mutex_enter(&soft_config_mutex);
1059 p = soft_config_list;
1060 if (p != NULL) {
1072 if (count == 0) {
1073 mutex_exit(&soft_config_mutex);
1074 kmem_free(new_entry->ce_name, name_len);
1075 kmem_free(new_entry, sizeof (kcf_soft_conf_entry_t));
1076 return (CRYPTO_SUCCESS);
1077 }
1078
1079 if (soft_config_count > KCF_MAX_CONFIG_ENTRIES) {
1080 mutex_exit(&soft_config_mutex);
1081 kmem_free(new_entry->ce_name, name_len);
1082 kmem_free(new_entry, sizeof (kcf_soft_conf_entry_t));
1083 cmn_err(CE_WARN, "out of soft_config_list entries");
1084 return (CRYPTO_FAILED);
1085 }
1086
1087 /* add to head of list */
1088 new_entry->ce_next = soft_config_list;
1089 soft_config_list = new_entry;
1090 soft_config_count++;
1091 entry = new_entry;
1092 } else { /* mechanism already in list */
1093 kmem_free(new_entry->ce_name, name_len);
1094 kmem_free(new_entry, sizeof (kcf_soft_conf_entry_t));
1095 }
1096
1097 /* mechanism count == 0 means remove entry from list */
1098 if (count == 0) {
1099 if (prev == NULL) {
1100 /* remove first in list */
1101 soft_config_list = entry->ce_next;
1102 } else {
1103 prev->ce_next = entry->ce_next;
1104 }
1105 soft_config_count--;
1106 mutex_exit(&soft_config_mutex);
1107
1108 /* free entry */
1109 free_soft_config_entry(entry);
1110
1111 return (CRYPTO_SUCCESS);
1112 }
1141 p = soft_config_list;
1142 while (p != NULL) {
1143 next = p->ce_next;
1144 for (i = 0; i < p->ce_count; i++) {
1145 if (strcmp(mech, &p->ce_mechs[i][0]) == 0) {
1146 name_len = strlen(p->ce_name) + 1;
1147 bcopy(p->ce_name, tmp_name, name_len);
1148 break;
1149 }
1150 }
1151 p = next;
1152 }
1153 mutex_exit(&soft_config_mutex);
1154
1155 if (name_len == 0)
1156 return (CRYPTO_FAILED);
1157
1158 *name = kmem_alloc(name_len, KM_SLEEP);
1159 bcopy(tmp_name, *name, name_len);
1160 return (CRYPTO_SUCCESS);
1161 }
|