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 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 
30 #include <security/cryptoki.h>
31 #include "softGlobal.h"
32 #include "softSession.h"
33 #include "softKeys.h"
34 #include "softOps.h"
35 
36 
37 CK_RV
38 C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
39     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
40 {
41 
42 	CK_RV		rv;
43 	soft_session_t	*session_p;
44 	boolean_t	lock_held = B_FALSE;
45 
46 	if (!softtoken_initialized)
47 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
48 
49 	/* Obtain the session pointer. */
50 	rv = handle2session(hSession, &session_p);
51 	if (rv != CKR_OK)
52 		return (rv);
53 
54 	if ((pMechanism == NULL) || (phKey == NULL)) {
55 		rv = CKR_ARGUMENTS_BAD;
56 		goto clean_exit;
57 	}
58 
59 	if ((pTemplate == NULL) && (ulCount != 0)) {
60 		rv = CKR_ARGUMENTS_BAD;
61 		goto clean_exit;
62 	}
63 
64 	rv = soft_genkey(session_p, pMechanism, pTemplate,
65 	    ulCount, phKey);
66 
67 clean_exit:
68 	SES_REFRELE(session_p, lock_held);
69 	return (rv);
70 
71 }
72 
73 
74 CK_RV
75 C_GenerateKeyPair(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
76     CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount,
77     CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount,
78     CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey)
79 {
80 
81 	CK_RV		rv;
82 	soft_session_t	*session_p;
83 	boolean_t	lock_held = B_FALSE;
84 
85 	if (!softtoken_initialized)
86 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
87 
88 	/* Obtain the session pointer. */
89 	rv = handle2session(hSession, &session_p);
90 	if (rv != CKR_OK)
91 		return (rv);
92 
93 	if ((pMechanism == NULL) || (phPublicKey == NULL) ||
94 	    (phPrivateKey == NULL)) {
95 		rv = CKR_ARGUMENTS_BAD;
96 		goto clean_exit;
97 	}
98 
99 	if ((pPublicKeyTemplate == NULL) ||
100 	    (ulPublicKeyAttributeCount == 0)) {
101 		rv = CKR_ARGUMENTS_BAD;
102 		goto clean_exit;
103 	}
104 
105 	if ((pPrivateKeyTemplate == NULL) &&
106 	    (ulPrivateKeyAttributeCount != 0)) {
107 		rv = CKR_ARGUMENTS_BAD;
108 		goto clean_exit;
109 	}
110 
111 	rv = soft_genkey_pair(session_p, pMechanism, pPublicKeyTemplate,
112 	    ulPublicKeyAttributeCount, pPrivateKeyTemplate,
113 	    ulPrivateKeyAttributeCount, phPublicKey, phPrivateKey);
114 
115 clean_exit:
116 	SES_REFRELE(session_p, lock_held);
117 	return (rv);
118 }
119 
120 CK_RV
121 C_WrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
122     CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey,
123     CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen)
124 {
125 	CK_RV		rv;
126 	soft_session_t	*session_p;
127 	soft_object_t	*wrappingkey_p;
128 	soft_object_t	*hkey_p;
129 	boolean_t	lock_held = B_FALSE;
130 
131 	if (!softtoken_initialized)
132 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
133 
134 	/* Obtain the session pointer. */
135 	rv = handle2session(hSession, &session_p);
136 	if (rv != CKR_OK)
137 		return (rv);
138 
139 	if (pMechanism == NULL) {
140 		rv = CKR_ARGUMENTS_BAD;
141 		goto clean_exit;
142 	}
143 
144 	if (pulWrappedKeyLen == NULL) {
145 		rv = CKR_ARGUMENTS_BAD;
146 		goto clean_exit;
147 	}
148 
149 	/* Obtain the wrapping key object pointer. */
150 	HANDLE2OBJECT(hWrappingKey, wrappingkey_p, rv);
151 	if (rv != CKR_OK) {
152 		rv = CKR_WRAPPING_KEY_HANDLE_INVALID;
153 		goto clean_exit;
154 	}
155 
156 	/* Obtain the to-be-wrapped key object pointer. */
157 	HANDLE2OBJECT(hKey, hkey_p, rv);
158 	if (rv != CKR_OK)
159 		goto clean_exit1;
160 
161 	/* Check if given wrapping key may be used for wrapping. */
162 	if (!(wrappingkey_p->bool_attr_mask & WRAP_BOOL_ON)) {
163 		rv = CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
164 		goto clean_exit2;
165 	}
166 
167 	/* Check if given wrapping key may be used for encryption. */
168 	if (!(wrappingkey_p->bool_attr_mask & ENCRYPT_BOOL_ON)) {
169 		rv = CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
170 		goto clean_exit2;
171 	}
172 
173 	/*
174 	 * Check to see if key to be wrapped is extractable.
175 	 * Note: this should always be true for softtoken keys.
176 	 */
177 	if (!(hkey_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) {
178 		rv = CKR_KEY_UNEXTRACTABLE;
179 		goto clean_exit2;
180 	}
181 
182 	(void) pthread_mutex_lock(&session_p->session_mutex);
183 	lock_held = B_TRUE;
184 
185 	/*
186 	 * Wrapping key objects requires calling encrypt operations.
187 	 * Check to see if encrypt operation is already active.
188 	 */
189 	if (session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE) {
190 		/* free the memory to avoid memory leak */
191 		soft_crypt_cleanup(session_p, B_TRUE, lock_held);
192 	}
193 
194 	/* This active flag will remain ON while wrapping the key. */
195 	session_p->encrypt.flags = CRYPTO_OPERATION_ACTIVE;
196 
197 	(void) pthread_mutex_unlock(&session_p->session_mutex);
198 	lock_held = B_FALSE;
199 
200 	rv = soft_wrapkey(session_p, pMechanism, wrappingkey_p,
201 	    hkey_p, pWrappedKey, pulWrappedKeyLen);
202 
203 	(void) pthread_mutex_lock(&session_p->session_mutex);
204 	session_p->encrypt.flags = 0;
205 	lock_held = B_TRUE;
206 
207 clean_exit2:
208 	OBJ_REFRELE(hkey_p);
209 clean_exit1:
210 	OBJ_REFRELE(wrappingkey_p);
211 clean_exit:
212 	SES_REFRELE(session_p, lock_held);
213 	return (rv);
214 }
215 
216 CK_RV
217 C_UnwrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
218     CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey,
219     CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate,
220     CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
221 {
222 	CK_RV		rv;
223 	soft_session_t	*session_p;
224 	soft_object_t	*unwrappingkey_p;
225 	boolean_t	lock_held = B_FALSE;
226 
227 	if (!softtoken_initialized)
228 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
229 
230 	/* Obtain the session pointer. */
231 	rv = handle2session(hSession, &session_p);
232 	if (rv != CKR_OK)
233 		return (rv);
234 
235 	if (pMechanism == NULL) {
236 		rv = CKR_ARGUMENTS_BAD;
237 		goto clean_exit;
238 	}
239 
240 	if ((pTemplate == NULL) || (ulAttributeCount == 0)) {
241 		rv = CKR_ARGUMENTS_BAD;
242 		goto clean_exit;
243 	}
244 
245 	if ((pWrappedKey == NULL) || (ulWrappedKeyLen == 0)) {
246 		rv = CKR_ARGUMENTS_BAD;
247 		goto clean_exit;
248 	}
249 
250 	if (phKey == NULL) {
251 		rv = CKR_ARGUMENTS_BAD;
252 		goto clean_exit;
253 	}
254 
255 	/* Obtain the unwrapping key object pointer. */
256 	HANDLE2OBJECT(hUnwrappingKey, unwrappingkey_p, rv);
257 	if (rv != CKR_OK) {
258 		rv = CKR_UNWRAPPING_KEY_HANDLE_INVALID;
259 		goto clean_exit;
260 	}
261 
262 	/* Check if given unwrapping key may be used for unwrapping. */
263 	if (!(unwrappingkey_p->bool_attr_mask & UNWRAP_BOOL_ON)) {
264 		rv = CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
265 		goto clean_exit1;
266 	}
267 
268 	/* Check if given unwrapping key may be used to decrypt. */
269 	if (!(unwrappingkey_p->bool_attr_mask & DECRYPT_BOOL_ON)) {
270 		rv = CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
271 		goto clean_exit1;
272 	}
273 
274 	(void) pthread_mutex_lock(&session_p->session_mutex);
275 	lock_held = B_TRUE;
276 
277 	/*
278 	 * Unwrapping key objects requires calling decrypt operations.
279 	 * Check to see if decrypt operation is already active.
280 	 */
281 	if (session_p->decrypt.flags & CRYPTO_OPERATION_ACTIVE) {
282 		/* free the memory to avoid memory leak */
283 		soft_crypt_cleanup(session_p, B_FALSE, lock_held);
284 	}
285 
286 	/*
287 	 * This active flag will remain ON until application
288 	 * is done unwrapping the key.
289 	 */
290 	session_p->decrypt.flags = CRYPTO_OPERATION_ACTIVE;
291 
292 	(void) pthread_mutex_unlock(&session_p->session_mutex);
293 	lock_held = B_FALSE;
294 
295 	rv = soft_unwrapkey(session_p, pMechanism, unwrappingkey_p,
296 	    pWrappedKey, ulWrappedKeyLen, pTemplate, ulAttributeCount,
297 	    phKey);
298 
299 	(void) pthread_mutex_lock(&session_p->session_mutex);
300 	session_p->decrypt.flags = 0;
301 	lock_held = B_TRUE;
302 
303 clean_exit1:
304 	OBJ_REFRELE(unwrappingkey_p);
305 clean_exit:
306 	SES_REFRELE(session_p, lock_held);
307 	return (rv);
308 }
309 
310 
311 CK_RV
312 C_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
313     CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate,
314     CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
315 {
316 
317 	CK_RV		rv;
318 	soft_session_t	*session_p;
319 	soft_object_t	*basekey_p;
320 	boolean_t	lock_held = B_FALSE;
321 
322 	if (!softtoken_initialized)
323 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
324 
325 	/* Obtain the session pointer. */
326 	rv = handle2session(hSession, &session_p);
327 	if (rv != CKR_OK)
328 		return (rv);
329 
330 	if (pMechanism == NULL) {
331 		rv = CKR_ARGUMENTS_BAD;
332 		goto clean_exit;
333 	}
334 
335 	if (((pTemplate != NULL) && (ulAttributeCount == 0)) ||
336 	    ((pTemplate == NULL) && (ulAttributeCount != 0))) {
337 		rv = CKR_ARGUMENTS_BAD;
338 		goto clean_exit;
339 	}
340 
341 	/* Obtain the private key object pointer. */
342 	HANDLE2OBJECT(hBaseKey, basekey_p, rv);
343 	if (rv != CKR_OK)
344 		goto clean_exit;
345 
346 	/* Check to see if key object allows for derivation. */
347 	if (!(basekey_p->bool_attr_mask & DERIVE_BOOL_ON)) {
348 		rv = CKR_KEY_TYPE_INCONSISTENT;
349 		goto clean_exit1;
350 	}
351 
352 	rv = soft_derivekey(session_p, pMechanism, basekey_p,
353 	    pTemplate, ulAttributeCount, phKey);
354 
355 clean_exit1:
356 	OBJ_REFRELE(basekey_p);
357 clean_exit:
358 	SES_REFRELE(session_p, lock_held);
359 	return (rv);
360 }
361