* This file is part of the openHiTLS project.
*
* openHiTLS is licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "hitls_build.h"
#if defined(HITLS_CRYPTO_CBC_MAC) || defined(HITLS_CRYPTO_CMAC)
#include <stdlib.h>
#include <string.h>
#include "bsl_sal.h"
#include "crypt_utils.h"
#include "crypt_errno.h"
#include "bsl_err_internal.h"
#include "crypt_local_types.h"
#include "cipher_mac_common.h"
int32_t CipherMacInitCtx(Cipher_MAC_Common_Ctx *ctx, const EAL_SymMethod *method)
{
if (ctx == NULL || method == NULL) {
BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
void *key = (void *)BSL_SAL_Calloc(1u, method->ctxSize);
if (key == NULL) {
BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
return CRYPT_MEM_ALLOC_FAIL;
}
ctx->key = key;
ctx->method = method;
return CRYPT_SUCCESS;
}
void CipherMacDeinitCtx(Cipher_MAC_Common_Ctx *ctx)
{
if (ctx == NULL || ctx->method == NULL) {
BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
return;
}
const EAL_SymMethod *method = ctx->method;
BSL_SAL_ClearFree((void *)(ctx->key), method->ctxSize);
ctx->key = NULL;
}
int32_t CipherMacInit(Cipher_MAC_Common_Ctx *ctx, const uint8_t *key, uint32_t len)
{
if (ctx == NULL || ctx->method == NULL || (key == NULL && len != 0)) {
BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
int32_t ret = ctx->method->setEncryptKey(ctx->key, key, len);
if (ret != CRYPT_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
return ret;
}
memset(ctx->data, 0, CIPHER_MAC_MAXBLOCKSIZE);
ctx->len = 0;
return CRYPT_SUCCESS;
}
int32_t CipherMacUpdate(Cipher_MAC_Common_Ctx *ctx, const uint8_t *in, uint32_t len)
{
if (ctx == NULL || ctx->method == NULL || (in == NULL && len != 0)) {
BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
const EAL_SymMethod *method = ctx->method;
int32_t ret;
uint32_t blockSize = method->blockSize;
const uint8_t *inTmp = in;
uint32_t lenTmp = len;
if (ctx->len > 0) {
if (ctx->len > (UINT32_MAX - lenTmp)) {
BSL_ERR_PUSH_ERROR(CRYPT_CMAC_INPUT_OVERFLOW);
return CRYPT_CMAC_INPUT_OVERFLOW;
}
uint32_t end = (ctx->len + lenTmp) > (blockSize) ? (blockSize) : (ctx->len + lenTmp);
uint8_t *left = ctx->left + ctx->len;
uint8_t *leftEnd = ctx->left + end;
while (left < leftEnd) {
*left = *inTmp;
left++;
inTmp++;
}
lenTmp -= (end - ctx->len);
if (lenTmp == 0) {
ctx->len = end;
return CRYPT_SUCCESS;
}
DATA_XOR(ctx->left, ctx->data, ctx->left, blockSize);
ret = method->encryptBlock(ctx->key, ctx->left, ctx->data, blockSize);
if (ret != CRYPT_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
return ret;
}
}
while (lenTmp > blockSize) {
DATA_XOR(inTmp, ctx->data, ctx->left, blockSize);
ret = method->encryptBlock(ctx->key, ctx->left, ctx->data, blockSize);
if (ret != CRYPT_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
return ret;
}
lenTmp -= blockSize;
inTmp += blockSize;
}
uint8_t *left = ctx->left;
const uint8_t *leftSrcEnd = inTmp + lenTmp;
while (inTmp < leftSrcEnd) {
*left = *inTmp;
left++;
inTmp++;
}
ctx->len = lenTmp;
return CRYPT_SUCCESS;
}
int32_t CipherMacReinit(Cipher_MAC_Common_Ctx *ctx)
{
if (ctx == NULL) {
BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
memset(ctx->data, 0, CIPHER_MAC_MAXBLOCKSIZE);
ctx->len = 0;
return CRYPT_SUCCESS;
}
int32_t CipherMacDeinit(Cipher_MAC_Common_Ctx *ctx)
{
if (ctx == NULL || ctx->method == NULL) {
return CRYPT_NULL_INPUT;
}
const uint32_t ctxSize = ctx->method->ctxSize;
BSL_SAL_CleanseData(ctx->key, ctxSize);
memset(ctx->data, 0, CIPHER_MAC_MAXBLOCKSIZE);
memset(ctx->left, 0, CIPHER_MAC_MAXBLOCKSIZE);
ctx->len = 0;
return CRYPT_SUCCESS;
}
int32_t CipherMacGetMacLen(const Cipher_MAC_Common_Ctx *ctx, void *val, uint32_t len)
{
if (ctx == NULL || ctx->method == NULL || val == NULL || len != sizeof(uint32_t)) {
BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
*(uint32_t *)val = ctx->method->blockSize;
return CRYPT_SUCCESS;
}
#endif