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