LLeonShufor upload
c10db38f创建于 19 天前历史提交
/*

 * 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 "pkg_upgradefile.h"

#include <cerrno>

#include <cstdio>

#include <cstring>

#include <ctime>

#include <limits>

#include <memory>

#include "dump.h"

#include "log/log.h"

#include "openssl_util.h"

#include "pkg_verify_util.h"

#include "pkg_lz4file.h"

#include "pkg_manager.h"

#include "pkg_pkgfile.h"

#include "pkg_stream.h"

#include "pkg_utils.h"

#include "pkg_zipfile.h"

#include "securec.h"

#include "utils.h"

#include "updater/updater_const.h"



#define TLV_CHECK_AND_RETURN(tlv, tlvType, len, fileLen)                                         \

    do {                                                                                         \

        if (!((tlv)->length < (fileLen) && (tlv)->length >= (len) && (tlv)->type == (tlvType) && \

              ((tlv)->length + sizeof(PkgTlv)) < (fileLen))) {                                   \

            PKG_LOGE("Invalid tlv type: %d length %u ", tlvType, ((tlv)->length));               \

            return PKG_INVALID_FILE;                                                             \

        }                                                                                        \

    } while (0)



using namespace std;



namespace Hpackage {

constexpr int32_t UPGRADE_FILE_HEADER_LEN = 3 * sizeof(PkgTlv) + sizeof(UpgradePkgHeader) + sizeof(UpgradePkgTime);

constexpr int32_t UPGRADE_FILE_BASIC_LEN = 2 * sizeof(PkgTlv) + sizeof(UpgradePkgHeader) + sizeof(UpgradePkgTime);

constexpr int32_t HASH_TLV_SIZE = 6;

constexpr int16_t TLV_TYPE_FOR_HASH_HEADER = 0x0006;

constexpr int16_t TLV_TYPE_FOR_HASH_DATA = 0x0007;

constexpr int16_t TLV_TYPE_FOR_SIGN = 0x0008;

constexpr int32_t UPGRADE_RESERVE_LEN = 16;

constexpr int16_t TLV_TYPE_FOR_SHA256 = 0x0001;

constexpr int16_t TLV_TYPE_FOR_SHA384 = 0x0011;

constexpr size_t BUFFER_SIZE = 4 * 1024 * 1024;



// chunk tlv type

using ChunkListInfoTlv = ChunkTlv<uint16_t, uint32_t, 0x10>;

using ParitionNumChunkTlv = ChunkTlv<uint16_t, uint16_t, 0x16>;

using HashParitionChunkTlv = ChunkTlv<uint16_t, uint16_t, 0x17>;

using ImageHashChunkTlv = ChunkTlv<uint16_t, uint16_t, 0x18>;

using ImageSizeChunkTlv = ChunkTlv<uint16_t, uint16_t, 0x19>;

using ParitionNameChunkTlv = ChunkTlv<uint16_t, uint16_t, 0x20>;



int32_t UpgradeFileEntry::Init(const PkgManager::FileInfoPtr fileInfo, PkgStreamPtr inStream)

{

    int32_t ret = PkgEntry::Init(&fileInfo_.fileInfo, fileInfo, inStream);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("Fail to check input param");

        return PKG_INVALID_PARAM;

    }

    ComponentInfo *info = (ComponentInfo *)fileInfo;

    if (info != nullptr) {

        fileInfo_.version = info->version;

        fileInfo_.id = info->id;

        fileInfo_.resType = info->resType;

        fileInfo_.type = info->type;

        fileInfo_.compFlags = info->compFlags;

        fileInfo_.originalSize = info->originalSize;

        if (memcpy_s(fileInfo_.digest, sizeof(fileInfo_.digest), info->digest, sizeof(info->digest)) != EOK) {

            PKG_LOGE("UpgradeFileEntry memcpy failed");

            return PKG_NONE_MEMORY;

        }

    }

    return PKG_SUCCESS;

}



size_t UpgradePkgFile::GetUpgradeSignatureLen() const

{

    return SIGN_SHA256_LEN + SIGN_SHA384_LEN;

}



size_t UpgradePkgFile::GetDigestLen() const

{

    return DigestAlgorithm::GetDigestLen(pkgInfo_.pkgInfo.digestMethod);

}



int32_t UpgradePkgFile::GetEntryOffset(size_t &dataOffset, const PkgManager::FileInfoPtr file)

{

    if (!CheckState({PKG_FILE_STATE_IDLE, PKG_FILE_STATE_WORKING}, PKG_FILE_STATE_WORKING)) {

        PKG_LOGE("error state curr %d ", state_);

        return PKG_INVALID_STATE;

    }

    if (pkgEntryMapId_.size() >= pkgInfo_.pkgInfo.entryCount) {

        PKG_LOGE("More entry for and for %s %zu", file->identity.c_str(), pkgEntryMapId_.size());

        return PKG_INVALID_PARAM;

    }

    PKG_LOGI("Add file %s to package", file->identity.c_str());

    size_t compDataLen = 0;

    for (auto &it : pkgEntryMapId_) {

        compDataLen += (*it.second).GetFileInfo()->packedSize;

    }

    dataOffset = UPGRADE_FILE_HEADER_LEN + pkgInfo_.pkgInfo.entryCount * sizeof(UpgradeCompInfo);

    dataOffset += UPGRADE_RESERVE_LEN + GetUpgradeSignatureLen();

    dataOffset += compDataLen;



    return PKG_SUCCESS;

}



int32_t UpgradePkgFile::AddEntry(const PkgManager::FileInfoPtr file, const PkgStreamPtr inStream)

{

    if (file == nullptr || inStream == nullptr) {

        PKG_LOGE("Fail to check input param");

        return PKG_INVALID_PARAM;

    }

    size_t dataOffset = 0;



    int32_t ret = GetEntryOffset(dataOffset, file);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("Fail to GetEntryOffset");

        return ret;

    }



    UpgradeFileEntry *entry = static_cast<UpgradeFileEntry *>(AddPkgEntry(file->identity));

    if (entry == nullptr) {

        PKG_LOGE("Fail create pkg node for %s", file->identity.c_str());

        return PKG_NONE_MEMORY;

    }

    ret = entry->Init(file, inStream);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("Fail init entry for %s", file->identity.c_str());

        return ret;

    }



    size_t encodeLen = 0;

    ret = entry->Pack(inStream, dataOffset, encodeLen);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("Fail Pack for %s", file->identity.c_str());

        return ret;

    }

    packedFileSize_ += encodeLen;



    size_t offset = UPGRADE_FILE_HEADER_LEN + (pkgEntryMapId_.size() - 1) * sizeof(UpgradeCompInfo);

    ret = entry->EncodeHeader(inStream, offset, encodeLen);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("Fail encode header for %s", file->identity.c_str());

        return ret;

    }



    PKG_LOGI("Header offset:%zu data offset:%zu packedFileSize: %zu", offset, dataOffset, packedFileSize_);

    return PKG_SUCCESS;

}



int32_t UpgradePkgFile::CheckPackageHeader(std::vector<uint8_t> &buffer, size_t &offset)

{

    if (!CheckState({PKG_FILE_STATE_WORKING}, PKG_FILE_STATE_CLOSE)) {

        PKG_LOGE("error state curr %d ", state_);

        return PKG_INVALID_STATE;

    }

    WriteLE16(buffer.data(), GetPackageTlvType()); // Type is 1 for package header in TLV format

    WriteLE16(buffer.data() + sizeof(uint16_t), sizeof(UpgradePkgHeader));

    offset += sizeof(PkgTlv);

    UpgradePkgHeader *header = reinterpret_cast<UpgradePkgHeader *>(buffer.data() + offset);

    if (header == nullptr) {

        PKG_LOGE("Fail to create header");

        return PKG_NONE_MEMORY;

    }

    header->pkgInfoLength = sizeof(PkgTlv) + sizeof(PkgTlv) + sizeof(PkgTlv) + sizeof(UpgradePkgHeader) +

        sizeof(UpgradePkgTime) + pkgInfo_.pkgInfo.entryCount * sizeof(UpgradeCompInfo) + UPGRADE_RESERVE_LEN;

    WriteLE32(reinterpret_cast<uint8_t *>(&header->updateFileVersion), pkgInfo_.updateFileVersion);

    int32_t ret = memcpy_s(header->softwareVersion, sizeof(header->softwareVersion), pkgInfo_.softwareVersion.data(),

        pkgInfo_.softwareVersion.size());

    if (ret != EOK) {

        PKG_LOGE("Fail to memcpy_s %s ret: %d", pkgStream_->GetFileName().c_str(), ret);

        return ret;

    }

    ret = memcpy_s(header->productUpdateId, sizeof(header->productUpdateId), pkgInfo_.productUpdateId.data(),

        pkgInfo_.productUpdateId.size());

    if (ret != EOK) {

        PKG_LOGE("Fail to memcpy_s %s ret: %d", pkgStream_->GetFileName().c_str(), ret);

        return ret;

    }

    offset += sizeof(UpgradePkgHeader);

    // 时间tlv

    WriteLE16(buffer.data() + offset, 0x02); // Type is 2 for time in TLV format

    WriteLE16(buffer.data() + offset + sizeof(uint16_t), sizeof(UpgradePkgTime));

    offset += sizeof(PkgTlv);

    return PKG_SUCCESS;

}



int32_t UpgradePkgFile::WriteBuffer(std::vector<uint8_t> &buffer, size_t &offset, size_t &signOffset)

{

    offset += pkgInfo_.pkgInfo.entryCount * sizeof(UpgradeCompInfo);

    signOffset = offset + UPGRADE_RESERVE_LEN;



    buffer.assign(buffer.capacity(), 0);

    size_t nameLen = 0;

    int32_t ret = PkgFileImpl::ConvertStringToBuffer(

        pkgInfo_.descriptPackageId, {buffer.data(), UPGRADE_RESERVE_LEN}, nameLen);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("Fail write descriptPackageId");

        return ret;

    }

    ret = pkgStream_->Write(buffer, GetUpgradeSignatureLen() + UPGRADE_RESERVE_LEN, offset);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("Fail write sign for %s", pkgStream_->GetFileName().c_str());

        return ret;

    }

    PKG_LOGI("SavePackage success file length: %zu signOffset %zu", pkgStream_->GetFileLength(), signOffset);

    pkgStream_->Flush(offset);

    return PKG_SUCCESS;

}



int32_t UpgradePkgFile::SavePackage(size_t &signOffset)

{

    PKG_LOGI("SavePackage %s", pkgStream_->GetFileName().c_str());



    // Allocate buffer size with max possible size

    size_t buffSize = GetUpgradeSignatureLen() + UPGRADE_RESERVE_LEN;

    buffSize = ((buffSize < UPGRADE_FILE_HEADER_LEN) ? UPGRADE_FILE_HEADER_LEN : buffSize);

    std::vector<uint8_t> buffer(buffSize);



    size_t offset = 0;

    // Package header information

    int32_t ret = CheckPackageHeader(buffer, offset);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("Fail to CheckPackageHeader");

        return PKG_NONE_MEMORY;

    }



    UpgradePkgTime *time = reinterpret_cast<UpgradePkgTime *>(buffer.data() + offset);

    ret = memcpy_s(time->date, sizeof(time->date), pkgInfo_.date.data(), pkgInfo_.date.size());

    if (ret != EOK) {

        PKG_LOGE("Fail to memcpy_s %s ret: %d", pkgStream_->GetFileName().c_str(), ret);

        return PKG_NONE_MEMORY;

    }

    ret = memcpy_s(time->time, sizeof(time->time), pkgInfo_.time.data(), pkgInfo_.time.size());

    if (ret != EOK) {

        PKG_LOGE("Fail to memcpy_s %s ret: %d", pkgStream_->GetFileName().c_str(), ret);

        return PKG_NONE_MEMORY;

    }

    offset += sizeof(UpgradePkgTime);

    // 组件的tlv

    WriteLE16(buffer.data() + offset, 0x05); // Type is 5 for component in TLV format

    WriteLE16(buffer.data() + offset + sizeof(uint16_t), pkgInfo_.pkgInfo.entryCount * sizeof(UpgradeCompInfo));

    offset += sizeof(PkgTlv);

    ret = pkgStream_->Write(buffer, UPGRADE_FILE_HEADER_LEN, 0);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("Fail write upgrade file header for %s ret: %d", pkgStream_->GetFileName().c_str(), ret);

        return ret;

    }

    // Clear buffer and save signature information

    ret = WriteBuffer(buffer, offset, signOffset);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("Fail WriteBuffer");

        return ret;

    }

    return PKG_SUCCESS;

}



int32_t UpgradePkgFile::ReadSignData(std::vector<uint8_t> &signData,

    size_t &parsedLen, DigestAlgorithm::DigestAlgorithmPtr algorithm)

{

    Updater::UPDATER_INIT_RECORD;

    size_t readBytes = 0;

    size_t signLen = parsedLen;

    PkgBuffer buffer(HASH_TLV_SIZE);

    int32_t ret = pkgStream_->Read(buffer, parsedLen, buffer.length, readBytes);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("read sign data fail");

        UPDATER_LAST_WORD(ret, parsedLen);

        return ret;

    }

    parsedLen += buffer.length;

    uint16_t dataType = ReadLE16(buffer.buffer);

    uint32_t dataLen = ReadLE32(buffer.buffer + sizeof(uint16_t));

    if (dataType != TLV_TYPE_FOR_SIGN) {

        PKG_LOGE("Invalid tlv type: %hu length %u ", dataType, dataLen);

        UPDATER_LAST_WORD(ret, dataType);

        return PKG_INVALID_FILE;

    }



    PkgBuffer signBuf(dataLen);

    ret = pkgStream_->Read(signBuf, parsedLen, signBuf.length, readBytes);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("read hash data fail");

        UPDATER_LAST_WORD(ret, parsedLen);

        return ret;

    }

    parsedLen += signBuf.length;

    signData.resize(dataLen);

    signData.assign(signBuf.data.begin(), signBuf.data.end());



    // refresh component data offset

    signLen = parsedLen - signLen;

    for (auto &it : pkgEntryMapId_) {

        if (it.second != nullptr) {

            it.second->AddDataOffset(signLen);

        }

    }

    return PKG_SUCCESS;

}



int32_t UpgradePkgFile::ReadImgHashTLV(std::vector<uint8_t> &imgHashBuf, size_t &parsedLen,

                                       DigestAlgorithm::DigestAlgorithmPtr algorithm, uint32_t needType)

{

    Updater::UPDATER_INIT_RECORD;

    size_t readBytes = 0;

    PkgBuffer buffer(HASH_TLV_SIZE);

    int32_t ret = pkgStream_->Read(buffer, parsedLen, buffer.length, readBytes);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("read image hash header fail");

        UPDATER_LAST_WORD(ret, "read image hash header fail");

        return ret;

    }



    parsedLen += buffer.length;

    uint16_t type = ReadLE16(buffer.buffer);

    uint32_t len = ReadLE32(buffer.buffer + sizeof(uint16_t));

    if (type != needType) {

        PKG_LOGE("Invalid tlv type: %d length %u ", type, len);

        return PKG_INVALID_FILE;

    }

    algorithm->Update(buffer, buffer.length);

    imgHashBuf.insert(imgHashBuf.end(), buffer.data.begin(), buffer.data.end());



    PkgBuffer dataBuf(len);

    ret = pkgStream_->Read(dataBuf, parsedLen, dataBuf.length, readBytes);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("read hash data fail");

        UPDATER_LAST_WORD(ret, "read hash data fail");

        return ret;

    }

    parsedLen += dataBuf.length;

    algorithm->Update(dataBuf, dataBuf.length);

    imgHashBuf.insert(imgHashBuf.end(), dataBuf.data.begin(), dataBuf.data.end());

    return PKG_SUCCESS;

}



int32_t UpgradePkgFile::ReadChunkListInfo(size_t &parsedLen, DigestAlgorithm::DigestAlgorithmPtr algorithm)

{

    Updater::UPDATER_INIT_RECORD;

    PkgBuffer buffer {};

    if (ReadChunkTlv<ChunkListInfoTlv>(buffer, parsedLen, algorithm) != PKG_SUCCESS) {

        return PKG_INVALID_PKG_FORMAT;

    }

    chunkInfo_.chunkListCount = ReadLE32(buffer.buffer);

    chunkInfo_.chunkListSize = ReadLE64(buffer.buffer + sizeof(uint32_t));

    return PKG_SUCCESS;

}



int32_t UpgradePkgFile::ReadPartitionNumChunk(size_t &parsedLen, DigestAlgorithm::DigestAlgorithmPtr algorithm)

{

    Updater::UPDATER_INIT_RECORD;

    PkgBuffer buffer {};

    if (ReadChunkTlv<ParitionNumChunkTlv>(buffer, parsedLen, algorithm) != PKG_SUCCESS) {

        return PKG_INVALID_PKG_FORMAT;

    }

    if (buffer.Size() != sizeof(uint16_t)) {

        PKG_LOGE("paritionNum size invalid %zu", buffer.Size());

        UPDATER_LAST_WORD("paritionNum size invalid", buffer.Size());

        return PKG_INVALID_PKG_FORMAT;

    }

    chunkInfo_.partitionNum = ReadLE16(buffer.buffer);

    return PKG_SUCCESS;

}



int32_t UpgradePkgFile::ReadPartitionNameChunk(size_t &parsedLen,

    DigestAlgorithm::DigestAlgorithmPtr algorithm, std::string &paritionName)

{

    Updater::UPDATER_INIT_RECORD;

    PkgBuffer buffer {};

    if (ReadChunkTlv<ParitionNameChunkTlv>(buffer, parsedLen, algorithm) != PKG_SUCCESS) {

        return PKG_INVALID_PKG_FORMAT;

    }

    PkgFileImpl::ConvertBufferToString(paritionName, {buffer.buffer, buffer.length});

    return PKG_SUCCESS;

}



int32_t UpgradePkgFile::ReadImageSizeChunk(size_t &parsedLen,

    DigestAlgorithm::DigestAlgorithmPtr algorithm, uint64_t &imageSize)

{

    Updater::UPDATER_INIT_RECORD;

    PkgBuffer buffer {};

    if (ReadChunkTlv<ImageSizeChunkTlv>(buffer, parsedLen, algorithm) != PKG_SUCCESS) {

        return PKG_INVALID_PKG_FORMAT;

    }

    if (buffer.Size() != sizeof(uint64_t)) {

        PKG_LOGE("imageSize len invalid %zu", buffer.Size());

        UPDATER_LAST_WORD("imageSize len invalid", buffer.Size());

        return PKG_INVALID_PKG_FORMAT;

    }

    imageSize = ReadLE64(buffer.buffer);

    return PKG_SUCCESS;

}



int32_t UpgradePkgFile::ReadImageHashChunk(size_t &parsedLen,

    DigestAlgorithm::DigestAlgorithmPtr algorithm, std::string &imageHash)

{

    Updater::UPDATER_INIT_RECORD;

    PkgBuffer buffer {};

    if (ReadChunkTlv<ImageHashChunkTlv>(buffer, parsedLen, algorithm) != PKG_SUCCESS) {

        return PKG_INVALID_PKG_FORMAT;

    }

    PkgFileImpl::ConvertBufferToString(imageHash, {buffer.buffer, buffer.length});

    return PKG_SUCCESS;

}



int32_t UpgradePkgFile::ReadHashPartitionChunk(size_t &parsedLen,

    DigestAlgorithm::DigestAlgorithmPtr algorithm, std::string &hashParitionName)

{

    Updater::UPDATER_INIT_RECORD;

    PkgBuffer buffer {};

    if (ReadChunkTlv<HashParitionChunkTlv>(buffer, parsedLen, algorithm) != PKG_SUCCESS) {

        return PKG_INVALID_PKG_FORMAT;

    }

    PkgFileImpl::ConvertBufferToString(hashParitionName, {buffer.buffer, buffer.length});

    return PKG_SUCCESS;

}



int32_t UpgradePkgFile::ReadChunkInfo(size_t &parsedLen, DigestAlgorithm::DigestAlgorithmPtr algorithm)

{

    Updater::UPDATER_INIT_RECORD;

    if (pkgInfo_.updateFileVersion < UPGRADE_FILE_VERSION_V5 || pkgInfo_.updateFileType != UPGRADE_FILE_TYPE_STREAM) {

        PKG_LOGI("file version is %d, file type is %d, skip chunk info",

            pkgInfo_.updateFileVersion, pkgInfo_.updateFileType);

        return PKG_SUCCESS;

    }

    size_t beginParsedLen = parsedLen;

    if (ReadChunkListInfo(parsedLen, algorithm) != PKG_SUCCESS) {

        return PKG_INVALID_PKG_FORMAT;

    }

    if (ReadPartitionNumChunk(parsedLen, algorithm) != PKG_SUCCESS) {

        return PKG_INVALID_PKG_FORMAT;

    }

    for (int i = 0; i < chunkInfo_.partitionNum; ++i) {

        std::string paritionName;

        uint64_t imageSize = 0;

        if (ReadPartitionNameChunk(parsedLen, algorithm, paritionName) != PKG_SUCCESS ||

            ReadImageSizeChunk(parsedLen, algorithm, imageSize) != PKG_SUCCESS) {

            return PKG_INVALID_PKG_FORMAT;

        }

        paritionName.insert(0, "/");

        PKG_LOGI("image size info image: %s, %llu", paritionName.c_str(), imageSize);

        if (!chunkInfo_.imageSizeMap.emplace(paritionName, imageSize).second) {

            PKG_LOGE("image size map emplace failed %s %llu", paritionName.c_str(), imageSize);

            return PKG_INVALID_PKG_FORMAT;

        }

    }

    for (int i = 0; i < chunkInfo_.partitionNum; ++i) {

        std::string hashParitionName;

        std::string imageHash;

        if (ReadHashPartitionChunk(parsedLen, algorithm, hashParitionName) != PKG_SUCCESS ||

            ReadImageHashChunk(parsedLen, algorithm, imageHash) != PKG_SUCCESS) {

            return PKG_INVALID_PKG_FORMAT;

        }

        hashParitionName.insert(0, "/");

        if (!chunkInfo_.imageHashMap.emplace(hashParitionName, imageHash).second) {

            PKG_LOGE("image size map emplace failed %s %s", hashParitionName.c_str(), imageHash.c_str());

            return PKG_INVALID_PKG_FORMAT;

        }

    }

    // refresh component data offset

    for (auto &it : pkgEntryMapId_) {

        it.second->AddDataOffset(parsedLen - beginParsedLen);

    }

    return PKG_SUCCESS;

}



int32_t UpgradePkgFile::ReadImgHashData(size_t &parsedLen, DigestAlgorithm::DigestAlgorithmPtr algorithm)

{

    Updater::UPDATER_INIT_RECORD;

#ifndef DIFF_PATCH_SDK

    if ((!Updater::Utils::CheckUpdateMode(Updater::SDCARD_MODE) &&

        !Updater::Utils::CheckUpdateMode(Updater::USB_MODE) &&

        !Updater::Utils::CheckUpdateMode(Updater::SDCARD_INTRAL_MODE)) ||

        pkgInfo_.updateFileVersion < UPGRADE_FILE_VERSION_V2 ||

        Updater::Utils::CheckUpdateMode(Updater::TOB_PKG_TAG)) {

        PKG_LOGI("ignore image hash check");

        return PKG_SUCCESS;

    }

#endif



    std::vector<uint8_t> imgHashBuf;

    // read hash header

    int32_t ret = ReadImgHashTLV(imgHashBuf, parsedLen, algorithm, TLV_TYPE_FOR_HASH_HEADER);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("read image hash info fail");

        UPDATER_LAST_WORD(ret, "read image hash info fail");

        return ret;

    }



    // read hash data

    ret = ReadImgHashTLV(imgHashBuf, parsedLen, algorithm, TLV_TYPE_FOR_HASH_DATA);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("read image hash data fail");

        UPDATER_LAST_WORD(ret, "read image hash data fail");

        return ret;

    }



    // refresh component data offset

    for (auto &it : pkgEntryMapId_) {

        it.second->AddDataOffset(imgHashBuf.size());

    }



#ifndef DIFF_PATCH_SDK

    if (pkgInfo_.updateFileVersion >= UPGRADE_FILE_VERSION_V3) {

        hashCheck_ = LoadImgHashDataNew(imgHashBuf.data(), imgHashBuf.size());

    } else {

        hashCheck_ = LoadImgHashData(imgHashBuf.data(), imgHashBuf.size());

    }

    if (hashCheck_ == nullptr) {

        PKG_LOGE("pause hash data fail");

        return PKG_INVALID_FILE;

    }

#endif



    return PKG_SUCCESS;

}



int32_t UpgradePkgFile::ReadPackageInfo(std::vector<uint8_t> &signData, size_t &parsedLen,

    DigestAlgorithm::DigestAlgorithmPtr algorithm)

{

    Updater::UPDATER_INIT_RECORD;

    PkgBuffer buffer(GetUpgradeSignatureLen() + UPGRADE_RESERVE_LEN);

    size_t readBytes = 0;

    int32_t ret = pkgStream_->Read(buffer, parsedLen, buffer.length, readBytes);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("read sign data fail");

        UPDATER_LAST_WORD(ret, "read sign data fail");

        return ret;

    }



    PkgFileImpl::ConvertBufferToString(pkgInfo_.descriptPackageId, {buffer.buffer, UPGRADE_RESERVE_LEN});

    if (pkgInfo_.pkgInfo.digestMethod == PKG_DIGEST_TYPE_SHA384) {

        signData.resize(SIGN_SHA384_LEN);

        ret = memcpy_s(signData.data(), signData.size(),

            buffer.buffer + UPGRADE_RESERVE_LEN + SIGN_SHA256_LEN, SIGN_SHA384_LEN);

    } else {

        signData.resize(SIGN_SHA256_LEN);

        ret = memcpy_s(signData.data(), signData.size(), buffer.buffer + UPGRADE_RESERVE_LEN, SIGN_SHA256_LEN);

    }

    if (ret != EOK) {

        PKG_LOGE("memcpy sign data fail");

        UPDATER_LAST_WORD(PKG_NONE_MEMORY, "memcpy sign data fail");

        return PKG_NONE_MEMORY;

    }



    // refresh component data offset

    for (auto &it : pkgEntryMapId_) {

        if (it.second != nullptr) {

            it.second->AddDataOffset(GetUpgradeSignatureLen());

        }

    }



    ret = memset_s(buffer.buffer + UPGRADE_RESERVE_LEN, buffer.length - UPGRADE_RESERVE_LEN,

        0, GetUpgradeSignatureLen());

    if (ret != EOK) {

        PKG_LOGE("memset buff fail");

        UPDATER_LAST_WORD(PKG_NONE_MEMORY, "memset buff fail");

        return PKG_NONE_MEMORY;

    }

    algorithm->Update(buffer, UPGRADE_RESERVE_LEN + GetUpgradeSignatureLen());

    parsedLen += UPGRADE_RESERVE_LEN + GetUpgradeSignatureLen();

    return PKG_SUCCESS;

}



int32_t UpgradePkgFile::LoadPackage(std::vector<std::string> &fileNames, VerifyFunction verifier)

{

    Updater::UPDATER_INIT_RECORD;

    if (verifier == nullptr) {

        PKG_LOGE("Check verifier nullptr");

        UPDATER_LAST_WORD(PKG_INVALID_SIGNATURE, "Check verifier nullptr");

        return PKG_INVALID_SIGNATURE;

    }

    if (!CheckState({PKG_FILE_STATE_IDLE}, PKG_FILE_STATE_WORKING)) {

        PKG_LOGE("error state curr %d ", state_);

        UPDATER_LAST_WORD(PKG_INVALID_STATE, "error state curr");

        return PKG_INVALID_STATE;

    }

    PKG_LOGI("LoadPackage %s ", pkgStream_->GetFileName().c_str());

    size_t fileLen = pkgStream_->GetFileLength();

    // Allocate buffer with smallest package size

    size_t buffSize = UPGRADE_FILE_HEADER_LEN + sizeof(UpgradeCompInfo) +

        GetUpgradeSignatureLen() + UPGRADE_RESERVE_LEN;

    if (fileLen < buffSize) {

        PKG_LOGE("Invalid file %s fileLen:%zu ", pkgStream_->GetFileName().c_str(), fileLen);

        UPDATER_LAST_WORD(PKG_INVALID_STATE, "Invalid file " + pkgStream_->GetFileName(), fileLen);

        return PKG_INVALID_FILE;

    }



    DigestAlgorithm::DigestAlgorithmPtr algorithm = nullptr;

    // Parse header

    size_t parsedLen = 0;

    int32_t ret = ReadUpgradePkgHeader(parsedLen, algorithm);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("Decode header fail %d", ret);

        UPDATER_LAST_WORD(ret, "Decode header fail");

        return ret;

    }



    ret = ReadComponents(parsedLen, algorithm, fileNames);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("Decode components fail %d", ret);

        UPDATER_LAST_WORD(ret, "Decode components fail");

        return ret;

    }

    ret = ReadChunkInfo(parsedLen, algorithm);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("read chunkinfo fail %d", ret);

        UPDATER_LAST_WORD(ret, "read chunkinfo fail");

        return ret;

    }

    ret = VerifyFile(parsedLen, algorithm, verifier);

    pkgInfo_.pkgInfo.updateFileHeadLen = parsedLen;

    return ret;

}



int32_t UpgradePkgFile::VerifyFile(size_t &parsedLen, DigestAlgorithm::DigestAlgorithmPtr algorithm,

                                   VerifyFunction verifier)

{

    if (pkgInfo_.updateFileVersion >= UPGRADE_FILE_VERSION_V2) {

        return VerifyFileV2(parsedLen, algorithm, verifier);

    }



    return VerifyFileV1(parsedLen, algorithm, verifier);

}



int32_t UpgradePkgFile::VerifyFileV1(size_t &parsedLen, DigestAlgorithm::DigestAlgorithmPtr algorithm,

                                     VerifyFunction verifier)

{

    std::vector<uint8_t> signData;

    // Read signature information

    int32_t ret = ReadPackageInfo(signData, parsedLen, algorithm);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("ReadPackageInfo fail %d", ret);

        return ret;

    }

    // Calculate digest and verify

    return Verify(parsedLen, algorithm, verifier, signData);

}



int32_t UpgradePkgFile::VerifyFileV2(size_t &parsedLen, DigestAlgorithm::DigestAlgorithmPtr algorithm,

                                     VerifyFunction verifier)

{

    int32_t ret = ReadReserveData(parsedLen, algorithm);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("ReadReserveData fail %d", ret);

        return ret;

    }



    // Read image hash information

    ret = ReadImgHashData(parsedLen, algorithm);

    if (ret != PKG_SUCCESS) {

        PKG_LOGW("LoadImgHashData fail %d, ignore image hash check", ret);

        return ret;

    }



    // Read signature information

    std::vector<uint8_t> signData;

    ret = ReadSignData(signData, parsedLen, algorithm);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("ReadSignData fail %d", ret);

        return ret;

    }

    return VerifyHeader(algorithm, verifier, signData);

}



int32_t UpgradePkgFile::Verify(size_t start, DigestAlgorithm::DigestAlgorithmPtr algorithm,

    VerifyFunction verifier, const std::vector<uint8_t> &signData)

{

    Updater::UPDATER_INIT_RECORD;

    int ret = 0;

    size_t buffSize = BUFFER_SIZE;

    size_t offset = start;

    size_t readBytes = 0;

    PkgBuffer buffer(buffSize);



    while (offset + readBytes < pkgStream_->GetFileLength()) {

        offset += readBytes;

        readBytes = 0;

        size_t remainBytes = pkgStream_->GetFileLength() - offset;

        remainBytes = ((remainBytes > buffSize) ? buffSize : remainBytes);

        ret = pkgStream_->Read(buffer, offset, remainBytes, readBytes);

        if (ret != PKG_SUCCESS) {

            PKG_LOGE("Fail to read data ");

            UPDATER_LAST_WORD(ret, "Fail to read data ");

            return ret;

        }

        algorithm->Update(buffer, readBytes);

        pkgManager_->PostDecodeProgress(POST_TYPE_VERIFY_PKG, remainBytes, nullptr);

    }



    PkgBuffer digest(GetDigestLen());

    algorithm->Final(digest);

    ret = verifier(&pkgInfo_.pkgInfo, digest.data, signData);

    if (ret != 0) {

        PKG_LOGE("Fail to verifier signature");

        UPDATER_LAST_WORD(PKG_INVALID_SIGNATURE, "Fail to verifier signature");

        return PKG_INVALID_SIGNATURE;

    }

    return 0;

}



int32_t UpgradePkgFile::VerifyHeader(DigestAlgorithm::DigestAlgorithmPtr algorithm,

    VerifyFunction verifier, const std::vector<uint8_t> &signData)

{

    Updater::UPDATER_INIT_RECORD;

    PkgBuffer digest(GetDigestLen());

    algorithm->Final(digest);

    int ret = 0;

    if (pkgInfo_.updateFileVersion >= UPGRADE_FILE_VERSION_V4) {

        auto signature = signData;

        PkgVerifyUtil pkgVerifyUtil;

        ret = pkgVerifyUtil.VerifySign(signature, digest.data);

    } else {

        ret = verifier(&pkgInfo_.pkgInfo, digest.data, signData);

    }

    if (ret != 0) {

        PKG_LOGE("Fail to verifier signature");

        UPDATER_LAST_WORD(PKG_INVALID_SIGNATURE);

        return PKG_INVALID_SIGNATURE;

    }

    return 0;

}



int32_t UpgradePkgFile::SetUpradeEntryStream(UpgradeFileEntry *entry)

{

    if (entry == nullptr || pkgStream_ == nullptr) {

        PKG_LOGE("entry or stream is null");

        return PKG_INVALID_PARAM;

    }

    entry->SetEntryPkgStream(pkgStream_);

    return PKG_SUCCESS;

}



int32_t UpgradePkgFile::SaveEntry(const PkgBuffer &buffer, size_t &parsedLen, UpgradeParam &info,

    DigestAlgorithm::DigestAlgorithmPtr algorithm, std::vector<std::string> &fileNames)

{

    UpgradeFileEntry *entry = new (std::nothrow) UpgradeFileEntry(this, nodeId_++);

    if (entry == nullptr) {

        PKG_LOGE("Fail create upgrade node for %s", pkgStream_->GetFileName().c_str());

        return PKG_NONE_MEMORY;

    }



    // Extract header information from file

    size_t decodeLen = 0;

    PkgBuffer headerBuff(buffer.buffer + info.currLen, info.readLen - info.currLen);

    const size_t headerOffset = parsedLen + info.srcOffset;

    const size_t dataOffset = info.dataOffset;

    int32_t ret = entry->DecodeHeader(headerBuff, headerOffset, dataOffset, decodeLen);

    if (ret != PKG_SUCCESS) {

        delete entry;

        PKG_LOGE("Fail to decode header");

        return ret;

    }

    // Set entry stream

    if (SetUpradeEntryStream(entry) != PKG_SUCCESS) {

        delete entry;

        PKG_LOGE("Fail to set entry stream");

        return PKG_INVALID_PARAM;

    }

    // Save entry

    pkgEntryMapId_.insert(pair<uint32_t, PkgEntryPtr>(entry->GetNodeId(), entry));

    pkgEntryMapFileName_.insert(std::pair<std::string, PkgEntryPtr>(entry->GetFileName(), entry));

    fileNames.push_back(entry->GetFileName());

    components_.push_back(entry->GetFileName());

    PkgBuffer signBuffer(buffer.buffer + info.currLen, decodeLen);

    algorithm->Update(signBuffer, decodeLen); // Generate digest for components



    info.currLen += decodeLen;

    info.srcOffset += decodeLen;



    if (entry->GetFileInfo() == nullptr) {

        delete entry;

        PKG_LOGE("Failed to get file info");

        return PKG_INVALID_FILE;

    }



    info.dataOffset += entry->GetFileInfo()->packedSize;

    pkgInfo_.pkgInfo.entryCount++;

    PKG_LOGSEN(Updater::INFO) << "Component offset: " << headerOffset << " " << dataOffset << " packed "

        << entry->GetFileInfo()->packedSize << " unpacked " << entry->GetFileInfo()->unpackedSize

        << " " << entry->GetFileInfo()->identity.c_str();

    return PKG_SUCCESS;

}



int32_t UpgradePkgFile::ReadComponents(size_t &parsedLen,

    DigestAlgorithm::DigestAlgorithmPtr algorithm, std::vector<std::string> &fileNames)

{

    Updater::UPDATER_INIT_RECORD;

    UpgradeParam info;

    size_t fileLen = pkgStream_->GetFileLength();

    info.readLen = 0;

    PkgBuffer buffer(sizeof(PkgTlv));

    int32_t ret = pkgStream_->Read(buffer, parsedLen, buffer.length, info.readLen);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("Read component fail");

        UPDATER_LAST_WORD(ret, "Read component fail");

        return ret;

    }

    PkgTlv tlv;

    tlv.type = ReadLE16(buffer.buffer);

    tlv.length = ReadLE16(buffer.buffer + sizeof(uint16_t));

    TLV_CHECK_AND_RETURN(&tlv, 5, sizeof(UpgradeCompInfo), fileLen); // component type is 5

    algorithm->Update(buffer, sizeof(PkgTlv)); // tlv generate digest



    parsedLen += sizeof(PkgTlv);



    info.dataOffset = parsedLen + tlv.length + UPGRADE_RESERVE_LEN;

    info.srcOffset = 0;

    info.currLen = sizeof(PkgTlv);

    PkgBuffer compBuffer(sizeof(UpgradeCompInfo));

    while (info.srcOffset < tlv.length) {

        if (info.currLen + sizeof(UpgradeCompInfo) > info.readLen) {

            info.readLen = 0;

            ret = pkgStream_->Read(compBuffer, parsedLen + info.srcOffset, compBuffer.length, info.readLen);

            if (ret != PKG_SUCCESS) {

                PKG_LOGE("Fail to read data");

                UPDATER_LAST_WORD(ret, "Fail to read data");

                return ret;

            }

            info.currLen = 0;

        }

        ret = SaveEntry(compBuffer, parsedLen, info, algorithm, fileNames);

        if (ret != PKG_SUCCESS) {

            PKG_LOGE("SaveEntry");

            UPDATER_LAST_WORD(ret, "SaveEntry");

            return ret;

        }

    }

    parsedLen += info.srcOffset;

    return PKG_SUCCESS;

}



void UpgradePkgFile::ParsePkgHeaderToTlv(const PkgBuffer &buffer, size_t &currLen, PkgTlv &tlv)

{

    pkgInfo_.pkgInfo.pkgType = PkgFile::PKG_TYPE_UPGRADE;

    pkgInfo_.pkgInfo.signMethod = PKG_SIGN_METHOD_RSA;

    pkgInfo_.pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256;



    tlv.type = ReadLE16(buffer.buffer);

    tlv.length = ReadLE16(buffer.buffer + sizeof(uint16_t));

    if (tlv.type == TLV_TYPE_FOR_SHA384) {

        pkgInfo_.pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA384;

    }



    // Header information

    currLen = sizeof(PkgTlv);

    UpgradePkgHeader *header = reinterpret_cast<UpgradePkgHeader *>(buffer.buffer + currLen);

    pkgInfo_.updateFileVersion = ReadLE16(buffer.buffer + currLen + offsetof(UpgradePkgHeader, updateFileVersion));

    pkgInfo_.updateFileType = ReadLE16(buffer.buffer + currLen + offsetof(UpgradePkgHeader, updateFileType));

    PkgFileImpl::ConvertBufferToString(pkgInfo_.softwareVersion, {header->softwareVersion,

        sizeof(header->softwareVersion)});

    PkgFileImpl::ConvertBufferToString(pkgInfo_.productUpdateId, {header->productUpdateId,

        sizeof(header->productUpdateId)});

}



int32_t UpgradePkgFile::ReadReserveData(size_t &parsedLen, DigestAlgorithm::DigestAlgorithmPtr &algorithm)

{

    Updater::UPDATER_INIT_RECORD;

    size_t readBytes = 0;

    PkgBuffer reserve_buf(UPGRADE_RESERVE_LEN);

    int32_t ret = pkgStream_->Read(reserve_buf, parsedLen, reserve_buf.length, readBytes);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("read reserve data fail");

        UPDATER_LAST_WORD(ret);

        return ret;

    }

    PkgFileImpl::ConvertBufferToString(pkgInfo_.descriptPackageId, {reserve_buf.buffer, UPGRADE_RESERVE_LEN});

    algorithm->Update(reserve_buf, reserve_buf.length);

    parsedLen += reserve_buf.length;

    return PKG_SUCCESS;

}



int32_t UpgradePkgFile::ReadUpgradePkgHeader(size_t &realLen, DigestAlgorithm::DigestAlgorithmPtr &algorithm)

{

    Updater::UPDATER_INIT_RECORD;

    size_t fileLen = pkgStream_->GetFileLength();

    size_t readLen = 0;

    size_t currLen = 0;

    PkgTlv tlv;

    PkgBuffer buffer(UPGRADE_FILE_BASIC_LEN);

    int32_t ret = pkgStream_->Read(buffer, 0, buffer.length, readLen);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("Fail to read header");

        UPDATER_LAST_WORD(ret, "Fail to read header");

        return ret;

    }



    ParsePkgHeaderToTlv(buffer, currLen, tlv);

    algorithm = PkgAlgorithmFactory::GetDigestAlgorithm(pkgInfo_.pkgInfo.digestMethod);

    if (algorithm == nullptr) {

        PKG_LOGE("Invalid file %s", pkgStream_->GetFileName().c_str());

        UPDATER_LAST_WORD(PKG_NOT_EXIST_ALGORITHM, "invalid file " + pkgStream_->GetFileName());

        return PKG_NOT_EXIST_ALGORITHM;

    }

    algorithm->Init();



    if (currLen + tlv.length >= readLen) { // Extra TLV information, read it.

        realLen = currLen + tlv.length;

        algorithm->Update(buffer, realLen);

        ret = pkgStream_->Read(buffer, realLen, buffer.length, readLen);

        if (ret != PKG_SUCCESS) {

            PKG_LOGE("Fail to read header");

            UPDATER_LAST_WORD(ret, "Fail to read TLV");

            return ret;

        }

        currLen = 0;

    } else {

        currLen += tlv.length;

    }

    // Time information

    tlv.type = ReadLE16(buffer.buffer + currLen);

    tlv.length = ReadLE16(buffer.buffer + currLen + sizeof(uint16_t));

    TLV_CHECK_AND_RETURN(&tlv, sizeof(uint16_t), sizeof(UpgradePkgTime), fileLen);

    currLen += sizeof(PkgTlv);

    UpgradePkgTime *time = reinterpret_cast<UpgradePkgTime *>(buffer.buffer + currLen);

    PkgFileImpl::ConvertBufferToString(pkgInfo_.date, {time->date, sizeof(time->date)});

    PkgFileImpl::ConvertBufferToString(pkgInfo_.time, {time->time, sizeof(time->time)});

    currLen += tlv.length;

    realLen += currLen;



    // Parser header to get compressional algorithm

    algorithm->Update(buffer, currLen); // Generate digest

    return PKG_SUCCESS;

}



int32_t UpgradeFileEntry::GetUpGradeCompInfo(UpgradeCompInfo &comp)

{

    if (memset_s(&comp, sizeof(comp), 0, sizeof(comp)) != EOK) {

        PKG_LOGE("UpgradeFileEntry memset_s failed");

        return PKG_NONE_MEMORY;

    }

    size_t len = 0;

    int32_t ret = PkgFileImpl::ConvertStringToBuffer(

        fileInfo_.fileInfo.identity, {comp.address, sizeof(comp.address)}, len);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("outStream or inStream null for %s", fileName_.c_str());

        return PKG_INVALID_PARAM;

    }



    ret = PkgFileImpl::ConvertStringToBuffer(fileInfo_.version, {comp.version, sizeof(comp.version)}, len);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("outStream or inStream null for %s", fileName_.c_str());

        return PKG_INVALID_PARAM;

    }

    ret = memcpy_s(comp.digest, sizeof(comp.digest), fileInfo_.digest, sizeof(fileInfo_.digest));

    if (ret != EOK) {

        PKG_LOGE("Fail to memcpy_s ret: %d", ret);

        return ret;

    }

    return PKG_SUCCESS;

}



int32_t UpgradeFileEntry::EncodeHeader(PkgStreamPtr inStream, size_t startOffset, size_t &encodeLen)

{

    PkgStreamPtr outStream = pkgFile_->GetPkgStream();

    if (outStream == nullptr || inStream == nullptr) {

        PKG_LOGE("outStream or inStream null for %s", fileName_.c_str());

        return PKG_INVALID_PARAM;

    }



    UpgradeCompInfo comp;

    int ret = GetUpGradeCompInfo(comp);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("GetUpGradeCompInfo failed");

        return ret;

    }



    WriteLE32(reinterpret_cast<uint8_t *>(&comp.size), fileInfo_.fileInfo.unpackedSize);

    WriteLE16(reinterpret_cast<uint8_t *>(&comp.id), fileInfo_.id);

    WriteLE32(reinterpret_cast<uint8_t *>(&comp.originalSize), fileInfo_.originalSize);

    comp.resType = fileInfo_.resType;

    comp.flags = fileInfo_.compFlags;

    comp.type = fileInfo_.type;



    headerOffset_ = startOffset;

    PkgBuffer buffer(reinterpret_cast<uint8_t *>(&comp), sizeof(comp));

    ret = outStream->Write(buffer, sizeof(comp), startOffset);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("Fail write header for %s", fileName_.c_str());

        return ret;

    }

    encodeLen = sizeof(UpgradeCompInfo);



    PKG_LOGI("EncodeHeader startOffset: %zu %zu packedSize:%zu %zu ", headerOffset_, dataOffset_,

        fileInfo_.fileInfo.packedSize, fileInfo_.fileInfo.unpackedSize);

    return PKG_SUCCESS;

}



int32_t UpgradeFileEntry::Pack(PkgStreamPtr inStream, size_t startOffset, size_t &encodeLen)

{

    PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(&fileInfo_.fileInfo);

    PkgStreamPtr outStream = pkgFile_->GetPkgStream();

    if (algorithm == nullptr || outStream == nullptr || inStream == nullptr) {

        PKG_LOGE("outStream or inStream null for %s", fileName_.c_str());

        return PKG_INVALID_PARAM;

    }



    PkgAlgorithmContext context = {

        {0, startOffset},

        {fileInfo_.fileInfo.packedSize, fileInfo_.fileInfo.unpackedSize},

        0, fileInfo_.fileInfo.digestMethod

    };

    if (memcpy_s(context.digest, sizeof(context.digest), fileInfo_.digest, sizeof(fileInfo_.digest)) != EOK) {

        PKG_LOGE("UpgradeFileEntry pack memcpy failed");

        return PKG_NONE_MEMORY;

    }

    int32_t ret = algorithm->Pack(inStream, outStream, context);

    if (ret != PKG_SUCCESS) {

        PKG_LOGE("Fail Compress for %s", fileName_.c_str());

        return ret;

    }



    // Fill digest and compressed size of file

    if (memcpy_s(fileInfo_.digest, sizeof(fileInfo_.digest), context.digest, sizeof(context.digest)) != EOK) {

        PKG_LOGE("UpgradeFileEntry pack memcpy failed");

        return PKG_NONE_MEMORY;

    }

    fileInfo_.fileInfo.packedSize = context.packedSize;

    dataOffset_ = startOffset;

    encodeLen = fileInfo_.fileInfo.packedSize;

    PKG_LOGI("Pack start:%zu unpackSize:%zu packSize:%zu", startOffset, fileInfo_.fileInfo.unpackedSize,

        fileInfo_.fileInfo.packedSize);

    return PKG_SUCCESS;

}



int32_t UpgradeFileEntry::DecodeHeader(PkgBuffer &buffer, size_t headerOffset, size_t dataOffset,

    size_t &decodeLen)

{

    UpgradePkgFile *pkgFile = static_cast<UpgradePkgFile*>(GetPkgFile());

    if (pkgFile == nullptr) {

        PKG_LOGE("Get pkg file ptr fail");

        return PKG_INVALID_PARAM;

    }



    PkgStreamPtr inStream = pkgFile->GetPkgStream();

    if (inStream == nullptr) {

        PKG_LOGE("outStream or inStream null for %s", fileName_.c_str());

        return PKG_INVALID_PARAM;

    }

    if (buffer.length < sizeof(UpgradeCompInfo)) {

        PKG_LOGE("Fail to check buffer %zu", buffer.length);

        return PKG_INVALID_PKG_FORMAT;

    }



    UpgradeCompInfo *info = reinterpret_cast<UpgradeCompInfo *>(buffer.buffer);

    if (pkgFile->GetUpgradeFileVer() >= UPGRADE_FILE_VERSION_V3) {

        fileInfo_.fileInfo.packedSize = ReadLE64(buffer.buffer + offsetof(UpgradeCompInfo, size));

    } else {

        fileInfo_.fileInfo.packedSize = ReadLE32(buffer.buffer + offsetof(UpgradeCompInfo, size));

        fileInfo_.originalSize = ReadLE32(buffer.buffer + offsetof(UpgradeCompInfo, originalSize));

    }

    fileInfo_.fileInfo.unpackedSize = fileInfo_.fileInfo.packedSize;

    fileInfo_.fileInfo.packMethod = PKG_COMPRESS_METHOD_NONE;

    fileInfo_.fileInfo.digestMethod = PKG_DIGEST_TYPE_NONE;

    fileInfo_.fileInfo.resType = info->resType;

    PkgFileImpl::ConvertBufferToString(fileInfo_.fileInfo.identity, {info->address, sizeof(info->address)});

    PkgFileImpl::ConvertBufferToString(fileInfo_.version, {info->version, sizeof(info->version)});

    fileName_ = fileInfo_.fileInfo.identity;

    int32_t ret = memcpy_s(fileInfo_.digest, sizeof(fileInfo_.digest), info->digest, sizeof(info->digest));

    if (ret != EOK) {

        PKG_LOGE("Fail to memcpy_s ret: %d Component offset: %zu %zu packedSize:%zu %zu %s", ret, headerOffset,

            dataOffset, fileInfo_.fileInfo.packedSize, fileInfo_.fileInfo.unpackedSize, fileName_.c_str());

        return ret;

    }

    fileInfo_.id = ReadLE16(buffer.buffer + offsetof(UpgradeCompInfo, id));

    fileInfo_.resType = info->resType;

    fileInfo_.compFlags = info->flags;

    fileInfo_.type = info->type;

    fileInfo_.fileInfo.type = info->type;

    headerOffset_ = headerOffset;

    dataOffset_ = dataOffset;

    decodeLen = sizeof(UpgradeCompInfo);



    return PKG_SUCCESS;

}



int32_t UpgradeFileEntry::Unpack(PkgStreamPtr outStream)

{

    PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(&fileInfo_.fileInfo);

    if (algorithm == nullptr) {

        PKG_LOGE("can not algorithm for %s", fileName_.c_str());

        return PKG_INVALID_PARAM;

    }



    PkgStreamPtr inStream = pkgFile_->GetPkgEntryStream();

    if (outStream == nullptr || inStream == nullptr) {

        PKG_LOGE("outStream or inStream null for %s", fileName_.c_str());

        return PKG_INVALID_PARAM;

    }

    PkgAlgorithmContext context = {

        {this->dataOffset_, 0},

        {fileInfo_.fileInfo.packedSize, fileInfo_.fileInfo.unpackedSize},

        0, fileInfo_.fileInfo.digestMethod

    };

    int32_t ret = memcpy_s(context.digest, sizeof(context.digest), fileInfo_.digest, sizeof(fileInfo_.digest));

    if (ret != EOK) {

        PKG_LOGE("Fail to memcpy_s ret: %d", ret);

        return ret;

    }

    ret = algorithm->UnpackWithVerify(inStream, outStream, context,

        [this](PkgBuffer &buffer, size_t len, size_t offset) ->int32_t {

            return Verify(buffer, len, offset);

        });

    if (ret != PKG_SUCCESS) {

        PKG_LOGSEN(Updater::INFO) << "Fail Decompress for " << fileName_.c_str();

        return ret;

    }

    PKG_LOGSEN(Updater::INFO) << "Unpack " << fileName_.c_str() << " data offset:" << dataOffset_

        << " packedSize:" << fileInfo_.fileInfo.packedSize << " unpackedSize:" << fileInfo_.fileInfo.unpackedSize;

    outStream->Flush(fileInfo_.fileInfo.unpackedSize);

    return PKG_SUCCESS;

}



std::pair<size_t, size_t> UpgradeFileEntry::GetEntryRange(void)

{

    return {this->dataOffset_ + readOffset_, this->dataOffset_ + fileInfo_.fileInfo.packedSize};

}



size_t UpgradeFileEntry::GetOriginalSize() const

{

    UpgradePkgFile *pkgFile = static_cast<UpgradePkgFile*>(GetPkgFile());

    if (pkgFile == nullptr) {

        PKG_LOGE("pkg file is null");

        return 0;

    }

    const auto &chunkInfo = pkgFile->GetUpgradeChunkInfo();

    auto it = chunkInfo.imageSizeMap.find(fileName_);

    if (it != chunkInfo.imageSizeMap.end()) {

        PKG_LOGI("%s found in chunk info, return image size %zu", fileName_.c_str(), it->second);

        return it->second;

    }

    PKG_LOGI("%s not found in chunk info, return unpacked size %zu", fileName_.c_str(),

        fileInfo_.fileInfo.unpackedSize);

    return fileInfo_.fileInfo.unpackedSize;

}



int32_t UpgradeFileEntry::Verify(PkgBuffer &buffer, size_t len, size_t offset)

{

    UpgradePkgFile *pkgFile = static_cast<UpgradePkgFile*>(GetPkgFile());

    if (pkgFile == nullptr) {

        PKG_LOGE("Get pkg file ptr fail: %s", fileName_.c_str());

        return PKG_INVALID_PARAM;

    }



    if (pkgFile->GetImgHashData() == nullptr) {

        return PKG_SUCCESS;

    }



    PkgManager::StreamPtr stream = nullptr;

    int32_t ret = pkgFile->GetPkgMgr()->CreatePkgStream(stream, fileName_, buffer);

    if (stream == nullptr || ret != PKG_SUCCESS) {

        PKG_LOGE("Failed to create stream");

        return PKG_INVALID_PARAM;

    }



    std::vector<uint8_t> hashVal;

    ret = CalcSha256Digest(PkgStreamImpl::ConvertPkgStream(stream), len, hashVal);

    if (ret != 0) {

        PKG_LOGE("cal digest for pkg stream, buffer.length: %zu", buffer.length);

        return PKG_INVALID_PARAM;

    }

#ifndef DIFF_PATCH_SDK

    size_t end = offset + len - 1;

    bool checkRet = false;

    if (pkgFile->GetUpgradeFileVer() >= UPGRADE_FILE_VERSION_V3) {

        checkRet = CheckDataHashNew(pkgFile->GetImgHashData(), fileName_.c_str(),

                                    offset, end, hashVal.data(), hashVal.size());

    } else {

        std::string imgName = fileName_ + (fileNum_ == 0 ? "" : std::to_string(fileNum_));

        checkRet = check_data_hash(pkgFile->GetImgHashData(), imgName.c_str(),

                                   offset, end, hashVal.data(), hashVal.size());

    }

    if (!checkRet) {

        PKG_LOGE("check image hash value fail, name: %s, offset: %zu, end: %u", fileName_.c_str(), offset, end);

        return PKG_INVALID_PARAM;

    }

#endif

    return PKG_SUCCESS;

}



int16_t UpgradePkgFile::GetPackageTlvType()

{

    static int16_t packageTlvType[PKG_DIGEST_TYPE_MAX] = {

        TLV_TYPE_FOR_SHA256, TLV_TYPE_FOR_SHA256, TLV_TYPE_FOR_SHA256, TLV_TYPE_FOR_SHA384

    };

    if (pkgInfo_.pkgInfo.digestMethod < PKG_DIGEST_TYPE_MAX) {

        return packageTlvType[pkgInfo_.pkgInfo.digestMethod];

    }

    return TLV_TYPE_FOR_SHA256;

}

} // namespace Hpackage