1fb299fa2Sopenharmony_ci/* 2fb299fa2Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License. 5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at 6fb299fa2Sopenharmony_ci * 7fb299fa2Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8fb299fa2Sopenharmony_ci * 9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and 13fb299fa2Sopenharmony_ci * limitations under the License. 14fb299fa2Sopenharmony_ci */ 15fb299fa2Sopenharmony_ci 16fb299fa2Sopenharmony_ci#include "pkg_verify_util.h" 17fb299fa2Sopenharmony_ci#include <unistd.h> 18fb299fa2Sopenharmony_ci#include "dump.h" 19fb299fa2Sopenharmony_ci#include "openssl_util.h" 20fb299fa2Sopenharmony_ci#include "pkcs7_signed_data.h" 21fb299fa2Sopenharmony_ci#include "pkg_algo_sign.h" 22fb299fa2Sopenharmony_ci#include "pkg_algorithm.h" 23fb299fa2Sopenharmony_ci#include "pkg_manager_impl.h" 24fb299fa2Sopenharmony_ci#include "pkg_utils.h" 25fb299fa2Sopenharmony_ci#include "securec.h" 26fb299fa2Sopenharmony_ci#include "zip_pkg_parse.h" 27fb299fa2Sopenharmony_ci 28fb299fa2Sopenharmony_cinamespace Hpackage { 29fb299fa2Sopenharmony_cinamespace { 30fb299fa2Sopenharmony_ciconstexpr uint32_t ZIP_EOCD_FIXED_PART_LEN = 22; 31fb299fa2Sopenharmony_ciconstexpr uint32_t PKG_FOOTER_SIZE = 6; 32fb299fa2Sopenharmony_ciconstexpr uint32_t PKG_HASH_CONTENT_LEN = SHA256_DIGEST_LENGTH; 33fb299fa2Sopenharmony_ci} 34fb299fa2Sopenharmony_ci 35fb299fa2Sopenharmony_ciint32_t PkgVerifyUtil::VerifySourceDigest(std::vector<uint8_t> &signature, std::vector<uint8_t> &sourceDigest, 36fb299fa2Sopenharmony_ci const std::string & keyPath) const 37fb299fa2Sopenharmony_ci{ 38fb299fa2Sopenharmony_ci std::vector<std::vector<uint8_t>> sigs; 39fb299fa2Sopenharmony_ci Pkcs7SignedData pkcs7; 40fb299fa2Sopenharmony_ci SignAlgorithm::SignAlgorithmPtr signAlgorithm = PkgAlgorithmFactory::GetVerifyAlgorithm( 41fb299fa2Sopenharmony_ci keyPath, PKG_DIGEST_TYPE_SHA256); 42fb299fa2Sopenharmony_ci int32_t ret = pkcs7.ReadSig(signature.data(), signature.size(), sigs); 43fb299fa2Sopenharmony_ci if (ret != PKCS7_SUCCESS) { 44fb299fa2Sopenharmony_ci UPDATER_LAST_WORD("pkcs7", ret); 45fb299fa2Sopenharmony_ci return ret; 46fb299fa2Sopenharmony_ci } 47fb299fa2Sopenharmony_ci for (auto &sig : sigs) { 48fb299fa2Sopenharmony_ci if (signAlgorithm->VerifyDigest(sourceDigest, sig) == 0) { 49fb299fa2Sopenharmony_ci return PKG_SUCCESS; 50fb299fa2Sopenharmony_ci } 51fb299fa2Sopenharmony_ci } 52fb299fa2Sopenharmony_ci return PKG_VERIFY_FAIL; 53fb299fa2Sopenharmony_ci} 54fb299fa2Sopenharmony_ci 55fb299fa2Sopenharmony_ciint32_t PkgVerifyUtil::VerifyAccPackageSign(const PkgStreamPtr pkgStream, const std::string &keyPath) const 56fb299fa2Sopenharmony_ci{ 57fb299fa2Sopenharmony_ci if (pkgStream == nullptr) { 58fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_PARAM); 59fb299fa2Sopenharmony_ci return PKG_INVALID_PARAM; 60fb299fa2Sopenharmony_ci } 61fb299fa2Sopenharmony_ci size_t signatureSize = 0; 62fb299fa2Sopenharmony_ci std::vector<uint8_t> signature; 63fb299fa2Sopenharmony_ci uint16_t commentTotalLenAll = 0; 64fb299fa2Sopenharmony_ci if (GetSignature(pkgStream, signatureSize, signature, commentTotalLenAll) != PKG_SUCCESS) { 65fb299fa2Sopenharmony_ci PKG_LOGE("get package signature fail!"); 66fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_SIGNATURE); 67fb299fa2Sopenharmony_ci return PKG_INVALID_SIGNATURE; 68fb299fa2Sopenharmony_ci } 69fb299fa2Sopenharmony_ci size_t srcDataLen = pkgStream->GetFileLength() - commentTotalLenAll -2; 70fb299fa2Sopenharmony_ci size_t readLen = 0; 71fb299fa2Sopenharmony_ci std::vector<uint8_t> sourceDigest; 72fb299fa2Sopenharmony_ci PkgBuffer digest(srcDataLen); 73fb299fa2Sopenharmony_ci pkgStream->Read(digest, 0, srcDataLen, readLen); 74fb299fa2Sopenharmony_ci sourceDigest.assign(digest.buffer, digest.buffer + readLen); 75fb299fa2Sopenharmony_ci return VerifySourceDigest(signature, sourceDigest, keyPath); 76fb299fa2Sopenharmony_ci} 77fb299fa2Sopenharmony_ci 78fb299fa2Sopenharmony_ciint32_t PkgVerifyUtil::VerifySign(std::vector<uint8_t> &signData, std::vector<uint8_t> &digest) const 79fb299fa2Sopenharmony_ci{ 80fb299fa2Sopenharmony_ci std::vector<uint8_t> hash; 81fb299fa2Sopenharmony_ci int32_t ret = Pkcs7verify(signData, hash); 82fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 83fb299fa2Sopenharmony_ci PKG_LOGE("pkcs7 verify fail!"); 84fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(ret); 85fb299fa2Sopenharmony_ci return ret; 86fb299fa2Sopenharmony_ci } 87fb299fa2Sopenharmony_ci size_t hashLen = hash.size(); 88fb299fa2Sopenharmony_ci if ((hashLen != digest.size()) || memcmp(hash.data(), digest.data(), hashLen) != EOK) { 89fb299fa2Sopenharmony_ci PKG_LOGE("Failed to memcmp data."); 90fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_DIGEST); 91fb299fa2Sopenharmony_ci return PKG_INVALID_DIGEST; 92fb299fa2Sopenharmony_ci } 93fb299fa2Sopenharmony_ci return PKG_SUCCESS; 94fb299fa2Sopenharmony_ci} 95fb299fa2Sopenharmony_ci 96fb299fa2Sopenharmony_ciint32_t PkgVerifyUtil::VerifyPackageSign(const PkgStreamPtr pkgStream) const 97fb299fa2Sopenharmony_ci{ 98fb299fa2Sopenharmony_ci if (pkgStream == nullptr) { 99fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_PARAM); 100fb299fa2Sopenharmony_ci return PKG_INVALID_PARAM; 101fb299fa2Sopenharmony_ci } 102fb299fa2Sopenharmony_ci size_t signatureSize = 0; 103fb299fa2Sopenharmony_ci std::vector<uint8_t> signature; 104fb299fa2Sopenharmony_ci uint16_t commentTotalLenAll = 0; 105fb299fa2Sopenharmony_ci if (GetSignature(pkgStream, signatureSize, signature, commentTotalLenAll) != PKG_SUCCESS) { 106fb299fa2Sopenharmony_ci PKG_LOGE("get package signature fail!"); 107fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_SIGNATURE); 108fb299fa2Sopenharmony_ci return PKG_INVALID_SIGNATURE; 109fb299fa2Sopenharmony_ci } 110fb299fa2Sopenharmony_ci 111fb299fa2Sopenharmony_ci std::vector<uint8_t> hash; 112fb299fa2Sopenharmony_ci int32_t ret = Pkcs7verify(signature, hash); 113fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 114fb299fa2Sopenharmony_ci PKG_LOGE("pkcs7 verify fail!"); 115fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(ret); 116fb299fa2Sopenharmony_ci return ret; 117fb299fa2Sopenharmony_ci } 118fb299fa2Sopenharmony_ci size_t srcDataLen = pkgStream->GetFileLength() - commentTotalLenAll - 2; 119fb299fa2Sopenharmony_ci 120fb299fa2Sopenharmony_ci ret = HashCheck(pkgStream, srcDataLen, hash); 121fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 122fb299fa2Sopenharmony_ci srcDataLen = pkgStream->GetFileLength() - signatureSize - ZIP_EOCD_FIXED_PART_LEN; 123fb299fa2Sopenharmony_ci ret = HashCheck(pkgStream, srcDataLen, hash); 124fb299fa2Sopenharmony_ci } 125fb299fa2Sopenharmony_ci PKG_LOGI("verify package signature %s", ret == PKG_SUCCESS ? "successfull" : "failed"); 126fb299fa2Sopenharmony_ci return ret; 127fb299fa2Sopenharmony_ci} 128fb299fa2Sopenharmony_ci 129fb299fa2Sopenharmony_ciint32_t PkgVerifyUtil::GetSignature(const PkgStreamPtr pkgStream, size_t &signatureSize, 130fb299fa2Sopenharmony_ci std::vector<uint8_t> &signature, uint16_t &commentTotalLenAll) const 131fb299fa2Sopenharmony_ci{ 132fb299fa2Sopenharmony_ci size_t signatureStart = 0; 133fb299fa2Sopenharmony_ci int32_t ret = ParsePackage(pkgStream, signatureStart, signatureSize, commentTotalLenAll); 134fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS || signatureSize < PKG_FOOTER_SIZE) { 135fb299fa2Sopenharmony_ci PKG_LOGE("Parse package failed."); 136fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(-1); 137fb299fa2Sopenharmony_ci return -1; 138fb299fa2Sopenharmony_ci } 139fb299fa2Sopenharmony_ci 140fb299fa2Sopenharmony_ci size_t signDataLen = signatureSize - PKG_FOOTER_SIZE; 141fb299fa2Sopenharmony_ci PkgBuffer signData(signDataLen); 142fb299fa2Sopenharmony_ci size_t readLen = 0; 143fb299fa2Sopenharmony_ci ret = pkgStream->Read(signData, signatureStart, signDataLen, readLen); 144fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 145fb299fa2Sopenharmony_ci PKG_LOGE("read signature failed %s", pkgStream->GetFileName().c_str()); 146fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(ret); 147fb299fa2Sopenharmony_ci return ret; 148fb299fa2Sopenharmony_ci } 149fb299fa2Sopenharmony_ci signature.assign(signData.buffer, signData.buffer + readLen); 150fb299fa2Sopenharmony_ci 151fb299fa2Sopenharmony_ci size_t fileLen = pkgStream->GetFileLength(); 152fb299fa2Sopenharmony_ci if (fileLen < (signatureSize + ZIP_EOCD_FIXED_PART_LEN)) { 153fb299fa2Sopenharmony_ci PKG_LOGE("Invalid fileLen[%zu] and signature size[%zu]", fileLen, signatureSize); 154fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_PARAM, fileLen, signatureSize); 155fb299fa2Sopenharmony_ci return PKG_INVALID_PARAM; 156fb299fa2Sopenharmony_ci } 157fb299fa2Sopenharmony_ci 158fb299fa2Sopenharmony_ci return PKG_SUCCESS; 159fb299fa2Sopenharmony_ci} 160fb299fa2Sopenharmony_ci 161fb299fa2Sopenharmony_ciint32_t PkgVerifyUtil::ParsePackage(const PkgStreamPtr pkgStream, size_t &signatureStart, 162fb299fa2Sopenharmony_ci size_t &signatureSize, uint16_t &commentTotalLenAll) const 163fb299fa2Sopenharmony_ci{ 164fb299fa2Sopenharmony_ci ZipPkgParse zipParse; 165fb299fa2Sopenharmony_ci PkgSignComment pkgSignComment {}; 166fb299fa2Sopenharmony_ci int32_t ret = zipParse.ParseZipPkg(pkgStream, pkgSignComment); 167fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 168fb299fa2Sopenharmony_ci PKG_LOGE("Parse zip package signature failed."); 169fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(ret); 170fb299fa2Sopenharmony_ci return ret; 171fb299fa2Sopenharmony_ci } 172fb299fa2Sopenharmony_ci signatureStart = pkgStream->GetFileLength() - pkgSignComment.signCommentAppendLen; 173fb299fa2Sopenharmony_ci signatureSize = pkgSignComment.signCommentAppendLen; 174fb299fa2Sopenharmony_ci commentTotalLenAll = pkgSignComment.signCommentTotalLen; 175fb299fa2Sopenharmony_ci 176fb299fa2Sopenharmony_ci return PKG_SUCCESS; 177fb299fa2Sopenharmony_ci} 178fb299fa2Sopenharmony_ci 179fb299fa2Sopenharmony_ciint32_t PkgVerifyUtil::Pkcs7verify(std::vector<uint8_t> &signature, std::vector<uint8_t> &hash) const 180fb299fa2Sopenharmony_ci{ 181fb299fa2Sopenharmony_ci Pkcs7SignedData pkcs7; 182fb299fa2Sopenharmony_ci 183fb299fa2Sopenharmony_ci return pkcs7.GetHashFromSignBlock(signature.data(), signature.size(), hash); 184fb299fa2Sopenharmony_ci} 185fb299fa2Sopenharmony_ci 186fb299fa2Sopenharmony_ciint32_t PkgVerifyUtil::HashCheck(const PkgStreamPtr srcData, const size_t dataLen, 187fb299fa2Sopenharmony_ci const std::vector<uint8_t> &hash) const 188fb299fa2Sopenharmony_ci{ 189fb299fa2Sopenharmony_ci Updater::UPDATER_INIT_RECORD; 190fb299fa2Sopenharmony_ci if (srcData == nullptr || dataLen == 0) { 191fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_PARAM); 192fb299fa2Sopenharmony_ci return PKG_INVALID_PARAM; 193fb299fa2Sopenharmony_ci } 194fb299fa2Sopenharmony_ci 195fb299fa2Sopenharmony_ci size_t digestLen = hash.size(); 196fb299fa2Sopenharmony_ci if (digestLen != PKG_HASH_CONTENT_LEN) { 197fb299fa2Sopenharmony_ci PKG_LOGE("calc pkg sha256 digest failed."); 198fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_PARAM); 199fb299fa2Sopenharmony_ci return PKG_INVALID_PARAM; 200fb299fa2Sopenharmony_ci } 201fb299fa2Sopenharmony_ci std::vector<uint8_t> sourceDigest(digestLen); 202fb299fa2Sopenharmony_ci int32_t ret = CalcSha256Digest(srcData, dataLen, sourceDigest); 203fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 204fb299fa2Sopenharmony_ci PKG_LOGE("calc pkg sha256 digest failed."); 205fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(ret); 206fb299fa2Sopenharmony_ci return ret; 207fb299fa2Sopenharmony_ci } 208fb299fa2Sopenharmony_ci 209fb299fa2Sopenharmony_ci if (memcmp(hash.data(), sourceDigest.data(), digestLen) != EOK) { 210fb299fa2Sopenharmony_ci PKG_LOGW("Failed to memcmp data."); 211fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_DIGEST); 212fb299fa2Sopenharmony_ci return PKG_INVALID_DIGEST; 213fb299fa2Sopenharmony_ci } 214fb299fa2Sopenharmony_ci 215fb299fa2Sopenharmony_ci return PKG_SUCCESS; 216fb299fa2Sopenharmony_ci} 217fb299fa2Sopenharmony_ci} // namespace Hpackage 218