* 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 <stddef.h>
#include "hitls_build.h"
#include <string.h>
#include "tls_binlog_id.h"
#include "bsl_log_internal.h"
#include "bsl_log.h"
#include "bsl_err_internal.h"
#include "hitls_error.h"
#include "hitls_cert_reg.h"
#include "hitls_x509_adapt.h"
#ifdef HITLS_TLS_FEATURE_PROVIDER
#include "hitls_pki_x509.h"
#endif
#include "tls_config.h"
#include "tls.h"
#include "cert.h"
#include "cert_mgr.h"
#include "cert_method.h"
#ifndef HITLS_TLS_FEATURE_PROVIDER
HITLS_CERT_MgrMethod g_certMgrMethod = {0};
static bool IsMethodValid(const HITLS_CERT_MgrMethod *method)
{
bool valid = method == NULL ||
method->certStoreNew == NULL ||
method->certStoreDup == NULL ||
method->certStoreFree == NULL ||
method->certStoreCtrl == NULL ||
method->buildCertChain == NULL ||
method->verifyCertChain == NULL ||
method->certEncode == NULL ||
method->certParse == NULL ||
method->certDup == NULL ||
method->certFree == NULL ||
method->certCtrl == NULL ||
method->keyParse == NULL ||
method->keyDup == NULL ||
method->keyFree == NULL ||
method->keyCtrl == NULL ||
method->createSign == NULL ||
method->verifySign == NULL ||
method->checkPrivateKey == NULL;
if (valid) {
return false;
}
return true;
}
int32_t HITLS_CERT_RegisterMgrMethod(HITLS_CERT_MgrMethod *method)
{
if (IsMethodValid(method) == false) {
BSL_ERR_PUSH_ERROR(HITLS_NULL_INPUT);
return RETURN_ERROR_NUMBER_PROCESS(HITLS_NULL_INPUT, BINLOG_ID16108, "input NULL");
}
memcpy(&g_certMgrMethod, method, sizeof(HITLS_CERT_MgrMethod));
return HITLS_SUCCESS;
}
void HITLS_CERT_DeinitMgrMethod(void)
{
HITLS_CERT_MgrMethod mgr = {0};
memcpy(&g_certMgrMethod, &mgr, sizeof(HITLS_CERT_MgrMethod));
}
HITLS_CERT_MgrMethod *SAL_CERT_GetMgrMethod(void)
{
return &g_certMgrMethod;
}
HITLS_CERT_MgrMethod *HITLS_CERT_GetMgrMethod(void)
{
return SAL_CERT_GetMgrMethod();
}
#endif
int32_t CheckCertCallBackRetVal(
const char *logStr, int32_t callBackRet, uint32_t bingLogId, int32_t hitlsRet, int32_t cmd)
{
#ifndef HITLS_BSL_LOG
(void)logStr;
(void)bingLogId;
#endif
if (callBackRet != HITLS_SUCCESS) {
if (cmd == CERT_KEY_CTRL_IS_KEYENC_USAGE || cmd == CERT_KEY_CTRL_IS_DATA_ENC_USAGE ||
cmd == CERT_KEY_CTRL_IS_KEY_AGREEMENT_USAGE) {
return hitlsRet;
}
BSL_LOG_BINLOG_FIXLEN(bingLogId, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"%s cmd %d error: callback ret = 0x%x.", logStr != NULL ? logStr : "", cmd, callBackRet, 0);
BSL_ERR_PUSH_ERROR(hitlsRet);
return hitlsRet;
}
return HITLS_SUCCESS;
}
HITLS_CERT_Store *SAL_CERT_StoreNew(const CERT_MgrCtx *mgrCtx)
{
#ifdef HITLS_TLS_FEATURE_PROVIDER
return HITLS_X509_ProviderStoreCtxNew(mgrCtx->libCtx, mgrCtx->attrName);
#else
return mgrCtx->method.certStoreNew();
#endif
}
HITLS_CERT_Store *SAL_CERT_StoreDup(const CERT_MgrCtx *mgrCtx, HITLS_CERT_Store *store)
{
#ifdef HITLS_TLS_FEATURE_PROVIDER
(void)mgrCtx;
return HITLS_X509_Adapt_StoreDup(store);
#else
return mgrCtx->method.certStoreDup(store);
#endif
}
void SAL_CERT_StoreFree(const CERT_MgrCtx *mgrCtx, HITLS_CERT_Store *store)
{
#ifdef HITLS_TLS_FEATURE_PROVIDER
(void)mgrCtx;
return HITLS_X509_StoreCtxFree(store);
#else
mgrCtx->method.certStoreFree(store);
#endif
}
int32_t SAL_CERT_BuildChain(HITLS_Config *config, HITLS_CERT_Store *store, HITLS_CERT_X509 *cert,
HITLS_CERT_X509 **certList, uint32_t *num)
{
int32_t ret;
#ifdef HITLS_TLS_FEATURE_PROVIDER
ret = HITLS_X509_Adapt_BuildCertChain(config, store, cert, certList, num);
#else
ret = config->certMgrCtx->method.buildCertChain(config, store, cert, certList, num);
#endif
return CheckCertCallBackRetVal(
LOG_STR("cert store build chain by cert"), ret, BINLOG_ID16083, HITLS_CERT_ERR_BUILD_CHAIN, CERT_CTRL_BUTT);
}
int32_t SAL_CERT_VerifyChain(HITLS_Ctx *ctx, HITLS_CERT_Store *store, HITLS_CERT_X509 **certList, uint32_t num)
{
int32_t ret;
#ifdef HITLS_TLS_FEATURE_PROVIDER
ret = HITLS_X509_Adapt_VerifyCertChain(ctx, store, certList, num);
#else
ret = ctx->config.tlsConfig.certMgrCtx->method.verifyCertChain(ctx, store, certList, num);
#endif
return CheckCertCallBackRetVal(
LOG_STR("cert store verify chain"), ret, BINLOG_ID16084, HITLS_CERT_ERR_VERIFY_CERT_CHAIN, CERT_CTRL_BUTT);
}
int32_t SAL_CERT_X509Encode(HITLS_Ctx *ctx, HITLS_CERT_X509 *cert, uint8_t *buf, uint32_t len, uint32_t *usedLen)
{
int32_t ret;
#ifdef HITLS_TLS_FEATURE_PROVIDER
ret = HITLS_X509_Adapt_CertEncode(ctx, cert, buf, len, usedLen);
#else
ret = ctx->config.tlsConfig.certMgrCtx->method.certEncode(ctx, cert, buf, len, usedLen);
#endif
return CheckCertCallBackRetVal(
LOG_STR("encode cert"), ret, BINLOG_ID16086, HITLS_CERT_ERR_ENCODE_CERT, CERT_CTRL_BUTT);
}
HITLS_CERT_Chain *SAL_CERT_X509ParseBundleFile(HITLS_Config *config, const uint8_t *buf, uint32_t len,
HITLS_ParseType type, HITLS_ParseFormat format)
{
return HITLS_X509_Adapt_BundleCertParse(LIBCTX_FROM_CONFIG(config),
ATTRIBUTE_FROM_CONFIG(config), buf, len, type, SAL_CERT_GetParseFormatStr(format));
}
HITLS_CERT_X509 *SAL_CERT_X509Parse(HITLS_Lib_Ctx *libCtx, const char *attrName,
HITLS_Config *config, const uint8_t *buf, uint32_t len,
HITLS_ParseType type, HITLS_ParseFormat format)
{
#ifdef HITLS_TLS_FEATURE_PROVIDER
(void)config;
return HITLS_CERT_ProviderCertParse(libCtx, attrName, buf, len, type, SAL_CERT_GetParseFormatStr(format));
#else
(void)libCtx;
(void)attrName;
return config->certMgrCtx->method.certParse(config, buf, len, type, format);
#endif
}
HITLS_CERT_X509 *SAL_CERT_X509Dup(const CERT_MgrCtx *mgrCtx, HITLS_CERT_X509 *cert)
{
#ifdef HITLS_TLS_FEATURE_PROVIDER
(void)mgrCtx;
return (HITLS_CERT_X509 *)HITLS_X509_Adapt_CertDup(cert);
#else
return mgrCtx->method.certDup(cert);
#endif
}
void SAL_CERT_X509Free(HITLS_CERT_X509 *cert)
{
#ifdef HITLS_TLS_FEATURE_PROVIDER
HITLS_X509_CertFree(cert);
#else
if (cert == NULL) {
return;
}
g_certMgrMethod.certFree(cert);
#endif
}
HITLS_CERT_X509 *SAL_CERT_X509Ref(const CERT_MgrCtx *mgrCtx, HITLS_CERT_X509 *cert)
{
#ifdef HITLS_TLS_FEATURE_PROVIDER
(void)mgrCtx;
return HITLS_X509_Adapt_CertRef(cert);
#else
if (mgrCtx->method.certRef == NULL) {
return NULL;
}
return mgrCtx->method.certRef(cert);
#endif
}
typedef struct {
const char *name;
HITLS_ParseFormat format;
} ParseFormatMap;
static const ParseFormatMap PARSE_FORMAT_MAP[] = {
{"PEM", TLS_PARSE_FORMAT_PEM},
{"ASN1", TLS_PARSE_FORMAT_ASN1},
{"PFX_COM", TLS_PARSE_FORMAT_PFX_COM},
{"PKCS12", TLS_PARSE_FORMAT_PKCS12}
};
const char *SAL_CERT_GetParseFormatStr(HITLS_ParseFormat format)
{
for (size_t i = 0; i < sizeof(PARSE_FORMAT_MAP) / sizeof(PARSE_FORMAT_MAP[0]); i++) {
if (PARSE_FORMAT_MAP[i].format == format) {
return PARSE_FORMAT_MAP[i].name;
}
}
return NULL;
}
#ifndef HITLS_TLS_FEATURE_PROVIDER
static HITLS_ParseFormat GetTlsParseFormat(const char *format)
{
if (format == NULL) {
return TLS_PARSE_FORMAT_BUTT;
}
for (size_t i = 0; i < sizeof(PARSE_FORMAT_MAP) / sizeof(PARSE_FORMAT_MAP[0]); i++) {
if (BSL_SAL_StrcaseCmp(format, PARSE_FORMAT_MAP[i].name) == 0) {
return PARSE_FORMAT_MAP[i].format;
}
}
return TLS_PARSE_FORMAT_BUTT;
}
#endif
HITLS_CERT_Key *SAL_CERT_KeyParse(HITLS_Config *config, const uint8_t *buf, uint32_t len,
HITLS_ParseType type, const char *format, const char *encodeType)
{
#ifdef HITLS_TLS_FEATURE_PROVIDER
return HITLS_X509_Adapt_ProviderKeyParse(config, buf, len, type, format, encodeType);
#else
(void)encodeType;
return config->certMgrCtx->method.keyParse(config, buf, len, type, GetTlsParseFormat(format));
#endif
}
HITLS_CERT_Key *SAL_CERT_KeyDup(const CERT_MgrCtx *mgrCtx, HITLS_CERT_Key *key)
{
#ifdef HITLS_TLS_FEATURE_PROVIDER
(void)mgrCtx;
return (HITLS_CERT_Key *)CRYPT_EAL_PkeyDupCtx(key);
#else
return mgrCtx->method.keyDup(key);
#endif
}
void SAL_CERT_KeyFree(const CERT_MgrCtx *mgrCtx, HITLS_CERT_Key *key)
{
#ifdef HITLS_TLS_FEATURE_PROVIDER
(void)mgrCtx;
CRYPT_EAL_PkeyFreeCtx(key);
#else
if (key == NULL) {
return;
}
mgrCtx->method.keyFree(key);
#endif
}
int32_t SAL_CERT_StoreCtrl(HITLS_Config *config, HITLS_CERT_Store *store, HITLS_CERT_CtrlCmd cmd, void *in, void *out)
{
if (cmd > CERT_CTRL_BUTT - 1) {
BSL_ERR_PUSH_ERROR(HITLS_CERT_CTRL_ERR_INVALID_CMD);
return HITLS_CERT_CTRL_ERR_INVALID_CMD;
}
int32_t ret;
#ifdef HITLS_TLS_FEATURE_PROVIDER
ret = HITLS_X509_Adapt_StoreCtrl(config, store, cmd, in, out);
#else
ret = config->certMgrCtx->method.certStoreCtrl(config, store, cmd, in, out);
#endif
return CheckCertCallBackRetVal(LOG_STR("cert store ctrl"), ret, BINLOG_ID16094, ret, cmd);
}
int32_t SAL_CERT_X509Ctrl(HITLS_Config *config, HITLS_CERT_X509 *cert, HITLS_CERT_CtrlCmd cmd, void *in, void *out)
{
if (cert == NULL) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16279, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "input null", 0, 0, 0, 0);
BSL_ERR_PUSH_ERROR(HITLS_NULL_INPUT);
return HITLS_NULL_INPUT;
}
if (cmd > CERT_CTRL_BUTT - 1) {
BSL_ERR_PUSH_ERROR(HITLS_CERT_CTRL_ERR_INVALID_CMD);
return HITLS_CERT_CTRL_ERR_INVALID_CMD;
}
int32_t ret;
#ifdef HITLS_TLS_FEATURE_PROVIDER
ret = HITLS_X509_Adapt_CertCtrl(config, cert, cmd, in, out);
#else
ret = config->certMgrCtx->method.certCtrl(config, cert, cmd, in, out);
#endif
return CheckCertCallBackRetVal(LOG_STR("cert ctrl"), ret, BINLOG_ID16096, ret, cmd);
}
int32_t SAL_CERT_KeyCtrl(HITLS_Config *config, HITLS_CERT_Key *key, HITLS_CERT_CtrlCmd cmd, void *in, void *out)
{
if (key == NULL) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16280, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "input null", 0, 0, 0, 0);
BSL_ERR_PUSH_ERROR(HITLS_NULL_INPUT);
return HITLS_NULL_INPUT;
}
if (cmd > CERT_CTRL_BUTT - 1) {
BSL_ERR_PUSH_ERROR(HITLS_CERT_CTRL_ERR_INVALID_CMD);
return HITLS_CERT_CTRL_ERR_INVALID_CMD;
}
int32_t ret;
#ifdef HITLS_TLS_FEATURE_PROVIDER
ret = HITLS_X509_Adapt_KeyCtrl(config, key, cmd, in, out);
#else
ret = config->certMgrCtx->method.keyCtrl(config, key, cmd, in, out);
#endif
return CheckCertCallBackRetVal(LOG_STR("key ctrl"), ret, BINLOG_ID16098, ret, cmd);
}
int32_t SAL_CERT_CreateSign(HITLS_Ctx *ctx, HITLS_CERT_Key *key, CERT_SignParam *signParam)
{
if (key == NULL) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16281, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "input null", 0, 0, 0, 0);
BSL_ERR_PUSH_ERROR(HITLS_NULL_INPUT);
return HITLS_NULL_INPUT;
}
int32_t ret;
#ifdef HITLS_TLS_FEATURE_PROVIDER
ret = HITLS_X509_Adapt_CreateSign(ctx, key, signParam->signAlgo, signParam->hashAlgo, signParam->data,
signParam->dataLen, signParam->sign, &signParam->signLen);
#else
ret = ctx->config.tlsConfig.certMgrCtx->method.createSign(ctx, key, signParam->signAlgo,
signParam->hashAlgo, signParam->data, signParam->dataLen, signParam->sign, &signParam->signLen);
#endif
return CheckCertCallBackRetVal(
LOG_STR("create signature"), ret, BINLOG_ID16103, HITLS_CERT_ERR_CREATE_SIGN, CERT_CTRL_BUTT);
}
int32_t SAL_CERT_VerifySign(HITLS_Ctx *ctx, HITLS_CERT_Key *key, CERT_SignParam *signParam)
{
int32_t ret;
#ifdef HITLS_TLS_FEATURE_PROVIDER
ret = HITLS_X509_Adapt_VerifySign(ctx, key, signParam->signAlgo,
signParam->hashAlgo, signParam->data, signParam->dataLen, signParam->sign, signParam->signLen);
#else
ret = ctx->config.tlsConfig.certMgrCtx->method.verifySign(ctx, key, signParam->signAlgo,
signParam->hashAlgo, signParam->data, signParam->dataLen, signParam->sign, signParam->signLen);
#endif
return CheckCertCallBackRetVal(
LOG_STR("verify signature"), ret, BINLOG_ID16101, HITLS_CERT_ERR_VERIFY_SIGN, CERT_CTRL_BUTT);
}
#if defined(HITLS_TLS_SUITE_KX_RSA) || defined(HITLS_TLS_PROTO_TLCP11)
int32_t SAL_CERT_KeyEncrypt(HITLS_Ctx *ctx, HITLS_CERT_Key *key, const uint8_t *in, uint32_t inLen,
uint8_t *out, uint32_t *outLen)
{
int32_t ret;
#ifdef HITLS_TLS_FEATURE_PROVIDER
ret = HITLS_X509_Adapt_Encrypt(ctx, key, in, inLen, out, outLen);
#else
if (ctx->config.tlsConfig.certMgrCtx->method.encrypt == NULL) {
return RETURN_ERROR_NUMBER_PROCESS(HITLS_UNREGISTERED_CALLBACK, BINLOG_ID15333, "unregistered encrypt");
}
ret = ctx->config.tlsConfig.certMgrCtx->method.encrypt(ctx, key, in, inLen, out, outLen);
#endif
return CheckCertCallBackRetVal(
LOG_STR("pubkey encrypt"), ret, BINLOG_ID15059, HITLS_CERT_ERR_ENCRYPT, CERT_CTRL_BUTT);
}
int32_t SAL_CERT_KeyDecrypt(HITLS_Ctx *ctx, HITLS_CERT_Key *key, const uint8_t *in, uint32_t inLen,
uint8_t *out, uint32_t *outLen)
{
#ifdef HITLS_TLS_FEATURE_PROVIDER
return HITLS_X509_Adapt_Decrypt(ctx, key, in, inLen, out, outLen);
#else
if (ctx->config.tlsConfig.certMgrCtx->method.decrypt == NULL) {
return RETURN_ERROR_NUMBER_PROCESS(HITLS_UNREGISTERED_CALLBACK, BINLOG_ID15334, "unregistered decrypt");
}
return ctx->config.tlsConfig.certMgrCtx->method.decrypt(ctx, key, in, inLen, out, outLen);
#endif
}
#endif
int32_t SAL_CERT_CheckPrivateKey(HITLS_Config *config, HITLS_CERT_X509 *cert, HITLS_CERT_Key *key)
{
int32_t ret;
#ifdef HITLS_TLS_FEATURE_PROVIDER
ret = HITLS_X509_Adapt_CheckPrivateKey(config, cert, key);
#else
ret = config->certMgrCtx->method.checkPrivateKey(config, cert, key);
#endif
return CheckCertCallBackRetVal(
LOG_STR("check cert and private key"), ret, BINLOG_ID15538, HITLS_CERT_ERR_CHECK_CERT_AND_KEY, CERT_CTRL_BUTT);
}
#ifdef HITLS_TLS_CONFIG_CERT_CRL
HITLS_CERT_CRLList *SAL_CERT_CrlParse(HITLS_Config *config, const uint8_t *buf, uint32_t len,
HITLS_ParseType type, HITLS_ParseFormat format)
{
return HITLS_X509_Adapt_CrlParse(config, buf, len, type, format);
}
void SAL_CERT_CrlFree(HITLS_CERT_CRLList *crlList)
{
HITLS_X509_Adapt_CrlFree(crlList);
}
#endif