• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025-2025 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 "feature/param_update/sign_tools.h"
17 
18 #include <unistd.h>
19 #include <fstream>       // for ifstream
20 #include <openssl/bio.h> // bio
21 #include <openssl/evp.h> // evp
22 #include <openssl/pem.h> // PEM_read_bio_RSA_PUBKEY
23 #include <openssl/rsa.h> // rsa
24 #include <sstream>       // stringstream
25 #include <cstdlib>
26 #include <climits>
27 
28 #include "common/util/file_utils.h"
29 #include "fms_log_wrapper.h"
30 
31 namespace OHOS {
32 namespace AppExecFwk {
VerifyFileSign(const std::string & pubKeyPath,const std::string & singPath,const std::string & digestPath)33 bool SignTools::VerifyFileSign(const std::string &pubKeyPath, const std::string &singPath,
34     const std::string &digestPath)
35 {
36     if (!(FileUtils::IsFileExists(pubKeyPath) && FileUtils::IsFileExists(singPath) &&
37         FileUtils::IsFileExists(digestPath))) {
38         HILOG_ERROR("file not exist");
39         return false;
40     }
41 
42     const std::string signStr = GetfileStream(singPath);
43     const std::string digeststr = GetfileStream(digestPath);
44 
45     BIO *bio = BIO_new_file(pubKeyPath.c_str(), "r");
46 
47     RSA *pubKey = RSA_new();
48 
49     if (PEM_read_bio_RSA_PUBKEY(bio, &pubKey, NULL, NULL) == NULL) {
50         HILOG_ERROR("get pubKey is failed");
51         BIO_free(bio);
52         RSA_free(pubKey);
53         return false;
54     }
55 
56     bool verify = false;
57     if (!(pubKey == NULL || signStr.empty() || digeststr.empty())) {
58         verify = VerifyRsa(pubKey, digeststr, signStr);
59     } else {
60         HILOG_ERROR("param is null");
61     }
62     BIO_free(bio);
63     RSA_free(pubKey);
64     return verify;
65 }
66 
VerifyRsa(RSA * pubKey,const std::string & digest,const std::string & sign)67 bool SignTools::VerifyRsa(RSA *pubKey, const std::string &digest, const std::string &sign)
68 {
69     EVP_PKEY *evpKey = NULL;
70     EVP_MD_CTX *ctx = NULL;
71     evpKey = EVP_PKEY_new();
72     if (evpKey == nullptr) {
73         HILOG_ERROR("evpKey is nullptr");
74         return false;
75     }
76     if (EVP_PKEY_set1_RSA(evpKey, pubKey) != 1) {
77         HILOG_ERROR("EVP_PKEY_set1_RSA fail");
78         EVP_PKEY_free(evpKey);
79         return false;
80     }
81     ctx = EVP_MD_CTX_new();
82     EVP_MD_CTX_init(ctx);
83     if (ctx == nullptr) {
84         HILOG_ERROR("ctx is nullptr");
85         EVP_PKEY_free(evpKey);
86         return false;
87     }
88     if (EVP_VerifyInit_ex(ctx, EVP_sha256(), NULL) != 1) {
89         HILOG_ERROR("EVP_VerifyInit_ex fail");
90         EVP_PKEY_free(evpKey);
91         EVP_MD_CTX_free(ctx);
92         return false;
93     }
94     if (EVP_VerifyUpdate(ctx, digest.c_str(), digest.size()) != 1) {
95         HILOG_ERROR("EVP_VerifyUpdate fail");
96         EVP_PKEY_free(evpKey);
97         EVP_MD_CTX_free(ctx);
98         return false;
99     }
100     if (EVP_VerifyFinal(ctx, (unsigned char *)sign.c_str(), sign.size(), evpKey) != 1) {
101         HILOG_ERROR("EVP_VerifyFinal fail)");
102         EVP_PKEY_free(evpKey);
103         EVP_MD_CTX_free(ctx);
104         return false;
105     }
106 
107     EVP_PKEY_free(evpKey);
108     EVP_MD_CTX_free(ctx);
109     return true;
110 }
111 
GetfileStream(const std::string & filepath)112 std::string SignTools::GetfileStream(const std::string &filepath)
113 {
114     std::string fileString;
115     char canonicalPath[PATH_MAX] = { '\0' };
116     if (realpath(filepath.c_str(), canonicalPath) == nullptr) {
117         HILOG_ERROR("canonicalPath is null");
118         return fileString;
119     }
120     canonicalPath[PATH_MAX - 1] = '\0';
121     std::ifstream file(canonicalPath, std::ios::in | std::ios::binary);
122     if (!file.good()) {
123         HILOG_ERROR("Failed to open the file!");
124         return fileString;
125     }
126     std::stringstream infile;
127     infile << file.rdbuf();
128     fileString = infile.str();
129     file.close();
130     return fileString;
131 }
132 
133 
CalcFileSha256Digest(const std::string & fpath)134 std::tuple<int, std::string> SignTools::CalcFileSha256Digest(const std::string &fpath)
135 {
136     auto res = std::make_unique<unsigned char[]>(SHA256_DIGEST_LENGTH);
137     SHA256_CTX ctx;
138     SHA256_Init(&ctx);
139     auto sha256Update = [ctx = &ctx](char *buf, size_t len) { SHA256_Update(ctx, buf, len); };
140     int err = ForEachFileSegment(fpath, sha256Update);
141     SHA256_Final(res.get(), &ctx);
142     if (err) {
143         return { err, "" };
144     }
145     std::string dist;
146     CalcBase64(res.get(), SHA256_DIGEST_LENGTH, dist);
147     return { err, dist };
148 };
149 
ForEachFileSegment(const std::string & fpath,std::function<void (char *,size_t)> executor)150 int SignTools::ForEachFileSegment(const std::string &fpath, std::function<void(char *, size_t)> executor)
151 {
152     char canonicalPath[PATH_MAX] = { '\0' };
153     if (realpath(fpath.c_str(), canonicalPath) == nullptr) {
154         HILOG_ERROR("canonicalPath is null");
155         return errno;
156     }
157     canonicalPath[PATH_MAX - 1] = '\0';
158     std::unique_ptr<FILE, decltype(&fclose)> filp = { fopen(canonicalPath, "r"), fclose };
159     if (!filp) {
160         return errno;
161     }
162     const size_t pageSize { getpagesize() };
163     auto buf = std::make_unique<char[]>(pageSize);
164     size_t actLen;
165     do {
166         actLen = fread(buf.get(), 1, pageSize, filp.get());
167         if (actLen > 0) {
168             executor(buf.get(), actLen);
169         }
170     } while (actLen == pageSize);
171 
172     return ferror(filp.get()) ? errno : 0;
173 }
174 
CalcBase64(uint8_t * input,uint32_t inputLen,std::string & encodedStr)175 void SignTools::CalcBase64(uint8_t *input, uint32_t inputLen, std::string &encodedStr)
176 {
177     size_t expectedLength = 4 * ((inputLen + 2) / 3);
178     encodedStr.resize(expectedLength);
179     int actualLength = EVP_EncodeBlock(reinterpret_cast<uint8_t *>(&encodedStr[0]), input, inputLen);
180     encodedStr.resize(actualLength);
181     HILOG_INFO("expectedLength = %{public}zu, actualLength = %{public}d", expectedLength, actualLength);
182 }
183 }  // namespace AppExecFwk
184 }  // namespace OHOS