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 32namespace OHOS { 33namespace SignatureTools { 34const int64_t HapSignerBlockUtils::HAP_SIG_BLOCK_MAGIC_LOW_OLD = 2334950737560224072LL; 35const int64_t HapSignerBlockUtils::HAP_SIG_BLOCK_MAGIC_HIGH_OLD = 3617552046287187010LL; 36const int64_t HapSignerBlockUtils::HAP_SIG_BLOCK_MAGIC_LOW = 7451613641622775868LL; 37const int64_t HapSignerBlockUtils::HAP_SIG_BLOCK_MAGIC_HIGH = 4497797983070462062LL; 38 39/* 1MB = 1024 * 1024 Bytes */ 40const int64_t HapSignerBlockUtils::CHUNK_SIZE = 1048576LL; 41 42const int32_t HapSignerBlockUtils::HAP_SIG_BLOCK_MIN_SIZE = 32; 43const int32_t HapSignerBlockUtils::ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH = 32; 44 45const int32_t HapSignerBlockUtils::ZIP_EOCD_SEG_MIN_SIZE = 22; 46const int32_t HapSignerBlockUtils::ZIP_EOCD_SEGMENT_FLAG = 0x06054b50; 47const int32_t HapSignerBlockUtils::ZIP_EOCD_COMMENT_LENGTH_OFFSET = 20; 48const int32_t HapSignerBlockUtils::ZIP_CD_OFFSET_IN_EOCD = 16; 49const int32_t HapSignerBlockUtils::ZIP_CD_SIZE_OFFSET_IN_EOCD = 12; 50const int32_t HapSignerBlockUtils::ZIP_BLOCKS_NUM_NEED_DIGEST = 3; 51 52const char HapSignerBlockUtils::ZIP_FIRST_LEVEL_CHUNK_PREFIX = 0x5a; 53const 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 */ 60bool 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 83bool 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 101bool 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*/ 152bool 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 179bool 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 207bool 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 218bool 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 228bool 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 272bool 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 302bool 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 311bool 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 */ 334bool 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 397bool 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 429bool 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 444bool 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 481bool 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 499bool 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 530bool 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 576DigestParameter 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 586int32_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 600bool 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 622int64_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 676void 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