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 "signature_tools_log.h"
16 #include "signature_algorithm_helper.h"
17 #include "bc_pkcs7_generator.h"
18 #include "digest_common.h"
19 #include "sign_hap.h"
20
21 namespace OHOS {
22 namespace SignatureTools {
Sign(DataSource* contents[], int32_t len, SignerConfig& config, std::vector<OptionalBlock>& optionalBlocks, ByteBuffer& result)23 bool SignHap::Sign(DataSource* contents[], int32_t len, SignerConfig& config,
24 std::vector<OptionalBlock>& optionalBlocks, ByteBuffer& result)
25 {
26 if (len != CONTENT_NUBER) {
27 PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR,
28 "zip contents len must is 3, now is " + std::to_string(len));
29 return false;
30 }
31 std::vector<SignatureAlgorithmHelper> algoClass = config.GetSignatureAlgorithms();
32 if (algoClass.empty()) {
33 PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR, "Signature Algorithms is empty");
34 return false;
35 }
36 SignatureAlgorithm algo = static_cast<SignatureAlgorithm>(algoClass[0].m_id);
37 SIGNATURE_TOOLS_LOGI("[SignHap] Signature Algorithm is %d", algo);
38 int32_t nId = DigestCommon::GetDigestAlgorithmId(algo);
39 DigestParameter digestParam = HapSignerBlockUtils::GetDigestParameter(nId);
40 ByteBuffer digContext;
41 std::vector<std::pair<int32_t, ByteBuffer>> nidAndcontentDigestsVec;
42 // 1:Summarize corresponding content and optionalBlock
43 if (!ComputeDigests(digestParam, contents, CONTENT_NUBER, optionalBlocks, digContext)) {
44 SIGNATURE_TOOLS_LOGE("[SignHap] compute Digests failed");
45 return false;
46 }
47 SIGNATURE_TOOLS_LOGI("[SignHap] ComputeDigests %d", digContext.GetCapacity());
48 // 2:Encoding Summary Information
49 ByteBuffer digMessage;
50 std::pair<int32_t, ByteBuffer> nidAndcontentDigests = std::make_pair(algo, digContext);
51 nidAndcontentDigestsVec.push_back(nidAndcontentDigests);
52 EncodeListOfPairsToByteArray(digestParam, nidAndcontentDigestsVec, digMessage);
53
54 SIGNATURE_TOOLS_LOGI("[SignHap] EncodeListOfPairsToByteArray %d", digMessage.GetCapacity());
55 // 3:Encrypt the encoded summary information.
56 std::shared_ptr<Pkcs7Generator> pkcs7Generator = std::make_shared<BCPkcs7Generator>();
57 std::string digMessageData(digMessage.GetBufferPtr(), digMessage.GetCapacity());
58 std::string ret;
59 if (pkcs7Generator->GenerateSignedData(digMessageData, &config, ret) != 0) {
60 SIGNATURE_TOOLS_LOGE("[SignHap] Generate Signed Data failed");
61 return false;
62 }
63 SIGNATURE_TOOLS_LOGI("[SignHap] GenerateSignedData %lu", static_cast<unsigned long>(ret.size()));
64 bool checkGenerateHapSigningBlockFlag = GenerateHapSigningBlock(ret, optionalBlocks,
65 config.GetCompatibleVersion(), result);
66 if (!checkGenerateHapSigningBlockFlag) {
67 PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR, "Generate Hap Signing Block failed");
68 return false;
69 }
70 SIGNATURE_TOOLS_LOGI("[SignHap] GenerateHapSigningBlock %d", result.GetCapacity());
71 return true;
72 }
73
ComputeDigests(const DigestParameter& digestParam, DataSource* contents[], int32_t len, const std::vector<OptionalBlock>& optionalBlocks, ByteBuffer& result)74 bool SignHap::ComputeDigests(const DigestParameter& digestParam, DataSource* contents[], int32_t len,
75 const std::vector<OptionalBlock>& optionalBlocks, ByteBuffer& result)
76 {
77 ByteBuffer chunkDigest;
78 bool ret = HapSignerBlockUtils::ComputeDigestsForEachChunk(digestParam, contents, len, chunkDigest);
79 if (!ret) {
80 PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR, "Compute Content Digests failed");
81 return false;
82 }
83 bool checkComputeDigestsWithOptionalBlockFlag =
84 HapSignerBlockUtils::ComputeDigestsWithOptionalBlock(digestParam, optionalBlocks, chunkDigest, result);
85 if (!checkComputeDigestsWithOptionalBlockFlag) {
86 PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR, "Compute Final Digests failed");
87 return false;
88 }
89 return true;
90 }
91
EncodeListOfPairsToByteArray(const DigestParameter& digestParam, const std::vector<std::pair<int32_t, ByteBuffer>>&nidAndcontentDigests, ByteBuffer& result)92 void SignHap::EncodeListOfPairsToByteArray(const DigestParameter& digestParam,
93 const std::vector<std::pair<int32_t,
94 ByteBuffer>>&nidAndcontentDigests, ByteBuffer& result)
95 {
96 int encodeSize = 0;
97 encodeSize += INT_SIZE + INT_SIZE;
98 for (const auto& pair : nidAndcontentDigests) {
99 encodeSize += INT_SIZE + INT_SIZE + INT_SIZE + pair.second.GetCapacity();
100 }
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 = 0L;
144 for (const auto& elem : optionalBlocks) optionalBlockSize += elem.optionalBlockValue.GetCapacity();
145 long resultSize = ((OPTIONAL_TYPE_SIZE + OPTIONAL_LENGTH_SIZE + OPTIONAL_OFFSET_SIZE) *
146 (optionalBlocks.size() + 1)) +
147 optionalBlockSize +
148 hapSignatureSchemeBlock.size() +
149 BLOCK_COUNT + HapUtils::BLOCK_SIZE + BLOCK_MAGIC + BLOCK_VERSION;
150 if (resultSize > INT_MAX) {
151 SIGNATURE_TOOLS_LOGE("Illegal Argument. HapSigningBlock out of range: %ld", resultSize);
152 return false;
153 }
154 result.SetCapacity((int)resultSize);
155 std::unordered_map<int, int> typeAndOffsetMap;
156 int currentOffset = ((OPTIONAL_TYPE_SIZE + OPTIONAL_LENGTH_SIZE
157 + OPTIONAL_OFFSET_SIZE) * (optionalBlocks.size() + 1));
158 int currentOffsetInBlockValue = 0;
159 int blockValueSizes = (int)(optionalBlockSize + hapSignatureSchemeBlock.size());
160 std::string blockValues(blockValueSizes, 0);
161 for (const auto& elem : optionalBlocks) {
162 if (memcpy_s(blockValues.data() + currentOffsetInBlockValue, blockValueSizes,
163 elem.optionalBlockValue.GetBufferPtr(),
164 elem.optionalBlockValue.GetCapacity()) != 0) {
165 SIGNATURE_TOOLS_LOGE("GenerateHapSigningBlock memcpy_s failed\n");
166 return false;
167 }
168 typeAndOffsetMap.insert({ elem.optionalType, currentOffset });
169 currentOffset += elem.optionalBlockValue.GetCapacity();
170 currentOffsetInBlockValue += elem.optionalBlockValue.GetCapacity();
171 }
172 if (memcpy_s(blockValues.data() + currentOffsetInBlockValue, blockValueSizes, hapSignatureSchemeBlock.data(),
173 hapSignatureSchemeBlock.size()) != 0) {
174 SIGNATURE_TOOLS_LOGE("GenerateHapSigningBlock memcpy_s failed\n");
175 return false;
176 }
177 typeAndOffsetMap.insert({ HapUtils::HAP_SIGNATURE_SCHEME_V1_BLOCK_ID, currentOffset });
178 ExtractedResult(optionalBlocks, result, typeAndOffsetMap);
179 result.PutInt32(HapUtils::HAP_SIGNATURE_SCHEME_V1_BLOCK_ID); // type
180 result.PutInt32(hapSignatureSchemeBlock.size()); // length
181 int offset = typeAndOffsetMap.at(HapUtils::HAP_SIGNATURE_SCHEME_V1_BLOCK_ID);
182 result.PutInt32(offset); // offset
183 result.PutData(blockValues.c_str(), blockValueSizes);
184 result.PutInt32(optionalBlocks.size() + 1); // Signing block count
185 result.PutInt64(resultSize); // length of hap signing block
186 std::vector<int8_t> signingBlockMagic = HapUtils::GetHapSigningBlockMagic(compatibleVersion);
187 result.PutData((const char*)signingBlockMagic.data(), signingBlockMagic.size()); // magic
188 result.PutInt32(HapUtils::GetHapSigningBlockVersion(compatibleVersion)); // version
189 return true;
190 }
191
ExtractedResult(std::vector<OptionalBlock>& optionalBlocks, ByteBuffer& result, std::unordered_map<int, int>& typeAndOffsetMap)192 void SignHap::ExtractedResult(std::vector<OptionalBlock>& optionalBlocks, ByteBuffer& result,
193 std::unordered_map<int, int>& typeAndOffsetMap)
194 {
195 int offset;
196 for (const auto& elem : optionalBlocks) {
197 result.PutInt32(elem.optionalType); // type
198 result.PutInt32(elem.optionalBlockValue.GetCapacity()); // length
199 offset = typeAndOffsetMap.at(elem.optionalType);
200 result.PutInt32(offset); // offset
201 }
202 }
203 } // namespace SignatureTools
204 } // namespace OHOS