154aa6d63Sopenharmony_ci/* 254aa6d63Sopenharmony_ci * Copyright (c) 2024-2024 Huawei Device Co., Ltd. 354aa6d63Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 454aa6d63Sopenharmony_ci * you may not use this file except in compliance with the License. 554aa6d63Sopenharmony_ci * You may obtain a copy of the License at 654aa6d63Sopenharmony_ci * 754aa6d63Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 854aa6d63Sopenharmony_ci * 954aa6d63Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1054aa6d63Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1154aa6d63Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1254aa6d63Sopenharmony_ci * See the License for the specific language governing permissions and 1354aa6d63Sopenharmony_ci * limitations under the License. 1454aa6d63Sopenharmony_ci */ 1554aa6d63Sopenharmony_ci#include <climits> 1654aa6d63Sopenharmony_ci#include <cstdlib> 1754aa6d63Sopenharmony_ci#include <regex> 1854aa6d63Sopenharmony_ci#include <unordered_map> 1954aa6d63Sopenharmony_ci#include <vector> 2054aa6d63Sopenharmony_ci#include <algorithm> 2154aa6d63Sopenharmony_ci 2254aa6d63Sopenharmony_ci#include "securec.h" 2354aa6d63Sopenharmony_ci#include "hap_signer_block_utils.h" 2454aa6d63Sopenharmony_ci#include "signature_info.h" 2554aa6d63Sopenharmony_ci#include "options.h" 2654aa6d63Sopenharmony_ci#include "openssl/pem.h" 2754aa6d63Sopenharmony_ci#include "pkcs7_data.h" 2854aa6d63Sopenharmony_ci#include "hap_utils.h" 2954aa6d63Sopenharmony_ci#include "string_utils.h" 3054aa6d63Sopenharmony_ci#include "verify_code_signature.h" 3154aa6d63Sopenharmony_ci#include "param_constants.h" 3254aa6d63Sopenharmony_ci#include "file_utils.h" 3354aa6d63Sopenharmony_ci#include "nlohmann/json.hpp" 3454aa6d63Sopenharmony_ci#include "verify_hap.h" 3554aa6d63Sopenharmony_ci 3654aa6d63Sopenharmony_ciusing namespace nlohmann; 3754aa6d63Sopenharmony_cinamespace OHOS { 3854aa6d63Sopenharmony_cinamespace SignatureTools { 3954aa6d63Sopenharmony_ciconst int32_t VerifyHap::HEX_PRINT_LENGTH = 3; 4054aa6d63Sopenharmony_ciconst int32_t VerifyHap::DIGEST_BLOCK_LEN_OFFSET = 8; 4154aa6d63Sopenharmony_ciconst int32_t VerifyHap::DIGEST_ALGORITHM_OFFSET = 12; 4254aa6d63Sopenharmony_ciconst int32_t VerifyHap::DIGEST_LEN_OFFSET = 16; 4354aa6d63Sopenharmony_ciconst int32_t VerifyHap::DIGEST_OFFSET_IN_CONTENT = 20; 4454aa6d63Sopenharmony_ciconst std::string VerifyHap::HAP_APP_PATTERN = "[^]*.hap$"; 4554aa6d63Sopenharmony_ciconst std::string VerifyHap::HQF_APP_PATTERN = "[^]*.hqf$"; 4654aa6d63Sopenharmony_ciconst std::string VerifyHap::HSP_APP_PATTERN = "[^]*.hsp$"; 4754aa6d63Sopenharmony_ciconst std::string VerifyHap::APP_APP_PATTERN = "[^]*.app$"; 4854aa6d63Sopenharmony_cistatic constexpr int ZIP_HEAD_OF_SUBSIGNING_BLOCK_LENGTH = 12; 4954aa6d63Sopenharmony_ci 5054aa6d63Sopenharmony_ciVerifyHap::VerifyHap() : isPrintCert(true) 5154aa6d63Sopenharmony_ci{ 5254aa6d63Sopenharmony_ci} 5354aa6d63Sopenharmony_ci 5454aa6d63Sopenharmony_ciVerifyHap::VerifyHap(bool printCert) 5554aa6d63Sopenharmony_ci{ 5654aa6d63Sopenharmony_ci isPrintCert = printCert; 5754aa6d63Sopenharmony_ci} 5854aa6d63Sopenharmony_ci 5954aa6d63Sopenharmony_civoid VerifyHap::setIsPrintCert(bool printCert) 6054aa6d63Sopenharmony_ci{ 6154aa6d63Sopenharmony_ci isPrintCert = printCert; 6254aa6d63Sopenharmony_ci} 6354aa6d63Sopenharmony_ci 6454aa6d63Sopenharmony_cibool VerifyHap::HapOutPutPkcs7(PKCS7* p7, const std::string& outPutPath) 6554aa6d63Sopenharmony_ci{ 6654aa6d63Sopenharmony_ci std::string p7bContent = StringUtils::Pkcs7ToString(p7); 6754aa6d63Sopenharmony_ci if (p7bContent.empty()) { 6854aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("p7b to string failed!\n"); 6954aa6d63Sopenharmony_ci return false; 7054aa6d63Sopenharmony_ci } 7154aa6d63Sopenharmony_ci if (FileUtils::Write(p7bContent, outPutPath) < 0) { 7254aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("p7b write to file falied!\n"); 7354aa6d63Sopenharmony_ci return false; 7454aa6d63Sopenharmony_ci } 7554aa6d63Sopenharmony_ci return true; 7654aa6d63Sopenharmony_ci} 7754aa6d63Sopenharmony_ci 7854aa6d63Sopenharmony_cibool VerifyHap::outputOptionalBlocks(const std::string& outputProfileFile, const std::string& outputProofFile, 7954aa6d63Sopenharmony_ci const std::string& outputPropertyFile, 8054aa6d63Sopenharmony_ci const std::vector<OptionalBlock>& optionBlocks) 8154aa6d63Sopenharmony_ci{ 8254aa6d63Sopenharmony_ci for (auto& optionBlock : optionBlocks) { 8354aa6d63Sopenharmony_ci if (optionBlock.optionalType == HapUtils::HAP_PROFILE_BLOCK_ID) { 8454aa6d63Sopenharmony_ci if (!writeOptionalBytesToFile(optionBlock, outputProfileFile)) { 8554aa6d63Sopenharmony_ci return false; 8654aa6d63Sopenharmony_ci } 8754aa6d63Sopenharmony_ci } else if (optionBlock.optionalType == HapUtils::HAP_PROPERTY_BLOCK_ID) { 8854aa6d63Sopenharmony_ci if (!writeOptionalBytesToFile(optionBlock, outputPropertyFile)) { 8954aa6d63Sopenharmony_ci return false; 9054aa6d63Sopenharmony_ci } 9154aa6d63Sopenharmony_ci } else if (optionBlock.optionalType == HapUtils::HAP_PROOF_OF_ROTATION_BLOCK_ID) { 9254aa6d63Sopenharmony_ci if (!writeOptionalBytesToFile(optionBlock, outputProofFile)) { 9354aa6d63Sopenharmony_ci return false; 9454aa6d63Sopenharmony_ci } 9554aa6d63Sopenharmony_ci } else { 9654aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("Unsupported Block Id: %d", optionBlock.optionalType); 9754aa6d63Sopenharmony_ci return false; 9854aa6d63Sopenharmony_ci } 9954aa6d63Sopenharmony_ci } 10054aa6d63Sopenharmony_ci return true; 10154aa6d63Sopenharmony_ci} 10254aa6d63Sopenharmony_cibool VerifyHap::writeOptionalBytesToFile(const OptionalBlock& optionalBlock, const std::string& path) 10354aa6d63Sopenharmony_ci{ 10454aa6d63Sopenharmony_ci if (path.empty()) { 10554aa6d63Sopenharmony_ci return true; 10654aa6d63Sopenharmony_ci } 10754aa6d63Sopenharmony_ci std::string optionBlockString(optionalBlock.optionalBlockValue.GetBufferPtr(), 10854aa6d63Sopenharmony_ci optionalBlock.optionalBlockValue.GetCapacity()); 10954aa6d63Sopenharmony_ci if (FileUtils::Write(optionBlockString, path) < 0) { 11054aa6d63Sopenharmony_ci PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "write optional bytes to file:" + path + " falied!"); 11154aa6d63Sopenharmony_ci return false; 11254aa6d63Sopenharmony_ci } 11354aa6d63Sopenharmony_ci return true; 11454aa6d63Sopenharmony_ci} 11554aa6d63Sopenharmony_ci 11654aa6d63Sopenharmony_cibool VerifyHap::HapOutPutCertChain(std::vector<X509*>& certs, const std::string& outPutPath) 11754aa6d63Sopenharmony_ci{ 11854aa6d63Sopenharmony_ci if (isPrintCert) { 11954aa6d63Sopenharmony_ci if (!PrintCertChainToCmd(certs)) { 12054aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("print cert chain to cmd failed\n"); 12154aa6d63Sopenharmony_ci return false; 12254aa6d63Sopenharmony_ci } 12354aa6d63Sopenharmony_ci } 12454aa6d63Sopenharmony_ci VerifyHapOpensslUtils::GetOpensslErrorMessage(); 12554aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGD("outPutPath = %s", outPutPath.c_str()); 12654aa6d63Sopenharmony_ci std::vector<std::string> certStr; 12754aa6d63Sopenharmony_ci for (auto& cert : certs) { 12854aa6d63Sopenharmony_ci certStr.emplace_back(StringUtils::SubjectToString(cert)); 12954aa6d63Sopenharmony_ci certStr.emplace_back(StringUtils::x509CertToString(cert)); 13054aa6d63Sopenharmony_ci } 13154aa6d63Sopenharmony_ci std::string outPutCertChainContent; 13254aa6d63Sopenharmony_ci for (auto& certstr : certStr) { 13354aa6d63Sopenharmony_ci outPutCertChainContent += certstr; 13454aa6d63Sopenharmony_ci } 13554aa6d63Sopenharmony_ci if (FileUtils::Write(outPutCertChainContent, outPutPath) < 0) { 13654aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("certChain write to file falied!\n"); 13754aa6d63Sopenharmony_ci return false; 13854aa6d63Sopenharmony_ci } 13954aa6d63Sopenharmony_ci return true; 14054aa6d63Sopenharmony_ci} 14154aa6d63Sopenharmony_ci 14254aa6d63Sopenharmony_ciint32_t VerifyHap::Verify(const std::string& filePath, Options* options) 14354aa6d63Sopenharmony_ci{ 14454aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGD("Start Verify"); 14554aa6d63Sopenharmony_ci std::string standardFilePath; 14654aa6d63Sopenharmony_ci if (!CheckFilePath(filePath, standardFilePath)) { 14754aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("Check file path%s failed", filePath.c_str()); 14854aa6d63Sopenharmony_ci return IO_ERROR; 14954aa6d63Sopenharmony_ci } 15054aa6d63Sopenharmony_ci RandomAccessFile hapFile; 15154aa6d63Sopenharmony_ci if (!hapFile.Init(standardFilePath)) { 15254aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("%s init failed", standardFilePath.c_str()); 15354aa6d63Sopenharmony_ci return ZIP_ERROR; 15454aa6d63Sopenharmony_ci } 15554aa6d63Sopenharmony_ci int32_t resultCode = Verify(hapFile, options, filePath); 15654aa6d63Sopenharmony_ci if (resultCode != RET_OK) { 15754aa6d63Sopenharmony_ci PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, standardFilePath + " verify failed"); 15854aa6d63Sopenharmony_ci } 15954aa6d63Sopenharmony_ci return resultCode; 16054aa6d63Sopenharmony_ci} 16154aa6d63Sopenharmony_ci 16254aa6d63Sopenharmony_cibool VerifyHap::CheckFilePath(const std::string& filePath, std::string& standardFilePath) 16354aa6d63Sopenharmony_ci{ 16454aa6d63Sopenharmony_ci char path[PATH_MAX] = { 0x00 }; 16554aa6d63Sopenharmony_ci if (filePath.size() > PATH_MAX || realpath(filePath.c_str(), path) == nullptr) { 16654aa6d63Sopenharmony_ci PrintErrorNumberMsg("IO_ERROR", IO_ERROR, 16754aa6d63Sopenharmony_ci filePath + " does not exist or is over " + std::to_string(PATH_MAX) + " chars"); 16854aa6d63Sopenharmony_ci return false; 16954aa6d63Sopenharmony_ci } 17054aa6d63Sopenharmony_ci standardFilePath = std::string(path); 17154aa6d63Sopenharmony_ci std::string standardFilePathTmp = std::string(path); 17254aa6d63Sopenharmony_ci std::transform(standardFilePathTmp.begin(), standardFilePathTmp.end(), standardFilePathTmp.begin(), 17354aa6d63Sopenharmony_ci [](unsigned char c) { return std::tolower(c); }); 17454aa6d63Sopenharmony_ci bool ret = (!std::regex_match(standardFilePathTmp, std::regex(HAP_APP_PATTERN)) && 17554aa6d63Sopenharmony_ci !std::regex_match(standardFilePathTmp, std::regex(HSP_APP_PATTERN)) && 17654aa6d63Sopenharmony_ci !std::regex_match(standardFilePathTmp, std::regex(APP_APP_PATTERN)) && 17754aa6d63Sopenharmony_ci !std::regex_match(standardFilePathTmp, std::regex(HQF_APP_PATTERN))); 17854aa6d63Sopenharmony_ci if (ret) { 17954aa6d63Sopenharmony_ci PrintErrorNumberMsg("COMMAND_PARAM_ERROR", COMMAND_PARAM_ERROR, 18054aa6d63Sopenharmony_ci "only support format is [hap, hqf, hsp, app]"); 18154aa6d63Sopenharmony_ci return false; 18254aa6d63Sopenharmony_ci } 18354aa6d63Sopenharmony_ci return true; 18454aa6d63Sopenharmony_ci} 18554aa6d63Sopenharmony_ci 18654aa6d63Sopenharmony_ciint32_t VerifyHap::Verify(RandomAccessFile& hapFile, Options* options, const std::string& filePath) 18754aa6d63Sopenharmony_ci{ 18854aa6d63Sopenharmony_ci SignatureInfo hapSignInfo; 18954aa6d63Sopenharmony_ci if (!HapSignerBlockUtils::FindHapSignature(hapFile, hapSignInfo)) { 19054aa6d63Sopenharmony_ci return ZIP_ERROR; 19154aa6d63Sopenharmony_ci } 19254aa6d63Sopenharmony_ci 19354aa6d63Sopenharmony_ci if (CheckCodeSign(filePath, hapSignInfo.optionBlocks) == false) { 19454aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("check coode sign failed\n"); 19554aa6d63Sopenharmony_ci return VERIFY_ERROR; 19654aa6d63Sopenharmony_ci } 19754aa6d63Sopenharmony_ci 19854aa6d63Sopenharmony_ci Pkcs7Context pkcs7Context; 19954aa6d63Sopenharmony_ci if (!VerifyAppPkcs7(pkcs7Context, hapSignInfo.hapSignatureBlock)) { 20054aa6d63Sopenharmony_ci return PARSE_ERROR; 20154aa6d63Sopenharmony_ci } 20254aa6d63Sopenharmony_ci 20354aa6d63Sopenharmony_ci if (!GetDigestAndAlgorithm(pkcs7Context)) { 20454aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("Get digest failed"); 20554aa6d63Sopenharmony_ci return PARSE_ERROR; 20654aa6d63Sopenharmony_ci } 20754aa6d63Sopenharmony_ci 20854aa6d63Sopenharmony_ci STACK_OF(X509_CRL)* x509Crl = nullptr; 20954aa6d63Sopenharmony_ci if (!VerifyHapOpensslUtils::GetCrlStack(pkcs7Context.p7, x509Crl)) { 21054aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("Get Crl stack failed"); 21154aa6d63Sopenharmony_ci return PARSE_ERROR; 21254aa6d63Sopenharmony_ci } 21354aa6d63Sopenharmony_ci 21454aa6d63Sopenharmony_ci if (!VerifyCertOpensslUtils::VerifyCrl(pkcs7Context.certChain[0], x509Crl, pkcs7Context)) { 21554aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("Verify Crl stack failed"); 21654aa6d63Sopenharmony_ci return VERIFY_ERROR; 21754aa6d63Sopenharmony_ci } 21854aa6d63Sopenharmony_ci 21954aa6d63Sopenharmony_ci if (!HapSignerBlockUtils::VerifyHapIntegrity(pkcs7Context, hapFile, hapSignInfo)) { 22054aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("Verify Integrity failed"); 22154aa6d63Sopenharmony_ci return VERIFY_ERROR; 22254aa6d63Sopenharmony_ci } 22354aa6d63Sopenharmony_ci if (!HapOutPutCertChain(pkcs7Context.certChain[0], 22454aa6d63Sopenharmony_ci options->GetString(Options::OUT_CERT_CHAIN))) { 22554aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("out put cert chain failed"); 22654aa6d63Sopenharmony_ci return IO_ERROR; 22754aa6d63Sopenharmony_ci } 22854aa6d63Sopenharmony_ci 22954aa6d63Sopenharmony_ci if (!outputOptionalBlocks(options->GetString(ParamConstants::PARAM_VERIFY_PROFILE_FILE), 23054aa6d63Sopenharmony_ci options->GetString(ParamConstants::PARAM_VERIFY_PROOF_FILE), 23154aa6d63Sopenharmony_ci options->GetString(ParamConstants::PARAM_VERIFY_PROPERTY_FILE), 23254aa6d63Sopenharmony_ci hapSignInfo.optionBlocks)) { 23354aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("output Optional Blocks failed"); 23454aa6d63Sopenharmony_ci return IO_ERROR; 23554aa6d63Sopenharmony_ci } 23654aa6d63Sopenharmony_ci return RET_OK; 23754aa6d63Sopenharmony_ci} 23854aa6d63Sopenharmony_ci 23954aa6d63Sopenharmony_cibool VerifyHap::CheckCodeSign(const std::string& hapFilePath, 24054aa6d63Sopenharmony_ci const std::vector<OptionalBlock>& optionalBlocks)const 24154aa6d63Sopenharmony_ci{ 24254aa6d63Sopenharmony_ci std::unordered_map<int, ByteBuffer> map; 24354aa6d63Sopenharmony_ci for (const OptionalBlock& block : optionalBlocks) { 24454aa6d63Sopenharmony_ci map.emplace(block.optionalType, block.optionalBlockValue); 24554aa6d63Sopenharmony_ci } 24654aa6d63Sopenharmony_ci bool codeSignFlag = map.find(HapUtils::HAP_PROPERTY_BLOCK_ID) != map.end() && 24754aa6d63Sopenharmony_ci map[HapUtils::HAP_PROPERTY_BLOCK_ID].GetCapacity() > 0; 24854aa6d63Sopenharmony_ci if (codeSignFlag) { 24954aa6d63Sopenharmony_ci ByteBuffer propertyBlockArray = map[HapUtils::HAP_PROPERTY_BLOCK_ID]; 25054aa6d63Sopenharmony_ci std::vector<std::string> fileNameArray = StringUtils::SplitString(hapFilePath, '.'); 25154aa6d63Sopenharmony_ci if (fileNameArray.size() < ParamConstants::FILE_NAME_MIN_LENGTH) { 25254aa6d63Sopenharmony_ci PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "ZIP64 format not supported."); 25354aa6d63Sopenharmony_ci return false; 25454aa6d63Sopenharmony_ci } 25554aa6d63Sopenharmony_ci 25654aa6d63Sopenharmony_ci if (propertyBlockArray.GetCapacity() < ZIP_HEAD_OF_SUBSIGNING_BLOCK_LENGTH) 25754aa6d63Sopenharmony_ci return false; 25854aa6d63Sopenharmony_ci uint32_t blockType; 25954aa6d63Sopenharmony_ci propertyBlockArray.GetUInt32(OFFSET_ZERO, blockType); 26054aa6d63Sopenharmony_ci uint32_t blockLength; 26154aa6d63Sopenharmony_ci propertyBlockArray.GetUInt32(OFFSET_FOUR, blockLength); 26254aa6d63Sopenharmony_ci uint32_t blockOffset; 26354aa6d63Sopenharmony_ci propertyBlockArray.GetUInt32(OFFSET_EIGHT, blockOffset); 26454aa6d63Sopenharmony_ci 26554aa6d63Sopenharmony_ci if (blockType != HapUtils::HAP_CODE_SIGN_BLOCK_ID) { 26654aa6d63Sopenharmony_ci PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "code sign data not exist in hap " + hapFilePath); 26754aa6d63Sopenharmony_ci return false; 26854aa6d63Sopenharmony_ci } 26954aa6d63Sopenharmony_ci auto ite = map.find(HapUtils::HAP_PROFILE_BLOCK_ID); 27054aa6d63Sopenharmony_ci if (ite == map.end()) 27154aa6d63Sopenharmony_ci return false; 27254aa6d63Sopenharmony_ci ByteBuffer profileArray = ite->second; 27354aa6d63Sopenharmony_ci std::string profileArray_(profileArray.GetBufferPtr(), profileArray.GetCapacity()); 27454aa6d63Sopenharmony_ci std::string profileContent; 27554aa6d63Sopenharmony_ci if (GetProfileContent(profileArray_, profileContent) < 0) { 27654aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("get profile content failed, file: %s", hapFilePath.c_str()); 27754aa6d63Sopenharmony_ci return false; 27854aa6d63Sopenharmony_ci } 27954aa6d63Sopenharmony_ci std::string suffix = fileNameArray[fileNameArray.size() - 1]; 28054aa6d63Sopenharmony_ci bool isCodeSign = VerifyCodeSignature::VerifyHap(hapFilePath, blockOffset, blockLength, 28154aa6d63Sopenharmony_ci suffix, profileContent); 28254aa6d63Sopenharmony_ci if (!isCodeSign) { 28354aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("verify codesign failed, file: %s", hapFilePath.c_str()); 28454aa6d63Sopenharmony_ci return false; 28554aa6d63Sopenharmony_ci } 28654aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGI("verify codesign success."); 28754aa6d63Sopenharmony_ci return true; 28854aa6d63Sopenharmony_ci } 28954aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGI("can not find codesign block."); 29054aa6d63Sopenharmony_ci return true; 29154aa6d63Sopenharmony_ci} 29254aa6d63Sopenharmony_ci 29354aa6d63Sopenharmony_ciint VerifyHap::GetProfileContent(const std::string profile, std::string& ret) 29454aa6d63Sopenharmony_ci{ 29554aa6d63Sopenharmony_ci json obj = json::parse(profile, nullptr, false); 29654aa6d63Sopenharmony_ci if (!obj.is_discarded() && obj.is_structured()) { 29754aa6d63Sopenharmony_ci ret = profile; 29854aa6d63Sopenharmony_ci return 0; 29954aa6d63Sopenharmony_ci } 30054aa6d63Sopenharmony_ci PKCS7Data p7Data; 30154aa6d63Sopenharmony_ci if (p7Data.Parse(profile) < 0) { 30254aa6d63Sopenharmony_ci ret = profile; 30354aa6d63Sopenharmony_ci return -1; 30454aa6d63Sopenharmony_ci } 30554aa6d63Sopenharmony_ci if (p7Data.Verify() < 0) { 30654aa6d63Sopenharmony_ci PrintErrorNumberMsg("PKCS7_VERIFY_ERROR", VERIFY_ERROR, 30754aa6d63Sopenharmony_ci "Verify profile pkcs7 failed! Profile is invalid"); 30854aa6d63Sopenharmony_ci ret = profile; 30954aa6d63Sopenharmony_ci return -1; 31054aa6d63Sopenharmony_ci } 31154aa6d63Sopenharmony_ci if (p7Data.GetContent(ret) < 0) { 31254aa6d63Sopenharmony_ci PrintErrorNumberMsg("PKCS7_VERIFY_ERROR", VERIFY_ERROR, 31354aa6d63Sopenharmony_ci "Check profile failed, signed profile content is not byte array"); 31454aa6d63Sopenharmony_ci ret = profile; 31554aa6d63Sopenharmony_ci return -1; 31654aa6d63Sopenharmony_ci } 31754aa6d63Sopenharmony_ci return 0; 31854aa6d63Sopenharmony_ci} 31954aa6d63Sopenharmony_ci 32054aa6d63Sopenharmony_cibool VerifyHap::VerifyAppPkcs7(Pkcs7Context& pkcs7Context, const ByteBuffer& hapSignatureBlock) 32154aa6d63Sopenharmony_ci{ 32254aa6d63Sopenharmony_ci const unsigned char* pkcs7Block = reinterpret_cast<const unsigned char*>(hapSignatureBlock.GetBufferPtr()); 32354aa6d63Sopenharmony_ci uint32_t pkcs7Len = static_cast<unsigned int>(hapSignatureBlock.GetCapacity()); 32454aa6d63Sopenharmony_ci if (!VerifyHapOpensslUtils::ParsePkcs7Package(pkcs7Block, pkcs7Len, pkcs7Context)) { 32554aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("parse pkcs7 failed"); 32654aa6d63Sopenharmony_ci return false; 32754aa6d63Sopenharmony_ci } 32854aa6d63Sopenharmony_ci if (!VerifyHapOpensslUtils::GetCertChains(pkcs7Context.p7, pkcs7Context)) { 32954aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("GetCertChains from pkcs7 failed"); 33054aa6d63Sopenharmony_ci return false; 33154aa6d63Sopenharmony_ci } 33254aa6d63Sopenharmony_ci if (!VerifyHapOpensslUtils::VerifyPkcs7(pkcs7Context)) { 33354aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("verify signature failed"); 33454aa6d63Sopenharmony_ci return false; 33554aa6d63Sopenharmony_ci } 33654aa6d63Sopenharmony_ci return true; 33754aa6d63Sopenharmony_ci} 33854aa6d63Sopenharmony_ci 33954aa6d63Sopenharmony_cibool VerifyHap::GetDigestAndAlgorithm(Pkcs7Context& digest) 34054aa6d63Sopenharmony_ci{ 34154aa6d63Sopenharmony_ci /* 34254aa6d63Sopenharmony_ci * contentinfo format: 34354aa6d63Sopenharmony_ci * int: version 34454aa6d63Sopenharmony_ci * int: block number 34554aa6d63Sopenharmony_ci * digest blocks: 34654aa6d63Sopenharmony_ci * each digest block format: 34754aa6d63Sopenharmony_ci * int: length of sizeof(digestblock) - 4 34854aa6d63Sopenharmony_ci * int: Algorithm ID 34954aa6d63Sopenharmony_ci * int: length of digest 35054aa6d63Sopenharmony_ci * byte[]: digest 35154aa6d63Sopenharmony_ci */ 35254aa6d63Sopenharmony_ci /* length of sizeof(digestblock - 4) */ 35354aa6d63Sopenharmony_ci int32_t digestBlockLen; 35454aa6d63Sopenharmony_ci if (!digest.content.GetInt32(DIGEST_BLOCK_LEN_OFFSET, digestBlockLen)) { 35554aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("get digestBlockLen failed"); 35654aa6d63Sopenharmony_ci return false; 35754aa6d63Sopenharmony_ci } 35854aa6d63Sopenharmony_ci /* Algorithm ID */ 35954aa6d63Sopenharmony_ci if (!digest.content.GetInt32(DIGEST_ALGORITHM_OFFSET, digest.digestAlgorithm)) { 36054aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("get digestAlgorithm failed"); 36154aa6d63Sopenharmony_ci return false; 36254aa6d63Sopenharmony_ci } 36354aa6d63Sopenharmony_ci /* length of digest */ 36454aa6d63Sopenharmony_ci int32_t digestlen; 36554aa6d63Sopenharmony_ci if (!digest.content.GetInt32(DIGEST_LEN_OFFSET, digestlen)) { 36654aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("get digestlen failed"); 36754aa6d63Sopenharmony_ci return false; 36854aa6d63Sopenharmony_ci } 36954aa6d63Sopenharmony_ci int32_t sum = sizeof(digestlen) + sizeof(digest.digestAlgorithm) + digestlen; 37054aa6d63Sopenharmony_ci if (sum != digestBlockLen) { 37154aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("digestBlockLen: %d is not equal to sum: %d", 37254aa6d63Sopenharmony_ci digestBlockLen, sum); 37354aa6d63Sopenharmony_ci return false; 37454aa6d63Sopenharmony_ci } 37554aa6d63Sopenharmony_ci /* set position to the digest start point */ 37654aa6d63Sopenharmony_ci digest.content.SetPosition(DIGEST_OFFSET_IN_CONTENT); 37754aa6d63Sopenharmony_ci /* set limit to the digest end point */ 37854aa6d63Sopenharmony_ci digest.content.SetLimit(DIGEST_OFFSET_IN_CONTENT + digestlen); 37954aa6d63Sopenharmony_ci digest.content.Slice(); 38054aa6d63Sopenharmony_ci return true; 38154aa6d63Sopenharmony_ci} 38254aa6d63Sopenharmony_ci 38354aa6d63Sopenharmony_ciint32_t VerifyHap::WriteVerifyOutput(Pkcs7Context& pkcs7Context, std::vector<int8_t>& profile, Options* options) 38454aa6d63Sopenharmony_ci{ 38554aa6d63Sopenharmony_ci if (pkcs7Context.certChain.size() > 0) { 38654aa6d63Sopenharmony_ci bool flag = VerifyHap::HapOutPutCertChain(pkcs7Context.certChain[0], 38754aa6d63Sopenharmony_ci options->GetString(Options::OUT_CERT_CHAIN)); 38854aa6d63Sopenharmony_ci if (!flag) { 38954aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("out put cert chain failed"); 39054aa6d63Sopenharmony_ci return IO_ERROR; 39154aa6d63Sopenharmony_ci } 39254aa6d63Sopenharmony_ci } 39354aa6d63Sopenharmony_ci if (pkcs7Context.p7 == nullptr) { 39454aa6d63Sopenharmony_ci std::string p7bContent(profile.begin(), profile.end()); 39554aa6d63Sopenharmony_ci bool writeFlag = FileUtils::Write(p7bContent, options->GetString(Options::OUT_PROFILE)) < 0; 39654aa6d63Sopenharmony_ci if (writeFlag) { 39754aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("p7b write to file falied!\n"); 39854aa6d63Sopenharmony_ci return IO_ERROR; 39954aa6d63Sopenharmony_ci } 40054aa6d63Sopenharmony_ci return RET_OK; 40154aa6d63Sopenharmony_ci } 40254aa6d63Sopenharmony_ci bool pkcs7flag = VerifyHap::HapOutPutPkcs7(pkcs7Context.p7, options->GetString(Options::OUT_PROFILE)); 40354aa6d63Sopenharmony_ci if (!pkcs7flag) { 40454aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("out put p7b failed"); 40554aa6d63Sopenharmony_ci return IO_ERROR; 40654aa6d63Sopenharmony_ci } 40754aa6d63Sopenharmony_ci return RET_OK; 40854aa6d63Sopenharmony_ci} 40954aa6d63Sopenharmony_ci 41054aa6d63Sopenharmony_cibool VerifyHap::PrintCertChainToCmd(std::vector<X509*>& certChain) 41154aa6d63Sopenharmony_ci{ 41254aa6d63Sopenharmony_ci BIO* outFd = BIO_new_fp(stdout, BIO_NOCLOSE); 41354aa6d63Sopenharmony_ci if (!outFd) { 41454aa6d63Sopenharmony_ci PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "The stdout stream may have errors"); 41554aa6d63Sopenharmony_ci return false; 41654aa6d63Sopenharmony_ci } 41754aa6d63Sopenharmony_ci uint64_t format = XN_FLAG_SEP_COMMA_PLUS; // Print according to RFC2253 41854aa6d63Sopenharmony_ci uint64_t content = X509_FLAG_NO_EXTENSIONS | X509_FLAG_NO_ATTRIBUTES | X509_FLAG_NO_HEADER | X509_FLAG_NO_SIGDUMP; 41954aa6d63Sopenharmony_ci int num = 0; 42054aa6d63Sopenharmony_ci for (auto& cert : certChain) { 42154aa6d63Sopenharmony_ci PrintMsg("+++++++++++++++++++++++++++++++++certificate #" + std::to_string(num) + 42254aa6d63Sopenharmony_ci "+++++++++++++++++++++++++++++++++++++"); 42354aa6d63Sopenharmony_ci if (!X509_print_ex(outFd, cert, format, content)) { 42454aa6d63Sopenharmony_ci VerifyHapOpensslUtils::GetOpensslErrorMessage(); 42554aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("print x509 cert to cmd failed"); 42654aa6d63Sopenharmony_ci BIO_free(outFd); 42754aa6d63Sopenharmony_ci return false; 42854aa6d63Sopenharmony_ci } 42954aa6d63Sopenharmony_ci ++num; 43054aa6d63Sopenharmony_ci } 43154aa6d63Sopenharmony_ci BIO_free(outFd); 43254aa6d63Sopenharmony_ci return true; 43354aa6d63Sopenharmony_ci} 43454aa6d63Sopenharmony_ci} // namespace SignatureTools 43554aa6d63Sopenharmony_ci} // namespace OHOS