dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / pkcs11 / pkcs11_softtoken / common / softDigestUtil.c
blob9a2b9925e63cdf01d0702830b0278ece285d4ae1
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 MD5Update((MD5_CTX *)session_p->digest.context,
236 pData, ulDataLen);
237 MD5Final(pDigest, (MD5_CTX *)session_p->digest.context);
238 } else {
240 * this is called by soft_digest_final()
242 MD5Final(pDigest, (MD5_CTX *)session_p->digest.context);
243 len = sizeof (MD5_CTX);
245 break;
247 case CKM_SHA_1:
248 if (pData != NULL) {
250 * this is called by soft_digest()
253 SHA1Update((SHA1_CTX *)session_p->digest.context,
254 pData, ulDataLen);
255 SHA1Final(pDigest,
256 (SHA1_CTX *)session_p->digest.context);
257 } else {
259 * this is called by soft_digest_final()
261 SHA1Final(pDigest,
262 (SHA1_CTX *)session_p->digest.context);
263 len = sizeof (SHA1_CTX);
265 break;
266 case CKM_SHA256:
267 case CKM_SHA384:
268 case CKM_SHA512:
269 if (pData != NULL) {
271 * this is called by soft_digest()
274 SHA2Update((SHA2_CTX *)session_p->digest.context,
275 pData, ulDataLen);
277 SHA2Final(pDigest,
278 (SHA2_CTX *)session_p->digest.context);
279 } else {
281 * this is called by soft_digest_final()
283 SHA2Final(pDigest,
284 (SHA2_CTX *)session_p->digest.context);
285 len = sizeof (SHA2_CTX);
288 break;
291 /* Paranoia on behalf of C_DigestKey callers: bzero the context */
292 if (session_p->digest.flags & CRYPTO_KEY_DIGESTED) {
293 bzero(session_p->digest.context, len);
294 session_p->digest.flags &= ~CRYPTO_KEY_DIGESTED;
296 *pulDigestLen = digestLen;
297 (void) pthread_mutex_lock(&session_p->session_mutex);
298 free(session_p->digest.context);
299 session_p->digest.context = NULL;
300 (void) pthread_mutex_unlock(&session_p->session_mutex);
302 return (CKR_OK);
307 * soft_digest()
309 * Arguments:
310 * session_p: pointer to soft_session_t struct
311 * pData: pointer to the input data to be digested
312 * ulDataLen: length of the input data
313 * pDigest: pointer to the output data after digesting
314 * pulDigestLen: length of the output data
316 * Description:
317 * called by C_Digest(). This function calls soft_digest_common().
319 * Returns:
320 * see return values in soft_digest_common().
322 CK_RV
323 soft_digest(soft_session_t *session_p, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
324 CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
327 return (soft_digest_common(session_p, pData, ulDataLen,
328 pDigest, pulDigestLen));
333 * soft_digest_update()
335 * Arguments:
336 * session_p: pointer to soft_session_t struct
337 * pPart: pointer to the input data to be digested
338 * ulPartLen: length of the input data
340 * Description:
341 * called by C_DigestUpdate(). This function calls the corresponding
342 * software provided digest update routine based on the mechanism.
344 * Returns:
345 * CKR_OK: success
346 * CKR_MECHANISM_INVALID: invalid MECHANISM type.
348 CK_RV
349 soft_digest_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
350 CK_ULONG ulPartLen)
353 switch (session_p->digest.mech.mechanism) {
355 case CKM_MD5:
356 MD5Update((MD5_CTX *)session_p->digest.context,
357 pPart, ulPartLen);
358 break;
360 case CKM_SHA_1:
361 SHA1Update((SHA1_CTX *)session_p->digest.context,
362 pPart, ulPartLen);
363 break;
365 case CKM_SHA256:
366 case CKM_SHA384:
367 case CKM_SHA512:
368 SHA2Update((SHA2_CTX *)session_p->digest.context,
369 pPart, ulPartLen);
370 break;
372 default:
373 return (CKR_MECHANISM_INVALID);
376 return (CKR_OK);
381 * soft_digest_final()
383 * Arguments:
384 * session_p: pointer to soft_session_t struct
385 * pDigest: pointer to the output data after digesting
386 * pulDigestLen: length of the output data
388 * Description:
389 * called by C_DigestFinal(). This function calls soft_digest_common().
391 * Returns:
392 * see return values in soft_digest_common().
394 CK_RV
395 soft_digest_final(soft_session_t *session_p, CK_BYTE_PTR pDigest,
396 CK_ULONG_PTR pulDigestLen)
399 return (soft_digest_common(session_p, NULL, 0,
400 pDigest, pulDigestLen));
404 * Perform digest init operation internally for the support of
405 * CKM_MD5_RSA_PKCS, CKM_SHA1_RSA_PKCS, CKM_SHA1_KEY_DERIVATION
406 * and CKM_MD5_KEY_DERIVATION mechanisms.
408 * This function is called with the session being held, and without
409 * its mutex taken.
411 CK_RV
412 soft_digest_init_internal(soft_session_t *session_p, CK_MECHANISM_PTR
413 pMechanism)
416 CK_RV rv;
418 (void) pthread_mutex_lock(&session_p->session_mutex);
420 /* Check to see if digest operation is already active */
421 if (session_p->digest.flags & CRYPTO_OPERATION_ACTIVE) {
422 (void) pthread_mutex_unlock(&session_p->session_mutex);
423 return (CKR_OPERATION_ACTIVE);
426 session_p->digest.flags = CRYPTO_OPERATION_ACTIVE;
428 (void) pthread_mutex_unlock(&session_p->session_mutex);
430 rv = soft_digest_init(session_p, pMechanism);
432 if (rv != CKR_OK) {
433 (void) pthread_mutex_lock(&session_p->session_mutex);
434 session_p->digest.flags &= ~CRYPTO_OPERATION_ACTIVE;
435 (void) pthread_mutex_unlock(&session_p->session_mutex);
438 return (rv);
442 * Call soft_digest_update() function with the value of a secret key.
444 CK_RV
445 soft_digest_key(soft_session_t *session_p, soft_object_t *key_p)
448 CK_RV rv;
450 /* Only secret key is allowed to be digested */
451 if (key_p->class != CKO_SECRET_KEY)
452 return (CKR_KEY_INDIGESTIBLE);
454 if ((OBJ_SEC_VALUE(key_p) == NULL) ||
455 (OBJ_SEC_VALUE_LEN(key_p) == 0))
456 return (CKR_KEY_SIZE_RANGE);
458 rv = soft_digest_update(session_p, OBJ_SEC_VALUE(key_p),
459 OBJ_SEC_VALUE_LEN(key_p));
461 return (rv);
466 * This function releases allocated digest context. The caller
467 * may (lock_held == B_TRUE) or may not (lock_held == B_FALSE)
468 * hold a session mutex.
470 void
471 soft_digest_cleanup(soft_session_t *session_p, boolean_t lock_held)
473 boolean_t lock_true = B_TRUE;
475 if (!lock_held)
476 (void) pthread_mutex_lock(&session_p->session_mutex);
478 if (session_p->digest.context != NULL) {
479 free(session_p->digest.context);
480 session_p->digest.context = NULL;
483 session_p->digest.flags = 0;
485 if (!lock_held)
486 SES_REFRELE(session_p, lock_true);