xref: /illumos-gate/usr/src/uts/common/crypto/api/kcf_session.c (revision 88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98)
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 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 
28 #pragma ident	"%Z%%M%	%I%	%E% SMI"
29 
30 #include <sys/errno.h>
31 #include <sys/types.h>
32 #include <sys/kmem.h>
33 #include <sys/cmn_err.h>
34 #include <sys/sysmacros.h>
35 #include <sys/crypto/common.h>
36 #include <sys/crypto/impl.h>
37 #include <sys/crypto/api.h>
38 #include <sys/crypto/spi.h>
39 #include <sys/crypto/sched_impl.h>
40 
41 #define	CRYPTO_OPS_OFFSET(f)		offsetof(crypto_ops_t, co_##f)
42 #define	CRYPTO_OBJECT_OFFSET(f)		offsetof(crypto_object_ops_t, f)
43 #define	CRYPTO_SESSION_OFFSET(f)	offsetof(crypto_session_ops_t, f)
44 
45 int
46 crypto_session_open(crypto_provider_t provider, crypto_session_id_t *sidp,
47 crypto_call_req_t *crq)
48 {
49 	kcf_req_params_t params;
50 	kcf_provider_desc_t *real_provider;
51 	kcf_provider_desc_t *pd = provider;
52 
53 	ASSERT(KCF_PROV_REFHELD(pd));
54 
55 	/* find a provider that supports session ops */
56 	(void) kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(session_ops),
57 	    CRYPTO_SESSION_OFFSET(session_open),
58 	    CHECK_RESTRICT(crq), pd, &real_provider);
59 
60 	if (real_provider != NULL) {
61 		int rv;
62 
63 		ASSERT(real_provider == pd ||
64 		    pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER);
65 
66 		if (CHECK_FASTPATH(crq, pd)) {
67 			rv = KCF_PROV_SESSION_OPEN(real_provider, sidp,
68 			    KCF_SWFP_RHNDL(crq), pd);
69 			KCF_PROV_INCRSTATS(pd, rv);
70 		} else {
71 			KCF_WRAP_SESSION_OPS_PARAMS(&params,
72 			    KCF_OP_SESSION_OPEN, sidp, 0, CRYPTO_USER, NULL,
73 			    0, pd);
74 			rv = kcf_submit_request(real_provider, NULL, crq,
75 			    &params, B_FALSE);
76 		}
77 		KCF_PROV_REFRELE(real_provider);
78 
79 		if (rv != CRYPTO_SUCCESS) {
80 			return (rv);
81 		}
82 	}
83 	return (CRYPTO_SUCCESS);
84 }
85 
86 int
87 crypto_session_close(crypto_provider_t provider, crypto_session_id_t sid,
88     crypto_call_req_t *crq)
89 {
90 	int rv;
91 	kcf_req_params_t params;
92 	kcf_provider_desc_t *real_provider;
93 	kcf_provider_desc_t *pd = provider;
94 
95 	if (pd == NULL)
96 	    return (CRYPTO_ARGUMENTS_BAD);
97 
98 	ASSERT(KCF_PROV_REFHELD(pd));
99 
100 	/* find a provider that supports session ops */
101 	(void) kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(session_ops),
102 	    CRYPTO_SESSION_OFFSET(session_close), CHECK_RESTRICT(crq),
103 	    pd, &real_provider);
104 
105 	ASSERT(real_provider == pd ||
106 	    pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER);
107 
108 	/* edge case is where the logical provider has no members */
109 	if (real_provider != NULL) {
110 		/* The fast path for SW providers. */
111 		if (CHECK_FASTPATH(crq, pd)) {
112 			rv = KCF_PROV_SESSION_CLOSE(real_provider,
113 			    sid, KCF_SWFP_RHNDL(crq), pd);
114 			KCF_PROV_INCRSTATS(pd, rv);
115 		} else {
116 			KCF_WRAP_SESSION_OPS_PARAMS(&params,
117 			    KCF_OP_SESSION_CLOSE, NULL, sid,
118 			    CRYPTO_USER, NULL, 0, pd);
119 			rv = kcf_submit_request(real_provider, NULL, crq,
120 			    &params, B_FALSE);
121 		}
122 		KCF_PROV_REFRELE(real_provider);
123 	}
124 	return (CRYPTO_SUCCESS);
125 }
126 
127 int
128 crypto_session_login(crypto_provider_t provider, crypto_session_id_t sid,
129     crypto_user_type_t type, char *pin, ulong_t len, crypto_call_req_t *crq)
130 {
131 	kcf_req_params_t params;
132 	kcf_provider_desc_t *pd = provider;
133 	kcf_provider_desc_t *real_provider = pd;
134 	int rv;
135 
136 	ASSERT(KCF_PROV_REFHELD(pd));
137 
138 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
139 		rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
140 		    session_ops), CRYPTO_SESSION_OFFSET(session_login),
141 		    CHECK_RESTRICT(crq), pd, &real_provider);
142 
143 		if (rv != CRYPTO_SUCCESS)
144 			return (rv);
145 	}
146 
147 	if (CHECK_FASTPATH(crq, real_provider)) {
148 		rv = KCF_PROV_SESSION_LOGIN(real_provider, sid,
149 		    type, pin, len, KCF_SWFP_RHNDL(crq));
150 		KCF_PROV_INCRSTATS(pd, rv);
151 	} else {
152 		KCF_WRAP_SESSION_OPS_PARAMS(&params, KCF_OP_SESSION_LOGIN,
153 		    NULL, sid, type, pin, len, real_provider);
154 		rv = kcf_submit_request(real_provider, NULL, crq,
155 		    &params, B_FALSE);
156 	}
157 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
158 		KCF_PROV_REFRELE(real_provider);
159 
160 	return (rv);
161 }
162 
163 int
164 crypto_session_logout(crypto_provider_t provider, crypto_session_id_t sid,
165     crypto_call_req_t *crq)
166 {
167 	kcf_req_params_t params;
168 	kcf_provider_desc_t *pd = provider;
169 	kcf_provider_desc_t *real_provider = pd;
170 	int rv;
171 
172 	ASSERT(KCF_PROV_REFHELD(pd));
173 
174 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
175 		rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
176 		    session_ops), CRYPTO_SESSION_OFFSET(session_logout),
177 		    CHECK_RESTRICT(crq), pd, &real_provider);
178 
179 		if (rv != CRYPTO_SUCCESS)
180 			return (rv);
181 	}
182 
183 	if (CHECK_FASTPATH(crq, real_provider)) {
184 		rv = KCF_PROV_SESSION_LOGOUT(real_provider, sid,
185 		    KCF_SWFP_RHNDL(crq));
186 		KCF_PROV_INCRSTATS(pd, rv);
187 	} else {
188 		KCF_WRAP_SESSION_OPS_PARAMS(&params, KCF_OP_SESSION_LOGOUT,
189 		    NULL, sid, 0, NULL, 0, real_provider);
190 		rv = kcf_submit_request(real_provider, NULL, crq,
191 		    &params, B_FALSE);
192 	}
193 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
194 		KCF_PROV_REFRELE(real_provider);
195 
196 	return (rv);
197 }
198