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