• 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 "verify_elf.h"
17 
18 #include <fstream>
19 #include "constant.h"
20 #include "signature_tools_log.h"
21 #include "verify_hap_openssl_utils.h"
22 
23 namespace OHOS {
24 namespace SignatureTools {
25 
26 const int FLAG_SELF_SIGN = 1 << 4;
27 const std::string VerifyElf::codesignSec = ".codesign";
28 const std::string VerifyElf::profileSec = ".profile";
29 const std::string VerifyElf::permissionSec = ".permission";
30 
Verify(Options * options)31 bool VerifyElf::Verify(Options* options)
32 {
33     // check param
34     if (options == nullptr) {
35         PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "Param options is null.");
36         return false;
37     }
38     std::string elfFile = options->GetString(Options::IN_FILE);
39     ELFIO::elfio elfReader;
40     if (!elfReader.load(elfFile)) {
41         SIGNATURE_TOOLS_LOGE("failed to load input ELF file");
42         return false;
43     }
44     // get codesignSec section
45     bool signFlag = ParseSignBlock(elfReader);
46     if (!signFlag) {
47         return false;
48     }
49     return true;
50 }
51 
ParseSignBlock(const ELFIO::elfio & elfReader)52 bool VerifyElf::ParseSignBlock(const ELFIO::elfio& elfReader)
53 {
54     ELFIO::section* sec = elfReader.sections[codesignSec];
55     if (!sec) {
56         PrintMsg("code signature is not found");
57         return true;
58     }
59     ELFIO::Elf64_Off secOffElf64 = sec->get_offset();
60     uint64_t secOff = static_cast<uint64_t>(secOffElf64);
61     if (secOff % PAGE_SIZE != 0) {
62         SIGNATURE_TOOLS_LOGE("code signature section offset is not aligned");
63         return false;
64     }
65     const char* data = sec->get_data();
66     uint64_t csBlockSize = sec->get_size();
67     if (csBlockSize == 0 || csBlockSize % PAGE_SIZE != 0) {
68         SIGNATURE_TOOLS_LOGE("code signature section size is not aligned");
69         return false;
70     }
71     const ElfSignInfo* signInfo = reinterpret_cast<const ElfSignInfo*>(data);
72     if ((signInfo->flags & FLAG_SELF_SIGN) == FLAG_SELF_SIGN) {
73         PrintMsg("code signature is self-sign");
74         return true;
75     }
76     Pkcs7Context pkcs7Context;
77     auto signData = reinterpret_cast<const unsigned char*>(signInfo->signature);
78 
79     PKCS7* p7 = d2i_PKCS7(nullptr, &signData, signInfo->signSize);
80     if (p7 == nullptr || !PKCS7_type_is_signed(p7) || p7->d.sign == nullptr) {
81         SIGNATURE_TOOLS_LOGE("sign data to pcs7 failed");
82         return false;
83     }
84     if (!VerifyHapOpensslUtils::GetCertChains(p7, pkcs7Context)) {
85         SIGNATURE_TOOLS_LOGE("GetCertChains form pkcs7 failed");
86         return false;
87     }
88     if (!PrintCertChainToCmd(pkcs7Context.certChain[0])) {
89         SIGNATURE_TOOLS_LOGE("print cert chain to cmd failed");
90         return false;
91     }
92     return true;
93 }
94 
PrintCertChainToCmd(std::vector<X509 * > & certChain)95 bool VerifyElf::PrintCertChainToCmd(std::vector<X509*>& certChain)
96 {
97     BIO* outFd = BIO_new_fp(stdout, BIO_NOCLOSE);
98     if (!outFd) {
99         PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "The stdout stream may have errors");
100         return false;
101     }
102     uint64_t format = XN_FLAG_SEP_COMMA_PLUS; // Print according to RFC2253
103     uint64_t content = X509_FLAG_NO_EXTENSIONS | X509_FLAG_NO_ATTRIBUTES | X509_FLAG_NO_HEADER | X509_FLAG_NO_SIGDUMP;
104     int num = 0;
105     for (auto& cert : certChain) {
106         PrintMsg("+++++++++++++++++++++++++++++++++certificate #" + std::to_string(num) +
107                  "+++++++++++++++++++++++++++++++++++++");
108         if (!X509_print_ex(outFd, cert, format, content)) {
109             VerifyHapOpensslUtils::GetOpensslErrorMessage();
110             SIGNATURE_TOOLS_LOGE("print x509 cert to cmd failed");
111             BIO_free(outFd);
112             return false;
113         }
114         ++num;
115     }
116     BIO_free(outFd);
117     return true;
118 }
119 
120 } // namespace SignatureTools
121 } // namespace OHOS