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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
32 #include <sys/types.h>
33 #include <security/cryptoki.h>
34 #include "softGlobal.h"
36 #include "softSession.h"
37 #include "softObject.h"
44 * session_p: pointer to soft_session_t struct
45 * pMechanism: pointer to CK_MECHANISM struct provided by application
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.
54 * CKR_HOST_MEMORY: run out of system memory
55 * CKR_MECHANISM_INVALID: invalid mechanism type
58 soft_digest_init(soft_session_t
*session_p
, CK_MECHANISM_PTR pMechanism
)
61 switch (pMechanism
->mechanism
) {
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
);
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
);
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
) {
116 session_p
->digest
.mech
.mechanism
= CKM_SHA256
;
117 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
119 (SHA2_CTX
*)session_p
->digest
.context
);
123 session_p
->digest
.mech
.mechanism
= CKM_SHA384
;
124 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
126 (SHA2_CTX
*)session_p
->digest
.context
);
130 session_p
->digest
.mech
.mechanism
= CKM_SHA512
;
131 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
133 (SHA2_CTX
*)session_p
->digest
.context
);
139 return (CKR_MECHANISM_INVALID
);
147 * soft_digest_common()
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
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.
163 * CKR_MECHANISM_INVALID: invalid mechanism type
164 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
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;
176 * Determine the output data length based on the mechanism
178 switch (session_p
->digest
.mech
.mechanism
) {
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
;
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
) {
233 * this is called by soft_digest()
236 MD5Update((MD5_CTX
*)session_p
->digest
.context
,
238 pData
, (uint_t
)ulDataLen
);
239 #else /* !__sparcv9 */
240 MD5Update((MD5_CTX
*)session_p
->digest
.context
,
242 #endif /* __sparcv9 */
243 MD5Final(pDigest
, (MD5_CTX
*)session_p
->digest
.context
);
246 * this is called by soft_digest_final()
248 MD5Final(pDigest
, (MD5_CTX
*)session_p
->digest
.context
);
249 len
= sizeof (MD5_CTX
);
256 * this is called by soft_digest()
260 SHA1Update((SHA1_CTX
*)session_p
->digest
.context
,
262 pData
, (uint32_t)ulDataLen
);
263 #else /* !__sparcv9 */
264 SHA1Update((SHA1_CTX
*)session_p
->digest
.context
,
266 #endif /* __sparcv9 */
268 (SHA1_CTX
*)session_p
->digest
.context
);
271 * this is called by soft_digest_final()
274 (SHA1_CTX
*)session_p
->digest
.context
);
275 len
= sizeof (SHA1_CTX
);
283 * this is called by soft_digest()
286 SHA2Update((SHA2_CTX
*)session_p
->digest
.context
,
290 (SHA2_CTX
*)session_p
->digest
.context
);
293 * this is called by soft_digest_final()
296 (SHA2_CTX
*)session_p
->digest
.context
);
297 len
= sizeof (SHA2_CTX
);
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
);
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
329 * called by C_Digest(). This function calls soft_digest_common().
332 * see return values in soft_digest_common().
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()
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
353 * called by C_DigestUpdate(). This function calls the corresponding
354 * software provided digest update routine based on the mechanism.
358 * CKR_MECHANISM_INVALID: invalid MECHANISM type.
361 soft_digest_update(soft_session_t
*session_p
, CK_BYTE_PTR pPart
,
365 switch (session_p
->digest
.mech
.mechanism
) {
369 MD5Update((MD5_CTX
*)session_p
->digest
.context
,
371 pPart
, (uint_t
)ulPartLen
);
372 #else /* !__sparcv9 */
373 MD5Update((MD5_CTX
*)session_p
->digest
.context
,
375 #endif /* __sparcv9 */
380 SHA1Update((SHA1_CTX
*)session_p
->digest
.context
,
382 pPart
, (uint32_t)ulPartLen
);
383 #else /* !__sparcv9 */
384 SHA1Update((SHA1_CTX
*)session_p
->digest
.context
,
386 #endif /* __sparcv9 */
392 SHA2Update((SHA2_CTX
*)session_p
->digest
.context
,
397 return (CKR_MECHANISM_INVALID
);
405 * soft_digest_final()
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
413 * called by C_DigestFinal(). This function calls soft_digest_common().
416 * see return values in soft_digest_common().
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
436 soft_digest_init_internal(soft_session_t
*session_p
, CK_MECHANISM_PTR
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
);
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
);
466 * Call soft_digest_update() function with the value of a secret key.
469 soft_digest_key(soft_session_t
*session_p
, soft_object_t
*key_p
)
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
));
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.
495 soft_digest_cleanup(soft_session_t
*session_p
, boolean_t lock_held
)
497 boolean_t lock_true
= B_TRUE
;
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;
510 SES_REFRELE(session_p
, lock_true
);