diff --git a/baselib/utils/include/utils_base64.h b/baselib/utils/include/utils_base64.h index 61d9e3bbea2c001bf5e69ddc5fec8889165a4bca..2d9fe8f0eb4e61e9579c955707b32b964294c742 100644 --- a/baselib/utils/include/utils_base64.h +++ b/baselib/utils/include/utils_base64.h @@ -24,6 +24,8 @@ extern "C" { int32_t Base64DecodeApp(const uint8_t *src, uint8_t **to); +int32_t Base64UrlDecodeApp(const uint8_t *src, uint8_t **to); + uint8_t *Base64EncodeApp(const uint8_t *from, uint32_t fromLen); #ifdef __cplusplus diff --git a/baselib/utils/include/utils_json.h b/baselib/utils/include/utils_json.h index 4ed7f5db540029d84646401873dba5836c27de39..75c3206b005f47ac3aa3d39bec8f5d9eee1065ff 100644 --- a/baselib/utils/include/utils_json.h +++ b/baselib/utils/include/utils_json.h @@ -16,6 +16,7 @@ #ifndef SEC_UTILS_JSON_H #define SEC_UTILS_JSON_H +#include #include #ifdef __cplusplus @@ -32,13 +33,19 @@ int32_t GetJsonFieldIntArray(JsonHandle handle, const char *field, int32_t *arra const char *GetJsonFieldString(JsonHandle handle, const char *field); JsonHandle GetJsonFieldJson(JsonHandle handle, const char *field); +JsonHandle GetJsonFieldJsonArray(JsonHandle handle, uint32_t num); +int32_t GetJsonFieldJsonArraySize(JsonHandle handle); + void AddFieldIntToJson(JsonHandle handle, const char *field, int32_t value); void AddFieldIntArrayToJson(JsonHandle handle, const char *field, const int32_t *array, int32_t arrayLen); +void AddFieldBoolToJson(JsonHandle handle, const char *field, bool value); void AddFieldStringToJson(JsonHandle handle, const char *field, const char *value); void AddFieldJsonToJson(JsonHandle handle, const char *field, JsonHandle json); char *ConvertJsonToString(JsonHandle handle); +bool CompareJsonData(JsonHandle handleA, JsonHandle handleB, bool caseSensitive); + #ifdef __cplusplus } #endif diff --git a/baselib/utils/src/utils_base64.c b/baselib/utils/src/utils_base64.c index 0e8cec35d309da5fabc4b3befd0e9d4288ef0aaa..8262dcd72695b0689414bdf17dfff6a9d4c5c8ed 100644 --- a/baselib/utils/src/utils_base64.c +++ b/baselib/utils/src/utils_base64.c @@ -15,6 +15,7 @@ #include "utils_base64.h" +#include #include #include @@ -25,7 +26,8 @@ extern "C" { #endif -#define MAX_MALLOC_LEN (1 * 1024 * 1024) +#define MAX_MALLOC_LEN (1 * 1024 * 1024) +#define RESIZE4(n) (((n) + 3) & ~3) static const char *g_base64EncodeTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const uint8_t g_base64DecodeTable[256] = { /* 256 due to character size */ @@ -213,6 +215,35 @@ int32_t Base64DecodeApp(const uint8_t *src, uint8_t **to) return realLen; } +int32_t Base64UrlDecodeApp(const uint8_t *src, uint8_t **to) +{ + if ((src == NULL) || to == NULL) { + SECURITY_LOG_DEBUG("Unexpected nullptr!"); + return 0; + } + uint32_t sourceLen = strlen((char*)src); + uint32_t alignLen = RESIZE4(sourceLen); + uint8_t *base64Str = (uint8_t*)malloc(alignLen + 1); + if (base64Str == NULL) { + SECURITY_LOG_DEBUG("Base64UrlDecodeApp MALLOC fail"); + return 0; + } + memset_s(base64Str, alignLen + 1, '=', alignLen + 1); + for (uint32_t i = 0; i < sourceLen; i++) { + if (src[i] == '-') + base64Str[i] = '+'; + else if (src[i] == '_') + base64Str[i] = '/'; + else + base64Str[i] = src[i]; + } + base64Str[alignLen] = '\0'; + const uint8_t *from = base64Str; + int32_t realLength = Base64DecodeApp(from, to); + free(base64Str); + return realLength; +} + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/baselib/utils/src/utils_json.c b/baselib/utils/src/utils_json.c index f70b8d515e544dd743e54922eb4d020c64764917..fece8e5bf175f7b0a4e9d582e8dfbd0acc8e1ee7 100644 --- a/baselib/utils/src/utils_json.c +++ b/baselib/utils/src/utils_json.c @@ -98,6 +98,14 @@ int32_t GetJsonFieldIntArray(JsonHandle handle, const char *field, int32_t *arra return index; } +void AddFieldBoolToJson(JsonHandle handle, const char *field, bool value) +{ + if (handle == NULL || field == NULL) { + return; + } + (void)cJSON_AddBoolToObject((cJSON *)handle, field, value); +} + const char *GetJsonFieldString(JsonHandle handle, const char *field) { if (handle == NULL) { @@ -127,6 +135,16 @@ JsonHandle GetJsonFieldJson(JsonHandle handle, const char *field) return cJSON_GetObjectItem((cJSON *)handle, field); } +JsonHandle GetJsonFieldJsonArray(JsonHandle handle, uint32_t num) +{ + return cJSON_GetArrayItem((cJSON *)handle, num); +} + +int32_t GetJsonFieldJsonArraySize(JsonHandle handle) +{ + return cJSON_GetArraySize((cJSON *)handle); +} + void AddFieldIntToJson(JsonHandle handle, const char *field, int32_t value) { if (handle == NULL || field == NULL) { @@ -172,6 +190,14 @@ char *ConvertJsonToString(JsonHandle handle) return NULL; } +bool CompareJsonData(JsonHandle handleA, JsonHandle handleB, bool caseSensitive) +{ + if (handleA == NULL || handleB == NULL) { + return false; + } + return cJSON_Compare(handleA, handleB, caseSensitive); +} + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/interfaces/inner_api/include/device_security_defines.h b/interfaces/inner_api/include/device_security_defines.h index 124f588d589438ce9e54aa237148469177b50abc..eaa9abf47f4c4cf4a32d21a2c8b692bd91c149f0 100644 --- a/interfaces/inner_api/include/device_security_defines.h +++ b/interfaces/inner_api/include/device_security_defines.h @@ -81,6 +81,17 @@ enum { ERR_MSG_OPEN_SESSION = 36, ERR_QUERY_WAITING = 37, ERR_NOEXIST_DEVICE = 38, + ERR_NOEXIST_COMMON_PK_INFO = 39, + ERR_ECC_VERIFY_ERR = 40, + ERR_GET_CLOUD_CRED_INFO = 41, + ERR_CALL_EXTERNAL_FUNC = 42, + ERR_PARSE_NOUNCE = 43, + ERR_ROOT_PUBKEY_NOT_RIGHT = 44, + ERR_PARSE_CLOUD_CRED_DATA = 45, + ERR_PARSE_PUBKEY_CHAIN = 46, + ERR_CHECK_CRED_INFO = 47, + ERR_ATTEST_NOT_READY = 48, + ERR_CLOUD_CRED_NOT_EXIST = 49, ERR_DEFAULT = 0xFFFF }; diff --git a/oem_property/ohos/BUILD.gn b/oem_property/ohos/BUILD.gn index abd558cf1d454602d7e8e2168fddb33418332d83..3d13e90819771d3a20edec126c1c797e09274649 100644 --- a/oem_property/ohos/BUILD.gn +++ b/oem_property/ohos/BUILD.gn @@ -65,17 +65,25 @@ ohos_source_set("dslm_ohos_cred_obj") { sources = [ "impl/dslm_ohos_request.c", "impl/dslm_ohos_verify.c", + "impl/external_interface.c", ] include_dirs = [ "//base/security/device_security_level/common/include", "//base/security/device_security_level/interfaces/inner_api/include", + "//base/security/device_security_level/services/include", + "//base/security/deviceauth/interfaces/innerkits", ] - deps = [ "//base/security/device_security_level/baselib/utils:utils_static" ] + deps = [ + "//base/security/device_security_level/baselib/utils:utils_static", + "//base/security/deviceauth/services:deviceauth_sdk", + ] external_deps = [ + "deviceauth_standard:deviceauth_sdk", "hilog_native:libhilog", + "huks:libhukssdk", "utils_base:utils", ] diff --git a/oem_property/ohos/impl/dslm_ohos_request.c b/oem_property/ohos/impl/dslm_ohos_request.c index 0c86fa794ec84de3438087249cd70b184e18b118..059a87afbb13b81debc6f430c72bb5e366f81b6d 100644 --- a/oem_property/ohos/impl/dslm_ohos_request.c +++ b/oem_property/ohos/impl/dslm_ohos_request.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2022 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 @@ -14,55 +14,120 @@ */ #include "dslm_ohos_request.h" +#include "external_interface.h" +#include #include -#include "securec.h" +#include "utils_hexstring.h" +#include "utils_json.h" #include "utils_log.h" - #include "utils_mem.h" +#define CRED_CFG_FILE_POSITION "/system/etc/dslm_finger.cfg" +#define CRED_STR_LEN_MAX 4096 +#define CHALLENGE_STRING_LENGTH 32 + +static int32_t GetCredFromCurrentDevice(char *credStr, uint32_t maxLen) +{ + FILE *fp = NULL; + fp = fopen(CRED_CFG_FILE_POSITION, "r"); + if (fp == NULL) { + SECURITY_LOG_INFO("fopen cred file failed!"); + return ERR_INVALID_PARA; + } + int32_t ret = fscanf_s(fp, "%s", credStr, maxLen); + if (ret == -1) { + ret = ERR_INVALID_PARA; + } else { + ret = SUCCESS; + } + if (fclose(fp) != 0) { + ret = ERR_INVALID_PARA; + } + return ret; +} + +static int32_t TransToJsonStr(uint64_t challenge, const char *pkInfoListStr, char **nounceStr) +{ + JsonHandle json = CreateJson(NULL); + if (json == NULL) { + return ERR_INVALID_PARA; + } + + // add challenge + + char challengeStr[CHALLENGE_STRING_LENGTH] = {0}; + char *saveData = &challengeStr[0]; + ByteToHexString((uint8_t *)&challenge, sizeof(challenge), (uint8_t *)saveData, CHALLENGE_STRING_LENGTH); + AddFieldStringToJson(json, "challenge", saveData); + + // add pkInfoList + AddFieldStringToJson(json, "pkInfoList", pkInfoListStr); + + // tran to json + *nounceStr = (char *)ConvertJsonToString(json); + if (*nounceStr == NULL) { + DestroyJson(json); + return ERR_JSON_ERR; + } + DestroyJson(json); + return SUCCESS; +} + int32_t RequestOhosDslmCred(const DeviceIdentify *device, const RequestObject *obj, DslmCredBuff **credBuff) { SECURITY_LOG_INFO("Invoke RequestOhosDslmCred"); - static const char *credStr = - "ewogICAgInR5cCI6ICJEU0wiLAp9." - "eyJzZWN1cml0eUxldmVsIjoiU0w0IiwibWFudWZhY3R1cmUiOiJNQU5VIiwic2lnblRpbWUiOiIyMDIxMTEwOTExMjczNCIsIm1vZGVsIjoiTU" - "9ERU" - "wiLCJ0eXBlIjoiZGVidWciLCJ1ZGlkIjoiMTIzNDU2Nzg5MEFCQ0RFRiIsInZlcnNpb24iOiIxLjAiLCJicmFuZCI6IkJSQU5EIiwic29mdHdh" - "cmVW" - "ZXJzaW9uIjoiMi4xLjAuNDIifQ==.MEUCIQCMglMcuEUhJBwbkPbgNi_VI7ksPkGZXBPMQI_YmepubQIgPuF9WLjaTum9d_" - "KhqmVdjfRmcFbhPh4Laq2NnlVz3uc." - "W3sidXNlclB1YmxpY0tleSI6Ik1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRWFnOFZIMzN4OUpDOTYwSWsxejNKNmo1cnk0OV" - "JENG" - "t0TTBvQUZGenhiNHdOdS1OckZSbm5XbnZmR3hGTW16VFBMLWYxY1NqWGd2UV9NdU9aenVpclNnIiwiYWxnb3JpdGhtIjoiU0hBMzg0d2l0aEVD" - "RFNB" - "Iiwic2lnbmF0dXJlIjoiTUdVQ01DakdwWEZPNlRjb2NtWFdMdHU1SXQ0LVRJNzFoNzhLdDYyYjZ6Mm9tcnNVWElHcnFsMTZXT0ExV2ZfdDdGSU" - "1RZ0" - "l4QVBHMlV5T2d0dk1pbi1hbVR6Wi1DN2ZyMWttVl9jODc4ckFnZVlrUGFxWWdPWWpiSGN0QnFzMkJCV05LMGsxTnJRIn0seyJ1c2VyUHVibGlj" - "S2V5" - "IjoiTUhZd0VBWUhLb1pJemowQ0FRWUZLNEVFQUNJRFlnQUVvM0N1Q0VMQzdTaUxhSkNCQ0RkY0NwZXRnSUdraFpMc0ZfYTBkZFUxQ1I3dzU0em" - "ppc0" - "NYWkdfdXk2ZGtGZWZrZTNVMW9CaWw0eGk1OU5xeVpOZ1FQbEFISVVHeWtRcVl4cHg1WjBqQUJCSnlBSlVscHRxM0p1Wk5UQTdIOVVLNyIsImFs" - "Z29y" - "aXRobSI6IlNIQTM4NHdpdGhFQ0RTQSIsInNpZ25hdHVyZSI6Ik1HVUNNQ1ZXUWIxdXFLb1E5SUFMaWJiWUlUX1NWSENXem84akcwRG1WNGt6Q0" - "JNQ3" - "pRQU0xZEFaSERGWFdidGUyY0FfWXdJeEFJSXVmaXJHbnN3NlBEV0txRm1mQmQ5Y3BubEFyLXVXV0RqZ2xuenoyRmx2LXNkaVhYRnR3amo3Y1hU" - "TF9F" - "NmJRUSJ9LHsidXNlclB1YmxpY0tleSI6Ik1IWXdFQVlIS29aSXpqMENBUVlGSzRFRUFDSURZZ0FFU09kcnY3eXhEaFoxWmRUdDB3QUxCMnhYc0" - "ZsUG" - "V2TkQ0b1lfWE44QWtFTVllWVVyTXBkX1hTQTdlTHo5eVJaa08yX3RoSEx4bUpURGZrOUJFeTlTa0xxUF9xOGZJdzBhSXNBMHI0SlN0djh4YVo0" - "RWxV" - "TGxPV2QxXzF4YV9fdnIiLCJhbGdvcml0aG0iOiJTSEEzODR3aXRoRUNEU0EiLCJzaWduYXR1cmUiOiJNR1FDTURmODNSNktLdm9tZnZyZVYycH" - "hVSE" - "pXb3RwM3BVOUdBWU5tcU1XUmVGcGp6WHpOVjc5dHNrZTBaa21JTVh3TXNBSXdXNUFiOWk4SnlObEp0WDJZcnpaYzJna3RranZ0U2JiSnYwaWhu" - "Umdx" - "MWNjUHBrVDJOc3F4ekJrZkRqOGhQWllzIn1d"; - - DslmCredBuff *out = CreateDslmCred(CRED_TYPE_STANDARD, strlen(credStr) + 1, (uint8_t *)credStr); - if (out == NULL) { - return ERR_MEMORY_ERR; + + char *pkInfoListStr = NULL; + char *nounceStr = NULL; + uint8_t *certChain = NULL; + uint32_t certChainLen = 0; + + char credStr[CRED_STR_LEN_MAX] = { 0 }; + int32_t ret = GetCredFromCurrentDevice(credStr, CRED_STR_LEN_MAX); + if (ret != SUCCESS) { + SECURITY_LOG_ERROR("read data frome CFG failed!"); + return ret; } - *credBuff = out; - return SUCCESS; + + do { + ret = GetPkInfoListStr(true, device->identity, device->length, &pkInfoListStr); + if (ret != SUCCESS) { + SECURITY_LOG_INFO("GetPkInfoListStr failed"); + break; + } + + ret = TransToJsonStr(obj->challenge, pkInfoListStr, &nounceStr); + if (ret != SUCCESS) { + SECURITY_LOG_INFO("TransToJsonStr failed"); + break; + } + + ret = DslmCredAttestAdapter(nounceStr, credStr, &certChain, &certChainLen); + if (ret != SUCCESS) { + SECURITY_LOG_INFO("DslmCredAttestAdapter failed"); + break; + } + + DslmCredBuff *out = CreateDslmCred(CRED_TYPE_STANDARD, certChainLen, certChain); + if (out == NULL) { + ret = ERR_MEMORY_ERR; + SECURITY_LOG_INFO("CreateDslmCred failed"); + break; + } + *credBuff = out; + ret = SUCCESS; + } while (0); + + if (pkInfoListStr != NULL) { + FREE(pkInfoListStr); + } + if (nounceStr != NULL) { + FREE(nounceStr); + } + if (certChain != NULL) { + FREE(certChain); + } + return ret; } diff --git a/oem_property/ohos/impl/dslm_ohos_verify.c b/oem_property/ohos/impl/dslm_ohos_verify.c index e62a2349ae6505130f19570c0df1cc05a2be1f15..fb5a6e66fca3eb6f12e19ed8591008e8d852ba32 100644 --- a/oem_property/ohos/impl/dslm_ohos_verify.c +++ b/oem_property/ohos/impl/dslm_ohos_verify.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2022 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 @@ -15,17 +15,629 @@ #include "dslm_ohos_verify.h" +#include #include -#include "securec.h" +#include "dslm_crypto.h" +#include "external_interface.h" +#include "utils_base64.h" +#include "utils_hexstring.h" +#include "utils_json.h" #include "utils_log.h" #include "utils_mem.h" #define OHOS_DEFAULT_LEVEL 1 + +#define DEVICE_LEVEL_CRED_TYPE_CRED_CLOUD_WITH_HUKS 100 + +#define UDID_STRING_LENGTH 65 + +#define SHA_256_HASH_RESULT_LEN 32 + +#define PBK_CHAIN_LEVEL 3 +#define PBK_CHAIN_THIRD_KEY_INDEX 2 + +#define JSON_KEY_USER_PUBLIC_KEY "userPublicKey" +#define JSON_KEY_SIGNATURE "signature" +#define JSON_KEY_ALGORITHM "algorithm" + +#define SEC_LEVEL_STR_LEN 3 // "SL0" +#define CLOUD_CRED_SEC_LEVEL_0 0 +#define CLOUD_CRED_SEC_LEVEL_MAX 5 + +#define CRED_KEY_CRED_VERSION "version" +#define CRED_KEY_MANUFACTURE "manufacture" +#define CRED_KEY_MODEL_NAME "model" +#define CRED_KEY_BRAND "brand" +#define CRED_KEY_OS_VERSION "softwareVersion" +#define CRED_KEY_UDID "udid" +#define CRED_KEY_TYPE "type" +#define CRED_KEY_SIGN_TIME "signTime" +#define CRED_KEY_SECURITY_LEVEL "securityLevel" + +#define CRED_VALUE_TYPE_DEBUG "debug" +#define CRED_VALUE_TYPE_RELEASE "release" + + +struct NounceOfCertChain { + uint64_t challenge; + uint8_t *pbkInfoList; + uint32_t pbkInfoListLen; +}; + +struct PbkChain { + struct DataBuffer src; + struct DataBuffer sig; + struct DataBuffer pbk; + uint32_t algorithm; +}; + +struct CredData { + char *credPtr; + const char *header; + const char *payload; + const char *signature; + const char *attestionInfo; + struct PbkChain pbkChain[PBK_CHAIN_LEVEL]; +}; + +static int32_t GetSecLevelFromString(const char *data, uint32_t dataLen, uint32_t *securityLevel) +{ + if (data == NULL || dataLen != SEC_LEVEL_STR_LEN) { + return ERR_INVALID_PARA; + } + if (memcmp(data, "SL", SEC_LEVEL_STR_LEN - 1) != 0) { + return ERR_INVALID_PARA; + } + int32_t num = data[SEC_LEVEL_STR_LEN - 1] - '0'; + if (num < CLOUD_CRED_SEC_LEVEL_0 || num > CLOUD_CRED_SEC_LEVEL_MAX) { + return ERR_INVALID_PARA; + } + *securityLevel = num; + return SUCCESS; +} + +static int32_t GetAlgorithmType(const char* data, uint32_t dataLen, uint32_t * algorithm) +{ + if (data == NULL || dataLen == 0) { + return ERR_INVALID_PARA; + } + if (strncmp(data, "SHA384withECDSA", strlen("SHA384withECDSA")) == 0) { + *algorithm = TYPE_ECDSA_SHA_384; + } else if (strncmp(data, "SHA256withECDSA", strlen("SHA256withECDSA")) == 0) { + *algorithm = TYPE_ECDSA_SHA_256; + } else { + return ERR_INVALID_PARA; + } + return SUCCESS; +} + +static int32_t CopyParamDataFromJson(const JsonHandle json, const char *paramKey, char *dest, uint32_t destLen) +{ + const char *tempData = GetJsonFieldString(json, paramKey); + if (tempData == NULL) { + return ERR_INVALID_PARA; + } + if (strcpy_s(dest, destLen, tempData) != EOK) { + return ERR_MEMORY_ERR; + } + return SUCCESS; +} + +static int32_t GetCredPayloadInfo(const char* credPayload, DslmCredInfo *credInfo) +{ + uint8_t *buffer = NULL; + Base64DecodeApp((uint8_t *)credPayload, &buffer); + if (buffer == NULL) { + return ERR_INVALID_PARA; + } + JsonHandle json = CreateJson((char*)buffer); + if (json == NULL) { + FREE(buffer); + return ERR_INVALID_PARA; + } + FREE(buffer); + buffer = NULL; + + do { + credInfo->credType = DEVICE_LEVEL_CRED_TYPE_CRED_CLOUD_WITH_HUKS; + + // get security level + if (CopyParamDataFromJson(json, CRED_KEY_SECURITY_LEVEL, credInfo->securityLevel, CRED_INFO_LEVEL_LEN) != + SUCCESS) { + SECURITY_LOG_ERROR("get securityLevel failed!"); + break; + } + if (GetSecLevelFromString(credInfo->securityLevel, strlen(credInfo->securityLevel), &(credInfo->credLevel)) != + SUCCESS) { + SECURITY_LOG_ERROR("get credLevel failed!"); + break; + } + + // get type, debug or release + if (CopyParamDataFromJson(json, CRED_KEY_TYPE, credInfo->type, CRED_INFO_TYPE_LEN) != SUCCESS) { + SECURITY_LOG_ERROR("get type failed!"); + break; + } + + // get cred version. The following data is not important, so continue even it fails. + if (CopyParamDataFromJson(json, CRED_KEY_CRED_VERSION, credInfo->version, CRED_INFO_VERSION_LEN) != SUCCESS) { + SECURITY_LOG_ERROR("get version failed!"); + } + + // get udid, when type is debug + if (strncmp(credInfo->type, CRED_VALUE_TYPE_DEBUG, strlen(CRED_VALUE_TYPE_DEBUG)) == 0) { + if (CopyParamDataFromJson(json, CRED_KEY_UDID, credInfo->udid, CRED_INFO_UDID_LEN) != SUCCESS) { + SECURITY_LOG_ERROR("get udid failed!"); + } + } + + // get signTime + if (CopyParamDataFromJson(json, CRED_KEY_SIGN_TIME, credInfo->signTime, CRED_INFO_SIGNTIME_LEN) != SUCCESS) { + SECURITY_LOG_ERROR("get signTime failed!"); + } + + // get manufacture + if (CopyParamDataFromJson(json, CRED_KEY_MANUFACTURE, credInfo->manufacture, CRED_INFO_MANU_LEN) != SUCCESS) { + SECURITY_LOG_ERROR("get manufacture failed!"); + } + + // get model + if (CopyParamDataFromJson(json, CRED_KEY_MODEL_NAME, credInfo->model, CRED_INFO_MODEL_LEN) != SUCCESS) { + SECURITY_LOG_ERROR("get model name failed!"); + } + + // get brand + if (CopyParamDataFromJson(json, CRED_KEY_BRAND, credInfo->brand, CRED_INFO_BRAND_LEN) != SUCCESS) { + SECURITY_LOG_ERROR("get brand failed!"); + } + + SECURITY_LOG_DEBUG("ParseCredPayload SUCCESS!"); + DestroyJson(json); + return SUCCESS; + } while (0); + + DestroyJson(json); + return ERR_GET_CLOUD_CRED_INFO; +} + +static int32_t GenerateDeviceUdid(const char *manufacture, const char *productModel, const char *serialNum, + char *udidStr, uint32_t MaxLen) +{ + uint32_t manufactureLen = strlen(manufacture); + uint32_t productModelLen = strlen(productModel); + uint32_t serialNumLen = strlen(serialNum); + + uint32_t dataLen = manufactureLen + productModelLen + serialNumLen; + char *data = (char*)MALLOC(dataLen + 1); + + if (strcat_s(data, dataLen + 1, manufacture) != EOK) { + return ERR_INVALID_PARA; + } + if (strcat_s(data, dataLen + 1, productModel) != EOK) { + return ERR_INVALID_PARA; + } + if (strcat_s(data, dataLen + 1, serialNum) != EOK) { + return ERR_INVALID_PARA; + } + + uint8_t hashResult[SHA_256_HASH_RESULT_LEN] = {0}; + CallHashSha256((uint8_t *)data, dataLen, hashResult); + + ByteToHexString(hashResult, SHA_256_HASH_RESULT_LEN, (uint8_t *)udidStr, UDID_STRING_LENGTH); + + return 0; +} + +static int32_t CheckCredInfo(const struct DeviceIdentify *device, const char* serialNum, const DslmCredInfo *info) +{ + if (strncmp(info->type, CRED_VALUE_TYPE_DEBUG, strlen(CRED_VALUE_TYPE_DEBUG)) == 0) { + if (strncmp((char*)device->identity, info->udid, strlen(info->udid)) == 0) { + return SUCCESS; + } + + char udidStr[UDID_STRING_LENGTH] = {0}; + GenerateDeviceUdid(info->manufacture, info->model, serialNum, udidStr, UDID_STRING_LENGTH); + if (strcasecmp(udidStr, info->udid) == 0) { + return SUCCESS; + } + return ERR_CHECK_CRED_INFO; + } + return SUCCESS; +} + +static int32_t ParseNounceOfCertChain(const char *jsonBuffer, struct NounceOfCertChain *nounce) +{ + JsonHandle json = CreateJson(jsonBuffer); + if (json == NULL) { + return ERR_INVALID_PARA; + } + + // 1. Get challenge. + const char *challengeStr = GetJsonFieldString(json, "challenge"); + if (challengeStr == NULL) { + DestroyJson(json); + return ERR_PARSE_NOUNCE; + } + int32_t ret = + HexStringToByte(challengeStr, strlen(challengeStr), (uint8_t *)&nounce->challenge, sizeof(nounce->challenge)); + if (ret != SUCCESS) { + DestroyJson(json); + return ERR_PARSE_NOUNCE; + } + + // 2. Get PublicKey Info. + const char *pkInfoListStr = GetJsonFieldString(json, "pkInfoList"); + if (pkInfoListStr == NULL) { + DestroyJson(json); + return ERR_PARSE_NOUNCE; + } + nounce->pbkInfoList = (uint8_t *)MALLOC(strlen(pkInfoListStr) + 1); + if (nounce->pbkInfoList == NULL) { + DestroyJson(json); + return ERR_NO_MEMORY; + } + + ret = strcpy_s((char*)nounce->pbkInfoList, strlen(pkInfoListStr) + 1, pkInfoListStr); + if (ret != EOK) { + FREE(nounce->pbkInfoList); + nounce->pbkInfoList = NULL; + DestroyJson(json); + return ERR_MEMORY_ERR; + } + DestroyJson(json); + return SUCCESS; +} + +static void FreeNounceOfCertChain(struct NounceOfCertChain *nounce) +{ + if (nounce != NULL && nounce->pbkInfoList != NULL) { + FREE(nounce->pbkInfoList); + nounce->pbkInfoList = NULL; + } + (void)memset_s(nounce, sizeof(struct NounceOfCertChain), 0, sizeof(struct NounceOfCertChain)); +} + +static int32_t FindCommonPkInfo(const char* bufferA, const char *bufferB) +{ + if (bufferA == NULL || bufferB == NULL) { + return ERR_INVALID_PARA; + } + JsonHandle jsonA = CreateJson(bufferA); + if (jsonA == NULL) { + return ERR_INVALID_PARA; + } + JsonHandle jsonB = CreateJson(bufferB); + if (jsonB == NULL) { + DestroyJson(jsonA); + return ERR_INVALID_PARA; + } + uint32_t sizeA = GetJsonFieldJsonArraySize(jsonA); + uint32_t sizeB = GetJsonFieldJsonArraySize(jsonB); + + for (uint32_t i = 0; i < sizeA; i++) { + for (uint32_t j = 0; j < sizeB; j++) { + if (CompareJsonData(GetJsonFieldJsonArray(jsonA, i), GetJsonFieldJsonArray(jsonB, j), true)) { + DestroyJson(jsonA); + DestroyJson(jsonB); + return SUCCESS; + } + } + } + DestroyJson(jsonA); + DestroyJson(jsonB); + return ERR_NOEXIST_COMMON_PK_INFO; +} + +static int32_t CheckNounceOfCertChain(const struct NounceOfCertChain *nounce, uint64_t challenge, + const char *pbkInfoList) +{ + if (challenge != nounce->challenge) { + SECURITY_LOG_ERROR("compare nounce challenge failed!"); + return ERR_CHALLENGE_ERR; + } + + int32_t ret = FindCommonPkInfo((char *)pbkInfoList, (char*)nounce->pbkInfoList); + if (ret != SUCCESS) { + SECURITY_LOG_ERROR("compare nounce public key info failed!"); + return ret; + } + return SUCCESS; +} + + +static int32_t VerifyNounceOfCertChain(const char *jsonStr, const struct DeviceIdentify *device, uint64_t challenge) +{ + char *pkInfoListStr = NULL; + struct NounceOfCertChain nounce; + (void)memset_s(&nounce, sizeof(struct NounceOfCertChain), 0, sizeof(struct NounceOfCertChain)); + + int32_t ret = ERR_DEFAULT; + do { + ret = ParseNounceOfCertChain(jsonStr, &nounce); + if (ret != SUCCESS) { + SECURITY_LOG_ERROR("ParseNounceOfCertChain failed!"); + break; + } + + ret = GetPkInfoListStr(false, (uint8_t *)device->identity, device->length, &pkInfoListStr); + if (ret != SUCCESS) { + SECURITY_LOG_ERROR("GetPkInfoListStr failed!"); + break; + } + + ret = CheckNounceOfCertChain(&nounce, challenge, pkInfoListStr); + if (ret != SUCCESS) { + SECURITY_LOG_ERROR("CheckNounceOfCertChain failed!"); + break; + } + SECURITY_LOG_DEBUG("VerifyNounceOfCertChain success!"); + } while (0); + + FreeNounceOfCertChain(&nounce); + FREE(pkInfoListStr); + return ret; +} + +static int32_t ParsePubKeyChain(const char *credAttestionInfo, uint32_t length, struct PbkChain *pbkChain) +{ + uint8_t *buffer = NULL; + Base64DecodeApp((uint8_t*)credAttestionInfo, &buffer); + if (buffer == NULL) { + return ERR_INVALID_PARA; + } + JsonHandle json = CreateJson((char *)buffer); + if (json == NULL) { + FREE(buffer); + return ERR_INVALID_PARA; + } + FREE(buffer); + if (GetJsonFieldJsonArraySize(json) != PBK_CHAIN_LEVEL) { + DestroyJson(json); + return ERR_JSON_ERR; + } + + JsonHandle item = NULL; + const char *srcMsg = NULL; + const char *sigMsg = NULL; + const char *pbkMsg = NULL; + const char *algMsg = NULL; + for (uint32_t i = 0; i < PBK_CHAIN_LEVEL; i++) { + item = GetJsonFieldJsonArray(json, PBK_CHAIN_LEVEL - i - 1); + pbkMsg = srcMsg; + srcMsg = GetJsonFieldString(item, JSON_KEY_USER_PUBLIC_KEY); + if (srcMsg == NULL) { + break; + } + sigMsg = GetJsonFieldString(item, JSON_KEY_SIGNATURE); + if (sigMsg == NULL) { + break; + } + algMsg = GetJsonFieldString(item, JSON_KEY_ALGORITHM); + if (algMsg == NULL) { + algMsg = "SHA384withECDSA"; + } + if (i == 0) { + pbkMsg = srcMsg; + } + pbkChain[i].src.length = Base64UrlDecodeApp((uint8_t *)srcMsg, &(pbkChain[i].src.data)); + if (pbkChain[i].src.data == NULL) { + break; + } + pbkChain[i].sig.length = Base64UrlDecodeApp((uint8_t *)sigMsg, &(pbkChain[i].sig.data)); + if (pbkChain[i].sig.data == NULL) { + break; + } + pbkChain[i].pbk.length = Base64UrlDecodeApp((uint8_t *)pbkMsg, &(pbkChain[i].pbk.data)); + if (pbkChain[i].pbk.data == NULL) { + break; + } + if (GetAlgorithmType(algMsg, strlen(algMsg), &(pbkChain[i].algorithm)) != SUCCESS) { + SECURITY_LOG_DEBUG("ParsePubKeyChain get type error"); + break; + } + + if (i == PBK_CHAIN_THIRD_KEY_INDEX) { + DestroyJson(json); + SECURITY_LOG_DEBUG("ParsePubKeyChain ok and return"); + return SUCCESS; + } + } + DestroyJson(json); + return ERR_PARSE_PUBKEY_CHAIN; +} + + +static int32_t ParseCredData(const char *credStr, struct CredData *credData) +{ + credData->credPtr = (char*)MALLOC(strlen(credStr) + 1); + if (credData->credPtr == NULL) { + return ERR_NO_MEMORY; + } + if (strcpy_s(credData->credPtr, strlen(credStr) + 1, credStr) != EOK) { + credData->credPtr = NULL; + return ERR_MEMORY_ERR; + } + + char *context = NULL; + credData->header = strtok_s(credData->credPtr, ".", &context); + if (context == NULL) { + return ERR_PARSE_CLOUD_CRED_DATA; + } + credData->payload = strtok_s(NULL, ".", &context); + if (context == NULL) { + return ERR_PARSE_CLOUD_CRED_DATA; + } + credData->signature = strtok_s(NULL, ".", &context); + if (context == NULL) { + return ERR_PARSE_CLOUD_CRED_DATA; + } + credData->attestionInfo = strtok_s(NULL, ".", &context); + if (context == NULL) { + return ERR_PARSE_CLOUD_CRED_DATA; + } + + return ParsePubKeyChain(credData->attestionInfo, strlen(credData->attestionInfo), &credData->pbkChain[0]); +} + +static int32_t VerifyCredPubKeyChain(const struct PbkChain *pbkChain) +{ + for (int i = 0; i < 3; i++) { + if (EcdsaVerify(&(pbkChain[i].src), &(pbkChain[i].sig), &(pbkChain[i].pbk), pbkChain[i].algorithm) != SUCCESS) { + return ERR_ECC_VERIFY_ERR; + } + } + SECURITY_LOG_ERROR("verifyCredPubKeyChain sucess!"); + return SUCCESS; +} + +static int32_t VerifyCredPayload(const char *cred, const struct CredData *credData) +{ + SECURITY_LOG_ERROR("VerifyCredPayload start!"); + + uint32_t srcMsgLen = strlen(credData->header) + strlen(credData->payload) + 1; + char *srcMsg = (char *)MALLOC(srcMsgLen + 1); + if (srcMsg == NULL) { + return ERR_NO_MEMORY; + } + (void)memset_s(srcMsg, srcMsgLen + 1, 0, srcMsgLen + 1); + if (memcpy_s(srcMsg, srcMsgLen, cred, srcMsgLen) != EOK) { + FREE(srcMsg); + return ERR_MEMORY_ERR; + } + + struct DataBuffer srcData, sigData, pbkData; + srcData.data = (uint8_t *)srcMsg; + srcData.length = strlen(srcMsg); + SECURITY_LOG_ERROR("src msg = %{public}s", srcMsg); + SECURITY_LOG_ERROR("src msgLen = %{public}d", srcData.length); + pbkData.data = credData->pbkChain[PBK_CHAIN_THIRD_KEY_INDEX].src.data; + pbkData.length = credData->pbkChain[PBK_CHAIN_THIRD_KEY_INDEX].src.length; + sigData.length = Base64UrlDecodeApp((uint8_t *)credData->signature, &(sigData.data)); + SECURITY_LOG_ERROR("sig msgLen = %{public}d", sigData.length); + if (sigData.data == NULL) { + FREE(srcMsg); + return ERR_MEMORY_ERR; + } + + int32_t ret = EcdsaVerify(&srcData, &sigData, &pbkData, TYPE_ECDSA_SHA_384); + if (ret != SUCCESS) { + SECURITY_LOG_ERROR("EcdsaVerify failed!"); + ret = ERR_ECC_VERIFY_ERR; + } else { + SECURITY_LOG_ERROR("EcdsaVerify success!"); + ret = SUCCESS; + } + FREE(srcMsg); + FREE(sigData.data); + return ret; +} + +static void FreeCredData(struct CredData *credData) +{ + if (credData == NULL) { + return; + } + if (credData->credPtr != NULL) { + FREE(credData->credPtr); + credData->credPtr = NULL; + } + for (uint32_t i = 0; i < PBK_CHAIN_LEVEL; i++) { + if (credData->pbkChain[i].src.data != NULL) { + FREE(credData->pbkChain[i].src.data); + credData->pbkChain[i].src.data = NULL; + } + if (credData->pbkChain[i].sig.data != NULL) { + FREE(credData->pbkChain[i].sig.data); + credData->pbkChain[i].sig.data = NULL; + } + if (credData->pbkChain[i].pbk.data != NULL) { + FREE(credData->pbkChain[i].pbk.data); + credData->pbkChain[i].pbk.data = NULL; + } + } + (void)memset_s(credData, sizeof(struct CredData), 0, sizeof(struct CredData)); +} + +static int32_t VerifyCredData(const char *credStr, DslmCredInfo *credInfo) +{ + struct CredData credData; + (void)memset_s(&credData, sizeof(struct CredData), 0, sizeof(struct CredData)); + + int32_t ret = ERR_DEFAULT; + do { + // 1. Parse Cred. + ret = ParseCredData(credStr, &credData); + if (ret != SUCCESS) { + SECURITY_LOG_ERROR("ParseCredData failed!"); + break; + } + + // 2. Verify public key chain, get root public key. + ret = VerifyCredPubKeyChain(&credData.pbkChain[0]); + if (ret != SUCCESS) { + SECURITY_LOG_ERROR("verifyCredPubKeyChain failed!"); + break; + } + + // 3. Verify source data by root public key. + ret = VerifyCredPayload(credStr, &credData); + if (ret != SUCCESS) { + SECURITY_LOG_ERROR("verifyCredPayload failed!"); + break; + } + + // 4. Parse cred payload. + ret = GetCredPayloadInfo(credData.payload, credInfo); + if (ret != SUCCESS) { + SECURITY_LOG_ERROR("verifyCredPayload failed!"); + break; + } + } while (0); + + FreeCredData(&credData); + return SUCCESS; +} + int32_t VerifyOhosDslmCred(const DeviceIdentify *device, uint64_t challenge, const DslmCredBuff *credBuff, DslmCredInfo *credInfo) { - SECURITY_LOG_INFO("Invoke VerifyOhosDslmCred = %{public}s", (char *)credBuff->credVal); - credInfo->credLevel = OHOS_DEFAULT_LEVEL; - return 0; + SECURITY_LOG_INFO("Invoke VerifyOhosDslmCred"); + struct CertChainValidateResult resultInfo; + InitCertChainValidateResult(&resultInfo, credBuff->credLen); + + int32_t ret = ERR_DEFAULT; + do { + // 1. Verify the certificate chain, get data in the certificate chain(nounce + UDID + cred). + ret = ValidateCertChainAdapter(credBuff->credVal, credBuff->credLen, &resultInfo); + if (ret != SUCCESS) { + SECURITY_LOG_ERROR("ValidateCertChainAdapter failed!"); + break; + } + + // 2. Parses the NOUNCE into CHALLENGE and PK_INFO_LIST, verifies them separtely. + ret = VerifyNounceOfCertChain((char*)resultInfo.nounce, device, challenge); + if (ret != SUCCESS) { + SECURITY_LOG_ERROR("verifyNounceOfCertChain failed!"); + break; + } + + // 3. The cred content is "
...", parse and vefity it. + ret = VerifyCredData((char*)resultInfo.cred, credInfo); + if (ret != SUCCESS) { + SECURITY_LOG_ERROR("VerifyCredData failed!"); + break; + } + + ret = CheckCredInfo(device, (char*)resultInfo.serialNum, credInfo); + if (ret != SUCCESS) { + SECURITY_LOG_ERROR("CheckCredInfo failed!"); + break; + } + } while (0); + + DestroyCertChainValidateResult(&resultInfo); + SECURITY_LOG_INFO("cred level = %{public}d", credInfo->credLevel); + SECURITY_LOG_INFO("VerifyOhosDslmCred SUCCESS!"); + return ret; } \ No newline at end of file diff --git a/oem_property/ohos/impl/external_interface.c b/oem_property/ohos/impl/external_interface.c new file mode 100644 index 0000000000000000000000000000000000000000..324e90fbb98e9ec7005dec873ea720560c094f2e --- /dev/null +++ b/oem_property/ohos/impl/external_interface.c @@ -0,0 +1,293 @@ +#/* + * Copyright (c) 2022 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 "device_security_defines.h" +#include "external_interface.h" + +#include + +#include "device_auth.h" +#include "hks_api.h" +#include "hks_param.h" +#include "utils_json.h" +#include "utils_log.h" +#include "utils_mem.h" + + +char g_keyData[] = "hi_key_data"; + +#define HKS_TAG_ATTESTATION_ID_UDID (HKS_TAG_TYPE_BYTES | 513) +#define HKS_TAG_ATTESTATION_ID_VERSION_INFO (HKS_TAG_TYPE_BYTES | 514) +#define HKS_INTERFACE_TRANS_PARAM_NUM 2 + +#define UDID_STRING_LENGTH 65 +#define HICHIAN_INPUT_PARAM_STRING_LENGTH 512 +#define CERT_CHAIN_BASE_LENGTH 4096 + +static int32_t HksAttestKey2(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, + struct HksCertChain *certChain) +{ + if ((keyAlias == NULL) || (paramSet == NULL) || (certChain == NULL)) { + return HKS_ERROR_NOT_SUPPORTED; + } + if (certChain->certs == NULL || certChain->certs->data == NULL || + HksCheckParamSet(paramSet, paramSet->paramSetSize) != HKS_SUCCESS) { + return HKS_ERROR_NOT_SUPPORTED; + } + + uint8_t *tmp = certChain->certs->data; + uint32_t offSet = 0; + uint32_t dataLen; + uint32_t totalSize = 0; + for (uint32_t i = 0; i < paramSet->paramsCnt; i++) { + switch (paramSet->params[i].tag) { + case HKS_TAG_ATTESTATION_CHALLENGE: + case HKS_TAG_ATTESTATION_ID_SERIAL: + case HKS_TAG_ATTESTATION_ID_UDID: + case HKS_TAG_ATTESTATION_ID_SEC_LEVEL_INFO: + case HKS_TAG_ATTESTATION_ID_VERSION_INFO: + (void)memcpy_s(tmp + offSet, sizeof(uint32_t), &(paramSet->params[i].tag), sizeof(uint32_t)); + offSet += sizeof(uint32_t); + dataLen = paramSet->params[i].blob.size; + (void)memcpy_s(tmp + offSet, sizeof(uint32_t), &dataLen, sizeof(uint32_t)); + offSet += sizeof(uint32_t); + (void)memcpy_s(tmp + offSet, dataLen, paramSet->params[i].blob.data, dataLen); + offSet += dataLen; + totalSize += (sizeof(uint32_t) * paramSet->paramsCnt + dataLen); + break; + default: + break; + } + } + + certChain->certs->size = totalSize; + certChain->certsCount = HKS_INTERFACE_TRANS_PARAM_NUM; + return HKS_SUCCESS; +} + +static int32_t HksValidateCertChain2(const struct HksCertChain *certChain, struct HksParamSet *paramSetOut) +{ + if (certChain->certsCount != HKS_INTERFACE_TRANS_PARAM_NUM) { + return HKS_ERROR_INVALID_ARGUMENT; + } + + uint8_t *tmp = certChain->certs->data; + uint32_t offSet = 0; + uint32_t dataLen; + struct HksParam tmpParams[5] = {0}; + for (uint32_t i = 0; i < HKS_INTERFACE_TRANS_PARAM_NUM; i++) { + tmpParams[i].tag = *((uint32_t *)(&tmp[offSet])); + offSet += sizeof(uint32_t); + dataLen = *((uint32_t *)(&tmp[offSet])); + tmpParams[i].blob.size = dataLen; + offSet += sizeof(uint32_t); + tmpParams[i].blob.data = (uint8_t *)MALLOC(dataLen); + if (tmpParams[i].blob.data == NULL) { + SECURITY_LOG_INFO("error"); + return HKS_ERROR_MALLOC_FAIL; + } + (void)memcpy_s(tmpParams[i].blob.data, dataLen, tmp + offSet, dataLen); + offSet += dataLen; + } + + uint32_t tmpTag; + for (uint32_t i = 0; i < paramSetOut->paramsCnt; i++) { + tmpTag = paramSetOut->params[i].tag; + switch (tmpTag) { + case HKS_TAG_ATTESTATION_CHALLENGE: + case HKS_TAG_ATTESTATION_ID_SERIAL: + case HKS_TAG_ATTESTATION_ID_UDID: + case HKS_TAG_ATTESTATION_ID_SEC_LEVEL_INFO: + case HKS_TAG_ATTESTATION_ID_VERSION_INFO: + for (uint32_t i = 0; i < HKS_INTERFACE_TRANS_PARAM_NUM; i++) { + if (tmpTag == tmpParams[i].tag) { + paramSetOut->params[i].blob.size = tmpParams[i].blob.size; + (void)memcpy_s(paramSetOut->params[i].blob.data, tmpParams[i].blob.size, tmpParams[i].blob.data, + tmpParams[i].blob.size); + } else { + continue; + } + } + break; + default: + break; + } + } + return HKS_SUCCESS; +} + +static int32_t GenerateFuncParamJson(bool isSelfPk, const char *udidStr, char *dest, uint32_t destMax) +{ + JsonHandle json = CreateJson(NULL); + if (json == NULL) { + return ERR_INVALID_PARA; + } + + AddFieldBoolToJson(json, "isSelfPk", isSelfPk); + AddFieldStringToJson(json, "udid", udidStr); + + char *paramsJsonBuffer = ConvertJsonToString(json); + if (paramsJsonBuffer == NULL) { + DestroyJson(json); + return ERR_MEMORY_ERR; + } + DestroyJson(json); + if (strcpy_s(dest, destMax, paramsJsonBuffer) != EOK) { + FREE(paramsJsonBuffer); + paramsJsonBuffer = NULL; + return ERR_MEMORY_ERR; + } + FREE(paramsJsonBuffer); + paramsJsonBuffer = NULL; + return SUCCESS; +} + +int32_t GetPkInfoListStr(bool isSelf, const uint8_t *udid, uint32_t udidLen, char **pkInfoList) +{ + SECURITY_LOG_INFO("GetPkInfoListStr start"); + + char udidStr[UDID_STRING_LENGTH] = {0}; + char paramJson[HICHIAN_INPUT_PARAM_STRING_LENGTH] = {0}; + char resultBuffer[] = "temp data"; + + if (memcpy_s(udidStr, UDID_STRING_LENGTH, udid, udidLen) != EOK) { + return ERR_MEMORY_ERR; + } + int32_t ret = GenerateFuncParamJson(isSelf, udidStr, ¶mJson[0], HICHIAN_INPUT_PARAM_STRING_LENGTH); + if (ret != SUCCESS) { + SECURITY_LOG_INFO("GenerateFuncParamJson failed"); + return ret; + } + + *pkInfoList = (char*)MALLOC(strlen(resultBuffer) + 1); + if (strcpy_s(*pkInfoList, strlen(resultBuffer) + 1, resultBuffer) != EOK) { + return ERR_MEMORY_ERR; + } + SECURITY_LOG_INFO("pkinfo = %{public}s", *pkInfoList); + return SUCCESS; +} + +int DslmCredAttestAdapter(char *nounceStr, char *credStr, uint8_t **certChain, uint32_t *certChainLen) +{ + SECURITY_LOG_INFO("DslmCredAttestAdapter start"); + + struct HksParam inputData[] = { + {.tag = HKS_TAG_ATTESTATION_CHALLENGE, .blob = {strlen(nounceStr) + 1, (uint8_t *)nounceStr}}, + {.tag = HKS_TAG_ATTESTATION_ID_SEC_LEVEL_INFO, .blob = {strlen(credStr) + 1, (uint8_t *)credStr}}, + }; + struct HksParamSet *inputParam = NULL; + if (HksInitParamSet(&inputParam) != HKS_SUCCESS) { + SECURITY_LOG_INFO("DslmCredAttestAdapter error 1"); + return -1; + } + if (HksAddParams(inputParam, inputData, sizeof(inputData) / sizeof(inputData[0])) != HKS_SUCCESS) { + SECURITY_LOG_INFO("DslmCredAttestAdapter error 2"); + return -1; + } + if (HksBuildParamSet(&inputParam) != HKS_SUCCESS) { + SECURITY_LOG_INFO("DslmCredAttestAdapter error 3"); + return -1; + } + + uint32_t certChainMaxLen = strlen(nounceStr) + strlen(credStr) + CERT_CHAIN_BASE_LENGTH; + *certChain = (uint8_t *)malloc(certChainMaxLen); + struct HksBlob certChainBlob = {certChainMaxLen, *certChain}; + struct HksCertChain hksCertChain = {&certChainBlob, HKS_INTERFACE_TRANS_PARAM_NUM}; + + const struct HksBlob keyAlias = { sizeof(g_keyData), (uint8_t*)g_keyData }; + + int32_t ret = HksAttestKey2(&keyAlias, inputParam, &hksCertChain); + if (ret != HKS_SUCCESS) { + SECURITY_LOG_INFO("HksAttestKey ret = %{public}d ", ret); + return ret; + } + *certChainLen = certChainBlob.size; + SECURITY_LOG_INFO("DslmCredAttestAdapter success, certChainLen = %{public}d ", *certChainLen); + return SUCCESS; +} + +int ValidateCertChainAdapter(uint8_t *data, uint32_t dataLen, struct CertChainValidateResult *resultInfo) +{ + SECURITY_LOG_INFO("ValidateCertChainAdapter start"); + struct HksParam outputData[] = { + {.tag = HKS_TAG_ATTESTATION_CHALLENGE, .blob = {resultInfo->nounceLen, resultInfo->nounce}}, + {.tag = HKS_TAG_ATTESTATION_ID_SEC_LEVEL_INFO, .blob = {resultInfo->credLen, resultInfo->cred}}, + }; + struct HksParamSet *outputParam = NULL; + if (HksInitParamSet(&outputParam) != HKS_SUCCESS) { + return -1; + } + if (HksAddParams(outputParam, outputData, sizeof(outputData) / sizeof(outputData[0])) != HKS_SUCCESS) { + return -1; + } + if (HksBuildParamSet(&outputParam) != HKS_SUCCESS) { + return -1; + } + + struct HksBlob certChainBlob = {dataLen, data}; + struct HksCertChain hksCertChain = {&certChainBlob, HKS_INTERFACE_TRANS_PARAM_NUM}; + int32_t ret = HksValidateCertChain2(&hksCertChain, outputParam); + if (ret != HKS_SUCCESS) { + SECURITY_LOG_INFO("HksValidateCertChain error, ret = %{public}d", ret); + return ERR_CALL_EXTERNAL_FUNC; + } + // fix + resultInfo->nounceLen = strlen((char *)outputParam->params[0].blob.data); + memcpy_s(resultInfo->nounce, resultInfo->nounceLen + 1, outputParam->params[0].blob.data, + resultInfo->nounceLen + 1); + resultInfo->credLen = strlen((char *)outputParam->params[1].blob.data); + memcpy_s(resultInfo->cred, resultInfo->credLen + 1, outputParam->params[1].blob.data, resultInfo->credLen + 1); + + SECURITY_LOG_INFO("resultInfo nounce len = %{public}d", resultInfo->nounceLen); + SECURITY_LOG_INFO("resultInfo cred len = %{public}d", resultInfo->credLen); + + SECURITY_LOG_INFO("resultInfo nounce = %{public}s", (char *)resultInfo->nounce); + SECURITY_LOG_INFO("resultInfo cred = %{public}s", (char *)resultInfo->cred); + + return SUCCESS; +} + +void InitCertChainValidateResult(struct CertChainValidateResult *resultInfo, uint32_t maxLen) +{ + (void)memset_s(resultInfo, sizeof(struct CertChainValidateResult), 0, sizeof(struct CertChainValidateResult)); + resultInfo->nounce = (uint8_t *)MALLOC(maxLen); + resultInfo->nounceLen = maxLen; + resultInfo->cred = (uint8_t *)MALLOC(maxLen); + resultInfo->credLen = maxLen; +} + +void DestroyCertChainValidateResult(struct CertChainValidateResult *resultInfo) +{ + if (resultInfo == NULL) { + return; + } + if (resultInfo->udid != NULL) { + FREE(resultInfo->udid); + resultInfo->udid = NULL; + } + if (resultInfo->nounce != NULL) { + FREE(resultInfo->nounce); + resultInfo->nounce = NULL; + } + if (resultInfo->cred != NULL) { + FREE(resultInfo->cred); + resultInfo->cred = NULL; + } + if (resultInfo->serialNum != NULL) { + FREE(resultInfo->serialNum); + resultInfo->serialNum = NULL; + } + (void)memset_s(resultInfo, sizeof(struct CertChainValidateResult), 0, sizeof(struct CertChainValidateResult)); +} \ No newline at end of file diff --git a/oem_property/ohos/impl/external_interface.h b/oem_property/ohos/impl/external_interface.h new file mode 100644 index 0000000000000000000000000000000000000000..53a0bf29b90fa0ac563cc4b9d77de52e153979b7 --- /dev/null +++ b/oem_property/ohos/impl/external_interface.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef EXTERNAL_INTERFACE_H +#define EXTERNAL_INTERFACE_H + +#include +#include + +struct CertChainValidateResult { + uint8_t *udid; + uint32_t udidLen; + uint8_t *nounce; + uint32_t nounceLen; + uint8_t *cred; + uint32_t credLen; + uint8_t *serialNum; + uint32_t serialNumLen; +}; + +int GetPkInfoListStr(bool isSelf, const uint8_t *udid, uint32_t udidLen, char **pkInfoList); +int DslmCredAttestAdapter(char *nounceStr, char *credStr, uint8_t **certChain, uint32_t *certChainLen); +int ValidateCertChainAdapter(uint8_t *data, uint32_t dataLen, struct CertChainValidateResult *resultInfo); + +void InitCertChainValidateResult(struct CertChainValidateResult *resultInfo, uint32_t maxLen); +void DestroyCertChainValidateResult(struct CertChainValidateResult *resultInfo); + +#endif // EXTERNAL_INTERFACE_H \ No newline at end of file diff --git a/profile/dslm_service.cfg b/profile/dslm_service.cfg index b4537c57130c8905bc5d324da8bc097ee1ba4571..be15958a03364f2ee42cdc2c526810abf21b0f65 100644 --- a/profile/dslm_service.cfg +++ b/profile/dslm_service.cfg @@ -10,8 +10,7 @@ "name" : "dslm_service", "path" : ["/system/bin/sa_main", "/system/profile/dslm_service.xml"], "uid" : "system", - "gid" : ["system", "shell"], - "secon" : "u:r:dslm_service:s0" + "gid" : ["system", "shell"] } ] -} \ No newline at end of file +} diff --git a/services/common/dslm_crypto.c b/services/common/dslm_crypto.c index 491d5da14104487597044e5bc23579447a24819b..4b8889e9e70a8b443166f44b78c208e0210e10ac 100644 --- a/services/common/dslm_crypto.c +++ b/services/common/dslm_crypto.c @@ -15,7 +15,12 @@ #include "dslm_crypto.h" +#include #include +#include + +#include "device_security_defines.h" +#include "utils_log.h" void GenerateRandom(RandomValue *rand, uint32_t length) { @@ -25,4 +30,62 @@ void GenerateRandom(RandomValue *rand, uint32_t length) rand->length = (length > RAMDOM_MAX_LEN) ? RAMDOM_MAX_LEN : length; RAND_bytes(&rand->value[0], rand->length); +} + +int32_t EcdsaVerify(const struct DataBuffer *srcData, const struct DataBuffer *sigData, + const struct DataBuffer *pbkData, uint32_t algorithm) +{ + if (srcData == NULL || sigData == NULL || pbkData == NULL) { + return ERR_INVALID_PARA; + } + if (srcData->data == NULL || sigData->data == NULL || pbkData->data == NULL || srcData->length == 0 || + sigData->length == 0 || pbkData->length == 0) { + return ERR_INVALID_PARA; + } + if ((algorithm != TYPE_ECDSA_SHA_256) && (algorithm != TYPE_ECDSA_SHA_384)) { + return ERR_INVALID_PARA; + } + + int32_t ret = ERR_ECC_VERIFY_ERR; + uint8_t *publicKey = pbkData->data; + const EVP_MD *type = (algorithm == TYPE_ECDSA_SHA_256) ? EVP_sha256() : EVP_sha384(); + EVP_PKEY *pkey = d2i_PUBKEY(NULL, (const unsigned char **)&(publicKey), pbkData->length); + if (pkey == NULL) { + return ret; + } + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + if (ctx == NULL) { + EVP_PKEY_free(pkey); + return ret; + } + + do { + ret = EVP_DigestVerifyInit(ctx, NULL, type, NULL, pkey); + if (ret != 1) { + break; + } + if (srcData == NULL) { + SECURITY_LOG_ERROR("srcData NULL!"); + } + ret = EVP_DigestUpdate(ctx, srcData->data, srcData->length); + if (ret != 1) { + break; + } + if (EVP_DigestVerifyFinal(ctx, sigData->data, sigData->length) <= 0) { + break; + } + ret = SUCCESS; + } while (0); + + EVP_PKEY_free(pkey); + EVP_MD_CTX_free(ctx); + return ret; +} + +void CallHashSha256(const uint8_t *data, uint32_t dataLen, uint8_t *out) +{ + SHA256_CTX sctx; + SHA256_Init(&sctx); + SHA256_Update(&sctx, data, dataLen); + SHA256_Final(out, &sctx); } \ No newline at end of file diff --git a/services/include/dslm_crypto.h b/services/include/dslm_crypto.h index c4b75155dfb15428de6a04e3195d1a0d48c69d17..32ea666b5d4d6053ab57ac9071fff5259c4776f9 100644 --- a/services/include/dslm_crypto.h +++ b/services/include/dslm_crypto.h @@ -21,6 +21,9 @@ #define RAMDOM_MAX_LEN 32 +#define TYPE_ECDSA_SHA_256 0 +#define TYPE_ECDSA_SHA_384 1 + #ifdef __cplusplus extern "C" { #endif @@ -30,7 +33,15 @@ typedef struct RandomValue { uint8_t value[RAMDOM_MAX_LEN]; } RandomValue; +struct DataBuffer { + uint8_t *data; + uint32_t length; +}; + void GenerateRandom(RandomValue *rand, uint32_t length); +int32_t EcdsaVerify(const struct DataBuffer *srcData, const struct DataBuffer *sigData, + const struct DataBuffer *pbkData, uint32_t algorithm); +void CallHashSha256(const uint8_t *data, uint32_t dataLen, uint8_t *out); #ifdef __cplusplus }