1 /*
2 * Copyright (c) 2023-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 "log_sign_tools.h"
17
18 #include "calc_fingerprint.h"
19 #include "file_util.h"
20 #include "hiview_logger.h"
21
22 namespace OHOS {
23 namespace HiviewDFX {
24 DEFINE_LOG_TAG("Hiview-ParamUpdate");
25
26 namespace {
27 constexpr int32_t BASE64_ENCODE_LEN_OF_EACH_GROUP_DATA = 4;
28 constexpr int32_t BASE64_ENCODE_PACKET_LEN = 3;
29 constexpr int BUFFER_SIZE = 4096;
30 }
31
VerifyFileSign(const std::string & pubKeyPath,const std::string & signPath,const std::string & digestPath)32 bool LogSignTools::VerifyFileSign(const std::string &pubKeyPath, const std::string &signPath,
33 const std::string &digestPath)
34 {
35 if (!FileUtil::FileExists(pubKeyPath)) {
36 HIVIEW_LOGE("pubKey file not exist");
37 return false;
38 }
39
40 if (!FileUtil::FileExists(signPath)) {
41 HIVIEW_LOGE("sign file not exist");
42 return false;
43 }
44
45 if (!FileUtil::FileExists(digestPath)) {
46 HIVIEW_LOGE("digest file not exist");
47 return false;
48 }
49
50 std::string signStr;
51 FileUtil::LoadStringFromFile(signPath, signStr);
52 std::string digestStr;
53 FileUtil::LoadStringFromFile(digestPath, digestStr);
54 RSA *pubKey = RSA_new();
55 bool verify = false;
56 if (!(pubKey == nullptr || signStr.empty() || digestStr.empty())) {
57 BIO *bio = BIO_new_file(pubKeyPath.c_str(), "r");
58 if (PEM_read_bio_RSA_PUBKEY(bio, &pubKey, nullptr, nullptr) == nullptr) {
59 HIVIEW_LOGE("get pubKey is failed.");
60 BIO_free(bio);
61 return false;
62 }
63 verify = VerifyRsa(pubKey, digestStr, signStr);
64 BIO_free(bio);
65 } else {
66 HIVIEW_LOGE("pubKey or signStr or digestStr is error.");
67 }
68 RSA_free(pubKey);
69 return verify;
70 }
71
CalcFileSha(const std::string & path,unsigned char * hash,size_t outLen)72 int LogSignTools::CalcFileSha(const std::string& path, unsigned char *hash, size_t outLen)
73 {
74 if (path.empty() || hash == nullptr || !FileUtil::IsLegalPath(path)) {
75 HIVIEW_LOGE("file is invalid.");
76 return EINVAL;
77 }
78
79 if (outLen < SHA256_DIGEST_LENGTH) {
80 HIVIEW_LOGE("hash buf len error.");
81 return ENOMEM;
82 }
83
84 FILE *fp = nullptr;
85 fp = fopen(path.c_str(), "rb");
86 if (fp == nullptr) {
87 HIVIEW_LOGE("open file failed.");
88 return errno; // if file not exist, errno will be ENOENT
89 }
90
91 size_t readSize;
92 char fbuffer[BUFFER_SIZE] = {0};
93 SHA256_CTX ctx;
94 SHA256_Init(&ctx);
95 while ((readSize = fread(fbuffer, 1, sizeof(fbuffer), fp))) {
96 SHA256_Update(&ctx, (unsigned char *)fbuffer, readSize);
97 }
98 if (fclose(fp)) {
99 HIVIEW_LOGE("fclose is failed");
100 }
101 fp = nullptr;
102 SHA256_Final(hash, &ctx);
103 return 0;
104 }
105
CalcFileSha256Digest(const std::string & fpath)106 std::string LogSignTools::CalcFileSha256Digest(const std::string &fpath)
107 {
108 unsigned char res[SHA256_DIGEST_LENGTH] = {0};
109 if (CalcFileSha(fpath, res, SHA256_DIGEST_LENGTH) != 0) {
110 HIVIEW_LOGE("CalcFileSha failed");
111 return "";
112 }
113 std::string dist;
114 CalcBase64(res, SHA256_DIGEST_LENGTH, dist);
115 return dist;
116 }
117
CalcBase64(uint8_t * input,uint32_t inputLen,std::string & encodedStr)118 void LogSignTools::CalcBase64(uint8_t *input, uint32_t inputLen, std::string &encodedStr)
119 {
120 size_t base64Len = static_cast<size_t>(ceil(static_cast<long double>(inputLen) / BASE64_ENCODE_PACKET_LEN) *
121 BASE64_ENCODE_LEN_OF_EACH_GROUP_DATA + 1);
122 std::unique_ptr<unsigned char[]> base64Str = std::make_unique<unsigned char[]>(base64Len);
123 size_t outLen = static_cast<size_t>(EVP_EncodeBlock(reinterpret_cast<uint8_t *>(base64Str.get()),
124 input, inputLen));
125 encodedStr = std::string(reinterpret_cast<char*>(base64Str.get()), outLen);
126 }
127
VerifyRsa(RSA * pubKey,const std::string & digest,const std::string & sign)128 bool LogSignTools::VerifyRsa(RSA *pubKey, const std::string &digest, const std::string &sign)
129 {
130 EVP_PKEY *evpKey = nullptr;
131 EVP_MD_CTX *ctx = nullptr;
132 evpKey = EVP_PKEY_new();
133 if (evpKey == nullptr) {
134 HIVIEW_LOGE("evpKey is nullptr");
135 return false;
136 }
137
138 if (EVP_PKEY_set1_RSA(evpKey, pubKey) != 1) {
139 HIVIEW_LOGE("set RSA failed.");
140 return false;
141 }
142
143 ctx = EVP_MD_CTX_new();
144 EVP_MD_CTX_init(ctx);
145 if (ctx == nullptr) {
146 HIVIEW_LOGE("ctx is nullptr.");
147 EVP_PKEY_free(evpKey);
148 return false;
149 }
150
151 if (EVP_VerifyInit_ex(ctx, EVP_sha256(), nullptr) != 1) {
152 HIVIEW_LOGE("VerifyInit failed.");
153 EVP_PKEY_free(evpKey);
154 EVP_MD_CTX_free(ctx);
155 return false;
156 }
157
158 if (EVP_VerifyUpdate(ctx, digest.c_str(), digest.size()) != 1) {
159 HIVIEW_LOGE("VerifyUpdate failed.");
160 EVP_PKEY_free(evpKey);
161 EVP_MD_CTX_free(ctx);
162 return false;
163 }
164
165 if (EVP_VerifyFinal(ctx, (unsigned char *)sign.c_str(), sign.size(), evpKey) != 1) {
166 HIVIEW_LOGE("VerifyFinal failed.");
167 EVP_PKEY_free(evpKey);
168 EVP_MD_CTX_free(ctx);
169 return false;
170 }
171 EVP_PKEY_free(evpKey);
172 EVP_MD_CTX_free(ctx);
173 return true;
174 }
175 }
176 }
177