* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "cm_native_api.h"
#include "cm_log.h"
#include "cm_mem.h"
#include "cert_manager_api.h"
#include "securec.h"
#define APPLICATION_PUBLIC_CERTIFICATION_STORE 0
#define APPLICATION_PRIVATE_CERTIFICATION_STORE 3
struct CmErrorCodeAdapter {
int32_t nativeErrCode;
int32_t ndkErrCode;
};
static struct CmErrorCodeAdapter g_errCodeTable[] = {
{ CM_SUCCESS, OH_CM_SUCCESS},
{ CMR_ERROR_INVALID_ARGUMENT, OH_CM_PARAMETER_VALIDATION_FAILED },
{ CMR_ERROR_PERMISSION_DENIED, OH_CM_HAS_NO_PERMISSION },
{ CMR_ERROR_INVALID_CERT_FORMAT, OH_CM_INVALID_CERT_FORMAT },
{ CMR_ERROR_INSUFFICIENT_DATA, OH_CM_INVALID_CERT_FORMAT },
{ CMR_ERROR_NOT_FOUND, OH_CM_NOT_FOUND },
{ CMR_ERROR_NOT_EXIST, OH_CM_NOT_FOUND },
{ CMR_ERROR_MAX_CERT_COUNT_REACHED, OH_CM_MAX_CERT_COUNT_REACHED },
{ CMR_ERROR_AUTH_CHECK_FAILED, OH_CM_NO_AUTHORIZATION },
{ CMR_ERROR_DEVICE_ENTER_ADVSECMODE, OH_CM_DEVICE_ENTER_ADVSECMODE },
{ CMR_ERROR_UKEY_GENERAL_ERROR, OH_CM_ACCESS_UKEY_SERVICE_FAILED },
{ CMR_ERROR_UKEY_DEVICE_SUPPORT, OH_CM_CAPABILITY_NOT_SUPPORTED },
{ CMR_ERROR_HUKS_GENERAL_ERROR, OH_CM_INNER_FAILURE },
};
static int32_t TranformErrorCode(int32_t errorCode)
{
uint32_t errCodeCount = sizeof(g_errCodeTable) / sizeof(g_errCodeTable[0]);
for (uint32_t i = 0; i < errCodeCount; ++i) {
if (errorCode == g_errCodeTable[i].nativeErrCode) {
return g_errCodeTable[i].ndkErrCode;
}
}
return OH_CM_INNER_FAILURE;
}
static int32_t InitAppCert(OH_CM_Credential *credential)
{
if (credential == NULL) {
return CMR_ERROR_NULL_POINTER;
}
credential->credData.data = (uint8_t *)(CmMalloc(MAX_LEN_CERTIFICATE_CHAIN));
if (credential->credData.data == NULL) {
CM_LOG_E("malloc file buffer failed");
return CMR_ERROR_MALLOC_FAIL;
}
(void)memset_s(credential->credData.data, MAX_LEN_CERTIFICATE_CHAIN, 0, MAX_LEN_CERTIFICATE_CHAIN);
credential->credData.size = MAX_LEN_CERTIFICATE_CHAIN;
return CM_SUCCESS;
}
static bool CheckCertPurpose(uint32_t certPurpose)
{
switch (certPurpose) {
case CM_CERT_PURPOSE_DEFAULT:
case CM_CERT_PURPOSE_ALL:
case CM_CERT_PURPOSE_SIGN:
case CM_CERT_PURPOSE_ENCRYPT:
return true;
default:
CM_LOG_E("invalid cert purpose: %u", certPurpose);
return false;
}
}
int32_t OH_CertManager_GetUkeyCertificate(const OH_CM_Blob *keyUri,
const OH_CM_UkeyInfo *ukeyInfo, OH_CM_CredentialDetailList *certificateList)
{
if (ukeyInfo == NULL || !CheckCertPurpose(ukeyInfo->certPurpose)) {
CM_LOG_E("cert purpose is invalid");
return OH_CM_PARAMETER_VALIDATION_FAILED;
}
if (certificateList == NULL) {
CM_LOG_E("certificateList is NULL");
return TranformErrorCode(CMR_ERROR_NULL_POINTER);
}
int32_t result = CmGetUkeyCert((const struct CmBlob *) keyUri, (const struct UkeyInfo *) ukeyInfo,
(struct CredentialDetailList *)certificateList);
if (result == CM_SUCCESS && certificateList->credentialCount == 0) {
CM_LOG_E("no available cert");
result = CMR_ERROR_NOT_FOUND;
}
return TranformErrorCode(result);
}
int32_t OH_CertManager_GetPrivateCertificate(const OH_CM_Blob *keyUri, OH_CM_Credential *certificate)
{
int32_t result = InitAppCert(certificate);
if (result != CM_SUCCESS) {
return TranformErrorCode(result);
}
result = CmGetAppCert((struct CmBlob *)keyUri, APPLICATION_PRIVATE_CERTIFICATION_STORE,
(struct Credential *)certificate);
return TranformErrorCode(result);
}
int32_t OH_CertManager_GetPublicCertificate(const OH_CM_Blob *keyUri, OH_CM_Credential *certificate)
{
int32_t result = InitAppCert(certificate);
if (result != CM_SUCCESS) {
return TranformErrorCode(result);
}
result = CmGetAppCert((struct CmBlob *)keyUri, APPLICATION_PUBLIC_CERTIFICATION_STORE,
(struct Credential *)certificate);
return TranformErrorCode(result);
}
void OH_CertManager_FreeUkeyCertificate(OH_CM_CredentialDetailList *certificateList)
{
CmFreeUkeyCertificate((struct CredentialDetailList *)certificateList);
}
void OH_CertManager_FreeCredential(OH_CM_Credential *certificate)
{
CmFreeCredential((struct Credential *)certificate);
}