• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <openssl/sha.h>
20 #include <sys/stat.h>
21 #include <sys/statfs.h>
22 #include <unistd.h>
23 
24 #include "file_utils.h"
25 
26 namespace OHOS {
27 namespace UpdateService {
28 constexpr int OPENSSL_SUCCESS = 1;
29 constexpr unsigned int SHA256_STRING_LEN = 65;
30 constexpr unsigned int SHA256_LENGTH = 32;
31 constexpr unsigned int MAX_BUFFER_LENGTH = 1024;
32 constexpr unsigned int SHA256_TO_STRING_STEP = 2;
33 
CalculateHashCode(std::string inputStr)34 std::string Sha256Utils::CalculateHashCode(std::string inputStr)
35 {
36     char result[SHA256_STRING_LEN] = {0};
37     if (!Sha256Calculate(reinterpret_cast<const unsigned char *>(inputStr.c_str()), inputStr.length(),
38         result, SHA256_STRING_LEN)) {
39         ENGINE_LOGE("CalculateHashCode fail, src = %s", inputStr.c_str());
40         return "";
41     }
42     return result;
43 }
44 
CheckFileSha256String(const std::string & fileName,const std::string & sha256String)45 bool Sha256Utils::CheckFileSha256String(const std::string &fileName, const std::string &sha256String)
46 {
47     if (!FileUtils::IsFileExist(fileName)) {
48         ENGINE_LOGE("check file sha256 failed, file not exist");
49         return false;
50     }
51     char sha256Result[SHA256_STRING_LEN] = {0}; // sha256Result len is 65
52     if (!GetFileSha256Str(fileName, sha256Result, sizeof(sha256Result))) {
53         ENGINE_LOGE("get file sha256 failed");
54         return false;
55     }
56     if (strcasecmp(sha256Result, sha256String.c_str()) != 0) {
57         ENGINE_LOGE("sha256 not same! input=%{public}s, cal=%{public}s", sha256Result, sha256String.c_str());
58         return false;
59     }
60     return true;
61 }
62 
FreeBuffer(char * buffer,std::ifstream & file)63 void Sha256Utils::FreeBuffer(char *buffer, std::ifstream &file)
64 {
65     if (buffer != nullptr) {
66         free(buffer);
67     }
68 
69     if (file.is_open()) {
70         file.close();
71     }
72 }
73 
GetDigestFromFile(const char * fileName,unsigned char digest[])74 bool Sha256Utils::GetDigestFromFile(const char *fileName, unsigned char digest[])
75 {
76     char realPath[PATH_MAX] = {};
77     if (realpath(fileName, realPath) == NULL) {
78         ENGINE_LOGI("file not exist or invalid");
79         return false;
80     }
81 
82     std::ifstream file(realPath, std::ios::binary);
83     if (!file.is_open()) {
84         ENGINE_LOGI("%{private}s Unable to open file", realPath);
85         return false;
86     }
87 
88     char *buffer = (char *)malloc(MAX_BUFFER_LENGTH); /* buffer len 1024 */
89     if (buffer == nullptr) {
90         ENGINE_LOGI("failed to allocate memory");
91         file.close();
92         return false;
93     }
94     SHA256_CTX sha256;
95     int32_t startRet = SHA256_Init(&sha256);
96     if (startRet != OPENSSL_SUCCESS) {
97         ENGINE_LOGE("SHA256_init_ret failed, startRet = %{public}d", startRet);
98         FreeBuffer(buffer, file);
99         return false;
100     }
101 
102     while (!file.eof()) {
103         file.read(buffer, MAX_BUFFER_LENGTH);
104         int32_t updateRet = SHA256_Update(&sha256, buffer, file.gcount());
105         if (updateRet != OPENSSL_SUCCESS) {
106             ENGINE_LOGE("SHA256_update_ret failed, updateRet = %{public}d", updateRet);
107             FreeBuffer(buffer, file);
108             return false;
109         }
110     }
111     int32_t finishRet = SHA256_Final(digest, &sha256);
112     if (finishRet != OPENSSL_SUCCESS) {
113         ENGINE_LOGE("SHA256_finish_ret failed, finishRet = %{public}d", finishRet);
114         FreeBuffer(buffer, file);
115         return false;
116     }
117     FreeBuffer(buffer, file);
118     return true;
119 }
120 
GetFileSha256Str(const std::string & fileName,char * sha256Result,uint32_t len)121 bool Sha256Utils::GetFileSha256Str(const std::string &fileName, char *sha256Result, uint32_t len)
122 {
123     unsigned char digest[SHA256_LENGTH] = {0};
124     GetDigestFromFile(fileName.c_str(), digest);
125     return TransDigestToSha256Result(sha256Result, len, digest);
126 }
127 
Sha256Calculate(const unsigned char * input,size_t len,char * componentId,unsigned int componentIdLen)128 bool Sha256Utils::Sha256Calculate(const unsigned char *input, size_t len, char *componentId,
129     unsigned int componentIdLen)
130 {
131     unsigned char digest[SHA256_LENGTH] = {0};
132     SHA256_CTX ctx;
133     int ret = memset_s(&ctx, sizeof(ctx), 0, sizeof(ctx));
134     if (ret != 0) {
135         ENGINE_LOGE("init sha256_context failed");
136         return false;
137     }
138     int startRet = SHA256_Init(&ctx);
139     if (startRet != OPENSSL_SUCCESS) {
140         ENGINE_LOGE("SHA256_Init failed, startRet = %{public}d", startRet);
141         return false;
142     }
143 
144     int updateRet = SHA256_Update(&ctx, input, len);
145     if (updateRet != OPENSSL_SUCCESS) {
146         ENGINE_LOGE("SHA256_Update failed, updateRet = %{public}d", updateRet);
147         return false;
148     }
149 
150     int finishRet = SHA256_Final(digest, &ctx);
151     if (finishRet != OPENSSL_SUCCESS) {
152         ENGINE_LOGE("SHA256_Final failed, finishRet = %{public}d", finishRet);
153         return false;
154     }
155 
156     return TransDigestToSha256Result(componentId, componentIdLen, digest);
157 }
158 
TransDigestToSha256Result(char * sha256Result,uint32_t componentIdLen,const unsigned char * digest)159 bool Sha256Utils::TransDigestToSha256Result(char *sha256Result, uint32_t componentIdLen, const unsigned char *digest)
160 {
161     for (unsigned int i = 0; i < SHA256_LENGTH; i++) {
162         unsigned int deviation = i * SHA256_TO_STRING_STEP;
163         if (deviation >= componentIdLen) {
164             ENGINE_LOGE("deviation len illegal");
165             return false;
166         }
167         int result = sprintf_s(sha256Result + deviation, (componentIdLen - deviation), "%02x", digest[i]);
168         if (result <= 0) {
169             ENGINE_LOGE("generated sha256 failed");
170             return false;
171         }
172     }
173     return true;
174 }
175 } // namespace UpdateService
176 } // namespace OHOS