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 struct DlCloseDeleter {
operator ()OHOS::HiviewDFX::__anon8d0bbd230111::DlCloseDeleter28 void operator()(void* handle)
29 {
30 if (handle) {
31 dlclose(handle);
32 }
33 }
34 };
35 }
36 DEFINE_LOG_TAG("CalcFingerprint");
ConvertToString(const unsigned char hash[SHA256_DIGEST_LENGTH],char * outstr,size_t len)37 int CalcFingerprint::ConvertToString(const unsigned char hash[SHA256_DIGEST_LENGTH], char *outstr, size_t len)
38 {
39 uint32_t i;
40 char *outHash = outstr;
41
42 if (hash == nullptr || outHash == nullptr) {
43 return EINVAL;
44 }
45 constexpr int charsEachHex = 2;
46 if (len < (SHA256_DIGEST_LENGTH * charsEachHex + 1)) { // 1: add '\0'
47 return ENOMEM;
48 }
49 for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
50 int err = snprintf_s(outHash, charsEachHex + 1, charsEachHex, "%02x", hash[i]);
51 if (err < 0) {
52 return err;
53 }
54 outHash += charsEachHex;
55 }
56 *outHash = '\0';
57 return 0;
58 }
59
60 /*
61 * API name : calc_file_sha1
62 * Description : calculate a file sha1 hash for given file
63 * Input parameters
64 * filePath : path of the file to be calculated
65 * hash : buffer to store output sha1 string
66 * Return
67 * 0 : successful
68 * x : fail
69 */
CalcFileSha(const string & filePath,char * hash,size_t len)70 int CalcFingerprint::CalcFileSha(const string& filePath, char *hash, size_t len)
71 {
72 if (filePath.empty() || hash == nullptr || !FileUtil::IsLegalPath(filePath)) {
73 HIVIEW_LOGE("invalid param.");
74 return EINVAL;
75 }
76 unsigned char value[SHA256_DIGEST_LENGTH] = {0};
77 int ret = CalcFileShaOriginal(filePath, value, len);
78 if (ret != 0) {
79 HIVIEW_LOGE("CalcFileShaOriginal failed.");
80 return ret;
81 }
82 return ConvertToString(value, hash, len);
83 }
84
CalcFileShaOriginal(const string & filePath,unsigned char * hash,size_t len)85 int CalcFingerprint::CalcFileShaOriginal(const string& filePath, unsigned char *hash, size_t len)
86 {
87 if (filePath.empty() || hash == nullptr || !FileUtil::IsLegalPath(filePath)) {
88 HIVIEW_LOGE("file is invalid.");
89 return EINVAL;
90 }
91
92 if (len < SHA256_DIGEST_LENGTH) {
93 HIVIEW_LOGE("hash buf len error.");
94 return ENOMEM;
95 }
96
97 FILE *fp = nullptr;
98 fp = fopen(filePath.c_str(), "rb");
99 if (fp == nullptr) {
100 HIVIEW_LOGE("open file failed.");
101 return errno; // if file not exist, errno will be ENOENT
102 }
103
104 size_t n;
105 char buffer[HASH_BUFFER_SIZE] = {0};
106 SHA256_CTX ctx;
107 SHA256_Init(&ctx);
108 while ((n = fread(buffer, 1, sizeof(buffer), fp))) {
109 SHA256_Update(&ctx, (unsigned char *)buffer, n);
110 }
111 if (fclose(fp)) {
112 HIVIEW_LOGE("fclose is failed");
113 }
114 fp = nullptr;
115 SHA256_Final(hash, &ctx);
116 return 0;
117 }
118
119 /*
120 * API name : calc_buffer_sha1
121 * Description : calculate a buffer sha1 hash for given buffer
122 * Input parameters
123 * buffer : buffer to store the content which needed to be calculated
124 * hash_str : buffer to store output sha1 string
125 * Return
126 * 0 : successful
127 * x : fail
128 */
CalcBufferSha(const string & buffer,size_t bufSize,char * hash,size_t len)129 int CalcFingerprint::CalcBufferSha(const string& buffer, size_t bufSize, char *hash, size_t len)
130 {
131 if (buffer.empty()) {
132 return EINVAL;
133 }
134 return CalcBufferSha((unsigned char *)buffer.c_str(), bufSize, hash, len);
135 }
136
137 /*
138 * API name : calc_buffer_sha1
139 * Description : calculate a buffer sha1 hash for given buffer
140 * Input parameters
141 * source : buffer to store the content which needed to be calculated
142 * sourceLen : input buffer len
143 * hash : buffer to store output sha1 string
144 * hashLen : output buff len
145 * Return
146 * 0 : successful
147 * x : fail
148 */
CalcBufferSha(unsigned char * source,size_t sourceLen,char * hash,size_t hashLen)149 int CalcFingerprint::CalcBufferSha(unsigned char* source, size_t sourceLen, char *hash, size_t hashLen)
150 {
151 if (source == nullptr || hash == nullptr || sourceLen == 0) {
152 return EINVAL;
153 }
154
155 unsigned char value[SHA256_DIGEST_LENGTH] = {0};
156 SHA256(source, sourceLen, value);
157 return ConvertToString(value, hash, hashLen);
158 }
159 }
160 }
161