1894b2776Smcpowers /*
2894b2776Smcpowers  * CDDL HEADER START
3894b2776Smcpowers  *
4894b2776Smcpowers  * The contents of this file are subject to the terms of the
5*9b009fc1SValerie Bubb Fenwick  * Common Development and Distribution License (the "License").
6*9b009fc1SValerie Bubb Fenwick  * 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 
26894b2776Smcpowers #include <sys/errno.h>
27894b2776Smcpowers #include <sys/types.h>
28894b2776Smcpowers #include <sys/kmem.h>
29894b2776Smcpowers #include <sys/cmn_err.h>
30894b2776Smcpowers #include <sys/sysmacros.h>
31894b2776Smcpowers #include <sys/crypto/common.h>
32894b2776Smcpowers #include <sys/crypto/impl.h>
33894b2776Smcpowers #include <sys/crypto/api.h>
34894b2776Smcpowers #include <sys/crypto/spi.h>
35894b2776Smcpowers #include <sys/crypto/sched_impl.h>
36894b2776Smcpowers 
37894b2776Smcpowers #define	CRYPTO_OPS_OFFSET(f)		offsetof(crypto_ops_t, co_##f)
38894b2776Smcpowers #define	CRYPTO_OBJECT_OFFSET(f)		offsetof(crypto_object_ops_t, f)
39894b2776Smcpowers #define	CRYPTO_SESSION_OFFSET(f)	offsetof(crypto_session_ops_t, f)
40894b2776Smcpowers 
41894b2776Smcpowers int
crypto_session_open(crypto_provider_t provider,crypto_session_id_t * sidp,crypto_call_req_t * crq)42894b2776Smcpowers crypto_session_open(crypto_provider_t provider, crypto_session_id_t *sidp,
43894b2776Smcpowers crypto_call_req_t *crq)
44894b2776Smcpowers {
45894b2776Smcpowers 	kcf_req_params_t params;
46894b2776Smcpowers 	kcf_provider_desc_t *real_provider;
47894b2776Smcpowers 	kcf_provider_desc_t *pd = provider;
48894b2776Smcpowers 
49894b2776Smcpowers 	ASSERT(KCF_PROV_REFHELD(pd));
50894b2776Smcpowers 
51894b2776Smcpowers 	/* find a provider that supports session ops */
52894b2776Smcpowers 	(void) kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(session_ops),
53*9b009fc1SValerie Bubb Fenwick 	    CRYPTO_SESSION_OFFSET(session_open), pd, &real_provider);
54894b2776Smcpowers 
55894b2776Smcpowers 	if (real_provider != NULL) {
56894b2776Smcpowers 		int rv;
57894b2776Smcpowers 
58894b2776Smcpowers 		ASSERT(real_provider == pd ||
59894b2776Smcpowers 		    pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER);
60894b2776Smcpowers 
61894b2776Smcpowers 		if (CHECK_FASTPATH(crq, pd)) {
62894b2776Smcpowers 			rv = KCF_PROV_SESSION_OPEN(real_provider, sidp,
63894b2776Smcpowers 			    KCF_SWFP_RHNDL(crq), pd);
64894b2776Smcpowers 			KCF_PROV_INCRSTATS(pd, rv);
65894b2776Smcpowers 		} else {
66894b2776Smcpowers 			KCF_WRAP_SESSION_OPS_PARAMS(&params,
67894b2776Smcpowers 			    KCF_OP_SESSION_OPEN, sidp, 0, CRYPTO_USER, NULL,
68894b2776Smcpowers 			    0, pd);
69894b2776Smcpowers 			rv = kcf_submit_request(real_provider, NULL, crq,
70894b2776Smcpowers 			    &params, B_FALSE);
71894b2776Smcpowers 		}
72894b2776Smcpowers 		KCF_PROV_REFRELE(real_provider);
73894b2776Smcpowers 
74894b2776Smcpowers 		if (rv != CRYPTO_SUCCESS) {
75894b2776Smcpowers 			return (rv);
76894b2776Smcpowers 		}
77894b2776Smcpowers 	}
78894b2776Smcpowers 	return (CRYPTO_SUCCESS);
79894b2776Smcpowers }
80894b2776Smcpowers 
81894b2776Smcpowers int
crypto_session_close(crypto_provider_t provider,crypto_session_id_t sid,crypto_call_req_t * crq)82894b2776Smcpowers crypto_session_close(crypto_provider_t provider, crypto_session_id_t sid,
83894b2776Smcpowers     crypto_call_req_t *crq)
84894b2776Smcpowers {
85894b2776Smcpowers 	int rv;
86894b2776Smcpowers 	kcf_req_params_t params;
87894b2776Smcpowers 	kcf_provider_desc_t *real_provider;
88894b2776Smcpowers 	kcf_provider_desc_t *pd = provider;
89894b2776Smcpowers 
90894b2776Smcpowers 	if (pd == NULL)
91*9b009fc1SValerie Bubb Fenwick 		return (CRYPTO_ARGUMENTS_BAD);
92894b2776Smcpowers 
93894b2776Smcpowers 	ASSERT(KCF_PROV_REFHELD(pd));
94894b2776Smcpowers 
95894b2776Smcpowers 	/* find a provider that supports session ops */
96894b2776Smcpowers 	(void) kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(session_ops),
97*9b009fc1SValerie Bubb Fenwick 	    CRYPTO_SESSION_OFFSET(session_close), pd, &real_provider);
98894b2776Smcpowers 
99894b2776Smcpowers 	ASSERT(real_provider == pd ||
100894b2776Smcpowers 	    pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER);
101894b2776Smcpowers 
102894b2776Smcpowers 	/* edge case is where the logical provider has no members */
103894b2776Smcpowers 	if (real_provider != NULL) {
104894b2776Smcpowers 		/* The fast path for SW providers. */
105894b2776Smcpowers 		if (CHECK_FASTPATH(crq, pd)) {
106894b2776Smcpowers 			rv = KCF_PROV_SESSION_CLOSE(real_provider,
107894b2776Smcpowers 			    sid, KCF_SWFP_RHNDL(crq), pd);
108894b2776Smcpowers 			KCF_PROV_INCRSTATS(pd, rv);
109894b2776Smcpowers 		} else {
110894b2776Smcpowers 			KCF_WRAP_SESSION_OPS_PARAMS(&params,
111894b2776Smcpowers 			    KCF_OP_SESSION_CLOSE, NULL, sid,
112894b2776Smcpowers 			    CRYPTO_USER, NULL, 0, pd);
113894b2776Smcpowers 			rv = kcf_submit_request(real_provider, NULL, crq,
114894b2776Smcpowers 			    &params, B_FALSE);
115894b2776Smcpowers 		}
116894b2776Smcpowers 		KCF_PROV_REFRELE(real_provider);
117894b2776Smcpowers 	}
118894b2776Smcpowers 	return (CRYPTO_SUCCESS);
119894b2776Smcpowers }
120894b2776Smcpowers 
121894b2776Smcpowers int
crypto_session_login(crypto_provider_t provider,crypto_session_id_t sid,crypto_user_type_t type,char * pin,ulong_t len,crypto_call_req_t * crq)122894b2776Smcpowers crypto_session_login(crypto_provider_t provider, crypto_session_id_t sid,
123894b2776Smcpowers     crypto_user_type_t type, char *pin, ulong_t len, crypto_call_req_t *crq)
124894b2776Smcpowers {
125894b2776Smcpowers 	kcf_req_params_t params;
126894b2776Smcpowers 	kcf_provider_desc_t *pd = provider;
127894b2776Smcpowers 	kcf_provider_desc_t *real_provider = pd;
128894b2776Smcpowers 	int rv;
129894b2776Smcpowers 
130894b2776Smcpowers 	ASSERT(KCF_PROV_REFHELD(pd));
131894b2776Smcpowers 
132894b2776Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
133894b2776Smcpowers 		rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
134894b2776Smcpowers 		    session_ops), CRYPTO_SESSION_OFFSET(session_login),
135*9b009fc1SValerie Bubb Fenwick 		    pd, &real_provider);
136894b2776Smcpowers 
137894b2776Smcpowers 		if (rv != CRYPTO_SUCCESS)
138894b2776Smcpowers 			return (rv);
139894b2776Smcpowers 	}
140894b2776Smcpowers 
141894b2776Smcpowers 	if (CHECK_FASTPATH(crq, real_provider)) {
142894b2776Smcpowers 		rv = KCF_PROV_SESSION_LOGIN(real_provider, sid,
143894b2776Smcpowers 		    type, pin, len, KCF_SWFP_RHNDL(crq));
144894b2776Smcpowers 		KCF_PROV_INCRSTATS(pd, rv);
145894b2776Smcpowers 	} else {
146894b2776Smcpowers 		KCF_WRAP_SESSION_OPS_PARAMS(&params, KCF_OP_SESSION_LOGIN,
147894b2776Smcpowers 		    NULL, sid, type, pin, len, real_provider);
148894b2776Smcpowers 		rv = kcf_submit_request(real_provider, NULL, crq,
149894b2776Smcpowers 		    &params, B_FALSE);
150894b2776Smcpowers 	}
151894b2776Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
152894b2776Smcpowers 		KCF_PROV_REFRELE(real_provider);
153894b2776Smcpowers 
154894b2776Smcpowers 	return (rv);
155894b2776Smcpowers }
156894b2776Smcpowers 
157894b2776Smcpowers int
crypto_session_logout(crypto_provider_t provider,crypto_session_id_t sid,crypto_call_req_t * crq)158894b2776Smcpowers crypto_session_logout(crypto_provider_t provider, crypto_session_id_t sid,
159894b2776Smcpowers     crypto_call_req_t *crq)
160894b2776Smcpowers {
161894b2776Smcpowers 	kcf_req_params_t params;
162894b2776Smcpowers 	kcf_provider_desc_t *pd = provider;
163894b2776Smcpowers 	kcf_provider_desc_t *real_provider = pd;
164894b2776Smcpowers 	int rv;
165894b2776Smcpowers 
166894b2776Smcpowers 	ASSERT(KCF_PROV_REFHELD(pd));
167894b2776Smcpowers 
168894b2776Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
169894b2776Smcpowers 		rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
170894b2776Smcpowers 		    session_ops), CRYPTO_SESSION_OFFSET(session_logout),
171*9b009fc1SValerie Bubb Fenwick 		    pd, &real_provider);
172894b2776Smcpowers 
173894b2776Smcpowers 		if (rv != CRYPTO_SUCCESS)
174894b2776Smcpowers 			return (rv);
175894b2776Smcpowers 	}
176894b2776Smcpowers 
177894b2776Smcpowers 	if (CHECK_FASTPATH(crq, real_provider)) {
178894b2776Smcpowers 		rv = KCF_PROV_SESSION_LOGOUT(real_provider, sid,
179894b2776Smcpowers 		    KCF_SWFP_RHNDL(crq));
180894b2776Smcpowers 		KCF_PROV_INCRSTATS(pd, rv);
181894b2776Smcpowers 	} else {
182894b2776Smcpowers 		KCF_WRAP_SESSION_OPS_PARAMS(&params, KCF_OP_SESSION_LOGOUT,
183894b2776Smcpowers 		    NULL, sid, 0, NULL, 0, real_provider);
184894b2776Smcpowers 		rv = kcf_submit_request(real_provider, NULL, crq,
185894b2776Smcpowers 		    &params, B_FALSE);
186894b2776Smcpowers 	}
187894b2776Smcpowers 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
188894b2776Smcpowers 		KCF_PROV_REFRELE(real_provider);
189894b2776Smcpowers 
190894b2776Smcpowers 	return (rv);
191894b2776Smcpowers }
192