diff --git a/default_config/standard/config.gni b/default_config/standard/config.gni index de40511..aea7480 100644 --- a/default_config/standard/config.gni +++ b/default_config/standard/config.gni @@ -13,7 +13,7 @@ declare_args() { enable_group = true - enable_account = false + enable_account = true enable_p2p_bind_lite_protocol = true enable_p2p_auth_lite_protocol = true diff --git a/deps_adapter/BUILD.gn b/deps_adapter/BUILD.gn index 28df2d9..c3c61e0 100644 --- a/deps_adapter/BUILD.gn +++ b/deps_adapter/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (C) 2021 Huawei Device Co., Ltd. +# Copyright (C) 2021-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 @@ -63,12 +63,13 @@ if (defined(ohos_lite)) { "//base/hiviewdfx/hilog_lite/interfaces/native/innerkits/hilog", "//third_party/bounds_checking_function/include", "//base/startup/syspara_lite/interfaces/kits/", + "//third_party/mbedtls/include", ] sources = hal_common_files sources += [ "${key_management_adapter_path}/impl/src/small/huks_adapter.c", - "${key_management_adapter_path}/impl/src/small/mbedtls_hash_to_point.c", + "${key_management_adapter_path}/impl/src/small/mbedtls_ec_adapter.c", "${os_adapter_path}/impl/src/linux/hc_condition.c", "${os_adapter_path}/impl/src/linux/hc_dev_info.c", "${os_adapter_path}/impl/src/linux/hc_file.c", @@ -79,7 +80,6 @@ if (defined(ohos_lite)) { cflags = [ "-DHILOG_ENABLE" ] defines = [ "LITE_DEVICE" ] - deps = [ "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared", "//base/security/huks/interfaces/innerkits/huks_lite:huks_3.0_sdk", @@ -102,12 +102,15 @@ if (defined(ohos_lite)) { "//third_party/openssl/include/", "//base/security/huks/interfaces/innerkits/huks_standard/main/include", "//base/startup/syspara_lite/interfaces/innerkits/native/syspara/include", + "//third_party/mbedtls/include", + "//third_party/mbedtls/include/mbedtls", ] sources = hal_common_files sources += [ "${key_management_adapter_path}/impl/src/standard/crypto_hash_to_point.c", "${key_management_adapter_path}/impl/src/standard/huks_adapter.c", + "${key_management_adapter_path}/impl/src/standard/mbedtls_ec_adapter.c", "${os_adapter_path}/impl/src/linux/hc_condition.c", "${os_adapter_path}/impl/src/linux/hc_dev_info.c", "${os_adapter_path}/impl/src/linux/hc_file.c", @@ -120,6 +123,7 @@ if (defined(ohos_lite)) { "//base/security/huks/interfaces/innerkits/huks_standard/main:libhukssdk", "//base/startup/syspara_lite/interfaces/innerkits/native/syspara:syspara", "//third_party/cJSON:cjson_static", + "//third_party/mbedtls:mbedtls_shared", "//third_party/openssl:libcrypto_static", "//utils/native/base:utils", ] diff --git a/deps_adapter/key_management_adapter/impl/inc/mbedtls_hash_to_point.h b/deps_adapter/key_management_adapter/impl/inc/mbedtls_ec_adapter.h similarity index 75% rename from deps_adapter/key_management_adapter/impl/inc/mbedtls_hash_to_point.h rename to deps_adapter/key_management_adapter/impl/inc/mbedtls_ec_adapter.h index 574eaf6..1a5cb90 100644 --- a/deps_adapter/key_management_adapter/impl/inc/mbedtls_hash_to_point.h +++ b/deps_adapter/key_management_adapter/impl/inc/mbedtls_ec_adapter.h @@ -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 @@ -13,11 +13,12 @@ * limitations under the License. */ -#ifndef MBEDTLS_HASH_TO_POINT_H -#define MBEDTLS_HASH_TO_POINT_H +#ifndef MBEDTLS_EC_ADAPTER_H +#define MBEDTLS_EC_ADAPTER_H #include #include "string_util.h" +#include "alg_defs.h" #define HASH2POINT_PARA_PREPRO 0xc0 #define BYTE_LENGTH_CURVE_25519 32 @@ -27,8 +28,9 @@ extern "C" { #endif int32_t MbedtlsHashToPoint(const Uint8Buff *hash, Uint8Buff *outEcPoint); +int32_t MbedtlsAgreeSharedSecret(const KeyBuff *priKey, const KeyBuff *pubKey, Uint8Buff *sharedKey); #ifdef __cplusplus } #endif -#endif \ No newline at end of file +#endif diff --git a/deps_adapter/key_management_adapter/impl/src/small/huks_adapter.c b/deps_adapter/key_management_adapter/impl/src/small/huks_adapter.c index 5e4d1d4..2f91c4d 100644 --- a/deps_adapter/key_management_adapter/impl/src/small/huks_adapter.c +++ b/deps_adapter/key_management_adapter/impl/src/small/huks_adapter.c @@ -18,7 +18,7 @@ #include "hks_api.h" #include "hks_param.h" #include "hks_type.h" -#include "mbedtls_hash_to_point.h" +#include "mbedtls_ec_adapter.h" #include "string_util.h" static enum HksKeyAlg g_algToHksAlgorithm[] = { @@ -619,6 +619,9 @@ static int32_t ConstructGenerateKeyPairWithStorageParams(struct HksParamSet **pa }, { .tag = HKS_TAG_KEY_AUTH_ID, .blob = *authIdBlob + }, { + .tag = HKS_TAG_DIGEST, + .uint32Param = HKS_DIGEST_SHA256 } }; @@ -804,7 +807,10 @@ static int32_t ConstructSignParams(struct HksParamSet **paramSet, Algorithm algo .uint32Param = HKS_KEY_PURPOSE_SIGN }, { .tag = HKS_TAG_ALGORITHM, - .uint32Param = g_algToHksAlgorithm[algo] // only support HKS_ALG_ED25519 + .uint32Param = g_algToHksAlgorithm[algo] // only support HKS_ALG_ED25519 and HKS_ALG_ECC. + }, { + .tag = HKS_TAG_DIGEST, + .uint32Param = HKS_DIGEST_SHA256 } }; @@ -826,7 +832,6 @@ static int32_t Sign(const Uint8Buff *keyAlias, const Uint8Buff *message, Algorit if (ret != HAL_SUCCESS) { return ret; } - CHECK_LEN_EQUAL_RETURN(outSignature->length, SIGNATURE_LEN, "outSignature->length"); struct HksBlob keyAliasBlob = { keyAlias->length, keyAlias->val }; Uint8Buff messageHash = { NULL, 0 }; @@ -851,11 +856,12 @@ static int32_t Sign(const Uint8Buff *keyAlias, const Uint8Buff *message, Algorit } ret = HksSign(&keyAliasBlob, paramSet, &messageBlob, &signatureBlob); - if ((ret != HKS_SUCCESS) || (signatureBlob.size != SIGNATURE_LEN)) { + if (ret != HKS_SUCCESS) { LOGE("Hks sign failed."); ret = HAL_FAILED; goto ERR; } + outSignature->length = signatureBlob.size; ret = HAL_SUCCESS; ERR: HksFreeParamSet(¶mSet); @@ -871,10 +877,13 @@ static int32_t ConstructVerifyParams(struct HksParamSet **paramSet, Algorithm al .uint32Param = HKS_KEY_PURPOSE_VERIFY }, { .tag = HKS_TAG_ALGORITHM, - .uint32Param = g_algToHksAlgorithm[algo] // only support HKS_ALG_ED25519 + .uint32Param = g_algToHksAlgorithm[algo] // only support HKS_ALG_ED25519 and HKS_ALG_ECC. }, { .tag = HKS_TAG_IS_KEY_ALIAS, .boolParam = isAlias + }, { + .tag = HKS_TAG_DIGEST, + .uint32Param = HKS_DIGEST_SHA256 } }; @@ -896,7 +905,6 @@ static int32_t Verify(const Uint8Buff *key, const Uint8Buff *message, Algorithm if (ret != HAL_SUCCESS) { return ret; } - CHECK_LEN_EQUAL_RETURN(signature->length, SIGNATURE_LEN, "signature"); struct HksBlob keyAliasBlob = { key->length, key->val }; Uint8Buff messageHash = { NULL, 0 }; @@ -936,6 +944,9 @@ ERR: static int32_t ConstructImportPublicKeyParams(struct HksParamSet **paramSet, Algorithm algo, uint32_t keyLen, const struct HksBlob *authIdBlob, const union KeyRoleInfoUnion *roleInfoUnion) { + if (g_algToHksAlgorithm[algo] == HKS_ALG_ECC) { + keyLen = ECC_PK_LEN; + } struct HksParam importParam[] = { { .tag = HKS_TAG_ALGORITHM, diff --git a/deps_adapter/key_management_adapter/impl/src/small/mbedtls_hash_to_point.c b/deps_adapter/key_management_adapter/impl/src/small/mbedtls_ec_adapter.c similarity index 94% rename from deps_adapter/key_management_adapter/impl/src/small/mbedtls_hash_to_point.c rename to deps_adapter/key_management_adapter/impl/src/small/mbedtls_ec_adapter.c index 42e457d..42f5bb2 100644 --- a/deps_adapter/key_management_adapter/impl/src/small/mbedtls_hash_to_point.c +++ b/deps_adapter/key_management_adapter/impl/src/small/mbedtls_ec_adapter.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 @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "mbedtls_hash_to_point.h" +#include "mbedtls_ec_adapter.h" #include #include #include "securec.h" @@ -279,3 +279,10 @@ int32_t MbedtlsHashToPoint(const Uint8Buff *hash, Uint8Buff *outEcPoint) } return status; } + +// only support P256 AgreeSharedSecret for standard system +int32_t MbedtlsAgreeSharedSecret(const KeyBuff *priKey, const KeyBuff *pubKey, Uint8Buff *sharedKey) +{ + LOGE("MbedtlsAgreeSharedSecret for P256 is not supported now in small system."); + return HAL_ERR_NOT_SUPPORTED; +} \ No newline at end of file diff --git a/deps_adapter/key_management_adapter/impl/src/standard/huks_adapter.c b/deps_adapter/key_management_adapter/impl/src/standard/huks_adapter.c index 44b9665..41882e8 100644 --- a/deps_adapter/key_management_adapter/impl/src/standard/huks_adapter.c +++ b/deps_adapter/key_management_adapter/impl/src/standard/huks_adapter.c @@ -19,10 +19,12 @@ #include "hks_api.h" #include "hks_param.h" #include "hks_type.h" +#include "mbedtls_ec_adapter.h" #include "string_util.h" #define BASE_IMPORT_PARAMS_LEN 7 #define EXT_IMPORT_PARAMS_LEN 2 +#define ECDH_COMMON_SIZE_P256 512 static enum HksKeyPurpose g_purposeToHksKeyPurpose[] = { HKS_KEY_PURPOSE_MAC, @@ -419,29 +421,135 @@ static int32_t AesGcmDecrypt(const Uint8Buff *key, const Uint8Buff *cipher, static int32_t HashToPoint(const Uint8Buff *hash, Algorithm algo, Uint8Buff *outEcPoint) { CHECK_PTR_RETURN_HAL_ERROR_CODE(hash, "hash"); - CHECK_PTR_RETURN_HAL_ERROR_CODE(hash->val, "hash->va"); + CHECK_PTR_RETURN_HAL_ERROR_CODE(hash->val, "hash->val"); CHECK_LEN_EQUAL_RETURN(hash->length, SHA256_LEN, "hash->length"); CHECK_PTR_RETURN_HAL_ERROR_CODE(outEcPoint, "outEcPoint"); - CHECK_PTR_RETURN_HAL_ERROR_CODE(outEcPoint->val, "outEcPoint->va"); - CHECK_LEN_EQUAL_RETURN(outEcPoint->length, SHA256_LEN, "outEcPoint->length"); + CHECK_PTR_RETURN_HAL_ERROR_CODE(outEcPoint->val, "outEcPoint->val"); - if (algo != X25519) { - LOGE("Invalid algo: %d.", algo); + if (algo != X25519 && algo != P256) { + LOGE("Compute algo: %d.", algo); return HAL_ERR_INVALID_PARAM; } + if (algo == P256) { + LOGI("Compute HashToPoint for P256"); + return MbedtlsHashToPoint(hash, outEcPoint); + } + CHECK_LEN_EQUAL_RETURN(outEcPoint->length, SHA256_LEN, "outEcPoint->length"); struct HksBlob hashBlob = { hash->length, hash->val }; struct HksBlob pointBlob = { outEcPoint->length, outEcPoint->val }; int32_t ret = OpensslHashToPoint(&hashBlob, &pointBlob); if (ret != HAL_SUCCESS || pointBlob.size != SHA256_LEN) { - LOGE("Hks hashToPoint failed, ret: %d", ret); + LOGE("HashToPoint for x25519 failed, ret: %d", ret); return HAL_FAILED; } return HAL_SUCCESS; } +static int32_t ConstructInitParamsP256(struct HksParamSet **initParamSet) +{ + struct HksParam agreeParamInit[] = { + { + .tag = HKS_TAG_ALGORITHM, + .uint32Param = HKS_ALG_ECDH + }, { + .tag = HKS_TAG_PURPOSE, + .uint32Param = HKS_KEY_PURPOSE_AGREE + }, { + .tag = HKS_TAG_KEY_SIZE, + .uint32Param = HKS_ECC_KEY_SIZE_256 + } + }; + int32_t ret = ConstructParamSet(initParamSet, agreeParamInit, CAL_ARRAY_SIZE(agreeParamInit)); + if (ret != HAL_SUCCESS) { + LOGE("Construct init param set failed for P256, ret = %d", ret); + } + return ret; +} + +static int32_t ConstructFinishParamsP256(struct HksParamSet **finishParamSet, + const struct HksBlob *sharedKeyAliasBlob) +{ + struct HksParam agreeParamFinish[] = { + { + .tag = HKS_TAG_KEY_STORAGE_FLAG, + .uint32Param = HKS_STORAGE_PERSISTENT + }, { + .tag = HKS_TAG_IS_KEY_ALIAS, + .boolParam = true + }, { + .tag = HKS_TAG_ALGORITHM, + .uint32Param = HKS_ALG_AES + }, { + .tag = HKS_TAG_KEY_SIZE, + .uint32Param = HKS_AES_KEY_SIZE_256 + }, { + .tag = HKS_TAG_PURPOSE, + .uint32Param = HKS_KEY_PURPOSE_DERIVE + }, { + .tag = HKS_TAG_DIGEST, + .uint32Param = HKS_DIGEST_SHA256 + }, { + .tag = HKS_TAG_KEY_ALIAS, + .blob = *sharedKeyAliasBlob + } + }; + int32_t ret = ConstructParamSet(finishParamSet, agreeParamFinish, CAL_ARRAY_SIZE(agreeParamFinish)); + if (ret != HAL_SUCCESS) { + LOGE("Construct finish param set failed for P256, ret = %d", ret); + } + return ret; +} + +static int32_t AgreeSharedSecretWithStorageP256(const KeyBuff *priKeyAlias, const KeyBuff *pubKey, + const struct HksBlob *sharedKeyAliasBlob) +{ + struct HksParamSet *initParamSet = NULL; + struct HksParamSet *finishParamSet = NULL; + int32_t ret = ConstructInitParamsP256(&initParamSet); + if (ret != HAL_SUCCESS) { + return ret; + } + ret = ConstructFinishParamsP256(&finishParamSet, sharedKeyAliasBlob); + if (ret != HAL_SUCCESS) { + HksFreeParamSet(&initParamSet); + return ret; + } + struct HksBlob priKeyAliasBlob = { priKeyAlias->keyLen, priKeyAlias->key }; + struct HksBlob pubKeyBlob = { pubKey->keyLen, pubKey->key }; + uint8_t handle[sizeof(uint64_t)] = { 0 }; + struct HksBlob handleBlob = { sizeof(uint64_t), handle }; + uint8_t outDataUpdate[ECDH_COMMON_SIZE_P256] = { 0 }; + struct HksBlob outDataUpdateBlob = { ECDH_COMMON_SIZE_P256, outDataUpdate }; + uint8_t outDataFinish[ECDH_COMMON_SIZE_P256] = { 0 }; + struct HksBlob outDataFinishBlob = { ECDH_COMMON_SIZE_P256, outDataFinish }; + do { + ret = HksInit(&priKeyAliasBlob, initParamSet, &handleBlob); + if (ret != HKS_SUCCESS) { + LOGE("Huks agree P256 key: HksInit failed, ret = %d", ret); + ret = HAL_ERR_HUKS; + break; + } + ret = HksUpdate(&handleBlob, initParamSet, &pubKeyBlob, &outDataUpdateBlob); + if (ret != HKS_SUCCESS) { + LOGE("Huks agree P256 key: HksUpdate failed, ret = %d", ret); + ret = HAL_ERR_HUKS; + break; + } + ret = HksFinish(&handleBlob, finishParamSet, &pubKeyBlob, &outDataFinishBlob); + if (ret != HKS_SUCCESS) { + LOGE("Huks agree P256 key: HksFinish failed, ret = %d", ret); + ret = HAL_ERR_HUKS; + break; + } + } while (0); + HksFreeParamSet(&initParamSet); + HksFreeParamSet(&finishParamSet); + return ret; +} + static int32_t ConstructAgreeWithStorageParams(struct HksParamSet **paramSet, uint32_t keyLen, Algorithm algo, const KeyBuff *priKey, const KeyBuff *pubKey) { @@ -465,7 +573,7 @@ static int32_t ConstructAgreeWithStorageParams(struct HksParamSet **paramSet, ui .uint32Param = HKS_KEY_GENERATE_TYPE_AGREE }, { .tag = HKS_TAG_AGREE_ALG, - .uint32Param = g_algToHksAlgorithm[algo] + .uint32Param = g_algToHksAlgorithm[algo] // only support HKS_ALG_ED25519 and HKS_ALG_X25519 }, { .tag = HKS_TAG_AGREE_PRIVATE_KEY_ALIAS, .blob = priKeyBlob @@ -481,7 +589,6 @@ static int32_t ConstructAgreeWithStorageParams(struct HksParamSet **paramSet, ui int32_t ret = ConstructParamSet(paramSet, agreeParam, CAL_ARRAY_SIZE(agreeParam)); if (ret != HAL_SUCCESS) { LOGE("Construct param set failed, ret = %d", ret); - return ret; } return ret; } @@ -501,6 +608,10 @@ static int32_t AgreeSharedSecretWithStorage(const KeyBuff *priKey, const KeyBuff CHECK_LEN_ZERO_RETURN_ERROR_CODE(sharedKeyLen, "sharedKeyLen"); struct HksBlob sharedKeyAliasBlob = { sharedKeyAlias->length, sharedKeyAlias->val }; + if (g_algToHksAlgorithm[algo] == HKS_ALG_ECC) { + LOGI("Hks agree key with storage for P256."); + return AgreeSharedSecretWithStorageP256(priKey, pubKey, &sharedKeyAliasBlob); + } struct HksParamSet *paramSet = NULL; int32_t ret = ConstructAgreeWithStorageParams(¶mSet, sharedKeyLen, algo, priKey, pubKey); if (ret != HAL_SUCCESS) { @@ -530,6 +641,11 @@ static int32_t AgreeSharedSecret(const KeyBuff *priKey, const KeyBuff *pubKey, A CHECK_PTR_RETURN_HAL_ERROR_CODE(sharedKey->val, "sharedKey->val"); CHECK_LEN_ZERO_RETURN_ERROR_CODE(sharedKey->length, "sharedKey->length"); + if (g_algToHksAlgorithm[algo] == HKS_ALG_ECC) { + LOGI("Hks agree key for P256."); + return MbedtlsAgreeSharedSecret(priKey, pubKey, sharedKey); + } + struct HksBlob priKeyBlob = { priKey->keyLen, priKey->key }; struct HksBlob pubKeyBlob = { pubKey->keyLen, pubKey->key }; struct HksBlob sharedKeyBlob = { sharedKey->length, sharedKey->val }; @@ -630,6 +746,9 @@ static int32_t ConstructGenerateKeyPairWithStorageParams(struct HksParamSet **pa }, { .tag = HKS_TAG_KEY_AUTH_ID, .blob = *authIdBlob + }, { + .tag = HKS_TAG_DIGEST, + .uint32Param = HKS_DIGEST_SHA256 } }; @@ -815,7 +934,10 @@ static int32_t ConstructSignParams(struct HksParamSet **paramSet, Algorithm algo .uint32Param = HKS_KEY_PURPOSE_SIGN }, { .tag = HKS_TAG_ALGORITHM, - .uint32Param = g_algToHksAlgorithm[algo] // only support HKS_ALG_ED25519 + .uint32Param = g_algToHksAlgorithm[algo] // only support HKS_ALG_ED25519 and HKS_ALG_ECC. + }, { + .tag = HKS_TAG_DIGEST, + .uint32Param = HKS_DIGEST_SHA256 } }; @@ -837,7 +959,6 @@ static int32_t Sign(const Uint8Buff *keyAlias, const Uint8Buff *message, Algorit if (ret != HAL_SUCCESS) { return ret; } - CHECK_LEN_EQUAL_RETURN(outSignature->length, SIGNATURE_LEN, "outSignature->length"); struct HksBlob keyAliasBlob = { keyAlias->length, keyAlias->val }; Uint8Buff messageHash = { NULL, 0 }; @@ -862,11 +983,12 @@ static int32_t Sign(const Uint8Buff *keyAlias, const Uint8Buff *message, Algorit } ret = HksSign(&keyAliasBlob, paramSet, &messageBlob, &signatureBlob); - if ((ret != HKS_SUCCESS) || (signatureBlob.size != SIGNATURE_LEN)) { + if (ret != HKS_SUCCESS) { LOGE("Hks sign failed."); ret = HAL_FAILED; goto ERR; } + outSignature->length = signatureBlob.size; ret = HAL_SUCCESS; ERR: HksFreeParamSet(¶mSet); @@ -882,10 +1004,13 @@ static int32_t ConstructVerifyParams(struct HksParamSet **paramSet, Algorithm al .uint32Param = HKS_KEY_PURPOSE_VERIFY }, { .tag = HKS_TAG_ALGORITHM, - .uint32Param = g_algToHksAlgorithm[algo] // only support HKS_ALG_ED25519 + .uint32Param = g_algToHksAlgorithm[algo] // only support HKS_ALG_ED25519 and HKS_ALG_ECC. }, { .tag = HKS_TAG_IS_KEY_ALIAS, .boolParam = isAlias + }, { + .tag = HKS_TAG_DIGEST, + .uint32Param = HKS_DIGEST_SHA256 } }; @@ -907,7 +1032,6 @@ static int32_t Verify(const Uint8Buff *key, const Uint8Buff *message, Algorithm if (ret != HAL_SUCCESS) { return ret; } - CHECK_LEN_EQUAL_RETURN(signature->length, SIGNATURE_LEN, "signature"); struct HksBlob keyAliasBlob = { key->length, key->val }; Uint8Buff messageHash = { NULL, 0 }; @@ -947,6 +1071,9 @@ ERR: static int32_t ConstructImportPublicKeyParams(struct HksParamSet **paramSet, Algorithm algo, uint32_t keyLen, const struct HksBlob *authIdBlob, const union KeyRoleInfoUnion *roleInfoUnion) { + if (g_algToHksAlgorithm[algo] == HKS_ALG_ECC) { + keyLen = ECC_PK_LEN; + } struct HksParam importParam[] = { { .tag = HKS_TAG_ALGORITHM, @@ -1129,6 +1256,13 @@ static bool CheckDlPublicKey(const Uint8Buff *key, const char *primeHex) return true; } +static bool CheckEcPublicKeyFuncFake(const Uint8Buff *pubKey, Algorithm algo) +{ + (void)pubKey; + (void)algo; + return true; +} + static int32_t CheckImportSymmetricKeyParam(const Uint8Buff *keyAlias, const Uint8Buff *authToken) { const Uint8Buff *inParams[] = { keyAlias, authToken }; @@ -1244,7 +1378,7 @@ static const AlgLoader g_huksLoader = { .verify = Verify, .importPublicKey = ImportPublicKey, .checkDlPublicKey = CheckDlPublicKey, - .checkEcPublicKey = NULL, + .checkEcPublicKey = CheckEcPublicKeyFuncFake, .bigNumCompare = BigNumCompare }; diff --git a/deps_adapter/key_management_adapter/impl/src/standard/mbedtls_ec_adapter.c b/deps_adapter/key_management_adapter/impl/src/standard/mbedtls_ec_adapter.c new file mode 100644 index 0000000..1b7063d --- /dev/null +++ b/deps_adapter/key_management_adapter/impl/src/standard/mbedtls_ec_adapter.c @@ -0,0 +1,313 @@ +/* + * 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 "mbedtls_ec_adapter.h" + +#include +#include +#include +#include +#include + +#include "hal_error.h" +#include "hc_log.h" +#include "huks_adapter.h" + +#define LOG_AND_RETURN_IF_FAIL(ret, fmt, ...) \ +do { \ + if ((ret) != 0) { \ + LOGE(fmt, ##__VA_ARGS__); \ + return (ret); \ + } \ +} while (0) + +#define LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, fmt, ...) \ +do { \ + if ((ret) != 0) { \ + LOGE(fmt, ##__VA_ARGS__); \ + goto CLEAN_UP; \ + } \ +} while (0) + +#define BITS_PER_BYTE 8 +#define EC_LEN 64 +#define SHA256_HASH_LEN 32 +#define P256_KEY_SIZE 32 +#define P256_PUBLIC_SIZE 64 // P256_KEY_SIZE * 2 + +typedef struct Blob { + uint32_t dataSize; + uint8_t *data; +} Blob; + +static const uint8_t g_pointA[] = { + 0x04, 0x53, 0xf9, 0xe4, 0xf4, 0xbc, 0x3a, 0xb5, 0x9d, 0x44, 0x78, 0x45, 0x21, 0x13, 0x8b, 0x49, + 0xba, 0xa3, 0x1c, 0xe2, 0xa8, 0xdb, 0xbd, 0xb8, 0xd6, 0x73, 0x31, 0x46, 0x3a, 0x69, 0x53, 0xf1, + 0xed, 0xef, 0x96, 0x1e, 0xdb, 0x42, 0xbe, 0x3a, 0x24, 0x43, 0xc4, 0x08, 0x23, 0xfb, 0x58, 0xee, + 0x61, 0x24, 0x8b, 0x59, 0x64, 0x65, 0x2d, 0xbc, 0x6b, 0xa5, 0x1d, 0x6e, 0x04, 0x22, 0x53, 0xae, + 0x27 +}; +static const uint8_t g_pointB[] = { + 0x04, 0x03, 0x4d, 0x11, 0x11, 0xa6, 0x3f, 0x5f, 0x72, 0x43, 0x59, 0x73, 0x8b, 0x46, 0xc3, 0xfd, + 0x70, 0x58, 0xb0, 0xb6, 0x11, 0xd3, 0x4f, 0xf3, 0x49, 0xa0, 0xd2, 0x86, 0xd7, 0x35, 0x33, 0xc5, + 0x36, 0xe4, 0x99, 0xcc, 0x13, 0x47, 0xe4, 0xab, 0xde, 0x8f, 0x3a, 0xd6, 0x65, 0x1a, 0x77, 0x0b, + 0xc4, 0x82, 0xd5, 0xac, 0x4b, 0x5d, 0xe4, 0xcc, 0x48, 0xb0, 0x54, 0x6c, 0x9b, 0x76, 0x76, 0x1a, + 0xba +}; + +static const uint8_t g_randomSeedCustom[] = { 0x4C, 0x54, 0x4B, 0x53 }; // LTKS means LiteKeystore + +static bool IsInvalidBlob(const Blob *blob) +{ + return (blob == NULL) || (blob->data == NULL) || (blob->dataSize == 0); +} + +static void InitPointParams(mbedtls_mpi *scalarA, mbedtls_mpi *scalarB, mbedtls_ecp_point *pointA, + mbedtls_ecp_point *pointB, mbedtls_ecp_point *result) +{ + mbedtls_mpi_init(scalarA); + mbedtls_mpi_init(scalarB); + mbedtls_ecp_point_init(pointA); + mbedtls_ecp_point_init(pointB); + mbedtls_ecp_point_init(result); +} + +static void FreePointParams(mbedtls_mpi *scalarA, mbedtls_mpi *scalarB, mbedtls_ecp_point *pointA, + mbedtls_ecp_point *pointB, mbedtls_ecp_point *result) +{ + mbedtls_mpi_free(scalarA); + mbedtls_mpi_free(scalarB); + mbedtls_ecp_point_free(pointA); + mbedtls_ecp_point_free(pointB); + mbedtls_ecp_point_free(result); +} + +static int32_t CalculateMessageDigest(mbedtls_md_type_t type, const Blob *input, Blob *output) +{ + const mbedtls_md_info_t *info = mbedtls_md_info_from_type(type); + if (info == NULL) { + return HAL_ERR_NOT_SUPPORTED; + } + + uint32_t outSize = mbedtls_md_get_size(info); + if (output->dataSize < outSize) { + return HAL_ERR_SHORT_BUFFER; + } + + int32_t ret = mbedtls_md(info, input->data, input->dataSize, output->data); + LOG_AND_RETURN_IF_FAIL(ret, "Calculate message digest failed.\n"); + + output->dataSize = outSize; + return ret; +} + +static int32_t Sha256(const Blob *input, Blob *output) +{ + if (IsInvalidBlob(input) || IsInvalidBlob(output)) { + LOGE("Input params for sha256 is invalid."); + return HAL_ERR_INVALID_PARAM; + } + return CalculateMessageDigest(MBEDTLS_MD_SHA256, input, output); +} + +static int32_t ReadBigNums(mbedtls_mpi *x, mbedtls_mpi *y, const Blob *blob) +{ + int32_t ret = mbedtls_mpi_read_binary(x, blob->data, P256_KEY_SIZE); + LOG_AND_RETURN_IF_FAIL(ret, "Read x coordinate of public key failed."); + return mbedtls_mpi_read_binary(y, blob->data + P256_KEY_SIZE, P256_KEY_SIZE); +} + +static int32_t ReadEcPublicKey(mbedtls_ecp_point *point, const Blob *publicKey) +{ + int32_t ret = ReadBigNums(&point->X, &point->Y, publicKey); + LOG_AND_RETURN_IF_FAIL(ret, "Read coordinate of public key failed."); + return mbedtls_mpi_lset(&point->Z, 1); +} + +static int32_t WriteOutBigNums(const mbedtls_mpi *x, const mbedtls_mpi *y, Blob *out) +{ + int32_t ret = mbedtls_mpi_write_binary(x, out->data, P256_KEY_SIZE); + LOG_AND_RETURN_IF_FAIL(ret, "Write x coordinate of public key failed."); + + ret = mbedtls_mpi_write_binary(y, out->data + P256_KEY_SIZE, P256_KEY_SIZE); + LOG_AND_RETURN_IF_FAIL(ret, "Write y coordinate of public key failed."); + + out->dataSize = P256_PUBLIC_SIZE; + return ret; +} + +static int32_t WriteOutEcPublicKey(const mbedtls_ecp_point *point, Blob *publicKey) +{ + return WriteOutBigNums(&point->X, &point->Y, publicKey); +} + +static int32_t EcKeyAgreement(const Blob *privateKey, const Blob *publicKey, Blob *secretKey) +{ + if (IsInvalidBlob(publicKey) || publicKey->dataSize != P256_PUBLIC_SIZE || IsInvalidBlob(secretKey) || + secretKey->dataSize != P256_PUBLIC_SIZE || IsInvalidBlob(privateKey)) { + LOGE("Input params for ec key agree is invalid."); + return HAL_ERR_INVALID_PARAM; + } + + mbedtls_mpi *secret = HcMalloc(sizeof(mbedtls_mpi), 0); + mbedtls_ecp_keypair *keyPair = HcMalloc(sizeof(mbedtls_ecp_keypair), 0); + mbedtls_entropy_context *entropy = HcMalloc(sizeof(mbedtls_entropy_context), 0); + mbedtls_ctr_drbg_context *ctrDrbg = HcMalloc(sizeof(mbedtls_ctr_drbg_context), 0); + + mbedtls_mpi_init(secret); + mbedtls_ecp_keypair_init(keyPair); + mbedtls_entropy_init(entropy); + mbedtls_ctr_drbg_init(ctrDrbg); + mbedtls_ecp_point P; + mbedtls_ecp_point_init(&P); + + int32_t ret = ReadEcPublicKey(&keyPair->Q, publicKey); + LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Read the public key failed.\n"); + + ret = mbedtls_ecp_group_load(&keyPair->grp, MBEDTLS_ECP_DP_SECP256R1); + LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Load the ecp group failed.\n"); + + ret = mbedtls_mpi_read_binary(&keyPair->d, privateKey->data, privateKey->dataSize); + LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Read the private key failed.\n"); + + ret = mbedtls_ctr_drbg_seed(ctrDrbg, mbedtls_entropy_func, entropy, + g_randomSeedCustom, sizeof(g_randomSeedCustom)); + LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Set custom string failed.\n"); + + ret = mbedtls_ecp_mul_restartable(&keyPair->grp, &P, &keyPair->d, &keyPair->Q, + mbedtls_ctr_drbg_random, ctrDrbg, NULL); + LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Compute secret key failed.\n"); + + mbedtls_mpi_copy(secret, &P.X); + WriteOutEcPublicKey(&P, secretKey); +CLEAN_UP: + mbedtls_mpi_free(secret); + mbedtls_ecp_keypair_free(keyPair); + mbedtls_entropy_free(entropy); + mbedtls_ctr_drbg_free(ctrDrbg); + mbedtls_ecp_point_free(&P); + HcFree(secret); + HcFree(keyPair); + HcFree(entropy); + HcFree(ctrDrbg); + return ret; +} + +static int32_t EcHashToPoint(const Blob *hash, Blob *point) +{ + if (IsInvalidBlob(hash) || IsInvalidBlob(point)) { + return HAL_ERR_INVALID_PARAM; + } + + if (point->dataSize < P256_PUBLIC_SIZE) { + return HAL_ERR_SHORT_BUFFER; + } + + mbedtls_mpi scalarA; + mbedtls_mpi scalarB; + mbedtls_ecp_point pointA; + mbedtls_ecp_point pointB; + mbedtls_ecp_point result; + InitPointParams(&scalarA, &scalarB, &pointA, &pointB, &result); + + mbedtls_ecp_group grp; + mbedtls_ecp_group_init(&grp); + uint8_t digest[SHA256_HASH_LEN] = { 0 }; + Blob digestBlob = { sizeof(digest), digest }; + + int32_t ret = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1); + LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Load ecp group failed.\n"); + ret = mbedtls_ecp_point_read_binary(&grp, &pointA, g_pointA, sizeof(g_pointA)); + LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Read point A failed.\n"); + ret = mbedtls_ecp_point_read_binary(&grp, &pointB, g_pointB, sizeof(g_pointB)); + LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Read point B failed.\n"); + ret = Sha256(hash, &digestBlob); + LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Compute message digest failed.\n"); + ret = mbedtls_mpi_lset(&scalarA, 1); + LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Set number one failed.\n"); + ret = mbedtls_mpi_read_binary(&scalarB, digest, SHA256_HASH_LEN); + LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Read digest failed.\n"); + ret = mbedtls_ecp_muladd(&grp, &result, &scalarA, &pointA, &scalarB, &pointB); + LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Double-scalar multiplication failed.\n"); + ret = mbedtls_ecp_check_pubkey(&grp, &result); + LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Invalid point on P256 is returned.\n"); + ret = WriteOutEcPublicKey(&result, point); + LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Write out public key failed.\n"); +CLEAN_UP: + FreePointParams(&scalarA, &scalarB, &pointA, &pointB, &result); + mbedtls_ecp_group_free(&grp); + return ret; +} + +// only support P256 HashToPoint for standard system +int32_t MbedtlsHashToPoint(const Uint8Buff *hash, Uint8Buff *outEcPoint) +{ + CHECK_PTR_RETURN_HAL_ERROR_CODE(hash, "hash"); + CHECK_PTR_RETURN_HAL_ERROR_CODE(hash->val, "hash->val"); + CHECK_LEN_EQUAL_RETURN(hash->length, SHA256_LEN, "hash->length"); + CHECK_PTR_RETURN_HAL_ERROR_CODE(outEcPoint, "outEcPoint"); + CHECK_PTR_RETURN_HAL_ERROR_CODE(outEcPoint->val, "outEcPoint->val"); + CHECK_LEN_EQUAL_RETURN(outEcPoint->length, EC_LEN, "outEcPoint->length"); + + struct Blob hashBlob = { + .dataSize = hash->length, + .data = hash->val + }; + struct Blob pointBlob = { + .dataSize = outEcPoint->length, + .data = outEcPoint->val + }; + + int32_t ret = EcHashToPoint(&hashBlob, &pointBlob); + if (ret != HAL_SUCCESS || pointBlob.dataSize != EC_LEN) { + LOGE("HashToPoint with mbedtls for P256 failed, ret: %d", ret); + return HAL_FAILED; + } + + return HAL_SUCCESS; +} + +// only support P256 AgreeSharedSecret for standard system +int32_t MbedtlsAgreeSharedSecret(const KeyBuff *priKey, const KeyBuff *pubKey, Uint8Buff *sharedKey) +{ + CHECK_PTR_RETURN_HAL_ERROR_CODE(priKey, "priKey"); + CHECK_PTR_RETURN_HAL_ERROR_CODE(priKey->key, "priKey->key"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(priKey->keyLen, "priKey->keyLen"); + CHECK_PTR_RETURN_HAL_ERROR_CODE(pubKey, "devicePk"); + CHECK_PTR_RETURN_HAL_ERROR_CODE(pubKey->key, "devicePk->key"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(pubKey->keyLen, "devicePk->keyLen"); + CHECK_PTR_RETURN_HAL_ERROR_CODE(sharedKey, "sharedKey"); + CHECK_PTR_RETURN_HAL_ERROR_CODE(sharedKey->val, "sharedKey->val"); + CHECK_LEN_ZERO_RETURN_ERROR_CODE(sharedKey->length, "sharedKey->length"); + + struct Blob priKeyBlob = { + .dataSize = priKey->keyLen, + .data = priKey->key + }; + struct Blob pubKeyBlob = { + .dataSize = pubKey->keyLen, + .data = pubKey->key + }; + struct Blob sharedKeyBlob = { + .dataSize = sharedKey->length, + .data = sharedKey->val + }; + int32_t ret = EcKeyAgreement(&priKeyBlob, &pubKeyBlob, &sharedKeyBlob); + if (ret != HAL_SUCCESS) { + LOGE("Agree key failed, ret = %d", ret); + return HAL_FAILED; + } + return HAL_SUCCESS; +} diff --git a/deps_adapter/key_management_adapter/interfaces/huks_adapter.h b/deps_adapter/key_management_adapter/interfaces/huks_adapter.h index 430b47d..21524f2 100644 --- a/deps_adapter/key_management_adapter/interfaces/huks_adapter.h +++ b/deps_adapter/key_management_adapter/interfaces/huks_adapter.h @@ -21,6 +21,7 @@ #include "hc_types.h" #define BITS_PER_BYTE 8 +#define ECC_PK_LEN 32 #define CAL_ARRAY_SIZE(arr) ((sizeof(arr)) / (sizeof((arr)[0]))) diff --git a/deps_adapter/os_adapter/impl/src/linux/hc_dev_info.c b/deps_adapter/os_adapter/impl/src/linux/hc_dev_info.c index 800b7cf..5d7ffb4 100644 --- a/deps_adapter/os_adapter/impl/src/linux/hc_dev_info.c +++ b/deps_adapter/os_adapter/impl/src/linux/hc_dev_info.c @@ -58,6 +58,17 @@ const char *GetStorageDirPath(void) return storageFile; } +const char *GetAccountStoragePath(void) +{ +#ifndef LITE_DEVICE + const char *storageFile = "/data/data/deviceauth/account"; +#else + const char *storageFile = "/storage/deviceauth/account"; +#endif + LOGI("[OS]: Account storage dir: %s", storageFile); + return storageFile; +} + #ifdef __cplusplus } #endif diff --git a/deps_adapter/os_adapter/interfaces/hal_error.h b/deps_adapter/os_adapter/interfaces/hal_error.h index 887ba97..0046dff 100644 --- a/deps_adapter/os_adapter/interfaces/hal_error.h +++ b/deps_adapter/os_adapter/interfaces/hal_error.h @@ -32,5 +32,8 @@ enum { HAL_ERR_BUILD_PARAM_SET_FAILED = -17, HAL_ERR_FRESH_PARAM_SET_FAILED = -18, HAL_ERR_INIT_FAILED = -19, + HAL_ERR_HUKS = -20, + HAL_ERR_SHORT_BUFFER = -21, + HAL_ERR_NOT_SUPPORTED = -22, }; #endif \ No newline at end of file diff --git a/deps_adapter/os_adapter/interfaces/hc_dev_info.h b/deps_adapter/os_adapter/interfaces/hc_dev_info.h index 5d7924e..6b61d04 100644 --- a/deps_adapter/os_adapter/interfaces/hc_dev_info.h +++ b/deps_adapter/os_adapter/interfaces/hc_dev_info.h @@ -37,6 +37,7 @@ int32_t HcGetUdid(uint8_t *udid, int32_t udidLen); const char *GetStoragePath(void); const char *GetStorageDirPath(void); +const char *GetAccountStoragePath(void); #ifdef __cplusplus } diff --git a/frameworks/inc/ipc_sdk.h b/frameworks/inc/ipc_sdk.h old mode 100755 new mode 100644 index 85b7684..1050446 --- a/frameworks/inc/ipc_sdk.h +++ b/frameworks/inc/ipc_sdk.h @@ -43,7 +43,6 @@ extern "C" { #define PARAM_TYPE_BIND 12 #define PARAM_TYPE_UNBIND 13 #define PARAM_TYPE_GROUP_TYPE 14 -#define PARAM_TYPE_CREDENTIAL 15 #define PARAM_TYPE_MGR_APPID 16 #define PARAM_TYPE_FRIEND_APPID 17 #define PARAM_TYPE_QUERY_PARAMS 18 @@ -62,6 +61,7 @@ extern "C" { #define PARAM_TYPE_CB_OBJECT 31 #define PARAM_TYPE_OS_ACCOUNT_ID 32 #define PARAM_TYPE_RETURN_DATA 33 +#define PARAM_TYPE_REQ_JSON 34 enum { IPC_CALL_ID_REG_CB = 1, @@ -73,7 +73,6 @@ enum { IPC_CALL_ID_ADD_GROUP_MEMBER, IPC_CALL_ID_DEL_GROUP_MEMBER, IPC_CALL_ID_GM_PROC_DATA, - IPC_CALL_ID_SAVE_CREDENTIAL, IPC_CALL_ID_APPLY_REG_INFO, IPC_CALL_ID_CHECK_ACCESS_TO_GROUP, IPC_CALL_ID_GET_PK_INFO_LIST, diff --git a/frameworks/src/ipc_sdk.c b/frameworks/src/ipc_sdk.c index e5905a8..275d6cf 100644 --- a/frameworks/src/ipc_sdk.c +++ b/frameworks/src/ipc_sdk.c @@ -565,21 +565,7 @@ static int32_t IpcGmProcessData(int64_t requestId, const uint8_t *data, uint32_t return ret; } -static int32_t IpcGmProcCredential(int32_t operationCode, const char *credential, char **returnJsonStr) -{ - LOGI("starting ..."); - (void)operationCode; - (void)returnJsonStr; - if (!IS_STRING_VALID(credential)) { - LOGE("The input groupType is invalid!"); - return HC_ERR_INVALID_PARAMS; - } - - LOGE("IpcGmProcCredential is currently not supported!"); - return HC_ERR_NOT_SUPPORT; -} - -static int32_t IpcGmGetRegisterInfo(char **registerInfo) +static int32_t IpcGmGetRegisterInfo(const char *reqJsonStr, char **registerInfo) { uintptr_t callCtx = 0x0; int32_t ret; @@ -588,7 +574,8 @@ static int32_t IpcGmGetRegisterInfo(char **registerInfo) char *outInfo = NULL; LOGI("starting ..."); - if (registerInfo == NULL) { + if ((reqJsonStr == NULL) || (registerInfo == NULL)) { + LOGE("Invalid params."); return HC_ERR_INVALID_PARAMS; } if (!IsServiceRunning()) { @@ -600,6 +587,12 @@ static int32_t IpcGmGetRegisterInfo(char **registerInfo) LOGE("CreateCallCtx failed, ret %d", ret); return HC_ERR_IPC_INIT; } + ret = SetCallRequestParamInfo(callCtx, PARAM_TYPE_REQ_JSON, (const uint8_t *)reqJsonStr, strlen(reqJsonStr) + 1); + if (ret != HC_SUCCESS) { + LOGE("set request param failed, ret %d, param id %d", ret, PARAM_TYPE_REQ_JSON); + DestroyCallCtx(&callCtx, NULL); + return HC_ERR_IPC_BUILD_PARAM; + } ret = DoBinderCall(callCtx, IPC_CALL_ID_APPLY_REG_INFO, true); if (ret == HC_ERR_IPC_INTERNAL_FAILED) { LOGE("ipc call failed"); @@ -1372,7 +1365,6 @@ static void InitIpcGmMethods(DeviceGroupManager *gmMethodObj) gmMethodObj->addMemberToGroup = IpcGmAddMemberToGroup; gmMethodObj->deleteMemberFromGroup = IpcGmDelMemberFromGroup; gmMethodObj->processData = IpcGmProcessData; - gmMethodObj->processCredential = IpcGmProcCredential; gmMethodObj->getRegisterInfo = IpcGmGetRegisterInfo; gmMethodObj->checkAccessToGroup = IpcGmCheckAccessToGroup; gmMethodObj->getPkInfoList = IpcGmGetPkInfoList; diff --git a/frameworks/src/ipc_service.c b/frameworks/src/ipc_service.c index afc21fc..6d35206 100644 --- a/frameworks/src/ipc_service.c +++ b/frameworks/src/ipc_service.c @@ -404,50 +404,20 @@ static int32_t IpcServiceGmProcessData(const IpcDataInfo *ipcParams, int32_t par return ret; } -static int32_t IpcServiceGmSaveCredential(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) -{ - int32_t callRet; - int32_t ret; - int32_t opCode = 0; - int32_t inOutLen; - const char *credential = NULL; - char *returnJsonStr = NULL; - - LOGI("starting ..."); - inOutLen = sizeof(int32_t); - ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_OPCODE, (uint8_t *)&opCode, &inOutLen); - if ((inOutLen != sizeof(int32_t)) || (ret != HC_SUCCESS)) { - LOGE("get param error, type %d", PARAM_TYPE_OPCODE); - return HC_ERR_IPC_BAD_PARAM; - } - ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_CREDENTIAL, (uint8_t *)&credential, NULL); - if ((credential == NULL) || (ret != HC_SUCCESS)) { - LOGE("get param error, type %d", PARAM_TYPE_CREDENTIAL); - return HC_ERR_IPC_BAD_PARAM; - } - callRet = g_devGroupMgrMethod.processCredential(opCode, credential, &returnJsonStr); - ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); - LOGI("process done, call ret %d, ipc ret %d", callRet, ret); - if ((ret == HC_SUCCESS) && (returnJsonStr != NULL)) { - ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_REG_INFO, - (const uint8_t *)returnJsonStr, strlen(returnJsonStr) + 1); - g_devGroupMgrMethod.destroyInfo(&returnJsonStr); - } else { - ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_REG_INFO, NULL, 0); - } - return (ret == HC_SUCCESS) ? ret : HC_ERROR; -} - static int32_t IpcServiceGmApplyRegisterInfo(const IpcDataInfo *ipcParams, int32_t paramNum, uintptr_t outCache) { int32_t callRet; int32_t ret; + const char *reqJsonStr = NULL; char *registerInfo = NULL; - (void)ipcParams; - (void)paramNum; LOGI("starting ..."); - callRet = g_devGroupMgrMethod.getRegisterInfo(®isterInfo); + ret = GetIpcRequestParamByType(ipcParams, paramNum, PARAM_TYPE_REQ_JSON, (uint8_t *)&reqJsonStr, NULL); + if ((reqJsonStr == NULL) || (ret != HC_SUCCESS)) { + LOGE("get param error, type %d", PARAM_TYPE_REQ_JSON); + return HC_ERR_IPC_BAD_PARAM; + } + callRet = g_devGroupMgrMethod.getRegisterInfo(reqJsonStr, ®isterInfo); ret = IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT, (const uint8_t *)&callRet, sizeof(int32_t)); ret += IpcEncodeCallReplay(outCache, PARAM_TYPE_IPC_RESULT_NUM, (const uint8_t *)&g_ipcResultNum1, sizeof(int32_t)); @@ -977,7 +947,6 @@ static int32_t AddMethodMap(uintptr_t ipcInstance) ret &= SetIpcCallMap(ipcInstance, IpcServiceGmAddMemberToGroup, IPC_CALL_ID_ADD_GROUP_MEMBER); ret &= SetIpcCallMap(ipcInstance, IpcServiceGmDelMemberFromGroup, IPC_CALL_ID_DEL_GROUP_MEMBER); ret &= SetIpcCallMap(ipcInstance, IpcServiceGmProcessData, IPC_CALL_ID_GM_PROC_DATA); - ret &= SetIpcCallMap(ipcInstance, IpcServiceGmSaveCredential, IPC_CALL_ID_SAVE_CREDENTIAL); ret &= SetIpcCallMap(ipcInstance, IpcServiceGmApplyRegisterInfo, IPC_CALL_ID_APPLY_REG_INFO); ret &= SetIpcCallMap(ipcInstance, IpcServiceGmCheckAccessToGroup, IPC_CALL_ID_CHECK_ACCESS_TO_GROUP); ret &= SetIpcCallMap(ipcInstance, IpcServiceGmGetPkInfoList, IPC_CALL_ID_GET_PK_INFO_LIST); diff --git a/frameworks/src/lite/ipc_adapt.c b/frameworks/src/lite/ipc_adapt.c index 3b873b1..c79b2e4 100644 --- a/frameworks/src/lite/ipc_adapt.c +++ b/frameworks/src/lite/ipc_adapt.c @@ -1518,9 +1518,9 @@ static bool IsTypeForSettingPtr(int32_t type) int32_t typeList[] = { PARAM_TYPE_APPID, PARAM_TYPE_DEV_AUTH_CB, PARAM_TYPE_LISTERNER, PARAM_TYPE_CREATE_PARAMS, PARAM_TYPE_GROUPID, PARAM_TYPE_UDID, PARAM_TYPE_ADD_PARAMS, PARAM_TYPE_DEL_PARAMS, - PARAM_TYPE_BIND, PARAM_TYPE_UNBIND, PARAM_TYPE_CREDENTIAL, PARAM_TYPE_MGR_APPID, - PARAM_TYPE_FRIEND_APPID, PARAM_TYPE_QUERY_PARAMS, PARAM_TYPE_COMM_DATA, PARAM_TYPE_REQ_CFM, - PARAM_TYPE_SESS_KEY, PARAM_TYPE_REQ_INFO, PARAM_TYPE_GROUP_INFO, PARAM_TYPE_AUTH_PARAMS + PARAM_TYPE_BIND, PARAM_TYPE_UNBIND, PARAM_TYPE_MGR_APPID, PARAM_TYPE_FRIEND_APPID, + PARAM_TYPE_QUERY_PARAMS, PARAM_TYPE_COMM_DATA, PARAM_TYPE_REQ_CFM, PARAM_TYPE_SESS_KEY, + PARAM_TYPE_REQ_INFO, PARAM_TYPE_GROUP_INFO, PARAM_TYPE_AUTH_PARAMS, PARAM_TYPE_REQ_JSON }; int32_t i; int32_t n = sizeof(typeList) / sizeof(typeList[0]); diff --git a/frameworks/src/standard/ipc_adapt.cpp b/frameworks/src/standard/ipc_adapt.cpp index 3dd4ec8..b5aa2a9 100644 --- a/frameworks/src/standard/ipc_adapt.cpp +++ b/frameworks/src/standard/ipc_adapt.cpp @@ -1427,9 +1427,9 @@ static bool IsTypeForSettingPtr(int32_t type) int32_t typeList[] = { PARAM_TYPE_APPID, PARAM_TYPE_DEV_AUTH_CB, PARAM_TYPE_LISTERNER, PARAM_TYPE_CREATE_PARAMS, PARAM_TYPE_GROUPID, PARAM_TYPE_UDID, PARAM_TYPE_ADD_PARAMS, PARAM_TYPE_DEL_PARAMS, - PARAM_TYPE_BIND, PARAM_TYPE_UNBIND, PARAM_TYPE_CREDENTIAL, PARAM_TYPE_MGR_APPID, - PARAM_TYPE_FRIEND_APPID, PARAM_TYPE_QUERY_PARAMS, PARAM_TYPE_COMM_DATA, PARAM_TYPE_REQ_CFM, - PARAM_TYPE_SESS_KEY, PARAM_TYPE_REQ_INFO, PARAM_TYPE_GROUP_INFO, PARAM_TYPE_AUTH_PARAMS + PARAM_TYPE_BIND, PARAM_TYPE_UNBIND, PARAM_TYPE_MGR_APPID, PARAM_TYPE_FRIEND_APPID, + PARAM_TYPE_QUERY_PARAMS, PARAM_TYPE_COMM_DATA, PARAM_TYPE_REQ_CFM, PARAM_TYPE_SESS_KEY, + PARAM_TYPE_REQ_INFO, PARAM_TYPE_GROUP_INFO, PARAM_TYPE_AUTH_PARAMS, PARAM_TYPE_REQ_JSON }; int32_t i; int32_t n = sizeof(typeList) / sizeof(typeList[0]); diff --git a/interfaces/innerkits/device_auth.h b/interfaces/innerkits/device_auth.h index 446376b..4c835c5 100644 --- a/interfaces/innerkits/device_auth.h +++ b/interfaces/innerkits/device_auth.h @@ -38,7 +38,6 @@ #define FIELD_DELETE_ID "deleteId" #define FIELD_APP_ID "appId" #define FIELD_SERVICE_TYPE "serviceType" -#define FIELD_PEER_AUTH_STATE "peerAuthState" #define FIELD_IS_DEVICE_LEVEL "isDeviceLevel" #define FIELD_ALTERNATIVE "alternative" #define FIELD_PEER_UDID "peerUdid" @@ -58,7 +57,6 @@ #define FIELD_SHARED_USER_ID "sharedUserId" #define FIELD_OWNER_USER_ID "ownerUserId" #define FIELD_DEVICE_ID "deviceId" -#define FIELD_UID_HASH "uidHash" #define FIELD_PIN_CODE "pinCode" #define FIELD_AUTH_ID "authId" #define FIELD_UDID "udid" @@ -76,6 +74,7 @@ typedef enum { } OsAccountEnum; typedef enum { + GROUP_TYPE_INVALID = -1, ALL_GROUP = 0, IDENTICAL_ACCOUNT_GROUP = 1, PEER_TO_PEER_GROUP = 256, @@ -173,8 +172,7 @@ typedef struct { int32_t (*deleteMemberFromGroup)(int32_t osAccountId, int64_t requestId, const char *appId, const char *deleteParams); int32_t (*processData)(int64_t requestId, const uint8_t *data, uint32_t dataLen); - int32_t (*processCredential)(int operationCode, const char *reqJsonStr, char **returnJsonStr); - int32_t (*getRegisterInfo)(char **returnRegisterInfo); + int32_t (*getRegisterInfo)(const char *reqJsonStr, char **returnRegisterInfo); int32_t (*checkAccessToGroup)(int32_t osAccountId, const char *appId, const char *groupId); int32_t (*getPkInfoList)(int32_t osAccountId, const char *appId, const char *queryParams, char **returnInfoList, uint32_t *returnInfoNum); diff --git a/interfaces/innerkits/device_auth_defines.h b/interfaces/innerkits/device_auth_defines.h index 538b50a..e3355ca 100644 --- a/interfaces/innerkits/device_auth_defines.h +++ b/interfaces/innerkits/device_auth_defines.h @@ -49,6 +49,7 @@ enum { HC_ERR_VERIFY_FAILED = 0x00001004, HC_ERR_HASH_FAIL = 0x00001005, HC_ERR_ALG_FAIL = 0x00001006, + HC_ERR_HKS_PARAM_SET_FAILED = 0x00001007, /* error code for json util , 0x00002000 ~ 0x00002FFF */ HC_ERR_JSON_FAIL = 0x00002001, @@ -89,6 +90,13 @@ enum { HC_ERR_INVALID_ALG = 0x0000400A, HC_ERR_IGNORE_MSG = 0x0000400B, HC_ERR_LOCAL_IDENTITY_NOT_EXIST = 0x0000400C, + HC_ERR_UNSUPPORTED_OPCODE = 0x0000400D, + HC_ERR_AUTH_TOKEN = 0x0000400F, + HC_ERR_PSK = 0x00004010, + HC_ERR_TOKEN = 0x00004011, + HC_ERR_GENERATE_RANDOM = 0x00004012, + HC_ERR_STATUS = 0x00004013, + HC_ERR_STEP = 0x00004014, /* error code for group , 0x00005000 ~ 0x00005FFF */ HC_ERR_ACCESS_DENIED = 0x00005001, @@ -106,6 +114,7 @@ enum { HC_ERR_SESSION_IS_FULL = 0x0000500D, HC_ERR_INVALID_UDID = 0x0000500E, HC_ERR_INVALID_TCIS_ID = 0x0000500F, + HC_ERR_DEL_GROUP = 0x00005010, /* error code for database , 0x00006000 ~ 0x00006FFF */ HC_ERR_DB = 0x00006001, @@ -126,6 +135,17 @@ enum { HC_ERR_CHANNEL_NOT_EXIST = 0x00008001, HC_ERR_SOFT_BUS = 0x00008002, + /* error code used on account-related authenticator */ + HC_ERR_GET_PK_INFO = 0x00009001, + HC_ERR_ACCOUNT_TASK_IS_FULL = 0x00009002, + HC_ERR_ACCOUNT_ECDH_FAIL = 0x00009003, + HC_ERR_ACCOUNT_VERIFY_PK_SIGN = 0x00009004, + HC_ERR_AUTH_STATUS = 0x00009005, + HC_ERR_AUTH_INTERNAL = 0x00009006, + HC_ERR_ADD_ACCOUNT_TASK = 0x00009007, + HC_ERR_CLIENT_CONFIRM_PROTOCOL = 0x00009008, + HC_ERR_SERVER_CONFIRM_PROTOCOL = 0x00009009, + /* error code used on DAS service */ INVALID_PARAMETERS = 0xF0000001, EXCEED_AUTHORITY = 0xF0000002, diff --git a/services/authenticators/inc/account_related/account_module.h b/services/authenticators/inc/account_related/account_module.h index 47259b9..af4eb0a 100644 --- a/services/authenticators/inc/account_related/account_module.h +++ b/services/authenticators/inc/account_related/account_module.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2021-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 @@ -17,12 +17,11 @@ #define ACCOUNT_MODULE_H #include "dev_auth_module_manager.h" -#include "hc_types.h" #include "json_utils.h" int32_t CheckAccountMsgRepeatability(const CJson *in); bool IsAccountSupported(void); AuthModuleBase *CreateAccountModule(void); -int32_t ProcessAccountCredentials(int credentialOpCode, const CJson *in, CJson *out); +int32_t ProcessAccountCredentials(int32_t osAccountId, int32_t credentialOpCode, const CJson *in, CJson *out); #endif diff --git a/services/authenticators/inc/account_related/account_module_defines.h b/services/authenticators/inc/account_related/account_module_defines.h new file mode 100644 index 0000000..04a0faa --- /dev/null +++ b/services/authenticators/inc/account_related/account_module_defines.h @@ -0,0 +1,56 @@ +/* + * 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 ACCOUNT_MODULE_DEFINES_H +#define ACCOUNT_MODULE_DEFINES_H + +#define SEED_SIZE 32 +#define USER_ID_SIZE 65 +#define PK_SIZE 128 +#define PK_VERSION_SIZE 256 +#define DEVICE_ID_SIZE 256 +#define SIGNATURE_SIZE 128 +#define PUBLIC_KEY_INFO_SIZE 1024 +#define SERVER_PK_SIZE 128 + +typedef enum { + TASK_TYPE_DEFAULT = 0, + TASK_TYPE_PAKE_V2_AUTH_CLIENT = 5, + TASK_TYPE_PAKE_V2_AUTH_SERVER = 6, + TASK_TYPE_ISO_AUTH_CLIENT = 7, + TASK_TYPE_ISO_AUTH_SERVER = 8, +} AccountTaskType; + +typedef enum { + CMD_PAKE_AUTH_MAIN_ONE = 0x0030, + RET_PAKE_AUTH_FOLLOWER_ONE = 0x0031, + CMD_PAKE_AUTH_MAIN_TWO = 0x0032, + RET_PAKE_AUTH_FOLLOWER_TWO = 0x0033, + ERR_MSG = 0x8080, +} MessageStepCode; + +typedef enum { + ALG_ECC = 0x0000, + ALG_RSA = 0x0001, + ALG_HKDF = 0x0002, + ALG_HMAC = 0x0003, + ALG_AES = 0x0004, + ALG_PBKDF2 = 0x0005, + ALG_ECDH = 0x0006, + ALG_X25519 = 0x0007, + ALG_ED25519 = 0x0008, +} KeyAlgEncode; + +#endif \ No newline at end of file diff --git a/services/authenticators/inc/account_related/account_multi_task_manager.h b/services/authenticators/inc/account_related/account_multi_task_manager.h new file mode 100644 index 0000000..3d384b6 --- /dev/null +++ b/services/authenticators/inc/account_related/account_multi_task_manager.h @@ -0,0 +1,46 @@ +/* + * 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 ACCOUNT_MULTI_TASK_MANAGER_H +#define ACCOUNT_MULTI_TASK_MANAGER_H + +#include "account_task_main.h" + +#define ACCOUNT_MULTI_TASK_MAX_SIZE 64 + +typedef struct { + int32_t count; + AccountTask *taskArray[ACCOUNT_MULTI_TASK_MAX_SIZE]; + bool (*isTaskNumUpToMax)(void); + int32_t (*addTaskToManager)(AccountTask *taskBase); + AccountTask *(*getTaskFromManager)(int32_t taskId); + void (*deleteTaskFromManager)(int32_t taskId); +} AccountMultiTaskManager; + +#ifdef __cplusplus +extern "C" { +#endif + +AccountMultiTaskManager *GetAccountMultiTaskManager(void); + +void InitAccountMultiTaskManager(void); + +void DestroyAccountMultiTaskManager(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/services/authenticators/inc/account_related/account_task_main.h b/services/authenticators/inc/account_related/account_task_main.h new file mode 100644 index 0000000..0f7428a --- /dev/null +++ b/services/authenticators/inc/account_related/account_task_main.h @@ -0,0 +1,39 @@ +/* + * 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 ACCOUNT_TASK_MAIN_H +#define ACCOUNT_TASK_MAIN_H + +#include "json_utils.h" +#include "account_module_defines.h" + +typedef struct TaskBaseT { + AccountTaskType (*getTaskType)(void); + void (*destroyTask)(struct TaskBaseT *); + int32_t (*process)(struct TaskBaseT *, const CJson *in, CJson *out, int32_t *status); + int32_t taskStatus; +} TaskBase; + +typedef struct AccountTaskT { + int32_t taskId; + void (*destroyTask)(struct AccountTaskT *); + int32_t (*processTask)(struct AccountTaskT *, const CJson *in, CJson *out, int32_t *status); + int32_t versionStatus; + TaskBase *subTask; +} AccountTask; + +AccountTask *CreateAccountTaskT(int32_t *taskId, const CJson *in, CJson *out); + +#endif diff --git a/services/authenticators/inc/account_related/account_version_util.h b/services/authenticators/inc/account_related/account_version_util.h new file mode 100644 index 0000000..0b9cd45 --- /dev/null +++ b/services/authenticators/inc/account_related/account_version_util.h @@ -0,0 +1,61 @@ +/* + * 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 ACCOUNT_VERSION_UTIL_H +#define ACCOUNT_VERSION_UTIL_H + +#include "alg_defs.h" +#include "json_utils.h" +#include "pake_defs.h" +#include "protocol_common.h" +#include "account_task_main.h" + +typedef enum { + BIND_VERSION_NO_NONE = 0, + BIND_PAKE_V2_DL = 0x0001, + BIND_PAKE_V2_EC_P256 = 0x0002, + BIND_PAKE_V2_EC_P256_WITH_PROOF = 0x0004, + BIND_PAKE_V2_EC_X25519 = 0x0008, + BIND_PAKE_V1_DL = 0x0010, +} BindVersionNo; + +typedef enum { + AUTH_VERSION_NO_NONE = 0, + AUTH_PAKE_V2_EC_P256 = 0x0001, + AUTH_ISO = 0x0002, +} AuthVersionNo; + +typedef enum { + VERSION_INITIAL = 0, + VERSION_NEGOTIATION = 1, + VERSION_CONFIRMED = 2, +} AccountVersionStatus; + +typedef struct _AccountVersionInfo { + uint64_t versionNo; + ProtocolType protocolType; + PakeAlgType pakeAlgType; + CurveType curveType; + bool withExtraOperation; + bool (*isTaskSupported)(void); + TaskBase *(*createTask)(const CJson *, CJson *, const struct _AccountVersionInfo *); +} AccountVersionInfo; + +void InitVersionInfos(void); +void DestroyVersionInfos(void); +uint64_t GetSupportedVersionNo(int32_t operationCode); +const AccountVersionInfo *GetNegotiatedVersionInfo(int32_t operationCode, uint64_t versionNo); + +#endif diff --git a/services/group_manager/inc/lcm_adapter/lcm_adapter.h b/services/authenticators/inc/account_related/auth/pake_v2_auth_task/pake_v2_auth_client_task.h similarity index 56% rename from services/group_manager/inc/lcm_adapter/lcm_adapter.h rename to services/authenticators/inc/account_related/auth/pake_v2_auth_task/pake_v2_auth_client_task.h index d01ccc8..c88390f 100644 --- a/services/group_manager/inc/lcm_adapter/lcm_adapter.h +++ b/services/authenticators/inc/account_related/auth/pake_v2_auth_task/pake_v2_auth_client_task.h @@ -1,31 +1,39 @@ -/* - * Copyright (C) 2021 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 LCM_ADAPTER_H -#define LCM_ADAPTER_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -int32_t ProcessCredential(int operationCode, const char *reqJsonStr, char **returnJsonStr); -int32_t GetRegisterInfo(char **returnRegisterInfo); - -#ifdef __cplusplus -} -#endif -#endif +/* + * 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 PAKE_V2_AUTH_CLIENT_TASK_H +#define PAKE_V2_AUTH_CLIENT_TASK_H + +#include "json_utils.h" +#include "pake_v2_auth_task_common.h" +#include "account_task_main.h" +#include "account_version_util.h" + +typedef struct { + TaskBase taskBase; + PakeAuthParams params; +} PakeV2AuthClientTask; + +#ifdef __cplusplus +extern "C" { +#endif + +TaskBase *CreatePakeV2AuthClientTask(const CJson *in, CJson *out, const AccountVersionInfo *verInfo); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/services/group_manager/src/lcm_adapter_mock/lcm_adapter_mock.c b/services/authenticators/inc/account_related/auth/pake_v2_auth_task/pake_v2_auth_server_task.h similarity index 50% rename from services/group_manager/src/lcm_adapter_mock/lcm_adapter_mock.c rename to services/authenticators/inc/account_related/auth/pake_v2_auth_task/pake_v2_auth_server_task.h index 48bb79e..5ddc374 100644 --- a/services/group_manager/src/lcm_adapter_mock/lcm_adapter_mock.c +++ b/services/authenticators/inc/account_related/auth/pake_v2_auth_task/pake_v2_auth_server_task.h @@ -1,32 +1,39 @@ -/* - * Copyright (C) 2021 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 "lcm_adapter.h" - -#include "device_auth_defines.h" - -int32_t ProcessCredential(int operationCode, const char *reqJsonStr, char **returnJsonStr) -{ - (void)operationCode; - (void)reqJsonStr; - (void)returnJsonStr; - return HC_ERR_NOT_SUPPORT; -} - -int32_t GetRegisterInfo(char **returnRegisterInfo) -{ - (void)returnRegisterInfo; - return HC_ERR_NOT_SUPPORT; -} \ No newline at end of file +/* + * 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 PAKE_V2_AUTH_SERVER_TASK_H +#define PAKE_V2_AUTH_SERVER_TASK_H + +#include "json_utils.h" +#include "pake_v2_auth_task_common.h" +#include "account_task_main.h" +#include "account_version_util.h" + +typedef struct { + TaskBase taskBase; + PakeAuthParams params; +} PakeV2AuthServerTask; + +#ifdef __cplusplus +extern "C" { +#endif + +TaskBase *CreatePakeV2AuthServerTask(const CJson *in, CJson *out, const AccountVersionInfo *verInfo); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/services/authenticators/inc/account_related/auth/pake_v2_auth_task/pake_v2_auth_task_common.h b/services/authenticators/inc/account_related/auth/pake_v2_auth_task/pake_v2_auth_task_common.h new file mode 100644 index 0000000..2c0cdeb --- /dev/null +++ b/services/authenticators/inc/account_related/auth/pake_v2_auth_task/pake_v2_auth_task_common.h @@ -0,0 +1,80 @@ +/* + * 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 PAKE_V2_AUTH_TASK_COMMON_H +#define PAKE_V2_AUTH_TASK_COMMON_H + +#include "json_utils.h" +#include "pake_defs.h" +#include "string_util.h" +#include "account_module_defines.h" +#include "account_task_main.h" +#include "account_version_util.h" + +typedef struct { + PakeBaseParams pakeParams; + uint64_t versionNo; + int32_t authForm; + int32_t osAccountId; + int32_t authKeyAlgEncode; + Uint8Buff deviceIdSelf; + Uint8Buff deviceIdPeer; + Uint8Buff devIdSelf; + Uint8Buff devIdPeer; + uint8_t pkCloud[SERVER_PK_SIZE]; + uint8_t userIdSelf[USER_ID_SIZE]; + uint8_t userIdPeer[USER_ID_SIZE]; + uint8_t pkSelf[PK_SIZE]; + Uint8Buff pkInfoSelf; + Uint8Buff pkInfoSignSelf; + uint8_t pkPeer[PK_SIZE]; + Uint8Buff pkInfoPeer; + Uint8Buff pkInfoSignPeer; +} PakeAuthParams; + +#ifdef __cplusplus +extern "C" { +#endif +bool IsPakeV2AuthTaskSupported(void); + +TaskBase *CreatePakeV2AuthTask(const CJson *in, CJson *out, const AccountVersionInfo *verInfo); + +int32_t VerifyPkSignPeer(const PakeAuthParams *params); + +int32_t GenerateEcdhSharedKey(PakeAuthParams *params); + +int32_t GetPkInfoPeer(PakeAuthParams *params, const CJson *in); + +int32_t InitPakeAuthParams(const CJson *in, PakeAuthParams *params, const AccountVersionInfo *verInfo); + +void DestroyPakeAuthParams(PakeAuthParams *params); + +int32_t ExtractPakePeerId(PakeAuthParams *params, const CJson *in); + +int32_t ExtractPakeSelfId(PakeAuthParams *params); + +int32_t ExtractSelfDeviceId(PakeAuthParams *params, const CJson *in, bool useSelfPrefix); + +int32_t ExtractPeerDeviceId(PakeAuthParams *params, const CJson *in); + +int32_t ExtractSelfDevId(PakeAuthParams *params, const CJson *in); + +int32_t ExtractPeerDevId(PakeAuthParams *params, const CJson *in); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/services/authenticators/inc/account_related/creds_manager/asysmetric_token_manager/asy_token_manager.h b/services/authenticators/inc/account_related/creds_manager/asysmetric_token_manager/asy_token_manager.h new file mode 100644 index 0000000..98605f9 --- /dev/null +++ b/services/authenticators/inc/account_related/creds_manager/asysmetric_token_manager/asy_token_manager.h @@ -0,0 +1,83 @@ +/* + * 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 ASY_TOKEN_MANAGER_H +#define ASY_TOKEN_MANAGER_H + +#include +#include "alg_defs.h" +#include "common_defs.h" +#include "string_util.h" + +#define SELF_ECC_KEY_LEN 32 + +#define COPY_STRING_GOTO_ERR_IF_FAIL(src, dest, tag) \ + do { \ + if ((src) == NULL) { \ + LOGE("%s is NULL", tag); \ + goto ERR; \ + } \ + if (memcpy_s((dest), sizeof(dest), src, HcStrlen(src) + 1) != EOK) { \ + LOGE("%s copy failed", tag); \ + goto ERR; \ + } \ + } while (0) + +typedef struct { + Uint8Buff version; + Uint8Buff userId; + Uint8Buff deviceId; + Uint8Buff devicePk; +} PkInfo; + +typedef struct { + Uint8Buff pkInfoStr; + PkInfo pkInfo; + Uint8Buff pkInfoSignature; + Uint8Buff serverPk; +} AccountToken; +DECLARE_HC_VECTOR(AccountTokenVec, AccountToken*) + +typedef struct { + int32_t (*addToken)(int32_t osAccountId, const CJson *in, CJson *out); + int32_t (*getToken)(int32_t osAccountId, AccountToken *token, const char *userId); + int32_t (*deleteToken)(int32_t osAccountId, const char *userId); + int32_t (*getRegisterProof)(const CJson *in, CJson *out); + int32_t (*getServerPublicKey)(int32_t osAccountId, const char *userId, Uint8Buff *serverPk); + int32_t (*generateKeyAlias)(const char *userId, const char *deviceId, + Uint8Buff *keyAlias, bool isServerPkAlias); + Algorithm (*getAlgVersion)(int32_t osAccountId, const char *userId); +} AccountAuthTokenManager; + +#ifdef __cplusplus +extern "C" { +#endif + +AccountAuthTokenManager *GetAccountAuthTokenManager(void); + +void InitTokenManager(void); +void DestroyTokenManager(void); + +AccountToken *CreateAccountToken(void); +void DestroyAccountToken(AccountToken *token); + +AccountTokenVec CreateAccountTokenVec(void); +void ClearAccountTokenVec(AccountTokenVec *vec); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/services/authenticators/src/account_related/account_module.c b/services/authenticators/src/account_related/account_module.c new file mode 100644 index 0000000..de38493 --- /dev/null +++ b/services/authenticators/src/account_related/account_module.c @@ -0,0 +1,184 @@ +/* + * 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 "account_module.h" +#include "alg_loader.h" +#include "asy_token_manager.h" +#include "clib_error.h" +#include "clib_types.h" +#include "common_defs.h" +#include "device_auth_defines.h" +#include "hc_log.h" +#include "json_utils.h" +#include "pake_v2_auth_client_task.h" +#include "pake_v2_auth_server_task.h" +#include "account_module_defines.h" +#include "account_multi_task_manager.h" +#include "account_version_util.h" + +#define ACCOUNT_CLIENT_FIRST_MESSAGE 0x0000 +#define ACCOUNT_CLIENT_STEP_MASK 0x000F + +typedef struct { + AuthModuleBase moduleBase; +} AccountModule; + +static AccountModule g_module; + +int32_t CheckAccountMsgRepeatability(const CJson *in) +{ + int32_t opCode; + if (GetIntFromJson(in, FIELD_OPERATION_CODE, &opCode) != CLIB_SUCCESS) { + LOGE("Get opCode failed."); + return HC_ERR_JSON_GET; + } + const char *key = NULL; + if (opCode == OP_BIND) { + key = FIELD_MESSAGE; + } else if (opCode == AUTHENTICATE) { + key = FIELD_STEP; + } else { + LOGE("Invalid opCode: %d.", opCode); + return HC_ERR_INVALID_PARAMS; + } + uint32_t message; + if (GetIntFromJson(in, key, (int32_t *)&message) != CLIB_SUCCESS) { + LOGD("There is no message code."); // The first message of the client has no message code + return HC_SUCCESS; + } + if ((message & ACCOUNT_CLIENT_STEP_MASK) == ACCOUNT_CLIENT_FIRST_MESSAGE) { + return HC_SUCCESS; + } + + LOGI("The message is repeated, ignore it, code: %u", message); + return HC_ERR_IGNORE_MSG; +} + +static int32_t CreateAccountTask(int32_t *taskId, const CJson *in, CJson *out) +{ + if (taskId == NULL || in == NULL || out == NULL) { + LOGE("Params is null in account task."); + return HC_ERR_NULL_PTR; + } + int32_t res = CheckAccountMsgRepeatability(in); + if (res != HC_SUCCESS) { + LOGE("The result of CheckAccountMsgRepeatability is %x.", res); + return res; + } + AccountMultiTaskManager *authManager = GetAccountMultiTaskManager(); + if (authManager == NULL) { + LOGE("Get multi auth manager instance failed."); + return HC_ERROR; + } + if (authManager->isTaskNumUpToMax() == true) { + LOGE("Account auth task is full."); + return HC_ERR_ACCOUNT_TASK_IS_FULL; + } + AccountTask *newTask = CreateAccountTaskT(taskId, in, out); + if (newTask == NULL) { + LOGE("Create account related task failed."); + return HC_ERR_ALLOC_MEMORY; + } + res = authManager->addTaskToManager(newTask); + if (res != HC_SUCCESS) { + LOGE("Add new task into task manager failed, res: %d.", res); + newTask->destroyTask(newTask); + } + return res; +} + +static int32_t ProcessAccountTask(int32_t taskId, const CJson *in, CJson *out, int32_t *status) +{ + AccountMultiTaskManager *authManager = GetAccountMultiTaskManager(); + if (authManager == NULL) { + LOGE("Get multi auth manager instance failed."); + return HC_ERROR; + } + AccountTask *currentTask = authManager->getTaskFromManager(taskId); + if (currentTask == NULL) { + LOGE("Get task from manager failed, taskId: %d.", taskId); + return HC_ERR_TASK_ID_IS_NOT_MATCH; + } + LOGD("Begin process account related task, taskId: %d.", taskId); + return currentTask->processTask(currentTask, in, out, status); +} + +static void DestroyAccountTask(int32_t taskId) +{ + AccountMultiTaskManager *authManager = GetAccountMultiTaskManager(); + if (authManager == NULL) { + LOGE("Get multi auth manager instance failed."); + return; + } + LOGI("Delete taskId:%d from task manager.", taskId); + authManager->deleteTaskFromManager(taskId); +} + +static void DestroyAccountModule(AuthModuleBase *module) +{ + DestroyAccountMultiTaskManager(); + DestroyTokenManager(); + DestroyVersionInfos(); + (void)memset_s(module, sizeof(AccountModule), 0, sizeof(AccountModule)); +} + +AuthModuleBase *CreateAccountModule(void) +{ + g_module.moduleBase.moduleType = ACCOUNT_MODULE; + g_module.moduleBase.createTask = CreateAccountTask; + g_module.moduleBase.processTask = ProcessAccountTask; + g_module.moduleBase.destroyTask = DestroyAccountTask; + g_module.moduleBase.destroyModule = DestroyAccountModule; + + InitVersionInfos(); + InitAccountMultiTaskManager(); + InitTokenManager(); + return (AuthModuleBase *)&g_module; +} + +bool IsAccountSupported(void) +{ + return true; +} + +int32_t ProcessAccountCredentials(int32_t osAccountId, int32_t credentialOpCode, const CJson *in, CJson *out) +{ + if (in == NULL) { + LOGE("The input param: in is null."); + return HC_ERR_NULL_PTR; + } + switch (credentialOpCode) { + case IMPORT_SELF_CREDENTIAL: + return GetAccountAuthTokenManager()->addToken(osAccountId, in, out); + case DELETE_SELF_CREDENTIAL: { + const char *userId = GetStringFromJson(in, FIELD_USER_ID); + if (userId == NULL) { + LOGE("Failed to get user id."); + return HC_ERR_JSON_GET; + } + return GetAccountAuthTokenManager()->deleteToken(osAccountId, userId); + } + case REQUEST_SIGNATURE: + if (out == NULL) { + LOGE("Params: out is null."); + return HC_ERR_NULL_PTR; + } + return GetAccountAuthTokenManager()->getRegisterProof(in, out); + default: + LOGE("Operation is not supported for: %d.", credentialOpCode); + break; + } + return HC_ERR_NOT_SUPPORT; +} diff --git a/services/authenticators/src/account_related/account_multi_task_manager.c b/services/authenticators/src/account_related/account_multi_task_manager.c new file mode 100644 index 0000000..dcadc6d --- /dev/null +++ b/services/authenticators/src/account_related/account_multi_task_manager.c @@ -0,0 +1,128 @@ +/* + * 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 "account_multi_task_manager.h" +#include "device_auth.h" +#include "device_auth_defines.h" +#include "hc_log.h" +#include "hc_types.h" + +static AccountMultiTaskManager g_taskManager; + +static bool IsManagerHasTaskId(int32_t taskId) +{ + for (uint32_t i = 0; i < ACCOUNT_MULTI_TASK_MAX_SIZE; ++i) { + if (g_taskManager.taskArray[i] != NULL && taskId == g_taskManager.taskArray[i]->taskId) { + LOGD("Task already exists, taskId: %d.", taskId); + return true; + } + } + LOGD("Multi auth manager do not has task id(%d).", taskId); + return false; +} + +static bool IsTaskNumUpToMax(void) +{ + if (g_taskManager.count >= ACCOUNT_MULTI_TASK_MAX_SIZE) { + LOGD("The number of tasks reaches maximun."); + return true; + } + return false; +} + +static bool CanAddTaskInManager(int32_t taskId) +{ + if (IsTaskNumUpToMax()) { + LOGE("Task number is up to limit."); + return false; + } + if (IsManagerHasTaskId(taskId)) { + LOGE("Task id is already in exist."); + return false; + } + return true; +} + +static int32_t AddTaskToManager(AccountTask *task) +{ + if (task == NULL) { + LOGE("Task is null."); + return HC_ERR_NULL_PTR; + } + + if (!CanAddTaskInManager(task->taskId)) { + LOGE("Can not add task into manager."); + return HC_ERR_ADD_ACCOUNT_TASK; + } + for (uint32_t i = 0; i < ACCOUNT_MULTI_TASK_MAX_SIZE; ++i) { + if (g_taskManager.taskArray[i] == NULL) { + g_taskManager.taskArray[i] = task; + g_taskManager.count++; + return HC_SUCCESS; + } + } + LOGE("There is no empty space in the task manager."); + return HC_ERR_OUT_OF_LIMIT; +} + +static AccountTask *GetTaskFromManager(int32_t taskId) +{ + for (uint32_t i = 0; i < ACCOUNT_MULTI_TASK_MAX_SIZE; ++i) { + if ((g_taskManager.taskArray[i] != NULL) && (g_taskManager.taskArray[i]->taskId == taskId)) { + return g_taskManager.taskArray[i]; + } + } + LOGE("Task does not exist, taskId: %d.", taskId); + return NULL; +} + +static void DeleteTaskFromManager(int32_t taskId) +{ + for (uint32_t i = 0; i < ACCOUNT_MULTI_TASK_MAX_SIZE; ++i) { + if ((g_taskManager.taskArray[i] != NULL) && (g_taskManager.taskArray[i]->taskId == taskId)) { + g_taskManager.taskArray[i]->destroyTask(g_taskManager.taskArray[i]); + g_taskManager.taskArray[i] = NULL; + g_taskManager.count--; + } + } +} + +void InitAccountMultiTaskManager(void) +{ + DestroyAccountMultiTaskManager(); + g_taskManager.count = 0; + g_taskManager.isTaskNumUpToMax = IsTaskNumUpToMax; + g_taskManager.addTaskToManager = AddTaskToManager; + g_taskManager.getTaskFromManager = GetTaskFromManager; + g_taskManager.deleteTaskFromManager = DeleteTaskFromManager; +} + +AccountMultiTaskManager *GetAccountMultiTaskManager(void) +{ + return &g_taskManager; +} + +void DestroyAccountMultiTaskManager(void) +{ + for (uint32_t i = 0; i < ACCOUNT_MULTI_TASK_MAX_SIZE; ++i) { + if (g_taskManager.taskArray[i] != NULL) { + if (g_taskManager.taskArray[i]->destroyTask != NULL) { + g_taskManager.taskArray[i]->destroyTask(g_taskManager.taskArray[i]); + } + g_taskManager.taskArray[i] = NULL; + } + } + (void)memset_s(&g_taskManager, sizeof(AccountMultiTaskManager), 0, sizeof(AccountMultiTaskManager)); +} \ No newline at end of file diff --git a/services/authenticators/src/account_related/account_task_main.c b/services/authenticators/src/account_related/account_task_main.c new file mode 100644 index 0000000..8f884da --- /dev/null +++ b/services/authenticators/src/account_related/account_task_main.c @@ -0,0 +1,227 @@ +/* + * 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 "account_task_main.h" +#include "alg_defs.h" +#include "alg_loader.h" +#include "common_defs.h" +#include "device_auth.h" +#include "device_auth_defines.h" +#include "clib_error.h" +#include "hc_log.h" +#include "json_utils.h" +#include "account_version_util.h" + +static void AccountSendErrMsgToSelf(CJson *out, int32_t errCode) +{ + CJson *sendToSelf = CreateJson(); + if (sendToSelf == NULL) { + LOGE("Create sendToSelf json failed."); + return; + } + if (AddIntToJson(sendToSelf, FIELD_ERROR_CODE, errCode) != CLIB_SUCCESS) { + LOGE("Add errCode to self json failed."); + FreeJson(sendToSelf); + return; + } + if (AddObjToJson(out, FIELD_SEND_TO_SELF, sendToSelf) != CLIB_SUCCESS) { + LOGE("Add sendToSelf obj to out json failed."); + FreeJson(sendToSelf); + return; + } + FreeJson(sendToSelf); +} + +static void AccountSendErrMsgToOut(CJson *out, int32_t opCode, int32_t errCode) +{ + CJson *sendToSelf = CreateJson(); + if (sendToSelf == NULL) { + LOGE("Create sendToSelf json failed."); + return; + } + CJson *sendToPeer = CreateJson(); + if (sendToPeer == NULL) { + LOGE("Create sendToPeer json failed."); + FreeJson(sendToSelf); + return; + } + if (opCode == OP_BIND) { + if (AddIntToJson(sendToPeer, FIELD_MESSAGE, ERR_MSG) != CLIB_SUCCESS) { + LOGE("Failed to add error message to json for bind."); + goto CLEAN_UP; + } + } else { + if (AddIntToJson(sendToPeer, FIELD_STEP, ERR_MSG) != CLIB_SUCCESS) { + LOGE("Failed to add error message to json for auth."); + goto CLEAN_UP; + } + } + if (AddIntToJson(sendToPeer, FIELD_ERROR_CODE, errCode) != CLIB_SUCCESS) { + LOGE("Add errCode to json failed."); + goto CLEAN_UP; + } + if (AddIntToJson(sendToSelf, FIELD_AUTH_FORM, ACCOUNT_MODULE) != CLIB_SUCCESS) { + LOGE("Add auth form to json failed."); + goto CLEAN_UP; + } + if (AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer) != CLIB_SUCCESS) { + LOGE("Add sendToPeer to json failed."); + goto CLEAN_UP; + } + if (AddObjToJson(out, FIELD_SEND_TO_SELF, sendToSelf) != CLIB_SUCCESS) { + LOGE("Add sendToSelf to json failed."); + goto CLEAN_UP; + } + +CLEAN_UP: + FreeJson(sendToPeer); + FreeJson(sendToSelf); + return; +} + +static void DestroyTaskT(AccountTask *task) +{ + if (task == NULL) { + return; + } + if (task->subTask != NULL) { + task->subTask->destroyTask(task->subTask); + } + HcFree(task); +} + +static bool IsPeerErrMessage(const CJson *in) +{ + int32_t res = 0; + int32_t message = 0; + if ((GetIntFromJson(in, FIELD_MESSAGE, &message) != CLIB_SUCCESS) && + (GetIntFromJson(in, FIELD_STEP, &message) != CLIB_SUCCESS)) { + LOGD("There is no message code."); // The first message of the client has no message code + return false; + } + if (message != ERR_MSG) { + return false; + } + + if (GetIntFromJson(in, FIELD_ERROR_CODE, &res) != CLIB_SUCCESS) { + LOGE("Get peer error code failed."); + } + LOGE("Receive error message from peer, errCode: %x.", res); + return true; +} + +static int32_t MapSubTaskTypeToOpCode(AccountTaskType subTaskType) +{ + if (subTaskType >= TASK_TYPE_PAKE_V2_AUTH_CLIENT && subTaskType <= TASK_TYPE_ISO_AUTH_SERVER) { + return AUTHENTICATE; + } + return CODE_NULL; +} + +static int32_t ProcessTaskT(AccountTask *task, const CJson *in, CJson *out, int32_t *status) +{ + if (IsPeerErrMessage(in)) { + AccountSendErrMsgToSelf(out, HC_ERR_PEER_ERROR); + return HC_ERR_PEER_ERROR; + } + int32_t res = task->subTask->process(task->subTask, in, out, status); + if (res != HC_SUCCESS) { + LOGE("Process subTask failed, res: %x.", res); + int32_t operationCode = MapSubTaskTypeToOpCode(task->subTask->getTaskType()); + AccountSendErrMsgToOut(out, operationCode, res); + } + return res; +} + +static int32_t NegotiateAndCreateSubTask(AccountTask *task, const CJson *in, CJson *out) +{ + bool isClient = false; + int32_t operationCode = 0; + uint64_t versionNo = 0; + if (GetBoolFromJson(in, FIELD_IS_CLIENT, &isClient) != CLIB_SUCCESS) { + LOGI("There is no isClient in json."); + } + if (GetIntFromJson(in, FIELD_OPERATION_CODE, &operationCode) != CLIB_SUCCESS) { + LOGE("Get operationCode from json failed."); + return HC_ERR_JSON_GET; + } + if (isClient) { + versionNo = GetSupportedVersionNo(operationCode); + } else if (GetInt64FromJson(in, FIELD_SUPPORTED_VERSION, (int64_t *)&versionNo) != CLIB_SUCCESS) { + LOGE("No peer supportedVersion for server."); + return HC_ERR_BAD_MESSAGE; + } + const AccountVersionInfo *verInfo = GetNegotiatedVersionInfo(operationCode, versionNo); + if (verInfo == NULL) { + LOGE("Get Negotiated versionInfo failed."); + return HC_ERR_UNSUPPORTED_VERSION; + } + task->subTask = verInfo->createTask(in, out, verInfo); + if (task->subTask == NULL) { + LOGE("Create sub task failed."); + return HC_ERR_ALLOC_MEMORY; + } + task->versionStatus = VERSION_CONFIRMED; + return HC_SUCCESS; +} + +static void AccountSendCreateError(const CJson *in, CJson *out, int32_t errCode) +{ + bool isClient = false; + if (GetBoolFromJson(in, FIELD_IS_CLIENT, &isClient) != CLIB_SUCCESS) { + LOGE("Get isClient from json failed."); + } + if (isClient) { + AccountSendErrMsgToSelf(out, errCode); + return; + } + int32_t operationCode = CODE_NULL; + if (GetIntFromJson(in, FIELD_OPERATION_CODE, &operationCode) != CLIB_SUCCESS) { + LOGE("Get operationCode from json failed."); + } else { + AccountSendErrMsgToOut(out, operationCode, errCode); + } +} + +AccountTask *CreateAccountTaskT(int32_t *taskId, const CJson *in, CJson *out) +{ + int32_t res; + AccountTask *task = (AccountTask *)HcMalloc(sizeof(AccountTask), 0); + if (task == NULL) { + LOGE("Malloc for account related task failed."); + res = HC_ERR_ALLOC_MEMORY; + goto ERR; + } + task->destroyTask = DestroyTaskT; + task->processTask = ProcessTaskT; + task->versionStatus = VERSION_INITIAL; + Uint8Buff taskIdBuf = { (uint8_t *)taskId, sizeof(int32_t) }; + res = GetLoaderInstance()->generateRandom(&taskIdBuf); + if (res != HC_SUCCESS) { + LOGE("Generate taskId failed, res: %d.", res); + goto ERR; + } + task->taskId = *taskId; + res = NegotiateAndCreateSubTask(task, in, out); + if (res != HC_SUCCESS) { + LOGE("NegotiateAndCreateSubTask failed, res: %d.", res); + goto ERR; + } + return task; +ERR: + AccountSendCreateError(in, out, res); + DestroyTaskT(task); + return NULL; +} diff --git a/services/authenticators/src/account_related/account_version_util.c b/services/authenticators/src/account_related/account_version_util.c new file mode 100644 index 0000000..56d2c05 --- /dev/null +++ b/services/authenticators/src/account_related/account_version_util.c @@ -0,0 +1,93 @@ +/* + * 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 "account_version_util.h" +#include "common_defs.h" +#include "hc_log.h" +#include "hc_types.h" +#include "pake_defs.h" +#include "pake_protocol_dl_common.h" +#include "pake_protocol_ec_common.h" +#include "pake_v2_auth_task_common.h" + +#define IS_SUPPORT_CURVE_256 true +#define IS_SUPPORT_CURVE_25519 false + +DECLARE_HC_VECTOR(AccountVersionInfoVec, void *) +IMPLEMENT_HC_VECTOR(AccountVersionInfoVec, void *, 1) + +static AccountVersionInfoVec g_authVersionInfoVec; + +static uint64_t g_authVersionNo = 0; + +static bool IsAuthPakeV2EcP256Supported(void) +{ + return IsPakeV2AuthTaskSupported() && (GetPakeEcAlg() == PAKE_ALG_EC) && IS_SUPPORT_CURVE_256; +} + +static AccountVersionInfo g_authVersionInfoAll[] = { + { AUTH_PAKE_V2_EC_P256, PAKE_V2, PAKE_ALG_EC, CURVE_256, false, IsAuthPakeV2EcP256Supported, CreatePakeV2AuthTask}, +}; + +void InitVersionInfos(void) +{ + g_authVersionInfoVec = CREATE_HC_VECTOR(AccountVersionInfoVec); + uint32_t size = sizeof(g_authVersionInfoAll) / sizeof(AccountVersionInfo); + for (uint32_t i = 0; i < size; i++) { + if (!g_authVersionInfoAll[i].isTaskSupported()) { + continue; + } + (void)g_authVersionInfoVec.pushBackT(&g_authVersionInfoVec, (void *)(&g_authVersionInfoAll[i])); + g_authVersionNo |= g_authVersionInfoAll[i].versionNo; + } +} + +void DestroyVersionInfos(void) +{ + DESTROY_HC_VECTOR(AccountVersionInfoVec, &g_authVersionInfoVec); +} + +static const AccountVersionInfo *NegotiateForAuth(uint64_t versionNo) +{ + uint32_t index; + void **ptr = NULL; + FOR_EACH_HC_VECTOR(g_authVersionInfoVec, index, ptr) { + if (ptr == NULL || *ptr == NULL) { + continue; + } + AccountVersionInfo *temp = (AccountVersionInfo *)(*ptr); + if ((temp->versionNo & versionNo) == versionNo) { + return temp; + } + } + LOGE("Version is not matched, failed to negotiate for account auth."); + return NULL; +} + +const AccountVersionInfo *GetNegotiatedVersionInfo(int32_t operationCode, uint64_t versionNo) +{ + // Now, only support auth negotiate. + if (operationCode != AUTHENTICATE) { + LOGE("operationCode is not auth, not supported."); + return NULL; + } + return NegotiateForAuth(versionNo); +} + +uint64_t GetSupportedVersionNo(int32_t operationCode) +{ + (void)operationCode; // Now, only support auth negotiate. + return g_authVersionNo; +} diff --git a/services/authenticators/src/account_related/auth/pake_v2_auth_task/pake_v2_auth_client_task.c b/services/authenticators/src/account_related/auth/pake_v2_auth_task/pake_v2_auth_client_task.c new file mode 100644 index 0000000..73d02e2 --- /dev/null +++ b/services/authenticators/src/account_related/auth/pake_v2_auth_task/pake_v2_auth_client_task.c @@ -0,0 +1,312 @@ +/* + * 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 "pake_v2_auth_client_task.h" +#include "common_defs.h" +#include "device_auth_defines.h" +#include "hal_error.h" +#include "hc_types.h" +#include "hc_log.h" +#include "string_util.h" +#include "protocol_common.h" +#include "account_module.h" +#include "account_version_util.h" +#include "pake_v2_auth_task_common.h" +#include "pake_v2_protocol_common.h" + +enum { + TASK_STATUS_PAKE_MAIN_BEGIN = 0, + TASK_STATUS_PAKE_MAIN_STEP_ONE = 1, + TASK_STATUS_PAKE_MAIN_STEP_TWO = 2, + TASK_STATUS_PAKE_MAIN_END = 3, +}; + +static AccountTaskType GetPakeV2AuthClientType(void) +{ + return TASK_TYPE_PAKE_V2_AUTH_CLIENT; +} + +static int32_t DealClientStepOne(PakeAuthParams *params, const CJson *in) +{ + int32_t res = ExtractSelfDevId(params, in); + if (res != HC_SUCCESS) { + LOGE("ExtractSelfDevId failed for client."); + } + return res; +} + +static int32_t AsyAuthClientStepOne(TaskBase *task, const CJson *in, CJson *out, int32_t *status) +{ + PakeV2AuthClientTask *innerTask = (PakeV2AuthClientTask *)task; + CJson *sendToPeer = CreateJson(); + if (sendToPeer == NULL) { + LOGE("Failed to create sendToPeer json."); + return HC_ERR_JSON_CREATE; + } + CJson *data = CreateJson(); + if (data == NULL) { + LOGE("Failed to create data json."); + FreeJson(sendToPeer); + return HC_ERR_JSON_CREATE; + } + uint64_t versionNo = GetSupportedVersionNo(AUTHENTICATE); + + GOTO_IF_ERR(GetIntFromJson(in, FIELD_AUTH_FORM, &innerTask->params.authForm)); + GOTO_IF_ERR(ExtractSelfDeviceId(&innerTask->params, in, true)); + GOTO_IF_ERR(DealClientStepOne(&innerTask->params, in)); + + GOTO_IF_ERR(AddInt64StringToJson(sendToPeer, FIELD_SUPPORTED_VERSION, versionNo)); + GOTO_IF_ERR(AddIntToJson(sendToPeer, FIELD_AUTH_FORM, innerTask->params.authForm)); + GOTO_IF_ERR(AddStringToJson(sendToPeer, FIELD_USER_ID, (const char *)innerTask->params.userIdSelf)); + GOTO_IF_ERR(AddIntToJson(sendToPeer, FIELD_STEP, CMD_PAKE_AUTH_MAIN_ONE)); + GOTO_IF_ERR(AddStringToJson(sendToPeer, FIELD_DEVICE_ID, (const char *)innerTask->params.deviceIdSelf.val)); + GOTO_IF_ERR(AddStringToJson(sendToPeer, FIELD_DEV_ID, (const char *)innerTask->params.devIdSelf.val)); + + GOTO_IF_ERR(AddIntToJson(data, FIELD_AUTH_KEY_ALG_ENCODE, ALG_ECC)); + GOTO_IF_ERR(AddStringToJson(data, FIELD_AUTH_PK_INFO, (const char *)innerTask->params.pkInfoSelf.val)); + GOTO_IF_ERR(AddByteToJson(data, FIELD_AUTH_PK_INFO_SIGN, innerTask->params.pkInfoSignSelf.val, + innerTask->params.pkInfoSignSelf.length)); + GOTO_IF_ERR(AddObjToJson(sendToPeer, FIELD_DATA, data)); + GOTO_IF_ERR(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer)); + innerTask->taskBase.taskStatus = TASK_STATUS_PAKE_MAIN_STEP_ONE; + *status = CONTINUE; + FreeJson(sendToPeer); + FreeJson(data); + return HC_SUCCESS; +ERR: + LOGE("Client step one failed."); + FreeJson(sendToPeer); + FreeJson(data); + return HC_ERR_AUTH_INTERNAL; +} + +static int32_t DealAsyStepTwoData(PakeV2AuthClientTask *task) +{ + if (ExtractPakeSelfId(&task->params) != HC_SUCCESS) { + LOGE("ExtractPakeSelfId failed for client."); + return HC_ERR_AUTH_INTERNAL; + } + if (VerifyPkSignPeer(&task->params) != HC_SUCCESS) { + LOGE("VerifyPkSignPeer failed for client."); + return HC_ERR_ACCOUNT_VERIFY_PK_SIGN; + } + if (GenerateEcdhSharedKey(&task->params) != HC_SUCCESS) { + LOGE("Generate ecdh shared key failed for client."); + return HC_ERR_ACCOUNT_ECDH_FAIL; + } + if (ClientConfirmPakeV2Protocol(&task->params.pakeParams)) { + LOGE("ClientConfirmPakeV2Protocol failed."); + return HC_ERR_CLIENT_CONFIRM_PROTOCOL; + } + return HC_SUCCESS; +} + +static int32_t PrepareAsyClientStepTwoData(const PakeV2AuthClientTask *innerTask, CJson *out) +{ + CJson *sendToPeer = CreateJson(); + if (sendToPeer == NULL) { + LOGE("Create sendToPeer json NULL."); + return HC_ERR_JSON_CREATE; + } + CJson *data = CreateJson(); + if (data == NULL) { + LOGE("Create data json NULL."); + FreeJson(sendToPeer); + return HC_ERR_JSON_CREATE; + } + int32_t ret = HC_SUCCESS; + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_AUTH_FORM, innerTask->params.authForm), ret); + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_STEP, CMD_PAKE_AUTH_MAIN_TWO), ret); + GOTO_ERR_AND_SET_RET(AddByteToJson(data, FIELD_KCF_DATA, innerTask->params.pakeParams.kcfData.val, + innerTask->params.pakeParams.kcfData.length), ret); + GOTO_ERR_AND_SET_RET(AddStringToJson(data, FIELD_DEVICE_ID, + (const char *)innerTask->params.deviceIdSelf.val), ret); + GOTO_ERR_AND_SET_RET(AddByteToJson(data, FIELD_EPK, innerTask->params.pakeParams.epkSelf.val, + innerTask->params.pakeParams.epkSelf.length), ret); + GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_DATA, data), ret); + GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), ret); +ERR: + FreeJson(sendToPeer); + FreeJson(data); + return ret; +} + +static int32_t AsyAuthClientStepTwo(TaskBase *task, const CJson *in, CJson *out, int32_t *status) +{ + PakeV2AuthClientTask *innerTask = (PakeV2AuthClientTask *)task; + if (innerTask->taskBase.taskStatus != TASK_STATUS_PAKE_MAIN_STEP_ONE) { + LOGE("Client step two status error."); + return HC_ERR_AUTH_STATUS; + } + const char *userIdPeer = GetStringFromJson(in, FIELD_USER_ID); + uint32_t userIdPeerLen = HcStrlen(userIdPeer) + 1; + if (userIdPeer == NULL || userIdPeerLen > USER_ID_SIZE) { + LOGE("Payload not contain peer userId or userId len is invalid."); + return HC_ERR_BAD_MESSAGE; + } + GOTO_IF_ERR(strcpy_s((char *)innerTask->params.userIdPeer, userIdPeerLen, userIdPeer)); + GOTO_IF_ERR(GetPkInfoPeer(&innerTask->params, in)); + GOTO_IF_ERR(ExtractPeerDeviceId(&innerTask->params, in)); + GOTO_IF_ERR(ExtractPeerDevId(&innerTask->params, in)); + GOTO_IF_ERR(ExtractPakePeerId(&innerTask->params, in)); + GOTO_IF_ERR(GetByteFromJson(in, FIELD_AUTH_PK_INFO_SIGN, innerTask->params.pkInfoSignPeer.val, + innerTask->params.pkInfoSignPeer.length)); + const char *pkInfoSignPeerStr = GetStringFromJson(in, FIELD_AUTH_PK_INFO_SIGN); + if (pkInfoSignPeerStr == NULL) { + LOGE("pkInfoSignPeer in client is null."); + return HC_ERR_NULL_PTR; + } + innerTask->params.pkInfoSignPeer.length = HcStrlen(pkInfoSignPeerStr) / BYTE_TO_HEX_OPER_LENGTH; + GOTO_IF_ERR(GetByteFromJson(in, FIELD_SALT, innerTask->params.pakeParams.salt.val, + innerTask->params.pakeParams.salt.length)); + GOTO_IF_ERR(GetByteFromJson(in, FIELD_EPK, innerTask->params.pakeParams.epkPeer.val, + innerTask->params.pakeParams.epkPeer.length)); + + GOTO_IF_ERR(DealAsyStepTwoData(innerTask)); + + GOTO_IF_ERR(PrepareAsyClientStepTwoData(innerTask, out)); + + innerTask->taskBase.taskStatus = TASK_STATUS_PAKE_MAIN_STEP_TWO; + *status = CONTINUE; + return HC_SUCCESS; +ERR: + LOGE("Client step two failed"); + return HC_ERR_AUTH_INTERNAL; +} + +static int32_t DealAsyStepThreeData(PakeAuthParams *params) +{ + int32_t res = ClientVerifyConfirmPakeV2Protocol(¶ms->pakeParams); + if (res != HC_SUCCESS) { + LOGE("Client Verify ConfirmPakeV2Protocol failed."); + } + return res; +} + +static int32_t SendFinalToOut(PakeV2AuthClientTask *task, CJson *out) +{ + CJson *sendToSelf = CreateJson(); + if (sendToSelf == NULL) { + LOGE("Create sendToSelf json NULL."); + return HC_ERR_JSON_CREATE; + } + GOTO_IF_ERR(AddStringToJson(sendToSelf, FIELD_USER_ID, (const char *)task->params.userIdPeer)); + GOTO_IF_ERR(AddByteToJson(sendToSelf, + FIELD_SESSION_KEY, task->params.pakeParams.sessionKey.val, task->params.pakeParams.sessionKey.length)); + GOTO_IF_ERR(AddStringToJson(sendToSelf, FIELD_DEVICE_ID, (const char *)task->params.deviceIdSelf.val)); + GOTO_IF_ERR(AddStringToJson(sendToSelf, FIELD_DEV_ID, (const char *)task->params.devIdPeer.val)); + GOTO_IF_ERR(AddObjToJson(out, FIELD_SEND_TO_SELF, sendToSelf)); + FreeJson(sendToSelf); + FreeAndCleanKey(&task->params.pakeParams.sessionKey); + return HC_SUCCESS; +ERR: + FreeAndCleanKey(&task->params.pakeParams.sessionKey); + FreeJson(sendToSelf); + LOGE("SendFinalToOut failed"); + return HC_ERR_AUTH_INTERNAL; +} + +static int32_t AsyAuthClientStepThree(TaskBase *task, const CJson *in, CJson *out, int32_t *status) +{ + PakeV2AuthClientTask *innerTask = (PakeV2AuthClientTask *)task; + if (innerTask->taskBase.taskStatus != TASK_STATUS_PAKE_MAIN_STEP_TWO) { + LOGE("Client step three status error."); + return HC_ERR_AUTH_STATUS; + } + GOTO_IF_ERR(GetByteFromJson(in, FIELD_KCF_DATA, + innerTask->params.pakeParams.kcfDataPeer.val, innerTask->params.pakeParams.kcfDataPeer.length)); + GOTO_IF_ERR(DealAsyStepThreeData(&innerTask->params)); + GOTO_IF_ERR(SendFinalToOut(innerTask, out)); + innerTask->taskBase.taskStatus = TASK_STATUS_PAKE_MAIN_END; + *status = FINISH; + return HC_SUCCESS; +ERR: + LOGE("Client step three failed"); + return HC_ERR_AUTH_INTERNAL; +} + +static int32_t ProcessClientTask(TaskBase *task, const CJson *in, CJson *out, int32_t *status) +{ + LOGI("Start process client pake v2 auth task."); + if (task == NULL || in == NULL || out == NULL || status == NULL) { + LOGE("ProcessClientTask in params NULL."); + return HC_ERR_INVALID_PARAMS; + } + + if (task->taskStatus == TASK_STATUS_PAKE_MAIN_BEGIN) { + return AsyAuthClientStepOne(task, in, out, status); + } + int32_t step = 0; // step comes from opposite device + if (GetIntFromJson(in, FIELD_STEP, &step) != HC_SUCCESS) { + LOGE("Get no auth step."); + return HC_ERR_JSON_GET; + } + int32_t res; + switch (step) { + case RET_PAKE_AUTH_FOLLOWER_ONE: // the step name of the opposite + res = AsyAuthClientStepTwo(task, in, out, status); + break; + case RET_PAKE_AUTH_FOLLOWER_TWO: + res = AsyAuthClientStepThree(task, in, out, status); + break; + case ERR_MSG: + return HC_ERR_PEER_ERROR; + default: + res = HC_ERR_BAD_MESSAGE; + break; + } + if (res != HC_SUCCESS) { + LOGE("error occurred and send error"); + return res; + } + LOGI("End process client, step = %d", step); + return HC_SUCCESS; +} + +static void DestroyAuthClientAuthTask(TaskBase *task) +{ + if (task == NULL) { + LOGD("Task is NULL"); + return; + } + PakeV2AuthClientTask *innerTask = (PakeV2AuthClientTask *)task; + DestroyPakeAuthParams(&(innerTask->params)); + HcFree(innerTask); +} + +TaskBase *CreatePakeV2AuthClientTask(const CJson *in, CJson *out, const AccountVersionInfo *verInfo) +{ + if (in == NULL || out == NULL || verInfo == NULL) { + LOGE("Params is null for create client pake v2 auth task."); + return NULL; + } + PakeV2AuthClientTask *taskParams = (PakeV2AuthClientTask *)HcMalloc(sizeof(PakeV2AuthClientTask), 0); + if (taskParams == NULL) { + LOGE("Malloc for PakeV2AuthClientTask failed."); + return NULL; + } + taskParams->taskBase.getTaskType = GetPakeV2AuthClientType; + taskParams->taskBase.destroyTask = DestroyAuthClientAuthTask; + taskParams->taskBase.process = ProcessClientTask; + int32_t res = InitPakeAuthParams(in, &(taskParams->params), verInfo); + if (res != HC_SUCCESS) { + DestroyAuthClientAuthTask((TaskBase *)taskParams); + LOGE("InitPakeAuthParams failed"); + return NULL; + } + + taskParams->taskBase.taskStatus = TASK_STATUS_PAKE_MAIN_BEGIN; + return (TaskBase *)taskParams; +} \ No newline at end of file diff --git a/services/authenticators/src/account_related/auth/pake_v2_auth_task/pake_v2_auth_server_task.c b/services/authenticators/src/account_related/auth/pake_v2_auth_task/pake_v2_auth_server_task.c new file mode 100644 index 0000000..b0a390e --- /dev/null +++ b/services/authenticators/src/account_related/auth/pake_v2_auth_task/pake_v2_auth_server_task.c @@ -0,0 +1,313 @@ +/* + * 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 "pake_v2_auth_server_task.h" + +#include "account_module.h" +#include "asy_token_manager.h" +#include "common_defs.h" +#include "device_auth_defines.h" +#include "hc_log.h" +#include "hc_types.h" +#include "pake_v2_auth_task_common.h" +#include "pake_v2_protocol_common.h" +#include "protocol_common.h" +#include "account_version_util.h" + +enum { + TASK_STATUS_PAKE_FOLLOW_BEGIN = 0, + TASK_STATUS_PAKE_FOLLOW_STEP_ONE = 1, + TASK_STATUS_PAKE_FOLLOW_STEP_TWO = 2, + TASK_STATUS_PAKE_FOLLOW_END = 3, +}; + +static AccountTaskType GetPakeV2AuthServerType(void) +{ + return TASK_TYPE_PAKE_V2_AUTH_SERVER; +} + +static void DestroyAuthServerAuthTask(TaskBase *task) +{ + if (task == NULL) { + LOGD("NULL pointer and return"); + return; + } + PakeV2AuthServerTask *innerTask = (PakeV2AuthServerTask *)task; + DestroyPakeAuthParams(&(innerTask->params)); + HcFree(innerTask); +} + +static int32_t DealAsyStepOneData(PakeV2AuthServerTask *task, const CJson *in) +{ + int32_t res = ExtractSelfDevId(&task->params, in); + if (res != HC_SUCCESS) { + LOGE("ExtractSelfDevId failed for server."); + return res; + } + if (VerifyPkSignPeer(&task->params) != HC_SUCCESS) { + LOGE("Step one: VerifyPkSignPeer failed for server."); + return HC_ERR_ACCOUNT_VERIFY_PK_SIGN; + } + if (GenerateEcdhSharedKey(&task->params) != HC_SUCCESS) { + LOGE("Step one: Generate ecdh shared key failed for server."); + return HC_ERR_ACCOUNT_ECDH_FAIL; + } + res = ServerResponsePakeV2Protocol(&task->params.pakeParams); + if (res != HC_SUCCESS) { + LOGE("Step one: ServerResponsePakeV2Protocol failed."); + return res; + } + if (ExtractPakeSelfId(&task->params) != HC_SUCCESS) { + LOGE("ConstructPayLoad peer failed."); + return HC_ERR_AUTH_INTERNAL; + } + return HC_SUCCESS; +} + +static int32_t GetNegotiatedVersionForServer(const CJson *in, uint64_t *negotiatedVersionNo) +{ + uint64_t peerSupportedVersion = 0; + if (GetInt64FromJson(in, FIELD_SUPPORTED_VERSION, (int64_t *)&peerSupportedVersion) != HC_SUCCESS) { + LOGE("Get version from client failed."); + return HC_ERR_JSON_GET; + } + const AccountVersionInfo *verInfo = GetNegotiatedVersionInfo(AUTHENTICATE, peerSupportedVersion); + if (verInfo == NULL) { + LOGE("Get negotiated VersionInfo failed for server."); + return HC_ERR_UNSUPPORTED_VERSION; + } + *negotiatedVersionNo = verInfo->versionNo; + return HC_SUCCESS; +} + +static int32_t PrepareAsyServerStepOneData(const PakeV2AuthServerTask *innerTask, const CJson *in, CJson *out) +{ + uint64_t negotiatedVersionNo = 0; + if (GetNegotiatedVersionForServer(in, &negotiatedVersionNo) != HC_SUCCESS) { + return HC_ERR_AUTH_INTERNAL; + } + CJson *sendToPeer = CreateJson(); + if (sendToPeer == NULL) { + LOGE("Create json NULL."); + return HC_ERR_JSON_CREATE; + } + CJson *data = CreateJson(); + if (data == NULL) { + LOGE("Create json NULL."); + FreeJson(sendToPeer); + return HC_ERR_JSON_CREATE; + } + int32_t ret = HC_SUCCESS; + GOTO_ERR_AND_SET_RET(AddInt64StringToJson(sendToPeer, FIELD_SUPPORTED_VERSION, negotiatedVersionNo), ret); + GOTO_ERR_AND_SET_RET(AddStringToJson(sendToPeer, FIELD_USER_ID, + (const char *)innerTask->params.userIdSelf), ret); + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_STEP, RET_PAKE_AUTH_FOLLOWER_ONE), ret); + GOTO_ERR_AND_SET_RET(AddStringToJson(sendToPeer, FIELD_DEVICE_ID, + (const char *)innerTask->params.deviceIdSelf.val), ret); + GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_AUTH_FORM, 1), ret); + GOTO_ERR_AND_SET_RET(AddStringToJson(sendToPeer, FIELD_DEV_ID, (const char *)innerTask->params.devIdSelf.val), ret); + + GOTO_ERR_AND_SET_RET(AddIntToJson(data, FIELD_AUTH_KEY_ALG_ENCODE, innerTask->params.authKeyAlgEncode), ret); + GOTO_ERR_AND_SET_RET(AddStringToJson(data, FIELD_AUTH_PK_INFO, + (const char *)innerTask->params.pkInfoSelf.val), ret); + GOTO_ERR_AND_SET_RET(AddByteToJson(data, FIELD_AUTH_PK_INFO_SIGN, innerTask->params.pkInfoSignSelf.val, + innerTask->params.pkInfoSignSelf.length), ret); + GOTO_ERR_AND_SET_RET(AddByteToJson(data, FIELD_EPK, innerTask->params.pakeParams.epkSelf.val, + innerTask->params.pakeParams.epkSelf.length), ret); + GOTO_ERR_AND_SET_RET(AddByteToJson(data, FIELD_SALT, innerTask->params.pakeParams.salt.val, + innerTask->params.pakeParams.salt.length), ret); + GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_DATA, data), ret); + GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), ret); +ERR: + FreeJson(sendToPeer); + FreeJson(data); + return ret; +} + +static int32_t AsyAuthServerStepOne(TaskBase *task, const CJson *in, CJson *out, int32_t *status) +{ + PakeV2AuthServerTask *innerTask = (PakeV2AuthServerTask *)task; + if (innerTask->taskBase.taskStatus != TASK_STATUS_PAKE_FOLLOW_STEP_ONE) { + LOGE("Server step one task status error."); + return HC_ERR_AUTH_STATUS; + } + GOTO_IF_ERR(GetIntFromJson(in, FIELD_AUTH_FORM, &innerTask->params.authForm)); + const char *userIdPeer = GetStringFromJson(in, FIELD_USER_ID); + uint32_t userIdPeerLen = HcStrlen(userIdPeer) + 1; + if (userIdPeer == NULL || userIdPeerLen > USER_ID_SIZE) { + LOGE("Payload not contain peer userId or userId len is invalid."); + return HC_ERR_BAD_MESSAGE; + } + GOTO_IF_ERR(strcpy_s((char *)innerTask->params.userIdPeer, userIdPeerLen, userIdPeer)); + GOTO_IF_ERR(ExtractSelfDeviceId(&innerTask->params, in, true)); + GOTO_IF_ERR(ExtractPeerDeviceId(&innerTask->params, in)); + GOTO_IF_ERR(ExtractPeerDevId(&innerTask->params, in)); + GOTO_IF_ERR(GetIntFromJson(in, FIELD_AUTH_KEY_ALG_ENCODE, &innerTask->params.authKeyAlgEncode)); + GOTO_IF_ERR(GetPkInfoPeer(&innerTask->params, in)); + GOTO_IF_ERR(GetByteFromJson(in, FIELD_AUTH_PK_INFO_SIGN, innerTask->params.pkInfoSignPeer.val, + innerTask->params.pkInfoSignPeer.length)); + const char *pkInfoSignPeerStr = GetStringFromJson(in, FIELD_AUTH_PK_INFO_SIGN); + if (pkInfoSignPeerStr == NULL) { + LOGE("pkInfoSignPeer in server is null."); + return HC_ERR_NULL_PTR; + } + innerTask->params.pkInfoSignPeer.length = HcStrlen(pkInfoSignPeerStr) / BYTE_TO_HEX_OPER_LENGTH; + GOTO_IF_ERR(DealAsyStepOneData(innerTask, in)); + GOTO_IF_ERR(PrepareAsyServerStepOneData(innerTask, in, out)); + + innerTask->taskBase.taskStatus = TASK_STATUS_PAKE_FOLLOW_STEP_TWO; + *status = CONTINUE; + return HC_SUCCESS; +ERR: + LOGE("Server step one failed."); + return HC_ERR_AUTH_INTERNAL; +} + +static int32_t DealAsyStepTwoData(PakeV2AuthServerTask *task) +{ + if (ServerConfirmPakeV2Protocol(&task->params.pakeParams) != HC_SUCCESS) { + LOGE("Server ConfirmPakeV2Protocol failed."); + return HC_ERR_SERVER_CONFIRM_PROTOCOL; + } + return HC_SUCCESS; +} + +static int32_t SendFinalToOut(PakeV2AuthServerTask *task, CJson *out) +{ + CJson *sendToSelf = CreateJson(); + if (sendToSelf == NULL) { + LOGE("Create json sendToSelf failed."); + return HC_ERR_JSON_CREATE; + } + CJson *sendToPeer = CreateJson(); + if (sendToPeer == NULL) { + LOGE("Create json sendToPeer failed."); + FreeJson(sendToSelf); + return HC_ERR_JSON_CREATE; + } + CJson *sendToPeerData = CreateJson(); + if (sendToPeerData == NULL) { + LOGE("Create json sendToPeerData failed."); + FreeJson(sendToPeer); + FreeJson(sendToSelf); + return HC_ERR_JSON_CREATE; + } + GOTO_IF_ERR(AddStringToJson(sendToSelf, FIELD_USER_ID, (const char *)task->params.userIdPeer)); + GOTO_IF_ERR(AddByteToJson(sendToSelf, FIELD_SESSION_KEY, + task->params.pakeParams.sessionKey.val, task->params.pakeParams.sessionKey.length)); + GOTO_IF_ERR(AddStringToJson(sendToSelf, FIELD_DEVICE_ID, (const char *)task->params.deviceIdSelf.val)); + GOTO_IF_ERR(AddStringToJson(sendToSelf, FIELD_DEV_ID, (const char *)task->params.devIdPeer.val)); + + GOTO_IF_ERR(AddIntToJson(sendToPeer, FIELD_AUTH_FORM, 1)); + GOTO_IF_ERR(AddIntToJson(sendToPeer, FIELD_STEP, RET_PAKE_AUTH_FOLLOWER_TWO)); + + GOTO_IF_ERR(AddByteToJson(sendToPeerData, + FIELD_KCF_DATA, task->params.pakeParams.kcfData.val, task->params.pakeParams.kcfData.length)); + GOTO_IF_ERR(AddObjToJson(out, FIELD_SEND_TO_SELF, sendToSelf)); + GOTO_IF_ERR(AddObjToJson(sendToPeer, FIELD_DATA, sendToPeerData)); + GOTO_IF_ERR(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer)); + FreeJson(sendToPeer); + FreeJson(sendToSelf); + FreeJson(sendToPeerData); + FreeAndCleanKey(&task->params.pakeParams.sessionKey); + return HC_SUCCESS; +ERR: + LOGE("Server send final failed"); + FreeJson(sendToPeer); + FreeJson(sendToSelf); + FreeJson(sendToPeerData); + FreeAndCleanKey(&task->params.pakeParams.sessionKey); + return HC_ERR_AUTH_INTERNAL; +} + +static int32_t AsyAuthServerStepTwo(TaskBase *task, const CJson *in, CJson *out, int32_t *status) +{ + PakeV2AuthServerTask *innerTask = (PakeV2AuthServerTask *)task; + if (innerTask->taskBase.taskStatus != TASK_STATUS_PAKE_FOLLOW_STEP_TWO) { + LOGE("Server task status error"); + return HC_ERR_AUTH_STATUS; + } + GOTO_IF_ERR(GetByteFromJson(in, + FIELD_EPK, innerTask->params.pakeParams.epkPeer.val, innerTask->params.pakeParams.epkPeer.length)); + GOTO_IF_ERR(GetByteFromJson(in, + FIELD_KCF_DATA, innerTask->params.pakeParams.kcfDataPeer.val, innerTask->params.pakeParams.kcfDataPeer.length)); + GOTO_IF_ERR(ExtractPakePeerId(&innerTask->params, in)); + GOTO_IF_ERR(DealAsyStepTwoData(innerTask)); + GOTO_IF_ERR(SendFinalToOut(innerTask, out)); + innerTask->taskBase.taskStatus = TASK_STATUS_PAKE_FOLLOW_END; + *status = FINISH; + return HC_SUCCESS; +ERR: + LOGE("server AsyAuthServerStepTwo failed"); + return HC_ERR_AUTH_INTERNAL; +} + +static int32_t ProcessServerTask(TaskBase *task, const CJson *in, CJson *out, int32_t *status) +{ + if ((task == NULL) || (in == NULL) || (out == NULL) || (status == NULL)) { + LOGE("invalid param"); + return HC_ERR_INVALID_PARAMS; + } + int32_t step = 0; + if (GetIntFromJson(in, FIELD_STEP, &step) != HC_SUCCESS) { + LOGE("server no auth step"); + return HC_ERR_JSON_GET; + } + LOGI("ProcessServerTask step: %d", step); + int32_t res; + switch (step) { + case CMD_PAKE_AUTH_MAIN_ONE: + res = AsyAuthServerStepOne(task, in, out, status); + break; + case CMD_PAKE_AUTH_MAIN_TWO: + res = AsyAuthServerStepTwo(task, in, out, status); + break; + case ERR_MSG: + return HC_ERR_PEER_ERROR; + default: + res = HC_ERR_BAD_MESSAGE; + break; + } + if (res != HC_SUCCESS) { + LOGE("Server ProcessServerTask failed, step: %d.", step); + } + return res; +} + +TaskBase *CreatePakeV2AuthServerTask(const CJson *in, CJson *out, const AccountVersionInfo *verInfo) +{ + if (in == NULL || out == NULL || verInfo == NULL) { + LOGE("Params is null."); + return NULL; + } + PakeV2AuthServerTask *taskParams = (PakeV2AuthServerTask *)HcMalloc(sizeof(PakeV2AuthServerTask), 0); + if (taskParams == NULL) { + LOGE("Malloc taskParams failed"); + return NULL; + } + (void)memset_s(taskParams, sizeof(PakeV2AuthServerTask), 0, sizeof(PakeV2AuthServerTask)); + taskParams->taskBase.getTaskType = GetPakeV2AuthServerType; + taskParams->taskBase.process = ProcessServerTask; + taskParams->taskBase.destroyTask = DestroyAuthServerAuthTask; + + if (InitPakeAuthParams(in, &(taskParams->params), verInfo) != HC_SUCCESS) { + LOGE("InitPakeAuthParams error."); + DestroyAuthServerAuthTask((TaskBase *)taskParams); + return NULL; + } + + taskParams->taskBase.taskStatus = TASK_STATUS_PAKE_FOLLOW_STEP_ONE; + return (TaskBase *)taskParams; +} \ No newline at end of file diff --git a/services/authenticators/src/account_related/auth/pake_v2_auth_task/pake_v2_auth_task_common.c b/services/authenticators/src/account_related/auth/pake_v2_auth_task/pake_v2_auth_task_common.c new file mode 100644 index 0000000..490a1c5 --- /dev/null +++ b/services/authenticators/src/account_related/auth/pake_v2_auth_task/pake_v2_auth_task_common.c @@ -0,0 +1,477 @@ +/* + * 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 "pake_v2_auth_task_common.h" + +#include +#include "account_module.h" +#include "asy_token_manager.h" +#include "common_defs.h" +#include "device_auth_defines.h" +#include "hc_dev_info.h" +#include "hal_error.h" +#include "hc_log.h" +#include "hc_types.h" +#include "pake_v2_protocol_common.h" +#include "pake_v2_auth_client_task.h" +#include "pake_v2_auth_server_task.h" +#include "protocol_common.h" +#include "string_util.h" + +#define P256_SHARED_SECRET_KEY_SIZE 32 +#define P256_PUBLIC_SIZE 64 +#define P256_KEY_SIZE 32 + +#define SHARED_KEY_ALIAS "sharedKeyAlias" + +bool IsPakeV2AuthTaskSupported(void) +{ + return true; +} + +TaskBase *CreatePakeV2AuthTask(const CJson *in, CJson *out, const AccountVersionInfo *verInfo) +{ + bool isClient = false; + if (GetBoolFromJson(in, FIELD_IS_CLIENT, &isClient) != HC_SUCCESS) { + LOGD("Get isClient from json failed."); + isClient = false; + } + if (isClient) { + return CreatePakeV2AuthClientTask(in, out, verInfo); + } + return CreatePakeV2AuthServerTask(in, out, verInfo); +} + +int32_t VerifyPkSignPeer(const PakeAuthParams *params) +{ + uint8_t *serverPkAlias = (uint8_t *)HcMalloc(SHA256_LEN, 0); + if (serverPkAlias == NULL) { + LOGE("Failed to malloc for serverPk key alias."); + return HC_ERR_ALLOC_MEMORY; + } + Uint8Buff serverPkAliasBuff = { + .val = serverPkAlias, + .length = SHA256_LEN + }; + + int32_t res = GetAccountAuthTokenManager()->generateKeyAlias((const char *)(params->userIdSelf), + (const char *)params->devIdSelf.val, &serverPkAliasBuff, true); + if (res != HC_SUCCESS) { + HcFree(serverPkAlias); + return res; + } + + Uint8Buff messageBuff = { + .val = params->pkInfoPeer.val, + .length = params->pkInfoPeer.length + }; + Uint8Buff peerSignBuff = { + .val = params->pkInfoSignPeer.val, + .length = params->pkInfoSignPeer.length + }; + res = params->pakeParams.loader->verify(&serverPkAliasBuff, &messageBuff, P256, &peerSignBuff, true); + HcFree(serverPkAlias); + if (res != HC_SUCCESS) { + LOGE("Verify pk sign failed."); + return HC_ERR_VERIFY_FAILED; + } + return HC_SUCCESS; +} + +int32_t GenerateEcdhSharedKey(PakeAuthParams *params) +{ + uint8_t *priAliasVal = (uint8_t *)HcMalloc(SHA256_LEN, 0); + if (priAliasVal == NULL) { + LOGE("Failed to malloc for self key alias."); + return HC_ERR_ALLOC_MEMORY; + } + Uint8Buff aliasBuff = { + .val = priAliasVal, + .length = SHA256_LEN + }; + int32_t res = GetAccountAuthTokenManager()->generateKeyAlias((const char *)(params->userIdSelf), + (const char *)params->devIdSelf.val, &aliasBuff, false); + if (res != HC_SUCCESS) { + HcFree(priAliasVal); + return res; + } + KeyBuff priAliasKeyBuff = { + .key = aliasBuff.val, + .keyLen = aliasBuff.length, + .isAlias = true + }; + KeyBuff publicKeyBuff = { + .key = params->pkPeer, + .keyLen = sizeof(params->pkPeer), + .isAlias = false + }; + uint32_t sharedKeyAliasLen = HcStrlen(SHARED_KEY_ALIAS) + 1; + params->pakeParams.psk.val = (uint8_t *)HcMalloc(sharedKeyAliasLen, 0); + if (params->pakeParams.psk.val == NULL) { + LOGE("Failed to malloc for psk alias."); + HcFree(priAliasVal); + return HC_ERR_ALLOC_MEMORY; + } + params->pakeParams.psk.length = sharedKeyAliasLen; + (void)memcpy_s(params->pakeParams.psk.val, sharedKeyAliasLen, SHARED_KEY_ALIAS, sharedKeyAliasLen); + res = params->pakeParams.loader->agreeSharedSecretWithStorage(&priAliasKeyBuff, &publicKeyBuff, + P256, P256_SHARED_SECRET_KEY_SIZE, &(params->pakeParams.psk)); + HcFree(priAliasVal); + return res; +} + +static int32_t InitCharStringBuff(Uint8Buff *param, uint32_t len) +{ + if (param == NULL || len <= 0) { + LOGE("param is invalid for init."); + return HC_ERR_NULL_PTR; + } + if (InitSingleParam(param, len + 1) != HC_SUCCESS) { + return HC_ERR_ALLOC_MEMORY; + } + param->length = len; + return HC_SUCCESS; +} + +int32_t ExtractPakePeerId(PakeAuthParams *params, const CJson *in) +{ + if (params == NULL || in == NULL) { + LOGE("Input params is invalid."); + return HC_ERR_INVALID_PARAMS; + } + int32_t deviceIdPeerLen = HcStrlen((const char *)params->deviceIdPeer.val); + if (InitCharStringBuff(¶ms->pakeParams.idPeer, + params->devIdPeer.length + deviceIdPeerLen) != HC_SUCCESS) { + LOGE("InitCharStringBuff: idPeer failed."); + return HC_ERR_AUTH_INTERNAL; + } + (void)memcpy_s(params->pakeParams.idPeer.val, params->pakeParams.idPeer.length, params->devIdPeer.val, + params->devIdPeer.length); + (void)memcpy_s(params->pakeParams.idPeer.val + params->devIdPeer.length, + params->pakeParams.idPeer.length - params->devIdPeer.length, params->deviceIdPeer.val, deviceIdPeerLen); + return HC_SUCCESS; +} + +int32_t ExtractPakeSelfId(PakeAuthParams *params) +{ + if (params == NULL) { + LOGE("Input params NULL."); + return HC_ERR_INVALID_PARAMS; + } + int32_t deviceIdSelfLen = HcStrlen((const char *)params->deviceIdSelf.val); + if (InitCharStringBuff(¶ms->pakeParams.idSelf, + params->devIdSelf.length + deviceIdSelfLen) != HC_SUCCESS) { + LOGE("InitCharStringBuff: idSelf failed."); + return HC_ERR_AUTH_INTERNAL; + } + + (void)memcpy_s(params->pakeParams.idSelf.val, params->pakeParams.idSelf.length, params->devIdSelf.val, + params->devIdSelf.length); + (void)memcpy_s(params->pakeParams.idSelf.val + params->devIdSelf.length, + params->pakeParams.idSelf.length - params->devIdSelf.length, params->deviceIdSelf.val, deviceIdSelfLen); + return HC_SUCCESS; +} + +int32_t ExtractSelfDeviceId(PakeAuthParams *params, const CJson *in, bool useSelfPrefix) +{ + if (params == NULL || in == NULL) { + LOGE("Input params NULL."); + return HC_ERR_INVALID_PARAMS; + } + const char *deviceId = NULL; + if (useSelfPrefix) { + deviceId = GetStringFromJson(in, FIELD_SELF_DEVICE_ID); + } else { + deviceId = GetStringFromJson(in, FIELD_DEVICE_ID); + } + if (deviceId == NULL) { + LOGE("Get selfDeviceId from json failed."); + return HC_ERR_JSON_GET; + } + params->deviceIdSelf.length = HcStrlen(deviceId); + params->deviceIdSelf.val = (uint8_t *)HcMalloc(params->deviceIdSelf.length + 1, 0); + if (params->deviceIdSelf.val == NULL) { + LOGE("Failed to malloc for deviceIdSelf."); + return HC_ERR_ALLOC_MEMORY; + } + if (memcpy_s(params->deviceIdSelf.val, params->deviceIdSelf.length + 1, + deviceId, params->deviceIdSelf.length) != EOK) { + LOGE("Memcpy_s for deviceIdSelf failed."); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +int32_t ExtractPeerDeviceId(PakeAuthParams *params, const CJson *in) +{ + if (params == NULL || in == NULL) { + LOGE("Input params NULL."); + return HC_ERR_INVALID_PARAMS; + } + const char *deviceId = GetStringFromJson(in, FIELD_DEVICE_ID); + if (deviceId == NULL) { + LOGE("Get peer deviceId failed."); + return HC_ERR_JSON_GET; + } + int32_t len = HcStrlen(deviceId); + if (InitCharStringBuff(¶ms->deviceIdPeer, len) != HC_SUCCESS) { + LOGE("InitCharStringBuff: deviceIdPeer failed."); + return HC_ERR_AUTH_INTERNAL; + } + if (memcpy_s(params->deviceIdPeer.val, params->deviceIdPeer.length + 1, deviceId, len) != EOK) { + LOGE("memcpy_s deviceId failed."); + return HC_ERR_MEMORY_COPY; + } + for (uint32_t i = 0; i < params->deviceIdPeer.length; i++) { + // Change a - f charactor to upper charactor. + if (params->deviceIdPeer.val[i] >= 'a' && params->deviceIdPeer.val[i] <= 'f') { + params->deviceIdPeer.val[i] = toupper(params->deviceIdPeer.val[i]); + } + } + return HC_SUCCESS; +} + +int32_t ExtractSelfDevId(PakeAuthParams *params, const CJson *in) +{ + if (params == NULL || in == NULL) { + LOGE("Input params is invalid."); + return HC_ERR_INVALID_PARAMS; + } + const char *devIdSelf = GetStringFromJson(in, FIELD_SELF_DEV_ID); + if (devIdSelf == NULL) { + LOGE("Get devIdSelf failed."); + return HC_ERR_JSON_GET; + } + params->devIdSelf.length = HcStrlen(devIdSelf); + params->devIdSelf.val = (uint8_t *)HcMalloc(params->devIdSelf.length + 1, 0); + if (params->devIdSelf.val == NULL) { + LOGE("Malloc for devIdSelf failed."); + return HC_ERR_ALLOC_MEMORY; + } + if (memcpy_s(params->devIdSelf.val, params->devIdSelf.length, devIdSelf, + params->devIdSelf.length) != EOK) { + LOGE("Copy for self devId failed."); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +int32_t ExtractPeerDevId(PakeAuthParams *params, const CJson *in) +{ + if (params == NULL || in == NULL) { + LOGE("Input params is invalid."); + return HC_ERR_INVALID_PARAMS; + } + const char *devId = GetStringFromJson(in, FIELD_DEV_ID); + if (devId == NULL) { + LOGE("Get PeerDevId failed."); + return HC_ERR_JSON_GET; + } + int32_t len = HcStrlen(devId); + // Peer devId type is hex string, no need to transfer. + if (InitCharStringBuff(¶ms->devIdPeer, len) != HC_SUCCESS) { + LOGE("InitCharStringBuff: idPeer failed."); + return HC_ERR_AUTH_INTERNAL; + } + if (memcpy_s(params->devIdPeer.val, params->devIdPeer.length, devId, len) != EOK) { + LOGE("Failed to copy devId."); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +int32_t GetPkInfoPeer(PakeAuthParams *params, const CJson *in) +{ + if (params == NULL || in == NULL) { + LOGE("Input params is invalid."); + return HC_ERR_INVALID_PARAMS; + } + + const char *pkInfoPeerStr = GetStringFromJson(in, FIELD_AUTH_PK_INFO); + if (pkInfoPeerStr == NULL) { + LOGE("Failed to get peer pkInfo string."); + return HC_ERR_JSON_GET; + } + int32_t len = HcStrlen(pkInfoPeerStr) + 1; + if (InitSingleParam(¶ms->pkInfoPeer, len) != HC_SUCCESS) { + LOGE("Failed to malloc for peer pkInfo."); + return HC_ERR_ALLOC_MEMORY; + } + if (memcpy_s(params->pkInfoPeer.val, len, pkInfoPeerStr, len) != EOK) { + LOGE("GetPkInfoPeer: copy pkInfoPeer failed."); + HcFree(params->pkInfoPeer.val); + params->pkInfoPeer.val = NULL; + return HC_ERR_ALLOC_MEMORY; + } + CJson *info = CreateJsonFromString(pkInfoPeerStr); + if (info == NULL) { + LOGE("Failed to create json for peer pkInfo."); + HcFree(params->pkInfoPeer.val); + params->pkInfoPeer.val = NULL; + return HC_ERR_JSON_CREATE; + } + if (GetByteFromJson(info, FIELD_DEVICE_PK, params->pkPeer, PK_SIZE) != HC_SUCCESS) { + LOGE("Failed to get devicePk."); + FreeJson(info); + HcFree(params->pkInfoPeer.val); + params->pkInfoPeer.val = NULL; + return HC_ERR_JSON_GET; + } + FreeJson(info); + return HC_SUCCESS; +} + +static int32_t GetAsyPubKeyInfo(PakeAuthParams *params) +{ + AccountToken *token = CreateAccountToken(); + if (token == NULL) { + LOGE("Failed to create token."); + return HC_ERR_ALLOC_MEMORY; + } + int32_t res = HC_ERR_GET_PK_INFO; + do { + if (GetAccountAuthTokenManager()->getToken(params->osAccountId, token, + (const char *)params->userIdSelf) != HC_SUCCESS) { + LOGE("Get token from local error."); + break; + } + int32_t pkInfoLen = token->pkInfoStr.length; + if (pkInfoLen >= PUBLIC_KEY_INFO_SIZE) { + LOGE("Length of pkInfo from local is error."); + break; + } + if (InitSingleParam(¶ms->pkInfoSelf, pkInfoLen) != HC_SUCCESS) { + LOGE("InitSingleParam: pkInfoSelf failed."); + break; + } + if (memcpy_s(params->pkInfoSelf.val, params->pkInfoSelf.length, token->pkInfoStr.val, pkInfoLen) != EOK) { + LOGE("Copy pkInfoSelf failed."); + break; + } + if (memcpy_s(params->pkSelf, PK_SIZE, token->pkInfo.devicePk.val, token->pkInfo.devicePk.length) != EOK) { + LOGE("Copy pkSelf failed."); + break; + } + if (memcpy_s(params->pkInfoSignSelf.val, params->pkInfoSignSelf.length, token->pkInfoSignature.val, + token->pkInfoSignature.length) != EOK) { + LOGE("Copy pkInfoSignSelf failed."); + break; + } + params->pkInfoSignSelf.length = token->pkInfoSignature.length; + Uint8Buff serverPk = { + .val = params->pkCloud, + .length = sizeof(params->pkCloud) + }; + if (GetAccountAuthTokenManager()->getServerPublicKey(params->osAccountId, + (const char *)params->userIdSelf, &serverPk) != HC_SUCCESS) { + LOGE("Get local server pk error."); + break; + } + res = HC_SUCCESS; + } while (0); + DestroyAccountToken(token); + return res; +} + +static int32_t FillUserIdForAuth(const CJson *in, PakeAuthParams *params) +{ + const char *userIdSelf = GetStringFromJson(in, FIELD_SELF_USER_ID); + if (userIdSelf == NULL) { + LOGE("Failed to get self userId from input data."); + return HC_ERR_JSON_GET; + } + if (memcpy_s(params->userIdSelf, sizeof(params->userIdSelf), userIdSelf, + sizeof(params->userIdSelf)) != EOK) { + LOGE("Copy for userIdSelf failed."); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +int32_t InitPakeAuthParams(const CJson *in, PakeAuthParams *params, const AccountVersionInfo *verInfo) +{ + if (in == NULL || params == NULL || verInfo == NULL) { + LOGE("Input params is NULL."); + return HC_ERR_INVALID_PARAMS; + } + const char *deviceId = GetStringFromJson(in, FIELD_SELF_DEVICE_ID); + if (deviceId == NULL) { + LOGE("Self deviceId is NULL."); + return HC_ERR_INVALID_PARAMS; + } + int32_t deviceIdLen = HcStrlen(deviceId); + GOTO_IF_ERR(GetIntFromJson(in, FIELD_OS_ACCOUNT_ID, ¶ms->osAccountId)); + GOTO_IF_ERR(InitPakeV2BaseParams(¶ms->pakeParams)); + GOTO_IF_ERR(InitSingleParam(¶ms->pakeParams.epkPeer, P256_PUBLIC_SIZE)); + GOTO_IF_ERR(InitSingleParam(¶ms->pkInfoSignSelf, SIGNATURE_SIZE)); + GOTO_IF_ERR(InitSingleParam(¶ms->pkInfoSignPeer, SIGNATURE_SIZE)); + GOTO_IF_ERR(InitSingleParam(¶ms->pakeParams.idSelf, deviceIdLen + 1)); + (void)memcpy_s(params->pakeParams.idSelf.val, deviceIdLen, deviceId, deviceIdLen); + params->pakeParams.idSelf.length = deviceIdLen; + GOTO_IF_ERR(FillUserIdForAuth(in, params)); + GOTO_IF_ERR(GetBoolFromJson(in, FIELD_IS_CLIENT, ¶ms->pakeParams.isClient)); + GOTO_IF_ERR(GetAsyPubKeyInfo(params)); + + params->pakeParams.supportedPakeAlg = verInfo->pakeAlgType; + params->pakeParams.curveType = verInfo->curveType; + params->versionNo = verInfo->versionNo; +#ifdef ACCOUNT_PAKE_DL_PRIME_LEN_384 + params->pakeParams.supportedDlPrimeMod = (uint32_t)params->pakeParams.supportedDlPrimeMod | DL_PRIME_MOD_384; +#endif +#ifdef ACCOUNT_PAKE_DL_PRIME_LEN_256 + params->pakeParams.supportedDlPrimeMod = (uint32_t)params->pakeParams.supportedDlPrimeMod | DL_PRIME_MOD_256; +#endif + return HC_SUCCESS; +ERR: + LOGE("InitPakeAuthParams failed."); + return HC_ERR_AUTH_INTERNAL; +} + +static void FreeUint8Buff(Uint8Buff *buff) +{ + if (buff == NULL) { + return; + } + if (buff->val != NULL) { + HcFree(buff->val); + buff->val = NULL; + } + buff->length = 0; +} + +void DestroyPakeAuthParams(PakeAuthParams *params) +{ + if (params == NULL) { + LOGE("Pointer is NULL."); + return; + } + + (void)memset_s(params->pkCloud, sizeof(params->pkCloud), 0, sizeof(params->pkCloud)); + (void)memset_s(params->userIdSelf, sizeof(params->userIdSelf), 0, sizeof(params->userIdSelf)); + (void)memset_s(params->userIdPeer, sizeof(params->userIdPeer), 0, sizeof(params->userIdPeer)); + (void)memset_s(params->pkSelf, sizeof(params->pkSelf), 0, sizeof(params->pkSelf)); + (void)memset_s(params->pkPeer, sizeof(params->pkPeer), 0, sizeof(params->pkPeer)); + (void)memset_s(params->pkInfoPeer.val, params->pkInfoPeer.length, 0, params->pkInfoPeer.length); + FreeUint8Buff(¶ms->pkInfoPeer); + FreeUint8Buff(¶ms->deviceIdPeer); + FreeUint8Buff(¶ms->devIdSelf); + FreeUint8Buff(¶ms->devIdPeer); + FreeUint8Buff(¶ms->pkInfoSelf); + FreeUint8Buff(¶ms->pkInfoSignPeer); + FreeUint8Buff(¶ms->pkInfoSignSelf); + DestroyPakeV2BaseParams(¶ms->pakeParams); + HcFree(params->deviceIdSelf.val); + params->deviceIdSelf.val = NULL; +} \ No newline at end of file diff --git a/services/authenticators/src/account_related/creds_manager/asysmetric_token_manager/asy_token_manager.c b/services/authenticators/src/account_related/creds_manager/asysmetric_token_manager/asy_token_manager.c new file mode 100644 index 0000000..b049fd4 --- /dev/null +++ b/services/authenticators/src/account_related/creds_manager/asysmetric_token_manager/asy_token_manager.c @@ -0,0 +1,1326 @@ +/* + * 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 "asy_token_manager.h" +#include "account_module_defines.h" +#include "alg_loader.h" +#include "common_defs.h" +#include "hc_dev_info.h" +#include "hal_error.h" +#include "hc_file.h" +#include "hc_log.h" +#include "hc_mutex.h" +#include "hc_types.h" +#include "string_util.h" + +IMPLEMENT_HC_VECTOR(AccountTokenVec, AccountToken*, 1) + +typedef struct { + int32_t osAccountId; + AccountTokenVec tokens; +} OsAccountTokenInfo; + +DECLARE_HC_VECTOR(AccountTokenDb, OsAccountTokenInfo) +IMPLEMENT_HC_VECTOR(AccountTokenDb, OsAccountTokenInfo, 1) + +#define MAX_DB_PATH_LEN 256 + +AccountAuthTokenManager g_tokenManager; + +static const AlgLoader *g_algLoader = NULL; +static bool g_isInitial = false; +static AccountTokenDb g_accountTokenDb; +static HcMutex *g_accountDbMutex; + +static int32_t GeneratePkInfoFromJson(PkInfo *info, const CJson *pkInfoJson) +{ + if (GetByteFromJson(pkInfoJson, FIELD_DEVICE_PK, info->devicePk.val, info->devicePk.length) != HC_SUCCESS) { + LOGE("get devicePk failed"); + return HC_ERR_JSON_GET; + } + const char *devicePk = GetStringFromJson(pkInfoJson, FIELD_DEVICE_PK); + info->devicePk.length = HcStrlen(devicePk) / BYTE_TO_HEX_OPER_LENGTH; + const char *version = GetStringFromJson(pkInfoJson, FIELD_VERSION); + if (version == NULL) { + LOGE("get version failed"); + return HC_ERR_JSON_GET; + } + if (memcpy_s(info->version.val, info->version.length, version, HcStrlen(version) + 1) != EOK) { + LOGE("memcpy_s version failed"); + return HC_ERR_MEMORY_COPY; + } + info->version.length = HcStrlen(version) + 1; + const char *deviceId = GetStringFromJson(pkInfoJson, FIELD_DEVICE_ID); + if (deviceId == NULL) { + LOGE("get deviceId failed"); + return HC_ERR_JSON_GET; + } + if (memcpy_s(info->deviceId.val, info->deviceId.length, deviceId, HcStrlen(deviceId) + 1) != EOK) { + LOGE("memcpy_s deviceId failed"); + return HC_ERR_MEMORY_COPY; + } + info->deviceId.length = HcStrlen(deviceId) + 1; + const char *userId = GetStringFromJson(pkInfoJson, FIELD_USER_ID); + if (userId == NULL) { + LOGE("get userId failed"); + return HC_ERR_JSON_GET; + } + if (memcpy_s(info->userId.val, info->userId.length, userId, HcStrlen(userId) + 1) != EOK) { + LOGE("memcpy_s userId failed"); + return HC_ERR_MEMORY_COPY; + } + info->userId.length = HcStrlen(userId) + 1; + return HC_SUCCESS; +} + +static bool GetTokenPath(int32_t osAccountId, char *tokenPath, uint32_t pathBufferLen) +{ + const char *beginPath = GetAccountStoragePath(); + if (beginPath == NULL) { + LOGE("Failed to get the account storage path!"); + return false; + } + int32_t ret; + if (osAccountId == DEFAULT_OS_ACCOUNT) { + ret = sprintf_s(tokenPath, pathBufferLen, "%s/account_data.dat", beginPath); + } else { + ret = sprintf_s(tokenPath, pathBufferLen, "%s/account_data%d.dat", beginPath, osAccountId); + } + if (ret <= 0) { + LOGE("sprintf_s fail!"); + return false; + } + return true; +} + +static int32_t GenerateTokenFromJson(CJson *tokenJson, AccountToken *token) +{ + CJson *pkInfoJson = GetObjFromJson(tokenJson, FIELD_PK_INFO); + if (pkInfoJson == NULL) { + LOGE("Failed to get pkInfoJson"); + return HC_ERR_JSON_GET; + } + char *pkInfoStr = PackJsonToString(pkInfoJson); + if (pkInfoStr == NULL) { + LOGE("Pack pkInfoStr failed"); + return HC_ERR_PACKAGE_JSON_TO_STRING_FAIL; + } + if (memcpy_s(token->pkInfoStr.val, token->pkInfoStr.length, pkInfoStr, HcStrlen(pkInfoStr) + 1) != EOK) { + LOGE("Memcpy failed for pkInfoStr"); + FreeJsonString(pkInfoStr); + return HC_ERR_MEMORY_COPY; + } + token->pkInfoStr.length = HcStrlen(pkInfoStr) + 1; + FreeJsonString(pkInfoStr); + if (GetByteFromJson(tokenJson, FIELD_PK_INFO_SIGNATURE, token->pkInfoSignature.val, + token->pkInfoSignature.length) != HC_SUCCESS) { + LOGE("Get pkInfoSignature failed"); + return HC_ERR_JSON_GET; + } + const char *signatureStr = GetStringFromJson(tokenJson, FIELD_PK_INFO_SIGNATURE); + token->pkInfoSignature.length = HcStrlen(signatureStr) / BYTE_TO_HEX_OPER_LENGTH; + if (GetByteFromJson(tokenJson, FIELD_SERVER_PK, token->serverPk.val, + token->serverPk.length) != HC_SUCCESS) { + LOGE("Get serverPk failed"); + return HC_ERR_JSON_GET; + } + const char *serverPkStr = GetStringFromJson(tokenJson, FIELD_SERVER_PK); + token->serverPk.length = HcStrlen(serverPkStr) / BYTE_TO_HEX_OPER_LENGTH; + int32_t ret = GeneratePkInfoFromJson(&token->pkInfo, pkInfoJson); + if (ret != HC_SUCCESS) { + LOGE("Generate pkInfo failed"); + return ret; + } + return HC_SUCCESS; +} + +static int32_t CreateTokensFromJson(CJson *tokensJson, AccountTokenVec *vec) +{ + int32_t tokenNum = GetItemNum(tokensJson); + if (tokenNum <= 0) { + LOGE("No token found."); + return HC_ERR_JSON_GET; + } + int32_t ret; + for (int32_t i = 0; i < tokenNum; i++) { + CJson *tokenJson = GetItemFromArray(tokensJson, i); + if (tokenJson == NULL) { + LOGE("Token json is null"); + ClearAccountTokenVec(vec); + return HC_ERR_JSON_GET; + } + AccountToken *token = CreateAccountToken(); + if (token == NULL) { + LOGE("Failed to create token"); + ClearAccountTokenVec(vec); + return HC_ERR_ALLOC_MEMORY; + } + ret = GenerateTokenFromJson(tokenJson, token); + if (ret != HC_SUCCESS) { + LOGE("Generate token failed"); + DestroyAccountToken(token); + ClearAccountTokenVec(vec); + return ret; + } + if (vec->pushBackT(vec, token) == NULL) { + LOGE("Failed to push token to vec"); + DestroyAccountToken(token); + ClearAccountTokenVec(vec); + return HC_ERR_MEMORY_COPY; + } + } + return HC_SUCCESS; +} + +static int32_t OpenTokenFile(int32_t osAccountId, FileHandle *file, int32_t mode) +{ + char *tokenPath = (char *)HcMalloc(MAX_DB_PATH_LEN, 0); + if (tokenPath == NULL) { + LOGE("Malloc tokenPath failed"); + return HC_ERR_ALLOC_MEMORY; + } + if (!GetTokenPath(osAccountId, tokenPath, MAX_DB_PATH_LEN)) { + LOGE("Get token path failed"); + HcFree(tokenPath); + return HC_ERROR; + } + int32_t ret = HcFileOpen(tokenPath, mode, file); + HcFree(tokenPath); + return ret; +} + +static int32_t ReadTokensFromFile(int32_t osAccountId, AccountTokenVec *vec) +{ + if (vec == NULL) { + LOGE("Input token vec is null."); + return HC_ERR_NULL_PTR; + } + FileHandle file = { 0 }; + int32_t ret = OpenTokenFile(osAccountId, &file, MODE_FILE_READ); + if (ret != HC_SUCCESS) { + LOGE("Open token file failed"); + return ret; + } + int32_t fileSize = HcFileSize(file); + if (fileSize <= 0) { + LOGE("file size stat failed"); + HcFileClose(file); + return HC_ERROR; + } + char *fileData = (char *)HcMalloc(fileSize, 0); + if (fileData == NULL) { + LOGE("Malloc file data failed"); + HcFileClose(file); + return HC_ERR_ALLOC_MEMORY; + } + if (HcFileRead(file, fileData, fileSize) != fileSize) { + LOGE("fileData read failed"); + HcFileClose(file); + HcFree(fileData); + return HC_ERROR; + } + HcFileClose(file); + CJson *readJsonFile = CreateJsonFromString(fileData); + HcFree(fileData); + if (readJsonFile == NULL) { + LOGE("fileData parse failed"); + return HC_ERR_JSON_CREATE; + } + ret = CreateTokensFromJson(readJsonFile, vec); + FreeJson(readJsonFile); + if (ret != HC_SUCCESS) { + LOGE("Failed to create tokens from json"); + } + return ret; +} + +static int32_t WriteTokensJsonToFile(int32_t osAccountId, CJson *tokensJson) +{ + char *storeJsonString = PackJsonToString(tokensJson); + if (storeJsonString == NULL) { + LOGE("Pack stored json to string failed."); + return HC_ERR_PACKAGE_JSON_TO_STRING_FAIL; + } + FileHandle file = { 0 }; + int32_t ret = OpenTokenFile(osAccountId, &file, MODE_FILE_WRITE); + if (ret != HC_SUCCESS) { + LOGE("Open token file failed."); + FreeJsonString(storeJsonString); + return ret; + } + int32_t fileSize = HcStrlen(storeJsonString) + 1; + if (HcFileWrite(file, storeJsonString, fileSize) == fileSize) { + ret = HC_SUCCESS; + } else { + LOGE("Failed to write token array to file."); + ret = HC_ERROR; + } + FreeJsonString(storeJsonString); + HcFileClose(file); + return ret; +} + +static int32_t GenerateJsonFromToken(AccountToken *token, CJson *tokenJson) +{ + CJson *pkInfoJson = CreateJsonFromString((const char *)token->pkInfoStr.val); + if (pkInfoJson == NULL) { + LOGE("Failed to create pkInfoJson"); + return HC_ERR_JSON_CREATE; + } + if (AddObjToJson(tokenJson, FIELD_PK_INFO, pkInfoJson) != HC_SUCCESS) { + LOGE("Add pkInfoJson to json failed"); + FreeJson(pkInfoJson); + return HC_ERR_JSON_ADD; + } + FreeJson(pkInfoJson); + if (AddByteToJson(tokenJson, FIELD_PK_INFO_SIGNATURE, token->pkInfoSignature.val, + token->pkInfoSignature.length) != HC_SUCCESS) { + LOGE("Add pkInfoSignature to json failed"); + return HC_ERR_JSON_ADD; + } + if (AddByteToJson(tokenJson, FIELD_SERVER_PK, token->serverPk.val, + token->serverPk.length) != HC_SUCCESS) { + LOGE("Add serverPk to json failed"); + return HC_ERR_JSON_ADD; + } + return HC_SUCCESS; +} + +static int32_t SaveTokensToFile(int32_t osAccountId, const AccountTokenVec *vec) +{ + CJson *storeJson = CreateJsonArray(); + if (storeJson == NULL) { + LOGE("Create json failed when save tokens to file."); + return HC_ERR_JSON_CREATE; + } + int32_t ret; + uint32_t index; + AccountToken **token; + FOR_EACH_HC_VECTOR(*vec, index, token) { + CJson *tokenJson = CreateJson(); + if (tokenJson == NULL) { + LOGE("Create token json failed."); + FreeJson(storeJson); + return HC_ERR_JSON_CREATE; + } + ret = GenerateJsonFromToken(*token, tokenJson); + if (ret != HC_SUCCESS) { + LOGE("Generate json from token failed"); + FreeJson(tokenJson); + FreeJson(storeJson); + return ret; + } + if (AddObjToArray(storeJson, tokenJson) != HC_SUCCESS) { + LOGE("Add token json to array failed"); + FreeJson(tokenJson); + FreeJson(storeJson); + return HC_ERR_JSON_ADD; + } + } + ret = WriteTokensJsonToFile(osAccountId, storeJson); + FreeJson(storeJson); + return ret; +} + +static Algorithm GetVerifyAlg(const char *version) +{ + (void)version; + return P256; +} + +static int32_t GenerateKeyAlias(const char *userId, const char *deviceId, Uint8Buff *alias, + bool isServerPkAlias) +{ + if ((userId == NULL) || (deviceId == NULL) || (alias == NULL)) { + LOGE("Invalid input params"); + return HC_ERR_NULL_PTR; + } + uint32_t userIdLen = HcStrlen(userId); + uint32_t deviceIdLen = HcStrlen(deviceId); + const char *serverPkTag = "serverPk"; + uint32_t serverPkTagLen = HcStrlen(serverPkTag); + uint32_t aliasStrLen; + if (isServerPkAlias) { + aliasStrLen = userIdLen + deviceIdLen + serverPkTagLen; + } else { + aliasStrLen = userIdLen + deviceIdLen; + } + uint8_t *aliasStr = (uint8_t *)HcMalloc(aliasStrLen, 0); + if (aliasStr == NULL) { + LOGE("Failed to malloc for self key aliasStr."); + return HC_ERR_ALLOC_MEMORY; + } + Uint8Buff aliasBuff = { + aliasStr, + aliasStrLen + }; + if (memcpy_s(aliasBuff.val, aliasBuff.length, userId, userIdLen) != EOK) { + LOGE("Failed to copy userId."); + HcFree(aliasStr); + return HC_ERR_MEMORY_COPY; + } + if (memcpy_s(aliasBuff.val + userIdLen, aliasBuff.length - userIdLen, + deviceId, deviceIdLen) != EOK) { + LOGE("Failed to copy deviceId."); + HcFree(aliasStr); + return HC_ERR_MEMORY_COPY; + } + if (isServerPkAlias && (memcpy_s(aliasBuff.val + userIdLen + deviceIdLen, + aliasBuff.length - userIdLen - deviceIdLen, serverPkTag, serverPkTagLen) != EOK)) { + LOGE("Failed to copy serverPkTag."); + HcFree(aliasStr); + return HC_ERR_MEMORY_COPY; + } + int32_t ret = g_algLoader->sha256(&aliasBuff, alias); + HcFree(aliasStr); + if (ret != HAL_SUCCESS) { + LOGE("Compute alias failed"); + } + return ret; +} + +static int32_t GenerateServerPkAlias(CJson *pkInfoJson, Uint8Buff *alias) +{ + const char *userId = GetStringFromJson(pkInfoJson, FIELD_USER_ID); + if (userId == NULL) { + LOGE("Failed to get userId"); + return HC_ERR_JSON_GET; + } + const char *deviceId = GetStringFromJson(pkInfoJson, FIELD_DEVICE_ID); + if (deviceId == NULL) { + LOGE("Failed to get deviceId"); + return HC_ERR_JSON_GET; + } + return GenerateKeyAlias(userId, deviceId, alias, true); +} + +static int32_t ImportServerPk(const CJson *credJson, Uint8Buff *keyAlias, uint8_t *serverPk, Algorithm alg) +{ + const char *serverPkStr = GetStringFromJson(credJson, FIELD_SERVER_PK); + if (serverPkStr == NULL) { + LOGE("Failed to get serverPkStr"); + return HC_ERR_JSON_GET; + } + uint32_t serverPkLen = HcStrlen(serverPkStr) / BYTE_TO_HEX_OPER_LENGTH; + Uint8Buff keyBuff = { + .val = serverPk, + .length = serverPkLen + }; + int32_t authId = 0; + Uint8Buff authIdBuff = { (uint8_t *)&authId, sizeof(int32_t) }; + ExtraInfo extInfo = { authIdBuff, -1, -1 }; + return g_algLoader->importPublicKey(keyAlias, &keyBuff, alg, &extInfo); +} + +static int32_t VerifyPkInfoSignature(const CJson *credJson, CJson *pkInfoJson, uint8_t *signature, + Uint8Buff *keyAlias, Algorithm alg) +{ + char *pkInfoStr = PackJsonToString(pkInfoJson); + if (pkInfoStr == NULL) { + LOGE("Failed to pack pkInfoStr"); + return HC_ERR_PACKAGE_JSON_TO_STRING_FAIL; + } + Uint8Buff messageBuff = { + .val = (uint8_t *)pkInfoStr, + .length = HcStrlen(pkInfoStr) + 1 + }; + const char *signatureStr = GetStringFromJson(credJson, FIELD_PK_INFO_SIGNATURE); + if (signatureStr == NULL) { + LOGE("Failed to get signatureStr"); + FreeJsonString(pkInfoStr); + return HC_ERR_JSON_GET; + } + uint32_t signatureLen = HcStrlen(signatureStr) / BYTE_TO_HEX_OPER_LENGTH; + Uint8Buff signatureBuff = { + .val = signature, + .length = signatureLen + }; + int32_t ret = g_algLoader->verify(keyAlias, &messageBuff, alg, &signatureBuff, true); + FreeJsonString(pkInfoStr); + return ret; +} + +static int32_t DoImportServerPkAndVerify(const CJson *credJson, uint8_t *signature, uint8_t *serverPk, + CJson *pkInfoJson) +{ + uint8_t *keyAliasValue = (uint8_t *)HcMalloc(SHA256_LEN, 0); + if (keyAliasValue == NULL) { + LOGE("Malloc keyAliasValue failed"); + return HC_ERR_ALLOC_MEMORY; + } + Uint8Buff keyAlias = { + .val = keyAliasValue, + .length = SHA256_LEN + }; + g_accountDbMutex->lock(g_accountDbMutex); + int32_t ret = GenerateServerPkAlias(pkInfoJson, &keyAlias); + if (ret != HC_SUCCESS) { + LOGE("Failed to generate serverPk alias"); + g_accountDbMutex->unlock(g_accountDbMutex); + HcFree(keyAliasValue); + return ret; + } + const char *version = GetStringFromJson(pkInfoJson, FIELD_VERSION); + if (version == NULL) { + LOGE("Failed to get version from pkInfo"); + g_accountDbMutex->unlock(g_accountDbMutex); + HcFree(keyAliasValue); + return HC_ERR_JSON_GET; + } + Algorithm alg = GetVerifyAlg(version); + ret = ImportServerPk(credJson, &keyAlias, serverPk, alg); + if (ret != HAL_SUCCESS) { + LOGE("Import server public key failed"); + g_accountDbMutex->unlock(g_accountDbMutex); + HcFree(keyAliasValue); + return ret; + } + LOGI("Import server public key success, start to verify"); + ret = VerifyPkInfoSignature(credJson, pkInfoJson, signature, &keyAlias, alg); + g_accountDbMutex->unlock(g_accountDbMutex); + HcFree(keyAliasValue); + if (ret != HC_SUCCESS) { + LOGE("Verify pkInfoSignature failed"); + } + return ret; +} + +static int32_t VerifySignature(const CJson *credJson) +{ + LOGI("start verify server message!"); + uint8_t *signature = (uint8_t *)HcMalloc(SIGNATURE_SIZE, 0); + if (signature == NULL) { + LOGE("malloc signature fail!"); + return HC_ERR_ALLOC_MEMORY; + } + if (GetByteFromJson(credJson, FIELD_PK_INFO_SIGNATURE, signature, SIGNATURE_SIZE) != EOK) { + LOGE("get pkInfoSignature fail"); + HcFree(signature); + return HC_ERR_JSON_GET; + } + uint8_t *serverPk = (uint8_t *)HcMalloc(SERVER_PK_SIZE, 0); + if (serverPk == NULL) { + LOGE("malloc serverPk fail!"); + HcFree(signature); + return HC_ERR_ALLOC_MEMORY; + } + if (GetByteFromJson(credJson, FIELD_SERVER_PK, serverPk, SERVER_PK_SIZE) != EOK) { + LOGE("get serverPk fail!"); + HcFree(signature); + HcFree(serverPk); + return HC_ERR_JSON_GET; + } + CJson *pkInfoJson = GetObjFromJson(credJson, FIELD_PK_INFO); + if (pkInfoJson == NULL) { + LOGE("Failed to get pkInfoJson"); + HcFree(signature); + HcFree(serverPk); + return HC_ERR_JSON_GET; + } + int32_t ret = DoImportServerPkAndVerify(credJson, signature, serverPk, pkInfoJson); + HcFree(signature); + HcFree(serverPk); + if (ret != HC_SUCCESS) { + LOGE("Verify pkInfoSignature failed"); + } else { + LOGI("Verify pkInfoSignature success"); + } + return ret; +} + +static OsAccountTokenInfo *GetTokenInfoByOsAccountId(int32_t osAccountId) +{ + uint32_t index = 0; + OsAccountTokenInfo *info = NULL; + FOR_EACH_HC_VECTOR(g_accountTokenDb, index, info) { + if ((info != NULL) && (info->osAccountId == osAccountId)) { + return info; + } + } + LOGI("Create a new os account database cache! [Id]: %d", osAccountId); + OsAccountTokenInfo newInfo; + newInfo.osAccountId = osAccountId; + newInfo.tokens = CreateAccountTokenVec(); + OsAccountTokenInfo *returnInfo = g_accountTokenDb.pushBackT(&g_accountTokenDb, newInfo); + if (returnInfo == NULL) { + LOGE("Failed to push OsAccountTokenInfo to database!"); + DestroyAccountTokenVec(&newInfo.tokens); + } + return returnInfo; +} + +static int32_t GeneratePkInfoFromInfo(const PkInfo *srcInfo, PkInfo *desInfo) +{ + if (memcpy_s(desInfo->userId.val, desInfo->userId.length, + srcInfo->userId.val, srcInfo->userId.length) != EOK) { + LOGE("Memcpy for userId failed."); + return HC_ERR_MEMORY_COPY; + } + desInfo->userId.length = srcInfo->userId.length; + if (memcpy_s(desInfo->deviceId.val, desInfo->deviceId.length, + srcInfo->deviceId.val, srcInfo->deviceId.length) != EOK) { + LOGE("Memcpy for deviceId failed."); + return HC_ERR_MEMORY_COPY; + } + desInfo->deviceId.length = srcInfo->deviceId.length; + if (memcpy_s(desInfo->devicePk.val, desInfo->devicePk.length, + srcInfo->devicePk.val, srcInfo->devicePk.length) != EOK) { + LOGE("Memcpy for devicePk failed."); + return HC_ERR_MEMORY_COPY; + } + desInfo->devicePk.length = srcInfo->devicePk.length; + if (memcpy_s(desInfo->version.val, desInfo->version.length, + srcInfo->version.val, srcInfo->version.length) != EOK) { + LOGE("Memcpy for version failed."); + return HC_ERR_MEMORY_COPY; + } + desInfo->version.length = srcInfo->version.length; + return HC_SUCCESS; +} + +static int32_t SaveOsAccountTokenDb(int32_t osAccountId) +{ + g_accountDbMutex->lock(g_accountDbMutex); + OsAccountTokenInfo *info = GetTokenInfoByOsAccountId(osAccountId); + if (info == NULL) { + LOGE("Get token info by os account id failed"); + g_accountDbMutex->unlock(g_accountDbMutex); + return HC_ERROR; + } + int32_t ret = SaveTokensToFile(osAccountId, &info->tokens); + if (ret != HC_SUCCESS) { + LOGE("Save tokens to file failed"); + g_accountDbMutex->unlock(g_accountDbMutex); + return ret; + } + g_accountDbMutex->unlock(g_accountDbMutex); + LOGI("Save an os account database successfully! [Id]: %d", osAccountId); + return HC_SUCCESS; +} + +static bool GenerateAccountTokenFromToken(const AccountToken *token, AccountToken *returnToken) +{ + if (memcpy_s(returnToken->pkInfoStr.val, returnToken->pkInfoStr.length, + token->pkInfoStr.val, token->pkInfoStr.length) != EOK) { + LOGE("Memcpy for pkInfoStr failed."); + return false; + } + returnToken->pkInfoStr.length = token->pkInfoStr.length; + if (GeneratePkInfoFromInfo(&token->pkInfo, &returnToken->pkInfo) != HC_SUCCESS) { + LOGE("Failed to generate pkInfo"); + return false; + } + if (memcpy_s(returnToken->serverPk.val, returnToken->serverPk.length, + token->serverPk.val, token->serverPk.length) != EOK) { + LOGE("Memcpy for serverPk failed."); + return false; + } + returnToken->serverPk.length = token->serverPk.length; + if (memcpy_s(returnToken->pkInfoSignature.val, returnToken->pkInfoSignature.length, + token->pkInfoSignature.val, token->pkInfoSignature.length) != EOK) { + LOGE("Memcpy for pkInfoSignature failed."); + return false; + } + returnToken->pkInfoSignature.length = token->pkInfoSignature.length; + return true; +} + +static AccountToken *DeepCopyToken(const AccountToken *token) +{ + AccountToken *returnToken = CreateAccountToken(); + if (returnToken == NULL) { + LOGE("Failed to create token"); + return NULL; + } + if (!GenerateAccountTokenFromToken(token, returnToken)) { + LOGE("Generate token from exist token failed"); + DestroyAccountToken(returnToken); + return NULL; + } + return returnToken; +} + +static AccountToken **QueryTokenPtrIfMatch(const AccountTokenVec *vec, const char *userId) +{ + if (userId == NULL) { + LOGE("Invalid input param."); + return NULL; + } + uint32_t index; + AccountToken **token; + FOR_EACH_HC_VECTOR(*vec, index, token) { + if ((token == NULL) || (*token == NULL)) { + continue; + } + if (strcmp(userId, (const char *)((*token)->pkInfo.userId.val)) == 0) { + return token; + } + } + return NULL; +} + +static AccountToken *GetAccountToken(int32_t osAccountId, const char *userId) +{ + g_accountDbMutex->lock(g_accountDbMutex); + OsAccountTokenInfo *info = GetTokenInfoByOsAccountId(osAccountId); + if (info == NULL) { + LOGE("Failed to get token by osAccountId"); + g_accountDbMutex->unlock(g_accountDbMutex); + return NULL; + } + AccountToken **token = QueryTokenPtrIfMatch(&info->tokens, userId); + if ((token == NULL) || (*token == NULL)) { + LOGE("Query token failed"); + g_accountDbMutex->unlock(g_accountDbMutex); + return NULL; + } + g_accountDbMutex->unlock(g_accountDbMutex); + return *token; +} + +static int32_t DeleteTokenInner(int32_t osAccountId, const char *userId, AccountTokenVec *deleteTokens) +{ + LOGI("Start to delete tokens from database!"); + g_accountDbMutex->lock(g_accountDbMutex); + OsAccountTokenInfo *info = GetTokenInfoByOsAccountId(osAccountId); + if (info == NULL) { + LOGE("Failed to get token by os account id"); + g_accountDbMutex->unlock(g_accountDbMutex); + return HC_ERROR; + } + int32_t count = 0; + uint32_t index = 0; + AccountToken **token = NULL; + while (index < HC_VECTOR_SIZE(&info->tokens)) { + token = info->tokens.getp(&info->tokens, index); + if ((token == NULL) || (*token == NULL) || + strcmp(userId, (const char *)((*token)->pkInfo.userId.val)) != 0) { + index++; + continue; + } + AccountToken *deleteToken = NULL; + HC_VECTOR_POPELEMENT(&info->tokens, &deleteToken, index); + count++; + LOGI("Delete a token from database successfully!"); + if (deleteTokens->pushBackT(deleteTokens, deleteToken) == NULL) { + LOGE("Failed to push deleted token to vec"); + DestroyAccountToken(deleteToken); + } + } + g_accountDbMutex->unlock(g_accountDbMutex); + if (count == 0) { + LOGE("No token deleted"); + return HC_ERROR; + } + LOGI("Number of tokens deleted: %d", count); + return HC_SUCCESS; +} + +static int32_t GetToken(int32_t osAccountId, AccountToken *token, const char *userId) +{ + if ((token == NULL) || (userId == NULL)) { + LOGE("Invalid input params"); + return HC_ERR_NULL_PTR; + } + AccountToken *existToken = GetAccountToken(osAccountId, userId); + if (existToken == NULL) { + LOGE("Token not exist"); + return HC_ERROR; + } + int32_t ret = GeneratePkInfoFromInfo(&existToken->pkInfo, &token->pkInfo); + if (ret != HC_SUCCESS) { + LOGE("Generate pkInfo failed"); + return ret; + } + GOTO_ERR_AND_SET_RET(memcpy_s(token->pkInfoStr.val, token->pkInfoStr.length, + existToken->pkInfoStr.val, existToken->pkInfoStr.length), ret); + token->pkInfoStr.length = existToken->pkInfoStr.length; + GOTO_ERR_AND_SET_RET(memcpy_s(token->pkInfoSignature.val, token->pkInfoSignature.length, + existToken->pkInfoSignature.val, existToken->pkInfoSignature.length), ret); + token->pkInfoSignature.length = existToken->pkInfoSignature.length; + GOTO_ERR_AND_SET_RET(memcpy_s(token->serverPk.val, token->serverPk.length, + existToken->serverPk.val, existToken->serverPk.length), ret); + token->serverPk.length = existToken->serverPk.length; + + ret = HC_SUCCESS; + LOGI("GetToken successfully!"); +ERR: + return ret; +} + +static int32_t AddTokenInner(int32_t osAccountId, const AccountToken *token) +{ + LOGI("Start to add a token to database!"); + g_accountDbMutex->lock(g_accountDbMutex); + OsAccountTokenInfo *info = GetTokenInfoByOsAccountId(osAccountId); + if (info == NULL) { + LOGE("Failed to get token by os account id"); + g_accountDbMutex->unlock(g_accountDbMutex); + return HC_ERROR; + } + AccountToken *newToken = DeepCopyToken(token); + if (newToken == NULL) { + LOGE("Deep copy token failed"); + g_accountDbMutex->unlock(g_accountDbMutex); + return HC_ERR_MEMORY_COPY; + } + AccountToken **oldTokenPtr = QueryTokenPtrIfMatch(&info->tokens, (const char *)(newToken->pkInfo.userId.val)); + if (oldTokenPtr != NULL) { + DestroyAccountToken(*oldTokenPtr); + *oldTokenPtr = newToken; + g_accountDbMutex->unlock(g_accountDbMutex); + LOGI("Replace an old token successfully!"); + return HC_SUCCESS; + } + if (info->tokens.pushBackT(&info->tokens, newToken) == NULL) { + DestroyAccountToken(newToken); + g_accountDbMutex->unlock(g_accountDbMutex); + LOGE("Failed to push token to vec!"); + return HC_ERR_MEMORY_COPY; + } + g_accountDbMutex->unlock(g_accountDbMutex); + LOGI("Add a token to database successfully!"); + return HC_SUCCESS; +} + +static int32_t DoExportPkAndCompare(const char *userId, const char *deviceId, + const char *devicePk, Uint8Buff *keyAlias) +{ + g_accountDbMutex->lock(g_accountDbMutex); + int32_t ret = GenerateKeyAlias(userId, deviceId, keyAlias, false); + if (ret != HC_SUCCESS) { + LOGE("Generate key alias failed."); + g_accountDbMutex->unlock(g_accountDbMutex); + return ret; + } + ret = g_algLoader->checkKeyExist(keyAlias); + if (ret != HAL_SUCCESS) { + LOGE("Key pair not exist."); + g_accountDbMutex->unlock(g_accountDbMutex); + return ret; + } + uint8_t *publicKeyVal = (uint8_t *)HcMalloc(PK_SIZE, 0); + if (publicKeyVal == NULL) { + LOGE("Malloc publicKeyVal failed"); + g_accountDbMutex->unlock(g_accountDbMutex); + return HC_ERR_ALLOC_MEMORY; + } + Uint8Buff publicKey = { + .val = publicKeyVal, + .length = PK_SIZE + }; + ret = g_algLoader->exportPublicKey(keyAlias, &publicKey); + if (ret != HAL_SUCCESS) { + LOGE("Failed to export public key"); + HcFree(publicKeyVal); + g_accountDbMutex->unlock(g_accountDbMutex); + return ret; + } + g_accountDbMutex->unlock(g_accountDbMutex); + if (strcmp((const char *)devicePk, (const char *)publicKeyVal) == 0) { + HcFree(publicKeyVal); + return HC_SUCCESS; + } + HcFree(publicKeyVal); + return HC_ERROR; +} + +static int32_t CheckDevicePk(const CJson *credJson) +{ + CJson *pkInfoJson = GetObjFromJson(credJson, FIELD_PK_INFO); + if (pkInfoJson == NULL) { + LOGE("Failed to get pkInfoJson"); + return HC_ERR_JSON_GET; + } + const char *userId = GetStringFromJson(pkInfoJson, FIELD_USER_ID); + if (userId == NULL) { + LOGE("Failed to get userId"); + return HC_ERR_JSON_GET; + } + const char *deviceId = GetStringFromJson(pkInfoJson, FIELD_DEVICE_ID); + if (deviceId == NULL) { + LOGE("Failed to get deviceId"); + return HC_ERR_JSON_GET; + } + uint8_t *devicePk = (uint8_t *)HcMalloc(PK_SIZE, 0); + if (devicePk == NULL) { + LOGE("Malloc devicePk failed"); + return HC_ERR_ALLOC_MEMORY; + } + if (GetByteFromJson(pkInfoJson, FIELD_DEVICE_PK, devicePk, PK_SIZE) != HC_SUCCESS) { + LOGE("Failed to get devicePk"); + HcFree(devicePk); + return HC_ERR_JSON_GET; + } + uint8_t *keyAliasValue = (uint8_t *)HcMalloc(SHA256_LEN, 0); + if (keyAliasValue == NULL) { + LOGE("Malloc keyAliasValue failed"); + HcFree(devicePk); + return HC_ERR_ALLOC_MEMORY; + } + Uint8Buff keyAlias = { + .val = keyAliasValue, + .length = SHA256_LEN + }; + int32_t ret = DoExportPkAndCompare(userId, deviceId, (const char *)devicePk, &keyAlias); + HcFree(devicePk); + HcFree(keyAliasValue); + if (ret == HC_SUCCESS) { + LOGI("Check devicePk success"); + } else { + LOGE("Check devicePk failed"); + } + return ret; +} + +static int32_t CheckUserId(const char *userId, CJson *credJson) +{ + CJson *pkInfoJson = GetObjFromJson(credJson, FIELD_PK_INFO); + if (pkInfoJson == NULL) { + LOGE("Failed to get pkInfoJson"); + return HC_ERR_JSON_GET; + } + const char *userIdFromPk = GetStringFromJson(pkInfoJson, FIELD_USER_ID); + if (userIdFromPk == NULL) { + LOGE("Failed to get userIdFromPk"); + return HC_ERR_JSON_GET; + } + if (strcmp(userId, userIdFromPk) == 0) { + return HC_SUCCESS; + } + return HC_ERROR; +} + +static int32_t CheckCredValidity(const CJson *in, CJson *credJson) +{ + const char *userId = GetStringFromJson(in, FIELD_USER_ID); + if (userId == NULL) { + LOGE("Failed to get userId"); + return HC_ERR_JSON_GET; + } + int32_t ret = VerifySignature(credJson); + if (ret != HC_SUCCESS) { + LOGE("Verify server credential failed!"); + return ret; + } + ret = CheckDevicePk(credJson); + if (ret != HC_SUCCESS) { + LOGE("Check devicePk failed!"); + return ret; + } + ret = CheckUserId(userId, credJson); + if (ret != HC_SUCCESS) { + LOGE("Check userId failed!"); + } + return ret; +} + +static int32_t AddToken(int32_t osAccountId, const CJson *in, CJson *out) +{ + (void)out; + if (in == NULL) { + LOGE("Input param is null!"); + return HC_ERR_NULL_PTR; + } + CJson *credJson = GetObjFromJson(in, FIELD_CREDENTIAL); + if (credJson == NULL) { + LOGE("Failed to get credJson"); + return HC_ERR_JSON_GET; + } + int32_t ret = CheckCredValidity(in, credJson); + if (ret != HC_SUCCESS) { + LOGE("Invalid credential"); + return ret; + } + AccountToken *token = CreateAccountToken(); + if (token == NULL) { + LOGE("Failed to allocate token memory!"); + return HC_ERR_ALLOC_MEMORY; + } + ret = GenerateTokenFromJson(credJson, token); + if (ret != HC_SUCCESS) { + LOGE("Failed to generate token"); + DestroyAccountToken(token); + return ret; + } + ret = AddTokenInner(osAccountId, token); + DestroyAccountToken(token); + if (ret != HC_SUCCESS) { + LOGE("Failed to add token inner"); + return ret; + } + ret = SaveOsAccountTokenDb(osAccountId); + if (ret != HC_SUCCESS) { + LOGE("Failed to save token to db"); + } + return ret; +} + +static int32_t DoGenerateAndExportPk(const char *userId, const char *deviceId, + Uint8Buff *keyAlias, Uint8Buff *publicKey) +{ + g_accountDbMutex->lock(g_accountDbMutex); + int32_t ret = GenerateKeyAlias(userId, deviceId, keyAlias, false); + if (ret != HC_SUCCESS) { + LOGE("Generate key alias failed"); + g_accountDbMutex->unlock(g_accountDbMutex); + return ret; + } + ret = g_algLoader->checkKeyExist(keyAlias); + if (ret != HAL_SUCCESS) { + LOGI("Key pair not exist, start to generate"); + int32_t authId = 0; + Uint8Buff authIdBuff = { (uint8_t *)&authId, sizeof(int32_t) }; + ExtraInfo extInfo = { authIdBuff, -1, -1 }; + ret = g_algLoader->generateKeyPairWithStorage(keyAlias, SELF_ECC_KEY_LEN, P256, &extInfo); + } else { + LOGI("Key pair already exists"); + } + if (ret != HAL_SUCCESS) { + LOGE("Generate key pair failed"); + g_accountDbMutex->unlock(g_accountDbMutex); + return ret; + } + ret = g_algLoader->exportPublicKey(keyAlias, publicKey); + g_accountDbMutex->unlock(g_accountDbMutex); + return ret; +} + +static int32_t GetRegisterProof(const CJson *in, CJson *out) +{ + const char *userId = GetStringFromJson(in, FIELD_USER_ID); + if (userId == NULL) { + LOGE("Failed to get userId!"); + return HC_ERR_JSON_GET; + } + const char *version = GetStringFromJson(in, FIELD_VERSION); + if (version == NULL) { + LOGE("Failed to get version!"); + return HC_ERR_JSON_GET; + } + const char *deviceId = GetStringFromJson(in, FIELD_DEVICE_ID); + if (deviceId == NULL) { + LOGE("Failed to get deviceId!"); + return HC_ERR_JSON_GET; + } + uint8_t *keyAliasValue = (uint8_t *)HcMalloc(SHA256_LEN, 0); + if (keyAliasValue == NULL) { + LOGE("Malloc keyAliasValue failed"); + return HC_ERR_ALLOC_MEMORY; + } + Uint8Buff keyAlias = { + .val = keyAliasValue, + .length = SHA256_LEN + }; + uint8_t *publicKeyVal = (uint8_t *)HcMalloc(PK_SIZE, 0); + if (publicKeyVal == NULL) { + LOGE("Malloc publicKeyVal failed"); + HcFree(keyAliasValue); + return HC_ERR_ALLOC_MEMORY; + } + Uint8Buff publicKey = { + .val = publicKeyVal, + .length = PK_SIZE + }; + int32_t ret = DoGenerateAndExportPk(userId, deviceId, &keyAlias, &publicKey); + HcFree(keyAliasValue); + if (ret != HC_SUCCESS) { + LOGE("exportPublicKey failed"); + goto ERR; + } + GOTO_ERR_AND_SET_RET(AddByteToJson(out, FIELD_DEVICE_PK, publicKeyVal, publicKey.length), ret); + GOTO_ERR_AND_SET_RET(AddStringToJson(out, FIELD_USER_ID, userId), ret); + GOTO_ERR_AND_SET_RET(AddStringToJson(out, FIELD_DEVICE_ID, deviceId), ret); + GOTO_ERR_AND_SET_RET(AddStringToJson(out, FIELD_VERSION, version), ret); + LOGI("Generate register proof successfully!"); +ERR: + HcFree(publicKeyVal); + return ret; +} + +static int32_t GetServerPublicKey(int32_t osAccountId, const char *userId, Uint8Buff *serverPk) +{ + if ((userId == NULL) || (serverPk == NULL)) { + LOGE("Invalid input params"); + return HC_ERR_NULL_PTR; + } + AccountToken *token = GetAccountToken(osAccountId, userId); + if (token == NULL) { + LOGE("Token not exist"); + return HC_ERROR; + } + if (memcpy_s(serverPk->val, serverPk->length, token->serverPk.val, token->serverPk.length) != HC_SUCCESS) { + LOGE("Memcpy for serverPk failed"); + return HC_ERR_MEMORY_COPY; + } + serverPk->length = token->serverPk.length; + return HC_SUCCESS; +} + +static Algorithm GetAlgVersion(int32_t osAccountId, const char *userId) +{ + if (userId == NULL) { + LOGE("Invalid input params, return default alg."); + return P256; + } + AccountToken *token = GetAccountToken(osAccountId, userId); + if (token == NULL) { + LOGE("Token not exist, return default alg."); + return P256; + } + return GetVerifyAlg((const char *)token->pkInfo.version.val); +} + +static void DeleteKeyPair(AccountToken *token) +{ + uint8_t *keyAliasValue = (uint8_t *)HcMalloc(SHA256_LEN, 0); + if (keyAliasValue == NULL) { + LOGE("Malloc keyAliasValue failed"); + return; + } + Uint8Buff keyAlias = { + .val = keyAliasValue, + .length = SHA256_LEN + }; + g_accountDbMutex->lock(g_accountDbMutex); + if (GenerateKeyAlias((const char *)token->pkInfo.userId.val, + (const char *)token->pkInfo.deviceId.val, &keyAlias, false) != HC_SUCCESS) { + LOGE("Failed to generate key alias"); + HcFree(keyAliasValue); + g_accountDbMutex->unlock(g_accountDbMutex); + return; + } + if (g_algLoader->deleteKey(&keyAlias) != HAL_SUCCESS) { + LOGE("Failed to delete key pair"); + } else { + LOGI("Delete key pair success"); + } + HcFree(keyAliasValue); + g_accountDbMutex->unlock(g_accountDbMutex); +} + +static int32_t DeleteToken(int32_t osAccountId, const char *userId) +{ + if (userId == NULL) { + LOGE("Invalid user id"); + return HC_ERR_NULL_PTR; + } + AccountTokenVec deleteTokens = CreateAccountTokenVec(); + int32_t ret = DeleteTokenInner(osAccountId, userId, &deleteTokens); + if (ret != HC_SUCCESS) { + LOGE("Failed to delete token inner, account id is: %d", osAccountId); + DestroyAccountTokenVec(&deleteTokens); + return ret; + } + ret = SaveOsAccountTokenDb(osAccountId); + if (ret != HC_SUCCESS) { + LOGE("Failed to save token to db, account id is: %d", osAccountId); + ClearAccountTokenVec(&deleteTokens); + return ret; + } + uint32_t index; + AccountToken **token; + FOR_EACH_HC_VECTOR(deleteTokens, index, token) { + if ((token != NULL) && (*token != NULL)) { + DeleteKeyPair(*token); + } + } + ClearAccountTokenVec(&deleteTokens); + return HC_SUCCESS; +} + +static void LoadOsAccountTokenDb(int32_t osAccountId) +{ + OsAccountTokenInfo info; + info.osAccountId = osAccountId; + info.tokens = CreateAccountTokenVec(); + if (ReadTokensFromFile(osAccountId, &info.tokens) != HC_SUCCESS) { + DestroyAccountTokenVec(&info.tokens); + return; + } + if (g_accountTokenDb.pushBackT(&g_accountTokenDb, info) == NULL) { + LOGE("Failed to push osAccountInfo to database!"); + ClearAccountTokenVec(&info.tokens); + } + LOGI("Load os account db successfully! [Id]: %d", osAccountId); +} + +static void LoadTokenDb(void) +{ + StringVector dbNameVec = CreateStrVector(); + HcFileGetSubFileName(GetAccountStoragePath(), &dbNameVec); + uint32_t index; + HcString *dbName = NULL; + FOR_EACH_HC_VECTOR(dbNameVec, index, dbName) { + int32_t osAccountId; + const char *name = StringGet(dbName); + if (name == NULL) { + continue; + } + if (strcmp(name, "account_data.dat") == 0) { + LoadOsAccountTokenDb(DEFAULT_OS_ACCOUNT); + } else if (sscanf_s(name, "account_data%d.dat", &osAccountId) == 1) { + LoadOsAccountTokenDb(osAccountId); + } + } + DestroyStrVector(&dbNameVec); +} + +void InitTokenManager(void) +{ + if (g_accountDbMutex == NULL) { + g_accountDbMutex = (HcMutex *)HcMalloc(sizeof(HcMutex), 0); + if (g_accountDbMutex == NULL) { + LOGE("Alloc account database mutex failed"); + return; + } + if (InitHcMutex(g_accountDbMutex) != HC_SUCCESS) { + LOGE("Init account mutex failed"); + HcFree(g_accountDbMutex); + g_accountDbMutex = NULL; + return; + } + } + g_accountDbMutex->lock(g_accountDbMutex); + (void)memset_s(&g_tokenManager, sizeof(AccountAuthTokenManager), 0, sizeof(AccountAuthTokenManager)); + g_tokenManager.addToken = AddToken; + g_tokenManager.getToken = GetToken; + g_tokenManager.deleteToken = DeleteToken; + g_tokenManager.getRegisterProof = GetRegisterProof; + g_tokenManager.getServerPublicKey = GetServerPublicKey; + g_tokenManager.generateKeyAlias = GenerateKeyAlias; + g_tokenManager.getAlgVersion = GetAlgVersion; + if (!g_isInitial) { + g_accountTokenDb = CREATE_HC_VECTOR(AccountTokenDb); + g_isInitial = true; + } + + LoadTokenDb(); + g_algLoader = GetLoaderInstance(); + if (g_algLoader == NULL) { + LOGE("Get loader failed."); + g_accountDbMutex->unlock(g_accountDbMutex); + return; + } + int32_t res = g_algLoader->initAlg(); + if (res != HAL_SUCCESS) { + LOGE("Failed to init algorithm!"); + } + g_accountDbMutex->unlock(g_accountDbMutex); +} + +void ClearAccountTokenVec(AccountTokenVec *vec) +{ + uint32_t index; + AccountToken **token; + FOR_EACH_HC_VECTOR(*vec, index, token) { + DestroyAccountToken(*token); + } + DESTROY_HC_VECTOR(AccountTokenVec, vec); +} + +static void InitTokenData(AccountToken *token) +{ + token->pkInfoStr.val = NULL; + token->pkInfoSignature.val = NULL; + token->serverPk.val = NULL; + token->pkInfo.deviceId.val = NULL; + token->pkInfo.userId.val = NULL; + token->pkInfo.version.val = NULL; + token->pkInfo.devicePk.val = NULL; +} + +AccountToken *CreateAccountToken(void) +{ + AccountToken *token = (AccountToken *)HcMalloc(sizeof(AccountToken), 0); + if (token == NULL) { + LOGE("Failed to allocate accountToken memory!"); + return NULL; + } + InitTokenData(token); + token->pkInfoStr.val = (uint8_t *)HcMalloc(PUBLIC_KEY_INFO_SIZE, 0); + GOTO_IF_CHECK_NULL(token->pkInfoStr.val, "pkInfoStr"); + token->pkInfoStr.length = PUBLIC_KEY_INFO_SIZE; + token->pkInfoSignature.val = (uint8_t *)HcMalloc(SIGNATURE_SIZE, 0); + GOTO_IF_CHECK_NULL(token->pkInfoSignature.val, "pkInfoSignature"); + token->pkInfoSignature.length = SIGNATURE_SIZE; + token->serverPk.val = (uint8_t *)HcMalloc(SERVER_PK_SIZE, 0); + GOTO_IF_CHECK_NULL(token->serverPk.val, "serverPk"); + token->serverPk.length = SERVER_PK_SIZE; + token->pkInfo.deviceId.val = (uint8_t *)HcMalloc(DEVICE_ID_SIZE, 0); + GOTO_IF_CHECK_NULL(token->pkInfo.deviceId.val, "deviceId"); + token->pkInfo.deviceId.length = DEVICE_ID_SIZE; + token->pkInfo.userId.val = (uint8_t *)HcMalloc(USER_ID_SIZE, 0); + GOTO_IF_CHECK_NULL(token->pkInfo.userId.val, "userId"); + token->pkInfo.userId.length = USER_ID_SIZE; + token->pkInfo.version.val = (uint8_t *)HcMalloc(PK_VERSION_SIZE, 0); + GOTO_IF_CHECK_NULL(token->pkInfo.version.val, "version"); + token->pkInfo.version.length = PK_VERSION_SIZE; + token->pkInfo.devicePk.val = (uint8_t *)HcMalloc(PK_SIZE, 0); + GOTO_IF_CHECK_NULL(token->pkInfo.devicePk.val, "devicePk"); + token->pkInfo.devicePk.length = PK_SIZE; + return token; +ERR: + DestroyAccountToken(token); + return NULL; +} + +void DestroyAccountToken(AccountToken *token) +{ + if (token == NULL) { + LOGE("Input token is null"); + return; + } + HcFree(token->pkInfoStr.val); + token->pkInfoStr.length = 0; + HcFree(token->pkInfoSignature.val); + token->pkInfoSignature.length = 0; + HcFree(token->serverPk.val); + token->serverPk.length = 0; + HcFree(token->pkInfo.deviceId.val); + token->pkInfo.deviceId.length = 0; + HcFree(token->pkInfo.userId.val); + token->pkInfo.userId.length = 0; + HcFree(token->pkInfo.version.val); + token->pkInfo.version.length = 0; + HcFree(token->pkInfo.devicePk.val); + token->pkInfo.devicePk.length = 0; + HcFree(token); +} + +AccountAuthTokenManager *GetAccountAuthTokenManager(void) +{ + return &g_tokenManager; +} + +void DestroyTokenManager(void) +{ + g_accountDbMutex->lock(g_accountDbMutex); + g_algLoader = NULL; + (void)memset_s(&g_tokenManager, sizeof(AccountAuthTokenManager), 0, sizeof(AccountAuthTokenManager)); + uint32_t index; + OsAccountTokenInfo *info = NULL; + FOR_EACH_HC_VECTOR(g_accountTokenDb, index, info) { + ClearAccountTokenVec(&info->tokens); + } + DESTROY_HC_VECTOR(AccountTokenDb, &g_accountTokenDb); + g_isInitial = false; + g_accountDbMutex->unlock(g_accountDbMutex); + if (g_accountDbMutex != NULL) { + DestroyHcMutex(g_accountDbMutex); + HcFree(g_accountDbMutex); + g_accountDbMutex = NULL; + } +} \ No newline at end of file diff --git a/services/authenticators/src/account_related_mock/account_module_mock.c b/services/authenticators/src/account_related_mock/account_module_mock.c index 4a105a8..59cdc83 100644 --- a/services/authenticators/src/account_related_mock/account_module_mock.c +++ b/services/authenticators/src/account_related_mock/account_module_mock.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2021-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 @@ -35,8 +35,9 @@ AuthModuleBase *CreateAccountModule(void) return NULL; } -int32_t ProcessAccountCredentials(int credentialOpCode, const CJson *in, CJson *out) +int32_t ProcessAccountCredentials(int32_t osAccountId, int32_t credentialOpCode, const CJson *in, CJson *out) { + (void)osAccountId; (void)credentialOpCode; (void)in; (void)out; diff --git a/services/data_manager/inc/data_manager.h b/services/data_manager/inc/data_manager.h index 2d28c23..d8049ec 100644 --- a/services/data_manager/inc/data_manager.h +++ b/services/data_manager/inc/data_manager.h @@ -33,8 +33,8 @@ typedef struct { int32_t type; /* including identical account group(1), peer to peer group(256), across account group(1282) */ int32_t visibility; /* visibility of the group */ int32_t expireTime; /* the time of group expired, unit day, user config */ - HcString userIdHash; /* hash result of the user account id */ - StringVector sharedUserIdHashVec; /* vector of hash results for shared user account id */ + HcString userId; /* the user account id */ + HcString sharedUserId; /* the shared user account id */ StringVector managers; /* group manager vector, group manager can add and delete members, index 0 is the owner */ StringVector friends; /* group friend vector, group friend can query group information */ } TrustedGroupEntry; @@ -45,11 +45,11 @@ typedef struct { HcString groupId; HcString udid; /* unique device id */ HcString authId; /* id by service defined for authentication */ + HcString userId; /* the user account id */ HcString serviceType; /* compatible with previous versions, the value is the same as groupId */ HcParcel ext; /* for caching extern data, user data */ uint8_t credential; /* 1 - asymmetrical, 2 - symmetrical */ uint8_t devType; /* 0 - accessory, 1 - controller, 2 - proxy */ - HcString userIdHash; /* hash result of the user account id */ uint64_t lastTm; /* accessed time of the device of the auth information, absolute time */ } TrustedDeviceEntry; DECLARE_HC_VECTOR(DeviceEntryVec, TrustedDeviceEntry*) @@ -58,6 +58,7 @@ typedef struct { const char *groupId; const char *groupName; const char *ownerName; + const char *userId; int32_t groupType; int32_t groupVisibility; } QueryGroupParams; diff --git a/services/data_manager/src/data_manager.c b/services/data_manager/src/data_manager.c index 3b62a38..9826129 100644 --- a/services/data_manager/src/data_manager.c +++ b/services/data_manager/src/data_manager.c @@ -34,8 +34,8 @@ typedef struct { TlvUint32 type; TlvInt32 visibility; TlvInt32 expireTime; - TlvString userIdHash; - TlvBuffer sharedUserIdHashVec; + TlvString userId; + TlvString sharedUserId; TlvBuffer managers; TlvBuffer friends; } TlvGroupElement; @@ -56,10 +56,10 @@ typedef struct { TlvString groupId; TlvString udid; TlvString authId; + TlvString userId; TlvString serviceType; TlvBuffer ext; TlvDevAuthFixedLenInfo info; - TlvString userIdHash; } TlvDeviceElement; DECLEAR_INIT_FUNC(TlvDeviceElement) DECLARE_TLV_VECTOR(TlvDeviceVec, TlvDeviceElement) @@ -80,8 +80,8 @@ BEGIN_TLV_STRUCT_DEFINE(TlvGroupElement, 0x0001) TLV_MEMBER(TlvUint32, type, 0x4003) TLV_MEMBER(TlvInt32, visibility, 0x4004) TLV_MEMBER(TlvInt32, expireTime, 0x4005) - TLV_MEMBER(TlvString, userIdHash, 0x4006) - TLV_MEMBER(TlvBuffer, sharedUserIdHashVec, 0x4007) + TLV_MEMBER(TlvString, userId, 0x4006) + TLV_MEMBER(TlvString, sharedUserId, 0x4007) TLV_MEMBER(TlvBuffer, managers, 0x4008) TLV_MEMBER(TlvBuffer, friends, 0x4009) END_TLV_STRUCT_DEFINE() @@ -91,7 +91,7 @@ BEGIN_TLV_STRUCT_DEFINE(TlvDeviceElement, 0x0002) TLV_MEMBER(TlvString, groupId, 0x4101) TLV_MEMBER(TlvString, udid, 0x4102) TLV_MEMBER(TlvString, authId, 0x4103) - TLV_MEMBER(TlvString, userIdHash, 0x4107) + TLV_MEMBER(TlvString, userId, 0x4107) TLV_MEMBER(TlvString, serviceType, 0x4104) TLV_MEMBER(TlvBuffer, ext, 0x4105) TLV_MEMBER(TlvDevAuthFixedLenInfo, info, 0x4106) @@ -229,8 +229,12 @@ bool GenerateGroupEntryFromEntry(const TrustedGroupEntry *entry, TrustedGroupEnt LOGE("[DB]: Failed to copy groupId!"); return false; } - if (!StringSet(&returnEntry->userIdHash, entry->userIdHash)) { - LOGE("[DB]: Failed to copy userIdHash!"); + if (!StringSet(&returnEntry->userId, entry->userId)) { + LOGE("[DB]: Failed to copy userId!"); + return false; + } + if (!StringSet(&returnEntry->sharedUserId, entry->sharedUserId)) { + LOGE("[DB]: Failed to copy sharedUserId!"); return false; } returnEntry->type = entry->type; @@ -265,12 +269,12 @@ bool GenerateDeviceEntryFromEntry(const TrustedDeviceEntry *entry, TrustedDevice LOGE("[DB]: Failed to copy authId!"); return false; } - if (!StringSet(&returnEntry->serviceType, entry->serviceType)) { - LOGE("[DB]: Failed to copy serviceType!"); + if (!StringSet(&returnEntry->userId, entry->userId)) { + LOGE("[DB]: Failed to copy userId!"); return false; } - if (!StringSet(&returnEntry->userIdHash, entry->userIdHash)) { - LOGE("[DB]: Failed to copy userIdHash!"); + if (!StringSet(&returnEntry->serviceType, entry->serviceType)) { + LOGE("[DB]: Failed to copy serviceType!"); return false; } returnEntry->credential = entry->credential; @@ -281,22 +285,28 @@ bool GenerateDeviceEntryFromEntry(const TrustedDeviceEntry *entry, TrustedDevice static bool GenerateGroupEntryFromTlv(TlvGroupElement *group, TrustedGroupEntry *entry) { - if (!LoadStringVectorFromParcel(&entry->managers, &group->managers.data)) { - return false; - } - if (!LoadStringVectorFromParcel(&entry->friends, &group->friends.data)) { - return false; - } - if (!LoadStringVectorFromParcel(&entry->sharedUserIdHashVec, &group->sharedUserIdHashVec.data)) { - return false; - } if (!StringSet(&entry->name, group->name.data)) { + LOGE("[DB]: Failed to load groupName from tlv!"); return false; } if (!StringSet(&entry->id, group->id.data)) { + LOGE("[DB]: Failed to load groupId from tlv!"); return false; } - if (!StringSet(&entry->userIdHash, group->userIdHash.data)) { + if (!StringSet(&entry->userId, group->userId.data)) { + LOGE("[DB]: Failed to load userId from tlv!"); + return false; + } + if (!StringSet(&entry->sharedUserId, group->sharedUserId.data)) { + LOGE("[DB]: Failed to load sharedUserId from tlv!"); + return false; + } + if (!LoadStringVectorFromParcel(&entry->managers, &group->managers.data)) { + LOGE("[DB]: Failed to load managers from tlv!"); + return false; + } + if (!LoadStringVectorFromParcel(&entry->friends, &group->friends.data)) { + LOGE("[DB]: Failed to load friends from tlv!"); return false; } entry->type = group->type.data; @@ -309,21 +319,27 @@ static bool GenerateDeviceEntryFromTlv(TlvDeviceElement *device, TrustedDeviceEn { deviceEntry->groupEntry = NULL; if (!StringSet(&deviceEntry->groupId, device->groupId.data)) { + LOGE("[DB]: Failed to load groupId from tlv!"); return false; } if (!StringSet(&deviceEntry->udid, device->udid.data)) { + LOGE("[DB]: Failed to load udid from tlv!"); return false; } if (!StringSet(&deviceEntry->authId, device->authId.data)) { + LOGE("[DB]: Failed to load authId from tlv!"); + return false; + } + if (!StringSet(&deviceEntry->userId, device->userId.data)) { + LOGE("[DB]: Failed to load userId from tlv!"); return false; } if (!StringSet(&deviceEntry->serviceType, device->serviceType.data)) { - return false; - } - if (!StringSet(&deviceEntry->userIdHash, device->userIdHash.data)) { + LOGE("[DB]: Failed to load serviceType from tlv!"); return false; } if (!ParcelCopy(&device->ext.data, &deviceEntry->ext)) { + LOGE("[DB]: Failed to load external data from tlv!"); return false; } deviceEntry->credential = device->info.data.credential; @@ -497,24 +513,30 @@ static void LoadDeviceAuthDb(void) static bool SetGroupElement(TlvGroupElement *element, TrustedGroupEntry *entry) { if (!StringSet(&element->name.data, entry->name)) { + LOGE("[DB]: Failed to copy groupName!"); return false; } if (!StringSet(&element->id.data, entry->id)) { + LOGE("[DB]: Failed to copy groupId!"); return false; } - if (!StringSet(&element->userIdHash.data, entry->userIdHash)) { + if (!StringSet(&element->userId.data, entry->userId)) { + LOGE("[DB]: Failed to copy userId!"); + return false; + } + if (!StringSet(&element->sharedUserId.data, entry->sharedUserId)) { + LOGE("[DB]: Failed to copy sharedUserId!"); return false; } element->type.data = entry->type; element->visibility.data = entry->visibility; element->expireTime.data = entry->expireTime; if (!SaveStringVectorToParcel(&entry->managers, &element->managers.data)) { + LOGE("[DB]: Failed to copy managers!"); return false; } if (!SaveStringVectorToParcel(&entry->friends, &element->friends.data)) { - return false; - } - if (!SaveStringVectorToParcel(&entry->sharedUserIdHashVec, &element->sharedUserIdHashVec.data)) { + LOGE("[DB]: Failed to copy friends!"); return false; } return true; @@ -523,21 +545,27 @@ static bool SetGroupElement(TlvGroupElement *element, TrustedGroupEntry *entry) static bool SetDeviceElement(TlvDeviceElement *element, TrustedDeviceEntry *entry) { if (!StringSet(&element->groupId.data, entry->groupId)) { + LOGE("[DB]: Failed to copy groupId!"); return false; } if (!StringSet(&element->udid.data, entry->udid)) { + LOGE("[DB]: Failed to copy udid!"); return false; } if (!StringSet(&element->authId.data, entry->authId)) { + LOGE("[DB]: Failed to copy authId!"); + return false; + } + if (!StringSet(&element->userId.data, entry->userId)) { + LOGE("[DB]: Failed to copy userId!"); return false; } if (!StringSet(&element->serviceType.data, entry->serviceType)) { - return false; - } - if (!StringSet(&element->userIdHash.data, entry->userIdHash)) { + LOGE("[DB]: Failed to copy serviceType!"); return false; } if (!ParcelCopy(&element->ext.data, &entry->ext)) { + LOGE("[DB]: Failed to copy external data!"); return false; } element->info.data.credential = entry->credential; @@ -639,6 +667,9 @@ static bool CompareQueryGroupParams(const QueryGroupParams *params, const Truste if ((params->groupName != NULL) && (strcmp(params->groupName, StringGet(&entry->name)) != 0)) { return false; } + if ((params->userId != NULL) && (strcmp(params->userId, StringGet(&entry->userId)) != 0)) { + return false; + } if ((params->groupType != ALL_GROUP) && (params->groupType != entry->type)) { return false; } @@ -747,6 +778,7 @@ QueryGroupParams InitQueryGroupParams(void) .groupId = NULL, .groupName = NULL, .ownerName = NULL, + .userId = NULL, .groupType = ALL_GROUP, .groupVisibility = ALL_GROUP_VISIBILITY }; @@ -772,8 +804,8 @@ TrustedGroupEntry *CreateGroupEntry(void) } ptr->name = CreateString(); ptr->id = CreateString(); - ptr->userIdHash = CreateString(); - ptr->sharedUserIdHashVec = CreateStrVector(); + ptr->userId = CreateString(); + ptr->sharedUserId = CreateString(); ptr->managers = CreateStrVector(); ptr->friends = CreateStrVector(); return ptr; @@ -783,10 +815,10 @@ void DestroyGroupEntry(TrustedGroupEntry *groupEntry) { DeleteString(&groupEntry->name); DeleteString(&groupEntry->id); - DeleteString(&groupEntry->userIdHash); + DeleteString(&groupEntry->userId); + DeleteString(&groupEntry->sharedUserId); DestroyStrVector(&groupEntry->managers); DestroyStrVector(&groupEntry->friends); - DestroyStrVector(&groupEntry->sharedUserIdHashVec); HcFree(groupEntry); } @@ -813,8 +845,8 @@ TrustedDeviceEntry *CreateDeviceEntry(void) ptr->groupId = CreateString(); ptr->udid = CreateString(); ptr->authId = CreateString(); + ptr->userId = CreateString(); ptr->serviceType = CreateString(); - ptr->userIdHash = CreateString(); ptr->ext = CreateParcel(0, 0); return ptr; } @@ -824,8 +856,8 @@ void DestroyDeviceEntry(TrustedDeviceEntry *deviceEntry) DeleteString(&deviceEntry->groupId); DeleteString(&deviceEntry->udid); DeleteString(&deviceEntry->authId); + DeleteString(&deviceEntry->userId); DeleteString(&deviceEntry->serviceType); - DeleteString(&deviceEntry->userIdHash); DeleteParcel(&deviceEntry->ext); HcFree(deviceEntry); } diff --git a/services/device_auth.c b/services/device_auth.c index e09dce4..51b8f63 100644 --- a/services/device_auth.c +++ b/services/device_auth.c @@ -25,7 +25,6 @@ #include "hc_init_protection.h" #include "hc_log.h" #include "json_utils.h" -#include "lcm_adapter.h" #include "os_account_adapter.h" #include "session_manager.h" #include "task_manager.h" @@ -280,7 +279,6 @@ DEVICE_AUTH_API_PUBLIC const DeviceGroupManager *GetGmInstance(void) g_groupManagerInstance->addMemberToGroup = AddMemberToGroupImpl; g_groupManagerInstance->deleteMemberFromGroup = DeleteMemberFromGroupImpl; g_groupManagerInstance->processData = ProcessBindDataImpl; - g_groupManagerInstance->processCredential = ProcessCredential; g_groupManagerInstance->getRegisterInfo = GetRegisterInfo; g_groupManagerInstance->checkAccessToGroup = CheckAccessToGroupImpl; g_groupManagerInstance->getPkInfoList = GetPkInfoListImpl; diff --git a/services/deviceauth.gni b/services/deviceauth.gni index 1546926..22d919b 100644 --- a/services/deviceauth.gni +++ b/services/deviceauth.gni @@ -41,7 +41,6 @@ inc_path = [ "${group_manager_path}/inc/callback_manager", "${group_manager_path}/inc/channel_manager", "${group_manager_path}/inc/channel_manager/soft_bus_channel", - "${group_manager_path}/inc/lcm_adapter", "${group_manager_path}/inc/session", "${group_manager_path}/inc/session/bind_session", "${group_manager_path}/inc/session/bind_session_lite", @@ -82,6 +81,7 @@ deviceauth_common_files = [ "${protocol_path}/src/pake_protocol/pake_v1_protocol/pake_v1_protocol_common.c", "${protocol_path}/src/pake_protocol/pake_protocol_dl_common/pake_protocol_dl_common.c", "${protocol_path}/src/pake_protocol/pake_protocol_ec_common/pake_protocol_ec_common.c", + "${protocol_path}/src/pake_protocol/pake_v2_protocol/pake_v2_protocol_common.c", ] dev_frameworks_files = [ @@ -222,9 +222,6 @@ broadcast_manager_files = broadcast_manager_mock_files = [ "${group_manager_path}/src/broadcast_manager/broadcast_manager_mock.c" ] -lcm_adapter_mock_files = - [ "${group_manager_path}/src/lcm_adapter_mock/lcm_adapter_mock.c" ] - deviceauth_files = dev_frameworks_files + deviceauth_common_files + key_agree_mock_files @@ -282,12 +279,12 @@ if (enable_p2p_auth_standard_protocol == true) { } if (enable_group == true && enable_account == true) { - import("//base/security/deviceauth_account/deviceauth_account.gni") + import("//base/security/deviceauth/services/deviceauth_account.gni") deviceauth_defines += account_related_defines inc_path += account_related_inc_path deviceauth_files += account_related_files + bind_peer_files } else if (enable_group == false && enable_account == true) { - import("//base/security/deviceauth_account/deviceauth_account.gni") + import("//base/security/deviceauth/services/deviceauth_account.gni") deviceauth_defines += account_related_defines inc_path += account_related_inc_path deviceauth_files += @@ -298,7 +295,7 @@ if (enable_group == true && enable_account == true) { group_auth_account_related_mock_files + group_manager_identical_account_mock_files + group_manager_across_account_mock_files + bind_peer_mock_files + - lcm_adapter_mock_files + authenticators_account_related_mock_files + authenticators_account_related_mock_files } if (enable_soft_bus_channel == true) { diff --git a/services/deviceauth_account.gni b/services/deviceauth_account.gni new file mode 100644 index 0000000..df77f3a --- /dev/null +++ b/services/deviceauth_account.gni @@ -0,0 +1,47 @@ +# 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. + +import("//base/security/deviceauth/deviceauth_env.gni") + +account_related_defines = [] +account_related_inc_path = [] + +deviceauth_account_group_manager_path = "${services_path}/group_manager" +deviceauth_account_group_auth_path = "${services_path}/group_auth" + +group_manager_identical_account_files = [ "${deviceauth_account_group_manager_path}/src/group_operation/identical_account_group/identical_account_group.c" ] +group_manager_across_account_files = [ "${deviceauth_account_group_manager_path}/src/group_operation/across_account_group/across_account_group.c" ] + +group_auth_account_related_files = [ "${deviceauth_account_group_auth_path}/src/group_auth_manager/account_related_group_auth/account_related_group_auth.c" ] + +account_related_inc_path += [ + "${services_path}/authenticators/inc", + "${services_path}/authenticators/inc/account_related", + "${services_path}/authenticators/inc/account_related/auth/pake_v2_auth_task", + "${services_path}/authenticators/inc/account_related/creds_manager/asysmetric_token_manager", +] + +authenticators_account_related_files = [ + "${services_path}/authenticators/src/account_related/account_module.c", + "${services_path}/authenticators/src/account_related/account_multi_task_manager.c", + "${services_path}/authenticators/src/account_related/account_task_main.c", + "${services_path}/authenticators/src/account_related/account_version_util.c", + "${services_path}/authenticators/src/account_related/creds_manager/asysmetric_token_manager/asy_token_manager.c", + "${services_path}/authenticators/src/account_related/auth/pake_v2_auth_task/pake_v2_auth_task_common.c", + "${services_path}/authenticators/src/account_related/auth/pake_v2_auth_task/pake_v2_auth_client_task.c", + "${services_path}/authenticators/src/account_related/auth/pake_v2_auth_task/pake_v2_auth_server_task.c", +] + +account_related_files = + group_auth_account_related_files + group_manager_identical_account_files + + group_manager_across_account_files + authenticators_account_related_files diff --git a/services/frameworks/inc/common_defs.h b/services/frameworks/inc/common_defs.h index f81bc24..6e65e97 100644 --- a/services/frameworks/inc/common_defs.h +++ b/services/frameworks/inc/common_defs.h @@ -22,6 +22,12 @@ #include "hc_vector.h" #include "json_utils.h" +#define FIELD_DEVICE_PK "devicePk" +#define FIELD_UDID "udid" +#define FIELD_PK_INFO_SIGNATURE "pkInfoSignature" +#define FIELD_CREDENTIAL "credential" +#define FIELD_SERVER_PK "serverPk" + #define FIELD_ADD_TYPE "addType" #define FIELD_ADD_ID "addId" #define FIELD_ADD_KEY "addKey" @@ -71,7 +77,6 @@ #define FIELD_NONCE "nonce" #define FIELD_OPERATION_CODE "operationCode" #define FIELD_OPERATION_PARAMS "operationParams" -#define FIELD_OS_ACCOUNT_ID "osAccountId" #define FIELD_OWNER_ID "ownerId" #define FIELD_OWNER_NAME "ownerName" #define FIELD_PERMISSION "Permission" @@ -79,9 +84,12 @@ #define FIELD_PEER_DEVICE_ID "peerDeviceId" #define FIELD_PIN_CODE "pinCode" #define FIELD_PUBLIC_KEY "publicKey" +#define FIELD_PK_INFO "pkInfo" #define FIELD_PKG_NAME "pkgName" #define FIELD_SELF_AUTH_ID "selfAuthId" #define FIELD_SELF_DEVICE_ID "selfDeviceId" +#define FIELD_SELF_DEV_ID "selfDevId" +#define FIELD_SELF_USER_ID "selfUserId" #define FIELD_REQUEST_ID "requestId" #define FIELD_RECEIVED_DATA "receivedData" #define FIELD_RETURN_CODE "returnCode" @@ -104,6 +112,13 @@ #define FIELD_VERSION "version" #define FIELD_MK_AGREE_MSG "mkaMsg" #define FIELD_PEER_ID_FROM_REQUEST "peerIdFromRequest" +#define FIELD_STEP "step" +#define FIELD_DATA "data" +#define FIELD_SUPPORTED_VERSION "supportedVersion" +#define FIELD_EPK "epk" +#define FIELD_AUTH_KEY_ALG_ENCODE "authKeyAlgEncode" +#define FIELD_AUTH_PK_INFO "authPkInfo" +#define FIELD_AUTH_PK_INFO_SIGN "authPkInfoSign" #define INVALID_MODULE_TYPE (-1) #define GROUP_ERR_MSG 0x8080 @@ -175,6 +190,14 @@ typedef enum { } \ } while (0) +#define GOTO_IF_CHECK_NULL(ptr, paramTag) \ + do { \ + if ((ptr) == NULL) { \ + LOGE("%s is null ptr", (paramTag)); \ + goto ERR; \ + } \ + } while (0) + #define GOTO_ERR_AND_SET_RET(x, res) do { \ res = x; \ if ((res) != HC_SUCCESS) { \ diff --git a/services/frameworks/inc/module/dev_auth_module_manager.h b/services/frameworks/inc/module/dev_auth_module_manager.h index c890ee1..2332120 100644 --- a/services/frameworks/inc/module/dev_auth_module_manager.h +++ b/services/frameworks/inc/module/dev_auth_module_manager.h @@ -56,7 +56,7 @@ int32_t DeletePeerAuthInfo(const char *pkgName, const char *serviceType, Uint8Bu int32_t GetPublicKey(int moduleType, AuthModuleParams *params, Uint8Buff *returnPk); // for ACCOUNT -int32_t ProcessCredentials(int credentialOpCode, const CJson *in, CJson *out, int moduleType); +int32_t GetRegisterInfo(const char *reqJsonStr, char **returnRegisterInfo); #ifdef __cplusplus } diff --git a/services/frameworks/src/module/dev_auth_module_manager.c b/services/frameworks/src/module/dev_auth_module_manager.c index 6f26bf1..330d09c 100644 --- a/services/frameworks/src/module/dev_auth_module_manager.c +++ b/services/frameworks/src/module/dev_auth_module_manager.c @@ -17,6 +17,7 @@ #include "common_defs.h" #include "das_module.h" #include "hc_log.h" +#include "hc_types.h" #include "hc_vector.h" #include "account_module.h" #include "version_util.h" @@ -257,6 +258,17 @@ static int32_t InitAccountModule(void) return HC_SUCCESS; } +static int32_t ProcessCredentials(int32_t osAccountId, int32_t credentialOpCode, + const CJson *in, CJson *out, int moduleType) +{ + if (moduleType != ACCOUNT_MODULE) { + LOGE("Unsupported method in the module, moduleType: %d.", moduleType); + return HC_ERR_NOT_SUPPORT; + } + + return ProcessAccountCredentials(osAccountId, credentialOpCode, in, out); +} + int32_t InitModules(void) { g_authModuleVec = CREATE_HC_VECTOR(AuthModuleVec); @@ -297,12 +309,35 @@ void DestroyModules(void) (void)memset_s(&g_version, sizeof(VersionStruct), 0, sizeof(VersionStruct)); } -int32_t ProcessCredentials(int credentialOpCode, const CJson *in, CJson *out, int moduleType) +int32_t GetRegisterInfo(const char *reqJsonStr, char **returnRegisterInfo) { - if (moduleType != ACCOUNT_MODULE) { - LOGE("Unsupported method in the module, moduleType: %d.", moduleType); - return HC_ERR_NOT_SUPPORT; + if ((reqJsonStr == NULL) || (returnRegisterInfo == NULL)) { + LOGE("The input param is NULL!"); + return HC_ERR_NULL_PTR; } - - return ProcessAccountCredentials(credentialOpCode, in, out); + CJson *requestJson = CreateJsonFromString(reqJsonStr); + if (requestJson == NULL) { + LOGE("Failed to create request json!"); + return HC_ERR_JSON_CREATE; + } + CJson *registerInfo = CreateJson(); + if (registerInfo == NULL) { + LOGE("Failed to allocate registerInfo memory!"); + FreeJson(requestJson); + return HC_ERR_JSON_CREATE; + } + int32_t result = ProcessCredentials(0, REQUEST_SIGNATURE, requestJson, registerInfo, ACCOUNT_MODULE); + FreeJson(requestJson); + if (result != HC_SUCCESS) { + LOGE("Failed to get register info!"); + FreeJson(registerInfo); + return result; + } + *returnRegisterInfo = PackJsonToString(registerInfo); + FreeJson(registerInfo); + if (*returnRegisterInfo == NULL) { + LOGE("Failed to convert json to string!"); + return HC_ERR_PACKAGE_JSON_TO_STRING_FAIL; + } + return HC_SUCCESS; } diff --git a/services/group_auth/inc/account_related_group_auth/account_related_group_auth.h b/services/group_auth/inc/account_related_group_auth/account_related_group_auth.h index 1ee1e64..4d42a6d 100644 --- a/services/group_auth/inc/account_related_group_auth/account_related_group_auth.h +++ b/services/group_auth/inc/account_related_group_auth/account_related_group_auth.h @@ -20,8 +20,8 @@ #include "base_group_auth.h" #include "data_manager.h" -typedef void (*GetAccountCandidateGroupFunc)(const CJson *param, const QueryGroupParams *queryParams, - GroupEntryVec *vec); +typedef void (*GetAccountCandidateGroupFunc)(int32_t osAccountId, const CJson *param, + QueryGroupParams *queryParams, GroupEntryVec *vec); typedef struct { BaseGroupAuth base; diff --git a/services/group_auth/inc/group_auth_data_operation.h b/services/group_auth/inc/group_auth_data_operation.h index ac335bc..c7331fc 100644 --- a/services/group_auth/inc/group_auth_data_operation.h +++ b/services/group_auth/inc/group_auth_data_operation.h @@ -27,6 +27,7 @@ int32_t GaGetTrustedDeviceEntryById(int32_t osAccountId, const char *deviceId, bool isUdid, const char *groupId, TrustedDeviceEntry *returnDeviceEntry); bool GaIsDeviceInGroup(int32_t groupType, int32_t osAccountId, const char *peerUdid, const char *peerAuthId, const char *groupId); +int32_t GaGetLocalDeviceInfo(int32_t osAccountId, const char *groupId, TrustedDeviceEntry *localAuthInfo); #ifdef __cplusplus } diff --git a/services/group_auth/inc/session/auth_session/auth_session_util.h b/services/group_auth/inc/session/auth_session/auth_session_util.h index 152151a..a04f2b0 100644 --- a/services/group_auth/inc/session/auth_session/auth_session_util.h +++ b/services/group_auth/inc/session/auth_session/auth_session_util.h @@ -30,6 +30,7 @@ int32_t GetAuthModuleType(const CJson *in); int32_t GetInfoHash(const uint8_t *info, uint32_t infoLen, char *str, uint32_t strLen); bool IsBleAuthForAcrossAccount(const CJson *authParam); int32_t GroupTypeToAuthForm(int32_t groupType); +int32_t AuthFormToGroupType(int32_t authForm); #ifdef __cplusplus } diff --git a/services/group_auth/inc/session/auth_session_common_util.h b/services/group_auth/inc/session/auth_session_common_util.h index ed74416..6361eae 100644 --- a/services/group_auth/inc/session/auth_session_common_util.h +++ b/services/group_auth/inc/session/auth_session_common_util.h @@ -26,7 +26,7 @@ extern "C" { char *GetServerConfirmation(const CJson *paramsFromClient, const CJson *reqParam, const DeviceAuthCallback *callback); int32_t GetGeneralReqParams(const CJson *receiveData, CJson *reqParam); -bool IsUidHashEqual(const char *uidHashInDb, const char *peerUidHash); +bool IsUserIdEqual(const char *userIdInDb, const char *peerUserIdInDb); #ifdef __cplusplus } #endif diff --git a/services/group_auth/src/group_auth_manager/account_related_group_auth/account_related_group_auth.c b/services/group_auth/src/group_auth_manager/account_related_group_auth/account_related_group_auth.c new file mode 100644 index 0000000..8ffc31c --- /dev/null +++ b/services/group_auth/src/group_auth_manager/account_related_group_auth/account_related_group_auth.c @@ -0,0 +1,627 @@ +/* + * 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 "account_related_group_auth.h" +#include "auth_session_common.h" +#include "auth_session_common_util.h" +#include "auth_session_util.h" +#include "common_defs.h" +#include "device_auth_defines.h" +#include "group_auth_data_operation.h" +#include "hc_dev_info.h" +#include "hc_log.h" +#include "hc_types.h" +#include "json_utils.h" +#include "string_util.h" + +static void OnAccountFinish(int64_t requestId, const CJson *authParam, const CJson *out, + const DeviceAuthCallback *callback); +static void OnAccountError(int64_t requestId, const AuthSession *session, int errorCode); +static int32_t FillAccountAuthInfo(int32_t osAccountId, const TrustedGroupEntry *entry, + const TrustedDeviceEntry *localAuthInfo, CJson *paramsData); +static void GetAccountCandidateGroup(int32_t osAccountId, const CJson *param, + QueryGroupParams *queryParams, GroupEntryVec *vec); +static int32_t GetAccountAuthParamForServer(const CJson *dataFromClient, ParamsVec *authParamsVec); +static int32_t GetAccountReqParams(const CJson *receiveData, CJson *reqParam); +static int32_t CombineAccountServerConfirms(const CJson *confirmationJson, CJson *dataFromClient); + +static AccountRelatedGroupAuth g_accountRelatedGroupAuth = { + .base.onFinish = OnAccountFinish, + .base.onError = OnAccountError, + .base.fillDeviceAuthInfo = FillAccountAuthInfo, + .base.getAuthParamForServer = GetAccountAuthParamForServer, + .base.getReqParams = GetAccountReqParams, + .base.combineServerConfirmParams = CombineAccountServerConfirms, + .base.authType = ACCOUNT_RELATED_GROUP_AUTH_TYPE, + .getAccountCandidateGroup = GetAccountCandidateGroup, +}; + +static int32_t GetSessionKeyForAccount(const CJson *sendToSelf, CJson *returnToSelf) +{ + int32_t keyLen = DEFAULT_RETURN_KEY_LENGTH; + uint8_t *sessionKey = (uint8_t *)HcMalloc(keyLen, 0); + if (sessionKey == NULL) { + LOGE("Failed to allocate memory for sessionKey!"); + return HC_ERR_ALLOC_MEMORY; + } + int32_t res = HC_SUCCESS; + do { + if (GetByteFromJson(sendToSelf, FIELD_SESSION_KEY, sessionKey, keyLen) != HC_SUCCESS) { + LOGE("Failed to get sessionKey!"); + res = HC_ERR_JSON_GET; + break; + } + if (AddByteToJson(returnToSelf, FIELD_SESSION_KEY, (const uint8_t *)sessionKey, keyLen) != HC_SUCCESS) { + LOGE("Failed to add sessionKey for onFinish!"); + res = HC_ERR_JSON_FAIL; + break; + } + } while (0); + (void)memset_s(sessionKey, keyLen, 0, keyLen); + HcFree(sessionKey); + sessionKey = NULL; + return res; +} + +static int32_t GetUserIdForAccount(const CJson *sendToSelf, CJson *returnToSelf) +{ + const char *peerUserId = GetStringFromJson(sendToSelf, FIELD_USER_ID); + if (peerUserId == NULL) { + LOGE("Failed to get peer uid!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(returnToSelf, FIELD_USER_ID, peerUserId) != HC_SUCCESS) { + LOGE("Failed to add peer uid!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static bool IsPeerInAccountRelatedGroup(const TrustedGroupEntry *groupEntry, const char *peerUserId) +{ + const char *peerUserIdInDb = StringGet(&groupEntry->userId); + if (peerUserIdInDb == NULL) { + LOGD("Failed to get peer userId from db!"); + return false; + } + if (IsUserIdEqual(peerUserIdInDb, peerUserId)) { + LOGI("[Account auth]: the input peer-userId is in one across group, add across-group auth!"); + return true; + } + return false; +} + +static bool IsPeerInIdenticalGroup(int32_t osAccountId, const char *peerUserId) +{ + bool isGroupExist = false; + GroupEntryVec accountVec = CreateGroupEntryVec(); + QueryGroupParams queryParams = InitQueryGroupParams(); + queryParams.groupType = IDENTICAL_ACCOUNT_GROUP; + do { + if (QueryGroups(osAccountId, &queryParams, &accountVec) != HC_SUCCESS) { + LOGD("No identical-account group in db, no identical-account auth!"); + break; + } + uint32_t index = 0; + TrustedGroupEntry **ptr = NULL; + while (index < accountVec.size(&accountVec)) { + ptr = accountVec.getp(&accountVec, index); + if ((ptr == NULL) || (*ptr == NULL)) { + index++; + continue; + } + if (IsPeerInAccountRelatedGroup(*ptr, peerUserId)) { + isGroupExist = true; + break; + } + } + } while (0); + ClearGroupEntryVec(&accountVec); + return isGroupExist; +} + +static void GaGetAccountGroup(int32_t osAccountId, GroupType type, const char *peerUserId, + QueryGroupParams *queryParams, GroupEntryVec *vec) +{ + LOGI("Try to get account group info, groupType: %d.", type); + queryParams->groupType = type; + if (QueryGroups(osAccountId, queryParams, vec) != HC_SUCCESS) { + LOGD("Database don't have local device's across-account group info!"); + return; + } + + uint32_t index = 0; + TrustedGroupEntry **ptr = NULL; + while (index < vec->size(vec)) { + ptr = vec->getp(vec, index); + if ((ptr == NULL) || (*ptr == NULL)) { + index++; + continue; + } + if ((peerUserId == NULL) || IsPeerInAccountRelatedGroup(*ptr, peerUserId)) { + index++; + continue; + } + TrustedGroupEntry *tempEntry = NULL; + HC_VECTOR_POPELEMENT(vec, &tempEntry, index); + DestroyGroupEntry((TrustedGroupEntry *)tempEntry); + } + LOGI("The candidate account group size is:%d.", vec->size(vec)); +} + +static void GetAccountCandidateGroup(int32_t osAccountId, const CJson *param, + QueryGroupParams *queryParams, GroupEntryVec *vec) +{ + /* Compare userId with local uid in DB. */ + bool identicalFlag = false; + bool acrossAccountFlag = false; + const char *peerUserId = GetStringFromJson(param, FIELD_USER_ID); + if (peerUserId != NULL) { + acrossAccountFlag = true; + identicalFlag = IsPeerInIdenticalGroup(osAccountId, peerUserId); + } else { + LOGD("userId is null in authParam."); + identicalFlag = true; + } + + if (identicalFlag) { + GaGetAccountGroup(osAccountId, IDENTICAL_ACCOUNT_GROUP, peerUserId, queryParams, vec); + } else if (acrossAccountFlag) { + GaGetAccountGroup(osAccountId, ACROSS_ACCOUNT_AUTHORIZE_GROUP, peerUserId, queryParams, vec); + } +} + +static int32_t FillAccountAuthInfo(int32_t osAccountId, const TrustedGroupEntry *entry, + const TrustedDeviceEntry *localAuthInfo, CJson *paramsData) +{ + (void)osAccountId; + const char *selfUserId = StringGet(&entry->userId); + const char *selfDeviceId = StringGet(&(localAuthInfo->udid)); + const char *selfDevId = StringGet(&(localAuthInfo->authId)); + if (selfUserId == NULL || selfDeviceId == NULL || selfDevId == NULL) { + LOGE("Failed to get self account info for client in account-related auth!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(paramsData, FIELD_SELF_USER_ID, selfUserId) != HC_SUCCESS) { + LOGE("Failed to add self userId for client in account-related auth!"); + return HC_ERR_JSON_FAIL; + } + if (AddStringToJson(paramsData, FIELD_SELF_DEVICE_ID, selfDeviceId) != HC_SUCCESS) { + LOGE("Failed to add self deviceId for client in account-related auth!"); + return HC_ERR_JSON_FAIL; + } + if (AddStringToJson(paramsData, FIELD_SELF_DEV_ID, selfDevId) != HC_SUCCESS) { + LOGE("Failed to add self devId for client in account-related auth!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static void OnAccountError(int64_t requestId, const AuthSession *session, int errorCode) +{ + AuthSession *realSession = (AuthSession *)session; + const DeviceAuthCallback *callback = session->base.callback; + ParamsVec list = realSession->paramsList; + CJson *authParam = list.get(&list, realSession->currentIndex); + if (authParam == NULL) { + LOGE("The json data in session is null!"); + return; + } + int32_t authForm = AUTH_FORM_INVALID_TYPE; + if (GetIntFromJson(authParam, FIELD_AUTH_FORM, &authForm) != HC_SUCCESS) { + LOGE("Failed to get auth type!"); + return; + } + + /* If there is alternative group, do not return error. */ + const char *altGroup = GetStringFromJson(authParam, FIELD_ALTERNATIVE); + if ((realSession->currentIndex < (list.size(&list) - 1)) || (altGroup != NULL)) { + LOGI("There are alternative groups."); + return; + } + if ((callback != NULL) && (callback->onError != NULL)) { + LOGE("Invoke OnAccountError!"); + callback->onError(requestId, authForm, errorCode, NULL); + } +} + +static int32_t GetAccountReqParams(const CJson *receiveData, CJson *reqParam) +{ + const char *peerUserId = GetStringFromJson(receiveData, FIELD_USER_ID); + if (peerUserId == NULL) { + LOGE("Failed to get peer uid for server!"); + return HC_ERR_JSON_GET; + } + + if (AddStringToJson(reqParam, FIELD_USER_ID, peerUserId) != HC_SUCCESS) { + LOGE("Failed to add peer uid!"); + return HC_ERR_JSON_FAIL; + } + const char *peerDeviceId = GetStringFromJson(receiveData, FIELD_DEVICE_ID); + if (peerDeviceId == NULL) { + LOGE("Failed to get deviceId from the data transmitted by the client!"); + return HC_ERR_JSON_GET; + } + if (AddStringToJson(reqParam, FIELD_DEVICE_ID, peerDeviceId) != HC_SUCCESS) { + LOGE("Failed to add reqParam: deviceId for onRequest!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddSelfUserIdForServer(int32_t osAccountId, GroupEntryVec *accountVec, CJson *data) +{ + const char *peerUserId = GetStringFromJson(data, FIELD_USER_ID); + if (peerUserId == NULL) { + LOGE("Failed to get peerUserId."); + return HC_ERR_JSON_GET; + } + int32_t authForm = AUTH_FORM_INVALID_TYPE; + if (GetIntFromJson(data, FIELD_AUTH_FORM, &authForm) != HC_SUCCESS) { + LOGE("Failed to get auth form for server!"); + return HC_ERR_JSON_GET; + } + int32_t groupType = AuthFormToGroupType(authForm); + if (groupType == GROUP_TYPE_INVALID) { + LOGE("Invalid authForm, authForm = %d.", authForm); + return HC_ERR_INVALID_PARAMS; + } + QueryGroupParams queryParams = InitQueryGroupParams(); + queryParams.groupType = groupType; + queryParams.userId = peerUserId; + int32_t res = QueryGroups(osAccountId, &queryParams, accountVec); + if ((res != HC_SUCCESS) || (accountVec->size(accountVec) == 0)) { + LOGE("Database don't have local device's account group info for server!"); + return res; + } + TrustedGroupEntry *groupEntry = accountVec->get(accountVec, 0); + if (groupEntry == NULL) { + LOGE("Group info is null."); + return HC_ERR_GROUP_NOT_EXIST; + } + const char *selfUserId = StringGet(&groupEntry->userId); + if (AddStringToJson(data, FIELD_SELF_USER_ID, selfUserId) != HC_SUCCESS) { + LOGE("Failed to add self userId for server in account-related auth!"); + return HC_ERR_JSON_FAIL; + } + return HC_SUCCESS; +} + +static int32_t AddSelfDevIdForServer(int32_t osAccountId, GroupEntryVec *accountVec, CJson *data) +{ + TrustedDeviceEntry *localDevInfo = CreateDeviceEntry(); + if (localDevInfo == NULL) { + LOGE("Failed to allocate memory for localDevInfo for server!"); + return HC_ERR_ALLOC_MEMORY; + } + TrustedGroupEntry *groupEntry = accountVec->get(accountVec, 0); + int32_t res; + do { + const char *groupId = StringGet(&groupEntry->id); + if (groupId == NULL) { + LOGE("Failed to get groupId for server!"); + res = HC_ERR_NULL_PTR; + break; + } + res = GaGetLocalDeviceInfo(osAccountId, groupId, localDevInfo); + const char *selfDevId = StringGet(&(localDevInfo->authId)); + if (AddStringToJson(data, FIELD_SELF_DEV_ID, selfDevId) != HC_SUCCESS) { + LOGE("Failed to add self devId for server in account-related auth!"); + res = HC_ERR_JSON_FAIL; + } + } while (0); + DestroyDeviceEntry(localDevInfo); + return res; +} + +static int32_t AddSelfAccountInfoForServer(CJson *data) +{ + int32_t osAccountId = INVALID_OS_ACCOUNT; + if (GetIntFromJson(data, FIELD_OS_ACCOUNT_ID, &osAccountId) != HC_SUCCESS) { + LOGE("Failed to get osAccountId for server!"); + return HC_ERR_JSON_GET; + } + GroupEntryVec accountVec = CreateGroupEntryVec(); + int32_t res = AddSelfUserIdForServer(osAccountId, &accountVec, data); + if (res != HC_SUCCESS) { + LOGE("Failed to add self userId for server auth!"); + ClearGroupEntryVec(&accountVec); + return res; + } + res = AddSelfDevIdForServer(osAccountId, &accountVec, data); + ClearGroupEntryVec(&accountVec); + return res; +} + +static int32_t CombineAccountServerConfirms(const CJson *confirmationJson, CJson *dataFromClient) +{ + bool isClient = false; + if (AddBoolToJson(dataFromClient, FIELD_IS_CLIENT, isClient) != HC_SUCCESS) { + LOGE("Failed to combine server param for isClient!"); + return HC_ERR_JSON_FAIL; + } + if (AddSelfAccountInfoForServer(dataFromClient) != HC_SUCCESS) { + LOGE("Failed to add account info for server!"); + return HC_ERR_GROUP_NOT_EXIST; + } + const char *peerUdid = GetStringFromJson(confirmationJson, FIELD_PEER_CONN_DEVICE_ID); + if (peerUdid != NULL) { + if (AddStringToJson(dataFromClient, FIELD_PEER_CONN_DEVICE_ID, peerUdid) != HC_SUCCESS) { + LOGE("Failed to combine server param for peerUdid!"); + return HC_ERR_JSON_FAIL; + } + } + + const char *tempChallenge = GetStringFromJson(confirmationJson, FIELD_BLE_CHALLENGE); + if (tempChallenge != NULL) { + if (AddStringToJson(dataFromClient, FIELD_BLE_CHALLENGE, tempChallenge) != HC_SUCCESS) { + LOGE("Failed to combine server param for tempChallenge!"); + return HC_ERR_JSON_FAIL; + } + } + return HC_SUCCESS; +} + +static int32_t GetAccountAuthParamForServer(const CJson *dataFromClient, ParamsVec *authParamsVec) +{ + LOGI("Begin get account-related auth params for server."); + const char *peerUserId = GetStringFromJson(dataFromClient, FIELD_USER_ID); + if (peerUserId == NULL) { + LOGE("Failed to get peer userId in client's payload!"); + return HC_ERR_JSON_GET; + } + char *localUdid = (char *)HcMalloc(INPUT_UDID_LEN, 0); + if (localUdid == NULL) { + LOGE("Failed to malloc for local udid!"); + return HC_ERR_ALLOC_MEMORY; + } + int32_t res = HcGetUdid((uint8_t *)localUdid, INPUT_UDID_LEN); + if (res != HC_SUCCESS) { + LOGE("[Account-related auth]: Failed to get self udid for server!"); + HcFree(localUdid); + return res; + } + + CJson *dupData = DuplicateJson(dataFromClient); + if (dupData == NULL) { + LOGE("Failed to create dupData for dataFromClient!"); + HcFree(localUdid); + return HC_ERR_JSON_FAIL; + } + if (AddStringToJson(dupData, FIELD_SELF_DEVICE_ID, localUdid) != HC_SUCCESS) { + LOGE("Failed to add self udid for server in account-related auth!"); + FreeJson(dupData); + HcFree(localUdid); + return HC_ERR_JSON_FAIL; + } + if (AddStringToJson(dupData, FIELD_GROUP_ID, peerUserId) != HC_SUCCESS) { + LOGE("Failed to add groupId for server in account-related auth!"); + FreeJson(dupData); + HcFree(localUdid); + return HC_ERR_JSON_FAIL; + } + HcFree(localUdid); + if (authParamsVec->pushBack(authParamsVec, (const void **)&dupData) == NULL) { + LOGE("Failed to push json data to vector in account-related auth!"); + FreeJson(dupData); + return HC_ERR_ALLOC_MEMORY; + } + return HC_SUCCESS; +} + +static int32_t AccountOnFinishToPeer(int64_t requestId, const CJson *out, const DeviceAuthCallback *callback) +{ + int32_t res = HC_SUCCESS; + const CJson *sendToPeer = GetObjFromJson(out, FIELD_SEND_TO_PEER); + if (sendToPeer == NULL) { + LOGI("No need to transmit data to peer for account-related auth."); + return res; + } + char *sendToPeerStr = PackJsonToString(sendToPeer); + if (sendToPeerStr == NULL) { + LOGE("Failed to pack sendToPeerStr!"); + return HC_ERR_ALLOC_MEMORY; + } + if ((callback != NULL) && (callback->onTransmit != NULL)) { + LOGD("Begin to transmit data to peer for auth in AccountOnFinishToPeer."); + if (!callback->onTransmit(requestId, (uint8_t *)sendToPeerStr, HcStrlen(sendToPeerStr) + 1)) { + LOGE("Failed to transmit data to peer!"); + res = HC_ERR_TRANSMIT_FAIL; + } + LOGD("End to transmit data to peer for auth in AccountOnFinishToPeer."); + } + FreeJsonString(sendToPeerStr); + return res; +} + +static int32_t PrepareTrustedDeviceInfo(int32_t osAccountId, const CJson *authParam, + const CJson *out, TrustedDeviceEntry *devEntry) +{ + const CJson *sendToSelf = GetObjFromJson(out, FIELD_SEND_TO_SELF); + if (sendToSelf == NULL) { + LOGE("Failed to get sendToSelf data for account!"); + return HC_ERR_JSON_GET; + } + const char *peerUdid = GetStringFromJson(authParam, FIELD_PEER_CONN_DEVICE_ID); + if (peerUdid == NULL) { + LOGE("Failed to get peer udid for account!"); + return HC_ERR_JSON_GET; + } + const char *peerAuthId = GetStringFromJson(sendToSelf, FIELD_DEV_ID); + if (peerAuthId == NULL) { + LOGE("Failed to get peer authId for account!"); + return HC_ERR_JSON_GET; + } + const char *groupId = GetStringFromJson(authParam, FIELD_GROUP_ID); + if (groupId == NULL) { + LOGE("Failed to get groupId from auth params when adding device info!"); + return HC_ERR_JSON_GET; + } + const char *peerUserId = GetStringFromJson(sendToSelf, FIELD_USER_ID); + if (peerUserId == NULL) { + LOGE("Failed to get peer userId!"); + return HC_ERR_JSON_GET; + } + if (!StringSetPointer(&(devEntry->userId), peerUserId) || + !StringSetPointer(&(devEntry->udid), peerUdid) || + !StringSetPointer(&(devEntry->authId), peerAuthId) || + !StringSetPointer(&(devEntry->groupId), groupId) || + !StringSetPointer(&(devEntry->serviceType), groupId)) { + LOGE("Failed to add device info when adding a trusted device!"); + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +static int32_t DeleteExistedDeviceInfoInDb(int32_t osAccountId, const CJson *authParam) +{ + const char *peerUdid = GetStringFromJson(authParam, FIELD_PEER_CONN_DEVICE_ID); + if (peerUdid == NULL) { + LOGE("Failed to get peer udid!"); + return HC_ERR_JSON_GET; + } + const char *groupId = GetStringFromJson(authParam, FIELD_GROUP_ID); + if (groupId == NULL) { + LOGE("Failed to get groupId from auth params when deleting device info!"); + return HC_ERR_JSON_GET; + } + QueryDeviceParams devParams = InitQueryDeviceParams(); + devParams.groupId = groupId; + devParams.udid = peerUdid; + int32_t result = DelTrustedDevice(osAccountId, &devParams); + if (result != HC_SUCCESS) { + LOGE("Failed to delete peer device from database!"); + return result; + } + return HC_SUCCESS; +} + +static int32_t AddTrustedDeviceForAccount(const CJson *authParam, const CJson *out) +{ + int32_t osAccountId = ANY_OS_ACCOUNT; + if (GetIntFromJson(authParam, FIELD_OS_ACCOUNT_ID, &osAccountId) != HC_SUCCESS) { + LOGE("Failed to get osAccountId for account!"); + return HC_ERR_JSON_GET; + } + int32_t res = DeleteExistedDeviceInfoInDb(osAccountId, authParam); + if (res != HC_SUCCESS) { + LOGE("Failed to delete the existed account device in db!"); + return res; + } + TrustedDeviceEntry *devEntry = CreateDeviceEntry(); + if (devEntry == NULL) { + LOGE("Failed to allocate device entry memory!"); + return HC_ERR_ALLOC_MEMORY; + } + do { + res = PrepareTrustedDeviceInfo(osAccountId, authParam, out, devEntry); + if (res != HC_SUCCESS) { + LOGE("Failed to prepare trust device params!"); + break; + } + res = AddTrustedDevice(osAccountId, devEntry); + if (res != HC_SUCCESS) { + LOGE("Failed to add trusted devices for account to database!"); + break; + } + } while (0); + DestroyDeviceEntry(devEntry); + return res; +} + +static int32_t PrepareAccountDataToSelf(const CJson *sendToSelf, CJson *returnToSelf) +{ + int32_t res = GetSessionKeyForAccount(sendToSelf, returnToSelf); + if (res != HC_SUCCESS) { + LOGE("Failed to get session key info for account auth!"); + return res; + } + res = GetUserIdForAccount(sendToSelf, returnToSelf); + if (res != HC_SUCCESS) { + LOGE("Failed to get user id for account auth!"); + } + return res; +} + +static int32_t AccountOnFinishToSelf(int64_t requestId, const CJson *authParam, const CJson *out, + const DeviceAuthCallback *callback) +{ + const CJson *sendToSelf = GetObjFromJson(out, FIELD_SEND_TO_SELF); + if (sendToSelf == NULL) { + LOGE("No data to send to self for onFinish."); + return HC_ERR_LOST_DATA; + } + + CJson *returnToSelf = CreateJson(); + if (returnToSelf == NULL) { + LOGE("Failed to create json for account-related auth in onFinish!"); + return HC_ERR_ALLOC_MEMORY; + } + int32_t res = PrepareAccountDataToSelf(sendToSelf, returnToSelf); + if (res != HC_SUCCESS) { + LOGE("Failed to add account-related returnToSelf data!"); + ClearSensitiveStringInJson(returnToSelf, FIELD_SESSION_KEY); + FreeJson(returnToSelf); + return res; + } + char *returnStr = PackJsonToString(returnToSelf); + ClearSensitiveStringInJson(returnToSelf, FIELD_SESSION_KEY); + FreeJson(returnToSelf); + if (returnStr == NULL) { + LOGE("Failed to pack return data to string!"); + return HC_ERR_ALLOC_MEMORY; + } + do { + int32_t authForm = AUTH_FORM_INVALID_TYPE; + if (GetIntFromJson(authParam, FIELD_AUTH_FORM, &authForm) != HC_SUCCESS) { + LOGE("Failed to get auth type!"); + res = HC_ERR_JSON_GET; + break; + } + if ((callback != NULL) && (callback->onFinish != NULL)) { + LOGD("Group auth call onFinish for account related auth."); + callback->onFinish(requestId, authForm, returnStr); + } + } while (0); + ClearAndFreeJsonString(returnStr); + return res; +} + +static void OnAccountFinish(int64_t requestId, const CJson *authParam, const CJson *out, + const DeviceAuthCallback *callback) +{ + LOGI("Begin call onFinish for account-related auth."); + if (AccountOnFinishToPeer(requestId, out, callback) != HC_SUCCESS) { + LOGE("Failed to send data to peer when account-related auth finished!"); + return; + } + if (ReturnSessionKey(requestId, authParam, out, callback) != HC_SUCCESS) { + LOGE("Failed to return session key for account-related auth!"); + return; + } + if (AddTrustedDeviceForAccount(authParam, out) != HC_SUCCESS) { + LOGD("Failed to add peer trusted devices to database for account-related auth!"); + } + if (AccountOnFinishToSelf(requestId, authParam, out, callback) != HC_SUCCESS) { + LOGE("Failed to send data to self when account-related auth finished!"); + return; + } + LOGI("Call onFinish for account-related auth successfully."); +} + +BaseGroupAuth *GetAccountRelatedGroupAuth(void) +{ + return (BaseGroupAuth *)&g_accountRelatedGroupAuth; +} \ No newline at end of file diff --git a/services/group_auth/src/group_auth_manager/group_auth_data_operation.c b/services/group_auth/src/group_auth_manager/group_auth_data_operation.c index f45e83e..139eeed 100644 --- a/services/group_auth/src/group_auth_manager/group_auth_data_operation.c +++ b/services/group_auth/src/group_auth_manager/group_auth_data_operation.c @@ -18,8 +18,10 @@ #include "common_defs.h" #include "device_auth.h" #include "device_auth_defines.h" +#include "hc_dev_info.h" #include "hc_log.h" #include "hc_string.h" +#include "hc_types.h" #include "hc_vector.h" static bool GaDeepCopyDeviceEntry(const TrustedDeviceEntry *entry, TrustedDeviceEntry *returnEntry) @@ -41,8 +43,8 @@ static bool GaDeepCopyDeviceEntry(const TrustedDeviceEntry *entry, TrustedDevice LOGE("[GA]: Failed to copy serviceType!"); return false; } - if (!StringSet(&returnEntry->userIdHash, entry->userIdHash)) { - LOGE("[GA]: Failed to copy userIdHash!"); + if (!StringSet(&returnEntry->userId, entry->userId)) { + LOGE("[GA]: Failed to copy userId!"); return false; } returnEntry->credential = entry->credential; @@ -66,8 +68,8 @@ static bool GaDeepCopyGroupEntry(const TrustedGroupEntry *entry, TrustedGroupEnt LOGE("[GA]: Failed to copy groupId!"); return false; } - if (!StringSet(&returnEntry->userIdHash, entry->userIdHash)) { - LOGE("[GA]: Failed to copy userIdHash!"); + if (!StringSet(&returnEntry->userId, entry->userId)) { + LOGE("[GA]: Failed to copy userId!"); return false; } returnEntry->type = entry->type; @@ -235,4 +237,25 @@ bool GaIsDeviceInGroup(int32_t groupType, int32_t osAccountId, const char *peerU return false; } return true; +} + +int32_t GaGetLocalDeviceInfo(int32_t osAccountId, const char *groupId, TrustedDeviceEntry *localAuthInfo) +{ + char *localUdid = (char *)HcMalloc(INPUT_UDID_LEN, 0); + if (localUdid == NULL) { + LOGE("Failed to malloc for local udid!"); + return HC_ERR_ALLOC_MEMORY; + } + int32_t res = HcGetUdid((uint8_t *)localUdid, INPUT_UDID_LEN); + if (res != HC_SUCCESS) { + LOGE("Failed to get local udid!"); + HcFree(localUdid); + return res; + } + res = GaGetTrustedDeviceEntryById(osAccountId, localUdid, true, groupId, localAuthInfo); + HcFree(localUdid); + if (res != HC_SUCCESS) { + LOGE("Failed to get local device info from database!"); + } + return res; } \ No newline at end of file diff --git a/services/group_auth/src/session/auth_session/auth_session_common.c b/services/group_auth/src/session/auth_session/auth_session_common.c index 8ddf8ea..de6ec65 100644 --- a/services/group_auth/src/session/auth_session/auth_session_common.c +++ b/services/group_auth/src/session/auth_session/auth_session_common.c @@ -119,29 +119,6 @@ static int32_t AddGeneralParams(const char *groupId, int32_t groupType, const Tr return HC_SUCCESS; } -static int32_t GetLocalDeviceInfoFromDatabase(int32_t osAccountId, const char *groupId, - TrustedDeviceEntry *localAuthInfo) -{ - char *localUdid = (char *)HcMalloc(INPUT_UDID_LEN, 0); - if (localUdid == NULL) { - LOGE("Failed to malloc for local udid!"); - return HC_ERR_ALLOC_MEMORY; - } - int32_t res = HcGetUdid((uint8_t *)localUdid, INPUT_UDID_LEN); - if (res != HC_SUCCESS) { - LOGE("[DB]: Failed to get local udid! res: %d", res); - HcFree(localUdid); - return res; - } - - res = GaGetTrustedDeviceEntryById(osAccountId, localUdid, true, groupId, localAuthInfo); - HcFree(localUdid); - if (res != HC_SUCCESS) { - LOGE("Failed to get local device info from database!"); - } - return res; -} - static int32_t ExtractAndAddParams(int32_t osAccountId, const char *groupId, const TrustedGroupEntry *groupInfo, CJson *paramsData) { @@ -154,7 +131,7 @@ static int32_t ExtractAndAddParams(int32_t osAccountId, const char *groupId, int32_t groupType = groupInfo->type; int32_t authForm = GroupTypeToAuthForm(groupType); do { - res = GetLocalDeviceInfoFromDatabase(osAccountId, groupId, localAuthInfo); + res = GaGetLocalDeviceInfo(osAccountId, groupId, localAuthInfo); if (res != HC_SUCCESS) { break; } @@ -227,7 +204,7 @@ static void GetCandidateGroupByOrder(int32_t osAccountId, const CJson *param, BaseGroupAuth *groupAuth = GetGroupAuth(ACCOUNT_RELATED_GROUP_AUTH_TYPE); if (groupAuth != NULL) { AccountRelatedGroupAuth *realGroupAuth = (AccountRelatedGroupAuth *)groupAuth; - realGroupAuth->getAccountCandidateGroup(param, queryParams, vec); + realGroupAuth->getAccountCandidateGroup(osAccountId, param, queryParams, vec); } queryParams->groupType = PEER_TO_PEER_GROUP; if (QueryGroups(osAccountId, queryParams, vec) != HC_SUCCESS) { @@ -767,14 +744,16 @@ int32_t ProcessTaskStatusForAuth(const AuthSession *session, const CJson *param, int32_t CreateAndProcessTask(AuthSession *session, CJson *paramInSession, CJson *out, int32_t *status) { int32_t moduleType = GetAuthModuleType(paramInSession); - const char *pkgName = GetStringFromJson(paramInSession, FIELD_SERVICE_PKG_NAME); - if (pkgName == NULL) { - LOGE("Pkg name is null!"); - return HC_ERR_NULL_PTR; - } - if (AddStringToJson(paramInSession, FIELD_PKG_NAME, pkgName) != HC_SUCCESS) { - LOGE("Failed to add pkg name to json!"); - return HC_ERR_JSON_FAIL; + if (moduleType == DAS_MODULE) { + const char *pkgName = GetStringFromJson(paramInSession, FIELD_SERVICE_PKG_NAME); + if (pkgName == NULL) { + LOGE("Pkg name is null!"); + return HC_ERR_NULL_PTR; + } + if (AddStringToJson(paramInSession, FIELD_PKG_NAME, pkgName) != HC_SUCCESS) { + LOGE("Failed to add pkg name to json!"); + return HC_ERR_JSON_FAIL; + } } session->curTaskId = 0; int32_t res = CreateTask(&(session->curTaskId), paramInSession, out, moduleType); diff --git a/services/group_auth/src/session/auth_session/auth_session_util.c b/services/group_auth/src/session/auth_session/auth_session_util.c index 30584b5..d9385f0 100644 --- a/services/group_auth/src/session/auth_session/auth_session_util.c +++ b/services/group_auth/src/session/auth_session/auth_session_util.c @@ -136,4 +136,25 @@ int32_t GroupTypeToAuthForm(int32_t groupType) break; } return authForm; +} + +int32_t AuthFormToGroupType(int32_t authForm) +{ + int32_t groupType; + switch (authForm) { + case AUTH_FORM_ACCOUNT_UNRELATED: + groupType = PEER_TO_PEER_GROUP; + break; + case AUTH_FORM_IDENTICAL_ACCOUNT: + groupType = IDENTICAL_ACCOUNT_GROUP; + break; + case AUTH_FORM_ACROSS_ACCOUNT: + groupType = ACROSS_ACCOUNT_AUTHORIZE_GROUP; + break; + default: + LOGE("Invalid auth form!"); + groupType = GROUP_TYPE_INVALID; + break; + } + return groupType; } \ No newline at end of file diff --git a/services/group_auth/src/session/auth_session_common_util.c b/services/group_auth/src/session/auth_session_common_util.c index 3fd5e86..058f6c8 100644 --- a/services/group_auth/src/session/auth_session_common_util.c +++ b/services/group_auth/src/session/auth_session_common_util.c @@ -19,13 +19,13 @@ #include "device_auth_defines.h" #include "hc_log.h" #include "hc_types.h" -#define UID_HASH_HEX_STRING_LEN_MAX 64 -#define UID_HASH_HEX_STRING_LEN_MIN 10 +#define UID_HEX_STRING_LEN_MAX 64 +#define UID_HEX_STRING_LEN_MIN 10 -static bool IsPeerUidHashLenValid(uint32_t peerUidHashLen) +static bool IsPeerUidLenValid(uint32_t peerUserIdLen) { - if ((peerUidHashLen < UID_HASH_HEX_STRING_LEN_MIN) || (peerUidHashLen > UID_HASH_HEX_STRING_LEN_MAX)) { - LOGE("The input uid hash len is invalid, input uid hash in hex string len = %d", peerUidHashLen); + if ((peerUserIdLen < UID_HEX_STRING_LEN_MIN) || (peerUserIdLen > UID_HEX_STRING_LEN_MAX)) { + LOGE("The input userId len is invalid, input userId in hex string len = %d", peerUserIdLen); return false; } return true; @@ -143,32 +143,31 @@ int32_t GetGeneralReqParams(const CJson *receiveData, CJson *reqParam) return HC_SUCCESS; } -bool IsUidHashEqual(const char *uidHashInDb, const char *peerUidHash) +bool IsUserIdEqual(const char *userIdInDb, const char *peerUserIdInDb) { - if ((uidHashInDb == NULL) || (peerUidHash == NULL)) { - LOGE("Input is null for uid hash!"); + if ((userIdInDb == NULL) || (peerUserIdInDb == NULL)) { + LOGE("Input is null for user id!"); return false; } - char *peerUidHashToUpper = NULL; - int32_t result = ToUpperCase(peerUidHash, &peerUidHashToUpper); - if (result != HC_SUCCESS) { - LOGE("Failed to convert the input uidHash to upper case!"); - return result; - } - uint32_t uidHashInDbLen = strlen(uidHashInDb); - uint32_t peerUidHashLen = strlen(peerUidHash); - if (!IsPeerUidHashLenValid(peerUidHashLen)) { - HcFree(peerUidHashToUpper); - peerUidHashToUpper = NULL; + char *peerUidToUpper = NULL; + if (ToUpperCase(peerUserIdInDb, &peerUidToUpper) != HC_SUCCESS) { + LOGE("Failed to convert the input userId to upper case!"); return false; } - uint32_t cmpHashLen = (uidHashInDbLen > peerUidHashLen) ? peerUidHashLen : uidHashInDbLen; - if (memcmp(uidHashInDb, peerUidHashToUpper, cmpHashLen) == EOK) { - HcFree(peerUidHashToUpper); - peerUidHashToUpper = NULL; + uint32_t userIdInDbLen = HcStrlen(userIdInDb); + uint32_t peerUserIdLen = HcStrlen(peerUserIdInDb); + if (!IsPeerUidLenValid(peerUserIdLen)) { + HcFree(peerUidToUpper); + peerUidToUpper = NULL; + return false; + } + uint32_t cmpLen = (userIdInDbLen > peerUserIdLen) ? peerUserIdLen : userIdInDbLen; + if (memcmp(userIdInDb, peerUidToUpper, cmpLen) == EOK) { + HcFree(peerUidToUpper); + peerUidToUpper = NULL; return true; } - HcFree(peerUidHashToUpper); - peerUidHashToUpper = NULL; + HcFree(peerUidToUpper); + peerUidToUpper = NULL; return false; } \ No newline at end of file diff --git a/services/group_manager/inc/across_account_group.h b/services/group_manager/inc/across_account_group.h index 893ff07..755d2f6 100644 --- a/services/group_manager/inc/across_account_group.h +++ b/services/group_manager/inc/across_account_group.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2021-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 @@ -24,9 +24,6 @@ extern "C" { typedef struct { BaseGroup base; - int32_t (*syncGroup)(const char *appId, const char *userIdHash, const char *deviceId, - const CJson *sharedUserIdHashList); - int32_t (*generateGroupId)(const char *userIdHash, const char *sharedUserIdHash, char **returnGroupId); } AcrossAccountGroup; bool IsAcrossAccountGroupSupported(void); diff --git a/services/group_manager/inc/group_manager.h b/services/group_manager/inc/group_manager.h index cd21b64..2977107 100644 --- a/services/group_manager/inc/group_manager.h +++ b/services/group_manager/inc/group_manager.h @@ -32,10 +32,6 @@ int32_t AddMemberToGroupImpl(int32_t osAccountId, int64_t requestId, const char int32_t DeleteMemberFromGroupImpl(int32_t osAccountId, int64_t requestId, const char *appId, const char *deleteParams); int32_t ProcessBindDataImpl(int64_t requestId, const uint8_t *data, uint32_t dataLen); int32_t ConfirmRequestImpl(int32_t osAccountId, int64_t requestId, const char *appId, const char *confirmParams); -int32_t GenerateAccountGroupIdImpl(int32_t groupType, const char *userIdHash, const char *sharedUserIdHash, - char **returnGroupId); -int32_t SyncAcrossAccountGroupImpl(const char *appId, const char *userIdHash, const char *deviceId, - const CJson *sharedUserIdHashList); int32_t AddGroupManagerImpl(int32_t osAccountId, const char *appId, const char *groupId, const char *managerAppId); int32_t AddGroupFriendImpl(int32_t osAccountId, const char *appId, const char *groupId, const char *friendAppId); int32_t DeleteGroupManagerImpl(int32_t osAccountId, const char *appId, const char *groupId, const char *managerAppId); diff --git a/services/group_manager/inc/group_operation.h b/services/group_manager/inc/group_operation.h index bc56027..b472f40 100644 --- a/services/group_manager/inc/group_operation.h +++ b/services/group_manager/inc/group_operation.h @@ -30,10 +30,6 @@ typedef struct { int32_t (*deleteMember)(int32_t osAccountId, int64_t requestId, const char *appId, const char *deleteParams); int32_t (*processBindData)(int64_t requestId, const uint8_t *data, uint32_t dataLen); int32_t (*confirmRequest)(int32_t osAccountId, int64_t requestId, const char *appId, const char *confirmParams); - int32_t (*generateAccountGroupId)(int32_t groupType, const char *userIdHash, const char *sharedUserIdHash, - char **returnGroupId); - int32_t (*syncAcrossAccountGroup)(const char *appId, const char *userIdHash, const char *deviceId, - const CJson *sharedUserIdHashList); int32_t (*addGroupRole)(int32_t osAccountId, bool isManager, const char *appId, const char *groupId, const char *roleAppId); int32_t (*deleteGroupRole)(int32_t osAccountId, bool isManager, const char *appId, const char *groupId, diff --git a/services/group_manager/inc/group_operation_common.h b/services/group_manager/inc/group_operation_common.h index dc60b75..206db25 100644 --- a/services/group_manager/inc/group_operation_common.h +++ b/services/group_manager/inc/group_operation_common.h @@ -35,7 +35,8 @@ bool IsGroupVisibilityValid(int groupVisibility); int32_t ProcessKeyPair(int action, const CJson *jsonParams, const char *groupId); int32_t GetHashMessage(const Uint8Buff *first, const Uint8Buff *second, uint8_t **hashMessage, uint32_t *messageSize); -int32_t AssertUserIdHashExist(const CJson *jsonParams); +int32_t AssertUserIdExist(const CJson *jsonParams); +int32_t AssertSharedUserIdExist(const CJson *jsonParams); int32_t CheckGroupExist(int32_t osAccountId, const char *groupId); int32_t CheckGroupNumLimit(int32_t osAccountId, int32_t groupType, const char *appId); int32_t CheckDeviceNumLimit(int32_t osAccountId, const char *groupId, const char *peerUdid); @@ -50,14 +51,15 @@ int32_t AddGroupOwnerToParams(const char *owner, TrustedGroupEntry *groupParams) int32_t AddGroupTypeToParams(int groupType, TrustedGroupEntry *groupParams); int32_t AddGroupVisibilityOrDefault(const CJson *jsonParams, TrustedGroupEntry *groupParams); int32_t AddExpireTimeOrDefault(const CJson *jsonParams, TrustedGroupEntry *groupParams); -int32_t AddUserIdHashToGroupParams(const CJson *jsonParams, TrustedGroupEntry *groupParams); +int32_t AddUserIdToGroupParams(const CJson *jsonParams, TrustedGroupEntry *groupParams); +int32_t AddSharedUserIdToGroupParams(const CJson *jsonParams, TrustedGroupEntry *groupParams); int32_t AddUdidToParams(TrustedDeviceEntry *devParams); int32_t AddAuthIdToParamsOrDefault(const CJson *jsonParams, TrustedDeviceEntry *devParams); int32_t AddUserTypeToParamsOrDefault(const CJson *jsonParams, TrustedDeviceEntry *devParams); int32_t AddServiceTypeToParams(const char *groupId, TrustedDeviceEntry *devParams); int32_t AddGroupIdToDevParams(const char *groupId, TrustedDeviceEntry *devParams); -int32_t AddUserIdHashToDevParams(const CJson *jsonParams, TrustedDeviceEntry *devParams); +int32_t AddUserIdToDevParams(const CJson *jsonParams, TrustedDeviceEntry *devParams); int32_t AddGroupToDatabaseByJson(int32_t osAccountId, int32_t (*generateGroupParams)(const CJson*, const char *, TrustedGroupEntry*), const CJson *jsonParams, const char *groupId); @@ -70,7 +72,8 @@ int32_t GenerateBindSuccessData(const char *peerAuthId, const char *groupId, cha int32_t GenerateUnbindSuccessData(const char *peerAuthId, const char *groupId, char **returnDataStr); int32_t GetGroupTypeFromDb(int32_t osAccountId, const char *groupId, int32_t *returnGroupType); -int32_t GetUserIdHashFromJson(const CJson *jsonParams, char **userIdHash); +int32_t GetUserIdFromJson(const CJson *jsonParams, char **userId); +int32_t GetSharedUserIdFromJson(const CJson *jsonParams, char **sharedUserId); int32_t GetGroupIdFromJson(const CJson *jsonParams, const char **groupId); int32_t GetAppIdFromJson(const CJson *jsonParams, const char **appId); diff --git a/services/group_manager/src/bind_peer/bind_peer.c b/services/group_manager/src/bind_peer/bind_peer.c index b573b88..26f1888 100644 --- a/services/group_manager/src/bind_peer/bind_peer.c +++ b/services/group_manager/src/bind_peer/bind_peer.c @@ -138,7 +138,8 @@ int32_t RequestBindPeer(int64_t requestId, const char *appId, const char *bindPa FreeJson(params); return HC_ERR_JSON_FAIL; } - if (InitAndPushGMTask(OP_BIND, requestId, params, DoClientTask) != HC_SUCCESS) { + int32_t osAccountId = ANY_OS_ACCOUNT; + if (InitAndPushGMTask(osAccountId, OP_BIND, requestId, params, DoClientTask) != HC_SUCCESS) { FreeJson(params); return HC_ERR_INIT_TASK_FAIL; } @@ -162,7 +163,8 @@ int32_t RequestUnbindPeer(int64_t requestId, const char *appId, const char *unbi FreeJson(params); return HC_ERR_JSON_FAIL; } - if (InitAndPushGMTask(OP_UNBIND, requestId, params, DoClientTask) != HC_SUCCESS) { + int32_t osAccountId = ANY_OS_ACCOUNT; + if (InitAndPushGMTask(osAccountId, OP_UNBIND, requestId, params, DoClientTask) != HC_SUCCESS) { FreeJson(params); return HC_ERR_INIT_TASK_FAIL; } @@ -186,7 +188,8 @@ int32_t RequestProcessLiteData(int64_t requestId, const char *appId, const uint8 FreeJson(params); return HC_ERR_JSON_FAIL; } - if (InitAndPushGMTask(GetOpCodeWhenLite(params), requestId, params, DoServerTask) != HC_SUCCESS) { + int32_t osAccountId = ANY_OS_ACCOUNT; + if (InitAndPushGMTask(osAccountId, GetOpCodeWhenLite(params), requestId, params, DoServerTask) != HC_SUCCESS) { FreeJson(params); return HC_ERR_INIT_TASK_FAIL; } diff --git a/services/group_manager/src/group_manager.c b/services/group_manager/src/group_manager.c index cba43c3..34c6634 100644 --- a/services/group_manager/src/group_manager.c +++ b/services/group_manager/src/group_manager.c @@ -56,20 +56,6 @@ int32_t ConfirmRequestImpl(int32_t osAccountId, int64_t requestId, const char *a confirmParams) : HC_ERR_NOT_SUPPORT; } -int32_t GenerateAccountGroupIdImpl(int32_t groupType, const char *userIdHash, const char *sharedUserIdHash, - char **returnGroupId) -{ - return IsGroupSupport() ? GetGroupImplInstance()->generateAccountGroupId(groupType, userIdHash, sharedUserIdHash, - returnGroupId) : HC_ERR_NOT_SUPPORT; -} - -int32_t SyncAcrossAccountGroupImpl(const char *appId, const char *userIdHash, const char *deviceId, - const CJson *sharedUserIdHashList) -{ - return IsGroupSupport() ? GetGroupImplInstance()->syncAcrossAccountGroup(appId, userIdHash, deviceId, - sharedUserIdHashList) : HC_ERR_NOT_SUPPORT; -} - int32_t AddGroupManagerImpl(int32_t osAccountId, const char *appId, const char *groupId, const char *managerAppId) { return IsGroupSupport() ? GetGroupImplInstance()->addGroupRole(osAccountId, true, appId, groupId, diff --git a/services/group_manager/src/group_operation/across_account_group/across_account_group.c b/services/group_manager/src/group_operation/across_account_group/across_account_group.c new file mode 100644 index 0000000..194b06e --- /dev/null +++ b/services/group_manager/src/group_operation/across_account_group/across_account_group.c @@ -0,0 +1,265 @@ +/* + * 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 "across_account_group.h" + +#include "alg_defs.h" +#include "callback_manager.h" +#include "common_defs.h" +#include "data_manager.h" +#include "device_auth_defines.h" +#include "group_operation_common.h" +#include "hc_log.h" +#include "string_util.h" + +/* 1: s1 > s2, -1: s1 <= s2 */ +static int32_t CompareString(const char *s1, const char *s2) +{ + if ((s1 == NULL) || (s2 == NULL)) { + LOGE("The input string contains NULL value!"); + return 0; + } + const char *tempChar1 = s1; + const char *tempChar2 = s2; + while ((*tempChar1 != '\0') && (*tempChar2 != '\0')) { + if (*tempChar1 > *tempChar2) { + return 1; + } else if (*tempChar1 < *tempChar2) { + return -1; + } + tempChar1++; + tempChar2++; + } + if (*tempChar1 != '\0') { + return 1; + } + return -1; +} + +static int32_t GenerateGroupId(const char *userId, const char *sharedUserId, char **returnGroupId) +{ + /* across account group: groupId = sha256(userId1 | userId2) */ + uint8_t *hashMessage = NULL; + uint32_t messageSize = 0; + const char *firstUserId = userId; + const char *secondUserId = sharedUserId; + if (CompareString(firstUserId, secondUserId) > 0) { + firstUserId = sharedUserId; + secondUserId = userId; + } + Uint8Buff firstUserIdBuff = { (uint8_t *)firstUserId, HcStrlen(firstUserId) }; + Uint8Buff secondUserIdBuff = { (uint8_t *)secondUserId, HcStrlen(secondUserId) }; + int32_t result = GetHashMessage(&firstUserIdBuff, &secondUserIdBuff, &hashMessage, &messageSize); + if (result != HC_SUCCESS) { + return result; + } + int hashStrLen = SHA256_LEN * BYTE_TO_HEX_OPER_LENGTH + 1; + *returnGroupId = (char *)HcMalloc(hashStrLen, 0); + if (*returnGroupId == NULL) { + LOGE("Failed to allocate returnGroupId memory!"); + HcFree(hashMessage); + return HC_ERR_ALLOC_MEMORY; + } + result = GetHashResult(hashMessage, messageSize, *returnGroupId, hashStrLen); + HcFree(hashMessage); + if (result != HC_SUCCESS) { + LOGE("Failed to get hash for groupId!"); + HcFree(*returnGroupId); + *returnGroupId = NULL; + return HC_ERR_HASH_FAIL; + } + return HC_SUCCESS; +} + +static int32_t GenerateDevParams(const CJson *jsonParams, const char *groupId, TrustedDeviceEntry *devParams) +{ + int32_t result; + if (((result = AddUdidToParams(devParams)) != HC_SUCCESS) || + ((result = AddAuthIdToParamsOrDefault(jsonParams, devParams)) != HC_SUCCESS) || + ((result = AddUserIdToDevParams(jsonParams, devParams)) != HC_SUCCESS) || + ((result = AddUserTypeToParamsOrDefault(jsonParams, devParams)) != HC_SUCCESS) || + ((result = AddGroupIdToDevParams(groupId, devParams)) != HC_SUCCESS) || + ((result = AddServiceTypeToParams(groupId, devParams)) != HC_SUCCESS)) { + return result; + } + return HC_SUCCESS; +} + +static int32_t GenerateGroupParams(const CJson *jsonParams, const char *groupId, TrustedGroupEntry *groupParams) +{ + const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID); + if (appId == NULL) { + LOGE("Failed to get appId from jsonParams!"); + return HC_ERR_JSON_GET; + } + int32_t result; + if (((result = AddGroupTypeToParams(ACROSS_ACCOUNT_AUTHORIZE_GROUP, groupParams)) != HC_SUCCESS) || + ((result = AddGroupNameToParams(groupId, groupParams)) != HC_SUCCESS) || + ((result = AddGroupIdToParams(groupId, groupParams)) != HC_SUCCESS) || + ((result = AddUserIdToGroupParams(jsonParams, groupParams)) != HC_SUCCESS) || + ((result = AddSharedUserIdToGroupParams(jsonParams, groupParams)) != HC_SUCCESS) || + ((result = AddGroupOwnerToParams(appId, groupParams)) != HC_SUCCESS) || + ((result = AddGroupVisibilityOrDefault(jsonParams, groupParams)) != HC_SUCCESS) || + ((result = AddExpireTimeOrDefault(jsonParams, groupParams)) != HC_SUCCESS)) { + return result; + } + return HC_SUCCESS; +} + +static int32_t GenerateAcrossAccountGroupId(const CJson *jsonParams, char **returnGroupId) +{ + char *userId = NULL; + char *sharedUserId = NULL; + int32_t result = GetUserIdFromJson(jsonParams, &userId); + if (result != HC_SUCCESS) { + return result; + } + result = GetSharedUserIdFromJson(jsonParams, &sharedUserId); + if (result != HC_SUCCESS) { + HcFree(userId); + return result; + } + result = GenerateGroupId(userId, sharedUserId, returnGroupId); + HcFree(userId); + HcFree(sharedUserId); + if (result != HC_SUCCESS) { + LOGE("Failed to generate groupId!"); + return result; + } + return HC_SUCCESS; +} + +static int32_t AssertIdenticalGroupExist(int32_t osAccountId, const CJson *jsonParams) +{ + char *userId = NULL; + int32_t result = GetUserIdFromJson(jsonParams, &userId); + if (result != HC_SUCCESS) { + return result; + } + GroupEntryVec groupEntryVec = CreateGroupEntryVec(); + QueryGroupParams params = InitQueryGroupParams(); + params.groupType = IDENTICAL_ACCOUNT_GROUP; + result = QueryGroups(osAccountId, ¶ms, &groupEntryVec); + if (result != HC_SUCCESS) { + LOGE("Failed to query groups!"); + HcFree(userId); + ClearGroupEntryVec(&groupEntryVec); + return result; + } + bool isExist = false; + uint32_t index; + TrustedGroupEntry **entry = NULL; + FOR_EACH_HC_VECTOR(groupEntryVec, index, entry) { + if ((entry != NULL) && (*entry != NULL) && (strcmp(userId, StringGet(&((*entry)->userId))) == 0)) { + isExist = true; + break; + } + } + HcFree(userId); + ClearGroupEntryVec(&groupEntryVec); + if (!isExist) { + LOGE("The identical account group has not been created!"); + return HC_ERR_GROUP_NOT_EXIST; + } + return HC_SUCCESS; +} + +static int32_t CheckCreateParams(int32_t osAccountId, const CJson *jsonParams) +{ + const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID); + if (appId == NULL) { + LOGE("Failed to get appId from jsonParams!"); + return HC_ERR_JSON_GET; + } + int32_t result; + if (((result = CheckUserTypeIfExist(jsonParams)) != HC_SUCCESS) || + ((result = CheckGroupVisibilityIfExist(jsonParams)) != HC_SUCCESS) || + ((result = CheckExpireTimeIfExist(jsonParams)) != HC_SUCCESS) || + ((result = AssertUserIdExist(jsonParams)) != HC_SUCCESS) || + ((result = AssertSharedUserIdExist(jsonParams)) != HC_SUCCESS) || + ((result = AssertIdenticalGroupExist(osAccountId, jsonParams)) != HC_SUCCESS)) { + return result; + } + return HC_SUCCESS; +} + +static int32_t CreateGroupInner(int32_t osAccountId, const CJson *jsonParams, char **returnGroupId) +{ + char *groupId = NULL; + int32_t result; + if (((result = CheckCreateParams(osAccountId, jsonParams)) != HC_SUCCESS) || + ((result = GenerateAcrossAccountGroupId(jsonParams, &groupId)) != HC_SUCCESS) || + ((result = AddGroupToDatabaseByJson(osAccountId, GenerateGroupParams, jsonParams, groupId)) != HC_SUCCESS) || + ((result = AddDeviceToDatabaseByJson(osAccountId, GenerateDevParams, jsonParams, groupId)) != HC_SUCCESS) || + ((result = SaveOsAccountDb(osAccountId)) != HC_SUCCESS)) { + HcFree(groupId); + return result; + } + *returnGroupId = groupId; + return HC_SUCCESS; +} + +static int32_t CreateGroup(int32_t osAccountId, CJson *jsonParams, char **returnJsonStr) +{ + LOGI("[Start]: Start to create a across account group!"); + if ((jsonParams == NULL) || (returnJsonStr == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + char *groupId = NULL; + int32_t result; + if (((result = CreateGroupInner(osAccountId, jsonParams, &groupId)) != HC_SUCCESS) || + ((result = ConvertGroupIdToJsonStr(groupId, returnJsonStr)) != HC_SUCCESS)) { + HcFree(groupId); + return result; + } + HcFree(groupId); + LOGI("[End]: Create a across account group successfully!"); + return HC_SUCCESS; +} + +static int32_t DeleteGroup(int32_t osAccountId, CJson *jsonParams, char **returnJsonStr) +{ + LOGI("[Start]: Start to delete a across account group!"); + if ((jsonParams == NULL) || (returnJsonStr == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + int32_t result; + const char *groupId = NULL; + if (((result = GetGroupIdFromJson(jsonParams, &groupId)) != HC_SUCCESS) || + ((result = DelGroupFromDb(osAccountId, groupId)) != HC_SUCCESS) || + ((result = ConvertGroupIdToJsonStr(groupId, returnJsonStr)) != HC_SUCCESS)) { + return result; + } + LOGI("[End]: Delete a across account group successfully!"); + return HC_SUCCESS; +} + +static AcrossAccountGroup g_acrossAccountGroup = { + .base.type = ACROSS_ACCOUNT_AUTHORIZE_GROUP, + .base.createGroup = CreateGroup, + .base.deleteGroup = DeleteGroup, +}; + +BaseGroup *GetAcrossAccountGroupInstance(void) +{ + return (BaseGroup *)&g_acrossAccountGroup; +} + +bool IsAcrossAccountGroupSupported(void) +{ + return true; +} diff --git a/services/group_manager/src/group_operation/group_operation.c b/services/group_manager/src/group_operation/group_operation.c index ae63472..ad64d81 100644 --- a/services/group_manager/src/group_operation/group_operation.c +++ b/services/group_manager/src/group_operation/group_operation.c @@ -484,48 +484,6 @@ static int32_t ProcessBindData(int64_t requestId, CJson *jsonParams, const Devic return instance->processData(requestId, jsonParams, callback); } -static int32_t GenerateAccountGroupId(int32_t groupType, const char *userIdHash, const char *sharedUserIdHash, - char **returnGroupId) -{ - if ((!IsAccountRelatedGroup(groupType)) || (!IsGroupTypeSupported(groupType))) { - LOGE("This type of group is not supported!"); - return HC_ERR_INVALID_PARAMS; - } - if (groupType == IDENTICAL_ACCOUNT_GROUP) { - IdenticalAccountGroup *instance = (IdenticalAccountGroup *)GetIdenticalAccountGroupInstance(); - if ((instance == NULL) || (instance->generateGroupId == NULL)) { - LOGE("The group instance is NULL or its function ptr is NULL!"); - return HC_ERR_NULL_PTR; - } - return instance->generateGroupId(userIdHash, returnGroupId); - } - AcrossAccountGroup *instance = (AcrossAccountGroup *)GetAcrossAccountGroupInstance(); - if ((instance == NULL) || (instance->generateGroupId == NULL)) { - LOGE("The group instance is NULL or its function ptr is NULL!"); - return HC_ERR_NULL_PTR; - } - return instance->generateGroupId(userIdHash, sharedUserIdHash, returnGroupId); -} - -static int32_t SyncAcrossAccountGroup(const char *appId, const char *userIdHash, const char *deviceId, - const CJson *sharedUserIdHashList) -{ - if ((appId == NULL) || (deviceId == NULL) || (userIdHash == NULL) || (sharedUserIdHashList == NULL)) { - LOGE("The input parameters contains NULL value!"); - return HC_ERR_INVALID_PARAMS; - } - if (!IsAcrossAccountGroupSupported()) { - LOGE("Across account group is not supported!"); - return HC_ERR_NOT_SUPPORT; - } - AcrossAccountGroup *instance = (AcrossAccountGroup *)GetAcrossAccountGroupInstance(); - if ((instance == NULL) || (instance->syncGroup == NULL)) { - LOGE("The group instance is NULL or its function ptr is NULL!"); - return HC_ERR_NULL_PTR; - } - return instance->syncGroup(appId, userIdHash, deviceId, sharedUserIdHashList); -} - static int32_t AddGroupRoleWithCheck(int32_t osAccuntId, bool isManager, const char *appId, const char *groupId, const char *roleAppId) { @@ -1172,8 +1130,6 @@ static const GroupImpl g_groupImplInstance = { .deleteMember = RequestDeleteMemberFromGroup, .processBindData = RequestProcessBindData, .confirmRequest = RequestConfirmRequest, - .generateAccountGroupId = GenerateAccountGroupId, - .syncAcrossAccountGroup = SyncAcrossAccountGroup, .addGroupRole = AddGroupRoleWithCheck, .deleteGroupRole = DeleteGroupRoleWithCheck, .getGroupRoles = GetGroupRolesWithCheck, diff --git a/services/group_manager/src/group_operation/group_operation_common.c b/services/group_manager/src/group_operation/group_operation_common.c index 53721c5..3796e9c 100644 --- a/services/group_manager/src/group_operation/group_operation_common.c +++ b/services/group_manager/src/group_operation/group_operation_common.c @@ -671,19 +671,35 @@ int32_t AddExpireTimeOrDefault(const CJson *jsonParams, TrustedGroupEntry *group return HC_SUCCESS; } -int32_t AddUserIdHashToGroupParams(const CJson *jsonParams, TrustedGroupEntry *groupParams) +int32_t AddUserIdToGroupParams(const CJson *jsonParams, TrustedGroupEntry *groupParams) { - char *userIdHash = NULL; - int32_t result = GetUserIdHashFromJson(jsonParams, &userIdHash); + char *userId = NULL; + int32_t result = GetUserIdFromJson(jsonParams, &userId); if (result != HC_SUCCESS) { return result; } - if (!StringSetPointer(&groupParams->userIdHash, userIdHash)) { - LOGE("Failed to copy userIdHash!"); - HcFree(userIdHash); + if (!StringSetPointer(&groupParams->userId, userId)) { + LOGE("Failed to copy userId!"); + HcFree(userId); return HC_ERR_MEMORY_COPY; } - HcFree(userIdHash); + HcFree(userId); + return HC_SUCCESS; +} + +int32_t AddSharedUserIdToGroupParams(const CJson *jsonParams, TrustedGroupEntry *groupParams) +{ + char *sharedUserId = NULL; + int32_t result = GetSharedUserIdFromJson(jsonParams, &sharedUserId); + if (result != HC_SUCCESS) { + return result; + } + if (!StringSetPointer(&groupParams->sharedUserId, sharedUserId)) { + LOGE("Failed to copy sharedUserId!"); + HcFree(sharedUserId); + return HC_ERR_MEMORY_COPY; + } + HcFree(sharedUserId); return HC_SUCCESS; } @@ -748,27 +764,37 @@ int32_t AddGroupIdToDevParams(const char *groupId, TrustedDeviceEntry *devParams return HC_SUCCESS; } -int32_t AddUserIdHashToDevParams(const CJson *jsonParams, TrustedDeviceEntry *devParams) +int32_t AddUserIdToDevParams(const CJson *jsonParams, TrustedDeviceEntry *devParams) { - char *userIdHash = NULL; - int32_t result = GetUserIdHashFromJson(jsonParams, &userIdHash); + char *userId = NULL; + int32_t result = GetUserIdFromJson(jsonParams, &userId); if (result != HC_SUCCESS) { return result; } - if (!StringSetPointer(&devParams->userIdHash, userIdHash)) { - LOGE("Failed to copy userIdHash!"); - HcFree(userIdHash); + if (!StringSetPointer(&devParams->userId, userId)) { + LOGE("Failed to copy userId!"); + HcFree(userId); return HC_ERR_MEMORY_COPY; } - HcFree(userIdHash); + HcFree(userId); return HC_SUCCESS; } -int32_t AssertUserIdHashExist(const CJson *jsonParams) +int32_t AssertUserIdExist(const CJson *jsonParams) { - const char *userIdHash = GetStringFromJson(jsonParams, FIELD_USER_ID); - if (userIdHash == NULL) { - LOGE("Failed to get userIdHash from jsonParams!"); + const char *userId = GetStringFromJson(jsonParams, FIELD_USER_ID); + if (userId == NULL) { + LOGE("Failed to get userId from jsonParams!"); + return HC_ERR_JSON_GET; + } + return HC_SUCCESS; +} + +int32_t AssertSharedUserIdExist(const CJson *jsonParams) +{ + const char *sharedUserId = GetStringFromJson(jsonParams, FIELD_PEER_USER_ID); + if (sharedUserId == NULL) { + LOGE("Failed to get sharedUserId from jsonParams!"); return HC_ERR_JSON_GET; } return HC_SUCCESS; @@ -1034,18 +1060,32 @@ int32_t GetGroupTypeFromDb(int32_t osAccountId, const char *groupId, int32_t *re return HC_SUCCESS; } -int32_t GetUserIdHashFromJson(const CJson *jsonParams, char **userIdHash) +int32_t GetUserIdFromJson(const CJson *jsonParams, char **userId) { - if ((jsonParams == NULL) || (userIdHash == NULL)) { + if ((jsonParams == NULL) || (userId == NULL)) { LOGE("The input parameters contains NULL value!"); return HC_ERR_INVALID_PARAMS; } - const char *oriUserIdHash = GetStringFromJson(jsonParams, FIELD_USER_ID); - if (oriUserIdHash == NULL) { - LOGE("Failed to get userIdHash from jsonParams!"); + const char *oriUserId = GetStringFromJson(jsonParams, FIELD_USER_ID); + if (oriUserId == NULL) { + LOGE("Failed to get userId from jsonParams!"); return HC_ERR_JSON_GET; } - return ToUpperCase(oriUserIdHash, userIdHash); + return ToUpperCase(oriUserId, userId); +} + +int32_t GetSharedUserIdFromJson(const CJson *jsonParams, char **sharedUserId) +{ + if ((jsonParams == NULL) || (sharedUserId == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + const char *oriUserId = GetStringFromJson(jsonParams, FIELD_PEER_USER_ID); + if (oriUserId == NULL) { + LOGE("Failed to get sharedUserId from jsonParams!"); + return HC_ERR_JSON_GET; + } + return ToUpperCase(oriUserId, sharedUserId); } int32_t GetGroupIdFromJson(const CJson *jsonParams, const char **groupId) diff --git a/services/group_manager/src/group_operation/identical_account_group/identical_account_group.c b/services/group_manager/src/group_operation/identical_account_group/identical_account_group.c new file mode 100644 index 0000000..4d89032 --- /dev/null +++ b/services/group_manager/src/group_operation/identical_account_group/identical_account_group.c @@ -0,0 +1,347 @@ +/* + * 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 "identical_account_group.h" +#include "alg_defs.h" +#include "callback_manager.h" +#include "common_defs.h" +#include "data_manager.h" +#include "device_auth_defines.h" +#include "group_operation_common.h" +#include "hc_log.h" +#include "string_util.h" +#include "account_module.h" + +static int32_t GenerateDevParams(const CJson *jsonParams, const char *groupId, TrustedDeviceEntry *devParams) +{ + int32_t result; + if (((result = AddUdidToParams(devParams)) != HC_SUCCESS) || + ((result = AddUserIdToDevParams(jsonParams, devParams)) != HC_SUCCESS) || + ((result = AddAuthIdToParamsOrDefault(jsonParams, devParams)) != HC_SUCCESS) || + ((result = AddUserTypeToParamsOrDefault(jsonParams, devParams)) != HC_SUCCESS) || + ((result = AddGroupIdToDevParams(groupId, devParams)) != HC_SUCCESS) || + ((result = AddServiceTypeToParams(groupId, devParams)) != HC_SUCCESS)) { + return result; + } + return HC_SUCCESS; +} + +static int32_t GenerateGroupParams(const CJson *jsonParams, const char *groupId, TrustedGroupEntry *groupParams) +{ + const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID); + if (appId == NULL) { + LOGE("Failed to get appId from jsonParams!"); + return HC_ERR_JSON_GET; + } + int32_t result; + if (((result = AddGroupTypeToParams(IDENTICAL_ACCOUNT_GROUP, groupParams)) != HC_SUCCESS) || + ((result = AddGroupNameToParams(groupId, groupParams)) != HC_SUCCESS) || + ((result = AddGroupIdToParams(groupId, groupParams)) != HC_SUCCESS) || + ((result = AddUserIdToGroupParams(jsonParams, groupParams)) != HC_SUCCESS) || + ((result = AddGroupOwnerToParams(appId, groupParams)) != HC_SUCCESS) || + ((result = AddGroupVisibilityOrDefault(jsonParams, groupParams)) != HC_SUCCESS) || + ((result = AddExpireTimeOrDefault(jsonParams, groupParams)) != HC_SUCCESS)) { + return result; + } + return HC_SUCCESS; +} + +static int32_t GenerateGroupId(const char *userId, char **returnGroupId) +{ + if ((userId == NULL) || (returnGroupId == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + /* identical account group: groupId = sha256(userId) */ + int hashStrLen = SHA256_LEN * BYTE_TO_HEX_OPER_LENGTH + 1; + *returnGroupId = (char *)HcMalloc(hashStrLen, 0); + if (*returnGroupId == NULL) { + LOGE("Failed to allocate returnGroupId memory!"); + return HC_ERR_ALLOC_MEMORY; + } + if (memcpy_s(*returnGroupId, hashStrLen, userId, HcStrlen(userId)) != EOK) { + LOGE("Failed to copy userId for groupId!"); + HcFree(*returnGroupId); + *returnGroupId = NULL; + return HC_ERR_MEMORY_COPY; + } + return HC_SUCCESS; +} + +static int32_t GenerateIdenticalGroupId(const CJson *jsonParams, char **returnGroupId) +{ + char *userId = NULL; + int32_t result = GetUserIdFromJson(jsonParams, &userId); + if (result != HC_SUCCESS) { + return result; + } + result = GenerateGroupId(userId, returnGroupId); + HcFree(userId); + if (result != HC_SUCCESS) { + LOGE("Failed to generate groupId!"); + return result; + } + return HC_SUCCESS; +} + +static int32_t AssertCredentialExist(const CJson *jsonParams) +{ + CJson *credJson = GetObjFromJson(jsonParams, FIELD_CREDENTIAL); + if (credJson == NULL) { + LOGE("Failed to get credJson!"); + return HC_ERR_JSON_GET; + } + int32_t credType; + int32_t ret = GetIntFromJson(credJson, FIELD_CREDENTIAL_TYPE, &credType); + if (ret != HC_SUCCESS) { + LOGE("Failed to get credential type"); + return ret; + } + const char *serverPk = GetStringFromJson(credJson, FIELD_SERVER_PK); + if (serverPk == NULL) { + LOGE("Failed to get serverPk"); + return HC_ERR_JSON_GET; + } + const char *pkInfoSignature = GetStringFromJson(credJson, FIELD_PK_INFO_SIGNATURE); + if (pkInfoSignature == NULL) { + LOGE("Failed to get pkInfoSignature"); + return HC_ERR_JSON_GET; + } + CJson *pkInfoJson = GetObjFromJson(credJson, FIELD_PK_INFO); + if (pkInfoJson == NULL) { + LOGE("Failed to get pkInfoJson"); + return HC_ERR_JSON_GET; + } + return HC_SUCCESS; +} + +static int32_t CheckCreateParams(int32_t osAccountId, const CJson *jsonParams) +{ + const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID); + if (appId == NULL) { + LOGE("Failed to get appId from jsonParams!"); + return HC_ERR_JSON_GET; + } + int32_t result; + if (((result = AssertUserIdExist(jsonParams)) != HC_SUCCESS) || + ((result = AssertCredentialExist(jsonParams)) != HC_SUCCESS) || + ((result = CheckUserTypeIfExist(jsonParams)) != HC_SUCCESS) || + ((result = CheckGroupVisibilityIfExist(jsonParams)) != HC_SUCCESS) || + ((result = CheckExpireTimeIfExist(jsonParams)) != HC_SUCCESS) || + ((result = CheckGroupNumLimit(osAccountId, IDENTICAL_ACCOUNT_GROUP, appId)) != HC_SUCCESS)) { + return result; + } + return HC_SUCCESS; +} + +static int32_t DeleteGroupById(int32_t osAccountId, const char *groupId) +{ + QueryGroupParams queryGroupParams = InitQueryGroupParams(); + queryGroupParams.groupId = groupId; + return DelGroup(osAccountId, &queryGroupParams); +} + +static int32_t DeleteDeviceById(int32_t osAccountId, const char *groupId) +{ + QueryDeviceParams queryDeviceParams = InitQueryDeviceParams(); + queryDeviceParams.groupId = groupId; + return DelTrustedDevice(osAccountId, &queryDeviceParams); +} + +static int32_t CreateIdenticalGroup(int32_t osAccountId, const CJson *jsonParams, char *groupId) +{ + int32_t result = AddGroupToDatabaseByJson(osAccountId, GenerateGroupParams, jsonParams, groupId); + if (result != HC_SUCCESS) { + LOGE("Add group to database failed"); + return result; + } + result = ProcessAccountCredentials(osAccountId, IMPORT_SELF_CREDENTIAL, jsonParams, NULL); + if (result != HC_SUCCESS) { + LOGE("Import credential failed"); + DeleteGroupById(osAccountId, groupId); + return result; + } + result = AddDeviceToDatabaseByJson(osAccountId, GenerateDevParams, jsonParams, groupId); + if (result != HC_SUCCESS) { + LOGE("Add device to database failed"); + DeleteGroupById(osAccountId, groupId); + ProcessAccountCredentials(osAccountId, DELETE_SELF_CREDENTIAL, jsonParams, NULL); + return result; + } + result = SaveOsAccountDb(osAccountId); + if (result != HC_SUCCESS) { + LOGE("Save data to db file failed"); + DeleteGroupById(osAccountId, groupId); + ProcessAccountCredentials(osAccountId, DELETE_SELF_CREDENTIAL, jsonParams, NULL); + DeleteDeviceById(osAccountId, groupId); + } + return result; +} + +static int32_t CreateGroupInner(int32_t osAccountId, const CJson *jsonParams, char **returnGroupId) +{ + char *groupId = NULL; + int32_t result; + if (((result = CheckCreateParams(osAccountId, jsonParams)) != HC_SUCCESS) || + ((result = GenerateIdenticalGroupId(jsonParams, &groupId)) != HC_SUCCESS)) { + LOGE("Check create params or generate groupId failed"); + return result; + } + if (IsGroupExistByGroupId(osAccountId, groupId)) { + LOGE("Group already exists, do not create it again"); + HcFree(groupId); + return HC_ERR_GROUP_DUPLICATE; + } + result = CreateIdenticalGroup(osAccountId, jsonParams, groupId); + if (result != HC_SUCCESS) { + HcFree(groupId); + return result; + } + *returnGroupId = groupId; + return HC_SUCCESS; +} + +static int32_t CreateGroup(int32_t osAccountId, CJson *jsonParams, char **returnJsonStr) +{ + LOGI("[Start]: Start to create a identical account group!"); + if ((jsonParams == NULL) || (returnJsonStr == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + int32_t result; + char *groupId = NULL; + if (((result = CreateGroupInner(osAccountId, jsonParams, &groupId)) != HC_SUCCESS) || + ((result = ConvertGroupIdToJsonStr(groupId, returnJsonStr)) != HC_SUCCESS)) { + HcFree(groupId); + LOGE("Create identical group failed, result:%d", result); + return result; + } + HcFree(groupId); + LOGI("[End]: Create a identical account group successfully!"); + return HC_SUCCESS; +} + +static int32_t DeleteAcrossAccountGroup(int32_t osAccountId, const char *identicalGroupId) +{ + TrustedGroupEntry *groupInfo = CreateGroupEntry(); + if (groupInfo == NULL) { + LOGE("Failed to allocate groupInfo memory!"); + return HC_ERR_ALLOC_MEMORY; + } + int32_t ret = GetGroupInfoById(osAccountId, identicalGroupId, groupInfo); + if (ret != HC_SUCCESS) { + LOGE("Failed to obtain the group information from the database!"); + DestroyGroupEntry(groupInfo); + return ret; + } + const char *userId = StringGet(&groupInfo->userId); + DestroyGroupEntry(groupInfo); + GroupEntryVec groupEntryVec = CreateGroupEntryVec(); + QueryGroupParams groupParams = InitQueryGroupParams(); + groupParams.userId = userId; + groupParams.groupType = ACROSS_ACCOUNT_AUTHORIZE_GROUP; + ret = QueryGroups(osAccountId, &groupParams, &groupEntryVec); + if (ret != HC_SUCCESS) { + LOGE("query across account groups failed!"); + ClearGroupEntryVec(&groupEntryVec); + return ret; + } + uint32_t groupIndex; + TrustedGroupEntry **entry = NULL; + FOR_EACH_HC_VECTOR(groupEntryVec, groupIndex, entry) { + if ((entry != NULL) && (*entry != NULL)) { + if (DeleteDeviceById(osAccountId, StringGet(&(*entry)->id)) != HC_SUCCESS) { + LOGE("Delete across account device failed"); + ret = HC_ERR_DEL_GROUP; + } + if (DeleteGroupById(osAccountId, StringGet(&(*entry)->id)) != HC_SUCCESS) { + LOGE("Delete across account group failed"); + ret = HC_ERR_DEL_GROUP; + } + } + } + ClearGroupEntryVec(&groupEntryVec); + return ret; +} + +static int32_t DeleteGroupInner(int32_t osAccountId, const char *groupId, CJson *jsonParams) +{ + int32_t ret = DeleteAcrossAccountGroup(osAccountId, groupId); + if ((ret != HC_SUCCESS) && (ret != HC_ERR_DEL_GROUP)) { + return ret; + } + if (DeleteDeviceById(osAccountId, groupId) != HC_SUCCESS) { + LOGE("Delete identical account device failed"); + ret = HC_ERR_DEL_GROUP; + } + if (DeleteGroupById(osAccountId, groupId) != HC_SUCCESS) { + LOGE("Delete identical account group failed"); + ret = HC_ERR_DEL_GROUP; + } + if (SaveOsAccountDb(osAccountId) != HC_SUCCESS) { + LOGE("Save data to db file failed"); + ret = HC_ERR_DEL_GROUP; + } + if ((AddStringToJson(jsonParams, FIELD_USER_ID, groupId) != HC_SUCCESS) || + (ProcessAccountCredentials(osAccountId, DELETE_SELF_CREDENTIAL, jsonParams, NULL) != HC_SUCCESS)) { + LOGE("Delete credential failed"); + ret = HC_ERR_DEL_GROUP; + } + return ret; +} + +static int32_t DeleteGroup(int32_t osAccountId, CJson *jsonParams, char **returnJsonStr) +{ + LOGI("[Start]: Start to delete the identical account group!"); + if ((jsonParams == NULL) || (returnJsonStr == NULL)) { + LOGE("The input parameters contains NULL value!"); + return HC_ERR_INVALID_PARAMS; + } + const char *groupId = NULL; + int32_t ret = GetGroupIdFromJson(jsonParams, &groupId); + if (ret != HC_SUCCESS) { + LOGE("Failed to get groupId"); + return ret; + } + ret = DeleteGroupInner(osAccountId, groupId, jsonParams); + if (ret != HC_SUCCESS) { + LOGE("Delete group inner failed"); + return ret; + } + ret = ConvertGroupIdToJsonStr(groupId, returnJsonStr); + if (ret != HC_SUCCESS) { + LOGE("Failed to convert groupId to json"); + return ret; + } + LOGI("[End]: Delete the identical account group successfully!"); + return HC_SUCCESS; +} + +static IdenticalAccountGroup g_identicalAccountGroup = { + .base.type = IDENTICAL_ACCOUNT_GROUP, + .base.createGroup = CreateGroup, + .base.deleteGroup = DeleteGroup, + .generateGroupId = GenerateGroupId +}; + +BaseGroup *GetIdenticalAccountGroupInstance(void) +{ + return (BaseGroup *)&g_identicalAccountGroup; +} + +bool IsIdenticalAccountGroupSupported(void) +{ + return true; +} \ No newline at end of file diff --git a/services/group_manager/src/group_operation/peer_to_peer_group_mock/peer_to_peer_group_mock.c b/services/group_manager/src/group_operation/peer_to_peer_group_mock/peer_to_peer_group_mock.c index c203048..ef3dc1f 100644 --- a/services/group_manager/src/group_operation/peer_to_peer_group_mock/peer_to_peer_group_mock.c +++ b/services/group_manager/src/group_operation/peer_to_peer_group_mock/peer_to_peer_group_mock.c @@ -24,5 +24,5 @@ BaseGroup *GetPeerToPeerGroupInstance(void) bool IsPeerToPeerGroupSupported(void) { - return true; + return false; } diff --git a/services/group_manager/src/key_agree/key_agree.c b/services/group_manager/src/key_agree/key_agree.c index 5748313..10563e6 100644 --- a/services/group_manager/src/key_agree/key_agree.c +++ b/services/group_manager/src/key_agree/key_agree.c @@ -108,7 +108,8 @@ int32_t RequestAuthKeyAgree(int64_t requestId, const char *appId, const char *ag FreeJson(params); return HC_ERR_JSON_FAIL; } - if (InitAndPushGMTask(AUTH_KEY_AGREEMENT, requestId, params, DoClientTask) != HC_SUCCESS) { + int32_t osAccountId = ANY_OS_ACCOUNT; + if (InitAndPushGMTask(osAccountId, AUTH_KEY_AGREEMENT, requestId, params, DoClientTask) != HC_SUCCESS) { FreeJson(params); return HC_ERR_INIT_TASK_FAIL; } @@ -132,7 +133,8 @@ int32_t RequestProcessKeyAgreeData(int64_t requestId, const char *appId, const u FreeJson(params); return HC_ERR_JSON_FAIL; } - if (InitAndPushGMTask(AUTH_KEY_AGREEMENT, requestId, params, DoServerTask) != HC_SUCCESS) { + int32_t osAccountId = ANY_OS_ACCOUNT; + if (InitAndPushGMTask(osAccountId, AUTH_KEY_AGREEMENT, requestId, params, DoServerTask) != HC_SUCCESS) { FreeJson(params); return HC_ERR_INIT_TASK_FAIL; } diff --git a/services/protocol/src/pake_protocol/pake_protocol_dl_common/pake_protocol_dl_common.c b/services/protocol/src/pake_protocol/pake_protocol_dl_common/pake_protocol_dl_common.c index f422550..3ff61ac 100644 --- a/services/protocol/src/pake_protocol/pake_protocol_dl_common/pake_protocol_dl_common.c +++ b/services/protocol/src/pake_protocol/pake_protocol_dl_common/pake_protocol_dl_common.c @@ -94,7 +94,7 @@ static int FillDlKeysLenAccordingToMod(PakeBaseParams *params) static int32_t InitDlPakeParams(PakeBaseParams *params) { - int res; + int32_t res; if (params->isClient) { res = FillDlKeysLenAccordingToEpkPeer(params); } else { diff --git a/services/protocol/src/pake_protocol/pake_protocol_ec_common/pake_protocol_ec_common.c b/services/protocol/src/pake_protocol/pake_protocol_ec_common/pake_protocol_ec_common.c index 52853cd..77a8519 100644 --- a/services/protocol/src/pake_protocol/pake_protocol_ec_common/pake_protocol_ec_common.c +++ b/services/protocol/src/pake_protocol/pake_protocol_ec_common/pake_protocol_ec_common.c @@ -33,9 +33,8 @@ static int32_t GenerateEsk(PakeBaseParams *params) { int32_t res; if (params->curveType == CURVE_256) { - LOGE("CURVE_256 is not supported."); - return HC_ERR_NOT_SUPPORT; - } else { // CURVE_25519 + return params->loader->generateRandom(&(params->eskSelf)); + } else if (params->curveType == CURVE_25519) { res = params->loader->generateRandom(&(params->eskSelf)); if (res != HC_SUCCESS) { LOGE("CURVE_25519: GenerateRandom for eskSelf failed, res: %x.", res); @@ -44,8 +43,11 @@ static int32_t GenerateEsk(PakeBaseParams *params) params->eskSelf.val[PAKE_EC_KEY_LEN - 1] &= PAKE_PRIVATE_KEY_AND_MASK_HIGH; params->eskSelf.val[0] &= PAKE_PRIVATE_KEY_AND_MASK_LOW; params->eskSelf.val[0] |= PAKE_PRIVATE_KEY_OR_MASK_LOW; + return HC_SUCCESS; + } else { + LOGE("Unsupported curve: %d.", params->curveType); + return HC_ERR_UNSUPPORTED_CURVE; } - return res; } static int32_t InitEcPakeParams(PakeBaseParams *params) @@ -107,11 +109,6 @@ CLEAN_UP: int32_t AgreeEcSharedSecret(PakeBaseParams *params, Uint8Buff *sharedSecret) { - if (params->curveType == CURVE_256) { - LOGE("CURVE_256 is not supported."); - CleanPakeSensitiveKeys(params); - return HC_ERR_NOT_SUPPORT; - } int32_t res; /* P256 requires buffer for both X and Y coordinates. */ uint32_t validKeyBufferLen = (params->curveType == CURVE_256) ? (PAKE_EC_KEY_LEN * 2) : (PAKE_EC_KEY_LEN); @@ -122,6 +119,11 @@ int32_t AgreeEcSharedSecret(PakeBaseParams *params, Uint8Buff *sharedSecret) } Algorithm alg = (params->curveType == CURVE_256) ? P256 : X25519; + if (!params->loader->checkEcPublicKey(&(params->epkPeer), alg)) { + LOGE("Check public key failed."); + res = HC_ERR_INVALID_PUBLIC_KEY; + goto CLEAN_UP; + } KeyBuff eskSelfBuff = { params->eskSelf.val, params->eskSelf.length, false }; KeyBuff epkPeerBuff = { params->epkPeer.val, params->epkPeer.length, false }; res = params->loader->agreeSharedSecret(&eskSelfBuff, &epkPeerBuff, alg, sharedSecret); diff --git a/services/protocol/src/pake_protocol/pake_v2_protocol/pake_v2_protocol_common.c b/services/protocol/src/pake_protocol/pake_v2_protocol/pake_v2_protocol_common.c new file mode 100644 index 0000000..47b550f --- /dev/null +++ b/services/protocol/src/pake_protocol/pake_v2_protocol/pake_v2_protocol_common.c @@ -0,0 +1,662 @@ +/* + * Copyright (C) 2021 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 "pake_v2_protocol_common.h" +#include "alg_loader.h" +#include "device_auth_defines.h" +#include "hc_log.h" +#include "hc_types.h" +#include "pake_defs.h" +#include "pake_protocol_dl_common.h" +#include "pake_protocol_ec_common.h" +#include "protocol_common.h" +#include "string_util.h" + +#define KCF_CODE_LEN 1 +#define PAKE_SESSION_KEY_LEN 32 + +static const uint8_t g_kcfCodeClient[KCF_CODE_LEN] = { 0x04 }; +static const uint8_t g_kcfCodeServer[KCF_CODE_LEN] = { 0x03 }; + +void DestroyPakeV2BaseParams(PakeBaseParams *params) +{ + if (params == NULL) { + return; + } + + CleanPakeSensitiveKeys(params); + + HcFree(params->salt.val); + params->salt.val = NULL; + + HcFree(params->challengeSelf.val); + params->challengeSelf.val = NULL; + + HcFree(params->challengePeer.val); + params->challengePeer.val = NULL; + + HcFree(params->epkSelf.val); + params->epkSelf.val = NULL; + + HcFree(params->epkPeer.val); + params->epkPeer.val = NULL; + + HcFree(params->idSelf.val); + params->idSelf.val = NULL; + + HcFree(params->idPeer.val); + params->idPeer.val = NULL; + + HcFree(params->kcfData.val); + params->kcfData.val = NULL; + + HcFree(params->kcfDataPeer.val); + params->kcfDataPeer.val = NULL; +} + +static int32_t AllocDefaultParams(PakeBaseParams *params) +{ + params->salt.length = PAKE_SALT_LEN; + params->salt.val = (uint8_t *)HcMalloc(params->salt.length, 0); + if (params->salt.val == NULL) { + LOGE("Malloc for salt failed."); + return HC_ERR_ALLOC_MEMORY; + } + + params->sharedSecret.length = SHA256_LEN; + params->sharedSecret.val = (uint8_t *)HcMalloc(params->sharedSecret.length, 0); + if (params->sharedSecret.val == NULL) { + LOGE("Malloc for sharedSecret failed."); + return HC_ERR_ALLOC_MEMORY; + } + + params->sessionKey.length = PAKE_SESSION_KEY_LEN; + params->sessionKey.val = (uint8_t *)HcMalloc(params->sessionKey.length, 0); + if (params->sessionKey.val == NULL) { + LOGE("Malloc for sessionKey failed."); + return HC_ERR_ALLOC_MEMORY; + } + + params->kcfData.length = HMAC_LEN; + params->kcfData.val = (uint8_t *)HcMalloc(params->kcfData.length, 0); + if (params->kcfData.val == NULL) { + LOGE("Malloc for kcfData failed."); + return HC_ERR_ALLOC_MEMORY; + } + + params->kcfDataPeer.length = HMAC_LEN; + params->kcfDataPeer.val = (uint8_t *)HcMalloc(params->kcfDataPeer.length, 0); + if (params->kcfDataPeer.val == NULL) { + LOGE("Malloc for kcfDataPeer failed."); + return HC_ERR_ALLOC_MEMORY; + } + return HC_SUCCESS; +} + +static void FillDefaultValue(PakeBaseParams *params) +{ + params->psk.val = NULL; + params->psk.length = 0; + params->challengeSelf.val = NULL; + params->challengeSelf.length = 0; + params->challengePeer.val = NULL; + params->challengePeer.length = 0; + params->eskSelf.val = NULL; + params->eskSelf.length = 0; + params->epkSelf.val = NULL; + params->epkSelf.length = 0; + params->epkPeer.val = NULL; + params->epkPeer.length = 0; + params->base.val = NULL; + params->base.length = 0; + params->idSelf.val = NULL; + params->idSelf.length = 0; + params->idPeer.val = NULL; + params->idPeer.length = 0; + params->hmacKey.val = NULL; + params->hmacKey.length = 0; + params->supportedDlPrimeMod = DL_PRIME_MOD_NONE; + params->largePrimeNumHex = NULL; + params->innerKeyLen = 0; + params->supportedPakeAlg = PAKE_ALG_NONE; + params->curveType = CURVE_NONE; + params->isClient = true; +} + +int32_t InitPakeV2BaseParams(PakeBaseParams *params) +{ + if (params == NULL) { + LOGE("Params is null."); + return HC_ERR_NULL_PTR; + } + + int32_t res = AllocDefaultParams(params); + if (res != HC_SUCCESS) { + goto CLEAN_UP; + } + + FillDefaultValue(params); + + params->loader = GetLoaderInstance(); + if (params->loader == NULL) { + res = HC_ERROR; + goto CLEAN_UP; + } + + return HC_SUCCESS; +CLEAN_UP: + DestroyPakeV2BaseParams(params); + return res; +} + +static int32_t GeneratePakeParams(PakeBaseParams *params) +{ + int32_t res; + uint8_t secretVal[PAKE_SECRET_LEN] = { 0 }; + Uint8Buff secret = { secretVal, PAKE_SECRET_LEN }; + if (!params->isClient) { + res = params->loader->generateRandom(&(params->salt)); + if (res != HC_SUCCESS) { + LOGE("Generate salt failed, res: %x.", res); + goto CLEAN_UP; + } + } + + Uint8Buff keyInfo = { (uint8_t *)HICHAIN_SPEKE_BASE_INFO, HcStrlen(HICHAIN_SPEKE_BASE_INFO) }; + res = params->loader->computeHkdf(&(params->psk), &(params->salt), &keyInfo, &secret, false); + if (res != HC_SUCCESS) { + LOGE("Derive secret from psk failed, res: %x.", res); + goto CLEAN_UP; + } + FreeAndCleanKey(¶ms->psk); + + if (((uint32_t)params->supportedPakeAlg & PAKE_ALG_EC) != 0) { + res = GenerateEcPakeParams(params, &secret); + } else if (((uint32_t)params->supportedPakeAlg & PAKE_ALG_DL) != 0) { + res = GenerateDlPakeParams(params, &secret); + } else { + res = HC_ERR_INVALID_ALG; + } + if (res != HC_SUCCESS) { + LOGE("GeneratePakeParams failed, pakeAlgType: 0x%x, res: 0x%x.", params->supportedPakeAlg, res); + goto CLEAN_UP; + } + (void)memset_s(secret.val, secret.length, 0, secret.length); + return res; +CLEAN_UP: + (void)memset_s(secret.val, secret.length, 0, secret.length); + CleanPakeSensitiveKeys(params); + return res; +} + +static int32_t ComputeSidSelf(const PakeBaseParams *params, Uint8Buff *sidSelf) +{ + int res; + Uint8Buff idSelfMsg = { NULL, params->idSelf.length + params->innerKeyLen }; + idSelfMsg.val = (uint8_t *)HcMalloc(idSelfMsg.length, 0); + if (idSelfMsg.val == NULL) { + LOGE("Malloc for idSelfMsg failed."); + res = HC_ERR_ALLOC_MEMORY; + goto CLEAN_UP; + } + + if (memcpy_s(idSelfMsg.val, idSelfMsg.length, params->idSelf.val, params->idSelf.length) != EOK) { + LOGE("Memcpy for idSelf failed."); + res = HC_ERR_MEMORY_COPY; + goto CLEAN_UP; + } + if (memcpy_s(idSelfMsg.val + params->idSelf.length, idSelfMsg.length - params->idSelf.length, + params->epkSelf.val, params->innerKeyLen) != EOK) { // only need x-coordinate + LOGE("Memcpy for epkSelf failed."); + res = HC_ERR_MEMORY_COPY; + goto CLEAN_UP; + } + res = params->loader->sha256(&idSelfMsg, sidSelf); + if (res != HC_SUCCESS) { + LOGE("Sha256 for idSelfMsg failed, res: %x.", res); + goto CLEAN_UP; + } +CLEAN_UP: + HcFree(idSelfMsg.val); + return res; +} + +static int32_t ComputeSidPeer(const PakeBaseParams *params, Uint8Buff *sidPeer) +{ + int res; + Uint8Buff idPeerMsg = { NULL, params->idPeer.length + params->innerKeyLen }; + idPeerMsg.val = (uint8_t *)HcMalloc(idPeerMsg.length, 0); + if (idPeerMsg.val == NULL) { + LOGE("Malloc for idPeerMsg failed."); + res = HC_ERR_ALLOC_MEMORY; + goto CLEAN_UP; + } + + if (memcpy_s(idPeerMsg.val, idPeerMsg.length, params->idPeer.val, params->idPeer.length) != EOK) { + LOGE("Memcpy for idPeer failed."); + res = HC_ERR_MEMORY_COPY; + goto CLEAN_UP; + } + if (memcpy_s(idPeerMsg.val + params->idPeer.length, idPeerMsg.length - params->idPeer.length, + params->epkPeer.val, params->innerKeyLen) != EOK) { // only need x-coordinate + LOGE("Memcpy for epkPeer failed."); + res = HC_ERR_MEMORY_COPY; + goto CLEAN_UP; + } + res = params->loader->sha256(&idPeerMsg, sidPeer); + if (res != HC_SUCCESS) { + LOGE("Sha256 for idPeerMsg failed, res: %x.", res); + goto CLEAN_UP; + } +CLEAN_UP: + HcFree(idPeerMsg.val); + return res; +} + +static int32_t ComputeSid(const PakeBaseParams *params, Uint8Buff *sid) +{ + int32_t res = HC_SUCCESS; + Uint8Buff sidSelf = { NULL, SHA256_LEN }; + Uint8Buff sidPeer = { NULL, SHA256_LEN }; + + sidSelf.val = (uint8_t *)HcMalloc(sidSelf.length, 0); + if (sidSelf.val == NULL) { + LOGE("Malloc for sidSelf failed."); + res = HC_ERR_ALLOC_MEMORY; + goto CLEAN_UP; + } + sidPeer.val = (uint8_t *)HcMalloc(sidPeer.length, 0); + if (sidPeer.val == NULL) { + LOGE("Malloc for sidPeer failed."); + res = HC_ERR_ALLOC_MEMORY; + goto CLEAN_UP; + } + + res = ComputeSidSelf(params, &sidSelf); + if (res != HC_SUCCESS) { + LOGE("ComputeSidSelf failed, res: %x", res); + goto CLEAN_UP; + } + + res = ComputeSidPeer(params, &sidPeer); + if (res != HC_SUCCESS) { + LOGE("ComputeSidPeer failed, res: %x", res); + goto CLEAN_UP; + } + + Uint8Buff *maxId = NULL; + Uint8Buff *minId = NULL; + int result = params->loader->bigNumCompare(&sidSelf, &sidPeer); + if (result <= 0) { + maxId = &sidSelf; + minId = &sidPeer; + } else { + maxId = &sidPeer; + minId = &sidSelf; + } + + if (memcpy_s(sid->val, sid->length, maxId->val, maxId->length) != EOK) { + LOGE("Memcpy for maxId failed."); + res = HC_ERR_MEMORY_COPY; + goto CLEAN_UP; + } + if (memcpy_s(sid->val + maxId->length, sid->length - maxId->length, minId->val, minId->length) != EOK) { + LOGE("Memcpy for minId failed."); + res = HC_ERR_MEMORY_COPY; + goto CLEAN_UP; + } +CLEAN_UP: + HcFree(sidSelf.val); + HcFree(sidPeer.val); + return res; +} + +static int32_t ComputeSharedSecret(PakeBaseParams *params, const Uint8Buff *sid, const Uint8Buff *tmpSharedSecret) +{ + int32_t res; + Uint8Buff sharedSecretMsg = { NULL, 0 }; + sharedSecretMsg.length = sid->length + params->innerKeyLen + HcStrlen(SHARED_SECRET_DERIVED_FACTOR); + sharedSecretMsg.val = (uint8_t *)HcMalloc(sharedSecretMsg.length, 0); + if (sharedSecretMsg.val == NULL) { + LOGE("Malloc for sharedSecretMsg failed."); + return HC_ERR_ALLOC_MEMORY; + } + + int32_t usedLen = 0; + if (memcpy_s(sharedSecretMsg.val, sharedSecretMsg.length, sid->val, sid->length) != EOK) { + LOGE("Memcpy for sidHex failed."); + res = HC_ERR_MEMORY_COPY; + goto CLEAN_UP; + } + usedLen += sid->length; + if (memcpy_s(sharedSecretMsg.val + usedLen, sharedSecretMsg.length - usedLen, + tmpSharedSecret->val, params->innerKeyLen) != EOK) { // Only need x-coordinate + LOGE("Memcpy for tmpSharedSecret failed."); + res = HC_ERR_MEMORY_COPY; + goto CLEAN_UP; + } + usedLen += params->innerKeyLen; + if (memcpy_s(sharedSecretMsg.val + usedLen, sharedSecretMsg.length - usedLen, + SHARED_SECRET_DERIVED_FACTOR, HcStrlen(SHARED_SECRET_DERIVED_FACTOR)) != EOK) { + LOGE("Memcpy for sharedSecret derived factor failed."); + res = HC_ERR_MEMORY_COPY; + goto CLEAN_UP; + } + + res = params->loader->sha256(&sharedSecretMsg, ¶ms->sharedSecret); + if (res != HC_SUCCESS) { + LOGE("Sha256 for sharedSecretMsg failed, res: %x.", res); + goto CLEAN_UP; + } +CLEAN_UP: + FreeAndCleanKey(&sharedSecretMsg); + return res; +} + +/* + * '|' means joint + * Z = epkB . eskA + * A = hash(idA | epkA_X) + * B = hash(idB | epkB_X) + * sid = MAX(A, B) | MIN(A, B) + * sharedSecret = hash(hex(sid) | Z_X | derivedFactor) + */ +static int32_t GenerateSharedSecret(PakeBaseParams *params) +{ + int32_t res; + Uint8Buff tmpSharedSecret = { NULL, 0 }; + Uint8Buff sid = { NULL, SHA256_LEN * 2 }; // sid is composed of client sid and server sid, so need twice SHA256_LEN + /* The key of P256 requires both X and Y coordinates values to represent it. */ + tmpSharedSecret.length = (params->curveType == CURVE_256) ? (params->innerKeyLen * 2) : (params->innerKeyLen); + tmpSharedSecret.val = (uint8_t *)HcMalloc(tmpSharedSecret.length, 0); + if (tmpSharedSecret.val == NULL) { + LOGE("Malloc for tmpSharedSecret failed."); + res = HC_ERR_ALLOC_MEMORY; + goto CLEAN_UP; + } + if (((uint32_t)params->supportedPakeAlg & PAKE_ALG_EC) != 0) { + res = AgreeEcSharedSecret(params, &tmpSharedSecret); + } else if (((uint32_t)params->supportedPakeAlg & PAKE_ALG_DL) != 0) { + res = AgreeDlSharedSecret(params, &tmpSharedSecret); + } else { + res = HC_ERR_INVALID_ALG; + } + if (res != HC_SUCCESS) { + LOGE("Agree intermediate sharedSecret failed, pakeAlgType: 0x%x, res: %x.", params->supportedPakeAlg, res); + goto CLEAN_UP; + } + FreeAndCleanKey(¶ms->eskSelf); + sid.val = (uint8_t *)HcMalloc(sid.length, 0); + if (sid.val == NULL) { + LOGE("Malloc for sid failed."); + res = HC_ERR_ALLOC_MEMORY; + goto CLEAN_UP; + } + res = ComputeSid(params, &sid); + if (res != HC_SUCCESS) { + LOGE("Compute sid failed, res: %x.", res); + goto CLEAN_UP; + } + res = ComputeSharedSecret(params, &sid, &tmpSharedSecret); + if (res != HC_SUCCESS) { + LOGE("ComputeSharedSecret failed, res: %x.", res); + goto CLEAN_UP; + } + goto OUT; +CLEAN_UP: + CleanPakeSensitiveKeys(params); +OUT: + FreeAndCleanKey(&sid); + FreeAndCleanKey(&tmpSharedSecret); + return res; +} + +static int32_t CombineEpk(const Uint8Buff *epkClient, const Uint8Buff *epkServer, uint32_t epkLenX, + Uint8Buff *proofMsg, uint32_t *usedLen) +{ + if (memcpy_s(proofMsg->val + *usedLen, proofMsg->length - *usedLen, + epkClient->val, epkLenX) != EOK) { // Only the x-coordinate of epk is required + LOGE("Memcpy for epkClient failed."); + return HC_ERR_MEMORY_COPY; + } + *usedLen += epkLenX; + if (memcpy_s(proofMsg->val + *usedLen, proofMsg->length - *usedLen, + epkServer->val, epkLenX) != EOK) { // Only the x-coordinate of epk is required + LOGE("Memcpy for epkServer failed."); + return HC_ERR_MEMORY_COPY; + } + *usedLen += epkLenX; + return HC_SUCCESS; +} + +static int32_t CombineProofMsg(const PakeBaseParams *params, Uint8Buff *proofMsg, bool isVerify) +{ + int32_t res; + uint32_t usedLen = 0; + const uint8_t *kcfCode = NULL; + + if ((params->isClient && !isVerify) || (!params->isClient && isVerify)) { + kcfCode = g_kcfCodeClient; + } else { + kcfCode = g_kcfCodeServer; + } + if (memcpy_s(proofMsg->val, proofMsg->length, kcfCode, KCF_CODE_LEN) != HC_SUCCESS) { + LOGE("Memcpy for g_kcfCode failed."); + return HC_ERR_MEMORY_COPY; + } + usedLen += KCF_CODE_LEN; + if (params->isClient) { + res = CombineEpk(¶ms->epkSelf, ¶ms->epkPeer, params->innerKeyLen, proofMsg, &usedLen); + } else { + res = CombineEpk(¶ms->epkPeer, ¶ms->epkSelf, params->innerKeyLen, proofMsg, &usedLen); + } + if (res != HC_SUCCESS) { + LOGE("CombineEpk failed, res: %x.", res); + return res; + } + if (memcpy_s(proofMsg->val + usedLen, proofMsg->length - usedLen, + params->sharedSecret.val, params->sharedSecret.length) != EOK) { + LOGE("Memcpy for sharedSecret failed."); + return HC_ERR_MEMORY_COPY; + } + usedLen += params->sharedSecret.length; + /* base only need x-coordinate */ + if (memcpy_s(proofMsg->val + usedLen, proofMsg->length - usedLen, params->base.val, params->innerKeyLen) != EOK) { + LOGE("Memcpy for base failed."); + return HC_ERR_MEMORY_COPY; + } + return res; +} + +/* + * msg = challenge_self + challenge_peer + * kcfdata = SHA256(byte(code), PK_CLIENT_X, PK_SERVER_X, sharedSecret, base_X) + */ +static int32_t GenerateProof(PakeBaseParams *params) +{ + int res; + Uint8Buff proofMsg = { NULL, 0 }; + proofMsg.length = KCF_CODE_LEN + params->innerKeyLen + params->innerKeyLen + + params->sharedSecret.length + params->innerKeyLen; + proofMsg.val = (uint8_t *)HcMalloc(proofMsg.length, 0); + if (proofMsg.val == NULL) { + LOGE("Malloc for proofMsg failed."); + res = HC_ERR_ALLOC_MEMORY; + goto CLEAN_UP; + } + res = CombineProofMsg(params, &proofMsg, false); + if (res != HC_SUCCESS) { + LOGE("CombineProofMsg failed, res: %x.", res); + goto CLEAN_UP; + } + res = params->loader->sha256(&proofMsg, ¶ms->kcfData); + if (res != HC_SUCCESS) { + LOGE("Sha256 for proofMsg failed, res: %x.", res); + goto CLEAN_UP; + } + goto OUT; +CLEAN_UP: + CleanPakeSensitiveKeys(params); +OUT: + FreeAndCleanKey(&proofMsg); + return res; +} + +static int32_t VerifyProof(PakeBaseParams *params) +{ + int res; + Uint8Buff proofMsg = { NULL, 0 }; + proofMsg.length = KCF_CODE_LEN + params->innerKeyLen + params->innerKeyLen + + params->sharedSecret.length + params->innerKeyLen; + proofMsg.val = (uint8_t *)HcMalloc(proofMsg.length, 0); + if (proofMsg.val == NULL) { + LOGE("Malloc for proofMsg failed."); + res = HC_ERR_ALLOC_MEMORY; + goto CLEAN_UP; + } + res = CombineProofMsg(params, &proofMsg, true); + if (res != HC_SUCCESS) { + LOGE("CombineProofMsg failed, res: %x.", res); + goto CLEAN_UP; + } + + uint8_t tmpKcfDataVal[SHA256_LEN] = { 0 }; + Uint8Buff tmpKcfData = { tmpKcfDataVal, SHA256_LEN }; + res = params->loader->sha256(&proofMsg, &tmpKcfData); + if (res != HC_SUCCESS) { + LOGE("Sha256 for proofMsg failed, res: %x.", res); + goto CLEAN_UP; + } + if (memcmp(tmpKcfData.val, params->kcfDataPeer.val, tmpKcfData.length) != EOK) { + LOGE("Compare kcfData failed."); + res = HC_ERR_PROOF_NOT_MATCH; + goto CLEAN_UP; + } + goto OUT; +CLEAN_UP: + CleanPakeSensitiveKeys(params); +OUT: + FreeAndCleanKey(&proofMsg); + return res; +} + +static int32_t GenerateSessionKey(PakeBaseParams *params) +{ + Uint8Buff keyInfo = { (uint8_t *)HICHAIN_SPEKE_SESSIONKEY_INFO, HcStrlen(HICHAIN_SPEKE_SESSIONKEY_INFO) }; + int res = params->loader->computeHkdf(¶ms->sharedSecret, ¶ms->salt, &keyInfo, ¶ms->sessionKey, false); + if (res != HC_SUCCESS) { + LOGE("ComputeHkdf for sessionKey failed, res: %x.", res); + CleanPakeSensitiveKeys(params); + } + FreeAndCleanKey(¶ms->base); + FreeAndCleanKey(¶ms->sharedSecret); + return res; +} + +int32_t ClientConfirmPakeV2Protocol(PakeBaseParams *params) +{ + if (params == NULL) { + LOGE("Params is null."); + return HC_ERR_NULL_PTR; + } + int32_t res = GeneratePakeParams(params); + if (res != HC_SUCCESS) { + LOGE("GeneratePakeParams failed, res: %x.", res); + goto CLEAN_UP; + } + res = GenerateSharedSecret(params); + if (res != HC_SUCCESS) { + LOGE("GenerateSharedSecret failed, res: %x.", res); + goto CLEAN_UP; + } + res = GenerateProof(params); + if (res != HC_SUCCESS) { + LOGE("GenerateProof failed, res: %x.", res); + goto CLEAN_UP; + } + return res; +CLEAN_UP: + CleanPakeSensitiveKeys(params); + return res; +} + +int32_t ClientVerifyConfirmPakeV2Protocol(PakeBaseParams *params) +{ + if (params == NULL) { + LOGE("Params is null."); + return HC_ERR_NULL_PTR; + } + int32_t res = VerifyProof(params); + if (res != HC_SUCCESS) { + LOGE("VerifyProof failed, res: %x.", res); + goto CLEAN_UP; + } + + res = GenerateSessionKey(params); + if (res != HC_SUCCESS) { + LOGE("GenerateSessionKey failed, res: %x.", res); + goto CLEAN_UP; + } + return res; +CLEAN_UP: + CleanPakeSensitiveKeys(params); + return res; +} + +int32_t ServerResponsePakeV2Protocol(PakeBaseParams *params) +{ + if (params == NULL) { + LOGE("Params is null."); + return HC_ERR_NULL_PTR; + } + int32_t res = GeneratePakeParams(params); + if (res != HC_SUCCESS) { + LOGE("GeneratePakeParams failed, res: %x.", res); + CleanPakeSensitiveKeys(params); + } + return res; +} + +int32_t ServerConfirmPakeV2Protocol(PakeBaseParams *params) +{ + if (params == NULL) { + LOGE("Params is null."); + return HC_ERR_NULL_PTR; + } + int32_t res = GenerateSharedSecret(params); + if (res != HC_SUCCESS) { + LOGE("GenerateSharedSecret failed, res: %x.", res); + goto CLEAN_UP; + } + res = VerifyProof(params); + if (res != HC_SUCCESS) { + LOGE("VerifyProof failed, res: %x.", res); + goto CLEAN_UP; + } + res = GenerateProof(params); + if (res != HC_SUCCESS) { + LOGE("GenerateProof failed, res: %x.", res); + goto CLEAN_UP; + } + res = GenerateSessionKey(params); + if (res != HC_SUCCESS) { + LOGE("GenerateSessionKey failed, res: %x.", res); + goto CLEAN_UP; + } + return res; +CLEAN_UP: + CleanPakeSensitiveKeys(params); + return res; +} diff --git a/test/unittest/deviceauth/BUILD.gn b/test/unittest/deviceauth/BUILD.gn index ddcadc1..e9fe1b7 100644 --- a/test/unittest/deviceauth/BUILD.gn +++ b/test/unittest/deviceauth/BUILD.gn @@ -26,6 +26,8 @@ ohos_unittest("deviceauth_llt") { include_dirs += [ "./include", "//third_party/json/include", + "//third_party/mbedtls/include", + "//third_party/mbedtls/include/mbedtls", "//utils/native/base/include", "//foundation/communication/dsoftbus/interfaces/kits/common", "//foundation/communication/dsoftbus/interfaces/kits/transport", @@ -44,6 +46,7 @@ ohos_unittest("deviceauth_llt") { "${key_management_adapter_path}/impl/src/alg_loader.c", "${key_management_adapter_path}/impl/src/standard/crypto_hash_to_point.c", "${key_management_adapter_path}/impl/src/standard/huks_adapter.c", + "${key_management_adapter_path}/impl/src/standard/mbedtls_ec_adapter.c", "${os_adapter_path}/impl/src/hc_mutex.c", "${os_adapter_path}/impl/src/hc_task_thread.c", "${os_adapter_path}/impl/src/hc_time.c", @@ -63,6 +66,7 @@ ohos_unittest("deviceauth_llt") { "//third_party/cJSON:cjson_static", "//third_party/googletest:gmock_main", "//third_party/googletest:gtest_main", + "//third_party/mbedtls:mbedtls_shared", "//third_party/openssl:libcrypto_static", "//utils/native/base:utils", ] diff --git a/test/unittest/deviceauth/source/deviceauth_standard_test.cpp b/test/unittest/deviceauth/source/deviceauth_standard_test.cpp index e55b612..63deb3c 100644 --- a/test/unittest/deviceauth/source/deviceauth_standard_test.cpp +++ b/test/unittest/deviceauth/source/deviceauth_standard_test.cpp @@ -554,7 +554,7 @@ HWTEST_F(GmGetJoinedGroupsTest, GmGetJoinedGroupsTest002, TestSize.Level0) char *returnData = NULL; uint32_t returnNum = 0; int32_t ret = gm->getJoinedGroups(TEST_REQ_ID, TEST_APP_ID, IDENTICAL_ACCOUNT_GROUP, &returnData, &returnNum); - EXPECT_NE(ret, HC_SUCCESS); + EXPECT_EQ(ret, HC_SUCCESS); } class GmGetRelatedGroupsTest : public testing::Test {