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 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <sys/zfs_context.h>
27 #include <sys/crypto/common.h>
28 #include <sys/crypto/api.h>
29 #include <sys/crypto/impl.h>
30 #include <sys/crypto/sched_impl.h>
31 
32 /*
33  * All event subscribers are put on a list. kcf_notify_list_lock
34  * protects changes to this list.
35  *
36  * The following locking order is maintained in the code - The
37  * global kcf_notify_list_lock followed by the individual lock
38  * in a kcf_ntfy_elem structure (kn_lock).
39  */
40 kmutex_t		ntfy_list_lock;
41 kcondvar_t		ntfy_list_cv;   /* cv the service thread waits on */
42 static kcf_ntfy_elem_t *ntfy_list_head;
43 
44 /*
45  * crypto_mech2id()
46  *
47  * Arguments:
48  *	. mechname: A null-terminated string identifying the mechanism name.
49  *
50  * Description:
51  *	Walks the mechanisms tables, looking for an entry that matches the
52  *	mechname. Once it find it, it builds the 64-bit mech_type and returns
53  *	it.  If there are no hardware or software providers for the mechanism,
54  *	but there is an unloaded software provider, this routine will attempt
55  *	to load it.
56  *
57  * Context:
58  *	Process and interruption.
59  *
60  * Returns:
61  *	The unique mechanism identified by 'mechname', if found.
62  *	CRYPTO_MECH_INVALID otherwise.
63  */
64 crypto_mech_type_t
crypto_mech2id(char * mechname)65 crypto_mech2id(char *mechname)
66 {
67 	return (crypto_mech2id_common(mechname, B_TRUE));
68 }
69 
70 /*
71  * We walk the notification list and do the callbacks.
72  */
73 void
kcf_walk_ntfylist(uint32_t event,void * event_arg)74 kcf_walk_ntfylist(uint32_t event, void *event_arg)
75 {
76 	kcf_ntfy_elem_t *nep;
77 	int nelem = 0;
78 
79 	mutex_enter(&ntfy_list_lock);
80 
81 	/*
82 	 * Count how many clients are on the notification list. We need
83 	 * this count to ensure that clients which joined the list after we
84 	 * have started this walk, are not wrongly notified.
85 	 */
86 	for (nep = ntfy_list_head; nep != NULL; nep = nep->kn_next)
87 		nelem++;
88 
89 	for (nep = ntfy_list_head; (nep != NULL && nelem); nep = nep->kn_next) {
90 		nelem--;
91 
92 		/*
93 		 * Check if this client is interested in the
94 		 * event.
95 		 */
96 		if (!(nep->kn_event_mask & event))
97 			continue;
98 
99 		mutex_enter(&nep->kn_lock);
100 		nep->kn_state = NTFY_RUNNING;
101 		mutex_exit(&nep->kn_lock);
102 		mutex_exit(&ntfy_list_lock);
103 
104 		/*
105 		 * We invoke the callback routine with no locks held. Another
106 		 * client could have joined the list meanwhile. This is fine
107 		 * as we maintain nelem as stated above. The NULL check in the
108 		 * for loop guards against shrinkage. Also, any callers of
109 		 * crypto_unnotify_events() at this point cv_wait till kn_state
110 		 * changes to NTFY_WAITING. Hence, nep is assured to be valid.
111 		 */
112 		(*nep->kn_func)(event, event_arg);
113 
114 		mutex_enter(&nep->kn_lock);
115 		nep->kn_state = NTFY_WAITING;
116 		cv_broadcast(&nep->kn_cv);
117 		mutex_exit(&nep->kn_lock);
118 
119 		mutex_enter(&ntfy_list_lock);
120 	}
121 
122 	mutex_exit(&ntfy_list_lock);
123 }
124 
125 #if defined(_KERNEL)
126 EXPORT_SYMBOL(crypto_mech2id);
127 #endif
128