#include "tpmtok_int.h"
CK_RV
sign_mgr_init(SESSION * sess,
SIGN_VERIFY_CONTEXT * ctx,
CK_MECHANISM * mech,
CK_BBOOL recover_mode,
CK_OBJECT_HANDLE key)
{
OBJECT * key_obj = NULL;
CK_ATTRIBUTE * attr = NULL;
CK_BYTE * ptr = NULL;
CK_KEY_TYPE keytype;
CK_OBJECT_CLASS class;
CK_BBOOL flag;
CK_RV rc;
if (! sess || ! ctx) {
return (CKR_FUNCTION_FAILED);
}
if (ctx->active != FALSE) {
return (CKR_OPERATION_ACTIVE);
}
rc = object_mgr_find_in_map1(sess->hContext, key, &key_obj);
if (rc != CKR_OK) {
return (CKR_KEY_HANDLE_INVALID);
}
rc = template_attribute_find(key_obj->template, CKA_SIGN, &attr);
if (rc == FALSE) {
return (CKR_KEY_TYPE_INCONSISTENT);
} else {
flag = *(CK_BBOOL *)attr->pValue;
if (flag != TRUE) {
return (CKR_KEY_FUNCTION_NOT_PERMITTED);
}
}
switch (mech->mechanism) {
case CKM_RSA_PKCS:
{
rc = template_attribute_find(key_obj->template,
CKA_KEY_TYPE, &attr);
if (rc == FALSE) {
return (CKR_KEY_TYPE_INCONSISTENT);
} else {
keytype = *(CK_KEY_TYPE *)attr->pValue;
if (keytype != CKK_RSA) {
return (CKR_KEY_TYPE_INCONSISTENT);
}
}
flag = template_attribute_find(key_obj->template,
CKA_CLASS, &attr);
if (flag == FALSE) {
return (CKR_KEY_TYPE_INCONSISTENT);
}
else
class = *(CK_OBJECT_CLASS *)attr->pValue;
if (class != CKO_PRIVATE_KEY) {
return (CKR_KEY_TYPE_INCONSISTENT);
}
ctx->context_len = 0;
ctx->context = NULL;
}
break;
case CKM_MD5_RSA_PKCS:
case CKM_SHA1_RSA_PKCS:
{
rc = template_attribute_find(key_obj->template,
CKA_KEY_TYPE, &attr);
if (rc == FALSE) {
return (CKR_KEY_TYPE_INCONSISTENT);
} else {
keytype = *(CK_KEY_TYPE *)attr->pValue;
if (keytype != CKK_RSA) {
return (CKR_KEY_TYPE_INCONSISTENT);
}
}
flag = template_attribute_find(key_obj->template,
CKA_CLASS, &attr);
if (flag == FALSE) {
return (CKR_FUNCTION_FAILED);
}
else
class = *(CK_OBJECT_CLASS *)attr->pValue;
if (class != CKO_PRIVATE_KEY) {
return (CKR_FUNCTION_FAILED);
}
ctx->context_len = sizeof (RSA_DIGEST_CONTEXT);
ctx->context = (CK_BYTE *)malloc(
sizeof (RSA_DIGEST_CONTEXT));
if (! ctx->context) {
return (CKR_HOST_MEMORY);
}
(void) memset(ctx->context, 0x0,
sizeof (RSA_DIGEST_CONTEXT));
}
break;
case CKM_MD5_HMAC:
case CKM_SHA_1_HMAC:
{
if (mech->ulParameterLen != 0) {
return (CKR_MECHANISM_PARAM_INVALID);
}
rc = template_attribute_find(key_obj->template,
CKA_KEY_TYPE, &attr);
if (rc == FALSE) {
return (CKR_KEY_TYPE_INCONSISTENT);
} else {
keytype = *(CK_KEY_TYPE *)attr->pValue;
if (keytype != CKK_GENERIC_SECRET) {
return (CKR_KEY_TYPE_INCONSISTENT);
}
}
ctx->context_len = 0;
ctx->context = NULL;
}
break;
case CKM_MD5_HMAC_GENERAL:
case CKM_SHA_1_HMAC_GENERAL:
{
CK_MAC_GENERAL_PARAMS *param =
(CK_MAC_GENERAL_PARAMS *)mech->pParameter;
if (mech->ulParameterLen !=
sizeof (CK_MAC_GENERAL_PARAMS)) {
return (CKR_MECHANISM_PARAM_INVALID);
}
if ((mech->mechanism == CKM_MD5_HMAC_GENERAL) &&
(*param > 16)) {
return (CKR_MECHANISM_PARAM_INVALID);
}
if ((mech->mechanism == CKM_SHA_1_HMAC_GENERAL) &&
(*param > 20)) {
return (CKR_MECHANISM_PARAM_INVALID);
}
rc = template_attribute_find(key_obj->template,
CKA_KEY_TYPE, &attr);
if (rc == FALSE) {
return (CKR_KEY_TYPE_INCONSISTENT);
} else {
keytype = *(CK_KEY_TYPE *)attr->pValue;
if (keytype != CKK_GENERIC_SECRET) {
return (CKR_KEY_TYPE_INCONSISTENT);
}
}
ctx->context_len = 0;
ctx->context = NULL;
}
break;
default:
return (CKR_MECHANISM_INVALID);
}
if (mech->ulParameterLen > 0 && mech->pParameter == NULL)
return (CKR_ARGUMENTS_BAD);
if (mech->ulParameterLen > 0) {
ptr = (CK_BYTE *)malloc(mech->ulParameterLen);
if (! ptr) {
return (CKR_HOST_MEMORY);
}
(void) memcpy(ptr, mech->pParameter, mech->ulParameterLen);
}
ctx->key = key;
ctx->mech.ulParameterLen = mech->ulParameterLen;
ctx->mech.mechanism = mech->mechanism;
ctx->mech.pParameter = ptr;
ctx->multi = FALSE;
ctx->active = TRUE;
ctx->recover = recover_mode;
return (CKR_OK);
}
CK_RV
sign_mgr_cleanup(SIGN_VERIFY_CONTEXT *ctx)
{
if (! ctx) {
return (CKR_FUNCTION_FAILED);
}
ctx->key = 0;
ctx->mech.ulParameterLen = 0;
ctx->mech.mechanism = 0;
ctx->multi = FALSE;
ctx->active = FALSE;
ctx->recover = FALSE;
ctx->context_len = 0;
if (ctx->mech.pParameter) {
free(ctx->mech.pParameter);
ctx->mech.pParameter = NULL;
}
if (ctx->context) {
free(ctx->context);
ctx->context = NULL;
}
return (CKR_OK);
}
CK_RV
sign_mgr_sign(SESSION * sess,
CK_BBOOL length_only,
SIGN_VERIFY_CONTEXT * ctx,
CK_BYTE * in_data,
CK_ULONG in_data_len,
CK_BYTE * out_data,
CK_ULONG * out_data_len)
{
if (! sess || ! ctx) {
return (CKR_FUNCTION_FAILED);
}
if (ctx->active == FALSE) {
return (CKR_OPERATION_NOT_INITIALIZED);
}
if (ctx->recover == TRUE) {
return (CKR_OPERATION_NOT_INITIALIZED);
}
if ((length_only == FALSE) && (! in_data || ! out_data)) {
return (CKR_FUNCTION_FAILED);
}
if (ctx->multi == TRUE) {
return (CKR_OPERATION_ACTIVE);
}
switch (ctx->mech.mechanism) {
case CKM_RSA_PKCS:
return (rsa_pkcs_sign(sess, length_only, ctx,
in_data, in_data_len,
out_data, out_data_len));
case CKM_MD5_RSA_PKCS:
case CKM_SHA1_RSA_PKCS:
return (rsa_hash_pkcs_sign(sess, length_only, ctx,
in_data, in_data_len,
out_data, out_data_len));
case CKM_MD5_HMAC:
case CKM_MD5_HMAC_GENERAL:
return (md5_hmac_sign(sess, length_only, ctx,
in_data, in_data_len,
out_data, out_data_len));
case CKM_SHA_1_HMAC:
case CKM_SHA_1_HMAC_GENERAL:
return (sha1_hmac_sign(sess, length_only, ctx,
in_data, in_data_len,
out_data, out_data_len));
default:
return (CKR_MECHANISM_INVALID);
}
}
CK_RV
sign_mgr_sign_update(SESSION * sess,
SIGN_VERIFY_CONTEXT * ctx,
CK_BYTE * in_data,
CK_ULONG in_data_len)
{
if (! sess || ! ctx || ! in_data) {
return (CKR_FUNCTION_FAILED);
}
if (ctx->active == FALSE) {
return (CKR_OPERATION_NOT_INITIALIZED);
}
if (ctx->recover == TRUE) {
return (CKR_OPERATION_NOT_INITIALIZED);
}
ctx->multi = TRUE;
switch (ctx->mech.mechanism) {
case CKM_MD5_RSA_PKCS:
case CKM_SHA1_RSA_PKCS:
return (rsa_hash_pkcs_sign_update(sess, ctx,
in_data, in_data_len));
default:
return (CKR_MECHANISM_INVALID);
}
}
CK_RV
sign_mgr_sign_final(SESSION * sess,
CK_BBOOL length_only,
SIGN_VERIFY_CONTEXT * ctx,
CK_BYTE * signature,
CK_ULONG * sig_len)
{
if (! sess || ! ctx) {
return (CKR_FUNCTION_FAILED);
}
if (ctx->active == FALSE) {
return (CKR_OPERATION_NOT_INITIALIZED);
}
if (ctx->recover == TRUE) {
return (CKR_OPERATION_NOT_INITIALIZED);
}
switch (ctx->mech.mechanism) {
case CKM_MD5_RSA_PKCS:
case CKM_SHA1_RSA_PKCS:
return (rsa_hash_pkcs_sign_final(sess, length_only,
ctx, signature, sig_len));
default:
return (CKR_MECHANISM_INVALID);
}
}
CK_RV
sign_mgr_sign_recover(SESSION * sess,
CK_BBOOL length_only,
SIGN_VERIFY_CONTEXT * ctx,
CK_BYTE * in_data,
CK_ULONG in_data_len,
CK_BYTE * out_data,
CK_ULONG * out_data_len)
{
if (! sess || ! ctx) {
return (CKR_FUNCTION_FAILED);
}
if (ctx->active == FALSE) {
return (CKR_OPERATION_NOT_INITIALIZED);
}
if (ctx->recover == FALSE) {
return (CKR_OPERATION_NOT_INITIALIZED);
}
if ((length_only == FALSE) && (! in_data || ! out_data)) {
return (CKR_FUNCTION_FAILED);
}
if (ctx->multi == TRUE) {
return (CKR_OPERATION_ACTIVE);
}
switch (ctx->mech.mechanism) {
case CKM_RSA_PKCS:
return (rsa_pkcs_sign(sess, length_only, ctx,
in_data, in_data_len,
out_data, out_data_len));
default:
return (CKR_MECHANISM_INVALID);
}
}