* 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 <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "crypt_errno.h"
#include "crypt_eal_provider.h"
#include "crypt_eal_implprovider.h"
#define CRYPT_EAL_DEFAULT_ATTR "provider?p12Load"
static int32_t RandFunc(uint8_t *randNum, uint32_t randLen)
{
for (uint32_t i = 0; i < randLen; i++) {
randNum[i] = (uint8_t)(rand() % UINT8_MAX);
}
return 0;
}
void *DRBG_RandNewCtx(void *provCtx, int32_t algId, BSL_Param *param)
{
(void)provCtx;
(void)algId;
(void)param;
return malloc(1);
}
int32_t DRBG_Instantiate(void *ctx, const uint8_t *person, uint32_t persLen, BSL_Param *param)
{
(void)ctx;
(void)person;
(void)persLen;
(void)param;
return CRYPT_SUCCESS;
}
int32_t DRBG_Uninstantiate(void *ctx)
{
(void)ctx;
return CRYPT_SUCCESS;
}
int32_t DRBG_Generate(void *ctx, uint8_t *out, uint32_t outLen,
const uint8_t *adin, uint32_t adinLen, BSL_Param *param)
{
(void)ctx;
(void)adin;
(void)adinLen;
(void)param;
RandFunc(out, outLen);
return CRYPT_SUCCESS;
}
int32_t DRBG_Reseed(void *ctx, const uint8_t *adin, uint32_t adinLen, BSL_Param *param)
{
(void)ctx;
(void)adin;
(void)adinLen;
(void)param;
return CRYPT_SUCCESS;
}
int32_t DRBG_Ctrl(void *ctx, int32_t cmd, void *val, uint32_t valLen)
{
(void)ctx;
(void)cmd;
(void)val;
(void)valLen;
return CRYPT_SUCCESS;
}
void DRBG_Free(void *ctx)
{
free(ctx);
}
void *MAC_NewCtx(void *provCtx, int32_t algid, BSL_Param *param)
{
(void)provCtx;
(void)param;
int *ctx = malloc(sizeof(int));
return ctx;
}
int32_t MAC_FreeCtx(void *ctx)
{
free(ctx);
return CRYPT_SUCCESS;
}
int32_t MAC_Init(void *ctx, const uint8_t *key, uint32_t len, void *param)
{
(void)ctx;
(void)key;
(void)len;
(void)param;
return CRYPT_SUCCESS;
}
int32_t MAC_Update(void *ctx, const uint8_t *in, uint32_t len)
{
(void)ctx;
(void)in;
(void)len;
return CRYPT_SUCCESS;
}
int32_t MAC_Final(void *ctx, uint8_t *out, uint32_t *len)
{
(void)ctx;
(void)out;
(void)len;
return CRYPT_SUCCESS;
}
const CRYPT_EAL_Func defMacHmac[] = {
{CRYPT_EAL_IMPLMAC_NEWCTX, MAC_NewCtx},
{CRYPT_EAL_IMPLMAC_INIT, MAC_Init},
{CRYPT_EAL_IMPLMAC_UPDATE, MAC_Update},
{CRYPT_EAL_IMPLMAC_FINAL, MAC_Final},
{CRYPT_EAL_IMPLMAC_REINITCTX, NULL},
{CRYPT_EAL_IMPLMAC_CTRL, NULL},
{CRYPT_EAL_IMPLMAC_FREECTX, MAC_FreeCtx},
CRYPT_EAL_FUNC_END,
};
const CRYPT_EAL_Func g_testRand[] = {
{CRYPT_EAL_IMPLRAND_DRBGNEWCTX, (CRYPT_EAL_ImplRandDrbgNewCtx)DRBG_RandNewCtx},
{CRYPT_EAL_IMPLRAND_DRBGINST, (CRYPT_EAL_ImplRandDrbgInst)DRBG_Instantiate},
{CRYPT_EAL_IMPLRAND_DRBGUNINST, (CRYPT_EAL_ImplRandDrbgUnInst)DRBG_Uninstantiate},
{CRYPT_EAL_IMPLRAND_DRBGGEN, (CRYPT_EAL_ImplRandDrbgGen)DRBG_Generate},
{CRYPT_EAL_IMPLRAND_DRBGRESEED, (CRYPT_EAL_ImplRandDrbgReSeed)DRBG_Reseed},
{CRYPT_EAL_IMPLRAND_DRBGCTRL, (CRYPT_EAL_ImplRandDrbgCtrl)DRBG_Ctrl},
{CRYPT_EAL_IMPLRAND_DRBGFREECTX, (CRYPT_EAL_ImplRandDrbgFreeCtx)DRBG_Free},
CRYPT_EAL_FUNC_END,
};
static const CRYPT_EAL_AlgInfo defMacs[] = {
{CRYPT_MAC_HMAC_SM3, defMacHmac, CRYPT_EAL_DEFAULT_ATTR},
CRYPT_EAL_ALGINFO_END
};
static const CRYPT_EAL_AlgInfo defRand[] = {
{CRYPT_RAND_SHA256, g_testRand, CRYPT_EAL_DEFAULT_ATTR},
{CRYPT_RAND_SM3, g_testRand, CRYPT_EAL_DEFAULT_ATTR},
CRYPT_EAL_ALGINFO_END
};
static int32_t CRYPT_EAL_DefaultProvQuery(void *provCtx, int32_t operaId, const CRYPT_EAL_AlgInfo **algInfos)
{
(void) provCtx;
int32_t ret = CRYPT_SUCCESS;
switch (operaId) {
case CRYPT_EAL_OPERAID_MAC:
*algInfos = defMacs;
break;
case CRYPT_EAL_OPERAID_RAND:
*algInfos = defRand;
break;
default:
ret = CRYPT_NOT_SUPPORT;
break;
}
return ret;
}
static void CRYPT_EAL_DefaultProvFree(void *provCtx)
{
return;
}
static CRYPT_EAL_Func defProvOutFuncs[] = {
{CRYPT_EAL_PROVCB_QUERY, CRYPT_EAL_DefaultProvQuery},
{CRYPT_EAL_PROVCB_FREE, CRYPT_EAL_DefaultProvFree},
{CRYPT_EAL_PROVCB_CTRL, NULL},
CRYPT_EAL_FUNC_END
};
int32_t CRYPT_EAL_ProviderInit(CRYPT_EAL_ProvMgrCtx *mgrCtx,
BSL_Param *param, CRYPT_EAL_Func *capFuncs, CRYPT_EAL_Func **outFuncs, void **provCtx)
{
CRYPT_RandSeedMethod entroy = {0};
CRYPT_EAL_ProvMgrCtrlCb mgrCtrl = NULL;
int32_t index = 0;
while (capFuncs[index].id != 0) {
switch (capFuncs[index].id) {
case CRYPT_EAL_CAP_GETENTROPY:
entroy.getEntropy = capFuncs[index].func;
break;
case CRYPT_EAL_CAP_CLEANENTROPY:
entroy.cleanEntropy = capFuncs[index].func;
break;
case CRYPT_EAL_CAP_GETNONCE:
entroy.getNonce = capFuncs[index].func;
break;
case CRYPT_EAL_CAP_CLEANNONCE:
entroy.cleanNonce = capFuncs[index].func;
break;
case CRYPT_EAL_CAP_MGRCTXCTRL:
mgrCtrl = capFuncs[index].func;
break;
default:
return CRYPT_PROVIDER_ERR_UNEXPECTED_IMPL;
}
index++;
}
void *seedCtx = NULL;
void *libCtx = NULL;
if (entroy.getEntropy == NULL || entroy.cleanEntropy == NULL || entroy.getNonce == NULL ||
entroy.cleanNonce == NULL || mgrCtrl == NULL) {
return CRYPT_NULL_INPUT;
}
int32_t ret = mgrCtrl(mgrCtx, CRYPT_EAL_MGR_GETSEEDCTX, &seedCtx, 0);
if (ret != CRYPT_SUCCESS) {
return ret;
}
ret = mgrCtrl(mgrCtx, CRYPT_EAL_MGR_GETLIBCTX, &libCtx, 0);
if (ret != CRYPT_SUCCESS) {
return ret;
}
CRYPT_Data entropy = {NULL, 0};
CRYPT_Range entropyRange = {32, 2147483632};
ret = entroy.getEntropy(seedCtx, &entropy, 256, &entropyRange);
if (ret != CRYPT_SUCCESS) {
return CRYPT_DRBG_FAIL_GET_ENTROPY;
}
entroy.cleanEntropy(seedCtx, &entropy);
if (param != NULL) {
if (param[0].value != libCtx) {
return CRYPT_INVALID_ARG;
}
}
*outFuncs = defProvOutFuncs;
return 0;
}