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