* 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 <stdint.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include "hitls_build.h"
#include "bsl_sal.h"
#include "bsl_errno.h"
#include "crypt_errno.h"
#include "crypt_types.h"
#include "crypt_eal_md.h"
#include "eal_md_local.h"
#include "crypt_eal_rand.h"
#include "crypt_eal_mac.h"
#include "crypt_eal_init.h"
#include "crypt_params_key.h"
#include "test.h"
#include "helper.h"
#include "crypto_test_util.h"
#include <errno.h>
#include <string.h>
#include "crypt_util_rand.h"
#include "bsl_err_internal.h"
#ifndef HITLS_BSL_SAL_MEM
void *TestMalloc(uint32_t len)
{
return malloc((size_t)len);
}
#endif
void TestMemInit(void)
{
#ifdef HITLS_BSL_SAL_MEM
return;
#else
BSL_SAL_CallBack_Ctrl(BSL_SAL_MEM_MALLOC, TestMalloc);
BSL_SAL_CallBack_Ctrl(BSL_SAL_MEM_FREE, free);
#endif
}
void TestErrClear(void)
{
#ifdef HITLS_BSL_ERR
BSL_ERR_ClearError();
#endif
}
bool TestIsErrStackEmpty(void)
{
#ifdef HITLS_BSL_ERR
if (BSL_ERR_Init() != BSL_SUCCESS) {
return false;
}
const char *file = NULL;
uint32_t line = 0;
int32_t err = BSL_ERR_GetErrorFileLine(&file, &line);
if (err == BSL_SUCCESS) {
return true;
}
Print("[BSL_ERR] unexpected error in stack: file=%s, line=%u\n", (file == NULL ? "NA" : file), line);
BSL_ERR_DeInit();
return false;
#else
return true;
#endif
}
bool TestIsErrStackNotEmpty(void)
{
#ifdef HITLS_BSL_ERR
if (BSL_ERR_Init() != BSL_SUCCESS) {
return true;
}
const char *file = NULL;
uint32_t line = 0;
int32_t err = BSL_ERR_GetErrorFileLine(&file, &line);
BSL_ERR_DeInit();
return err != BSL_SUCCESS;
#else
return true;
#endif
}
#if defined(HITLS_CRYPTO_EAL) && defined(HITLS_CRYPTO_DRBG)
typedef struct {
CRYPT_Data *entropy;
CRYPT_Data *nonce;
CRYPT_Data *pers;
CRYPT_Data *addin1;
CRYPT_Data *entropyPR1;
CRYPT_Data *addin2;
CRYPT_Data *entropyPR2;
CRYPT_Data *retBits;
} DRBG_Vec_t;
#ifndef HITLS_CRYPTO_ENTROPY
static int32_t GetEntropy(void *ctx, CRYPT_Data *entropy, uint32_t strength, CRYPT_Range *lenRange)
{
if (lenRange == NULL) {
Print("getEntropy Error lenRange NULL\n");
return CRYPT_NULL_INPUT;
}
if (ctx == NULL || entropy == NULL) {
Print("getEntropy Error\n");
lenRange->max = strength;
return CRYPT_NULL_INPUT;
}
DRBG_Vec_t *seedCtx = (DRBG_Vec_t *)ctx;
entropy->data = seedCtx->entropy->data;
entropy->len = seedCtx->entropy->len;
return CRYPT_SUCCESS;
}
static void CleanEntropy(void *ctx, CRYPT_Data *entropy)
{
(void)ctx;
(void)entropy;
return;
}
#endif
int32_t TestSimpleRand(uint8_t *buff, uint32_t len)
{
int rand = open("/dev/urandom", O_RDONLY);
if (rand < 0) {
printf("open /dev/urandom failed.\n");
return -1;
}
int l = read(rand, buff, len);
if (l < 0) {
printf("read from /dev/urandom failed. errno: %d.\n", errno);
close(rand);
return -1;
}
close(rand);
return 0;
}
int32_t TestSimpleRandEx(void *libCtx, uint8_t *buff, uint32_t len)
{
(void)libCtx;
return TestSimpleRand(buff, len);
}
int32_t TestSimpleRandExSelfCheck(void *libCtx, uint8_t *buff, uint32_t len)
{
if (libCtx == NULL) {
return CRYPT_PROVIDER_INVALID_LIB_CTX;
}
return TestSimpleRand(buff, len);
}
int TestRandInitEx(void *libCtx)
{
(void)libCtx;
int drbgAlgId = GetAvailableRandAlgId();
int32_t ret;
if (drbgAlgId == -1) {
Print("Drbg algs are disabled.");
return CRYPT_NOT_SUPPORT;
}
#ifndef HITLS_CRYPTO_ENTROPY
CRYPT_RandSeedMethod seedMeth = {GetEntropy, CleanEntropy, NULL, NULL};
uint8_t entropy[64] = {0};
CRYPT_Data tempEntropy = {entropy, sizeof(entropy)};
DRBG_Vec_t seedCtx = {0};
seedCtx.entropy = &tempEntropy;
#endif
BSL_ERR_SET_MARK();
#ifdef HITLS_CRYPTO_PROVIDER
#ifndef HITLS_CRYPTO_ENTROPY
BSL_Param param[4] = {0};
(void)BSL_PARAM_InitValue(¶m[0], CRYPT_PARAM_RAND_SEEDCTX, BSL_PARAM_TYPE_CTX_PTR, &seedCtx, 0);
(void)BSL_PARAM_InitValue(¶m[1], CRYPT_PARAM_RAND_SEED_GETENTROPY, BSL_PARAM_TYPE_FUNC_PTR,
seedMeth.getEntropy, 0);
(void)BSL_PARAM_InitValue(¶m[2], CRYPT_PARAM_RAND_SEED_CLEANENTROPY, BSL_PARAM_TYPE_FUNC_PTR,
seedMeth.cleanEntropy, 0);
ret = CRYPT_EAL_ProviderRandInitCtx(libCtx, (CRYPT_RAND_AlgId)drbgAlgId, "provider=default", NULL, 0, param);
#else
ret = CRYPT_EAL_ProviderRandInitCtx(libCtx, (CRYPT_RAND_AlgId)drbgAlgId, "provider=default", NULL, 0, NULL);
#endif
#else
#ifndef HITLS_CRYPTO_ENTROPY
ret = CRYPT_EAL_RandInit(drbgAlgId, &seedMeth, (void *)&seedCtx, NULL, 0);
#else
ret = CRYPT_EAL_RandInit(drbgAlgId, NULL, NULL, NULL, 0);
#endif
#endif
if (ret == CRYPT_EAL_ERR_DRBG_REPEAT_INIT) {
BSL_ERR_POP_TO_MARK();
ret = CRYPT_SUCCESS;
}
return ret;
}
int TestRandInit(void)
{
int32_t ret = TestRandInitEx(NULL);
if (ret != CRYPT_SUCCESS) {
return ret;
}
#ifdef HITLS_CRYPTO_PROVIDER
CRYPT_RandRegistEx(TestSimpleRandEx);
#else
CRYPT_RandRegist(TestSimpleRand);
#endif
return CRYPT_SUCCESS;
}
int TestRandInitSelfCheck(void)
{
int32_t ret = TestRandInitEx(NULL);
if (ret != CRYPT_SUCCESS) {
return ret;
}
#ifdef HITLS_CRYPTO_PROVIDER
CRYPT_RandRegistEx(TestSimpleRandExSelfCheck);
#else
CRYPT_RandRegist(TestSimpleRand);
#endif
return CRYPT_SUCCESS;
}
void TestRandDeInit(void)
{
CRYPT_RandRegist(NULL);
#ifdef HITLS_CRYPTO_PROVIDER
CRYPT_RandRegistEx(NULL);
#endif
#ifdef HITLS_CRYPTO_PROVIDER
CRYPT_EAL_RandDeinitEx(NULL);
#else
CRYPT_EAL_RandDeinit();
#endif
}
#endif
#if defined(HITLS_CRYPTO_EAL) && defined(HITLS_CRYPTO_MAC)
uint32_t TestGetMacLen(int algId)
{
switch (algId) {
case CRYPT_MAC_HMAC_MD5:
return 16;
case CRYPT_MAC_HMAC_SHA1:
return 20;
case CRYPT_MAC_HMAC_SHA224:
case CRYPT_MAC_HMAC_SHA3_224:
return 28;
case CRYPT_MAC_HMAC_SHA256:
case CRYPT_MAC_HMAC_SHA3_256:
return 32;
case CRYPT_MAC_HMAC_SHA384:
case CRYPT_MAC_HMAC_SHA3_384:
return 48;
case CRYPT_MAC_HMAC_SHA512:
case CRYPT_MAC_HMAC_SHA3_512:
return 64;
case CRYPT_MAC_HMAC_SM3:
return 32;
case CRYPT_MAC_CMAC_AES128:
case CRYPT_MAC_CMAC_AES192:
case CRYPT_MAC_CMAC_AES256:
return 16;
case CRYPT_MAC_CMAC_SM4:
return 16;
case CRYPT_MAC_CBC_MAC_SM4:
return 16;
case CRYPT_MAC_SIPHASH64:
return 8;
case CRYPT_MAC_SIPHASH128:
return 16;
default:
return 0;
}
}
void TestMacSameAddr(int algId, Hex *key, Hex *data, Hex *mac)
{
uint32_t outLen = data->len > mac->len ? data->len : mac->len;
uint8_t out[outLen];
CRYPT_EAL_MacCtx *ctx = NULL;
int32_t padType = CRYPT_PADDING_ZEROS;
ASSERT_TRUE(data->len <= (outLen));
memcpy(out, data->x, data->len);
TestMemInit();
ASSERT_TRUE((ctx = CRYPT_EAL_MacNewCtx(algId)) != NULL);
ASSERT_EQ(CRYPT_EAL_MacInit(ctx, key->x, key->len), CRYPT_SUCCESS);
if (algId == CRYPT_MAC_CBC_MAC_SM4) {
ASSERT_EQ(CRYPT_EAL_MacCtrl(ctx, CRYPT_CTRL_SET_CBC_MAC_PADDING, &padType, sizeof(padType)), CRYPT_SUCCESS);
}
ASSERT_EQ(CRYPT_EAL_MacUpdate(ctx, out, data->len), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_MacFinal(ctx, out, &outLen), CRYPT_SUCCESS);
ASSERT_COMPARE("mac result cmp", out, outLen, mac->x, mac->len);
EXIT:
CRYPT_EAL_MacFreeCtx(ctx);
}
void TestMacAddrNotAlign(int algId, Hex *key, Hex *data, Hex *mac)
{
uint32_t outLen = data->len > mac->len ? data->len : mac->len;
uint8_t out[outLen];
CRYPT_EAL_MacCtx *ctx = NULL;
int32_t padType = CRYPT_PADDING_ZEROS;
uint8_t keyTmp[key->len + 1] __attribute__((aligned(8)));
uint8_t dataTmp[data->len + 1] __attribute__((aligned(8)));
uint8_t *pKey = keyTmp + 1;
uint8_t *pData = dataTmp + 1;
ASSERT_TRUE(key->len <= sizeof(keyTmp));
memcpy(pKey, key->x, key->len);
ASSERT_TRUE(data->len <= sizeof(dataTmp));
memcpy(pData, data->x, data->len);
TestMemInit();
ASSERT_TRUE((ctx = CRYPT_EAL_MacNewCtx(algId)) != NULL);
ASSERT_EQ(CRYPT_EAL_MacInit(ctx, pKey, key->len), CRYPT_SUCCESS);
if (algId == CRYPT_MAC_CBC_MAC_SM4) {
ASSERT_EQ(CRYPT_EAL_MacCtrl(ctx, CRYPT_CTRL_SET_CBC_MAC_PADDING, &padType, sizeof(padType)), CRYPT_SUCCESS);
}
ASSERT_EQ(CRYPT_EAL_MacUpdate(ctx, pData, data->len), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_MacFinal(ctx, out, &outLen), CRYPT_SUCCESS);
ASSERT_COMPARE("mac result cmp", out, outLen, mac->x, mac->len);
ASSERT_TRUE(TestIsErrStackEmpty());
EXIT:
CRYPT_EAL_MacFreeCtx(ctx);
}
#endif
#ifdef HITLS_CRYPTO_CIPHER
CRYPT_EAL_CipherCtx *TestCipherNewCtx(CRYPT_EAL_LibCtx *libCtx, int32_t id, const char *attrName, int isProvider)
{
#ifdef HITLS_CRYPTO_PROVIDER
if (isProvider == 1) {
if (CRYPT_EAL_Init(0) != CRYPT_SUCCESS) {
return NULL;
}
return CRYPT_EAL_ProviderCipherNewCtx(libCtx, id, attrName);
} else {
return CRYPT_EAL_CipherNewCtx(id);
}
#else
(void)libCtx;
(void)attrName;
(void)isProvider;
return CRYPT_EAL_CipherNewCtx(id);
#endif
}
#endif
#ifdef HITLS_CRYPTO_PKEY
CRYPT_EAL_PkeyCtx *TestPkeyNewCtx(
CRYPT_EAL_LibCtx *libCtx, int32_t id, uint32_t operType, const char *attrName, int isProvider)
{
#ifdef HITLS_CRYPTO_PROVIDER
if (isProvider == 1) {
#ifdef HITLS_CRYPTO_EALINIT
if (CRYPT_EAL_Init(0) != CRYPT_SUCCESS) {
return NULL;
}
#endif
return CRYPT_EAL_ProviderPkeyNewCtx(libCtx, id, operType, attrName);
} else {
return CRYPT_EAL_PkeyNewCtx(id);
}
#else
(void)libCtx;
(void)operType;
(void)attrName;
(void)isProvider;
return CRYPT_EAL_PkeyNewCtx(id);
#endif
}
#endif