1 /*
2 * Copyright (c) 2023 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 "sha256_utils.h"
17
18 #include <cstdlib>
19 #include <sys/stat.h>
20 #include <sys/statfs.h>
21 #include <unistd.h>
22
23 #include "file_utils.h"
24 #include "mbedtls/sha256.h"
25
26 namespace OHOS {
27 namespace UpdateEngine {
28 constexpr unsigned int SHA256_STRING_LEN = 65;
29 constexpr unsigned int SHA256_LENGTH = 32;
30 constexpr unsigned int MAX_BUFFER_LENGTH = 1024;
31 constexpr unsigned int SHA256_TO_STRING_STEP = 2;
32
CalculateHashCode(std::string inputStr)33 std::string Sha256Utils::CalculateHashCode(std::string inputStr)
34 {
35 char result[SHA256_STRING_LEN] = {0};
36 if (!Sha256Calculate(reinterpret_cast<const unsigned char *>(inputStr.c_str()), inputStr.length(),
37 result, SHA256_STRING_LEN)) {
38 ENGINE_LOGE("CalculateHashCode fail, src = %s", inputStr.c_str());
39 return "";
40 }
41 return result;
42 }
43
CheckFileSha256String(const std::string & fileName,const std::string & sha256String)44 bool Sha256Utils::CheckFileSha256String(const std::string &fileName, const std::string &sha256String)
45 {
46 if (!FileUtils::IsFileExist(fileName)) {
47 ENGINE_LOGE("check file sha256 failed, fileName = %{pubilc}s is not exist", fileName.c_str());
48 return false;
49 }
50 char sha256Result[SHA256_STRING_LEN] = {0}; // sha256Result len is 65
51 if (!GetFileSha256Str(fileName, sha256Result, sizeof(sha256Result))) {
52 ENGINE_LOGE("get file sha256 failed");
53 return false;
54 }
55 if (strcasecmp(sha256Result, sha256String.c_str()) != 0) {
56 ENGINE_LOGE("sha256 not same! input=%{public}s, cal=%{public}s", sha256Result, sha256String.c_str());
57 return false;
58 }
59 return true;
60 }
61
GetDigestFromFile(const char * fileName,unsigned char digest[])62 bool Sha256Utils::GetDigestFromFile(const char *fileName, unsigned char digest[])
63 {
64 char *canonicalPath = realpath(fileName, NULL);
65 if (canonicalPath == NULL) {
66 ENGINE_LOGI("%s is not exist or invalid", fileName);
67 return false;
68 }
69 FILE *fp = fopen(canonicalPath, "rb");
70 free(canonicalPath);
71 if (fp == NULL) {
72 return false;
73 }
74 (void)fseek(fp, 0, SEEK_END);
75 long fLen = ftell(fp);
76 (void)fseek(fp, 0, SEEK_SET);
77
78 unsigned char buffer[MAX_BUFFER_LENGTH]; /* buffer len 1024 */
79 mbedtls_sha256_context context;
80 mbedtls_sha256_init(&context);
81 mbedtls_sha256_starts(&context, 0);
82 while (!feof(fp) && fLen > 0) {
83 int readCount = (sizeof(buffer) > (uint32_t)fLen) ? fLen : sizeof(buffer);
84 int count = (int)fread(buffer, 1, readCount, fp);
85 if (count != readCount) {
86 ENGINE_LOGE("read file %{public}s error", fileName);
87 break;
88 }
89 fLen -= count;
90 mbedtls_sha256_update(&context, buffer, count);
91 }
92 mbedtls_sha256_finish(&context, digest);
93 mbedtls_sha256_free(&context);
94 (void)fclose(fp);
95 return true;
96 }
97
GetFileSha256Str(const std::string & fileName,char * sha256Result,uint32_t len)98 bool Sha256Utils::GetFileSha256Str(const std::string &fileName, char *sha256Result, uint32_t len)
99 {
100 unsigned char digest[SHA256_LENGTH] = {0};
101 GetDigestFromFile(fileName.c_str(), digest);
102 return TransDigestToSha256Result(sha256Result, len, digest);
103 }
104
Sha256Calculate(const unsigned char * input,int len,char * componentId,int componentIdLen)105 bool Sha256Utils::Sha256Calculate(const unsigned char *input, int len, char *componentId, int componentIdLen)
106 {
107 unsigned char digest[SHA256_LENGTH] = {0};
108 mbedtls_sha256_context ctx;
109 int ret = memset_s(&ctx, sizeof(ctx), 0, sizeof(ctx));
110 if (ret != 0) {
111 ENGINE_LOGE("init mbedtls_sha256_context failed");
112 return false;
113 }
114 mbedtls_sha256_init(&ctx);
115 int startRet = mbedtls_sha256_starts(&ctx, 0);
116 if (startRet != 0) {
117 mbedtls_sha256_free(&ctx);
118 ENGINE_LOGE("mbedtls_sha256_starts_ret failed");
119 return false;
120 }
121
122 int updateRet = mbedtls_sha256_update(&ctx, input, len);
123 if (updateRet != 0) {
124 mbedtls_sha256_free(&ctx);
125 ENGINE_LOGE("mbedtls_sha256_update_ret failed");
126 return false;
127 }
128
129 int finishRet = mbedtls_sha256_finish(&ctx, digest);
130 if (finishRet != 0) {
131 mbedtls_sha256_free(&ctx);
132 ENGINE_LOGE("mbedtls_sha256_finish_ret failed");
133 return false;
134 }
135 mbedtls_sha256_free(&ctx);
136 return TransDigestToSha256Result(componentId, componentIdLen, digest);
137 }
138
TransDigestToSha256Result(char * sha256Result,uint32_t componentIdLen,const unsigned char * digest)139 bool Sha256Utils::TransDigestToSha256Result(char *sha256Result, uint32_t componentIdLen, const unsigned char *digest)
140 {
141 for (unsigned int i = 0; i < SHA256_LENGTH; i++) {
142 unsigned int deviation = i * SHA256_TO_STRING_STEP;
143 if (deviation >= componentIdLen) {
144 ENGINE_LOGE("deviation len illegal");
145 return false;
146 }
147 int result = sprintf_s(sha256Result + deviation, (componentIdLen - deviation), "%02x", digest[i]);
148 if (result <= 0) {
149 ENGINE_LOGE("generated sha256 failed");
150 return false;
151 }
152 }
153 return true;
154 }
155 } // namespace UpdateEngine
156 } // namespace OHOS