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
16 #include "hap_signer_block_utils.h"
17 #include <cinttypes>
18 #include <climits>
19 #include <vector>
20
21 #include "signature_info.h"
22 #include "algorithm"
23 #include "openssl/evp.h"
24 #include "securec.h"
25 #include "byte_buffer_data_source.h"
26 #include "file_data_source.h"
27 #include "digest_common.h"
28 //#include "verify_hap_openssl_utils.h"
29 #include "signature_tools_log.h"
30 #include "signature_tools_errno.h"
31
32 namespace OHOS {
33 namespace SignatureTools {
34 const int64_t HapSignerBlockUtils::HAP_SIG_BLOCK_MAGIC_LOW_OLD = 2334950737560224072LL;
35 const int64_t HapSignerBlockUtils::HAP_SIG_BLOCK_MAGIC_HIGH_OLD = 3617552046287187010LL;
36 const int64_t HapSignerBlockUtils::HAP_SIG_BLOCK_MAGIC_LOW = 7451613641622775868LL;
37 const int64_t HapSignerBlockUtils::HAP_SIG_BLOCK_MAGIC_HIGH = 4497797983070462062LL;
38
39 /* 1MB = 1024 * 1024 Bytes */
40 const int64_t HapSignerBlockUtils::CHUNK_SIZE = 1048576LL;
41
42 const int32_t HapSignerBlockUtils::HAP_SIG_BLOCK_MIN_SIZE = 32;
43 const int32_t HapSignerBlockUtils::ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH = 32;
44
45 const int32_t HapSignerBlockUtils::ZIP_EOCD_SEG_MIN_SIZE = 22;
46 const int32_t HapSignerBlockUtils::ZIP_EOCD_SEGMENT_FLAG = 0x06054b50;
47 const int32_t HapSignerBlockUtils::ZIP_EOCD_COMMENT_LENGTH_OFFSET = 20;
48 const int32_t HapSignerBlockUtils::ZIP_CD_OFFSET_IN_EOCD = 16;
49 const int32_t HapSignerBlockUtils::ZIP_CD_SIZE_OFFSET_IN_EOCD = 12;
50 const int32_t HapSignerBlockUtils::ZIP_BLOCKS_NUM_NEED_DIGEST = 3;
51
52 const char HapSignerBlockUtils::ZIP_FIRST_LEVEL_CHUNK_PREFIX = 0x5a;
53 const char HapSignerBlockUtils::ZIP_SECOND_LEVEL_CHUNK_PREFIX = 0xa5;
54
55 /*
56 * The package of hap is ZIP format, and contains four segments: contents of Zip entry,
57 * hap signatures block, central directory and end of central directory.
58 * The function will find the data segment of hap signature block from hap file.
59 */
FindHapSignature(RandomAccessFile& hapFile, SignatureInfo& signInfo)60 bool HapSignerBlockUtils::FindHapSignature(RandomAccessFile& hapFile, SignatureInfo& signInfo)
61 {
62 std::pair<ByteBuffer, int64_t> eocdAndOffsetInFile;
63 if (!FindEocdInHap(hapFile, eocdAndOffsetInFile)) {
64 SIGNATURE_TOOLS_LOGE("find EoCD failed");
65 return false;
66 }
67
68 signInfo.hapEocd = eocdAndOffsetInFile.first;
69 signInfo.hapEocdOffset = eocdAndOffsetInFile.second;
70 if (!GetCentralDirectoryOffset(signInfo.hapEocd, signInfo.hapEocdOffset, signInfo.hapCentralDirOffset)) {
71 SIGNATURE_TOOLS_LOGE("get CD offset failed");
72 PrintErrorNumberMsg("verify", VERIFY_ERROR, "ZIP End of Central Directory not found");
73 return false;
74 }
75
76 if (!FindHapSigningBlock(hapFile, signInfo.hapCentralDirOffset, signInfo)) {
77 SIGNATURE_TOOLS_LOGE("find signing block failed");
78 return false;
79 }
80 return true;
81 }
82
FindEocdInHap(RandomAccessFile& hapFile, std::pair<ByteBuffer, int64_t>& eocd)83 bool HapSignerBlockUtils::FindEocdInHap(RandomAccessFile& hapFile, std::pair<ByteBuffer, int64_t>& eocd)
84 {
85 /*
86 * EoCD has an optional comment block. Most hap packages do not contain this block.
87 * For hap packages without comment block, EoCD is the last 22 bytes of hap file.
88 * Try as a hap without comment block first to avoid unnecessarily reading more data.
89 */
90 if (FindEocdInHap(hapFile, 0, eocd)) {
91 SIGNATURE_TOOLS_LOGD("Find EoCD of Zip file");
92 return true;
93 }
94 /*
95 * If EoCD contain the comment block, we should find it from the offset of (fileLen - maxCommentSize - 22).
96 * The max size of comment block is 65535, because the comment length is an unsigned 16-bit number.
97 */
98 return FindEocdInHap(hapFile, USHRT_MAX, eocd);
99 }
100
FindEocdInHap(RandomAccessFile& hapFile, unsigned short maxCommentSize, std::pair<ByteBuffer, int64_t>& eocd)101 bool HapSignerBlockUtils::FindEocdInHap(RandomAccessFile& hapFile, unsigned short maxCommentSize,
102 std::pair<ByteBuffer, int64_t>& eocd)
103 {
104 int64_t fileLength = hapFile.GetLength();
105 /* check whether has enough space for EoCD in the file. */
106 if (fileLength < ZIP_EOCD_SEG_MIN_SIZE) {
107 SIGNATURE_TOOLS_LOGE("file length %" PRId64 " is too smaller", fileLength);
108 return false;
109 }
110
111 int32_t searchRange = static_cast<int>(maxCommentSize) + ZIP_EOCD_SEG_MIN_SIZE;
112 if (fileLength < static_cast<int64_t>(searchRange)) {
113 searchRange = static_cast<int>(fileLength);
114 }
115
116 ByteBuffer searchEocdBuffer(searchRange);
117 int64_t searchRangeOffset = fileLength - searchEocdBuffer.GetCapacity();
118 int64_t ret = hapFile.ReadFileFullyFromOffset(searchEocdBuffer, searchRangeOffset);
119 if (ret < 0) {
120 SIGNATURE_TOOLS_LOGE("read data from hap file error: %" PRId64, ret);
121 return false;
122 }
123
124 int32_t eocdOffsetInSearchBuffer = 0;
125 if (!FindEocdInSearchBuffer(searchEocdBuffer, eocdOffsetInSearchBuffer)) {
126 SIGNATURE_TOOLS_LOGE("eocd is not found");
127 return false;
128 }
129
130 searchEocdBuffer.SetPosition(eocdOffsetInSearchBuffer);
131 searchEocdBuffer.Slice();
132 eocd.first = searchEocdBuffer;
133 eocd.second = searchRangeOffset + eocdOffsetInSearchBuffer;
134 return true;
135 }
136
137
138 /*
139 * 4-bytes: End of central directory flag
140 * 2-bytes: Number of this disk
141 * 2-bytes: Number of the disk with the start of central directory
142 * 2-bytes: Total number of entries in the central directory on this disk
143 * 2-bytes: Total number of entries in the central directory
144 * 4-bytes: Size of central directory
145 * 4-bytes: offset of central directory in zip file
146 * 2-bytes: ZIP file comment length, the value n is in the range of [0, 65535]
147 * n-bytes: ZIP Comment block data
148 *
149 * This function find Eocd by searching Eocd flag from input buffer(searchBuffer) and
150 * making sure the comment length is equal to the expected value.
151 */
FindEocdInSearchBuffer(ByteBuffer& searchBuffer, int& offset)152 bool HapSignerBlockUtils::FindEocdInSearchBuffer(ByteBuffer& searchBuffer, int& offset)
153 {
154 int32_t searchBufferSize = searchBuffer.GetCapacity();
155 if (searchBufferSize < ZIP_EOCD_SEG_MIN_SIZE) {
156 SIGNATURE_TOOLS_LOGE("The size of searchBuffer %d is smaller than min size of Eocd",
157 searchBufferSize);
158 return false;
159 }
160
161 int32_t calcCurrentOffset = searchBufferSize - ZIP_EOCD_SEG_MIN_SIZE;
162 while (calcCurrentOffset >= 0) {
163 int32_t hapEocdSegmentFlag;
164 if (searchBuffer.GetInt32(calcCurrentOffset, hapEocdSegmentFlag) &&
165 (hapEocdSegmentFlag == ZIP_EOCD_SEGMENT_FLAG)) {
166 unsigned short commentLength;
167 int32_t expectedCommentLength = searchBufferSize - ZIP_EOCD_SEG_MIN_SIZE - calcCurrentOffset;
168 if (searchBuffer.GetUInt16(calcCurrentOffset + ZIP_EOCD_COMMENT_LENGTH_OFFSET, commentLength) &&
169 static_cast<int>(commentLength) == expectedCommentLength) {
170 offset = calcCurrentOffset;
171 return true;
172 }
173 }
174 calcCurrentOffset--;
175 }
176 return false;
177 }
178
GetCentralDirectoryOffset(ByteBuffer& eocd, int64_t eocdOffset, int64_t& centralDirectoryOffset)179 bool HapSignerBlockUtils::GetCentralDirectoryOffset(ByteBuffer& eocd, int64_t eocdOffset,
180 int64_t& centralDirectoryOffset)
181 {
182 uint32_t offsetValue;
183 uint32_t sizeValue;
184 if (!eocd.GetUInt32(ZIP_CD_OFFSET_IN_EOCD, offsetValue) ||
185 !eocd.GetUInt32(ZIP_CD_SIZE_OFFSET_IN_EOCD, sizeValue)) {
186 SIGNATURE_TOOLS_LOGE("GetUInt32 failed");
187 return false;
188 }
189
190 centralDirectoryOffset = static_cast<int64_t>(offsetValue);
191 if (centralDirectoryOffset > eocdOffset) {
192 SIGNATURE_TOOLS_LOGE("centralDirOffset %" PRId64 " is larger than eocdOffset %" PRId64,
193 centralDirectoryOffset, eocdOffset);
194 return false;
195 }
196
197 int64_t centralDirectorySize = static_cast<int64_t>(sizeValue);
198 if (centralDirectoryOffset + centralDirectorySize != eocdOffset) {
199 SIGNATURE_TOOLS_LOGE("centralDirOffset %" PRId64 " add centralDirSize %" PRId64 " is"
200 " not equal to eocdOffset %" PRId64, centralDirectoryOffset,
201 centralDirectorySize, eocdOffset);
202 return false;
203 }
204 return true;
205 }
206
GetCentralDirectorySize(ByteBuffer& eocd, long& centralDirectorySize)207 bool HapSignerBlockUtils::GetCentralDirectorySize(ByteBuffer& eocd, long& centralDirectorySize)
208 {
209 uint32_t cdSize;
210 if (!eocd.GetUInt32(ZIP_CD_SIZE_OFFSET_IN_EOCD, cdSize)) {
211 SIGNATURE_TOOLS_LOGE("GetUInt32 failed");
212 return false;
213 }
214 centralDirectorySize = (long)cdSize;
215 return true;
216 }
217
SetUnsignedInt32(ByteBuffer& buffer, int32_t offset, int64_t value)218 bool HapSignerBlockUtils::SetUnsignedInt32(ByteBuffer& buffer, int32_t offset, int64_t value)
219 {
220 if ((value < 0) || (value > static_cast<int64_t>(UINT_MAX))) {
221 SIGNATURE_TOOLS_LOGE("uint32 value of out range: %" PRId64, value);
222 return false;
223 }
224 buffer.PutInt32(offset, static_cast<int>(value));
225 return true;
226 }
227
FindHapSigningBlock(RandomAccessFile& hapFile, int64_t centralDirOffset, SignatureInfo& signInfo)228 bool HapSignerBlockUtils::FindHapSigningBlock(RandomAccessFile& hapFile, int64_t centralDirOffset,
229 SignatureInfo& signInfo)
230 {
231 if (centralDirOffset < HAP_SIG_BLOCK_MIN_SIZE) {
232 SIGNATURE_TOOLS_LOGE("HAP too small for HAP Signing Block: %" PRId64, centralDirOffset);
233 return false;
234 }
235 /*
236 * read hap signing block head, it's format:
237 * int32: blockCount
238 * int64: size
239 * 16 bytes: magic
240 * int32: version
241 */
242 ByteBuffer hapBlockHead(ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH);
243 int64_t ret = hapFile.ReadFileFullyFromOffset(hapBlockHead,
244 centralDirOffset - hapBlockHead.GetCapacity());
245 if (ret < 0) {
246 SIGNATURE_TOOLS_LOGE("read hapBlockHead error: %" PRId64, ret);
247 return false;
248 }
249 HapSignBlockHead hapSignBlockHead;
250 if (!ParseSignBlockHead(hapSignBlockHead, hapBlockHead)) {
251 SIGNATURE_TOOLS_LOGE("ParseSignBlockHead failed");
252 return false;
253 }
254
255 if (!CheckSignBlockHead(hapSignBlockHead)) {
256 SIGNATURE_TOOLS_LOGE("hapSignBlockHead is invalid");
257 return false;
258 }
259
260 signInfo.version = hapSignBlockHead.version;
261 int64_t blockArrayLen = hapSignBlockHead.hapSignBlockSize - ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH;
262 int64_t hapSignBlockOffset = centralDirOffset - hapSignBlockHead.hapSignBlockSize;
263 if (hapSignBlockOffset < 0) {
264 SIGNATURE_TOOLS_LOGE("HAP Signing Block offset out of range %" PRId64, hapSignBlockOffset);
265 return false;
266 }
267 signInfo.hapSigningBlockOffset = hapSignBlockOffset;
268 return FindHapSubSigningBlock(hapFile, hapSignBlockHead.blockCount,
269 blockArrayLen, hapSignBlockOffset, signInfo);
270 }
271
CheckSignBlockHead(const HapSignBlockHead& hapSignBlockHead)272 bool HapSignerBlockUtils::CheckSignBlockHead(const HapSignBlockHead& hapSignBlockHead)
273 {
274 int64_t magicLow = HAP_SIG_BLOCK_MAGIC_LOW;
275 int64_t magicHigh = HAP_SIG_BLOCK_MAGIC_HIGH;
276 if (hapSignBlockHead.version < VERSION_FOR_NEW_MAGIC_NUM) {
277 magicLow = HAP_SIG_BLOCK_MAGIC_LOW_OLD;
278 magicHigh = HAP_SIG_BLOCK_MAGIC_HIGH_OLD;
279 }
280
281 if ((hapSignBlockHead.hapSignBlockMagicLo != magicLow) ||
282 (hapSignBlockHead.hapSignBlockMagicHi != magicHigh)) {
283 SIGNATURE_TOOLS_LOGE("No HAP Signing Block before ZIP Central Directory");
284 return false;
285 }
286
287 if ((hapSignBlockHead.hapSignBlockSize < ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH) ||
288 (hapSignBlockHead.hapSignBlockSize > MAX_HAP_SIGN_BLOCK_SIZE)) {
289 SIGNATURE_TOOLS_LOGE("HAP Signing Block size out of range %" PRId64,
290 hapSignBlockHead.hapSignBlockSize);
291 return false;
292 }
293
294 if (hapSignBlockHead.blockCount > MAX_BLOCK_COUNT) {
295 SIGNATURE_TOOLS_LOGE("HAP Signing Block count out of range %d", hapSignBlockHead.blockCount);
296 return false;
297 }
298
299 return true;
300 }
301
ParseSignBlockHead(HapSignBlockHead& hapSignBlockHead, ByteBuffer& hapBlockHead)302 bool HapSignerBlockUtils::ParseSignBlockHead(HapSignBlockHead& hapSignBlockHead, ByteBuffer& hapBlockHead)
303 {
304 return hapBlockHead.GetInt32(hapSignBlockHead.blockCount) &&
305 hapBlockHead.GetInt64(hapSignBlockHead.hapSignBlockSize) &&
306 hapBlockHead.GetInt64(hapSignBlockHead.hapSignBlockMagicLo) &&
307 hapBlockHead.GetInt64(hapSignBlockHead.hapSignBlockMagicHi) &&
308 hapBlockHead.GetInt32(hapSignBlockHead.version);
309 }
310
ParseSubSignBlockHead(HapSubSignBlockHead& subSignBlockHead, ByteBuffer& hapBlockHead)311 bool HapSignerBlockUtils::ParseSubSignBlockHead(HapSubSignBlockHead& subSignBlockHead,
312 ByteBuffer& hapBlockHead)
313 {
314 return hapBlockHead.GetUInt32(subSignBlockHead.type) &&
315 hapBlockHead.GetUInt32(subSignBlockHead.length) &&
316 hapBlockHead.GetUInt32(subSignBlockHead.offset);
317 }
318
319 /*
320 * Hap Sign Block Format:
321 * HapSubSignBlock1_Head
322 * HapSubSignBlock2_Head
323 * ...
324 * HapSubSignBlockn_Head
325 * HapSubSignBlock1_data
326 * HapSubSignBlock2_data
327 * ...
328 * HapSubSignBlockn_data
329 * hap signing block head
330 *
331 * This function reads the head of the HapSubSignBlocks,
332 * and then reads the corresponding data of each block according to the offset provided by the head
333 */
FindHapSubSigningBlock(RandomAccessFile& hapFile, int32_t blockCount, int64_t blockArrayLen, int64_t hapSignBlockOffset, SignatureInfo& signInfo)334 bool HapSignerBlockUtils::FindHapSubSigningBlock(RandomAccessFile& hapFile,
335 int32_t blockCount,
336 int64_t blockArrayLen,
337 int64_t hapSignBlockOffset,
338 SignatureInfo& signInfo)
339 {
340 int64_t offsetMax = hapSignBlockOffset + blockArrayLen;
341 int64_t readLen = 0;
342 int64_t readHeadOffset = hapSignBlockOffset;
343 for (int32_t i = 0; i < blockCount; i++) {
344 ByteBuffer hapBlockHead(ZIP_CD_SIZE_OFFSET_IN_EOCD);
345 int64_t ret = hapFile.ReadFileFullyFromOffset(hapBlockHead, readHeadOffset);
346 if (ret < 0) {
347 return false;
348 }
349 HapSubSignBlockHead subSignBlockHead;
350 if (!ParseSubSignBlockHead(subSignBlockHead, hapBlockHead)) {
351 SIGNATURE_TOOLS_LOGE("ParseSubSignBlockHead failed");
352 return false;
353 }
354 readLen += sizeof(HapSubSignBlockHead);
355
356 readHeadOffset += sizeof(HapSubSignBlockHead);
357 if (readHeadOffset > offsetMax) {
358 SIGNATURE_TOOLS_LOGE("find %dst next head offset error", i);
359 return false;
360 }
361
362 int64_t headOffset = static_cast<int64_t>(subSignBlockHead.offset);
363 int64_t headLength = static_cast<int64_t>(subSignBlockHead.length);
364 /* check subSignBlockHead */
365 if ((offsetMax - headOffset) < hapSignBlockOffset) {
366 SIGNATURE_TOOLS_LOGE("Find %dst subblock data offset error", i);
367 return false;
368 }
369 if ((blockArrayLen - headLength) < readLen) {
370 SIGNATURE_TOOLS_LOGE("no enough data to be read for %dst subblock", i);
371 return false;
372 }
373
374 int64_t dataOffset = hapSignBlockOffset + headOffset;
375 ByteBuffer signBuffer(subSignBlockHead.length);
376 if ((ret = hapFile.ReadFileFullyFromOffset(signBuffer, dataOffset)) < 0) {
377 SIGNATURE_TOOLS_LOGE("read %dst subblock error: %" PRId64, i, ret);
378 return false;
379 }
380 readLen += headLength;
381
382 if (!ClassifyHapSubSigningBlock(signInfo, signBuffer, subSignBlockHead.type)) {
383 SIGNATURE_TOOLS_LOGE("subSigningBlock error, type is %d", subSignBlockHead.type);
384 return false;
385 }
386 }
387
388 /* size of block must be equal to the sum of all subblocks length */
389 if (readLen != blockArrayLen) {
390 SIGNATURE_TOOLS_LOGE("Len: %" PRId64 " is not equal blockArrayLen: %" PRId64,
391 readLen, blockArrayLen);
392 return false;
393 }
394 return true;
395 }
396
ClassifyHapSubSigningBlock(SignatureInfo& signInfo, const ByteBuffer& subBlock, uint32_t type)397 bool HapSignerBlockUtils::ClassifyHapSubSigningBlock(SignatureInfo& signInfo,
398 const ByteBuffer& subBlock, uint32_t type)
399 {
400 bool ret = false;
401 switch (type) {
402 case HAP_SIGN_BLOB:
403 {
404 if (signInfo.hapSignatureBlock.GetCapacity() != 0) {
405 SIGNATURE_TOOLS_LOGE("find more than one hap sign block");
406 break;
407 }
408 signInfo.hapSignatureBlock = subBlock;
409 ret = true;
410 break;
411 }
412 case PROFILE_BLOB:
413 case PROOF_ROTATION_BLOB:
414 case PROPERTY_BLOB:
415 {
416 OptionalBlock optionalBlockObject;
417 optionalBlockObject.optionalType = static_cast<int>(type);
418 optionalBlockObject.optionalBlockValue = subBlock;
419 signInfo.optionBlocks.push_back(optionalBlockObject);
420 ret = true;
421 break;
422 }
423 default:
424 break;
425 }
426 return ret;
427 }
428
GetOptionalBlockIndex(std::vector<OptionalBlock>& optionBlocks, int32_t type, int& index)429 bool HapSignerBlockUtils::GetOptionalBlockIndex(std::vector<OptionalBlock>& optionBlocks,
430 int32_t type,
431 int& index)
432 {
433 int32_t len = static_cast<int>(optionBlocks.size());
434 for (int32_t i = 0; i < len; i++) {
435 if (optionBlocks[i].optionalType == type) {
436 index = i;
437 return true;
438 }
439 }
440 SIGNATURE_TOOLS_LOGE("get optional block type:%d failed.", type);
441 return false;
442 }
443
VerifyHapIntegrity( Pkcs7Context& digestInfo, RandomAccessFile& hapFile, SignatureInfo& signInfo)444 bool HapSignerBlockUtils::VerifyHapIntegrity(
445 Pkcs7Context& digestInfo, RandomAccessFile& hapFile, SignatureInfo& signInfo)
446 {
447 if (!SetUnsignedInt32(signInfo.hapEocd, ZIP_CD_OFFSET_IN_EOCD, signInfo.hapSigningBlockOffset)) {
448 SIGNATURE_TOOLS_LOGE("Set central dir offset failed");
449 return false;
450 }
451
452 int64_t centralDirSize = signInfo.hapEocdOffset - signInfo.hapCentralDirOffset;
453 FileDataSource contentsZip(hapFile, 0, signInfo.hapSigningBlockOffset, 0);
454 FileDataSource centralDir(hapFile, signInfo.hapCentralDirOffset, centralDirSize, 0);
455 ByteBufferDataSource eocd(signInfo.hapEocd);
456 DataSource* content[ZIP_BLOCKS_NUM_NEED_DIGEST] = {&contentsZip, ¢ralDir, &eocd};
457 int32_t nId = DigestCommon::GetDigestAlgorithmId(digestInfo.digestAlgorithm);
458 DigestParameter digestParam = GetDigestParameter(nId);
459 ByteBuffer chunkDigest;
460 if (!ComputeDigestsForEachChunk(digestParam, content, ZIP_BLOCKS_NUM_NEED_DIGEST, chunkDigest)) {
461 SIGNATURE_TOOLS_LOGE("Compute Content Digests failed, alg: %d", nId);
462 return false;
463 }
464
465 ByteBuffer actualDigest;
466 if (!ComputeDigestsWithOptionalBlock(digestParam, signInfo.optionBlocks, chunkDigest, actualDigest)) {
467 SIGNATURE_TOOLS_LOGE("Compute Final Digests failed, alg: %d", nId);
468 return false;
469 }
470
471 if (!digestInfo.content.IsEqual(actualDigest)) {
472 SIGNATURE_TOOLS_LOGE("digest of contents verify failed, alg %d", nId);
473 return false;
474 }
475 PrintMsg(std::string("Digest verify result: ") + "success" + ", DigestAlgorithm: "
476 + DigestCommon::GetDigestAlgorithmString(digestInfo.digestAlgorithm));
477
478 return true;
479 }
480
ComputeDigestsWithOptionalBlock(const DigestParameter& digestParam, const std::vector<OptionalBlock>& optionalBlocks, const ByteBuffer& chunkDigest, ByteBuffer& finalDigest)481 bool HapSignerBlockUtils::ComputeDigestsWithOptionalBlock(const DigestParameter& digestParam,
482 const std::vector<OptionalBlock>& optionalBlocks,
483 const ByteBuffer& chunkDigest,
484 ByteBuffer& finalDigest)
485 {
486 unsigned char out[EVP_MAX_MD_SIZE];
487 int32_t digestLen = DigestCommon::GetDigest(chunkDigest, optionalBlocks, digestParam, out);
488 if (digestLen != digestParam.digestOutputSizeBytes) {
489 SIGNATURE_TOOLS_LOGE("GetDigest failed, outLen is not right, %u, %d",
490 digestLen, digestParam.digestOutputSizeBytes);
491 return false;
492 }
493
494 finalDigest.SetCapacity(digestParam.digestOutputSizeBytes);
495 finalDigest.PutData(0, reinterpret_cast<char*>(out), digestParam.digestOutputSizeBytes);
496 return true;
497 }
498
GetSumOfChunkDigestLen(DataSource* contents[], int32_t len, int32_t chunkDigestLen, int& chunkCount, int& sumOfChunkDigestLen)499 bool HapSignerBlockUtils::GetSumOfChunkDigestLen(DataSource* contents[], int32_t len,
500 int32_t chunkDigestLen, int& chunkCount,
501 int& sumOfChunkDigestLen)
502 {
503 for (int32_t i = 0; i < len; i++) {
504 if (contents[i] == nullptr) {
505 SIGNATURE_TOOLS_LOGE("contents[%d] is nullptr", i);
506 return false;
507 }
508 contents[i]->Reset();
509 chunkCount += GetChunkCount(contents[i]->Remaining(), CHUNK_SIZE);
510 }
511
512 if (chunkCount <= 0) {
513 SIGNATURE_TOOLS_LOGE("no content for digest");
514 return false;
515 }
516 if (chunkCount == 0) {
517 SIGNATURE_TOOLS_LOGE("no content for digest");
518 return false;
519 }
520 if (chunkDigestLen < 0 || ((INT_MAX - ZIP_CHUNK_DIGEST_PRIFIX_LEN) / chunkCount) < chunkDigestLen) {
521 SIGNATURE_TOOLS_LOGE("overflow chunkCount: %d, chunkDigestLen: %d",
522 chunkCount, chunkDigestLen);
523 return false;
524 }
525
526 sumOfChunkDigestLen = ZIP_CHUNK_DIGEST_PRIFIX_LEN + chunkCount * chunkDigestLen;
527 return true;
528 }
529
ComputeDigestsForEachChunk(const DigestParameter& digestParam, DataSource* contents[], int32_t len, ByteBuffer& result)530 bool HapSignerBlockUtils::ComputeDigestsForEachChunk(const DigestParameter& digestParam,
531 DataSource* contents[], int32_t len, ByteBuffer& result)
532 {
533 int32_t chunkCount = 0;
534 int32_t sumOfChunksLen = 0;
535 if (!GetSumOfChunkDigestLen(contents, len, digestParam.digestOutputSizeBytes, chunkCount, sumOfChunksLen)) {
536 SIGNATURE_TOOLS_LOGE("GetSumOfChunkDigestLen failed");
537 return false;
538 }
539 result.SetCapacity(sumOfChunksLen);
540 result.PutByte(0, ZIP_FIRST_LEVEL_CHUNK_PREFIX);
541 result.PutInt32(1, chunkCount);
542
543 int32_t chunkIndex = 0;
544 unsigned char outBlock[EVP_MAX_MD_SIZE];
545 unsigned char zipChunkContentPrefix[ZIP_CHUNK_DIGEST_PRIFIX_LEN] = {
546 (unsigned char)ZIP_SECOND_LEVEL_CHUNK_PREFIX, 0, 0, 0, 0};
547
548 int32_t zipOffset = ZIP_CHUNK_DIGEST_PRIFIX_LEN;
549 for (int32_t i = 0; i < len; i++) {
550 while (contents[i]->HasRemaining()) {
551 int32_t digestChunkSize = std::min(contents[i]->Remaining(), CHUNK_SIZE);
552 if (!InitDigestPrefix(digestParam, zipChunkContentPrefix, digestChunkSize)) {
553 SIGNATURE_TOOLS_LOGE("InitDigestPrefix failed");
554 return false;
555 }
556
557 if (!contents[i]->ReadDataAndDigestUpdate(digestParam, digestChunkSize)) {
558 SIGNATURE_TOOLS_LOGE("Copy Partial Buffer failed, count: %d", chunkIndex);
559 return false;
560 }
561
562 int32_t digestLen = DigestCommon::GetDigest(digestParam, outBlock);
563 if (digestLen != digestParam.digestOutputSizeBytes) {
564 SIGNATURE_TOOLS_LOGE("GetDigest failed len: %d digestSizeBytes: %d",
565 digestLen, digestParam.digestOutputSizeBytes);
566 return false;
567 }
568 result.PutData(zipOffset, reinterpret_cast<char*>(outBlock), digestParam.digestOutputSizeBytes);
569 zipOffset += digestLen;
570 chunkIndex++;
571 }
572 }
573 return true;
574 }
575
GetDigestParameter(int32_t nId)576 DigestParameter HapSignerBlockUtils::GetDigestParameter(int32_t nId)
577 {
578 DigestParameter digestParam;
579 digestParam.digestOutputSizeBytes = DigestCommon::GetDigestAlgorithmOutputSizeBytes(nId);
580 digestParam.md = EVP_get_digestbynid(nId);
581 digestParam.ctxPtr = EVP_MD_CTX_create();
582 EVP_MD_CTX_init(digestParam.ctxPtr);
583 return digestParam;
584 }
585
GetChunkCount(int64_t inputSize, int64_t chunkSize)586 int32_t HapSignerBlockUtils::GetChunkCount(int64_t inputSize, int64_t chunkSize)
587 {
588 if (chunkSize <= 0 || inputSize > LLONG_MAX - chunkSize) {
589 return 0;
590 }
591 if (chunkSize == 0)
592 return 0;
593 int64_t res = (inputSize + chunkSize - 1) / chunkSize;
594 if (res > INT_MAX || res < 0) {
595 return 0;
596 }
597 return static_cast<int>(res);
598 }
599
InitDigestPrefix(const DigestParameter& digestParam, unsigned char(&chunkContentPrefix)[ZIP_CHUNK_DIGEST_PRIFIX_LEN], int32_t chunkLen)600 bool HapSignerBlockUtils::InitDigestPrefix(const DigestParameter& digestParam,
601 unsigned char(&chunkContentPrefix)[ZIP_CHUNK_DIGEST_PRIFIX_LEN],
602 int32_t chunkLen)
603 {
604 if (memcpy_s((chunkContentPrefix + 1), ZIP_CHUNK_DIGEST_PRIFIX_LEN - 1,
605 (&chunkLen), sizeof(chunkLen)) != EOK) {
606 SIGNATURE_TOOLS_LOGE("memcpy_s failed");
607 return false;
608 }
609
610 if (!DigestCommon::DigestInit(digestParam)) {
611 SIGNATURE_TOOLS_LOGE("DigestInit failed");
612 return false;
613 }
614
615 if (!DigestCommon::DigestUpdate(digestParam, chunkContentPrefix, ZIP_CHUNK_DIGEST_PRIFIX_LEN)) {
616 SIGNATURE_TOOLS_LOGE("DigestUpdate failed");
617 return false;
618 }
619 return true;
620 }
621
CreatTestZipFile(const std::string& pathFile, SignatureInfo& signInfo)622 int64_t HapSignerBlockUtils::CreatTestZipFile(const std::string& pathFile, SignatureInfo& signInfo)
623 {
624 std::ofstream hapFileInfo(pathFile.c_str(), std::ios::binary | std::ios::out | std::ios::trunc);
625 if (!hapFileInfo.is_open()) {
626 return 0;
627 }
628 char block[TEST_FILE_BLOCK_LENGTH] = {0};
629 /* input contents of ZIP entries */
630 hapFileInfo.seekp(0, std::ios_base::beg);
631 hapFileInfo.write(block, sizeof(block));
632 /* input sign block */
633 HapSubSignBlockHead signBlob;
634 HapSubSignBlockHead profileBlob;
635 HapSubSignBlockHead propertyBlob;
636 CreateHapSubSignBlockHead(signBlob, profileBlob, propertyBlob);
637 hapFileInfo.write(reinterpret_cast<char*>(&signBlob), sizeof(signBlob));
638 hapFileInfo.write(reinterpret_cast<char*>(&profileBlob), sizeof(profileBlob));
639 hapFileInfo.write(reinterpret_cast<char*>(&propertyBlob), sizeof(propertyBlob));
640 for (int32_t i = 0; i < TEST_FILE_BLOCK_COUNT; i++) {
641 hapFileInfo.write(block, sizeof(block));
642 }
643 int32_t blockCount = TEST_FILE_BLOCK_COUNT;
644 hapFileInfo.write(reinterpret_cast<char*>(&blockCount), sizeof(blockCount));
645 int64_t signBlockSize = (sizeof(HapSubSignBlockHead) + sizeof(block)) * TEST_FILE_BLOCK_COUNT +
646 HapSignerBlockUtils::ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH;
647 hapFileInfo.write(reinterpret_cast<char*>(&signBlockSize), sizeof(signBlockSize));
648 int64_t magic = HapSignerBlockUtils::HAP_SIG_BLOCK_MAGIC_LOW_OLD;
649 hapFileInfo.write(reinterpret_cast<char*>(&magic), sizeof(magic));
650 magic = HapSignerBlockUtils::HAP_SIG_BLOCK_MAGIC_HIGH_OLD;
651 hapFileInfo.write(reinterpret_cast<char*>(&magic), sizeof(magic));
652 int32_t version = 1;
653 hapFileInfo.write(reinterpret_cast<char*>(&version), sizeof(version));
654 /* input central direction */
655 hapFileInfo.write(block, sizeof(block));
656 /* input end of central direction */
657 int32_t zidEocdSign = HapSignerBlockUtils::ZIP_EOCD_SEGMENT_FLAG;
658 hapFileInfo.write(reinterpret_cast<char*>(&zidEocdSign), sizeof(zidEocdSign));
659 hapFileInfo.write(reinterpret_cast<char*>(&magic), sizeof(magic));
660 uint32_t centralDirLen = sizeof(block);
661 hapFileInfo.write(reinterpret_cast<char*>(¢ralDirLen), sizeof(centralDirLen));
662 uint32_t centralDirOffset = TEST_FILE_BLOCK_LENGTH + signBlockSize;
663 hapFileInfo.write(reinterpret_cast<char*>(¢ralDirOffset), sizeof(centralDirOffset));
664 short eocdCommentLen = 0;
665 hapFileInfo.write(reinterpret_cast<char*>(&eocdCommentLen), sizeof(eocdCommentLen));
666 hapFileInfo.close();
667 signInfo.hapCentralDirOffset = centralDirOffset;
668 signInfo.hapEocdOffset = centralDirOffset + centralDirLen;
669 signInfo.hapSignatureBlock.SetCapacity(TEST_FILE_BLOCK_LENGTH);
670 signInfo.hapSignatureBlock.PutData(0, block, sizeof(block));
671 int64_t sumLen = signInfo.hapEocdOffset + sizeof(zidEocdSign) + sizeof(centralDirLen) +
672 sizeof(centralDirOffset) + sizeof(magic) + sizeof(eocdCommentLen);
673 return sumLen;
674 }
675
CreateHapSubSignBlockHead(HapSubSignBlockHead& signBlob, HapSubSignBlockHead& profileBlob, HapSubSignBlockHead& propertyBlob)676 void HapSignerBlockUtils::CreateHapSubSignBlockHead(HapSubSignBlockHead& signBlob,
677 HapSubSignBlockHead& profileBlob,
678 HapSubSignBlockHead& propertyBlob)
679 {
680 signBlob.type = HAP_SIGN_BLOB;
681 signBlob.length = TEST_FILE_BLOCK_LENGTH;
682 signBlob.offset = sizeof(HapSubSignBlockHead) * TEST_FILE_BLOCK_COUNT;
683 propertyBlob.type = PROPERTY_BLOB;
684 propertyBlob.length = TEST_FILE_BLOCK_LENGTH;
685 propertyBlob.offset = profileBlob.offset + profileBlob.length;
686 profileBlob.type = PROFILE_BLOB;
687 profileBlob.length = TEST_FILE_BLOCK_LENGTH;
688 profileBlob.offset = signBlob.offset + signBlob.length;
689 }
690 } // namespace SignatureTools
691 } // namespace OHOS