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 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/errno.h>
30 #include <sys/types.h>
31 #include <sys/kmem.h>
32 #include <sys/cmn_err.h>
33 #include <sys/sysmacros.h>
34 #include <sys/crypto/common.h>
35 #include <sys/crypto/impl.h>
36 #include <sys/crypto/api.h>
37 #include <sys/crypto/spi.h>
38 #include <sys/crypto/sched_impl.h>
39 
40 #define	CRYPTO_OPS_OFFSET(f)		offsetof(crypto_ops_t, co_##f)
41 #define	CRYPTO_KEY_OFFSET(f)		offsetof(crypto_key_ops_t, f)
42 
43 int
44 crypto_key_generate(crypto_provider_t provider, crypto_session_id_t sid,
45     crypto_mechanism_t *mech, crypto_object_attribute_t *attrs, uint_t count,
46     crypto_object_id_t *handle, crypto_call_req_t *crq)
47 {
48 	kcf_req_params_t params;
49 	kcf_provider_desc_t *pd = provider;
50 	kcf_provider_desc_t *real_provider = pd;
51 	int rv;
52 
53 	ASSERT(KCF_PROV_REFHELD(pd));
54 
55 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
56 		rv = kcf_get_hardware_provider(mech->cm_type,
57 		    CRYPTO_MECH_INVALID, CHECK_RESTRICT(crq),
58 		    pd, &real_provider, CRYPTO_FG_GENERATE);
59 
60 		if (rv != CRYPTO_SUCCESS)
61 			return (rv);
62 	}
63 
64 	if (CHECK_FASTPATH(crq, real_provider)) {
65 		rv = KCF_PROV_KEY_GENERATE(real_provider, sid,
66 		    mech, attrs, count, handle, KCF_SWFP_RHNDL(crq));
67 		KCF_PROV_INCRSTATS(pd, rv);
68 	} else {
69 		KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_GENERATE, sid,
70 		    mech, attrs, count, handle, NULL, 0, NULL, NULL, NULL, 0);
71 		rv = kcf_submit_request(real_provider, NULL, crq,
72 		    &params, B_FALSE);
73 	}
74 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
75 		KCF_PROV_REFRELE(real_provider);
76 
77 	return (rv);
78 }
79 
80 int
81 crypto_key_generate_pair(crypto_provider_t provider, crypto_session_id_t sid,
82     crypto_mechanism_t *mech, crypto_object_attribute_t *pub_attrs,
83     uint_t pub_count, crypto_object_attribute_t *pri_attrs, uint_t pri_count,
84     crypto_object_id_t *pub_handle, crypto_object_id_t *pri_handle,
85     crypto_call_req_t *crq)
86 {
87 	kcf_req_params_t params;
88 	kcf_provider_desc_t *pd = provider;
89 	kcf_provider_desc_t *real_provider = pd;
90 	int rv;
91 
92 	ASSERT(KCF_PROV_REFHELD(pd));
93 
94 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
95 		rv = kcf_get_hardware_provider(mech->cm_type,
96 		    CRYPTO_MECH_INVALID, CHECK_RESTRICT(crq),
97 		    pd, &real_provider, CRYPTO_FG_GENERATE_KEY_PAIR);
98 
99 		if (rv != CRYPTO_SUCCESS)
100 			return (rv);
101 	}
102 
103 	if (CHECK_FASTPATH(crq, real_provider)) {
104 		rv = KCF_PROV_KEY_GENERATE_PAIR(real_provider, sid, mech,
105 		    pub_attrs, pub_count, pri_attrs, pri_count, pub_handle,
106 		    pri_handle, KCF_SWFP_RHNDL(crq));
107 		KCF_PROV_INCRSTATS(pd, rv);
108 	} else {
109 		KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_GENERATE_PAIR,
110 		    sid, mech, pub_attrs, pub_count, pub_handle, pri_attrs,
111 		    pri_count, pri_handle, NULL, NULL, 0);
112 		rv = kcf_submit_request(real_provider, NULL, crq,
113 		    &params, B_FALSE);
114 	}
115 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
116 		KCF_PROV_REFRELE(real_provider);
117 
118 	return (rv);
119 }
120 
121 int
122 crypto_key_wrap(crypto_provider_t provider, crypto_session_id_t sid,
123     crypto_mechanism_t *mech, crypto_key_t *wrapping_key,
124     crypto_object_id_t *key, uchar_t *wrapped_key, size_t *wrapped_key_len,
125     crypto_call_req_t *crq)
126 {
127 	kcf_req_params_t params;
128 	kcf_provider_desc_t *pd = provider;
129 	kcf_provider_desc_t *real_provider = pd;
130 	int rv;
131 
132 	ASSERT(KCF_PROV_REFHELD(pd));
133 
134 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
135 		rv = kcf_get_hardware_provider(mech->cm_type,
136 		    CRYPTO_MECH_INVALID, CHECK_RESTRICT(crq),
137 		    pd, &real_provider, CRYPTO_FG_WRAP);
138 
139 		if (rv != CRYPTO_SUCCESS)
140 			return (rv);
141 	}
142 
143 	if (CHECK_FASTPATH(crq, real_provider)) {
144 		rv = KCF_PROV_KEY_WRAP(real_provider, sid, mech, wrapping_key,
145 		    key, wrapped_key, wrapped_key_len, KCF_SWFP_RHNDL(crq));
146 		KCF_PROV_INCRSTATS(pd, rv);
147 	} else {
148 		KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_WRAP, sid, mech,
149 		    NULL, 0, key, NULL, 0, NULL, wrapping_key, wrapped_key,
150 		    wrapped_key_len);
151 		rv = kcf_submit_request(real_provider, NULL, crq,
152 		    &params, B_FALSE);
153 	}
154 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
155 		KCF_PROV_REFRELE(real_provider);
156 
157 	return (rv);
158 }
159 
160 int
161 crypto_key_unwrap(crypto_provider_t provider, crypto_session_id_t sid,
162     crypto_mechanism_t *mech, crypto_key_t *unwrapping_key,
163     uchar_t *wrapped_key, size_t *wrapped_key_len,
164     crypto_object_attribute_t *attrs, uint_t count, crypto_object_id_t *key,
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(mech->cm_type,
176 		    CRYPTO_MECH_INVALID, CHECK_RESTRICT(crq),
177 		    pd, &real_provider, CRYPTO_FG_UNWRAP);
178 
179 		if (rv != CRYPTO_SUCCESS)
180 			return (rv);
181 	}
182 
183 	if (CHECK_FASTPATH(crq, real_provider)) {
184 		rv = KCF_PROV_KEY_UNWRAP(real_provider, sid, mech,
185 		    unwrapping_key, wrapped_key, wrapped_key_len, attrs,
186 		    count, key, KCF_SWFP_RHNDL(crq));
187 		KCF_PROV_INCRSTATS(pd, rv);
188 	} else {
189 		KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_UNWRAP, sid, mech,
190 		    attrs, count, key, NULL, 0, NULL, unwrapping_key,
191 		    wrapped_key, wrapped_key_len);
192 		rv = kcf_submit_request(real_provider, NULL, crq,
193 		    &params, B_FALSE);
194 	}
195 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
196 		KCF_PROV_REFRELE(real_provider);
197 
198 	return (rv);
199 }
200 
201 int
202 crypto_key_derive(crypto_provider_t provider, crypto_session_id_t sid,
203     crypto_mechanism_t *mech, crypto_key_t *base_key,
204     crypto_object_attribute_t *attrs, uint_t count,
205     crypto_object_id_t *new_key, crypto_call_req_t *crq)
206 {
207 	kcf_req_params_t params;
208 	kcf_provider_desc_t *pd = provider;
209 	kcf_provider_desc_t *real_provider = pd;
210 	int rv;
211 
212 	ASSERT(KCF_PROV_REFHELD(pd));
213 
214 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
215 		rv = kcf_get_hardware_provider(mech->cm_type,
216 		    CRYPTO_MECH_INVALID, CHECK_RESTRICT(crq),
217 		    pd, &real_provider, CRYPTO_FG_DERIVE);
218 
219 		if (rv != CRYPTO_SUCCESS)
220 			return (rv);
221 	}
222 
223 	if (CHECK_FASTPATH(crq, real_provider)) {
224 		rv = KCF_PROV_KEY_DERIVE(real_provider, sid, mech, base_key,
225 		    attrs, count, new_key, KCF_SWFP_RHNDL(crq));
226 		KCF_PROV_INCRSTATS(pd, rv);
227 	} else {
228 		KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_DERIVE, sid, mech,
229 		    attrs, count, new_key, NULL, 0, NULL, base_key, NULL, NULL);
230 		rv = kcf_submit_request(real_provider, NULL, crq,
231 		    &params, B_FALSE);
232 	}
233 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
234 		KCF_PROV_REFRELE(real_provider);
235 
236 	return (rv);
237 }
238