8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / pkcs11 / pkcs11_softtoken / common / softDigestUtil.c
blobf1f685ed404f4f3798f85d5f69f5496dfb6a0018
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <strings.h>
27 #include <md5.h>
28 #include <pthread.h>
29 #include <stdlib.h>
30 #include <sys/sha1.h>
31 #include <sys/sha2.h>
32 #include <sys/types.h>
33 #include <security/cryptoki.h>
34 #include "softGlobal.h"
35 #include "softOps.h"
36 #include "softSession.h"
37 #include "softObject.h"
41 * soft_digest_init()
43 * Arguments:
44 * session_p: pointer to soft_session_t struct
45 * pMechanism: pointer to CK_MECHANISM struct provided by application
47 * Description:
48 * called by C_DigestInit(). This function allocates space for
49 * context, then calls the corresponding software provided digest
50 * init routine based on the mechanism.
52 * Returns:
53 * CKR_OK: success
54 * CKR_HOST_MEMORY: run out of system memory
55 * CKR_MECHANISM_INVALID: invalid mechanism type
57 CK_RV
58 soft_digest_init(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism)
61 switch (pMechanism->mechanism) {
63 case CKM_MD5:
64 (void) pthread_mutex_lock(&session_p->session_mutex);
66 session_p->digest.context = malloc(sizeof (MD5_CTX));
68 if (session_p->digest.context == NULL) {
69 (void) pthread_mutex_unlock(&session_p->session_mutex);
70 return (CKR_HOST_MEMORY);
73 session_p->digest.mech.mechanism = CKM_MD5;
74 (void) pthread_mutex_unlock(&session_p->session_mutex);
76 MD5Init((MD5_CTX *)session_p->digest.context);
78 break;
80 case CKM_SHA_1:
82 (void) pthread_mutex_lock(&session_p->session_mutex);
84 session_p->digest.context = malloc(sizeof (SHA1_CTX));
86 if (session_p->digest.context == NULL) {
87 (void) pthread_mutex_unlock(&session_p->session_mutex);
88 return (CKR_HOST_MEMORY);
91 session_p->digest.mech.mechanism = CKM_SHA_1;
92 session_p->digest.mech.pParameter = pMechanism->pParameter;
93 session_p->digest.mech.ulParameterLen =
94 pMechanism->ulParameterLen;
95 (void) pthread_mutex_unlock(&session_p->session_mutex);
97 SHA1Init((SHA1_CTX *)session_p->digest.context);
99 break;
101 case CKM_SHA256:
102 case CKM_SHA384:
103 case CKM_SHA512:
105 (void) pthread_mutex_lock(&session_p->session_mutex);
107 session_p->digest.context = malloc(sizeof (SHA2_CTX));
109 if (session_p->digest.context == NULL) {
110 (void) pthread_mutex_unlock(&session_p->session_mutex);
111 return (CKR_HOST_MEMORY);
114 switch (pMechanism->mechanism) {
115 case CKM_SHA256:
116 session_p->digest.mech.mechanism = CKM_SHA256;
117 (void) pthread_mutex_unlock(&session_p->session_mutex);
118 SHA2Init(SHA256,
119 (SHA2_CTX *)session_p->digest.context);
120 break;
122 case CKM_SHA384:
123 session_p->digest.mech.mechanism = CKM_SHA384;
124 (void) pthread_mutex_unlock(&session_p->session_mutex);
125 SHA2Init(SHA384,
126 (SHA2_CTX *)session_p->digest.context);
127 break;
129 case CKM_SHA512:
130 session_p->digest.mech.mechanism = CKM_SHA512;
131 (void) pthread_mutex_unlock(&session_p->session_mutex);
132 SHA2Init(SHA512,
133 (SHA2_CTX *)session_p->digest.context);
134 break;
136 break;
138 default:
139 return (CKR_MECHANISM_INVALID);
142 return (CKR_OK);
147 * soft_digest_common()
149 * Arguments:
150 * session_p: pointer to soft_session_t struct
151 * pData: pointer to the input data to be digested
152 * ulDataLen: length of the input data
153 * pDigest: pointer to the output data after digesting
154 * pulDigestLen: length of the output data
156 * Description:
157 * called by soft_digest() or soft_digest_final(). This function
158 * determines the length of output buffer and calls the corresponding
159 * software provided digest routine based on the mechanism.
161 * Returns:
162 * CKR_OK: success
163 * CKR_MECHANISM_INVALID: invalid mechanism type
164 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
165 * is too small
167 CK_RV
168 soft_digest_common(soft_session_t *session_p, CK_BYTE_PTR pData,
169 CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
172 CK_ULONG digestLen = 0;
173 size_t len = 0;
176 * Determine the output data length based on the mechanism
178 switch (session_p->digest.mech.mechanism) {
180 case CKM_MD5:
181 digestLen = 16;
182 break;
184 case CKM_SHA_1:
185 digestLen = 20;
186 break;
188 case CKM_SHA256:
189 digestLen = 32;
190 break;
192 case CKM_SHA384:
193 digestLen = 48;
194 break;
196 case CKM_SHA512:
197 digestLen = 64;
198 break;
200 default:
201 return (CKR_MECHANISM_INVALID);
204 if (pDigest == NULL) {
206 * Application only wants to know the length of the
207 * buffer needed to hold the message digest.
209 *pulDigestLen = digestLen;
210 return (CKR_OK);
213 if (*pulDigestLen < digestLen) {
215 * Application provides buffer too small to hold the
216 * digest message. Return the length of buffer needed
217 * to the application.
219 *pulDigestLen = digestLen;
220 return (CKR_BUFFER_TOO_SMALL);
224 * Call the corresponding system provided software digest routine.
225 * If the soft_digest_common() is called by soft_digest_final()
226 * the pData is NULL, and the ulDataLen is zero.
228 switch (session_p->digest.mech.mechanism) {
230 case CKM_MD5:
231 if (pData != NULL) {
233 * this is called by soft_digest()
235 #ifdef __sparcv9
236 MD5Update((MD5_CTX *)session_p->digest.context,
237 /* LINTED */
238 pData, (uint_t)ulDataLen);
239 #else /* !__sparcv9 */
240 MD5Update((MD5_CTX *)session_p->digest.context,
241 pData, ulDataLen);
242 #endif /* __sparcv9 */
243 MD5Final(pDigest, (MD5_CTX *)session_p->digest.context);
244 } else {
246 * this is called by soft_digest_final()
248 MD5Final(pDigest, (MD5_CTX *)session_p->digest.context);
249 len = sizeof (MD5_CTX);
251 break;
253 case CKM_SHA_1:
254 if (pData != NULL) {
256 * this is called by soft_digest()
259 #ifdef __sparcv9
260 SHA1Update((SHA1_CTX *)session_p->digest.context,
261 /* LINTED */
262 pData, (uint32_t)ulDataLen);
263 #else /* !__sparcv9 */
264 SHA1Update((SHA1_CTX *)session_p->digest.context,
265 pData, ulDataLen);
266 #endif /* __sparcv9 */
267 SHA1Final(pDigest,
268 (SHA1_CTX *)session_p->digest.context);
269 } else {
271 * this is called by soft_digest_final()
273 SHA1Final(pDigest,
274 (SHA1_CTX *)session_p->digest.context);
275 len = sizeof (SHA1_CTX);
277 break;
278 case CKM_SHA256:
279 case CKM_SHA384:
280 case CKM_SHA512:
281 if (pData != NULL) {
283 * this is called by soft_digest()
286 SHA2Update((SHA2_CTX *)session_p->digest.context,
287 pData, ulDataLen);
289 SHA2Final(pDigest,
290 (SHA2_CTX *)session_p->digest.context);
291 } else {
293 * this is called by soft_digest_final()
295 SHA2Final(pDigest,
296 (SHA2_CTX *)session_p->digest.context);
297 len = sizeof (SHA2_CTX);
300 break;
303 /* Paranoia on behalf of C_DigestKey callers: bzero the context */
304 if (session_p->digest.flags & CRYPTO_KEY_DIGESTED) {
305 bzero(session_p->digest.context, len);
306 session_p->digest.flags &= ~CRYPTO_KEY_DIGESTED;
308 *pulDigestLen = digestLen;
309 (void) pthread_mutex_lock(&session_p->session_mutex);
310 free(session_p->digest.context);
311 session_p->digest.context = NULL;
312 (void) pthread_mutex_unlock(&session_p->session_mutex);
314 return (CKR_OK);
319 * soft_digest()
321 * Arguments:
322 * session_p: pointer to soft_session_t struct
323 * pData: pointer to the input data to be digested
324 * ulDataLen: length of the input data
325 * pDigest: pointer to the output data after digesting
326 * pulDigestLen: length of the output data
328 * Description:
329 * called by C_Digest(). This function calls soft_digest_common().
331 * Returns:
332 * see return values in soft_digest_common().
334 CK_RV
335 soft_digest(soft_session_t *session_p, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
336 CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
339 return (soft_digest_common(session_p, pData, ulDataLen,
340 pDigest, pulDigestLen));
345 * soft_digest_update()
347 * Arguments:
348 * session_p: pointer to soft_session_t struct
349 * pPart: pointer to the input data to be digested
350 * ulPartLen: length of the input data
352 * Description:
353 * called by C_DigestUpdate(). This function calls the corresponding
354 * software provided digest update routine based on the mechanism.
356 * Returns:
357 * CKR_OK: success
358 * CKR_MECHANISM_INVALID: invalid MECHANISM type.
360 CK_RV
361 soft_digest_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
362 CK_ULONG ulPartLen)
365 switch (session_p->digest.mech.mechanism) {
367 case CKM_MD5:
368 #ifdef __sparcv9
369 MD5Update((MD5_CTX *)session_p->digest.context,
370 /* LINTED */
371 pPart, (uint_t)ulPartLen);
372 #else /* !__sparcv9 */
373 MD5Update((MD5_CTX *)session_p->digest.context,
374 pPart, ulPartLen);
375 #endif /* __sparcv9 */
376 break;
378 case CKM_SHA_1:
379 #ifdef __sparcv9
380 SHA1Update((SHA1_CTX *)session_p->digest.context,
381 /* LINTED */
382 pPart, (uint32_t)ulPartLen);
383 #else /* !__sparcv9 */
384 SHA1Update((SHA1_CTX *)session_p->digest.context,
385 pPart, ulPartLen);
386 #endif /* __sparcv9 */
387 break;
389 case CKM_SHA256:
390 case CKM_SHA384:
391 case CKM_SHA512:
392 SHA2Update((SHA2_CTX *)session_p->digest.context,
393 pPart, ulPartLen);
394 break;
396 default:
397 return (CKR_MECHANISM_INVALID);
400 return (CKR_OK);
405 * soft_digest_final()
407 * Arguments:
408 * session_p: pointer to soft_session_t struct
409 * pDigest: pointer to the output data after digesting
410 * pulDigestLen: length of the output data
412 * Description:
413 * called by C_DigestFinal(). This function calls soft_digest_common().
415 * Returns:
416 * see return values in soft_digest_common().
418 CK_RV
419 soft_digest_final(soft_session_t *session_p, CK_BYTE_PTR pDigest,
420 CK_ULONG_PTR pulDigestLen)
423 return (soft_digest_common(session_p, NULL, 0,
424 pDigest, pulDigestLen));
428 * Perform digest init operation internally for the support of
429 * CKM_MD5_RSA_PKCS, CKM_SHA1_RSA_PKCS, CKM_SHA1_KEY_DERIVATION
430 * and CKM_MD5_KEY_DERIVATION mechanisms.
432 * This function is called with the session being held, and without
433 * its mutex taken.
435 CK_RV
436 soft_digest_init_internal(soft_session_t *session_p, CK_MECHANISM_PTR
437 pMechanism)
440 CK_RV rv;
442 (void) pthread_mutex_lock(&session_p->session_mutex);
444 /* Check to see if digest operation is already active */
445 if (session_p->digest.flags & CRYPTO_OPERATION_ACTIVE) {
446 (void) pthread_mutex_unlock(&session_p->session_mutex);
447 return (CKR_OPERATION_ACTIVE);
450 session_p->digest.flags = CRYPTO_OPERATION_ACTIVE;
452 (void) pthread_mutex_unlock(&session_p->session_mutex);
454 rv = soft_digest_init(session_p, pMechanism);
456 if (rv != CKR_OK) {
457 (void) pthread_mutex_lock(&session_p->session_mutex);
458 session_p->digest.flags &= ~CRYPTO_OPERATION_ACTIVE;
459 (void) pthread_mutex_unlock(&session_p->session_mutex);
462 return (rv);
466 * Call soft_digest_update() function with the value of a secret key.
468 CK_RV
469 soft_digest_key(soft_session_t *session_p, soft_object_t *key_p)
472 CK_RV rv;
474 /* Only secret key is allowed to be digested */
475 if (key_p->class != CKO_SECRET_KEY)
476 return (CKR_KEY_INDIGESTIBLE);
478 if ((OBJ_SEC_VALUE(key_p) == NULL) ||
479 (OBJ_SEC_VALUE_LEN(key_p) == 0))
480 return (CKR_KEY_SIZE_RANGE);
482 rv = soft_digest_update(session_p, OBJ_SEC_VALUE(key_p),
483 OBJ_SEC_VALUE_LEN(key_p));
485 return (rv);
490 * This function releases allocated digest context. The caller
491 * may (lock_held == B_TRUE) or may not (lock_held == B_FALSE)
492 * hold a session mutex.
494 void
495 soft_digest_cleanup(soft_session_t *session_p, boolean_t lock_held)
497 boolean_t lock_true = B_TRUE;
499 if (!lock_held)
500 (void) pthread_mutex_lock(&session_p->session_mutex);
502 if (session_p->digest.context != NULL) {
503 free(session_p->digest.context);
504 session_p->digest.context = NULL;
507 session_p->digest.flags = 0;
509 if (!lock_held)
510 SES_REFRELE(session_p, lock_true);