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