* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "crypto_mac.h"
#include <string.h>
#include <securec.h>
#include "memory.h"
#include "crypto_common.h"
#include "crypto_sym_key.h"
#include "native_common.h"
#include "mac.h"
#include "mac_params.h"
#include "detailed_cmac_params.h"
#include "detailed_hmac_params.h"
typedef struct OH_CryptoMac {
HcfMacParamsSpec *paramsSpec;
HcfMac *macObj;
} OH_CryptoMac;
static const char *CMAC_NAME = "CMAC";
static const char *HMAC_NAME = "HMAC";
static OH_Crypto_ErrCode CryptoMacCreate(const char *algoName, OH_CryptoMac **ctx)
{
if ((algoName == NULL) || (ctx == NULL)) {
return CRYPTO_PARAMETER_CHECK_FAILED;
}
OH_CryptoMac *tmpCtx = (OH_CryptoMac *)HcfMalloc(sizeof(OH_CryptoMac), 0);
if (tmpCtx == NULL) {
return CRYPTO_MEMORY_ERROR;
}
HcfMacParamsSpec *paramsSpec = NULL;
const char *algName = NULL;
if (strcmp(algoName, CMAC_NAME) == 0) {
paramsSpec = (HcfMacParamsSpec *)HcfMalloc(sizeof(HcfCmacParamsSpec), 0);
algName = CMAC_NAME;
} else if (strcmp(algoName, HMAC_NAME) == 0) {
paramsSpec = (HcfMacParamsSpec *)HcfMalloc(sizeof(HcfHmacParamsSpec), 0);
algName = HMAC_NAME;
} else {
HcfFree(tmpCtx);
tmpCtx = NULL;
return CRYPTO_PARAMETER_CHECK_FAILED;
}
if (paramsSpec == NULL) {
HcfFree(tmpCtx);
tmpCtx = NULL;
return CRYPTO_MEMORY_ERROR;
}
paramsSpec->algName = algName;
tmpCtx->paramsSpec = paramsSpec;
*ctx = tmpCtx;
return CRYPTO_SUCCESS;
}
OH_Crypto_ErrCode OH_CryptoMac_Create(const char *algoName, OH_CryptoMac **ctx)
{
return CryptoMacCreate(algoName, ctx);
}
static OH_Crypto_ErrCode SetCmacParam(HcfCmacParamsSpec *paramsSpec, CryptoMac_ParamType type,
const Crypto_DataBlob *value)
{
switch (type) {
case CRYPTO_MAC_CIPHER_NAME_STR: {
char *data = (char *)HcfMalloc(value->len + 1, 0);
if (data == NULL) {
return CRYPTO_MEMORY_ERROR;
}
(void)memcpy_s(data, value->len, value->data, value->len);
HcfFree((void *)(paramsSpec->cipherName));
paramsSpec->cipherName = data;
return CRYPTO_SUCCESS;
}
default:
return CRYPTO_PARAMETER_CHECK_FAILED;
}
}
static OH_Crypto_ErrCode SetHmacParam(HcfHmacParamsSpec *paramsSpec, CryptoMac_ParamType type,
const Crypto_DataBlob *value)
{
switch (type) {
case CRYPTO_MAC_DIGEST_NAME_STR: {
char *data = (char *)HcfMalloc(value->len + 1, 0);
if (data == NULL) {
return CRYPTO_MEMORY_ERROR;
}
(void)memcpy_s(data, value->len, value->data, value->len);
HcfFree((void *)(paramsSpec->mdName));
paramsSpec->mdName = data;
return CRYPTO_SUCCESS;
}
default:
return CRYPTO_PARAMETER_CHECK_FAILED;
}
}
static OH_Crypto_ErrCode CryptoMacSetParam(OH_CryptoMac *ctx, CryptoMac_ParamType type, const Crypto_DataBlob *value)
{
if ((ctx == NULL) || (ctx->paramsSpec == NULL) || (ctx->paramsSpec->algName == NULL) || (value == NULL) ||
(value->data == NULL)) {
return CRYPTO_PARAMETER_CHECK_FAILED;
}
OH_Crypto_ErrCode res = CRYPTO_PARAMETER_CHECK_FAILED;
if (strcmp(ctx->paramsSpec->algName, "CMAC") == 0) {
res = SetCmacParam((HcfCmacParamsSpec*)(ctx->paramsSpec), type, value);
} else if (strcmp(ctx->paramsSpec->algName, "HMAC") == 0) {
res = SetHmacParam((HcfHmacParamsSpec*)(ctx->paramsSpec), type, value);
}
if (res != CRYPTO_SUCCESS) {
return res;
}
HcfMac *macObj = NULL;
HcfResult ret = HcfMacCreate(ctx->paramsSpec, &macObj);
if (ret != HCF_SUCCESS) {
return GetOhCryptoErrCodeNew(ret);
}
HcfObjDestroy(ctx->macObj);
ctx->macObj = macObj;
return CRYPTO_SUCCESS;
}
OH_Crypto_ErrCode OH_CryptoMac_SetParam(OH_CryptoMac *ctx, CryptoMac_ParamType type, const Crypto_DataBlob *value)
{
return CryptoMacSetParam(ctx, type, value);
}
static OH_Crypto_ErrCode CryptoMacInit(OH_CryptoMac *ctx, const OH_CryptoSymKey *key)
{
if ((ctx == NULL) || (ctx->macObj == NULL) || (ctx->macObj->init == NULL) || (key == NULL)) {
return CRYPTO_PARAMETER_CHECK_FAILED;
}
HcfResult ret = ctx->macObj->init(ctx->macObj, (const HcfSymKey *)key);
return GetOhCryptoErrCodeNew(ret);
}
OH_Crypto_ErrCode OH_CryptoMac_Init(OH_CryptoMac *ctx, const OH_CryptoSymKey *key)
{
return CryptoMacInit(ctx, key);
}
static OH_Crypto_ErrCode CryptoMacUpdate(OH_CryptoMac *ctx, const Crypto_DataBlob *in)
{
if ((ctx == NULL) || (ctx->macObj == NULL) || (ctx->macObj->update == NULL) || (in == NULL)) {
return CRYPTO_PARAMETER_CHECK_FAILED;
}
HcfResult ret = ctx->macObj->update(ctx->macObj, (HcfBlob *)in);
return GetOhCryptoErrCodeNew(ret);
}
OH_Crypto_ErrCode OH_CryptoMac_Update(OH_CryptoMac *ctx, const Crypto_DataBlob *in)
{
return CryptoMacUpdate(ctx, in);
}
static OH_Crypto_ErrCode CryptoMacFinal(OH_CryptoMac *ctx, Crypto_DataBlob *out)
{
if ((ctx == NULL) || (ctx->macObj == NULL) || (ctx->macObj->doFinal == NULL) || (out == NULL)) {
return CRYPTO_PARAMETER_CHECK_FAILED;
}
HcfResult ret = ctx->macObj->doFinal(ctx->macObj, (HcfBlob *)out);
return GetOhCryptoErrCodeNew(ret);
}
OH_Crypto_ErrCode OH_CryptoMac_Final(OH_CryptoMac *ctx, Crypto_DataBlob *out)
{
return CryptoMacFinal(ctx, out);
}
static OH_Crypto_ErrCode CryptoMacGetLength(OH_CryptoMac *ctx, uint32_t *length)
{
if ((ctx == NULL) || (ctx->macObj == NULL) || (ctx->macObj->getMacLength == NULL) || (length == NULL)) {
return CRYPTO_PARAMETER_CHECK_FAILED;
}
*length = ctx->macObj->getMacLength(ctx->macObj);
return CRYPTO_SUCCESS;
}
OH_Crypto_ErrCode OH_CryptoMac_GetLength(OH_CryptoMac *ctx, uint32_t *length)
{
return CryptoMacGetLength(ctx, length);
}
static void FreeMacParams(HcfMacParamsSpec *params)
{
if ((params == NULL) || (params->algName == NULL)) {
return;
}
if (strcmp(params->algName, "CMAC") == 0) {
HcfFree((void *)(((HcfCmacParamsSpec *)params)->cipherName));
((HcfCmacParamsSpec *)params)->cipherName = NULL;
} else if (strcmp(params->algName, "HMAC") == 0) {
HcfFree((void *)(((HcfHmacParamsSpec *)params)->mdName));
((HcfHmacParamsSpec *)params)->mdName = NULL;
}
params->algName = NULL;
HcfFree(params);
}
static void CryptoMacDestroy(OH_CryptoMac *ctx)
{
if (ctx == NULL) {
return;
}
FreeMacParams(ctx->paramsSpec);
ctx->paramsSpec = NULL;
HcfObjDestroy(ctx->macObj);
ctx->macObj = NULL;
HcfFree(ctx);
}
void OH_CryptoMac_Destroy(OH_CryptoMac *ctx)
{
CryptoMacDestroy(ctx);
}