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 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <pthread.h>
27 #include <security/cryptoki.h>
28 #include "softGlobal.h"
29 #include "softOps.h"
30 #include "softSession.h"
31
32
33 CK_RV
C_DigestInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism)34 C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism)
35 {
36
37 CK_RV rv;
38 soft_session_t *session_p;
39 boolean_t lock_held = B_TRUE;
40
41 if (!softtoken_initialized)
42 return (CKR_CRYPTOKI_NOT_INITIALIZED);
43
44 /*
45 * Obtain the session pointer. Also, increment the session
46 * reference count.
47 */
48 rv = handle2session(hSession, &session_p);
49 if (rv != CKR_OK)
50 return (rv);
51
52 if (pMechanism == NULL) {
53 rv = CKR_ARGUMENTS_BAD;
54 goto clean_exit;
55 }
56
57 /* Acquire the session lock */
58 (void) pthread_mutex_lock(&session_p->session_mutex);
59
60 /* Check to see if digest operation is already active */
61 if (session_p->digest.flags & CRYPTO_OPERATION_ACTIVE) {
62 /*
63 * Free the memory to avoid memory leak.
64 * digest.context is only a flat structure.
65 */
66 soft_digest_cleanup(session_p, lock_held);
67 }
68
69 /*
70 * This active flag will remain ON until application calls either
71 * C_Digest or C_DigestFinal to actually obtain the value of
72 * the message digest.
73 */
74 session_p->digest.flags = CRYPTO_OPERATION_ACTIVE;
75
76 (void) pthread_mutex_unlock(&session_p->session_mutex);
77
78 rv = soft_digest_init(session_p, pMechanism);
79
80 if (rv != CKR_OK) {
81 (void) pthread_mutex_lock(&session_p->session_mutex);
82 session_p->digest.flags &= ~CRYPTO_OPERATION_ACTIVE;
83 /*
84 * Decrement the session reference count.
85 * We hold the session lock, and SES_REFRELE()
86 * will release the session lock for us.
87 */
88 SES_REFRELE(session_p, lock_held);
89 return (rv);
90 }
91
92 clean_exit:
93 /*
94 * Decrement the session reference count.
95 * We do not hold the session lock.
96 */
97 lock_held = B_FALSE;
98 SES_REFRELE(session_p, lock_held);
99 return (rv);
100 }
101
102
103 CK_RV
C_Digest(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen)104 C_Digest(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
105 CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
106 {
107
108 CK_RV rv;
109 soft_session_t *session_p;
110 boolean_t lock_held = B_TRUE;
111
112 if (!softtoken_initialized)
113 return (CKR_CRYPTOKI_NOT_INITIALIZED);
114
115 /*
116 * Obtain the session pointer. Also, increment the session
117 * reference count.
118 */
119 rv = handle2session(hSession, &session_p);
120 if (rv != CKR_OK)
121 return (rv);
122
123 if (pData == NULL || pulDigestLen == NULL) {
124 rv = CKR_ARGUMENTS_BAD;
125 goto clean_exit;
126 }
127
128 /* Acquire the session lock */
129 (void) pthread_mutex_lock(&session_p->session_mutex);
130
131 /* Application must call C_DigestInit before calling C_Digest */
132 if (!(session_p->digest.flags & CRYPTO_OPERATION_ACTIVE)) {
133 /*
134 * Decrement the session reference count.
135 * We hold the session lock, and SES_REFRELE()
136 * will release the session lock for us.
137 */
138 SES_REFRELE(session_p, lock_held);
139 return (CKR_OPERATION_NOT_INITIALIZED);
140 }
141
142 /*
143 * C_Digest must be called without intervening C_DigestUpdate
144 * calls.
145 */
146 if (session_p->digest.flags & CRYPTO_OPERATION_UPDATE) {
147 /*
148 * C_Digest can not be used to terminate a multi-part
149 * operation, so we'll leave the active digest operation
150 * flag on and let the application continue with the
151 * digest update operation.
152 *
153 * Decrement the session reference count.
154 * We hold the session lock, and SES_REFRELE()
155 * will release the session lock for us.
156 */
157 SES_REFRELE(session_p, lock_held);
158 return (CKR_FUNCTION_FAILED);
159 }
160
161 (void) pthread_mutex_unlock(&session_p->session_mutex);
162
163 rv = soft_digest(session_p, pData, ulDataLen, pDigest, pulDigestLen);
164
165 if ((rv == CKR_BUFFER_TOO_SMALL) ||
166 (pDigest == NULL && rv == CKR_OK)) {
167 /*
168 * We will not terminate the active digest operation flag,
169 * when the application-supplied buffer is too small, or
170 * the application asks for the length of buffer to hold
171 * the message digest.
172 *
173 * Decrement the session reference count.
174 * We do not hold the session lock.
175 */
176 lock_held = B_FALSE;
177 SES_REFRELE(session_p, lock_held);
178 return (rv);
179 }
180
181 clean_exit:
182 /*
183 * Terminates the active digest operation.
184 * Application needs to call C_DigestInit again for next
185 * digest operation.
186 */
187 (void) pthread_mutex_lock(&session_p->session_mutex);
188
189 soft_digest_cleanup(session_p, lock_held);
190
191 /*
192 * Decrement the session reference count.
193 * We hold the session lock, and SES_REFRELE()
194 * will release the session lock for us.
195 */
196 SES_REFRELE(session_p, lock_held);
197
198 return (rv);
199 }
200
201
202 CK_RV
C_DigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen)203 C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
204 CK_ULONG ulPartLen)
205 {
206
207 CK_RV rv;
208 soft_session_t *session_p;
209 boolean_t lock_held = B_TRUE;
210
211 if (!softtoken_initialized)
212 return (CKR_CRYPTOKI_NOT_INITIALIZED);
213
214 /*
215 * Obtain the session pointer. Also, increment the session
216 * reference count.
217 */
218 rv = handle2session(hSession, &session_p);
219 if (rv != CKR_OK)
220 return (rv);
221
222 if (pPart == NULL) {
223 rv = CKR_ARGUMENTS_BAD;
224 goto clean_exit;
225 }
226
227 /* Acquire the session lock */
228 (void) pthread_mutex_lock(&session_p->session_mutex);
229
230 /*
231 * Application must call C_DigestInit before calling
232 * C_DigestUpdate.
233 */
234 if (!(session_p->digest.flags & CRYPTO_OPERATION_ACTIVE)) {
235 /*
236 * Decrement the session reference count.
237 * We hold the session lock, and SES_REFRELE()
238 * will release the session lock for us.
239 */
240 SES_REFRELE(session_p, lock_held);
241 return (CKR_OPERATION_NOT_INITIALIZED);
242 }
243
244 /* Set update flag to protect C_Digest */
245 session_p->digest.flags |= CRYPTO_OPERATION_UPDATE;
246
247 (void) pthread_mutex_unlock(&session_p->session_mutex);
248
249 rv = soft_digest_update(session_p, pPart, ulPartLen);
250
251 if (rv == CKR_OK) {
252 /*
253 * Decrement the session reference count.
254 * We do not hold the session lock.
255 */
256 lock_held = B_FALSE;
257 SES_REFRELE(session_p, lock_held);
258 return (CKR_OK);
259 }
260
261 clean_exit:
262 /*
263 * After an error occurred, terminate the current digest
264 * operation by resetting the active and update flags.
265 */
266 (void) pthread_mutex_lock(&session_p->session_mutex);
267
268 soft_digest_cleanup(session_p, lock_held);
269
270 /*
271 * Decrement the session reference count.
272 * We hold the session lock, and SES_REFRELE()
273 * will release the session lock for us.
274 */
275 SES_REFRELE(session_p, lock_held);
276
277 return (rv);
278 }
279
280
281 CK_RV
C_DigestKey(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hKey)282 C_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
283 {
284
285 CK_RV rv;
286 soft_session_t *session_p;
287 soft_object_t *key_p;
288 boolean_t lock_held = B_TRUE;
289
290 if (!softtoken_initialized)
291 return (CKR_CRYPTOKI_NOT_INITIALIZED);
292
293 /*
294 * Obtain the session pointer. Also, increment the session
295 * reference count.
296 */
297 rv = handle2session(hSession, &session_p);
298 if (rv != CKR_OK)
299 return (rv);
300
301 /* Obtain the object pointer. */
302 HANDLE2OBJECT(hKey, key_p, rv);
303 if (rv != CKR_OK)
304 goto clean_exit;
305
306 (void) pthread_mutex_lock(&session_p->session_mutex);
307
308 /*
309 * Application must call C_DigestInit before calling
310 * C_DigestKey.
311 */
312 if (!(session_p->digest.flags & CRYPTO_OPERATION_ACTIVE)) {
313 /*
314 * Decrement the session reference count.
315 * We hold the session lock, and SES_REFRELE()
316 * will release the session lock for us.
317 */
318 OBJ_REFRELE(key_p);
319 SES_REFRELE(session_p, lock_held);
320 return (CKR_OPERATION_NOT_INITIALIZED);
321 }
322
323 /*
324 * Remember the fact that a key was thrown into the mix, so that
325 * C_DigestFinal bzero()'s the digest context before freeing it.
326 */
327 session_p->digest.flags |= (CRYPTO_KEY_DIGESTED |
328 CRYPTO_OPERATION_UPDATE);
329
330 (void) pthread_mutex_unlock(&session_p->session_mutex);
331
332 rv = soft_digest_key(session_p, key_p);
333
334 if (rv == CKR_OK) {
335 /*
336 * Decrement the session reference count.
337 * We do not hold the session lock.
338 */
339 lock_held = B_FALSE;
340 OBJ_REFRELE(key_p);
341 SES_REFRELE(session_p, lock_held);
342 return (CKR_OK);
343 }
344
345 OBJ_REFRELE(key_p);
346 clean_exit:
347 /*
348 * After an error occurred, terminate the current digest
349 * operation by resetting the active and update flags.
350 */
351 (void) pthread_mutex_lock(&session_p->session_mutex);
352
353 soft_digest_cleanup(session_p, lock_held);
354
355 /*
356 * Decrement the session reference count.
357 * We hold the session lock, and SES_REFRELE()
358 * will release the session lock for us.
359 */
360 SES_REFRELE(session_p, lock_held);
361 return (rv);
362 }
363
364
365 CK_RV
C_DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen)366 C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest,
367 CK_ULONG_PTR pulDigestLen)
368 {
369
370 CK_RV rv;
371 soft_session_t *session_p;
372 boolean_t lock_held = B_TRUE;
373
374 if (!softtoken_initialized)
375 return (CKR_CRYPTOKI_NOT_INITIALIZED);
376
377 /*
378 * Obtain the session pointer. Also, increment the session
379 * reference count.
380 */
381 rv = handle2session(hSession, &session_p);
382 if (rv != CKR_OK)
383 return (rv);
384
385 if (pulDigestLen == NULL) {
386 rv = CKR_ARGUMENTS_BAD;
387 goto clean_exit;
388 }
389
390 /* Acquire the session lock */
391 (void) pthread_mutex_lock(&session_p->session_mutex);
392
393 /*
394 * Application must call C_DigestInit before calling
395 * C_DigestFinal.
396 */
397 if (!(session_p->digest.flags & CRYPTO_OPERATION_ACTIVE)) {
398 /*
399 * Decrement the session reference count.
400 * We hold the session lock, and SES_REFRELE()
401 * will release the session lock for us.
402 */
403 SES_REFRELE(session_p, lock_held);
404 return (CKR_OPERATION_NOT_INITIALIZED);
405 }
406
407 (void) pthread_mutex_unlock(&session_p->session_mutex);
408
409 rv = soft_digest_final(session_p, pDigest, pulDigestLen);
410
411 if ((rv == CKR_BUFFER_TOO_SMALL) ||
412 (pDigest == NULL && rv == CKR_OK)) {
413 /*
414 * We will not terminate the active digest operation flag,
415 * when the application-supplied buffer is too small, or
416 * the application asks for the length of buffer to hold
417 * the message digest.
418 *
419 * Decrement the session reference count.
420 * We do not hold the session lock.
421 */
422 lock_held = B_FALSE;
423 SES_REFRELE(session_p, lock_held);
424 return (rv);
425 }
426
427 clean_exit:
428 /* Terminates the active digest operation */
429 (void) pthread_mutex_lock(&session_p->session_mutex);
430
431 soft_digest_cleanup(session_p, lock_held);
432
433 /*
434 * Decrement the session reference count.
435 * We hold the session lock, and SES_REFRELE()
436 * will release the session lock for us.
437 */
438 SES_REFRELE(session_p, lock_held);
439
440 return (rv);
441 }
442