• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-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 
16 #include "verify/hap_verify_v2.h"
17 
18 #include <climits>
19 #include <cstdlib>
20 #include <fcntl.h>
21 #include <regex>
22 #include <sys/stat.h>
23 #include <unistd.h>
24 
25 #include "securec.h"
26 
27 #include "common/hap_verify_log.h"
28 #include "init/hap_crl_manager.h"
29 #include "init/trusted_source_manager.h"
30 #include "ticket/ticket_verify.h"
31 #include "util/hap_profile_verify_utils.h"
32 #include "util/hap_signing_block_utils.h"
33 #include "util/signature_info.h"
34 
35 namespace OHOS {
36 namespace Security {
37 namespace Verify {
38 const int32_t HapVerifyV2::HEX_PRINT_LENGTH = 3;
39 const int32_t HapVerifyV2::DIGEST_BLOCK_LEN_OFFSET = 8;
40 const int32_t HapVerifyV2::DIGEST_ALGORITHM_OFFSET = 12;
41 const int32_t HapVerifyV2::DIGEST_LEN_OFFSET = 16;
42 const int32_t HapVerifyV2::DIGEST_OFFSET_IN_CONTENT = 20;
43 const std::string HapVerifyV2::HAP_APP_PATTERN = "[^]*.hap$";
44 const std::string HapVerifyV2::HQF_APP_PATTERN = "[^]*.hqf$";
45 const std::string HapVerifyV2::HSP_APP_PATTERN = "[^]*.hsp$";
46 const std::string HapVerifyV2::P7B_PATTERN = "[^]*\\.p7b$";
47 const std::string OPENHARMONY_CERT = "C=CN, O=OpenHarmony, OU=OpenHarmony Team, CN=OpenHarmony Application Root CA";
48 
Verify(const std::string & filePath,HapVerifyResult & hapVerifyV1Result,bool readFile)49 int32_t HapVerifyV2::Verify(const std::string& filePath, HapVerifyResult& hapVerifyV1Result, bool readFile)
50 {
51     HAPVERIFY_LOG_DEBUG("Start Verify");
52     std::string standardFilePath;
53     if (!CheckFilePath(filePath, standardFilePath)) {
54         return FILE_PATH_INVALID;
55     }
56 
57     RandomAccessFile hapFile;
58     if (!hapFile.Init(standardFilePath, readFile)) {
59         HAPVERIFY_LOG_ERROR("open standard file failed");
60         return OPEN_FILE_ERROR;
61     }
62 
63     int32_t resultCode = Verify(hapFile, hapVerifyV1Result);
64     return resultCode;
65 }
66 
Verify(const int32_t fileFd,HapVerifyResult & hapVerifyV1Result)67 int32_t HapVerifyV2::Verify(const int32_t fileFd, HapVerifyResult& hapVerifyV1Result)
68 {
69     HAPVERIFY_LOG_INFO("Start Verify with fd");
70     RandomAccessFile hapFile;
71     if (!hapFile.InitWithFd(fileFd)) {
72         HAPVERIFY_LOG_ERROR("init with fd failed");
73         return OPEN_FILE_ERROR;
74     }
75 
76     return Verify(hapFile, hapVerifyV1Result);
77 }
78 
CheckFilePath(const std::string & filePath,std::string & standardFilePath)79 bool HapVerifyV2::CheckFilePath(const std::string& filePath, std::string& standardFilePath)
80 {
81     char path[PATH_MAX + 1] = { 0x00 };
82     if (filePath.size() > PATH_MAX || realpath(filePath.c_str(), path) == nullptr) {
83         HAPVERIFY_LOG_ERROR("filePath is not a standard path");
84         return false;
85     }
86     standardFilePath = std::string(path);
87     try {
88         if (!std::regex_match(standardFilePath, std::regex(HAP_APP_PATTERN)) &&
89             !std::regex_match(standardFilePath, std::regex(HSP_APP_PATTERN)) &&
90             !std::regex_match(standardFilePath, std::regex(HQF_APP_PATTERN))) {
91             HAPVERIFY_LOG_ERROR("file is not hap, hsp or hqf package");
92             return false;
93         }
94     } catch(const std::regex_error& e) {
95         HAPVERIFY_LOG_ERROR("regex match error");
96         return false;
97     }
98     return true;
99 }
100 
CheckP7bPath(const std::string & filePath,std::string & standardFilePath)101 bool HapVerifyV2::CheckP7bPath(const std::string& filePath, std::string& standardFilePath)
102 {
103     char path[PATH_MAX + 1] = { 0x00 };
104     if (filePath.size() > PATH_MAX || realpath(filePath.c_str(), path) == nullptr) {
105         HAPVERIFY_LOG_ERROR("filePath is not a standard path");
106         return false;
107     }
108     standardFilePath = std::string(path);
109     try {
110         if (!std::regex_match(standardFilePath, std::regex(P7B_PATTERN))) {
111             HAPVERIFY_LOG_ERROR("file is not p7b");
112             return false;
113         }
114     } catch(const std::regex_error& e) {
115         HAPVERIFY_LOG_ERROR("regex match error");
116         return false;
117     }
118     return true;
119 }
120 
Verify(RandomAccessFile & hapFile,HapVerifyResult & hapVerifyV1Result)121 int32_t HapVerifyV2::Verify(RandomAccessFile& hapFile, HapVerifyResult& hapVerifyV1Result)
122 {
123     SignatureInfo hapSignInfo;
124     if (!HapSigningBlockUtils::FindHapSignature(hapFile, hapSignInfo)) {
125         return SIGNATURE_NOT_FOUND;
126     }
127     hapVerifyV1Result.SetVersion(hapSignInfo.version);
128     hapVerifyV1Result.SetPkcs7SignBlock(hapSignInfo.hapSignatureBlock);
129     hapVerifyV1Result.SetPkcs7ProfileBlock(hapSignInfo.hapSignatureBlock);
130     hapVerifyV1Result.SetOptionalBlocks(hapSignInfo.optionBlocks);
131     Pkcs7Context pkcs7Context;
132     if (!VerifyAppPkcs7(pkcs7Context, hapSignInfo.hapSignatureBlock)) {
133         return VERIFY_APP_PKCS7_FAIL;
134     }
135     int32_t profileIndex = 0;
136     if (!HapSigningBlockUtils::GetOptionalBlockIndex(hapSignInfo.optionBlocks, PROFILE_BLOB, profileIndex)) {
137         return NO_PROFILE_BLOCK_FAIL;
138     }
139     bool profileNeedWriteCrl = false;
140     int32_t ret = VerifyAppSourceAndParseProfile(pkcs7Context,
141         hapSignInfo.optionBlocks[profileIndex].optionalBlockValue, hapVerifyV1Result, profileNeedWriteCrl);
142     if (ret != VERIFY_SUCCESS) {
143         HAPVERIFY_LOG_ERROR("APP source is not trusted");
144         return ret;
145     }
146     if (!GetDigestAndAlgorithm(pkcs7Context)) {
147         HAPVERIFY_LOG_ERROR("Get digest failed");
148         return GET_DIGEST_FAIL;
149     }
150     std::vector<std::string> publicKeys;
151     if (!HapVerifyOpensslUtils::GetPublickeys(pkcs7Context.certChains[0], publicKeys)) {
152         HAPVERIFY_LOG_ERROR("Get publicKeys failed");
153         return GET_PUBLICKEY_FAIL;
154     }
155     hapVerifyV1Result.SetPublicKey(publicKeys);
156     std::vector<std::string> certSignatures;
157     if (!HapVerifyOpensslUtils::GetSignatures(pkcs7Context.certChains[0], certSignatures)) {
158         HAPVERIFY_LOG_ERROR("Get sianatures failed");
159         return GET_SIGNATURE_FAIL;
160     }
161     hapVerifyV1Result.SetSignature(certSignatures);
162     if (!HapSigningBlockUtils::VerifyHapIntegrity(pkcs7Context, hapFile, hapSignInfo)) {
163         HAPVERIFY_LOG_ERROR("Verify Integrity failed");
164         return VERIFY_INTEGRITY_FAIL;
165     }
166     WriteCrlIfNeed(pkcs7Context, profileNeedWriteCrl);
167     return VERIFY_SUCCESS;
168 }
169 
VerifyAppPkcs7(Pkcs7Context & pkcs7Context,const HapByteBuffer & hapSignatureBlock)170 bool HapVerifyV2::VerifyAppPkcs7(Pkcs7Context& pkcs7Context, const HapByteBuffer& hapSignatureBlock)
171 {
172     const unsigned char* pkcs7Block = reinterpret_cast<const unsigned char*>(hapSignatureBlock.GetBufferPtr());
173     uint32_t pkcs7Len = static_cast<unsigned int>(hapSignatureBlock.GetCapacity());
174     if (!HapVerifyOpensslUtils::ParsePkcs7Package(pkcs7Block, pkcs7Len, pkcs7Context)) {
175         HAPVERIFY_LOG_ERROR("parse pkcs7 failed");
176         return false;
177     }
178     if (!HapVerifyOpensslUtils::GetCertChains(pkcs7Context.p7, pkcs7Context)) {
179         HAPVERIFY_LOG_ERROR("GetCertChains from pkcs7 failed");
180         return false;
181     }
182     if (!HapVerifyOpensslUtils::VerifyPkcs7(pkcs7Context)) {
183         HAPVERIFY_LOG_ERROR("verify signature failed");
184         return false;
185     }
186     return true;
187 }
188 
VerifyAppSourceAndParseProfile(Pkcs7Context & pkcs7Context,const HapByteBuffer & hapProfileBlock,HapVerifyResult & hapVerifyV1Result,bool & profileNeadWriteCrl)189 int32_t HapVerifyV2::VerifyAppSourceAndParseProfile(Pkcs7Context& pkcs7Context,
190     const HapByteBuffer& hapProfileBlock, HapVerifyResult& hapVerifyV1Result, bool& profileNeadWriteCrl)
191 {
192     std::string certSubject;
193     if (!HapCertVerifyOpensslUtils::GetSubjectFromX509(pkcs7Context.certChains[0][0], certSubject)) {
194         HAPVERIFY_LOG_ERROR("Get info of sign cert failed");
195         return APP_SOURCE_NOT_TRUSTED;
196     }
197     HAPVERIFY_LOG_DEBUG("App signature subject: %{private}s, issuer: %{public}s",
198         certSubject.c_str(), pkcs7Context.certIssuer.c_str());
199 
200     TrustedSourceManager& trustedSourceManager = TrustedSourceManager::GetInstance();
201     pkcs7Context.matchResult = trustedSourceManager.IsTrustedSource(certSubject, pkcs7Context.certIssuer,
202         HAP_SIGN_BLOB, pkcs7Context.certChains[0].size());
203 
204     if (pkcs7Context.matchResult.matchState == MATCH_WITH_SIGN &&
205         pkcs7Context.matchResult.rootCa != pkcs7Context.rootCa) {
206         HAPVERIFY_LOG_ERROR("MatchRootCa failed, target rootCa: %{public}s, rootCa in pkcs7: %{public}s",
207             pkcs7Context.matchResult.rootCa.c_str(), pkcs7Context.rootCa.c_str());
208         return APP_SOURCE_NOT_TRUSTED;
209     }
210 
211     Pkcs7Context profileContext;
212     std::string profile;
213     if (!HapProfileVerifyUtils::ParseProfile(profileContext, pkcs7Context, hapProfileBlock, profile)) {
214         HAPVERIFY_LOG_ERROR("Parse profile pkcs7 failed");
215         return APP_SOURCE_NOT_TRUSTED;
216     }
217 
218     if (!VerifyProfileSignature(pkcs7Context, profileContext)) {
219         HAPVERIFY_LOG_ERROR("VerifyProfileSignature failed");
220         return APP_SOURCE_NOT_TRUSTED;
221     }
222     /*
223      * If app source is not trusted, verify profile.
224      * If profile is debug, check whether app signed cert is same as the debug cert in profile.
225      * If profile is release, do not allow installation of this app.
226      */
227     bool isCallParseAndVerify = false;
228     ProvisionInfo provisionInfo;
229     if (pkcs7Context.matchResult.matchState == DO_NOT_MATCH) {
230         if (!HapProfileVerifyUtils::VerifyProfile(profileContext)) {
231             HAPVERIFY_LOG_ERROR("profile verify failed");
232             return APP_SOURCE_NOT_TRUSTED;
233         }
234         if (profileContext.matchResult.rootCa != pkcs7Context.rootCa) {
235             HAPVERIFY_LOG_ERROR("MatchProfileRootCa failed, target rootCa: %{public}s, rootCa in profile: %{public}s",
236                 profileContext.matchResult.rootCa.c_str(), pkcs7Context.rootCa.c_str());
237             return APP_SOURCE_NOT_TRUSTED;
238         }
239         AppProvisionVerifyResult profileRet = ParseAndVerify(profile, provisionInfo);
240         if (profileRet != PROVISION_OK) {
241             HAPVERIFY_LOG_ERROR("profile parsing failed, error: %{public}d", static_cast<int>(profileRet));
242             if (profileRet == PROVISION_DEVICE_UNAUTHORIZED) {
243                 return DEVICE_UNAUTHORIZED;
244             }
245             return APP_SOURCE_NOT_TRUSTED;
246         }
247         if (!VerifyProfileInfo(pkcs7Context, profileContext, provisionInfo)) {
248             HAPVERIFY_LOG_ERROR("VerifyProfileInfo failed");
249             return APP_SOURCE_NOT_TRUSTED;
250         }
251         isCallParseAndVerify = true;
252     }
253 
254     AppProvisionVerifyResult profileRet = ParseAndVerifyProfileIfNeed(profile, provisionInfo, isCallParseAndVerify);
255     if (profileRet != PROVISION_OK) {
256         if (profileRet == PROVISION_DEVICE_UNAUTHORIZED) {
257             return DEVICE_UNAUTHORIZED;
258         }
259         return APP_SOURCE_NOT_TRUSTED;
260     }
261 
262     if (!GenerateAppId(provisionInfo) || !GenerateFingerprint(provisionInfo)) {
263         HAPVERIFY_LOG_ERROR("Generate appId or generate fingerprint failed");
264         return APP_SOURCE_NOT_TRUSTED;
265     }
266     SetOrganization(provisionInfo);
267     SetProfileBlockData(pkcs7Context, hapProfileBlock, provisionInfo);
268     provisionInfo.isOpenHarmony = OPENHARMONY_CERT == pkcs7Context.rootCa;
269 
270     hapVerifyV1Result.SetProvisionInfo(provisionInfo);
271     profileNeadWriteCrl = profileContext.needWriteCrl;
272     return VERIFY_SUCCESS;
273 }
274 
VerifyProfileSignature(const Pkcs7Context & pkcs7Context,Pkcs7Context & profileContext)275 bool HapVerifyV2::VerifyProfileSignature(const Pkcs7Context& pkcs7Context, Pkcs7Context& profileContext)
276 {
277     if (pkcs7Context.matchResult.matchState == MATCH_WITH_SIGN &&
278         (pkcs7Context.matchResult.source == APP_THIRD_PARTY_PRELOAD ||
279         pkcs7Context.matchResult.source == APP_SYSTEM)) {
280         if (!HapProfileVerifyUtils::VerifyProfile(profileContext)) {
281             HAPVERIFY_LOG_ERROR("profile verify failed");
282             return false;
283         }
284     }
285     return true;
286 }
287 
GenerateAppId(ProvisionInfo & provisionInfo)288 bool HapVerifyV2::GenerateAppId(ProvisionInfo& provisionInfo)
289 {
290     std::string& certInProfile = provisionInfo.bundleInfo.distributionCertificate;
291     if (provisionInfo.bundleInfo.distributionCertificate.empty()) {
292         certInProfile = provisionInfo.bundleInfo.developmentCertificate;
293         HAPVERIFY_LOG_DEBUG("use development Certificate");
294     }
295     std::string publicKey;
296     if (!HapCertVerifyOpensslUtils::GetPublickeyBase64FromPemCert(certInProfile, publicKey)) {
297         return false;
298     }
299     provisionInfo.appId = publicKey;
300     HAPVERIFY_LOG_DEBUG("provisionInfo.appId: %{public}s", provisionInfo.appId.c_str());
301     return true;
302 }
303 
GenerateFingerprint(ProvisionInfo & provisionInfo)304 bool HapVerifyV2::GenerateFingerprint(ProvisionInfo& provisionInfo)
305 {
306     std::string& certInProfile = provisionInfo.bundleInfo.distributionCertificate;
307     if (provisionInfo.bundleInfo.distributionCertificate.empty()) {
308         certInProfile = provisionInfo.bundleInfo.developmentCertificate;
309         HAPVERIFY_LOG_DEBUG("use development Certificate");
310     }
311     std::string fingerprint;
312     if (!HapCertVerifyOpensslUtils::GetFingerprintBase64FromPemCert(certInProfile, fingerprint)) {
313         HAPVERIFY_LOG_ERROR("Generate fingerprint from pem certificate failed");
314         return false;
315     }
316     provisionInfo.fingerprint = fingerprint;
317     HAPVERIFY_LOG_DEBUG("fingerprint is : %{private}s", fingerprint.c_str());
318     return true;
319 }
320 
SetProfileBlockData(const Pkcs7Context & pkcs7Context,const HapByteBuffer & hapProfileBlock,ProvisionInfo & provisionInfo)321 void HapVerifyV2::SetProfileBlockData(const Pkcs7Context& pkcs7Context, const HapByteBuffer& hapProfileBlock,
322     ProvisionInfo& provisionInfo)
323 {
324     if (pkcs7Context.matchResult.matchState == MATCH_WITH_SIGN &&
325         pkcs7Context.matchResult.source == APP_GALLARY) {
326         HAPVERIFY_LOG_DEBUG("profile is from app gallary and unnecessary to set profile block");
327         return;
328     }
329     provisionInfo.profileBlockLength = hapProfileBlock.GetCapacity();
330     HAPVERIFY_LOG_DEBUG("profile block data length is %{public}d", provisionInfo.profileBlockLength);
331     if (provisionInfo.profileBlockLength == 0) {
332         HAPVERIFY_LOG_ERROR("invalid profile block");
333         return;
334     }
335     provisionInfo.profileBlock = std::make_unique<unsigned char[]>(provisionInfo.profileBlockLength);
336     unsigned char *profileBlockData = provisionInfo.profileBlock.get();
337     const unsigned char *originalProfile = reinterpret_cast<const unsigned char*>(hapProfileBlock.GetBufferPtr());
338     if (profileBlockData == nullptr || originalProfile ==nullptr) {
339         HAPVERIFY_LOG_ERROR("invalid profileBlockData or originalProfile");
340         return;
341     }
342     if (memcpy_s(profileBlockData, provisionInfo.profileBlockLength, originalProfile,
343         provisionInfo.profileBlockLength) != 0) {
344         HAPVERIFY_LOG_ERROR("memcpy failed");
345     }
346 }
347 
VerifyProfileInfo(const Pkcs7Context & pkcs7Context,const Pkcs7Context & profileContext,ProvisionInfo & provisionInfo)348 bool HapVerifyV2::VerifyProfileInfo(const Pkcs7Context& pkcs7Context, const Pkcs7Context& profileContext,
349     ProvisionInfo& provisionInfo)
350 {
351     if (!CheckProfileSignatureIsRight(profileContext.matchResult.matchState, provisionInfo.type)) {
352         return false;
353     }
354     std::string& certInProfile = provisionInfo.bundleInfo.developmentCertificate;
355     if (provisionInfo.type == ProvisionType::RELEASE) {
356         if (!IsAppDistributedTypeAllowInstall(provisionInfo.distributionType, provisionInfo)) {
357             HAPVERIFY_LOG_ERROR("untrusted source app with release profile distributionType: %{public}d",
358                 static_cast<int>(provisionInfo.distributionType));
359             return false;
360         }
361         certInProfile = provisionInfo.bundleInfo.distributionCertificate;
362         HAPVERIFY_LOG_DEBUG("allow install app with release profile distributionType: %{public}d",
363             static_cast<int>(provisionInfo.distributionType));
364     }
365     HAPVERIFY_LOG_DEBUG("provisionInfo.type: %{public}d", static_cast<int>(provisionInfo.type));
366     if (!HapCertVerifyOpensslUtils::CompareX509Cert(pkcs7Context.certChains[0][0], certInProfile)) {
367         HAPVERIFY_LOG_ERROR("developed cert is not same as signed cert");
368         return false;
369     }
370     return true;
371 }
372 
IsAppDistributedTypeAllowInstall(const AppDistType & type,const ProvisionInfo & provisionInfo) const373 bool HapVerifyV2::IsAppDistributedTypeAllowInstall(const AppDistType& type, const ProvisionInfo& provisionInfo) const
374 {
375     switch (type) {
376         case AppDistType::NONE_TYPE:
377             return false;
378         case AppDistType::APP_GALLERY:
379             if (CheckTicketSource(provisionInfo)) {
380                 HAPVERIFY_LOG_INFO("current device is allowed to install opentest application");
381                 return true;
382             }
383             return false;
384         case AppDistType::ENTERPRISE:
385         case AppDistType::ENTERPRISE_NORMAL:
386         case AppDistType::ENTERPRISE_MDM:
387         case AppDistType::OS_INTEGRATION:
388         case AppDistType::CROWDTESTING:
389         case AppDistType::INTERNALTESTING:
390             return true;
391         default:
392             return false;
393     }
394 }
395 
CheckProfileSignatureIsRight(const MatchingStates & matchState,const ProvisionType & type)396 bool HapVerifyV2::CheckProfileSignatureIsRight(const MatchingStates& matchState, const ProvisionType& type)
397 {
398     if (matchState == MATCH_WITH_PROFILE && type == ProvisionType::RELEASE) {
399         return true;
400     } else if (matchState == MATCH_WITH_PROFILE_DEBUG && type == ProvisionType::DEBUG) {
401         return true;
402     }
403     HAPVERIFY_LOG_ERROR("isTrustedSource: %{public}d is not match with profile type: %{public}d",
404         static_cast<int>(matchState), static_cast<int>(type));
405     return false;
406 }
407 
WriteCrlIfNeed(const Pkcs7Context & pkcs7Context,const bool & profileNeedWriteCrl)408 void HapVerifyV2::WriteCrlIfNeed(const Pkcs7Context& pkcs7Context, const bool& profileNeedWriteCrl)
409 {
410     if (!pkcs7Context.needWriteCrl && !profileNeedWriteCrl) {
411         return;
412     }
413     HapCrlManager& hapCrlManager = HapCrlManager::GetInstance();
414     hapCrlManager.WriteCrlsToFile();
415 }
416 
ParseAndVerifyProfileIfNeed(const std::string & profile,ProvisionInfo & provisionInfo,bool isCallParseAndVerify)417 AppProvisionVerifyResult HapVerifyV2::ParseAndVerifyProfileIfNeed(const std::string& profile,
418     ProvisionInfo& provisionInfo, bool isCallParseAndVerify)
419 {
420     if (isCallParseAndVerify) {
421         return PROVISION_OK;
422     }
423     AppProvisionVerifyResult profileRet = ParseAndVerify(profile, provisionInfo);
424     if (profileRet != PROVISION_OK) {
425         HAPVERIFY_LOG_ERROR("profile parse failed, error: %{public}d", static_cast<int>(profileRet));
426         return profileRet;
427     }
428     return PROVISION_OK;
429 }
430 
GetDigestAndAlgorithm(Pkcs7Context & digest)431 bool HapVerifyV2::GetDigestAndAlgorithm(Pkcs7Context& digest)
432 {
433     /*
434      * contentinfo format:
435      * int: version
436      * int: block number
437      * digest blocks:
438      * each digest block format:
439      * int: length of sizeof(digestblock) - 4
440      * int: Algorithm ID
441      * int: length of digest
442      * byte[]: digest
443      */
444     /* length of sizeof(digestblock - 4) */
445     int32_t digestBlockLen;
446     if (!digest.content.GetInt32(DIGEST_BLOCK_LEN_OFFSET, digestBlockLen)) {
447         HAPVERIFY_LOG_ERROR("get digestBlockLen failed");
448         return false;
449     }
450     /* Algorithm ID */
451     if (!digest.content.GetInt32(DIGEST_ALGORITHM_OFFSET, digest.digestAlgorithm)) {
452         HAPVERIFY_LOG_ERROR("get digestAlgorithm failed");
453         return false;
454     }
455     /* length of digest */
456     int32_t digestlen;
457     if (!digest.content.GetInt32(DIGEST_LEN_OFFSET, digestlen)) {
458         HAPVERIFY_LOG_ERROR("get digestlen failed");
459         return false;
460     }
461 
462     int32_t sum = sizeof(digestlen) + sizeof(digest.digestAlgorithm) + digestlen;
463     if (sum != digestBlockLen) {
464         HAPVERIFY_LOG_ERROR("digestBlockLen: %{public}d is not equal to sum: %{public}d",
465             digestBlockLen, sum);
466         return false;
467     }
468     /* set position to the digest start point */
469     digest.content.SetPosition(DIGEST_OFFSET_IN_CONTENT);
470     /* set limit to the digest end point */
471     digest.content.SetLimit(DIGEST_OFFSET_IN_CONTENT + digestlen);
472     digest.content.Slice();
473     return true;
474 }
475 
ParseHapProfile(const std::string & filePath,HapVerifyResult & hapVerifyV1Result,bool readFile)476 int32_t HapVerifyV2::ParseHapProfile(const std::string& filePath, HapVerifyResult& hapVerifyV1Result, bool readFile)
477 {
478     HAPVERIFY_LOG_INFO("start to ParseHapProfile");
479     std::string standardFilePath;
480     if (!CheckFilePath(filePath, standardFilePath)) {
481         return FILE_PATH_INVALID;
482     }
483 
484     RandomAccessFile hapFile;
485     if (!hapFile.Init(standardFilePath, readFile)) {
486         HAPVERIFY_LOG_ERROR("open standard file failed");
487         return OPEN_FILE_ERROR;
488     }
489 
490     SignatureInfo hapSignInfo;
491     if (!HapSigningBlockUtils::FindHapSignature(hapFile, hapSignInfo)) {
492         return SIGNATURE_NOT_FOUND;
493     }
494 
495     int32_t profileIndex = 0;
496     if (!HapSigningBlockUtils::GetOptionalBlockIndex(hapSignInfo.optionBlocks, PROFILE_BLOB, profileIndex)) {
497         return NO_PROFILE_BLOCK_FAIL;
498     }
499     auto pkcs7ProfileBlock = hapSignInfo.optionBlocks[profileIndex].optionalBlockValue;
500     const unsigned char* pkcs7Block = reinterpret_cast<const unsigned char*>(pkcs7ProfileBlock.GetBufferPtr());
501     uint32_t pkcs7Len = static_cast<unsigned int>(pkcs7ProfileBlock.GetCapacity());
502     Pkcs7Context profileContext;
503     if (!HapVerifyOpensslUtils::ParsePkcs7Package(pkcs7Block, pkcs7Len, profileContext)) {
504         HAPVERIFY_LOG_ERROR("parse pkcs7 failed");
505         return false;
506     }
507     std::string profile = std::string(profileContext.content.GetBufferPtr(), profileContext.content.GetCapacity());
508     HAPVERIFY_LOG_DEBUG("profile is %{public}s", profile.c_str());
509     ProvisionInfo info;
510     auto ret = ParseProfile(profile, info);
511     if (ret != PROVISION_OK) {
512         return PROFILE_PARSE_FAIL;
513     }
514 
515     if (!GenerateFingerprint(info)) {
516         HAPVERIFY_LOG_ERROR("Generate appId or generate fingerprint failed");
517         return PROFILE_PARSE_FAIL;
518     }
519     SetOrganization(info);
520     hapVerifyV1Result.SetProvisionInfo(info);
521     return VERIFY_SUCCESS;
522 }
523 
ParseHapSignatureInfo(const std::string & filePath,SignatureInfo & hapSignInfo)524 int32_t HapVerifyV2::ParseHapSignatureInfo(const std::string& filePath, SignatureInfo &hapSignInfo)
525 {
526     std::string standardFilePath;
527     if (!CheckFilePath(filePath, standardFilePath)) {
528         return FILE_PATH_INVALID;
529     }
530 
531     RandomAccessFile hapFile;
532     if (!hapFile.Init(standardFilePath)) {
533         HAPVERIFY_LOG_ERROR("open standard file failed");
534         return OPEN_FILE_ERROR;
535     }
536 
537     if (!HapSigningBlockUtils::FindHapSignature(hapFile, hapSignInfo)) {
538         return SIGNATURE_NOT_FOUND;
539     }
540     return VERIFY_SUCCESS;
541 }
542 
SetOrganization(ProvisionInfo & provisionInfo)543 void HapVerifyV2::SetOrganization(ProvisionInfo& provisionInfo)
544 {
545     std::string& certInProfile = provisionInfo.bundleInfo.distributionCertificate;
546     if (provisionInfo.bundleInfo.distributionCertificate.empty()) {
547         HAPVERIFY_LOG_ERROR("distributionCertificate is empty");
548         return;
549     }
550     std::string organization;
551     if (!HapCertVerifyOpensslUtils::GetOrganizationFromPemCert(certInProfile, organization)) {
552         HAPVERIFY_LOG_ERROR("Generate organization from pem certificate failed");
553         return;
554     }
555     provisionInfo.organization = organization;
556 }
557 
VerifyProfile(const std::string & filePath,ProvisionInfo & provisionInfo)558 int32_t HapVerifyV2::VerifyProfile(const std::string& filePath, ProvisionInfo& provisionInfo)
559 {
560     HAPVERIFY_LOG_INFO("start to VerifyProfile");
561     std::string standardFilePath;
562     if (!CheckP7bPath(filePath, standardFilePath)) {
563         return FILE_PATH_INVALID;
564     }
565     Pkcs7Context pkcs7Context;
566     if (!ParseProfileFromP7b(filePath, pkcs7Context)) {
567         return PROFILE_PARSE_FAIL;
568     }
569     std::string profile = std::string(pkcs7Context.content.GetBufferPtr(), pkcs7Context.content.GetCapacity());
570     if (!HapProfileVerifyUtils::VerifyProfile(pkcs7Context)) {
571         HAPVERIFY_LOG_ERROR("profile verify failed");
572         return APP_SOURCE_NOT_TRUSTED;
573     }
574     AppProvisionVerifyResult profileRet = ParseAndVerify(profile, provisionInfo);
575     if (profileRet != PROVISION_OK) {
576         HAPVERIFY_LOG_ERROR("profile parsing failed, error: %{public}d", static_cast<int>(profileRet));
577         if (profileRet == PROVISION_DEVICE_UNAUTHORIZED) {
578             return DEVICE_UNAUTHORIZED;
579         }
580         return APP_SOURCE_NOT_TRUSTED;
581     }
582     return VERIFY_SUCCESS;
583 }
584 
ParseProfileFromP7b(const std::string & p7bFilePath,Pkcs7Context & pkcs7Context)585 bool HapVerifyV2::ParseProfileFromP7b(const std::string& p7bFilePath, Pkcs7Context& pkcs7Context)
586 {
587     int32_t fd = open(p7bFilePath.c_str(), O_RDONLY);
588     if (fd < 0) {
589         HAPVERIFY_LOG_ERROR("open p7b file failed, path: %{public}s", p7bFilePath.c_str());
590         return false;
591     }
592     struct stat st;
593     if (fstat(fd, &st) < 0 || st.st_size <= 0) {
594         HAPVERIFY_LOG_ERROR("fstat p7b file failed, path: %{public}s", p7bFilePath.c_str());
595         close(fd);
596         return false;
597     }
598     std::vector<unsigned char> buffer(st.st_size);
599     ssize_t readSize = pread(fd, buffer.data(), st.st_size, 0);
600     if (readSize < 0 || static_cast<size_t>(readSize) != buffer.size()) {
601         HAPVERIFY_LOG_ERROR("pread p7b file failed, path: %{public}s, error: %{public}d", p7bFilePath.c_str(), errno);
602         close(fd);
603         return false;
604     }
605     close(fd);
606     const unsigned char* p7bData = buffer.data();
607     uint32_t p7bLen = static_cast<uint32_t>(buffer.size());
608     if (!HapVerifyOpensslUtils::ParsePkcs7Package(p7bData, p7bLen, pkcs7Context)) {
609         HAPVERIFY_LOG_ERROR("parse p7b failed, path: %{public}s", p7bFilePath.c_str());
610         return false;
611     }
612     return true;
613 }
614 } // namespace Verify
615 } // namespace Security
616 } // namespace OHOS
617