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 21namespace OHOS { 22namespace SignatureTools { 23bool 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 74bool 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 92void 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 114bool 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 192void 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