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