1 /*
2 * Copyright (c) 2024-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <fstream>
17 #include <map>
18 #include <cstdio>
19 #include <cstdlib>
20
21 #include "fs_digest_utils.h"
22 #include "file_utils.h"
23 #include "hash_utils.h"
24
25 namespace OHOS {
26 namespace SignatureTools {
27
GetHashAlgsId(const std::string & algMethod)28 int HashUtils::GetHashAlgsId(const std::string& algMethod)
29 {
30 int result = static_cast<int>(HashAlgs::USE_NONE);
31 if (0 == algMethod.compare("SHA-256")) {
32 result = static_cast<int>(HashAlgs::USE_SHA256);
33 }
34 if (0 == algMethod.compare("SHA-384")) {
35 result = static_cast<int>(HashAlgs::USE_SHA384);
36 }
37 if (0 == algMethod.compare("SHA-512")) {
38 result = static_cast<int>(HashAlgs::USE_SHA512);
39 }
40 return result;
41 }
42
GetHashAlgName(int algId)43 std::string HashUtils::GetHashAlgName(int algId)
44 {
45 if (static_cast<int>(HashAlgs::USE_SHA256) == algId) {
46 return "SHA-256";
47 }
48 if (static_cast<int>(HashAlgs::USE_SHA384) == algId) {
49 return "SHA-384";
50 }
51 if (static_cast<int>(HashAlgs::USE_SHA512) == algId) {
52 return "SHA-512";
53 }
54 return "";
55 }
56
GetFileDigest(const std::string & inputFile,const std::string & algName)57 std::vector<int8_t> HashUtils::GetFileDigest(const std::string& inputFile, const std::string& algName)
58 {
59 std::vector<int8_t> result;
60
61 std::ifstream input(inputFile, std::ios::binary);
62 if (0 != input.rdstate()) {
63 PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "failed to get input stream object!");
64 return std::vector<int8_t>();
65 }
66
67 char buffer[HASH_LEN] = { 0 };
68 int num = 0;
69 std::map<int, std::vector<int8_t>> hashMap;
70
71 while (!input.eof()) {
72 input.read(buffer, HASH_LEN);
73
74 if (input.fail() && !input.eof()) {
75 PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "error occurred while reading data.");
76 return std::vector<int8_t>();
77 }
78
79 std::streamsize readLen = input.gcount();
80 std::string str;
81 for (int i = 0; i < readLen; ++i) {
82 str.push_back(buffer[i]);
83 }
84
85 std::vector<int8_t> dig = GetByteDigest(str, readLen, algName);
86 hashMap.emplace(num, dig);
87 ++num;
88 }
89
90 if (hashMap.empty()) {
91 PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "hashMap is empty.");
92 return std::vector<int8_t>();
93 }
94
95 DigestUtils fileDigestUtils(HASH_SHA256);
96 for (const auto& hashMapItem : hashMap) {
97 std::string str(hashMapItem.second.begin(), hashMapItem.second.end());
98 fileDigestUtils.AddData(str);
99 }
100 std::string digest = fileDigestUtils.Result(DigestUtils::Type::BINARY);
101 for (std::string::size_type i = 0; i < digest.size(); i++) {
102 result.push_back(digest[i]);
103 }
104 return result;
105 }
106
GetDigestFromBytes(const std::vector<int8_t> & fileBytes,int64_t length,const std::string & algName)107 std::vector<int8_t> HashUtils::GetDigestFromBytes(const std::vector<int8_t>& fileBytes, int64_t length,
108 const std::string& algName)
109 {
110 if (fileBytes.empty() || length <= 0) {
111 PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "file bytes is empty.");
112 return std::vector<int8_t>();
113 }
114 std::map<int, std::vector<int8_t>> hashMap;
115 int64_t readLength = 0;
116 int64_t num = 0;
117 while (readLength < length) {
118 int64_t blockLength = length - readLength > HASH_LEN ? HASH_LEN : (length - readLength);
119 std::string readStr(fileBytes.begin() + readLength, fileBytes.begin() + readLength + blockLength);
120 std::vector<int8_t> dig = GetByteDigest(readStr, readStr.size(), algName);
121 hashMap.emplace(num, dig);
122 ++num;
123 readLength += readStr.size();
124 }
125 if (hashMap.empty()) {
126 PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "hashMap is empty.");
127 return std::vector<int8_t>();
128 }
129 DigestUtils digestUtils(HASH_SHA256);
130 for (const auto& item : hashMap) {
131 std::string str(item.second.begin(), item.second.end());
132 digestUtils.AddData(str);
133 }
134 std::string digest = digestUtils.Result(DigestUtils::Type::BINARY);
135 std::vector<int8_t> result;
136 for (std::string::size_type i = 0; i < digest.size(); i++) {
137 result.push_back(digest[i]);
138 }
139 return result;
140 }
141
GetByteDigest(const std::string & str,int count,const std::string & algMethod)142 std::vector<int8_t> HashUtils::GetByteDigest(const std::string& str, int count, const std::string& algMethod)
143 {
144 std::vector<int8_t> result;
145 DigestUtils digestUtils(HASH_SHA256);
146 digestUtils.AddData(str);
147 std::string digest = digestUtils.Result(DigestUtils::Type::BINARY);
148 for (std::string::size_type i = 0; i < digest.size(); i++) {
149 result.push_back(digest[i]);
150 }
151 return result;
152 }
153
154 } // namespace SignatureTools
155 } // namespace OHOS