• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #include "calc_fingerprint.h"
16 
17 #include <dlfcn.h>
18 #include <securec.h>
19 
20 #include "common_defines.h"
21 #include "file_util.h"
22 
23 using namespace std;
24 namespace OHOS {
25 namespace HiviewDFX {
26 namespace {
27 constexpr const char *LIB_NAME = "libcrypto_openssl.z.so";
28 constexpr const char *SHA256_INIT_FUNC_NAME = "SHA256_Init";
29 constexpr const char *SHA256_UPDATE_FUNC_NAME = "SHA256_Update";
30 constexpr const char *SHA256_FINAL_FUNC_NAME = "SHA256_Final";
31 constexpr const char *SHA256_FUNC_NAME = "SHA256";
32 struct DlCloseDeleter {
operator ()OHOS::HiviewDFX::__anon216660810111::DlCloseDeleter33     void operator()(void* handle)
34     {
35         if (handle) {
36             dlclose(handle);
37         }
38     }
39 };
40 }
41 DEFINE_LOG_TAG("CalcFingerprint");
ConvertToString(const unsigned char hash[SHA256_DIGEST_LENGTH],char * outstr,size_t len)42 int CalcFingerprint::ConvertToString(const unsigned char hash[SHA256_DIGEST_LENGTH], char *outstr, size_t len)
43 {
44     uint32_t i;
45     char *outHash = outstr;
46 
47     if (hash == nullptr || outHash == nullptr) {
48         return EINVAL;
49     }
50     constexpr int charsEachHex = 2;
51     if (len < (SHA256_DIGEST_LENGTH * charsEachHex + 1)) { // 1: add '\0'
52         return ENOMEM;
53     }
54     for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
55         int err = snprintf_s(outHash, charsEachHex + 1, charsEachHex, "%02x", hash[i]);
56         if (err < 0) {
57             return err;
58         }
59         outHash += charsEachHex;
60     }
61     *outHash = '\0';
62     return 0;
63 }
64 
65 /*
66  * API name : calc_file_sha1
67  * Description : calculate a file sha1 hash for given file
68  * Input parameters
69  * filePath : path of the file to be calculated
70  * hash      : buffer to store output sha1 string
71  * Return
72  * 0 : successful
73  * x : fail
74  */
CalcFileSha(const string & filePath,char * hash,size_t len)75 int CalcFingerprint::CalcFileSha(const string& filePath, char *hash, size_t len)
76 {
77     if (filePath.empty() || hash == nullptr || !FileUtil::IsLegalPath(filePath)) {
78         HIVIEW_LOGE("invalid param.");
79         return EINVAL;
80     }
81     unsigned char value[SHA256_DIGEST_LENGTH] = {0};
82     int ret = CalcFileShaOriginal(filePath, value, len);
83     if (ret != 0) {
84         HIVIEW_LOGE("CalcFileShaOriginal failed.");
85         return ret;
86     }
87     return ConvertToString(value, hash, len);
88 }
89 
CalcFileShaOriginal(const string & filePath,unsigned char * hash,size_t len)90 int CalcFingerprint::CalcFileShaOriginal(const string& filePath, unsigned char *hash, size_t len)
91 {
92     if (filePath.empty() || hash == nullptr || !FileUtil::IsLegalPath(filePath)) {
93         HIVIEW_LOGE("file is invalid.");
94         return EINVAL;
95     }
96 
97     if (len < SHA256_DIGEST_LENGTH) {
98         HIVIEW_LOGE("hash buf len error.");
99         return ENOMEM;
100     }
101 
102     FILE *fp = nullptr;
103     fp = fopen(filePath.c_str(), "rb");
104     if (fp == nullptr) {
105         HIVIEW_LOGE("open file failed.");
106         return errno; // if file not exist, errno will be ENOENT
107     }
108 
109     unique_ptr<void, DlCloseDeleter> handle(dlopen(LIB_NAME, RTLD_LAZY));
110     if (!handle) {
111         HIVIEW_LOGE("dlopen %{public}s failed, %{public}s.", LIB_NAME, dlerror());
112         fclose(fp);
113         fp = nullptr;
114         return EINVAL;
115     }
116     auto sha256Init = reinterpret_cast<int (*)(SHA256_CTX *c)>(dlsym(handle.get(), SHA256_INIT_FUNC_NAME));
117     auto sha256Update = reinterpret_cast<int (*)(SHA256_CTX *c, const void *data, size_t len)>(dlsym(handle.get(),
118         SHA256_UPDATE_FUNC_NAME));
119     auto sha256Final = reinterpret_cast<int (*)(unsigned char *md, SHA256_CTX *c)>(dlsym(handle.get(),
120         SHA256_FINAL_FUNC_NAME));
121     if (!sha256Init || !sha256Update || !sha256Final) {
122         HIVIEW_LOGE("dlsym failed, %{public}s.", dlerror());
123         fclose(fp);
124         fp = nullptr;
125         return EINVAL;
126     }
127 
128     size_t n;
129     char buffer[HASH_BUFFER_SIZE] = {0};
130     SHA256_CTX ctx;
131     sha256Init(&ctx);
132     while ((n = fread(buffer, 1, sizeof(buffer), fp))) {
133         sha256Update(&ctx, (unsigned char *)buffer, n);
134     }
135     if (fclose(fp)) {
136         HIVIEW_LOGE("fclose is failed");
137     }
138     fp = nullptr;
139     sha256Final(hash, &ctx);
140     return 0;
141 }
142 
143 /*
144  * API name : calc_buffer_sha1
145  * Description : calculate a buffer sha1 hash for given buffer
146  * Input parameters
147  * buffer : buffer to store the content which needed to be calculated
148  * hash_str   : buffer to store output sha1 string
149  * Return
150  * 0 : successful
151  * x : fail
152  */
CalcBufferSha(const string & buffer,size_t bufSize,char * hash,size_t len)153 int CalcFingerprint::CalcBufferSha(const string& buffer, size_t bufSize, char *hash, size_t len)
154 {
155     if (buffer.empty()) {
156         return EINVAL;
157     }
158     return CalcBufferSha((unsigned char *)buffer.c_str(), bufSize, hash, len);
159 }
160 
161 /*
162  * API name : calc_buffer_sha1
163  * Description : calculate a buffer sha1 hash for given buffer
164  * Input parameters
165  * source : buffer to store the content which needed to be calculated
166  * sourceLen : input buffer len
167  * hash : buffer to store output sha1 string
168  * hashLen : output buff len
169  * Return
170  * 0 : successful
171  * x : fail
172  */
CalcBufferSha(unsigned char * source,size_t sourceLen,char * hash,size_t hashLen)173 int CalcFingerprint::CalcBufferSha(unsigned char* source, size_t sourceLen, char *hash, size_t hashLen)
174 {
175     if (source == nullptr || hash == nullptr || sourceLen == 0) {
176         return EINVAL;
177     }
178 
179     unique_ptr<void, DlCloseDeleter> handle(dlopen(LIB_NAME, RTLD_LAZY));
180     if (!handle) {
181         HIVIEW_LOGE("dlopen %{public}s failed, %{public}s.", LIB_NAME, dlerror());
182         return EINVAL;
183     }
184     using SHA256Func = unsigned char *(*)(const unsigned char *d, size_t n, unsigned char *md);
185     auto sha256 = reinterpret_cast<SHA256Func>(dlsym(handle.get(), SHA256_FUNC_NAME));
186     if (!sha256) {
187         HIVIEW_LOGE("dlsym %{public}s failed, %{public}s.", SHA256_FUNC_NAME, dlerror());
188         return EINVAL;
189     }
190 
191     unsigned char value[SHA256_DIGEST_LENGTH] = {0};
192     sha256(source, sourceLen, value);
193     return ConvertToString(value, hash, hashLen);
194 }
195 }
196 }
197