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