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
1654aa6d63Sopenharmony_ci#include <fstream>
1754aa6d63Sopenharmony_ci#include <map>
1854aa6d63Sopenharmony_ci#include <cstdio>
1954aa6d63Sopenharmony_ci#include <cstdlib>
2054aa6d63Sopenharmony_ci
2154aa6d63Sopenharmony_ci#include "fs_digest_utils.h"
2254aa6d63Sopenharmony_ci#include "file_utils.h"
2354aa6d63Sopenharmony_ci#include "hash_utils.h"
2454aa6d63Sopenharmony_ci
2554aa6d63Sopenharmony_cinamespace OHOS {
2654aa6d63Sopenharmony_cinamespace SignatureTools {
2754aa6d63Sopenharmony_ci
2854aa6d63Sopenharmony_ciint HashUtils::GetHashAlgsId(const std::string& algMethod)
2954aa6d63Sopenharmony_ci{
3054aa6d63Sopenharmony_ci    int result = static_cast<int>(HashAlgs::USE_NONE);
3154aa6d63Sopenharmony_ci    if (0 == algMethod.compare("SHA-256")) {
3254aa6d63Sopenharmony_ci        result = static_cast<int>(HashAlgs::USE_SHA256);
3354aa6d63Sopenharmony_ci    }
3454aa6d63Sopenharmony_ci    if (0 == algMethod.compare("SHA-384")) {
3554aa6d63Sopenharmony_ci        result = static_cast<int>(HashAlgs::USE_SHA384);
3654aa6d63Sopenharmony_ci    }
3754aa6d63Sopenharmony_ci    if (0 == algMethod.compare("SHA-512")) {
3854aa6d63Sopenharmony_ci        result = static_cast<int>(HashAlgs::USE_SHA512);
3954aa6d63Sopenharmony_ci    }
4054aa6d63Sopenharmony_ci    return result;
4154aa6d63Sopenharmony_ci}
4254aa6d63Sopenharmony_ci
4354aa6d63Sopenharmony_cistd::string HashUtils::GetHashAlgName(int algId)
4454aa6d63Sopenharmony_ci{
4554aa6d63Sopenharmony_ci    if (static_cast<int>(HashAlgs::USE_SHA256) == algId) {
4654aa6d63Sopenharmony_ci        return "SHA-256";
4754aa6d63Sopenharmony_ci    }
4854aa6d63Sopenharmony_ci    if (static_cast<int>(HashAlgs::USE_SHA384) == algId) {
4954aa6d63Sopenharmony_ci        return "SHA-384";
5054aa6d63Sopenharmony_ci    }
5154aa6d63Sopenharmony_ci    if (static_cast<int>(HashAlgs::USE_SHA512) == algId) {
5254aa6d63Sopenharmony_ci        return "SHA-512";
5354aa6d63Sopenharmony_ci    }
5454aa6d63Sopenharmony_ci    return "";
5554aa6d63Sopenharmony_ci}
5654aa6d63Sopenharmony_ci
5754aa6d63Sopenharmony_cistd::vector<int8_t> HashUtils::GetFileDigest(const std::string& inputFile, const std::string& algName)
5854aa6d63Sopenharmony_ci{
5954aa6d63Sopenharmony_ci    std::vector<int8_t> result;
6054aa6d63Sopenharmony_ci
6154aa6d63Sopenharmony_ci    std::ifstream input(inputFile, std::ios::binary);
6254aa6d63Sopenharmony_ci    if (0 != input.rdstate()) {
6354aa6d63Sopenharmony_ci        PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "failed to get input stream object!");
6454aa6d63Sopenharmony_ci        return std::vector<int8_t>();
6554aa6d63Sopenharmony_ci    }
6654aa6d63Sopenharmony_ci
6754aa6d63Sopenharmony_ci    char buffer[HASH_LEN] = { 0 };
6854aa6d63Sopenharmony_ci    int num = 0;
6954aa6d63Sopenharmony_ci    std::map<int, std::vector<int8_t>> hashMap;
7054aa6d63Sopenharmony_ci
7154aa6d63Sopenharmony_ci    while (!input.eof()) {
7254aa6d63Sopenharmony_ci        input.read(buffer, HASH_LEN);
7354aa6d63Sopenharmony_ci
7454aa6d63Sopenharmony_ci        if (input.fail() && !input.eof()) {
7554aa6d63Sopenharmony_ci            PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "error occurred while reading data.");
7654aa6d63Sopenharmony_ci            return std::vector<int8_t>();
7754aa6d63Sopenharmony_ci        }
7854aa6d63Sopenharmony_ci
7954aa6d63Sopenharmony_ci        std::streamsize readLen = input.gcount();
8054aa6d63Sopenharmony_ci        std::string str;
8154aa6d63Sopenharmony_ci        for (int i = 0; i < readLen; ++i) {
8254aa6d63Sopenharmony_ci            str.push_back(buffer[i]);
8354aa6d63Sopenharmony_ci        }
8454aa6d63Sopenharmony_ci
8554aa6d63Sopenharmony_ci        std::vector<int8_t> dig = GetByteDigest(str, readLen, algName);
8654aa6d63Sopenharmony_ci        hashMap.emplace(num, dig);
8754aa6d63Sopenharmony_ci        ++num;
8854aa6d63Sopenharmony_ci    }
8954aa6d63Sopenharmony_ci
9054aa6d63Sopenharmony_ci    if (hashMap.empty()) {
9154aa6d63Sopenharmony_ci        PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "hashMap is empty.");
9254aa6d63Sopenharmony_ci        return std::vector<int8_t>();
9354aa6d63Sopenharmony_ci    }
9454aa6d63Sopenharmony_ci
9554aa6d63Sopenharmony_ci    DigestUtils fileDigestUtils(HASH_SHA256);
9654aa6d63Sopenharmony_ci    for (const auto& hashMapItem : hashMap) {
9754aa6d63Sopenharmony_ci        std::string str(hashMapItem.second.begin(), hashMapItem.second.end());
9854aa6d63Sopenharmony_ci        fileDigestUtils.AddData(str);
9954aa6d63Sopenharmony_ci    }
10054aa6d63Sopenharmony_ci    std::string digest = fileDigestUtils.Result(DigestUtils::Type::BINARY);
10154aa6d63Sopenharmony_ci    for (std::string::size_type i = 0; i < digest.size(); i++) {
10254aa6d63Sopenharmony_ci        result.push_back(digest[i]);
10354aa6d63Sopenharmony_ci    }
10454aa6d63Sopenharmony_ci    return result;
10554aa6d63Sopenharmony_ci}
10654aa6d63Sopenharmony_ci
10754aa6d63Sopenharmony_cistd::vector<int8_t> HashUtils::GetDigestFromBytes(const std::vector<int8_t>& fileBytes, int64_t length,
10854aa6d63Sopenharmony_ci                                                  const std::string& algName)
10954aa6d63Sopenharmony_ci{
11054aa6d63Sopenharmony_ci    if (fileBytes.empty() || length <= 0) {
11154aa6d63Sopenharmony_ci        PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "file bytes is empty.");
11254aa6d63Sopenharmony_ci        return std::vector<int8_t>();
11354aa6d63Sopenharmony_ci    }
11454aa6d63Sopenharmony_ci    std::map<int, std::vector<int8_t>> hashMap;
11554aa6d63Sopenharmony_ci    int64_t readLength = 0;
11654aa6d63Sopenharmony_ci    int64_t num = 0;
11754aa6d63Sopenharmony_ci    while (readLength < length) {
11854aa6d63Sopenharmony_ci        int64_t blockLength = length - readLength > HASH_LEN ? HASH_LEN : (length - readLength);
11954aa6d63Sopenharmony_ci        std::string readStr(fileBytes.begin() + readLength, fileBytes.begin() + readLength + blockLength);
12054aa6d63Sopenharmony_ci        std::vector<int8_t> dig = GetByteDigest(readStr, readStr.size(), algName);
12154aa6d63Sopenharmony_ci        hashMap.emplace(num, dig);
12254aa6d63Sopenharmony_ci        ++num;
12354aa6d63Sopenharmony_ci        readLength += readStr.size();
12454aa6d63Sopenharmony_ci    }
12554aa6d63Sopenharmony_ci    if (hashMap.empty()) {
12654aa6d63Sopenharmony_ci        PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "hashMap is empty.");
12754aa6d63Sopenharmony_ci        return std::vector<int8_t>();
12854aa6d63Sopenharmony_ci    }
12954aa6d63Sopenharmony_ci    DigestUtils digestUtils(HASH_SHA256);
13054aa6d63Sopenharmony_ci    for (const auto& item : hashMap) {
13154aa6d63Sopenharmony_ci        std::string str(item.second.begin(), item.second.end());
13254aa6d63Sopenharmony_ci        digestUtils.AddData(str);
13354aa6d63Sopenharmony_ci    }
13454aa6d63Sopenharmony_ci    std::string digest = digestUtils.Result(DigestUtils::Type::BINARY);
13554aa6d63Sopenharmony_ci    std::vector<int8_t> result;
13654aa6d63Sopenharmony_ci    for (std::string::size_type i = 0; i < digest.size(); i++) {
13754aa6d63Sopenharmony_ci        result.push_back(digest[i]);
13854aa6d63Sopenharmony_ci    }
13954aa6d63Sopenharmony_ci    return result;
14054aa6d63Sopenharmony_ci}
14154aa6d63Sopenharmony_ci
14254aa6d63Sopenharmony_cistd::vector<int8_t> HashUtils::GetByteDigest(const std::string& str, int count, const std::string& algMethod)
14354aa6d63Sopenharmony_ci{
14454aa6d63Sopenharmony_ci    std::vector<int8_t> result;
14554aa6d63Sopenharmony_ci    DigestUtils digestUtils(HASH_SHA256);
14654aa6d63Sopenharmony_ci    digestUtils.AddData(str);
14754aa6d63Sopenharmony_ci    std::string digest = digestUtils.Result(DigestUtils::Type::BINARY);
14854aa6d63Sopenharmony_ci    for (std::string::size_type i = 0; i < digest.size(); i++) {
14954aa6d63Sopenharmony_ci        result.push_back(digest[i]);
15054aa6d63Sopenharmony_ci    }
15154aa6d63Sopenharmony_ci    return result;
15254aa6d63Sopenharmony_ci}
15354aa6d63Sopenharmony_ci
15454aa6d63Sopenharmony_ci} // namespace SignatureTools
15554aa6d63Sopenharmony_ci} // namespace OHOS