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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 
26 #include <sys/errno.h>
27 #include <sys/types.h>
28 #include <sys/kmem.h>
29 #include <sys/cmn_err.h>
30 #include <sys/sysmacros.h>
31 #include <sys/crypto/common.h>
32 #include <sys/crypto/impl.h>
33 #include <sys/crypto/api.h>
34 #include <sys/crypto/spi.h>
35 #include <sys/crypto/sched_impl.h>
36 
37 #define	CRYPTO_OPS_OFFSET(f)		offsetof(crypto_ops_t, co_##f)
38 #define	CRYPTO_OBJECT_OFFSET(f)		offsetof(crypto_object_ops_t, f)
39 
40 int
crypto_object_create(crypto_provider_t provider,crypto_session_id_t sid,crypto_object_attribute_t * attrs,uint_t count,crypto_object_id_t * object_handle,crypto_call_req_t * crq)41 crypto_object_create(crypto_provider_t provider, crypto_session_id_t sid,
42     crypto_object_attribute_t *attrs, uint_t count,
43     crypto_object_id_t *object_handle, crypto_call_req_t *crq)
44 {
45 	kcf_req_params_t params;
46 	kcf_provider_desc_t *pd = provider;
47 	kcf_provider_desc_t *real_provider = pd;
48 	int rv;
49 
50 	ASSERT(KCF_PROV_REFHELD(pd));
51 
52 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
53 		rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
54 		    object_ops), CRYPTO_OBJECT_OFFSET(object_create),
55 		    pd, &real_provider);
56 
57 		if (rv != CRYPTO_SUCCESS)
58 			return (rv);
59 	}
60 
61 	if (CHECK_FASTPATH(crq, real_provider)) {
62 		rv = KCF_PROV_OBJECT_CREATE(real_provider, sid,
63 		    attrs, count, object_handle, KCF_SWFP_RHNDL(crq));
64 		KCF_PROV_INCRSTATS(pd, rv);
65 	} else {
66 		KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_CREATE,
67 		    sid, 0, attrs, count, object_handle, 0,
68 		    NULL, NULL, 0, NULL);
69 		rv = kcf_submit_request(real_provider, NULL, crq,
70 		    &params, B_FALSE);
71 	}
72 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
73 		KCF_PROV_REFRELE(real_provider);
74 
75 	return (rv);
76 }
77 
78 int
crypto_object_destroy(crypto_provider_t provider,crypto_session_id_t sid,crypto_object_id_t object_handle,crypto_call_req_t * crq)79 crypto_object_destroy(crypto_provider_t provider, crypto_session_id_t sid,
80     crypto_object_id_t object_handle, crypto_call_req_t *crq)
81 {
82 	kcf_req_params_t params;
83 	kcf_provider_desc_t *pd = provider;
84 	kcf_provider_desc_t *real_provider = pd;
85 	int rv;
86 
87 	ASSERT(KCF_PROV_REFHELD(pd));
88 
89 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
90 		rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
91 		    object_ops), CRYPTO_OBJECT_OFFSET(object_destroy),
92 		    pd, &real_provider);
93 
94 		if (rv != CRYPTO_SUCCESS)
95 			return (rv);
96 	}
97 
98 	if (CHECK_FASTPATH(crq, real_provider)) {
99 		rv = KCF_PROV_OBJECT_DESTROY(real_provider, sid,
100 		    object_handle, KCF_SWFP_RHNDL(crq));
101 		KCF_PROV_INCRSTATS(pd, rv);
102 	} else {
103 		KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_DESTROY,
104 		    sid, object_handle, NULL, 0, NULL, 0,
105 		    NULL, NULL, 0, NULL);
106 		rv = kcf_submit_request(real_provider, NULL, crq,
107 		    &params, B_FALSE);
108 	}
109 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
110 		KCF_PROV_REFRELE(real_provider);
111 
112 	return (rv);
113 }
114 
115 int
crypto_object_copy(crypto_provider_t provider,crypto_session_id_t sid,crypto_object_id_t object_handle,crypto_object_attribute_t * attrs,uint_t count,crypto_object_id_t * new_handle,crypto_call_req_t * crq)116 crypto_object_copy(crypto_provider_t provider, crypto_session_id_t sid,
117     crypto_object_id_t object_handle, crypto_object_attribute_t *attrs,
118     uint_t count, crypto_object_id_t *new_handle, crypto_call_req_t *crq)
119 {
120 	kcf_req_params_t params;
121 	kcf_provider_desc_t *pd = provider;
122 	kcf_provider_desc_t *real_provider = pd;
123 	int rv;
124 
125 	ASSERT(KCF_PROV_REFHELD(pd));
126 
127 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
128 		rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
129 		    object_ops), CRYPTO_OBJECT_OFFSET(object_copy),
130 		    pd, &real_provider);
131 
132 		if (rv != CRYPTO_SUCCESS)
133 			return (rv);
134 	}
135 
136 	if (CHECK_FASTPATH(crq, real_provider)) {
137 		rv = KCF_PROV_OBJECT_COPY(real_provider, sid,
138 		    object_handle, attrs, count, new_handle,
139 		    KCF_SWFP_RHNDL(crq));
140 		KCF_PROV_INCRSTATS(pd, rv);
141 	} else {
142 		KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_COPY,
143 		    sid, object_handle, attrs, count,
144 		    new_handle, 0, NULL, NULL, 0, NULL);
145 		rv = kcf_submit_request(real_provider, NULL, crq,
146 		    &params, B_FALSE);
147 	}
148 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
149 		KCF_PROV_REFRELE(real_provider);
150 
151 	return (rv);
152 }
153 
154 int
crypto_object_get_attribute_value(crypto_provider_t provider,crypto_session_id_t sid,crypto_object_id_t object_handle,crypto_object_attribute_t * attrs,uint_t count,crypto_call_req_t * crq)155 crypto_object_get_attribute_value(crypto_provider_t provider,
156     crypto_session_id_t sid, crypto_object_id_t object_handle,
157     crypto_object_attribute_t *attrs, uint_t count, crypto_call_req_t *crq)
158 {
159 	kcf_req_params_t params;
160 	kcf_provider_desc_t *pd = provider;
161 	kcf_provider_desc_t *real_provider = pd;
162 	int rv;
163 
164 	ASSERT(KCF_PROV_REFHELD(pd));
165 
166 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
167 		rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
168 		    object_ops),
169 		    CRYPTO_OBJECT_OFFSET(object_get_attribute_value),
170 		    pd, &real_provider);
171 
172 		if (rv != CRYPTO_SUCCESS)
173 			return (rv);
174 	}
175 
176 	if (CHECK_FASTPATH(crq, real_provider)) {
177 		rv = KCF_PROV_OBJECT_GET_ATTRIBUTE_VALUE(real_provider,
178 		    sid, object_handle, attrs, count, KCF_SWFP_RHNDL(crq));
179 		KCF_PROV_INCRSTATS(pd, rv);
180 	} else {
181 		KCF_WRAP_OBJECT_OPS_PARAMS(&params,
182 		    KCF_OP_OBJECT_GET_ATTRIBUTE_VALUE, sid, object_handle,
183 		    attrs, count, NULL, 0, NULL, NULL, 0, NULL);
184 		rv = kcf_submit_request(real_provider, NULL, crq,
185 		    &params, B_FALSE);
186 	}
187 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
188 		KCF_PROV_REFRELE(real_provider);
189 
190 	return (rv);
191 }
192 
193 int
crypto_object_set_attribute_value(crypto_provider_t provider,crypto_session_id_t sid,crypto_object_id_t object_handle,crypto_object_attribute_t * attrs,uint_t count,crypto_call_req_t * crq)194 crypto_object_set_attribute_value(crypto_provider_t provider,
195     crypto_session_id_t sid, crypto_object_id_t object_handle,
196     crypto_object_attribute_t *attrs, uint_t count, crypto_call_req_t *crq)
197 {
198 	kcf_req_params_t params;
199 	kcf_provider_desc_t *pd = provider;
200 	kcf_provider_desc_t *real_provider = pd;
201 	int rv;
202 
203 	ASSERT(KCF_PROV_REFHELD(pd));
204 
205 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
206 		rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
207 		    object_ops),
208 		    CRYPTO_OBJECT_OFFSET(object_set_attribute_value),
209 		    pd, &real_provider);
210 
211 		if (rv != CRYPTO_SUCCESS)
212 			return (rv);
213 	}
214 
215 	if (CHECK_FASTPATH(crq, real_provider)) {
216 		rv = KCF_PROV_OBJECT_SET_ATTRIBUTE_VALUE(real_provider,
217 		    sid, object_handle, attrs, count, KCF_SWFP_RHNDL(crq));
218 		KCF_PROV_INCRSTATS(pd, rv);
219 	} else {
220 		KCF_WRAP_OBJECT_OPS_PARAMS(&params,
221 		    KCF_OP_OBJECT_SET_ATTRIBUTE_VALUE, sid, object_handle,
222 		    attrs, count, NULL, 0, NULL, NULL, 0, NULL);
223 		rv = kcf_submit_request(real_provider, NULL, crq,
224 		    &params, B_FALSE);
225 	}
226 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
227 		KCF_PROV_REFRELE(real_provider);
228 
229 	return (rv);
230 }
231 
232 int
crypto_object_get_size(crypto_provider_t provider,crypto_session_id_t sid,crypto_object_id_t object_handle,size_t * size,crypto_call_req_t * crq)233 crypto_object_get_size(crypto_provider_t provider, crypto_session_id_t sid,
234     crypto_object_id_t object_handle, size_t *size, crypto_call_req_t *crq)
235 {
236 	kcf_req_params_t params;
237 	kcf_provider_desc_t *pd = provider;
238 	kcf_provider_desc_t *real_provider = pd;
239 	int rv;
240 
241 	ASSERT(KCF_PROV_REFHELD(pd));
242 
243 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
244 		rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
245 		    object_ops), CRYPTO_OBJECT_OFFSET(object_get_size),
246 		    pd, &real_provider);
247 
248 		if (rv != CRYPTO_SUCCESS)
249 			return (rv);
250 
251 	}
252 
253 	if (CHECK_FASTPATH(crq, real_provider)) {
254 		rv = KCF_PROV_OBJECT_GET_SIZE(real_provider,
255 		    sid, object_handle, size, KCF_SWFP_RHNDL(crq));
256 		KCF_PROV_INCRSTATS(pd, rv);
257 	} else {
258 		KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_GET_SIZE, sid,
259 		    object_handle, NULL, 0, NULL, size, NULL, NULL, 0, NULL);
260 		rv = kcf_submit_request(real_provider, NULL, crq,
261 		    &params, B_FALSE);
262 	}
263 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
264 		KCF_PROV_REFRELE(real_provider);
265 
266 	return (rv);
267 }
268 
269 int
crypto_object_find_init(crypto_provider_t provider,crypto_session_id_t sid,crypto_object_attribute_t * attrs,uint_t count,void ** cookie,crypto_call_req_t * crq)270 crypto_object_find_init(crypto_provider_t provider, crypto_session_id_t sid,
271     crypto_object_attribute_t *attrs, uint_t count, void **cookie,
272     crypto_call_req_t *crq)
273 {
274 	kcf_req_params_t params;
275 	kcf_provider_desc_t *pd = provider;
276 	kcf_provider_desc_t *real_provider = pd;
277 	int rv;
278 
279 	ASSERT(KCF_PROV_REFHELD(pd));
280 
281 	if (cookie == NULL) {
282 		return (CRYPTO_ARGUMENTS_BAD);
283 	}
284 
285 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
286 		rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
287 		    object_ops), CRYPTO_OBJECT_OFFSET(object_find_init),
288 		    pd, &real_provider);
289 
290 		if (rv != CRYPTO_SUCCESS)
291 			return (rv);
292 	}
293 
294 	if (CHECK_FASTPATH(crq, real_provider)) {
295 		rv = KCF_PROV_OBJECT_FIND_INIT(real_provider,
296 		    sid, attrs, count, cookie, KCF_SWFP_RHNDL(crq));
297 		KCF_PROV_INCRSTATS(pd, rv);
298 	} else {
299 		KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_FIND_INIT,
300 		    sid, 0, attrs, count, NULL, 0, cookie, NULL, 0, NULL);
301 		rv = kcf_submit_request(real_provider, NULL, crq,
302 		    &params, B_FALSE);
303 	}
304 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
305 		KCF_PROV_REFRELE(real_provider);
306 
307 	return (rv);
308 }
309 
310 int
crypto_object_find_final(crypto_provider_t provider,void * cookie,crypto_call_req_t * crq)311 crypto_object_find_final(crypto_provider_t provider, void *cookie,
312     crypto_call_req_t *crq)
313 {
314 	kcf_req_params_t params;
315 	kcf_provider_desc_t *pd = provider;
316 	kcf_provider_desc_t *real_provider = pd;
317 	int rv;
318 
319 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
320 		rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
321 		    object_ops), CRYPTO_OBJECT_OFFSET(object_find_final),
322 		    pd, &real_provider);
323 
324 		if (rv != CRYPTO_SUCCESS)
325 			return (rv);
326 	}
327 
328 	if (CHECK_FASTPATH(crq, real_provider)) {
329 		rv = KCF_PROV_OBJECT_FIND_FINAL(real_provider,
330 		    cookie, KCF_SWFP_RHNDL(crq));
331 		KCF_PROV_INCRSTATS(pd, rv);
332 	} else {
333 		KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_FIND_FINAL,
334 		    0, 0, NULL, 0, NULL, 0, NULL, cookie, 0, NULL);
335 		rv = kcf_submit_request(real_provider, NULL, NULL, &params,
336 		    B_FALSE);
337 	}
338 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
339 		KCF_PROV_REFRELE(real_provider);
340 
341 	return (rv);
342 }
343 
344 int
crypto_object_find(crypto_provider_t provider,void * cookie,crypto_object_id_t * handles,uint_t * count,uint_t max_count,crypto_call_req_t * crq)345 crypto_object_find(crypto_provider_t provider, void *cookie,
346     crypto_object_id_t *handles, uint_t *count, uint_t max_count,
347     crypto_call_req_t *crq)
348 {
349 	kcf_req_params_t params;
350 	kcf_provider_desc_t *pd = provider;
351 	kcf_provider_desc_t *real_provider = pd;
352 	int rv;
353 
354 	ASSERT(KCF_PROV_REFHELD(pd));
355 
356 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
357 		rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
358 		    object_ops), CRYPTO_OBJECT_OFFSET(object_find),
359 		    pd, &real_provider);
360 
361 		if (rv != CRYPTO_SUCCESS)
362 			return (rv);
363 	}
364 
365 	if (CHECK_FASTPATH(crq, real_provider)) {
366 		rv = KCF_PROV_OBJECT_FIND(real_provider, cookie, handles,
367 		    max_count, count, KCF_SWFP_RHNDL(crq));
368 		KCF_PROV_INCRSTATS(pd, rv);
369 	} else {
370 		KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_FIND, 0,
371 		    0, NULL, 0, handles, 0, NULL, cookie, max_count, count);
372 		rv = kcf_submit_request(real_provider, NULL, crq,
373 		    &params, B_FALSE);
374 	}
375 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
376 		KCF_PROV_REFRELE(real_provider);
377 
378 	return (rv);
379 }
380