• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-2024 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 #include <numeric>
16 
17 #include "signature_tools_log.h"
18 #include "signature_algorithm_helper.h"
19 #include "bc_pkcs7_generator.h"
20 #include "digest_common.h"
21 #include "sign_hap.h"
22 
23 namespace OHOS {
24 namespace SignatureTools {
Sign(DataSource * contents[],int32_t len,SignerConfig & config,std::vector<OptionalBlock> & optionalBlocks,ByteBuffer & result)25 bool SignHap::Sign(DataSource* contents[], int32_t len, SignerConfig& config,
26                    std::vector<OptionalBlock>& optionalBlocks, ByteBuffer& result)
27 {
28     if (len != CONTENT_NUBER) {
29         PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR,
30                             "zip contents len must is 3, now is " + std::to_string(len));
31         return false;
32     }
33     std::vector<SignatureAlgorithmHelper> algoClass = config.GetSignatureAlgorithms();
34     if (algoClass.empty()) {
35         PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR, "Signature Algorithms is empty");
36         return false;
37     }
38     SignatureAlgorithm algo = static_cast<SignatureAlgorithm>(algoClass[0].m_id);
39     SIGNATURE_TOOLS_LOGI("[SignHap] Signature Algorithm  is %d", algo);
40     int32_t nId = DigestCommon::GetDigestAlgorithmId(algo);
41     DigestParameter digestParam = HapSignerBlockUtils::GetDigestParameter(nId);
42     ByteBuffer digContext;
43     std::vector<std::pair<int32_t, ByteBuffer>> nidAndcontentDigestsVec;
44     // 1:Summarize corresponding content and optionalBlock
45     if (!ComputeDigests(digestParam, contents, CONTENT_NUBER, optionalBlocks, digContext)) {
46         SIGNATURE_TOOLS_LOGE("[SignHap] compute Digests failed");
47         return false;
48     }
49     SIGNATURE_TOOLS_LOGI("[SignHap] ComputeDigests %d", digContext.GetCapacity());
50     // 2:Encoding Summary Information
51     ByteBuffer digMessage;
52     std::pair<int32_t, ByteBuffer> nidAndcontentDigests = std::make_pair(algo, digContext);
53     nidAndcontentDigestsVec.push_back(nidAndcontentDigests);
54     EncodeListOfPairsToByteArray(digestParam, nidAndcontentDigestsVec, digMessage);
55 
56     SIGNATURE_TOOLS_LOGI("[SignHap] EncodeListOfPairsToByteArray %d", digMessage.GetCapacity());
57     // 3:Encrypt the encoded summary information.
58     std::shared_ptr<Pkcs7Generator> pkcs7Generator = std::make_shared<BCPkcs7Generator>();
59     std::string digMessageData(digMessage.GetBufferPtr(), digMessage.GetCapacity());
60     std::string ret;
61     if (pkcs7Generator->GenerateSignedData(digMessageData, &config, ret) != 0) {
62         SIGNATURE_TOOLS_LOGE("[SignHap] Generate Signed Data failed");
63         return false;
64     }
65     SIGNATURE_TOOLS_LOGI("[SignHap] GenerateSignedData %lu", static_cast<unsigned long>(ret.size()));
66     bool checkGenerateHapSigningBlockFlag = GenerateHapSigningBlock(ret, optionalBlocks,
67                                                                     config.GetCompatibleVersion(), result);
68     if (!checkGenerateHapSigningBlockFlag) {
69         PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR, "Generate Hap Signing Block failed");
70         return false;
71     }
72     SIGNATURE_TOOLS_LOGI("[SignHap] GenerateHapSigningBlock %d", result.GetCapacity());
73     return true;
74 }
75 
ComputeDigests(const DigestParameter & digestParam,DataSource * contents[],int32_t len,const std::vector<OptionalBlock> & optionalBlocks,ByteBuffer & result)76 bool SignHap::ComputeDigests(const DigestParameter& digestParam, DataSource* contents[], int32_t len,
77                              const std::vector<OptionalBlock>& optionalBlocks, ByteBuffer& result)
78 {
79     ByteBuffer chunkDigest;
80     bool ret = HapSignerBlockUtils::ComputeDigestsForEachChunk(digestParam, contents, len, chunkDigest);
81     if (!ret) {
82         PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR, "Compute Content Digests failed");
83         return false;
84     }
85     bool checkComputeDigestsWithOptionalBlockFlag =
86         HapSignerBlockUtils::ComputeDigestsWithOptionalBlock(digestParam, optionalBlocks, chunkDigest, result);
87     if (!checkComputeDigestsWithOptionalBlockFlag) {
88         PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR, "Compute Final Digests failed");
89         return false;
90     }
91     return true;
92 }
93 
EncodeListOfPairsToByteArray(const DigestParameter & digestParam,const std::vector<std::pair<int32_t,ByteBuffer>> & nidAndcontentDigests,ByteBuffer & result)94 void SignHap::EncodeListOfPairsToByteArray(const DigestParameter& digestParam,
95                                            const std::vector<std::pair<int32_t,
96                                            ByteBuffer>>&nidAndcontentDigests, ByteBuffer& result)
97 {
98     int encodeSize = INT_SIZE * 2  + INT_SIZE * 3 * nidAndcontentDigests.size();
99     encodeSize += std::accumulate(nidAndcontentDigests.begin(), nidAndcontentDigests.end(), 0,
100         [](int sum, const std::pair<int32_t, ByteBuffer>& pair) { return sum + pair.second.GetCapacity(); });
101     result.SetCapacity(encodeSize);
102     result.PutInt32(CONTENT_VERSION); // version
103     result.PutInt32(BLOCK_NUMBER); // block number
104     for (const auto& pair : nidAndcontentDigests) {
105         auto second = pair.second;
106         result.PutInt32(INT_SIZE + INT_SIZE + second.GetCapacity());
107         result.PutInt32(pair.first);
108         result.PutInt32(second.GetCapacity());
109         result.Put(second);
110     }
111     return;
112 }
113 
GenerateHapSigningBlock(const std::string & hapSignatureSchemeBlock,std::vector<OptionalBlock> & optionalBlocks,int compatibleVersion,ByteBuffer & result)114 bool SignHap::GenerateHapSigningBlock(const std::string& hapSignatureSchemeBlock,
115                                       std::vector<OptionalBlock>& optionalBlocks,
116                                       int compatibleVersion, ByteBuffer& result)
117 {
118     // FORMAT:
119     // Proof-of-Rotation pairs(optional):
120     // uint32:type
121     // uint32:length
122     // uint32:offset
123     // Property pairs(optional):
124     // uint32:type
125     // uint32:length
126     // uint32:offset
127     // Profile capability pairs(optional):
128     // uint32:type
129     // uint32:length
130     // uint32:offset
131     // length bytes : app signing pairs
132     // uint32:type
133     // uint32:length
134     // uint32:offset
135     // repeated ID-value pairs(reserved extensions):
136     // length bytes : Proof-of-Rotation values
137     // length bytes : property values
138     // length bytes : profile capability values
139     // length bytes : signature schema values
140     // uint64: size
141     // uint128: magic
142     // uint32: version
143     long optionalBlockSize = std::accumulate(optionalBlocks.begin(), optionalBlocks.end(), 0L,
144         [](int64_t sum, const auto& elem) { return sum + elem.optionalBlockValue.GetCapacity(); });
145     long resultSize = ((OPTIONAL_TYPE_SIZE + OPTIONAL_LENGTH_SIZE + OPTIONAL_OFFSET_SIZE) *
146                        (optionalBlocks.size() + 1)) + optionalBlockSize + hapSignatureSchemeBlock.size() +
147         BLOCK_COUNT + HapUtils::BLOCK_SIZE + BLOCK_MAGIC + BLOCK_VERSION;
148     if (resultSize > INT_MAX) {
149         SIGNATURE_TOOLS_LOGE("Illegal Argument. HapSigningBlock out of range: %ld", resultSize);
150         return false;
151     }
152     result.SetCapacity((int)resultSize);
153     std::unordered_map<int, int> typeAndOffsetMap;
154     int currentOffset = ((OPTIONAL_TYPE_SIZE + OPTIONAL_LENGTH_SIZE
155                          + OPTIONAL_OFFSET_SIZE) * (optionalBlocks.size() + 1));
156     int currentOffsetInBlockValue = 0;
157     int blockValueSizes = (int)(optionalBlockSize + hapSignatureSchemeBlock.size());
158     std::string blockValues(blockValueSizes, 0);
159     for (const auto& elem : optionalBlocks) {
160         if (memcpy_s(blockValues.data() + currentOffsetInBlockValue, blockValueSizes,
161             elem.optionalBlockValue.GetBufferPtr(),
162             elem.optionalBlockValue.GetCapacity()) != 0) {
163             SIGNATURE_TOOLS_LOGE("GenerateHapSigningBlock memcpy_s failed\n");
164             return false;
165         }
166         typeAndOffsetMap.insert({ elem.optionalType, currentOffset });
167         currentOffset += elem.optionalBlockValue.GetCapacity();
168         currentOffsetInBlockValue += elem.optionalBlockValue.GetCapacity();
169     }
170     if (memcpy_s(blockValues.data() + currentOffsetInBlockValue, blockValueSizes, hapSignatureSchemeBlock.data(),
171         hapSignatureSchemeBlock.size()) != 0) {
172         SIGNATURE_TOOLS_LOGE("GenerateHapSigningBlock memcpy_s failed\n");
173         return false;
174     }
175     typeAndOffsetMap.insert({ HapUtils::HAP_SIGNATURE_SCHEME_V1_BLOCK_ID, currentOffset });
176     ExtractedResult(optionalBlocks, result, typeAndOffsetMap);
177     result.PutInt32(HapUtils::HAP_SIGNATURE_SCHEME_V1_BLOCK_ID); // type
178     result.PutInt32(hapSignatureSchemeBlock.size()); // length
179     int offset = typeAndOffsetMap.at(HapUtils::HAP_SIGNATURE_SCHEME_V1_BLOCK_ID);
180     result.PutInt32(offset); // offset
181     result.PutData(blockValues.c_str(), blockValueSizes);
182     result.PutInt32(optionalBlocks.size() + 1); // Signing block count
183     result.PutInt64(resultSize); // length of hap signing block
184     std::vector<int8_t> signingBlockMagic = HapUtils::GetHapSigningBlockMagic(compatibleVersion);
185     result.PutData(reinterpret_cast<const char*>(signingBlockMagic.data()), signingBlockMagic.size()); // magic
186     result.PutInt32(HapUtils::GetHapSigningBlockVersion(compatibleVersion)); // version
187     return true;
188 }
189 
ExtractedResult(std::vector<OptionalBlock> & optionalBlocks,ByteBuffer & result,std::unordered_map<int,int> & typeAndOffsetMap)190 void SignHap::ExtractedResult(std::vector<OptionalBlock>& optionalBlocks, ByteBuffer& result,
191                               std::unordered_map<int, int>& typeAndOffsetMap)
192 {
193     int offset;
194     for (const auto& elem : optionalBlocks) {
195         result.PutInt32(elem.optionalType);  // type
196         result.PutInt32(elem.optionalBlockValue.GetCapacity());  // length
197         offset = typeAndOffsetMap.at(elem.optionalType);
198         result.PutInt32(offset);  // offset
199     }
200 }
201 } // namespace SignatureTools
202 } // namespace OHOS