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()
235 MD5Update((MD5_CTX
*)session_p
->digest
.context
,
237 MD5Final(pDigest
, (MD5_CTX
*)session_p
->digest
.context
);
240 * this is called by soft_digest_final()
242 MD5Final(pDigest
, (MD5_CTX
*)session_p
->digest
.context
);
243 len
= sizeof (MD5_CTX
);
250 * this is called by soft_digest()
253 SHA1Update((SHA1_CTX
*)session_p
->digest
.context
,
256 (SHA1_CTX
*)session_p
->digest
.context
);
259 * this is called by soft_digest_final()
262 (SHA1_CTX
*)session_p
->digest
.context
);
263 len
= sizeof (SHA1_CTX
);
271 * this is called by soft_digest()
274 SHA2Update((SHA2_CTX
*)session_p
->digest
.context
,
278 (SHA2_CTX
*)session_p
->digest
.context
);
281 * this is called by soft_digest_final()
284 (SHA2_CTX
*)session_p
->digest
.context
);
285 len
= sizeof (SHA2_CTX
);
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
);
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
317 * called by C_Digest(). This function calls soft_digest_common().
320 * see return values in soft_digest_common().
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()
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
341 * called by C_DigestUpdate(). This function calls the corresponding
342 * software provided digest update routine based on the mechanism.
346 * CKR_MECHANISM_INVALID: invalid MECHANISM type.
349 soft_digest_update(soft_session_t
*session_p
, CK_BYTE_PTR pPart
,
353 switch (session_p
->digest
.mech
.mechanism
) {
356 MD5Update((MD5_CTX
*)session_p
->digest
.context
,
361 SHA1Update((SHA1_CTX
*)session_p
->digest
.context
,
368 SHA2Update((SHA2_CTX
*)session_p
->digest
.context
,
373 return (CKR_MECHANISM_INVALID
);
381 * soft_digest_final()
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
389 * called by C_DigestFinal(). This function calls soft_digest_common().
392 * see return values in soft_digest_common().
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
412 soft_digest_init_internal(soft_session_t
*session_p
, CK_MECHANISM_PTR
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
);
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
);
442 * Call soft_digest_update() function with the value of a secret key.
445 soft_digest_key(soft_session_t
*session_p
, soft_object_t
*key_p
)
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
));
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.
471 soft_digest_cleanup(soft_session_t
*session_p
, boolean_t lock_held
)
473 boolean_t lock_true
= B_TRUE
;
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;
486 SES_REFRELE(session_p
, lock_true
);