* 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_CODECS) && defined(HITLS_CRYPTO_PROVIDER)
#include <string.h>
#include "bsl_sal.h"
#include "bsl_list.h"
#include "bsl_err_internal.h"
#include "crypt_errno.h"
#include "crypt_eal_provider.h"
#include "crypt_eal_implprovider.h"
#include "crypt_provider.h"
#include "crypt_eal_pkey.h"
#include "crypt_eal_codecs.h"
#include "bsl_types.h"
#include "bsl_params.h"
#include "crypt_params_key.h"
#include "crypt_types.h"
#include "crypt_utils.h"
#include "decode_local.h"
int32_t CRYPT_DECODE_ParseDecoderAttr(const char *attrName, DECODER_AttrInfo *info)
{
char *rest = NULL;
info->inFormat = NULL;
info->inType = NULL;
info->outFormat = NULL;
info->outType = NULL;
info->attrName = (char *)BSL_SAL_Dump(attrName, (uint32_t)strlen(attrName) + 1);
if (info->attrName == NULL) {
BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
return CRYPT_MEM_ALLOC_FAIL;
}
char *token = strtok_r(info->attrName, ",", &rest);
while (token != NULL) {
while (*token == ' ') {
token++;
}
if (strstr(token, "inFormat=") == token) {
info->inFormat = token + strlen("inFormat=");
} else if (strstr(token, "inType=") == token) {
info->inType = token + strlen("inType=");
} else if (strstr(token, "outFormat=") == token) {
info->outFormat = token + strlen("outFormat=");
} else if (strstr(token, "outType=") == token) {
info->outType = token + strlen("outType=");
}
token = strtok_r(NULL, ",", &rest);
}
return CRYPT_SUCCESS;
}
static int32_t SetDecoderMethod(CRYPT_DECODER_Ctx *ctx, const CRYPT_EAL_Func *funcs)
{
int32_t index = 0;
CRYPT_DECODER_Method *method = BSL_SAL_Calloc(1, sizeof(CRYPT_DECODER_Method));
if (method == NULL) {
BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
return CRYPT_MEM_ALLOC_FAIL;
}
while (funcs[index].func != NULL) {
switch (funcs[index].id) {
case CRYPT_DECODER_IMPL_NEWCTX:
method->newCtx = (CRYPT_DECODER_IMPL_NewCtx)funcs[index].func;
break;
case CRYPT_DECODER_IMPL_SETPARAM:
method->setParam = (CRYPT_DECODER_IMPL_SetParam)funcs[index].func;
break;
case CRYPT_DECODER_IMPL_GETPARAM:
method->getParam = (CRYPT_DECODER_IMPL_GetParam)funcs[index].func;
break;
case CRYPT_DECODER_IMPL_DECODE:
method->decode = (CRYPT_DECODER_IMPL_Decode)funcs[index].func;
break;
case CRYPT_DECODER_IMPL_FREEOUTDATA:
method->freeOutData = (CRYPT_DECODER_IMPL_FreeOutData)funcs[index].func;
break;
case CRYPT_DECODER_IMPL_FREECTX:
method->freeCtx = (CRYPT_DECODER_IMPL_FreeCtx)funcs[index].func;
break;
default:
BSL_SAL_Free(method);
BSL_ERR_PUSH_ERROR(CRYPT_PROVIDER_ERR_UNEXPECTED_IMPL);
return CRYPT_PROVIDER_ERR_UNEXPECTED_IMPL;
}
index++;
}
ctx->method = method;
return CRYPT_SUCCESS;
}
CRYPT_DECODER_Ctx *CRYPT_DECODE_NewDecoderCtxByMethod(const CRYPT_EAL_Func *funcs, CRYPT_EAL_ProvMgrCtx *mgrCtx,
const char *attrName)
{
void *provCtx = NULL;
DECODER_AttrInfo attrInfo = {0};
CRYPT_DECODER_Ctx *ctx = BSL_SAL_Calloc(1, sizeof(CRYPT_DECODER_Ctx));
if (ctx == NULL) {
BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
return NULL;
}
int32_t ret = CRYPT_EAL_ProviderCtrl(mgrCtx, CRYPT_PROVIDER_GET_USER_CTX, &provCtx, sizeof(provCtx));
if (ret != CRYPT_SUCCESS) {
goto ERR;
}
ret = SetDecoderMethod(ctx, funcs);
if (ret != CRYPT_SUCCESS) {
goto ERR;
}
if (ctx->method->newCtx == NULL || ctx->method->setParam == NULL) {
BSL_ERR_PUSH_ERROR(CRYPT_NOT_SUPPORT);
goto ERR;
}
ctx->decoderCtx = ctx->method->newCtx(provCtx);
if (ctx->decoderCtx == NULL) {
BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
goto ERR;
}
BSL_Param param[2] = {{CRYPT_PARAM_DECODE_PROVIDER_CTX, BSL_PARAM_TYPE_CTX_PTR, mgrCtx, 0, 0},
BSL_PARAM_END};
ret = ctx->method->setParam(ctx->decoderCtx, param);
if (ret != CRYPT_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
goto ERR;
}
if (attrName != NULL) {
ret = CRYPT_DECODE_ParseDecoderAttr(attrName, &attrInfo);
if (ret != CRYPT_SUCCESS) {
goto ERR;
}
}
ctx->providerMgrCtx = mgrCtx;
ctx->inFormat = attrInfo.inFormat;
ctx->inType = attrInfo.inType;
ctx->outFormat = attrInfo.outFormat;
ctx->outType = attrInfo.outType;
ctx->attrName = attrName != NULL ? attrInfo.attrName : NULL;
ctx->decoderState = CRYPT_DECODER_STATE_UNTRIED;
return ctx;
ERR:
CRYPT_DECODE_Free(ctx);
return NULL;
}
CRYPT_DECODER_Ctx *CRYPT_DECODE_ProviderNewCtx(CRYPT_EAL_LibCtx *libCtx, int32_t pkeyAlgId, const char *attrName)
{
const CRYPT_EAL_Func *funcsDecoder = NULL;
CRYPT_EAL_ProvMgrCtx *mgrCtx = NULL;
int32_t ret = CRYPT_EAL_ProviderGetFuncsAndMgrCtx(libCtx, CRYPT_EAL_OPERAID_DECODER, pkeyAlgId, attrName,
&funcsDecoder, &mgrCtx, false);
if (ret != CRYPT_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
return NULL;
}
if (mgrCtx == NULL) {
BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
return NULL;
}
return CRYPT_DECODE_NewDecoderCtxByMethod(funcsDecoder, mgrCtx, attrName);
}
void CRYPT_DECODE_Free(CRYPT_DECODER_Ctx *ctx)
{
if (ctx == NULL) {
return;
}
if (ctx->method != NULL && ctx->method->freeCtx != NULL) {
ctx->method->freeCtx(ctx->decoderCtx);
}
BSL_SAL_Free(ctx->method);
BSL_SAL_Free(ctx->attrName);
BSL_SAL_Free(ctx);
}
int32_t CRYPT_DECODE_SetParam(CRYPT_DECODER_Ctx *ctx, const BSL_Param *param)
{
if (ctx == NULL || param == NULL) {
BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
if (ctx->method == NULL || ctx->method->setParam == NULL) {
BSL_ERR_PUSH_ERROR(CRYPT_NOT_SUPPORT);
return CRYPT_NOT_SUPPORT;
}
return ctx->method->setParam(ctx->decoderCtx, param);
}
int32_t CRYPT_DECODE_GetParam(CRYPT_DECODER_Ctx *ctx, BSL_Param *param)
{
if (ctx == NULL || param == NULL) {
BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
if (ctx->method == NULL || ctx->method->getParam == NULL) {
BSL_ERR_PUSH_ERROR(CRYPT_NOT_SUPPORT);
return CRYPT_NOT_SUPPORT;
}
return ctx->method->getParam(ctx->decoderCtx, param);
}
int32_t CRYPT_DECODE_Decode(CRYPT_DECODER_Ctx *ctx, const BSL_Param *inParam, BSL_Param **outParam)
{
if (ctx == NULL || inParam == NULL || outParam == NULL) {
BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
return CRYPT_NULL_INPUT;
}
if (ctx->method == NULL || ctx->method->decode == NULL) {
BSL_ERR_PUSH_ERROR(CRYPT_NOT_SUPPORT);
return CRYPT_NOT_SUPPORT;
}
int32_t ret = ctx->method->decode(ctx->decoderCtx, inParam, outParam);
if (ret != CRYPT_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
}
return ret;
}
void CRYPT_DECODE_FreeOutData(CRYPT_DECODER_Ctx *ctx, BSL_Param *outData)
{
if (ctx == NULL || outData == NULL || ctx->method == NULL || ctx->method->freeOutData == NULL) {
return;
}
ctx->method->freeOutData(ctx->decoderCtx, outData);
}
#endif