1894b2776Smcpowers /*
2894b2776Smcpowers  * CDDL HEADER START
3894b2776Smcpowers  *
4894b2776Smcpowers  * The contents of this file are subject to the terms of the
572eff6e2Smcpowers  * Common Development and Distribution License (the "License").
672eff6e2Smcpowers  * You may not use this file except in compliance with the License.
7894b2776Smcpowers  *
8894b2776Smcpowers  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9894b2776Smcpowers  * or http://www.opensolaris.org/os/licensing.
10894b2776Smcpowers  * See the License for the specific language governing permissions
11894b2776Smcpowers  * and limitations under the License.
12894b2776Smcpowers  *
13894b2776Smcpowers  * When distributing Covered Code, include this CDDL HEADER in each
14894b2776Smcpowers  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15894b2776Smcpowers  * If applicable, add the following below this CDDL HEADER, with the
16894b2776Smcpowers  * fields enclosed by brackets "[]" replaced with your own identifying
17894b2776Smcpowers  * information: Portions Copyright [yyyy] [name of copyright owner]
18894b2776Smcpowers  *
19894b2776Smcpowers  * CDDL HEADER END
20894b2776Smcpowers  */
21894b2776Smcpowers /*
22*9b009fc1SValerie Bubb Fenwick  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23894b2776Smcpowers  */
24894b2776Smcpowers 
25894b2776Smcpowers #include <sys/errno.h>
26894b2776Smcpowers #include <sys/types.h>
27894b2776Smcpowers #include <sys/kmem.h>
28894b2776Smcpowers #include <sys/cmn_err.h>
29894b2776Smcpowers #include <sys/sysmacros.h>
30894b2776Smcpowers #include <sys/crypto/common.h>
31894b2776Smcpowers #include <sys/crypto/impl.h>
32894b2776Smcpowers #include <sys/crypto/api.h>
33894b2776Smcpowers #include <sys/crypto/spi.h>
34894b2776Smcpowers #include <sys/crypto/sched_impl.h>
35894b2776Smcpowers 
36894b2776Smcpowers #define	CRYPTO_OPS_OFFSET(f)		offsetof(crypto_ops_t, co_##f)
37894b2776Smcpowers #define	CRYPTO_KEY_OFFSET(f)		offsetof(crypto_key_ops_t, f)
38894b2776Smcpowers 
39894b2776Smcpowers 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)40894b2776Smcpowers crypto_key_generate(crypto_provider_t provider, crypto_session_id_t sid,
41894b2776Smcpowers     crypto_mechanism_t *mech, crypto_object_attribute_t *attrs, uint_t count,
42894b2776Smcpowers     crypto_object_id_t *handle, crypto_call_req_t *crq)
43894b2776Smcpowers {
44894b2776Smcpowers 	kcf_req_params_t params;
45894b2776Smcpowers 	kcf_provider_desc_t *pd = provider;
46894b2776Smcpowers 	kcf_provider_desc_t *real_provider = pd;
47894b2776Smcpowers 	int rv;
48894b2776Smcpowers 
49894b2776Smcpowers 	ASSERT(KCF_PROV_REFHELD(pd));
50894b2776Smcpowers 
51894b2776Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
52436935a1SVladimir Kotal 		rv = kcf_get_hardware_provider(mech->cm_type, NULL,
53*9b009fc1SValerie Bubb Fenwick 		    CRYPTO_MECH_INVALID, NULL, pd, &real_provider,
54*9b009fc1SValerie Bubb Fenwick 		    CRYPTO_FG_GENERATE);
55894b2776Smcpowers 
56894b2776Smcpowers 		if (rv != CRYPTO_SUCCESS)
57894b2776Smcpowers 			return (rv);
58894b2776Smcpowers 	}
59894b2776Smcpowers 
60894b2776Smcpowers 	if (CHECK_FASTPATH(crq, real_provider)) {
61894b2776Smcpowers 		rv = KCF_PROV_KEY_GENERATE(real_provider, sid,
62894b2776Smcpowers 		    mech, attrs, count, handle, KCF_SWFP_RHNDL(crq));
63894b2776Smcpowers 		KCF_PROV_INCRSTATS(pd, rv);
64894b2776Smcpowers 	} else {
65894b2776Smcpowers 		KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_GENERATE, sid,
66894b2776Smcpowers 		    mech, attrs, count, handle, NULL, 0, NULL, NULL, NULL, 0);
67894b2776Smcpowers 		rv = kcf_submit_request(real_provider, NULL, crq,
68894b2776Smcpowers 		    &params, B_FALSE);
69894b2776Smcpowers 	}
70894b2776Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
71894b2776Smcpowers 		KCF_PROV_REFRELE(real_provider);
72894b2776Smcpowers 
73894b2776Smcpowers 	return (rv);
74894b2776Smcpowers }
75894b2776Smcpowers 
76894b2776Smcpowers 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)77894b2776Smcpowers crypto_key_generate_pair(crypto_provider_t provider, crypto_session_id_t sid,
78894b2776Smcpowers     crypto_mechanism_t *mech, crypto_object_attribute_t *pub_attrs,
79894b2776Smcpowers     uint_t pub_count, crypto_object_attribute_t *pri_attrs, uint_t pri_count,
80894b2776Smcpowers     crypto_object_id_t *pub_handle, crypto_object_id_t *pri_handle,
81894b2776Smcpowers     crypto_call_req_t *crq)
82894b2776Smcpowers {
83894b2776Smcpowers 	kcf_req_params_t params;
84894b2776Smcpowers 	kcf_provider_desc_t *pd = provider;
85894b2776Smcpowers 	kcf_provider_desc_t *real_provider = pd;
86894b2776Smcpowers 	int rv;
87894b2776Smcpowers 
88894b2776Smcpowers 	ASSERT(KCF_PROV_REFHELD(pd));
89894b2776Smcpowers 
90894b2776Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
91436935a1SVladimir Kotal 		rv = kcf_get_hardware_provider(mech->cm_type, NULL,
92*9b009fc1SValerie Bubb Fenwick 		    CRYPTO_MECH_INVALID, NULL, pd, &real_provider,
93*9b009fc1SValerie Bubb Fenwick 		    CRYPTO_FG_GENERATE_KEY_PAIR);
94894b2776Smcpowers 
95894b2776Smcpowers 		if (rv != CRYPTO_SUCCESS)
96894b2776Smcpowers 			return (rv);
97894b2776Smcpowers 	}
98894b2776Smcpowers 
99894b2776Smcpowers 	if (CHECK_FASTPATH(crq, real_provider)) {
100894b2776Smcpowers 		rv = KCF_PROV_KEY_GENERATE_PAIR(real_provider, sid, mech,
101894b2776Smcpowers 		    pub_attrs, pub_count, pri_attrs, pri_count, pub_handle,
102894b2776Smcpowers 		    pri_handle, KCF_SWFP_RHNDL(crq));
103894b2776Smcpowers 		KCF_PROV_INCRSTATS(pd, rv);
104894b2776Smcpowers 	} else {
105894b2776Smcpowers 		KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_GENERATE_PAIR,
106894b2776Smcpowers 		    sid, mech, pub_attrs, pub_count, pub_handle, pri_attrs,
107894b2776Smcpowers 		    pri_count, pri_handle, NULL, NULL, 0);
108894b2776Smcpowers 		rv = kcf_submit_request(real_provider, NULL, crq,
109894b2776Smcpowers 		    &params, B_FALSE);
110894b2776Smcpowers 	}
111894b2776Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
112894b2776Smcpowers 		KCF_PROV_REFRELE(real_provider);
113894b2776Smcpowers 
114894b2776Smcpowers 	return (rv);
115894b2776Smcpowers }
116894b2776Smcpowers 
117894b2776Smcpowers 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)118894b2776Smcpowers crypto_key_wrap(crypto_provider_t provider, crypto_session_id_t sid,
119894b2776Smcpowers     crypto_mechanism_t *mech, crypto_key_t *wrapping_key,
120894b2776Smcpowers     crypto_object_id_t *key, uchar_t *wrapped_key, size_t *wrapped_key_len,
121894b2776Smcpowers     crypto_call_req_t *crq)
122894b2776Smcpowers {
123894b2776Smcpowers 	kcf_req_params_t params;
124894b2776Smcpowers 	kcf_provider_desc_t *pd = provider;
125894b2776Smcpowers 	kcf_provider_desc_t *real_provider = pd;
126894b2776Smcpowers 	int rv;
127894b2776Smcpowers 
128894b2776Smcpowers 	ASSERT(KCF_PROV_REFHELD(pd));
129894b2776Smcpowers 
130894b2776Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
131436935a1SVladimir Kotal 		rv = kcf_get_hardware_provider(mech->cm_type, wrapping_key,
132*9b009fc1SValerie Bubb Fenwick 		    CRYPTO_MECH_INVALID, NULL, pd, &real_provider,
133*9b009fc1SValerie Bubb Fenwick 		    CRYPTO_FG_WRAP);
134894b2776Smcpowers 
135894b2776Smcpowers 		if (rv != CRYPTO_SUCCESS)
136894b2776Smcpowers 			return (rv);
137894b2776Smcpowers 	}
138894b2776Smcpowers 
139894b2776Smcpowers 	if (CHECK_FASTPATH(crq, real_provider)) {
140894b2776Smcpowers 		rv = KCF_PROV_KEY_WRAP(real_provider, sid, mech, wrapping_key,
141894b2776Smcpowers 		    key, wrapped_key, wrapped_key_len, KCF_SWFP_RHNDL(crq));
142894b2776Smcpowers 		KCF_PROV_INCRSTATS(pd, rv);
143894b2776Smcpowers 	} else {
144894b2776Smcpowers 		KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_WRAP, sid, mech,
145894b2776Smcpowers 		    NULL, 0, key, NULL, 0, NULL, wrapping_key, wrapped_key,
146894b2776Smcpowers 		    wrapped_key_len);
147894b2776Smcpowers 		rv = kcf_submit_request(real_provider, NULL, crq,
148894b2776Smcpowers 		    &params, B_FALSE);
149894b2776Smcpowers 	}
150894b2776Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
151894b2776Smcpowers 		KCF_PROV_REFRELE(real_provider);
152894b2776Smcpowers 
153894b2776Smcpowers 	return (rv);
154894b2776Smcpowers }
155894b2776Smcpowers 
156894b2776Smcpowers 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)157894b2776Smcpowers crypto_key_unwrap(crypto_provider_t provider, crypto_session_id_t sid,
158894b2776Smcpowers     crypto_mechanism_t *mech, crypto_key_t *unwrapping_key,
159894b2776Smcpowers     uchar_t *wrapped_key, size_t *wrapped_key_len,
160894b2776Smcpowers     crypto_object_attribute_t *attrs, uint_t count, crypto_object_id_t *key,
161894b2776Smcpowers     crypto_call_req_t *crq)
162894b2776Smcpowers {
163894b2776Smcpowers 	kcf_req_params_t params;
164894b2776Smcpowers 	kcf_provider_desc_t *pd = provider;
165894b2776Smcpowers 	kcf_provider_desc_t *real_provider = pd;
166894b2776Smcpowers 	int rv;
167894b2776Smcpowers 
168894b2776Smcpowers 	ASSERT(KCF_PROV_REFHELD(pd));
169894b2776Smcpowers 
170894b2776Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
171436935a1SVladimir Kotal 		rv = kcf_get_hardware_provider(mech->cm_type, unwrapping_key,
172*9b009fc1SValerie Bubb Fenwick 		    CRYPTO_MECH_INVALID, NULL, pd, &real_provider,
173*9b009fc1SValerie Bubb Fenwick 		    CRYPTO_FG_UNWRAP);
174894b2776Smcpowers 
175894b2776Smcpowers 		if (rv != CRYPTO_SUCCESS)
176894b2776Smcpowers 			return (rv);
177894b2776Smcpowers 	}
178894b2776Smcpowers 
179894b2776Smcpowers 	if (CHECK_FASTPATH(crq, real_provider)) {
180894b2776Smcpowers 		rv = KCF_PROV_KEY_UNWRAP(real_provider, sid, mech,
181894b2776Smcpowers 		    unwrapping_key, wrapped_key, wrapped_key_len, attrs,
182894b2776Smcpowers 		    count, key, KCF_SWFP_RHNDL(crq));
183894b2776Smcpowers 		KCF_PROV_INCRSTATS(pd, rv);
184894b2776Smcpowers 	} else {
185894b2776Smcpowers 		KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_UNWRAP, sid, mech,
186894b2776Smcpowers 		    attrs, count, key, NULL, 0, NULL, unwrapping_key,
187894b2776Smcpowers 		    wrapped_key, wrapped_key_len);
188894b2776Smcpowers 		rv = kcf_submit_request(real_provider, NULL, crq,
189894b2776Smcpowers 		    &params, B_FALSE);
190894b2776Smcpowers 	}
191894b2776Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
192894b2776Smcpowers 		KCF_PROV_REFRELE(real_provider);
193894b2776Smcpowers 
194894b2776Smcpowers 	return (rv);
195894b2776Smcpowers }
196894b2776Smcpowers 
197894b2776Smcpowers 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)198894b2776Smcpowers crypto_key_derive(crypto_provider_t provider, crypto_session_id_t sid,
199894b2776Smcpowers     crypto_mechanism_t *mech, crypto_key_t *base_key,
200894b2776Smcpowers     crypto_object_attribute_t *attrs, uint_t count,
201894b2776Smcpowers     crypto_object_id_t *new_key, crypto_call_req_t *crq)
202894b2776Smcpowers {
203894b2776Smcpowers 	kcf_req_params_t params;
204894b2776Smcpowers 	kcf_provider_desc_t *pd = provider;
205894b2776Smcpowers 	kcf_provider_desc_t *real_provider = pd;
206894b2776Smcpowers 	int rv;
207894b2776Smcpowers 
208894b2776Smcpowers 	ASSERT(KCF_PROV_REFHELD(pd));
209894b2776Smcpowers 
210894b2776Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
211436935a1SVladimir Kotal 		rv = kcf_get_hardware_provider(mech->cm_type, base_key,
212*9b009fc1SValerie Bubb Fenwick 		    CRYPTO_MECH_INVALID, NULL, pd, &real_provider,
213*9b009fc1SValerie Bubb Fenwick 		    CRYPTO_FG_DERIVE);
214894b2776Smcpowers 
215894b2776Smcpowers 		if (rv != CRYPTO_SUCCESS)
216894b2776Smcpowers 			return (rv);
217894b2776Smcpowers 	}
218894b2776Smcpowers 
219894b2776Smcpowers 	if (CHECK_FASTPATH(crq, real_provider)) {
220894b2776Smcpowers 		rv = KCF_PROV_KEY_DERIVE(real_provider, sid, mech, base_key,
221894b2776Smcpowers 		    attrs, count, new_key, KCF_SWFP_RHNDL(crq));
222894b2776Smcpowers 		KCF_PROV_INCRSTATS(pd, rv);
223894b2776Smcpowers 	} else {
224894b2776Smcpowers 		KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_DERIVE, sid, mech,
225894b2776Smcpowers 		    attrs, count, new_key, NULL, 0, NULL, base_key, NULL, NULL);
226894b2776Smcpowers 		rv = kcf_submit_request(real_provider, NULL, crq,
227894b2776Smcpowers 		    &params, B_FALSE);
228894b2776Smcpowers 	}
229894b2776Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
230894b2776Smcpowers 		KCF_PROV_REFRELE(real_provider);
231894b2776Smcpowers 
232894b2776Smcpowers 	return (rv);
233894b2776Smcpowers }
234