• 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 <algorithm>
17 
18 #include "fs_verity_descriptor.h"
19 #include "fs_verity_descriptor_with_sign.h"
20 #include "code_signing.h"
21 
22 namespace OHOS {
23 namespace SignatureTools {
24 
25 const FsVerityHashAlgorithm FS_SHA256(1, "SHA-256", 256 / 8);
26 const FsVerityHashAlgorithm FS_SHA512(2, "SHA-512", 512 / 8);
27 const int8_t LOG_2_OF_FSVERITY_HASH_PAGE_SIZE = 12;
28 const int FLAG_SELF_SIGN = 1 << 4;
29 const uint8_t ELF_CODE_SIGN_VERSION = 0x3;
30 
CodeSigning(SignerConfig * signConfig,bool selfSign)31 CodeSigning::CodeSigning(SignerConfig* signConfig, bool selfSign)
32 {
33     m_signConfig = signConfig;
34     m_selfSign = selfSign;
35 }
36 
CodeSigning()37 CodeSigning::CodeSigning()
38 {
39 }
40 
GetElfCodeSignBlock(const std::string & input,uint64_t & csOffset,std::vector<int8_t> & codesignData)41 bool CodeSigning::GetElfCodeSignBlock(const std::string &input, uint64_t& csOffset, std::vector<int8_t>& codesignData)
42 {
43     SIGNATURE_TOOLS_LOGI("Start to sign elf code.");
44     std::ifstream inputstream(input, std::ios::binary | std::ios::ate);
45     if (!inputstream.is_open()) {
46         PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "open file: " + input + "failed");
47         return false;
48     }
49     int flags = 0;
50     if (m_selfSign) {
51         flags = flags | FLAG_SELF_SIGN;
52     }
53     std::streamsize fileSize = inputstream.tellg();
54     inputstream.seekg(0, std::ios::beg);
55     std::unique_ptr<FsVerityGenerator> fsVerityGenerator = std::make_unique<FsVerityGenerator>();
56     fsVerityGenerator->SetCsOffset(csOffset);
57     fsVerityGenerator->GenerateFsVerityDigest(inputstream, fileSize, flags);
58     std::vector<int8_t> signature;
59 
60     if (!m_selfSign) {
61         std::string ownerID;
62         GetOwnerIdFromCert(ownerID);
63         std::vector<int8_t> fsVerityDigest = fsVerityGenerator->GetFsVerityDigest();
64         bool generateSignatureFlag = GenerateSignature(fsVerityDigest, ownerID, signature);
65         if (!generateSignatureFlag) {
66             SIGNATURE_TOOLS_LOGE("[SignElf] generate elf signature failed");
67             return false;
68         }
69     } else {
70         signature = fsVerityGenerator->GetDescriptorDigest();
71     }
72 
73     FsVerityDescriptor::Builder fsdbuilder;
74     fsdbuilder.SetFileSize(fileSize)
75               .SetHashAlgorithm(FS_SHA256.GetId())
76               .SetLog2BlockSize(LOG_2_OF_FSVERITY_HASH_PAGE_SIZE)
77               .SetSaltSize(fsVerityGenerator->GetSaltSize())
78               .SetSignSize(signature.size())
79               .SetSalt(fsVerityGenerator->GetSalt())
80               .SetRawRootHash(fsVerityGenerator->GetRootHash())
81               .SetFlags(flags)
82               .SetCsVersion(ELF_CODE_SIGN_VERSION);
83 
84     FsVerityDescriptorWithSign fsVerityDescriptorWithSign =
85         FsVerityDescriptorWithSign(FsVerityDescriptor(fsdbuilder), signature);
86     std::vector<int8_t> treeBytes = fsVerityGenerator->GetTreeBytes();
87     fsVerityDescriptorWithSign.ToByteArray(codesignData);
88     return true;
89 }
90 
GenerateSignature(const std::vector<int8_t> & signedData,const std::string & ownerID,std::vector<int8_t> & ret)91 bool CodeSigning::GenerateSignature(const std::vector<int8_t>& signedData, const std::string& ownerID,
92                                     std::vector<int8_t>& ret)
93 {
94     if (m_signConfig->GetSigner() != nullptr) {
95         STACK_OF(X509)* certs = NULL;
96         certs = m_signConfig->GetSigner()->GetCertificates();
97         if (certs == nullptr) {
98             PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR, "No certificates configured for sign.");
99             return false;
100         }
101         sk_X509_pop_free(certs, X509_free);
102     } else {
103         return false;
104     }
105     std::unique_ptr<BCSignedDataGenerator> bcSignedDataGenerator =
106         std::make_unique<BCSignedDataGenerator>();
107     if (!ownerID.empty()) {
108         SIGNATURE_TOOLS_LOGW("generate signature get owner id not null.");
109         bcSignedDataGenerator->SetOwnerId(ownerID);
110     }
111     std::string signed_data(signedData.begin(), signedData.end());
112     std::string ret_str;
113     if (signedData.empty()) {
114         PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR, "Generate verity digest is null");
115         return false;
116     }
117     bool generateSignedDataFlag = bcSignedDataGenerator->GenerateSignedData(signed_data, m_signConfig, ret_str);
118     if (generateSignedDataFlag) {
119         SIGNATURE_TOOLS_LOGE("Generate signedData failed");
120         return false;
121     }
122     ret = std::vector<int8_t>(ret_str.begin(), ret_str.end());
123     return true;
124 }
125 
GetOwnerIdFromCert(std::string & ownerID)126 bool CodeSigning::GetOwnerIdFromCert(std::string& ownerID)
127 {
128     if (m_signConfig == nullptr) {
129         ownerID = "";
130         return true;
131     }
132     STACK_OF(X509)* certs = m_signConfig->GetSigner()->GetCertificates();
133     if (sk_X509_num(certs) < MIN_CERT_CHAIN_SIZE) {
134         SIGNATURE_TOOLS_LOGE("sign certs not a cert chain");
135         return false;
136     }
137     X509* cert = sk_X509_value(certs, 0);
138     X509_NAME* subject = X509_get_subject_name(cert);
139     VerifyCertOpensslUtils::GetTextFromX509Name(subject, NID_organizationalUnitName, ownerID);
140     SIGNATURE_TOOLS_LOGI("organizationalUnitName = %s.", ownerID.c_str());
141     return true;
142 }
143 } // namespace SignatureTools
144 } // namespace OHOS
145