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