* 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_EAL) && defined(HITLS_CRYPTO_PKEY)
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "eal_pkey_local.h"
#include "crypt_eal_pkey.h"
#include "crypt_errno.h"
#include "crypt_algid.h"
#include "crypt_local_types.h"
#include "crypt_types.h"
#include "bsl_sal.h"
#include "bsl_err_internal.h"
#include "crypt_utils.h"
#include "eal_md_local.h"
#include "eal_common.h"
#include "crypt_ealinit.h"
#include "bsl_params.h"
#include "crypt_params_key.h"
#include "eal_pkey.h"
#ifdef HITLS_CRYPTO_PROVIDER
#include "crypt_eal_implprovider.h"
#include "crypt_provider.h"
#endif
static void EalPkeyCopyMethod(const EAL_PkeyMethod *method, EAL_PkeyUnitaryMethod *dest)
{
dest->newCtx = method->newCtx;
dest->dupCtx = method->dupCtx;
dest->freeCtx = method->freeCtx;
dest->setPara = method->setPara;
dest->getPara = method->getPara;
dest->gen = method->gen;
dest->ctrl = method->ctrl;
dest->setPub = method->setPub;
dest->setPrv = method->setPrv;
dest->getPub = method->getPub;
dest->getPrv = method->getPrv;
dest->sign = method->sign;
dest->signData = method->signData;
dest->verify = method->verify;
dest->verifyData = method->verifyData;
dest->recover = method->recover;
dest->computeShareKey = method->computeShareKey;
dest->encrypt = method->encrypt;
dest->decrypt = method->decrypt;
dest->headd = method->headd;
dest->hemul = method->hemul;
dest->check = method->check;
dest->cmp = method->cmp;
dest->pkeyEncaps = method->pkeyEncaps;
dest->pkeyDecaps = method->pkeyDecaps;
dest->blind = method->blind;
dest->unBlind = method->unBlind;
}
CRYPT_EAL_PkeyCtx *PkeyNewDefaultCtx(CRYPT_PKEY_AlgId id)
{
const EAL_PkeyMethod *method = CRYPT_EAL_PkeyFindMethod(id);
if (method == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, id, CRYPT_EAL_ERR_ALGID);
return NULL;
}
CRYPT_EAL_PkeyCtx *pkey = BSL_SAL_Calloc(1, sizeof(CRYPT_EAL_PkeyCtx));
if (pkey == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, id, CRYPT_MEM_ALLOC_FAIL);
return NULL;
}
EalPkeyCopyMethod(method, &pkey->method);
pkey->key = pkey->method.newCtx();
if (pkey->key == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, id, CRYPT_MEM_ALLOC_FAIL);
BSL_SAL_Free(pkey);
return NULL;
}
pkey->id = id;
BSL_SAL_ReferencesInit(&(pkey->references));
return pkey;
}
CRYPT_EAL_PkeyCtx *CRYPT_EAL_PkeyNewCtx(CRYPT_PKEY_AlgId id)
{
#ifdef HITLS_CRYPTO_ASM_CHECK
if (CRYPT_ASMCAP_Pkey(id) != CRYPT_SUCCESS) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, id, CRYPT_EAL_ALG_ASM_NOT_SUPPORT);
return NULL;
}
#endif
return PkeyNewDefaultCtx(id);
}
static int32_t PkeyCopyCtx(CRYPT_EAL_PkeyCtx *to, const CRYPT_EAL_PkeyCtx *from)
{
if (from->method.dupCtx == NULL || from->method.freeCtx == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, from->id, CRYPT_EAL_ALG_NOT_SUPPORT);
return CRYPT_EAL_ALG_NOT_SUPPORT;
}
void *newKey = from->method.dupCtx(from->key);
if (newKey == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, from->id, CRYPT_EAL_PKEY_DUP_ERROR);
return CRYPT_EAL_PKEY_DUP_ERROR;
}
BSL_SAL_ReferencesFree(&(to->references));
if (to->key != NULL) {
to->method.freeCtx(to->key);
}
memcpy(to, from, sizeof(CRYPT_EAL_PkeyCtx));
to->key = newKey;
BSL_SAL_ReferencesInit(&(to->references));
return CRYPT_SUCCESS;
}
int32_t CRYPT_EAL_PkeyCopyCtx(CRYPT_EAL_PkeyCtx *to, const CRYPT_EAL_PkeyCtx *from)
{
if (to == NULL || from == NULL) {
BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
if (to == from) {
BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
return CRYPT_INVALID_ARG;
}
if (to->key != NULL) {
if (to->method.freeCtx == NULL) {
BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
return CRYPT_INVALID_ARG;
}
}
return PkeyCopyCtx(to, from);
}
CRYPT_EAL_PkeyCtx *CRYPT_EAL_PkeyDupCtx(const CRYPT_EAL_PkeyCtx *pkey)
{
if (pkey == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, CRYPT_PKEY_MAX, CRYPT_NULL_INPUT);
return NULL;
}
CRYPT_EAL_PkeyCtx *newPkey = BSL_SAL_Calloc(1, sizeof(CRYPT_EAL_PkeyCtx));
if (newPkey == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, CRYPT_MEM_ALLOC_FAIL);
return NULL;
}
if (PkeyCopyCtx(newPkey, pkey) != CRYPT_SUCCESS) {
BSL_SAL_FREE(newPkey);
return NULL;
}
return newPkey;
}
void CRYPT_EAL_PkeyFreeCtx(CRYPT_EAL_PkeyCtx *pkey)
{
if (pkey == NULL) {
return;
}
int ref = 0;
BSL_SAL_AtomicDownReferences(&(pkey->references), &ref);
if (ref > 0) {
return;
}
if (pkey->method.freeCtx != NULL) {
pkey->method.freeCtx(pkey->key);
}
BSL_SAL_ReferencesFree(&(pkey->references));
EAL_EVENT_REPORT(CRYPT_EVENT_ZERO, CRYPT_ALGO_PKEY, pkey->id, CRYPT_SUCCESS);
BSL_SAL_Free(pkey);
}
static int32_t ParaIsVaild(const CRYPT_EAL_PkeyCtx *pkey, const CRYPT_EAL_PkeyPara *para)
{
bool isInputValid = (pkey == NULL) || (para == NULL);
if (isInputValid) {
BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
if (pkey->id != para->id) {
BSL_ERR_PUSH_ERROR(CRYPT_EAL_ERR_ALGID);
return CRYPT_EAL_ERR_ALGID;
}
return CRYPT_SUCCESS;
}
int32_t CRYPT_EAL_PkeySetPara(CRYPT_EAL_PkeyCtx *pkey, const CRYPT_EAL_PkeyPara *para)
{
int32_t ret = ParaIsVaild(pkey, para);
if (ret != CRYPT_SUCCESS) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, CRYPT_PKEY_MAX, ret);
return ret;
}
if (pkey->method.setPara == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, CRYPT_EAL_ALG_NOT_SUPPORT);
return CRYPT_EAL_ALG_NOT_SUPPORT;
}
ret = PkeyProviderSetPara(pkey, para);
if (ret != CRYPT_SUCCESS) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, ret);
}
return ret;
}
int32_t CRYPT_EAL_PkeySetParaEx(CRYPT_EAL_PkeyCtx *pkey, const BSL_Param *param)
{
if (pkey == NULL || param == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, CRYPT_PKEY_MAX, CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
if (pkey->method.setPara == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, CRYPT_EAL_ALG_NOT_SUPPORT);
return CRYPT_EAL_ALG_NOT_SUPPORT;
}
int32_t ret = pkey->method.setPara(pkey->key, param);
if (ret != CRYPT_SUCCESS) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, ret);
}
return ret;
}
int32_t CRYPT_EAL_PkeyGetPara(const CRYPT_EAL_PkeyCtx *pkey, CRYPT_EAL_PkeyPara *para)
{
int32_t ret = ParaIsVaild(pkey, para);
if (ret != CRYPT_SUCCESS) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, CRYPT_PKEY_MAX, ret);
return ret;
}
if (pkey->method.getPara == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, CRYPT_EAL_ALG_NOT_SUPPORT);
return CRYPT_EAL_ALG_NOT_SUPPORT;
}
ret = PkeyProviderGetPara(pkey, para);
if (ret != CRYPT_SUCCESS) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, ret);
}
return ret;
}
int32_t CRYPT_EAL_PkeyCtrl(CRYPT_EAL_PkeyCtx *pkey, int32_t opt, void *val, uint32_t len)
{
if (pkey == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, CRYPT_PKEY_MAX, CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
if (pkey->method.ctrl == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, CRYPT_EAL_ALG_NOT_SUPPORT);
return CRYPT_EAL_ALG_NOT_SUPPORT;
}
int32_t ret = pkey->method.ctrl(pkey->key, opt, val, len);
if (ret != CRYPT_SUCCESS) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, ret);
}
return ret;
}
int32_t CRYPT_EAL_PkeySetParaById(CRYPT_EAL_PkeyCtx *pkey, CRYPT_PKEY_ParaId id)
{
int32_t paraId = (int32_t)id;
return CRYPT_EAL_PkeyCtrl(pkey, CRYPT_CTRL_SET_PARA_BY_ID, ¶Id, sizeof(paraId));
}
int32_t CRYPT_EAL_PkeyGen(CRYPT_EAL_PkeyCtx *pkey)
{
if (pkey == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, CRYPT_PKEY_MAX, CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
if (pkey->method.gen == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, CRYPT_EAL_ALG_NOT_SUPPORT);
return CRYPT_EAL_ALG_NOT_SUPPORT;
}
int32_t ret = pkey->method.gen(pkey->key);
if (ret != CRYPT_SUCCESS) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, ret);
return ret;
}
return CRYPT_SUCCESS;
}
static int32_t PriAndPubParamIsValid(const CRYPT_EAL_PkeyCtx *pkey, const void *key, bool isPriKey)
{
bool isInputValid = (pkey == NULL) || (key == NULL);
if (isInputValid) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, CRYPT_PKEY_MAX, CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
CRYPT_PKEY_AlgId id =
isPriKey == true ? ((CRYPT_EAL_PkeyPrv *)(uintptr_t)key)->id : ((CRYPT_EAL_PkeyPub *)(uintptr_t)key)->id;
if (id != pkey->id) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, CRYPT_EAL_ERR_ALGID);
return CRYPT_EAL_ERR_ALGID;
}
return CRYPT_SUCCESS;
}
int32_t CRYPT_EAL_PkeySetPub(CRYPT_EAL_PkeyCtx *pkey, const CRYPT_EAL_PkeyPub *key)
{
int32_t ret = PriAndPubParamIsValid(pkey, key, false);
if (ret != CRYPT_SUCCESS) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, (pkey == NULL) ? CRYPT_PKEY_MAX : pkey->id, ret);
return ret;
}
if (pkey->method.setPub == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, CRYPT_EAL_ALG_NOT_SUPPORT);
return CRYPT_EAL_ALG_NOT_SUPPORT;
}
ret = PkeyProviderSetPub(pkey, key);
EAL_EVENT_REPORT((ret == CRYPT_SUCCESS) ? CRYPT_EVENT_SETSSP : CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, ret);
return ret;
}
int32_t CRYPT_EAL_PkeySetPrv(CRYPT_EAL_PkeyCtx *pkey, const CRYPT_EAL_PkeyPrv *key)
{
int32_t ret = PriAndPubParamIsValid(pkey, key, true);
if (ret != CRYPT_SUCCESS) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, (pkey == NULL) ? CRYPT_PKEY_MAX : pkey->id, ret);
return ret;
}
if (pkey->method.setPrv == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, CRYPT_EAL_ALG_NOT_SUPPORT);
return CRYPT_EAL_ALG_NOT_SUPPORT;
}
ret = PkeyProviderSetPrv(pkey, key);
EAL_EVENT_REPORT((ret == CRYPT_SUCCESS) ? CRYPT_EVENT_SETSSP : CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, ret);
return ret;
}
static int32_t CommonParaGet(const CRYPT_EAL_PkeyCtx *pkey, BSL_Param *param,
int32_t (*getFunc)(const void *key, void *para))
{
if (pkey == NULL || param == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, CRYPT_PKEY_MAX, CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
if (getFunc == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, CRYPT_EAL_ALG_NOT_SUPPORT);
return CRYPT_EAL_ALG_NOT_SUPPORT;
}
int32_t ret = getFunc(pkey->key, param);
if (ret != CRYPT_SUCCESS) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, ret);
}
return ret;
}
static int32_t CommonParaSet(CRYPT_EAL_PkeyCtx *pkey, const BSL_Param *param,
int32_t (*setFunc)(void *key, const void *para))
{
if (pkey == NULL || param == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, CRYPT_PKEY_MAX, CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
if (setFunc == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, CRYPT_EAL_ALG_NOT_SUPPORT);
return CRYPT_EAL_ALG_NOT_SUPPORT;
}
int32_t ret = setFunc(pkey->key, param);
if (ret != CRYPT_SUCCESS) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, ret);
}
return ret;
}
int32_t CRYPT_EAL_PkeyGetPubEx(const CRYPT_EAL_PkeyCtx *pkey, BSL_Param *param)
{
return CommonParaGet(pkey, param, pkey == NULL ? NULL : pkey->method.getPub);
}
int32_t CRYPT_EAL_PkeySetPubEx(CRYPT_EAL_PkeyCtx *pkey, const BSL_Param *param)
{
return CommonParaSet(pkey, param, pkey == NULL ? NULL : pkey->method.setPub);
}
int32_t CRYPT_EAL_PkeyGetPrvEx(const CRYPT_EAL_PkeyCtx *pkey, BSL_Param *param)
{
return CommonParaGet(pkey, param, pkey == NULL ? NULL : pkey->method.getPrv);
}
int32_t CRYPT_EAL_PkeySetPrvEx(CRYPT_EAL_PkeyCtx *pkey, const BSL_Param *param)
{
return CommonParaSet(pkey, param, pkey == NULL ? NULL : pkey->method.setPrv);
}
int32_t CRYPT_EAL_PkeyGetPub(const CRYPT_EAL_PkeyCtx *pkey, CRYPT_EAL_PkeyPub *key)
{
int32_t ret = PriAndPubParamIsValid(pkey, key, false);
if (ret != CRYPT_SUCCESS) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, (pkey == NULL) ? CRYPT_PKEY_MAX : pkey->id, ret);
return ret;
}
if (pkey->method.getPub == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, CRYPT_EAL_ALG_NOT_SUPPORT);
return CRYPT_EAL_ALG_NOT_SUPPORT;
}
ret = PkeyProviderGetPub(pkey, key);
EAL_EVENT_REPORT((ret == CRYPT_SUCCESS) ? CRYPT_EVENT_GETSSP : CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, ret);
return ret;
}
int32_t CRYPT_EAL_PkeyGetPrv(const CRYPT_EAL_PkeyCtx *pkey, CRYPT_EAL_PkeyPrv *key)
{
int32_t ret = PriAndPubParamIsValid(pkey, key, true);
if (ret != CRYPT_SUCCESS) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, (pkey == NULL) ? CRYPT_PKEY_MAX : pkey->id, ret);
return ret;
}
if (pkey->method.getPrv == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, CRYPT_EAL_ALG_NOT_SUPPORT);
return CRYPT_EAL_ALG_NOT_SUPPORT;
}
ret = PkeyProviderGetPrv(pkey, key);
EAL_EVENT_REPORT((ret == CRYPT_SUCCESS) ? CRYPT_EVENT_GETSSP : CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, pkey->id, ret);
return ret;
}
uint32_t CRYPT_EAL_PkeyGetSignLen(const CRYPT_EAL_PkeyCtx *pkey)
{
int32_t result = 0;
int32_t ret = CRYPT_EAL_PkeyCtrl((CRYPT_EAL_PkeyCtx *)(uintptr_t)pkey,
CRYPT_CTRL_GET_SIGNLEN, &result, sizeof(result));
return ret == CRYPT_SUCCESS ? result : 0;
}
uint32_t CRYPT_EAL_PkeyGetKeyLen(const CRYPT_EAL_PkeyCtx *pkey)
{
int32_t result = 0;
int32_t ret = CRYPT_EAL_PkeyCtrl((CRYPT_EAL_PkeyCtx *)(uintptr_t)pkey,
CRYPT_CTRL_GET_BITS, &result, sizeof(result));
return ret == CRYPT_SUCCESS ? ((result + 7) >> 3) : 0;
}
uint32_t CRYPT_EAL_PkeyGetKeyBits(const CRYPT_EAL_PkeyCtx *pkey)
{
int32_t result = 0;
int32_t ret = CRYPT_EAL_PkeyCtrl((CRYPT_EAL_PkeyCtx *)(uintptr_t)pkey,
CRYPT_CTRL_GET_BITS, &result, sizeof(result));
return ret == CRYPT_SUCCESS ? result : 0;
}
uint32_t CRYPT_EAL_PkeyGetSecurityBits(const CRYPT_EAL_PkeyCtx *pkey)
{
int32_t result = 0;
int32_t ret = CRYPT_EAL_PkeyCtrl((CRYPT_EAL_PkeyCtx *)(uintptr_t)pkey,
CRYPT_CTRL_GET_SECBITS, &result, sizeof(result));
return ret == CRYPT_SUCCESS ? result : 0;
}
CRYPT_PKEY_AlgId CRYPT_EAL_PkeyGetId(const CRYPT_EAL_PkeyCtx *pkey)
{
if (pkey == NULL) {
return CRYPT_PKEY_MAX;
}
return pkey->id;
}
CRYPT_PKEY_ParaId CRYPT_EAL_PkeyGetParaId(const CRYPT_EAL_PkeyCtx *pkey)
{
int32_t result = 0;
int32_t ret = CRYPT_EAL_PkeyCtrl((CRYPT_EAL_PkeyCtx *)(uintptr_t)pkey, CRYPT_CTRL_GET_PARAID,
&result, sizeof(result));
return ret == CRYPT_SUCCESS ? result : CRYPT_PKEY_PARAID_MAX;
}
int32_t CRYPT_EAL_PkeyCmp(const CRYPT_EAL_PkeyCtx *a, const CRYPT_EAL_PkeyCtx *b)
{
if (a == NULL || b == NULL) {
if (a == b) {
return CRYPT_SUCCESS;
}
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, CRYPT_PKEY_MAX, CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
if (a->id != b->id) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, CRYPT_PKEY_MAX, CRYPT_EAL_PKEY_CMP_DIFF_KEY_TYPE);
return CRYPT_EAL_PKEY_CMP_DIFF_KEY_TYPE;
}
if (a->method.cmp == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, a->id, CRYPT_EAL_ALG_NOT_SUPPORT);
return CRYPT_EAL_ALG_NOT_SUPPORT;
}
return a->method.cmp(a->key, b->key);
}
int32_t CRYPT_EAL_PkeySetExtData(CRYPT_EAL_PkeyCtx *pkey, void *data)
{
if (pkey == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, CRYPT_PKEY_MAX, CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
pkey->extData = data;
return CRYPT_SUCCESS;
}
void *CRYPT_EAL_PkeyGetExtData(const CRYPT_EAL_PkeyCtx *pkey)
{
if (pkey == NULL) {
return NULL;
}
return pkey->extData;
}
bool CRYPT_EAL_PkeyIsValidAlgId(CRYPT_PKEY_AlgId id)
{
return CRYPT_EAL_PkeyFindMethod(id) != NULL;
}
int32_t CRYPT_EAL_PkeyUpRef(CRYPT_EAL_PkeyCtx *pkey)
{
int i = 0;
if (pkey == NULL) {
return CRYPT_NULL_INPUT;
}
return BSL_SAL_AtomicUpReferences(&(pkey->references), &i);
}
#ifdef HITLS_CRYPTO_PROVIDER
typedef struct {
int32_t id;
size_t offset;
} IdToOffset;
static int32_t CRYPT_EAL_SetKeyMethod(const CRYPT_EAL_Func *funcsKeyMgmt, EAL_PkeyUnitaryMethod *method)
{
if (funcsKeyMgmt != NULL) {
static const IdToOffset ID_MAP[] = {
{CRYPT_EAL_IMPLPKEYMGMT_NEWCTX, offsetof(EAL_PkeyUnitaryMethod, provNewCtx)},
{CRYPT_EAL_IMPLPKEYMGMT_SETPARAM, offsetof(EAL_PkeyUnitaryMethod, setPara)},
{CRYPT_EAL_IMPLPKEYMGMT_GETPARAM, offsetof(EAL_PkeyUnitaryMethod, getPara)},
{CRYPT_EAL_IMPLPKEYMGMT_GENKEY, offsetof(EAL_PkeyUnitaryMethod, gen)},
{CRYPT_EAL_IMPLPKEYMGMT_SETPRV, offsetof(EAL_PkeyUnitaryMethod, setPrv)},
{CRYPT_EAL_IMPLPKEYMGMT_SETPUB, offsetof(EAL_PkeyUnitaryMethod, setPub)},
{CRYPT_EAL_IMPLPKEYMGMT_GETPRV, offsetof(EAL_PkeyUnitaryMethod, getPrv)},
{CRYPT_EAL_IMPLPKEYMGMT_GETPUB, offsetof(EAL_PkeyUnitaryMethod, getPub)},
{CRYPT_EAL_IMPLPKEYMGMT_DUPCTX, offsetof(EAL_PkeyUnitaryMethod, dupCtx)},
{CRYPT_EAL_IMPLPKEYMGMT_CHECK, offsetof(EAL_PkeyUnitaryMethod, check)},
{CRYPT_EAL_IMPLPKEYMGMT_COMPARE, offsetof(EAL_PkeyUnitaryMethod, cmp)},
{CRYPT_EAL_IMPLPKEYMGMT_CTRL, offsetof(EAL_PkeyUnitaryMethod, ctrl)},
{CRYPT_EAL_IMPLPKEYMGMT_FREECTX, offsetof(EAL_PkeyUnitaryMethod, freeCtx)},
{CRYPT_EAL_IMPLPKEYMGMT_IMPORT, offsetof(EAL_PkeyUnitaryMethod, import)},
{CRYPT_EAL_IMPLPKEYMGMT_EXPORT, offsetof(EAL_PkeyUnitaryMethod, export)},
{0, 0}
};
for (int32_t i = 0; funcsKeyMgmt[i].id != 0; i++) {
const IdToOffset *entry = ID_MAP;
while (entry->id != 0 && entry->id != funcsKeyMgmt[i].id) {
entry++;
}
if (entry->id == 0) {
BSL_ERR_PUSH_ERROR(CRYPT_PROVIDER_ERR_UNEXPECTED_IMPL);
return CRYPT_PROVIDER_ERR_UNEXPECTED_IMPL;
}
void (**member)(void) = (void (**)(void))((uint8_t*)method + entry->offset);
*member = funcsKeyMgmt[i].func;
}
}
return CRYPT_SUCCESS;
}
#ifdef HITLS_CRYPTO_PKEY_CRYPT
static int32_t CRYPT_EAL_SetCipherMethod(const CRYPT_EAL_Func *funcsAsyCipher, EAL_PkeyUnitaryMethod *method)
{
int32_t index = 0;
if (funcsAsyCipher != NULL) {
while (funcsAsyCipher[index].id != 0) {
switch (funcsAsyCipher[index].id) {
case CRYPT_EAL_IMPLPKEYCIPHER_ENCRYPT:
method->encrypt = funcsAsyCipher[index].func;
break;
case CRYPT_EAL_IMPLPKEYCIPHER_DECRYPT:
method->decrypt = funcsAsyCipher[index].func;
break;
case CRYPT_EAL_IMPLPKEYCIPHER_HEADD:
method->headd = funcsAsyCipher[index].func;
break;
case CRYPT_EAL_IMPLPKEYCIPHER_HEMUL:
method->hemul = funcsAsyCipher[index].func;
break;
default:
BSL_ERR_PUSH_ERROR(CRYPT_PROVIDER_ERR_UNEXPECTED_IMPL);
return CRYPT_PROVIDER_ERR_UNEXPECTED_IMPL;
}
index++;
}
}
return CRYPT_SUCCESS;
}
#endif
#ifdef HITLS_CRYPTO_PKEY_EXCH
static int32_t CRYPT_EAL_SetExchMethod(const CRYPT_EAL_Func *funcsExch, EAL_PkeyUnitaryMethod *method)
{
int32_t index = 0;
if (funcsExch != NULL) {
while (funcsExch[index].id != 0) {
switch (funcsExch[index].id) {
case CRYPT_EAL_IMPLPKEYEXCH_EXCH:
method->computeShareKey = funcsExch[index].func;
break;
default:
BSL_ERR_PUSH_ERROR(CRYPT_PROVIDER_ERR_UNEXPECTED_IMPL);
return CRYPT_PROVIDER_ERR_UNEXPECTED_IMPL;
}
index++;
}
}
return CRYPT_SUCCESS;
}
#endif
#ifdef HITLS_CRYPTO_PKEY_SIGN
static int32_t CRYPT_EAL_SetSignMethod(const CRYPT_EAL_Func *funcSign, EAL_PkeyUnitaryMethod *method)
{
int32_t index = 0;
if (funcSign != NULL) {
while (funcSign[index].id != 0) {
switch (funcSign[index].id) {
case CRYPT_EAL_IMPLPKEYSIGN_SIGN:
method->sign = funcSign[index].func;
break;
case CRYPT_EAL_IMPLPKEYSIGN_SIGNDATA:
method->signData = funcSign[index].func;
break;
case CRYPT_EAL_IMPLPKEYSIGN_VERIFY:
method->verify = funcSign[index].func;
break;
case CRYPT_EAL_IMPLPKEYSIGN_VERIFYDATA:
method->verifyData = funcSign[index].func;
break;
case CRYPT_EAL_IMPLPKEYSIGN_BLIND:
method->blind = funcSign[index].func;
break;
case CRYPT_EAL_IMPLPKEYSIGN_UNBLIND:
method->unBlind = funcSign[index].func;
break;
case CRYPT_EAL_IMPLPKEYSIGN_RECOVER:
method->recover = funcSign[index].func;
break;
default:
BSL_ERR_PUSH_ERROR(CRYPT_PROVIDER_ERR_UNEXPECTED_IMPL);
return CRYPT_PROVIDER_ERR_UNEXPECTED_IMPL;
}
index++;
}
}
return CRYPT_SUCCESS;
}
#endif
#ifdef HITLS_CRYPTO_PKEY_KEM
static int32_t CRYPT_EAL_SetKemMethod(const CRYPT_EAL_Func *funcKem, EAL_PkeyUnitaryMethod *method)
{
int32_t index = 0;
if (funcKem != NULL) {
while (funcKem[index].id != 0) {
switch (funcKem[index].id) {
case CRYPT_EAL_IMPLPKEYKEM_ENCAPSULATE_INIT:
method->encapsInit = funcKem[index].func;
break;
case CRYPT_EAL_IMPLPKEYKEM_DECAPSULATE_INIT:
method->decapsInit = funcKem[index].func;
break;
case CRYPT_EAL_IMPLPKEYKEM_ENCAPSULATE:
method->pkeyEncaps = funcKem[index].func;
break;
case CRYPT_EAL_IMPLPKEYKEM_DECAPSULATE:
method->pkeyDecaps = funcKem[index].func;
break;
default:
BSL_ERR_PUSH_ERROR(CRYPT_PROVIDER_ERR_UNEXPECTED_IMPL);
return CRYPT_PROVIDER_ERR_UNEXPECTED_IMPL;
}
index++;
}
}
return CRYPT_SUCCESS;
}
#endif
int32_t CRYPT_EAL_SetPkeyMethod(EAL_PkeyUnitaryMethod *method, const CRYPT_EAL_AsyAlgFuncsInfo *funcs)
{
int32_t ret = CRYPT_EAL_SetKeyMethod(funcs->funcsKeyMgmt, method);
if (ret != CRYPT_SUCCESS) {
return ret;
}
#ifdef HITLS_CRYPTO_PKEY_CRYPT
ret = CRYPT_EAL_SetCipherMethod(funcs->funcsAsyCipher, method);
if (ret != CRYPT_SUCCESS) {
return ret;
}
#endif
#ifdef HITLS_CRYPTO_PKEY_EXCH
ret = CRYPT_EAL_SetExchMethod(funcs->funcsExch, method);
if (ret != CRYPT_SUCCESS) {
return ret;
}
#endif
#ifdef HITLS_CRYPTO_PKEY_SIGN
ret = CRYPT_EAL_SetSignMethod(funcs->funcSign, method);
if (ret != CRYPT_SUCCESS) {
return ret;
}
#endif
#ifdef HITLS_CRYPTO_PKEY_KEM
ret = CRYPT_EAL_SetKemMethod(funcs->funcKem, method);
#endif
return ret;
}
static int32_t ProviderGetTargetFuncs(CRYPT_EAL_LibCtx *libCtx, int32_t operaId, int32_t algId,
const char *attrName, const CRYPT_EAL_Func **funcs, CRYPT_EAL_ProvMgrCtx **mgrCtx)
{
int32_t ret = CRYPT_EAL_ProviderGetFuncsAndMgrCtx(libCtx, operaId, algId, attrName, funcs, mgrCtx, true);
return ret == CRYPT_NOT_SUPPORT ? CRYPT_SUCCESS : ret;
}
int32_t CRYPT_EAL_ProviderGetAsyAlgFuncs(CRYPT_EAL_LibCtx *libCtx, int32_t algId, uint32_t pkeyOperType,
const char *attrName, CRYPT_EAL_AsyAlgFuncsInfo *funcs)
{
int32_t ret = CRYPT_PROVIDER_NOT_SUPPORT;
if (pkeyOperType == CRYPT_EAL_PKEY_UNKNOWN_OPERATE) {
#ifdef HITLS_CRYPTO_PKEY_CRYPT
RETURN_RET_IF_ERR(ProviderGetTargetFuncs(libCtx, CRYPT_EAL_OPERAID_ASYMCIPHER, algId,
attrName, &funcs->funcsAsyCipher, &funcs->mgrCtx), ret);
#endif
#ifdef HITLS_CRYPTO_PKEY_EXCH
RETURN_RET_IF_ERR(ProviderGetTargetFuncs(libCtx, CRYPT_EAL_OPERAID_KEYEXCH, algId,
attrName, &funcs->funcsExch, &funcs->mgrCtx), ret);
#endif
#ifdef HITLS_CRYPTO_PKEY_SIGN
RETURN_RET_IF_ERR(ProviderGetTargetFuncs(libCtx, CRYPT_EAL_OPERAID_SIGN, algId,
attrName, &funcs->funcSign, &funcs->mgrCtx), ret);
#endif
#ifdef HITLS_CRYPTO_PKEY_KEM
RETURN_RET_IF_ERR(ProviderGetTargetFuncs(libCtx, CRYPT_EAL_OPERAID_KEM, algId,
attrName, &funcs->funcKem, &funcs->mgrCtx), ret);
#endif
}
#ifdef HITLS_CRYPTO_PKEY_CRYPT
if ((pkeyOperType & CRYPT_EAL_PKEY_CIPHER_OPERATE) == CRYPT_EAL_PKEY_CIPHER_OPERATE) {
ret = CRYPT_EAL_ProviderGetFuncsAndMgrCtx(libCtx, CRYPT_EAL_OPERAID_ASYMCIPHER, algId, attrName,
&funcs->funcsAsyCipher, &funcs->mgrCtx, false);
if (ret != CRYPT_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
return ret;
}
}
#endif
#ifdef HITLS_CRYPTO_PKEY_EXCH
if ((pkeyOperType & CRYPT_EAL_PKEY_EXCH_OPERATE) == CRYPT_EAL_PKEY_EXCH_OPERATE) {
ret = CRYPT_EAL_ProviderGetFuncsAndMgrCtx(libCtx, CRYPT_EAL_OPERAID_KEYEXCH, algId, attrName,
&funcs->funcsExch, &funcs->mgrCtx, false);
if (ret != CRYPT_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
return ret;
}
}
#endif
#ifdef HITLS_CRYPTO_PKEY_SIGN
if ((pkeyOperType & CRYPT_EAL_PKEY_SIGN_OPERATE) == CRYPT_EAL_PKEY_SIGN_OPERATE) {
ret = CRYPT_EAL_ProviderGetFuncsAndMgrCtx(libCtx, CRYPT_EAL_OPERAID_SIGN, algId, attrName,
&funcs->funcSign, &funcs->mgrCtx, false);
if (ret != CRYPT_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
return ret;
}
}
#endif
#ifdef HITLS_CRYPTO_PKEY_KEM
if ((pkeyOperType & CRYPT_EAL_PKEY_KEM_OPERATE) == CRYPT_EAL_PKEY_KEM_OPERATE) {
ret = CRYPT_EAL_ProviderGetFuncsAndMgrCtx(libCtx, CRYPT_EAL_OPERAID_KEM, algId, attrName,
&funcs->funcKem, &funcs->mgrCtx, false);
if (ret != CRYPT_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
return ret;
}
}
#endif
ret = CRYPT_EAL_ProviderGetFuncsAndMgrCtx(libCtx, CRYPT_EAL_OPERAID_KEYMGMT, algId, attrName,
&funcs->funcsKeyMgmt, &funcs->mgrCtx, false);
if (ret != CRYPT_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
}
return ret;
}
CRYPT_EAL_PkeyCtx *CRYPT_EAL_ProviderPkeyNewCtxInner(CRYPT_EAL_LibCtx *libCtx, int32_t algId, uint32_t pkeyOperType,
const char *attrName)
{
void *provCtx = NULL;
CRYPT_EAL_AsyAlgFuncsInfo funcInfo = {NULL, NULL, NULL, NULL, NULL, NULL};
int32_t ret = CRYPT_EAL_ProviderGetAsyAlgFuncs(libCtx, algId, pkeyOperType, attrName, &funcInfo);
if (ret != CRYPT_SUCCESS) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, algId, ret);
return NULL;
}
ret = CRYPT_EAL_ProviderCtrl(funcInfo.mgrCtx, CRYPT_PROVIDER_GET_USER_CTX, &provCtx, sizeof(provCtx));
if (ret != CRYPT_SUCCESS) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, algId, ret);
return NULL;
}
CRYPT_EAL_PkeyCtx *ctx = BSL_SAL_Calloc(1u, sizeof(CRYPT_EAL_PkeyCtx));
if (ctx == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, algId, CRYPT_MEM_ALLOC_FAIL);
return NULL;
}
GOTO_ERR_IF(CRYPT_EAL_SetPkeyMethod(&(ctx->method), &funcInfo), ret);
if (ctx->method.provNewCtx == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, algId, CRYPT_PROVIDER_ERR_IMPL_NULL);
goto ERR;
}
ctx->key = ctx->method.provNewCtx(provCtx, algId);
if (ctx->key == NULL) {
EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_PKEY, algId, CRYPT_MEM_ALLOC_FAIL);
goto ERR;
}
ctx->isProvider = true;
ctx->id = algId;
BSL_SAL_ReferencesInit(&(ctx->references));
return ctx;
ERR:
BSL_SAL_Free(ctx);
return NULL;
}
#endif
CRYPT_EAL_PkeyCtx *CRYPT_EAL_ProviderPkeyNewCtx(CRYPT_EAL_LibCtx *libCtx, int32_t algId, uint32_t pkeyOperType,
const char *attrName)
{
#ifdef HITLS_CRYPTO_PROVIDER
return CRYPT_EAL_ProviderPkeyNewCtxInner(libCtx, algId, pkeyOperType, attrName);
#else
(void)libCtx;
(void)pkeyOperType;
(void)attrName;
return CRYPT_EAL_PkeyNewCtx(algId);
#endif
}
#endif