* 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 "bsl_init.h"
#include "bsl_err_internal.h"
#include "crypt_local_types.h"
#include "crypt_algid.h"
#include "crypt_errno.h"
#include "crypt_eal_rand.h"
#include "crypt_utils.h"
#include "asmcap_local.h"
#include "crypt_ealinit.h"
#include "crypt_util_rand.h"
#ifdef HITLS_CRYPTO_PROVIDER
#include "crypt_eal_provider.h"
#include "crypt_provider.h"
#endif
#include "crypt_eal_init.h"
static uint64_t g_ealInitOpts = 0;
#if defined(HITLS_CRYPTO_PROVIDER)
static int32_t ProviderModuleInit(uint64_t initOpt, int32_t alg)
{
(void) alg;
int32_t ret = CRYPT_SUCCESS;
if ((initOpt & CRYPT_EAL_INIT_PROVIDER) && ((g_ealInitOpts & CRYPT_EAL_INIT_PROVIDER) == 0)) {
ret = CRYPT_EAL_InitPreDefinedProviders();
if (ret != CRYPT_SUCCESS) {
return ret;
}
g_ealInitOpts |= CRYPT_EAL_INIT_PROVIDER;
}
#if defined(HITLS_CRYPTO_DRBG)
if ((initOpt & CRYPT_EAL_INIT_PROVIDER_RAND) && ((g_ealInitOpts & CRYPT_EAL_INIT_PROVIDER_RAND) == 0)) {
ret = CRYPT_EAL_ProviderRandInitCtx(NULL, alg, "provider=default", NULL, 0, NULL);
if (ret != CRYPT_SUCCESS) {
return ret;
}
g_ealInitOpts |= CRYPT_EAL_INIT_PROVIDER_RAND;
}
#endif
return ret;
}
static void ProviderModuleFree(uint64_t initOpt)
{
if ((initOpt & CRYPT_EAL_INIT_PROVIDER) == 0) {
return;
}
CRYPT_EAL_FreePreDefinedProviders();
}
#else
static int32_t ProviderModuleInit(uint64_t initOpt, int32_t alg)
{
(void) initOpt;
(void) alg;
return CRYPT_SUCCESS;
}
static void ProviderModuleFree(uint64_t initOpt)
{
(void) initOpt;
}
#endif
#if defined(HITLS_CRYPTO_DRBG)
static void RandModuleFree(uint64_t initOpt)
{
if ((initOpt & CRYPT_EAL_INIT_RAND) == 0) {
return;
}
CRYPT_EAL_RandDeinit();
}
static int32_t RandModuleInit(uint64_t initOpt, int32_t alg)
{
if (!(initOpt & CRYPT_EAL_INIT_RAND) || (g_ealInitOpts & CRYPT_EAL_INIT_RAND) != 0) {
return BSL_SUCCESS;
}
int32_t ret = CRYPT_EAL_RandInit(alg, NULL, NULL, NULL, 0);
if (ret == CRYPT_SUCCESS) {
g_ealInitOpts |= CRYPT_EAL_INIT_RAND;
}
return ret;
}
#else
static void RandModuleFree(uint64_t initOpt)
{
(void) initOpt;
}
static int32_t RandModuleInit(uint64_t initOpt, int32_t alg)
{
(void) initOpt;
(void) alg;
return CRYPT_SUCCESS;
}
#endif
#if defined(HITLS_BSL_INIT)
static int32_t BslModuleInit(uint64_t initOpt)
{
if (!(initOpt & CRYPT_EAL_INIT_BSL) || (g_ealInitOpts & CRYPT_EAL_INIT_BSL) != 0) {
return BSL_SUCCESS;
}
int32_t ret = BSL_GLOBAL_Init();
if (ret == BSL_SUCCESS) {
g_ealInitOpts |= CRYPT_EAL_INIT_BSL;
}
return ret;
}
static void BslModuleFree(uint64_t initOpt)
{
if ((initOpt & CRYPT_EAL_INIT_BSL) == 0) {
return;
}
BSL_GLOBAL_DeInit();
}
#else
static int32_t BslModuleInit(uint64_t initOpt)
{
(void) initOpt;
return CRYPT_SUCCESS;
}
static void BslModuleFree(uint64_t initOpt)
{
(void) initOpt;
}
#endif
static int32_t GlobalLockInit(uint64_t initOpt)
{
if ((initOpt & CRYPT_EAL_INIT_LOCK) == 0 || (g_ealInitOpts & CRYPT_EAL_INIT_LOCK) != 0) {
return CRYPT_SUCCESS;
}
#ifdef HITLS_CRYPTO_ENTROPY
int32_t ret = EAL_SeedDrbgLockInit();
if (ret != CRYPT_SUCCESS) {
return ret;
}
#endif
g_ealInitOpts |= CRYPT_EAL_INIT_LOCK;
return CRYPT_SUCCESS;
}
static void GlobalLockFree(uint64_t initOpt)
{
if ((initOpt & CRYPT_EAL_INIT_LOCK) == 0) {
return;
}
#ifdef HITLS_CRYPTO_ENTROPY
EAL_SeedDrbgLockDeInit();
#endif
}
#if defined(HITLS_EAL_INIT_OPTS)
static bool g_ealInitOptsFlags = false;
#endif
#if defined(HITLS_EAL_INIT_OPTS)
__attribute__((constructor(102))) int32_t CRYPT_EAL_Init(uint64_t opts)
#else
int32_t CRYPT_EAL_Init(uint64_t opts)
#endif
{
int32_t ret = CRYPT_SUCCESS;
uint64_t initOpt = opts;
#if defined(HITLS_EAL_INIT_OPTS)
if (!g_ealInitOptsFlags) {
initOpt = HITLS_EAL_INIT_OPTS;
g_ealInitOptsFlags = true;
}
#endif
#if defined(HITLS_CRYPTO_INIT_RAND_ALG)
int32_t alg = HITLS_CRYPTO_INIT_RAND_ALG;
#else
int32_t alg = CRYPT_RAND_SHA256;
#endif
if ((initOpt & CRYPT_EAL_INIT_CPU) && (g_ealInitOpts & CRYPT_EAL_INIT_CPU) == 0) {
GetCpuInstrSupportState();
g_ealInitOpts |= CRYPT_EAL_INIT_CPU;
}
ret = BslModuleInit(initOpt);
if (ret != CRYPT_SUCCESS) {
g_ealInitOpts &= ~CRYPT_EAL_INIT_CPU;
return ret;
}
ret = GlobalLockInit(initOpt);
if (ret != CRYPT_SUCCESS) {
BslModuleFree(initOpt);
g_ealInitOpts &= ~(CRYPT_EAL_INIT_CPU | CRYPT_EAL_INIT_BSL);
return ret;
}
ret = ProviderModuleInit(initOpt, alg);
if (ret != CRYPT_SUCCESS) {
GlobalLockFree(initOpt);
BslModuleFree(initOpt);
g_ealInitOpts &= ~(CRYPT_EAL_INIT_CPU | CRYPT_EAL_INIT_BSL | CRYPT_EAL_INIT_LOCK);
return ret;
}
ret = RandModuleInit(initOpt, alg);
if (ret != CRYPT_SUCCESS) {
ProviderModuleFree(initOpt);
GlobalLockFree(initOpt);
BslModuleFree(initOpt);
g_ealInitOpts &= ~(CRYPT_EAL_INIT_CPU | CRYPT_EAL_INIT_BSL | CRYPT_EAL_INIT_LOCK |
CRYPT_EAL_INIT_PROVIDER | CRYPT_EAL_INIT_PROVIDER_RAND);
return ret;
}
return ret;
}
#if defined(HITLS_EAL_INIT_OPTS)
__attribute__((destructor(101))) void CRYPT_EAL_Cleanup(uint64_t opts)
#else
void CRYPT_EAL_Cleanup(uint64_t opts)
#endif
{
uint64_t initOpt = opts;
#if defined(HITLS_EAL_INIT_OPTS)
initOpt = CRYPT_EAL_INIT_ALL;
#endif
uint64_t cleanOpt = initOpt;
#if defined(HITLS_CRYPTO_PROVIDER) && defined(HITLS_CRYPTO_DRBG)
* Provider RAND is stored in the predefined provider libCtx. Freeing the
* provider also frees that DRBG, so keep the init-state bits consistent.
*/
if ((initOpt & CRYPT_EAL_INIT_PROVIDER) != 0) {
cleanOpt |= CRYPT_EAL_INIT_PROVIDER_RAND;
}
#endif
RandModuleFree(initOpt);
ProviderModuleFree(initOpt);
GlobalLockFree(initOpt);
BslModuleFree(initOpt);
g_ealInitOpts &= (~cleanOpt);
}
#ifdef HITLS_CRYPTO_ASM_CHECK
typedef int (*HITLS_ASM_CHECK_CALLBACK)(void);
typedef struct EAL_CheckAsm {
uint32_t id;
HITLS_ASM_CHECK_CALLBACK callback[2];
} EAL_CheckAsm;
static int32_t CryptCheckCapId(const BslCid id, const EAL_CheckAsm asmlist[], uint32_t len)
{
for (uint32_t i = 0; i < len; i++) {
if (asmlist[i].id != id) {
continue;
}
for (uint32_t j = 0; j < 2; j++) {
if (asmlist[i].callback[j] != NULL && asmlist[i].callback[j]() != CRYPT_SUCCESS) {
BSL_ERR_PUSH_ERROR(CRYPT_EAL_ALG_ASM_NOT_SUPPORT);
return CRYPT_EAL_ALG_ASM_NOT_SUPPORT;
}
}
}
return CRYPT_SUCCESS;
}
static const EAL_CheckAsm HITLS_ASM_SYM_ALG_CHECK[] = {
#if defined(HITLS_CRYPTO_AES_ASM)
{.id = CRYPT_CIPHER_AES128_CBC, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_AES192_CBC, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_AES256_CBC, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_AES128_CTR, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_AES192_CTR, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_AES256_CTR, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_AES128_ECB, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_AES192_ECB, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_AES256_ECB, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_AES128_XTS, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_AES256_XTS, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_AES128_CCM, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_AES192_CCM, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_AES256_CCM, .callback = {CRYPT_AES_AsmCheck, NULL}},
#if defined(HITLS_CRYPTO_GHASH_ASM)
{.id = CRYPT_CIPHER_AES128_GCM, .callback = {CRYPT_AES_AsmCheck, CRYPT_GHASH_AsmCheck}},
{.id = CRYPT_CIPHER_AES192_GCM, .callback = {CRYPT_AES_AsmCheck, CRYPT_GHASH_AsmCheck}},
{.id = CRYPT_CIPHER_AES256_GCM, .callback = {CRYPT_AES_AsmCheck, CRYPT_GHASH_AsmCheck}},
#endif
{.id = CRYPT_CIPHER_AES128_CFB, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_AES192_CFB, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_AES256_CFB, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_AES128_OFB, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_AES192_OFB, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_AES256_OFB, .callback = {CRYPT_AES_AsmCheck, NULL}},
#endif
#if defined(HITLS_CRYPTO_CHACHA20_ASM) || defined(HITLS_CRYPTO_CHACHA20POLY1305_ASM)
{.id = CRYPT_CIPHER_CHACHA20_POLY1305, .callback = {CRYPT_CHACHA20_AsmCheck, CRYPT_POLY1305_AsmCheck}},
#endif
#if defined(HITLS_CRYPTO_SM4_ASM)
{.id = CRYPT_CIPHER_SM4_XTS, .callback = {CRYPT_SM4_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_SM4_CBC, .callback = {CRYPT_SM4_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_SM4_ECB, .callback = {CRYPT_SM4_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_SM4_CTR, .callback = {CRYPT_SM4_AsmCheck, NULL}},
#if defined(HITLS_CRYPTO_GHASH_ASM)
{.id = CRYPT_CIPHER_SM4_GCM, .callback = {CRYPT_SM4_AsmCheck, CRYPT_GHASH_AsmCheck}},
#endif
{.id = CRYPT_CIPHER_SM4_CFB, .callback = {CRYPT_SM4_AsmCheck, NULL}},
{.id = CRYPT_CIPHER_SM4_OFB, .callback = {CRYPT_SM4_AsmCheck, NULL}},
#endif
{.id = CRYPT_CIPHER_MAX, .callback = {NULL, NULL}},
};
int32_t CRYPT_ASMCAP_Cipher(CRYPT_CIPHER_AlgId id)
{
return CryptCheckCapId((BslCid)id, HITLS_ASM_SYM_ALG_CHECK,
sizeof(HITLS_ASM_SYM_ALG_CHECK) / sizeof(EAL_CheckAsm));
}
#if defined(HITLS_CRYPTO_MD)
static const EAL_CheckAsm HITLS_ASM_MD_ALG_CHECK[] = {
#if defined(HITLS_CRYPTO_MD5_ASM)
{.id = CRYPT_MD_MD5, .callback = {CRYPT_MD5_AsmCheck, NULL}},
#endif
#if defined(HITLS_CRYPTO_SHA1_ASM)
{.id = CRYPT_MD_SHA1, .callback = {CRYPT_SHA1_AsmCheck, NULL}},
#endif
#if defined(HITLS_CRYPTO_SHA2_ASM)
{.id = CRYPT_MD_SHA224, .callback = {CRYPT_SHA2_AsmCheck, NULL}},
{.id = CRYPT_MD_SHA256, .callback = {CRYPT_SHA2_AsmCheck, NULL}},
{.id = CRYPT_MD_SHA384, .callback = {CRYPT_SHA2_AsmCheck, NULL}},
{.id = CRYPT_MD_SHA512, .callback = {CRYPT_SHA2_AsmCheck, NULL}},
#endif
#if defined(HITLS_CRYPTO_SM3_ASM)
{.id = CRYPT_MD_SM3, .callback = {CRYPT_SM3_AsmCheck, NULL}},
#endif
{.id = CRYPT_MD_MAX, .callback = {NULL, NULL}},
};
#endif
int32_t CRYPT_ASMCAP_Md(CRYPT_MD_AlgId id)
{
return CryptCheckCapId((BslCid)id, HITLS_ASM_MD_ALG_CHECK,
sizeof(HITLS_ASM_MD_ALG_CHECK) / sizeof(EAL_CheckAsm));
}
#if defined(HITLS_CRYPTO_PKEY)
static const EAL_CheckAsm HITLS_ASM_PKEY_ALG_CHECK[] = {
#if defined(HITLS_CRYPTO_BN_ASM)
{.id = CRYPT_PKEY_DSA, .callback = {CRYPT_BN_AsmCheck, NULL}},
{.id = CRYPT_PKEY_RSA, .callback = {CRYPT_BN_AsmCheck, NULL}},
{.id = CRYPT_PKEY_DH, .callback = {CRYPT_BN_AsmCheck, NULL}},
#if defined(HITLS_CRYPTO_CURVE_NISTP256_ASM)
{.id = CRYPT_PKEY_ECDSA, .callback = {CRYPT_BN_AsmCheck, CRYPT_ECP256_AsmCheck}},
{.id = CRYPT_PKEY_ECDH, .callback = {CRYPT_BN_AsmCheck, CRYPT_ECP256_AsmCheck}},
#endif
{.id = CRYPT_PKEY_SM2, .callback = {CRYPT_BN_AsmCheck, NULL}},
#endif
{.id = CRYPT_PKEY_MAX, .callback = {NULL, NULL}},
};
int32_t CRYPT_ASMCAP_Pkey(CRYPT_PKEY_AlgId id)
{
return CryptCheckCapId((BslCid)id, HITLS_ASM_PKEY_ALG_CHECK,
sizeof(HITLS_ASM_PKEY_ALG_CHECK) / sizeof(EAL_CheckAsm));
}
#endif
#if defined(HITLS_CRYPTO_DRBG)
static const EAL_CheckAsm HITLS_ASM_DRBG_ALG_CHECK[] = {
#if defined(HITLS_CRYPTO_SHA1_ASM)
{.id = CRYPT_RAND_SHA1, .callback = {CRYPT_SHA1_AsmCheck, NULL}},
{.id = CRYPT_RAND_HMAC_SHA1, .callback = {CRYPT_SHA1_AsmCheck, NULL}},
#endif
#if defined(HITLS_CRYPTO_SHA2_ASM)
{.id = CRYPT_RAND_SHA224, .callback = {CRYPT_SHA2_AsmCheck, NULL}},
{.id = CRYPT_RAND_SHA256, .callback = {CRYPT_SHA2_AsmCheck, NULL}},
{.id = CRYPT_RAND_SHA384, .callback = {CRYPT_SHA2_AsmCheck, NULL}},
{.id = CRYPT_RAND_SHA512, .callback = {CRYPT_SHA2_AsmCheck, NULL}},
{.id = CRYPT_RAND_HMAC_SHA224, .callback = {CRYPT_SHA2_AsmCheck, NULL}},
{.id = CRYPT_RAND_HMAC_SHA256, .callback = {CRYPT_SHA2_AsmCheck, NULL}},
{.id = CRYPT_RAND_HMAC_SHA384, .callback = {CRYPT_SHA2_AsmCheck, NULL}},
{.id = CRYPT_RAND_HMAC_SHA512, .callback = {CRYPT_SHA2_AsmCheck, NULL}},
#endif
#if defined(HITLS_CRYPTO_SM3_ASM)
{.id = CRYPT_RAND_SM3, .callback = {CRYPT_SM3_AsmCheck, NULL}},
#endif
#if defined(HITLS_CRYPTO_AES_ASM)
{.id = CRYPT_RAND_AES128_CTR, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_RAND_AES192_CTR, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_RAND_AES256_CTR, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_RAND_AES128_CTR_DF, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_RAND_AES192_CTR_DF, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_RAND_AES256_CTR_DF, .callback = {CRYPT_AES_AsmCheck, NULL}},
#endif
#if defined(HITLS_CRYPTO_SM4_ASM)
{.id = CRYPT_RAND_SM4_CTR_DF, .callback = {CRYPT_SM4_AsmCheck, NULL}},
#endif
{.id = CRYPT_RAND_ALGID_MAX, .callback = {NULL, NULL}},
};
int32_t CRYPT_ASMCAP_Drbg(CRYPT_RAND_AlgId id)
{
return CryptCheckCapId((BslCid)id, HITLS_ASM_DRBG_ALG_CHECK,
sizeof(HITLS_ASM_DRBG_ALG_CHECK) / sizeof(EAL_CheckAsm));
}
#endif
#if defined(HITLS_CRYPTO_MAC)
static const EAL_CheckAsm HITLS_ASM_MAC_ALG_CHECK[] = {
#if defined(HITLS_CRYPTO_MD5_ASM)
{.id = CRYPT_MAC_HMAC_MD5, .callback = {CRYPT_MD5_AsmCheck, NULL}},
#endif
#if defined(HITLS_CRYPTO_SHA1_ASM)
{.id = CRYPT_MAC_HMAC_SHA1, .callback = {CRYPT_SHA1_AsmCheck, NULL}},
#endif
#if defined(HITLS_CRYPTO_SHA2_ASM)
{.id = CRYPT_MAC_HMAC_SHA224, .callback = {CRYPT_SHA2_AsmCheck, NULL}},
{.id = CRYPT_MAC_HMAC_SHA256, .callback = {CRYPT_SHA2_AsmCheck, NULL}},
{.id = CRYPT_MAC_HMAC_SHA384, .callback = {CRYPT_SHA2_AsmCheck, NULL}},
{.id = CRYPT_MAC_HMAC_SHA512, .callback = {CRYPT_SHA2_AsmCheck, NULL}},
#endif
#if defined(HITLS_CRYPTO_SM3_ASM)
{.id = CRYPT_MAC_HMAC_SM3, .callback = {CRYPT_SM3_AsmCheck, NULL}},
#endif
#if defined(HITLS_CRYPTO_AES_ASM)
{.id = CRYPT_MAC_CMAC_AES128, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_MAC_CMAC_AES192, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_MAC_CMAC_AES256, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_MAC_GMAC_AES128, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_MAC_GMAC_AES192, .callback = {CRYPT_AES_AsmCheck, NULL}},
{.id = CRYPT_MAC_GMAC_AES256, .callback = {CRYPT_AES_AsmCheck, NULL}},
#endif
{.id = CRYPT_MAC_MAX, .callback = {NULL, NULL}},
};
int32_t CRYPT_ASMCAP_Mac(CRYPT_MAC_AlgId id)
{
return CryptCheckCapId((BslCid)id, HITLS_ASM_MAC_ALG_CHECK,
sizeof(HITLS_ASM_MAC_ALG_CHECK) / sizeof(EAL_CheckAsm));
}
#endif
#endif