/* * Copyright (c) 2022-2024 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 "pin_auth.h" #include <map> #include <sys/stat.h> #include <vector> #include <unistd.h> #include <pthread.h> #include "parameter.h" #include "securec.h" #include "sysparam_errno.h" #include "adaptor_memory.h" #include "adaptor_log.h" #include "all_in_one_func.h" #include "collector_func.h" #include "executor_func_common.h" #include "pin_auth_hdi.h" #include "verifier_func.h" namespace OHOS { namespace UserIam { namespace PinAuth { namespace { constexpr uint32_t MAX_TEMPLATEID_LEN = 32; std::map<int32_t, ResultCodeForCoAuth> g_convertResult = { {RESULT_SUCCESS, ResultCodeForCoAuth::SUCCESS}, {RESULT_BAD_PARAM, ResultCodeForCoAuth::INVALID_PARAMETERS}, {RESULT_COMPARE_FAIL, ResultCodeForCoAuth::FAIL}, {RESULT_BUSY, ResultCodeForCoAuth::BUSY}, {RESULT_PIN_FREEZE, ResultCodeForCoAuth::LOCKED}, {RESULT_BAD_COPY, ResultCodeForCoAuth::GENERAL_ERROR}, {RESULT_GENERAL_ERROR, ResultCodeForCoAuth::GENERAL_ERROR}, }; } /* This is for example only, Should be implemented in trusted environment. */ int32_t PinAuth::Init() { LOG_INFO("start"); std::lock_guard<std::mutex> gurard(mutex_); if (!LoadPinDb()) { LOG_ERROR("LoadPinDb fail!"); return PinResultToCoAuthResult(RESULT_GENERAL_ERROR); } if (GenerateAllInOneKeyPair() != RESULT_SUCCESS) { LOG_ERROR("GenerateAllInOneKeyPair fail!"); return PinResultToCoAuthResult(RESULT_GENERAL_ERROR); } if (GenerateCollectorKeyPair() != RESULT_SUCCESS) { LOG_ERROR("GenerateCollectorKeyPair fail!"); return PinResultToCoAuthResult(RESULT_GENERAL_ERROR); } if (GenerateVerifierKeyPair() != RESULT_SUCCESS) { LOG_ERROR("GenerateVerifierKeyPair fail!"); return PinResultToCoAuthResult(RESULT_GENERAL_ERROR); } LOG_INFO("InIt pinAuth succ"); return RESULT_SUCCESS; } /* This is for example only, Should be implemented in trusted environment. */ int32_t PinAuth::Close() { LOG_INFO("start"); std::lock_guard<std::mutex> gurard(mutex_); DestroyAllInOneKeyPair(); DestroyCollectorKeyPair(); DestroyVerifierKeyPair(); DestroyPinDb(); LOG_INFO("Close pinAuth succ"); return RESULT_SUCCESS; } /* This is for example only, Should be implemented in trusted environment. */ int32_t PinAuth::PinResultToCoAuthResult(int32_t resultCode) { LOG_INFO("PinAuth::PinResultToCoAuthResult enter"); if (g_convertResult.count(resultCode) == 0) { LOG_ERROR("PinResult and CoauthResult not match, convert GENERAL_ERROR"); return ResultCodeForCoAuth::GENERAL_ERROR; } else { return g_convertResult[resultCode]; } } /* This is for example only, Should be implemented in trusted environment. */ int32_t PinAuth::EnrollPin(uint64_t scheduleId, uint64_t subType, std::vector<uint8_t> &salt, const std::vector<uint8_t> &pinData, std::vector<uint8_t> &resultTlv) { LOG_INFO("start"); std::lock_guard<std::mutex> gurard(mutex_); if (salt.size() != CONST_SALT_LEN || pinData.size() != CONST_PIN_DATA_LEN) { LOG_ERROR("get bad params!"); return PinResultToCoAuthResult(RESULT_BAD_PARAM); } PinEnrollParam pinEnrollParam = {}; pinEnrollParam.scheduleId = scheduleId; pinEnrollParam.subType = subType; if (memcpy_s(&(pinEnrollParam.salt[0]), CONST_SALT_LEN, salt.data(), CONST_SALT_LEN) != EOK) { LOG_ERROR("copy salt to pinEnrollParam fail!"); return PinResultToCoAuthResult(RESULT_BAD_COPY); } if (memcpy_s(&(pinEnrollParam.pinData[0]), CONST_PIN_DATA_LEN, pinData.data(), CONST_PIN_DATA_LEN) != EOK) { LOG_ERROR("copy pinData to pinEnrollParam fail!"); return PinResultToCoAuthResult(RESULT_BAD_COPY); } Buffer *retTlv = CreateBufferBySize(RESULT_TLV_LEN); if (!IsBufferValid(retTlv)) { LOG_ERROR("retTlv is unValid!"); return PinResultToCoAuthResult(RESULT_GENERAL_ERROR); } ResultCode result = DoEnrollPin(&pinEnrollParam, retTlv); if (result != RESULT_SUCCESS) { LOG_ERROR("DoEnrollPin fail!"); goto ERROR; } resultTlv.resize(retTlv->contentSize); if (memcpy_s(resultTlv.data(), retTlv->contentSize, retTlv->buf, retTlv->contentSize) != EOK) { LOG_ERROR("copy retTlv to resultTlv fail!"); result = RESULT_BAD_COPY; goto ERROR; } ERROR: DestroyBuffer(retTlv); return PinResultToCoAuthResult(result); } /* This is for example only, Should be implemented in trusted environment. */ int32_t PinAuth::GenerateAlgoParameter(std::vector<uint8_t> &algoParameter, uint32_t &algoVersion) { LOG_INFO("start"); static constexpr uint32_t deviceUuidLength = 65; char localDeviceId[deviceUuidLength] = {0}; if (GetDevUdid(localDeviceId, deviceUuidLength) != EC_SUCCESS) { LOG_ERROR("GetDevUdid failed"); return GENERAL_ERROR; } uint32_t algoParameterLen = CONST_SALT_LEN; algoParameter.resize(algoParameterLen); int32_t result = DoGenerateAlgoParameter(algoParameter.data(), &algoParameterLen, &algoVersion, (uint8_t *)&(localDeviceId[0]), deviceUuidLength); if (result != RESULT_SUCCESS) { LOG_ERROR("DoGenerateAlgoParameter fail!"); return PinResultToCoAuthResult(result); } if (algoParameterLen != CONST_SALT_LEN) { LOG_ERROR("algoParameterLen is error!"); return GENERAL_ERROR; } return SUCCESS; } /* This is for example only, Should be implemented in trusted environment. */ int32_t PinAuth::AllInOneAuth( uint64_t scheduleId, uint64_t templateId, const std::vector<uint8_t> &extraInfo, PinAlgoParam &pinAlgoParam) { LOG_INFO("start"); std::lock_guard<std::mutex> gurard(mutex_); AlgoParamOut authAlgoParam = {}; ResultCode result = DoAllInOneAuth(scheduleId, templateId, extraInfo.data(), extraInfo.size(), &authAlgoParam); if (result != RESULT_SUCCESS) { LOG_ERROR("DoAllInOneAuth fail!"); return PinResultToCoAuthResult(result); } pinAlgoParam.algoVersion = authAlgoParam.algoVersion; pinAlgoParam.subType = authAlgoParam.subType; int32_t transResult = SetVectorByBuffer( pinAlgoParam.algoParameter, authAlgoParam.algoParameter, sizeof(authAlgoParam.algoParameter)); if (transResult != RESULT_SUCCESS) { LOG_ERROR("set algoParameter fail!"); return PinResultToCoAuthResult(transResult); } transResult = SetVectorByBuffer(pinAlgoParam.challenge, authAlgoParam.challenge, sizeof(authAlgoParam.challenge)); if (transResult != RESULT_SUCCESS) { LOG_ERROR("set challenge fail!"); return PinResultToCoAuthResult(transResult); } return RESULT_SUCCESS; } /* This is for example only, Should be implemented in trusted environment. */ int32_t PinAuth::AuthPin(uint64_t scheduleId, uint64_t templateId, const std::vector<uint8_t> &pinData, std::vector<uint8_t> &resultTlv) { LOG_INFO("start"); std::lock_guard<std::mutex> gurard(mutex_); if (pinData.size() != CONST_PIN_DATA_LEN) { LOG_ERROR("bad pinData len!"); return PinResultToCoAuthResult(RESULT_BAD_PARAM); } PinAuthParam pinAuthParam = {}; pinAuthParam.scheduleId = scheduleId; pinAuthParam.templateId = templateId; if (memcpy_s(&(pinAuthParam.pinData[0]), CONST_PIN_DATA_LEN, pinData.data(), pinData.size()) != EOK) { LOG_ERROR("mem copy pinData to pinAuthParam fail!"); return PinResultToCoAuthResult(RESULT_BAD_COPY); } Buffer *retTlv = CreateBufferBySize(RESULT_TLV_LEN); if (!IsBufferValid(retTlv)) { LOG_ERROR("retTlv is unValid!"); return PinResultToCoAuthResult(RESULT_GENERAL_ERROR); } ResultCode compareRet = RESULT_COMPARE_FAIL; ResultCode result = DoAuthPin(&pinAuthParam, retTlv, &compareRet); if (result != RESULT_SUCCESS) { LOG_ERROR("DoAuthPin fail!"); goto ERROR; } resultTlv.resize(retTlv->contentSize); if (memcpy_s(resultTlv.data(), retTlv->contentSize, retTlv->buf, retTlv->contentSize) != EOK) { LOG_ERROR("copy retTlv to resultTlv fail!"); result = RESULT_GENERAL_ERROR; goto ERROR; } result = compareRet; ERROR: DestroyBuffer(retTlv); return PinResultToCoAuthResult(result); } /* This is for example only, Should be implemented in trusted environment. */ int32_t PinAuth::QueryPinInfo(uint64_t templateId, PinCredentialInfo &pinCredentialInfoRet) { LOG_INFO("start"); std::lock_guard<std::mutex> gurard(mutex_); PinCredentialInfos pinCredentialInfosRet = {}; int32_t result = DoQueryPinInfo(templateId, &pinCredentialInfosRet); if (result != RESULT_SUCCESS) { LOG_ERROR("DoQueryPinInfo fail!"); return PinResultToCoAuthResult(result); } pinCredentialInfoRet.subType = pinCredentialInfosRet.subType; pinCredentialInfoRet.remainTimes = pinCredentialInfosRet.remainTimes; pinCredentialInfoRet.freezingTime = pinCredentialInfosRet.freezeTime; pinCredentialInfoRet.nextFailLockoutDuration = pinCredentialInfosRet.nextFailLockoutDuration; return RESULT_SUCCESS; } /* This is for example only, Should be implemented in trusted environment. */ int32_t PinAuth::DeleteTemplate(uint64_t templateId) { LOG_INFO("start"); std::lock_guard<std::mutex> gurard(mutex_); ResultCode result = DoDeleteTemplate(templateId); if (result != RESULT_SUCCESS) { LOG_ERROR("DoDeleteTemplate fail!"); return PinResultToCoAuthResult(RESULT_GENERAL_ERROR); } return PinResultToCoAuthResult(result); } /* This is for example only, Should be implemented in trusted environment. */ int32_t PinAuth::GetExecutorInfo(int32_t executorRole, std::vector<uint8_t> &pubKey, uint32_t &esl, uint32_t &maxTemplateAcl) { LOG_INFO("start"); std::lock_guard<std::mutex> gurard(mutex_); PinExecutorInfo pinExecutorInfo = {}; int32_t result = RESULT_GENERAL_ERROR; switch (executorRole) { case HDI::PinAuth::HdiExecutorRole::ALL_IN_ONE: result = DoGetAllInOneExecutorInfo(&pinExecutorInfo); break; case HDI::PinAuth::HdiExecutorRole::COLLECTOR: result = DoGetCollectorExecutorInfo(&pinExecutorInfo); break; case HDI::PinAuth::HdiExecutorRole::VERIFIER: result = DoGetVerifierExecutorInfo(&pinExecutorInfo); break; default: LOG_ERROR("unknown role"); break; } if (result != RESULT_SUCCESS) { LOG_ERROR("DoGetExecutorInfo fail!"); goto ERROR; } esl = pinExecutorInfo.esl; maxTemplateAcl = pinExecutorInfo.maxTemplateAcl; pubKey.resize(ED25519_FIX_PUBKEY_BUFFER_SIZE); if (memcpy_s(pubKey.data(), ED25519_FIX_PUBKEY_BUFFER_SIZE, pinExecutorInfo.pubKey, ED25519_FIX_PUBKEY_BUFFER_SIZE) != EOK) { LOG_ERROR("copy pinExecutorInfo to pubKey fail!"); result = RESULT_GENERAL_ERROR; goto ERROR; } ERROR: static_cast<void>(memset_s( pinExecutorInfo.pubKey, ED25519_FIX_PUBKEY_BUFFER_SIZE, 0, ED25519_FIX_PUBKEY_BUFFER_SIZE)); return PinResultToCoAuthResult(result); } /* This is for example only, Should be implemented in trusted environment. */ int32_t PinAuth::SetAllInOneFwkParam( const std::vector<uint64_t> &templateIdList, const std::vector<uint8_t> &frameworkPublicKey) { LOG_INFO("start"); std::lock_guard<std::mutex> gurard(mutex_); uint32_t templateIdListLen = templateIdList.size(); if (templateIdListLen > MAX_TEMPLATEID_LEN) { LOG_ERROR("check templateIdListLen fail!"); return PinResultToCoAuthResult(RESULT_GENERAL_ERROR); } ResultCode result = DoSetAllInOneFwkParam( &templateIdList[0], templateIdListLen, frameworkPublicKey.data(), frameworkPublicKey.size()); if (result != RESULT_SUCCESS) { LOG_ERROR("DoSetAllInOneFwkParam fail!"); } return PinResultToCoAuthResult(result); } void PinAuth::WriteAntiBrute(uint64_t templateId) { LOG_INFO("start"); std::lock_guard<std::mutex> gurard(mutex_); if (DoWriteAntiBruteInfoToFile(templateId) != RESULT_SUCCESS) { LOG_ERROR("DoWriteAntiBruteInfoToFile fail!"); } } /* This is for example only, Should be implemented in trusted environment. */ int32_t PinAuth::SetCollectorFwkParam(const std::vector<uint8_t> &frameworkPublicKey) { std::lock_guard<std::mutex> gurard(mutex_); int32_t result = DoSetCollectorFwkParam(frameworkPublicKey.data(), frameworkPublicKey.size()); if (result != RESULT_SUCCESS) { LOG_ERROR("DoSetCollectorFwkParam fail!"); } return PinResultToCoAuthResult(result); } int32_t PinAuth::SetVectorByBuffer(std::vector<uint8_t> &vec, const uint8_t *buf, uint32_t bufSize) { if (bufSize == 0) { vec.clear(); return RESULT_SUCCESS; } vec.resize(bufSize); if (memcpy_s(vec.data(), vec.size(), buf, bufSize) != EOK) { LOG_ERROR("copy buf fail!"); return RESULT_BAD_COPY; } return RESULT_SUCCESS; } /* This is for example only, Should be implemented in trusted environment. */ int32_t PinAuth::Collect(uint64_t scheduleId, const std::vector<uint8_t> &extraInfo, std::vector<uint8_t> &msg) { std::lock_guard<std::mutex> gurard(mutex_); uint8_t *out = new (std::nothrow) uint8_t[MAX_EXECUTOR_MSG_LEN]; if (out == nullptr) { LOG_ERROR("malloc out fail!"); return GENERAL_ERROR; } uint32_t outSize = MAX_EXECUTOR_MSG_LEN; int32_t result = DoCollect(scheduleId, extraInfo.data(), extraInfo.size(), out, &outSize); if (result != RESULT_SUCCESS) { LOG_ERROR("DoCollect fail!"); delete[] out; return PinResultToCoAuthResult(result); } result = SetVectorByBuffer(msg, out, outSize); delete[] out; if (result != RESULT_SUCCESS) { LOG_ERROR("set msg fail!"); } return PinResultToCoAuthResult(result); } /* This is for example only, Should be implemented in trusted environment. */ int32_t PinAuth::CancelCollect() { std::lock_guard<std::mutex> gurard(mutex_); int32_t result = DoCancelCollect(); if (result != RESULT_SUCCESS) { LOG_ERROR("DoCancelCollect fail!"); } return PinResultToCoAuthResult(result); } /* This is for example only, Should be implemented in trusted environment. */ int32_t PinAuth::SendMessageToCollector( uint64_t scheduleId, const std::vector<uint8_t> &msg, PinAlgoParam &pinAlgoParam) { std::lock_guard<std::mutex> gurard(mutex_); AlgoParamOut algoParam = {}; int32_t result = DoSendMessageToCollector(scheduleId, msg.data(), msg.size(), &algoParam); if (result != RESULT_SUCCESS) { LOG_ERROR("DoSendMessageToCollector fail!"); return PinResultToCoAuthResult(result); } pinAlgoParam.algoVersion = algoParam.algoVersion; pinAlgoParam.subType = algoParam.subType; result = SetVectorByBuffer(pinAlgoParam.algoParameter, algoParam.algoParameter, sizeof(algoParam.algoParameter)); if (result != RESULT_SUCCESS) { LOG_ERROR("set algoParameter fail!"); return PinResultToCoAuthResult(result); } result = SetVectorByBuffer(pinAlgoParam.challenge, algoParam.challenge, sizeof(algoParam.challenge)); if (result != RESULT_SUCCESS) { LOG_ERROR("set challenge fail!"); return PinResultToCoAuthResult(result); } return PinResultToCoAuthResult(result); } /* This is for example only, Should be implemented in trusted environment. */ int32_t PinAuth::SetDataToCollector(uint64_t scheduleId, const std::vector<uint8_t> &data, std::vector<uint8_t> &msg) { std::lock_guard<std::mutex> gurard(mutex_); int32_t result = RESULT_GENERAL_ERROR; uint8_t *pinData = const_cast<uint8_t *>(data.data()); uint8_t *out = new (std::nothrow) uint8_t[MAX_EXECUTOR_MSG_LEN]; uint32_t outSize = MAX_EXECUTOR_MSG_LEN; if (out == nullptr) { LOG_ERROR("new out fail!"); goto EXIT; } result = DoSetDataToCollector(scheduleId, pinData, data.size(), out, &outSize); if (result != RESULT_SUCCESS) { LOG_ERROR("DoSetDataToCollector fail!"); goto EXIT; } result = SetVectorByBuffer(msg, out, outSize); if (result != RESULT_SUCCESS) { LOG_ERROR("set msg fail!"); } EXIT: if (data.size() != 0) { (void)memset_s(pinData, data.size(), 0, data.size()); } if (out != nullptr) { delete[] out; } return PinResultToCoAuthResult(result); } /* This is for example only, Should be implemented in trusted environment. */ int32_t PinAuth::SetVerifierFwkParam(const std::vector<uint8_t> &frameworkPublicKey) { std::lock_guard<std::mutex> gurard(mutex_); int32_t result = DoSetVerifierFwkParam(frameworkPublicKey.data(), frameworkPublicKey.size()); if (result != RESULT_SUCCESS) { LOG_ERROR("DoSetVerifierFwkParam fail!"); } return PinResultToCoAuthResult(result); } /* This is for example only, Should be implemented in trusted environment. */ int32_t PinAuth::VerifierAuth( uint64_t scheduleId, uint64_t templateId, const std::vector<uint8_t> &extraInfo, std::vector<uint8_t> &msgOut) { std::lock_guard<std::mutex> gurard(mutex_); uint8_t *out = new (std::nothrow) uint8_t[MAX_EXECUTOR_MSG_LEN]; if (out == nullptr) { LOG_ERROR("new out fail!"); return GENERAL_ERROR; } VerifierMsg verifierMsg = { .msgIn = const_cast<uint8_t *>(extraInfo.data()), .msgInSize = extraInfo.size(), .msgOut = out, .msgOutSize = MAX_EXECUTOR_MSG_LEN, .isAuthEnd = false, .authResult = RESULT_GENERAL_ERROR, }; int32_t result = DoVerifierAuth(scheduleId, templateId, &verifierMsg); if (result != RESULT_SUCCESS) { LOG_ERROR("DoVerifierAuth fail!"); delete[] out; return PinResultToCoAuthResult(result); } if (verifierMsg.authResult == RESULT_SUCCESS) { delete[] out; return SUCCESS; } result = SetVectorByBuffer(msgOut, verifierMsg.msgOut, verifierMsg.msgOutSize); delete[] out; if (result != RESULT_SUCCESS) { LOG_ERROR("set msg fail!"); return PinResultToCoAuthResult(result); } return PinResultToCoAuthResult(verifierMsg.authResult); } /* This is for example only, Should be implemented in trusted environment. */ int32_t PinAuth::CancelVerifierAuth() { std::lock_guard<std::mutex> gurard(mutex_); int32_t result = DoCancelVerifierAuth(); if (result != RESULT_SUCCESS) { LOG_ERROR("DoCancelVerifierAuth fail!"); } return PinResultToCoAuthResult(result); } /* This is for example only, Should be implemented in trusted environment. */ int32_t PinAuth::SendMessageToVerifier(uint64_t scheduleId, const std::vector<uint8_t> &msgIn, std::vector<uint8_t> &msgOut, bool &isAuthEnd, int32_t &compareResult) { std::lock_guard<std::mutex> gurard(mutex_); uint8_t *out = new (std::nothrow) uint8_t[MAX_EXECUTOR_MSG_LEN]; if (out == nullptr) { LOG_ERROR("new out fail!"); return GENERAL_ERROR; } VerifierMsg verifierMsg = { .msgIn = const_cast<uint8_t *>(msgIn.data()), .msgInSize = msgIn.size(), .msgOut = out, .msgOutSize = MAX_EXECUTOR_MSG_LEN, .isAuthEnd = false, .authResult = RESULT_GENERAL_ERROR, }; int32_t result = DoSendMessageToVerifier(scheduleId, &verifierMsg); if (result != RESULT_SUCCESS) { LOG_ERROR("DoSendMessageToVerifier fail!"); delete[] out; return PinResultToCoAuthResult(result); } result = SetVectorByBuffer(msgOut, out, verifierMsg.msgOutSize); delete[] out; if (result != RESULT_SUCCESS) { LOG_ERROR("set msg fail!"); return PinResultToCoAuthResult(result); } isAuthEnd = verifierMsg.isAuthEnd; compareResult = PinResultToCoAuthResult(verifierMsg.authResult); return PinResultToCoAuthResult(result); } } // namespace PinAuth } // namespace UserIam } // namespace OHOS