#include <strings.h>
#include <md5.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/sha1.h>
#include <sys/sha2.h>
#include <sys/types.h>
#include <security/cryptoki.h>
#include "softGlobal.h"
#include "softOps.h"
#include "softSession.h"
#include "softObject.h"
CK_RV
soft_digest_init(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism)
{
switch (pMechanism->mechanism) {
case CKM_MD5:
(void) pthread_mutex_lock(&session_p->session_mutex);
session_p->digest.context = malloc(sizeof (MD5_CTX));
if (session_p->digest.context == NULL) {
(void) pthread_mutex_unlock(&session_p->session_mutex);
return (CKR_HOST_MEMORY);
}
session_p->digest.mech.mechanism = CKM_MD5;
(void) pthread_mutex_unlock(&session_p->session_mutex);
MD5Init((MD5_CTX *)session_p->digest.context);
break;
case CKM_SHA_1:
(void) pthread_mutex_lock(&session_p->session_mutex);
session_p->digest.context = malloc(sizeof (SHA1_CTX));
if (session_p->digest.context == NULL) {
(void) pthread_mutex_unlock(&session_p->session_mutex);
return (CKR_HOST_MEMORY);
}
session_p->digest.mech.mechanism = CKM_SHA_1;
session_p->digest.mech.pParameter = pMechanism->pParameter;
session_p->digest.mech.ulParameterLen =
pMechanism->ulParameterLen;
(void) pthread_mutex_unlock(&session_p->session_mutex);
SHA1Init((SHA1_CTX *)session_p->digest.context);
break;
case CKM_SHA256:
case CKM_SHA384:
case CKM_SHA512:
case CKM_SHA512_224:
case CKM_SHA512_256:
(void) pthread_mutex_lock(&session_p->session_mutex);
session_p->digest.context = malloc(sizeof (SHA2_CTX));
if (session_p->digest.context == NULL) {
(void) pthread_mutex_unlock(&session_p->session_mutex);
return (CKR_HOST_MEMORY);
}
session_p->digest.mech.mechanism = pMechanism->mechanism;
(void) pthread_mutex_unlock(&session_p->session_mutex);
switch (pMechanism->mechanism) {
case CKM_SHA256:
SHA2Init(SHA256,
(SHA2_CTX *)session_p->digest.context);
break;
case CKM_SHA384:
SHA2Init(SHA384,
(SHA2_CTX *)session_p->digest.context);
break;
case CKM_SHA512:
SHA2Init(SHA512,
(SHA2_CTX *)session_p->digest.context);
break;
case CKM_SHA512_224:
SHA2Init(SHA512_224,
(SHA2_CTX *)session_p->digest.context);
break;
case CKM_SHA512_256:
SHA2Init(SHA512_256,
(SHA2_CTX *)session_p->digest.context);
break;
}
break;
default:
return (CKR_MECHANISM_INVALID);
}
return (CKR_OK);
}
CK_RV
soft_digest_common(soft_session_t *session_p, CK_BYTE_PTR pData,
CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
{
CK_ULONG digestLen = 0;
size_t len = 0;
switch (session_p->digest.mech.mechanism) {
case CKM_MD5:
digestLen = 16;
break;
case CKM_SHA_1:
digestLen = SHA1_DIGEST_LENGTH;
break;
case CKM_SHA256:
digestLen = SHA256_DIGEST_LENGTH;
break;
case CKM_SHA384:
digestLen = SHA384_DIGEST_LENGTH;
break;
case CKM_SHA512:
digestLen = SHA512_DIGEST_LENGTH;
break;
case CKM_SHA512_224:
digestLen = SHA512_224_DIGEST_LENGTH;
break;
case CKM_SHA512_256:
digestLen = SHA512_256_DIGEST_LENGTH;
break;
default:
return (CKR_MECHANISM_INVALID);
}
if (pDigest == NULL) {
*pulDigestLen = digestLen;
return (CKR_OK);
}
if (*pulDigestLen < digestLen) {
*pulDigestLen = digestLen;
return (CKR_BUFFER_TOO_SMALL);
}
switch (session_p->digest.mech.mechanism) {
case CKM_MD5:
if (pData != NULL) {
#ifdef __sparcv9
MD5Update((MD5_CTX *)session_p->digest.context,
pData, (uint_t)ulDataLen);
#else
MD5Update((MD5_CTX *)session_p->digest.context,
pData, ulDataLen);
#endif
MD5Final(pDigest, (MD5_CTX *)session_p->digest.context);
} else {
MD5Final(pDigest, (MD5_CTX *)session_p->digest.context);
len = sizeof (MD5_CTX);
}
break;
case CKM_SHA_1:
if (pData != NULL) {
#ifdef __sparcv9
SHA1Update((SHA1_CTX *)session_p->digest.context,
pData, (uint32_t)ulDataLen);
#else
SHA1Update((SHA1_CTX *)session_p->digest.context,
pData, ulDataLen);
#endif
SHA1Final(pDigest,
(SHA1_CTX *)session_p->digest.context);
} else {
SHA1Final(pDigest,
(SHA1_CTX *)session_p->digest.context);
len = sizeof (SHA1_CTX);
}
break;
case CKM_SHA256:
case CKM_SHA384:
case CKM_SHA512:
case CKM_SHA512_224:
case CKM_SHA512_256:
if (pData != NULL) {
SHA2Update((SHA2_CTX *)session_p->digest.context,
pData, ulDataLen);
SHA2Final(pDigest,
(SHA2_CTX *)session_p->digest.context);
} else {
SHA2Final(pDigest,
(SHA2_CTX *)session_p->digest.context);
len = sizeof (SHA2_CTX);
}
break;
}
if (session_p->digest.flags & CRYPTO_KEY_DIGESTED) {
explicit_bzero(session_p->digest.context, len);
session_p->digest.flags &= ~CRYPTO_KEY_DIGESTED;
}
*pulDigestLen = digestLen;
(void) pthread_mutex_lock(&session_p->session_mutex);
free(session_p->digest.context);
session_p->digest.context = NULL;
(void) pthread_mutex_unlock(&session_p->session_mutex);
return (CKR_OK);
}
CK_RV
soft_digest(soft_session_t *session_p, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
{
return (soft_digest_common(session_p, pData, ulDataLen,
pDigest, pulDigestLen));
}
CK_RV
soft_digest_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
CK_ULONG ulPartLen)
{
switch (session_p->digest.mech.mechanism) {
case CKM_MD5:
#ifdef __sparcv9
MD5Update((MD5_CTX *)session_p->digest.context,
pPart, (uint_t)ulPartLen);
#else
MD5Update((MD5_CTX *)session_p->digest.context,
pPart, ulPartLen);
#endif
break;
case CKM_SHA_1:
#ifdef __sparcv9
SHA1Update((SHA1_CTX *)session_p->digest.context,
pPart, (uint32_t)ulPartLen);
#else
SHA1Update((SHA1_CTX *)session_p->digest.context,
pPart, ulPartLen);
#endif
break;
case CKM_SHA256:
case CKM_SHA384:
case CKM_SHA512:
case CKM_SHA512_224:
case CKM_SHA512_256:
SHA2Update((SHA2_CTX *)session_p->digest.context,
pPart, ulPartLen);
break;
default:
return (CKR_MECHANISM_INVALID);
}
return (CKR_OK);
}
CK_RV
soft_digest_final(soft_session_t *session_p, CK_BYTE_PTR pDigest,
CK_ULONG_PTR pulDigestLen)
{
return (soft_digest_common(session_p, NULL, 0,
pDigest, pulDigestLen));
}
CK_RV
soft_digest_init_internal(soft_session_t *session_p,
CK_MECHANISM_PTR pMechanism)
{
CK_RV rv;
(void) pthread_mutex_lock(&session_p->session_mutex);
if (session_p->digest.flags & CRYPTO_OPERATION_ACTIVE) {
(void) pthread_mutex_unlock(&session_p->session_mutex);
return (CKR_OPERATION_ACTIVE);
}
session_p->digest.flags = CRYPTO_OPERATION_ACTIVE;
(void) pthread_mutex_unlock(&session_p->session_mutex);
rv = soft_digest_init(session_p, pMechanism);
if (rv != CKR_OK) {
(void) pthread_mutex_lock(&session_p->session_mutex);
session_p->digest.flags &= ~CRYPTO_OPERATION_ACTIVE;
(void) pthread_mutex_unlock(&session_p->session_mutex);
}
return (rv);
}
CK_RV
soft_digest_key(soft_session_t *session_p, soft_object_t *key_p)
{
CK_RV rv;
if (key_p->class != CKO_SECRET_KEY)
return (CKR_KEY_INDIGESTIBLE);
if ((OBJ_SEC_VALUE(key_p) == NULL) ||
(OBJ_SEC_VALUE_LEN(key_p) == 0))
return (CKR_KEY_SIZE_RANGE);
rv = soft_digest_update(session_p, OBJ_SEC_VALUE(key_p),
OBJ_SEC_VALUE_LEN(key_p));
return (rv);
}
void
soft_digest_cleanup(soft_session_t *session_p, boolean_t lock_held)
{
boolean_t lock_true = B_TRUE;
if (!lock_held)
(void) pthread_mutex_lock(&session_p->session_mutex);
if (session_p->digest.context != NULL) {
free(session_p->digest.context);
session_p->digest.context = NULL;
}
session_p->digest.flags = 0;
if (!lock_held)
SES_REFRELE(session_p, lock_true);
}