1fb299fa2Sopenharmony_ci/* 2fb299fa2Sopenharmony_ci * Copyright (c) 2023 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 "hash_data_verifier.h" 17fb299fa2Sopenharmony_ci#include "log/dump.h" 18fb299fa2Sopenharmony_ci#include "openssl_util.h" 19fb299fa2Sopenharmony_ci#include "package/pkg_manager.h" 20fb299fa2Sopenharmony_ci#include "pkcs7_signed_data.h" 21fb299fa2Sopenharmony_ci#include "rust/hash_signed_data.h" 22fb299fa2Sopenharmony_ci#include "updater/updater_const.h" 23fb299fa2Sopenharmony_ci#include "zip_pkg_parse.h" 24fb299fa2Sopenharmony_ci 25fb299fa2Sopenharmony_cinamespace Hpackage { 26fb299fa2Sopenharmony_ciusing namespace Updater; 27fb299fa2Sopenharmony_ciconstexpr static std::size_t MAX_SIG_SIZE = 1024; 28fb299fa2Sopenharmony_ciconstexpr const char *UPDATER_HASH_SIGNED_DATA = "hash_signed_data"; 29fb299fa2Sopenharmony_ci 30fb299fa2Sopenharmony_ciHashDataVerifier::HashDataVerifier(PkgManager::PkgManagerPtr manager) 31fb299fa2Sopenharmony_ci : manager_(manager), pkcs7_(std::make_unique<Pkcs7SignedData>()) {} 32fb299fa2Sopenharmony_ci 33fb299fa2Sopenharmony_ciHashDataVerifier::~HashDataVerifier() 34fb299fa2Sopenharmony_ci{ 35fb299fa2Sopenharmony_ci ReleaseHashSignedData(hsd_); 36fb299fa2Sopenharmony_ci} 37fb299fa2Sopenharmony_ci 38fb299fa2Sopenharmony_cibool HashDataVerifier::LoadHashDataAndPkcs7(const std::string &pkgPath) 39fb299fa2Sopenharmony_ci{ 40fb299fa2Sopenharmony_ci Updater::UPDATER_INIT_RECORD; 41fb299fa2Sopenharmony_ci if (pkgPath == UPDATRE_SCRIPT_ZIP) { 42fb299fa2Sopenharmony_ci isNeedVerify_ = false; 43fb299fa2Sopenharmony_ci return true; 44fb299fa2Sopenharmony_ci } 45fb299fa2Sopenharmony_ci // only allow loading once 46fb299fa2Sopenharmony_ci if (hsd_ != nullptr) { 47fb299fa2Sopenharmony_ci PKG_LOGW("hash signed data has been loaded before"); 48fb299fa2Sopenharmony_ci return true; 49fb299fa2Sopenharmony_ci } 50fb299fa2Sopenharmony_ci if (manager_ == nullptr) { 51fb299fa2Sopenharmony_ci PKG_LOGE("pkg manager is null"); 52fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(false); 53fb299fa2Sopenharmony_ci return false; 54fb299fa2Sopenharmony_ci } 55fb299fa2Sopenharmony_ci // load pkcs7 from package 56fb299fa2Sopenharmony_ci if (!LoadPkcs7FromPackage(pkgPath)) { 57fb299fa2Sopenharmony_ci PKG_LOGE("load pkcs7 from %s failed", pkgPath.c_str()); 58fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_FILE, pkgPath); 59fb299fa2Sopenharmony_ci return false; 60fb299fa2Sopenharmony_ci } 61fb299fa2Sopenharmony_ci if (!LoadHashDataFromPackage()) { 62fb299fa2Sopenharmony_ci PKG_LOGE("load pkcs7 from %s failed", pkgPath.c_str()); 63fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_FILE, pkgPath); 64fb299fa2Sopenharmony_ci return false; 65fb299fa2Sopenharmony_ci } 66fb299fa2Sopenharmony_ci return true; 67fb299fa2Sopenharmony_ci} 68fb299fa2Sopenharmony_ci 69fb299fa2Sopenharmony_cibool HashDataVerifier::LoadHashDataFromPackage(const std::string &buffer) 70fb299fa2Sopenharmony_ci{ 71fb299fa2Sopenharmony_ci if (buffer.length() == 0) { 72fb299fa2Sopenharmony_ci PKG_LOGE("buffer is empty"); 73fb299fa2Sopenharmony_ci return false; 74fb299fa2Sopenharmony_ci } 75fb299fa2Sopenharmony_ci hsd_ = LoadHashSignedData(reinterpret_cast<const char *>(buffer.data())); 76fb299fa2Sopenharmony_ci return true; 77fb299fa2Sopenharmony_ci} 78fb299fa2Sopenharmony_ci 79fb299fa2Sopenharmony_cibool HashDataVerifier::LoadHashDataFromPackage(void) 80fb299fa2Sopenharmony_ci{ 81fb299fa2Sopenharmony_ci Updater::UPDATER_INIT_RECORD; 82fb299fa2Sopenharmony_ci PkgManager::StreamPtr outStream = nullptr; 83fb299fa2Sopenharmony_ci auto info = manager_->GetFileInfo(UPDATER_HASH_SIGNED_DATA); 84fb299fa2Sopenharmony_ci if (info == nullptr || info->unpackedSize == 0) { 85fb299fa2Sopenharmony_ci PKG_LOGE("hash signed data not find in pkg manager"); 86fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(false); 87fb299fa2Sopenharmony_ci return false; 88fb299fa2Sopenharmony_ci } 89fb299fa2Sopenharmony_ci // 1 more byte bigger than unpacked size to ensure a ending '\0' in buffer 90fb299fa2Sopenharmony_ci PkgBuffer buffer {info->unpackedSize + 1}; 91fb299fa2Sopenharmony_ci int32_t ret = manager_->CreatePkgStream(outStream, "", buffer); 92fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 93fb299fa2Sopenharmony_ci PKG_LOGE("create stream fail"); 94fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(false); 95fb299fa2Sopenharmony_ci return false; 96fb299fa2Sopenharmony_ci } 97fb299fa2Sopenharmony_ci ret = manager_->ExtractFile(UPDATER_HASH_SIGNED_DATA, outStream); 98fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 99fb299fa2Sopenharmony_ci manager_->ClosePkgStream(outStream); 100fb299fa2Sopenharmony_ci PKG_LOGE("extract file failed"); 101fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(false); 102fb299fa2Sopenharmony_ci return false; 103fb299fa2Sopenharmony_ci } 104fb299fa2Sopenharmony_ci hsd_ = LoadHashSignedData(reinterpret_cast<const char *>(buffer.data.data())); 105fb299fa2Sopenharmony_ci manager_->ClosePkgStream(outStream); 106fb299fa2Sopenharmony_ci if (hsd_ == nullptr) { 107fb299fa2Sopenharmony_ci PKG_LOGE("load hash signed data failed"); 108fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(false); 109fb299fa2Sopenharmony_ci return false; 110fb299fa2Sopenharmony_ci } 111fb299fa2Sopenharmony_ci return true; 112fb299fa2Sopenharmony_ci} 113fb299fa2Sopenharmony_ci 114fb299fa2Sopenharmony_cibool HashDataVerifier::LoadPkcs7FromPackage(const std::string &pkgPath) 115fb299fa2Sopenharmony_ci{ 116fb299fa2Sopenharmony_ci PkgManager::StreamPtr pkgStream = nullptr; 117fb299fa2Sopenharmony_ci int32_t ret = manager_->CreatePkgStream(pkgStream, pkgPath, 0, PkgStream::PkgStreamType_Read); 118fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 119fb299fa2Sopenharmony_ci PKG_LOGE("CreatePackage fail %s", pkgPath.c_str()); 120fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_FILE, pkgPath); 121fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(false); 122fb299fa2Sopenharmony_ci return false; 123fb299fa2Sopenharmony_ci } 124fb299fa2Sopenharmony_ci 125fb299fa2Sopenharmony_ci PkgVerifyUtil verifyUtil {}; 126fb299fa2Sopenharmony_ci size_t signatureSize = 0; 127fb299fa2Sopenharmony_ci std::vector<uint8_t> signature {}; 128fb299fa2Sopenharmony_ci uint16_t commentTotalLenAll = 0; 129fb299fa2Sopenharmony_ci ret = verifyUtil.GetSignature(PkgStreamImpl::ConvertPkgStream(pkgStream), 130fb299fa2Sopenharmony_ci signatureSize, signature, commentTotalLenAll); 131fb299fa2Sopenharmony_ci manager_->ClosePkgStream(pkgStream); 132fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 133fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(ret); 134fb299fa2Sopenharmony_ci return false; 135fb299fa2Sopenharmony_ci } 136fb299fa2Sopenharmony_ci return pkcs7_ != nullptr && pkcs7_->ParsePkcs7Data(signature.data(), signature.size()) == 0; 137fb299fa2Sopenharmony_ci} 138fb299fa2Sopenharmony_ci 139fb299fa2Sopenharmony_cibool HashDataVerifier::VerifyHashData(const std::string &preName, 140fb299fa2Sopenharmony_ci const std::string &fileName, PkgManager::StreamPtr stream) const 141fb299fa2Sopenharmony_ci{ 142fb299fa2Sopenharmony_ci if (!isNeedVerify_) { 143fb299fa2Sopenharmony_ci return true; 144fb299fa2Sopenharmony_ci } 145fb299fa2Sopenharmony_ci Updater::UPDATER_INIT_RECORD; 146fb299fa2Sopenharmony_ci if (stream == nullptr) { 147fb299fa2Sopenharmony_ci PKG_LOGE("stream is null"); 148fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(false); 149fb299fa2Sopenharmony_ci return false; 150fb299fa2Sopenharmony_ci } 151fb299fa2Sopenharmony_ci 152fb299fa2Sopenharmony_ci // get hash from stream 153fb299fa2Sopenharmony_ci std::vector<uint8_t> hash {}; 154fb299fa2Sopenharmony_ci int32_t ret = CalcSha256Digest(PkgStreamImpl::ConvertPkgStream(stream), stream->GetFileLength(), hash); 155fb299fa2Sopenharmony_ci if (ret != 0) { 156fb299fa2Sopenharmony_ci PKG_LOGE("cal digest for pkg stream"); 157fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(false, fileName); 158fb299fa2Sopenharmony_ci return false; 159fb299fa2Sopenharmony_ci } 160fb299fa2Sopenharmony_ci 161fb299fa2Sopenharmony_ci // get sig from hash data 162fb299fa2Sopenharmony_ci std::string name = preName + fileName; 163fb299fa2Sopenharmony_ci std::vector<uint8_t> sig(MAX_SIG_SIZE, 0); 164fb299fa2Sopenharmony_ci auto sigLen = GetSigFromHashData(hsd_, sig.data(), sig.size(), name.c_str()); 165fb299fa2Sopenharmony_ci if (sigLen == 0 || sig.size() < sigLen) { 166fb299fa2Sopenharmony_ci PKG_LOGE("get sig for %s failed", name.c_str()); 167fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_SIGNATURE, fileName, sigLen); 168fb299fa2Sopenharmony_ci return false; 169fb299fa2Sopenharmony_ci } 170fb299fa2Sopenharmony_ci sig.resize(sigLen); 171fb299fa2Sopenharmony_ci 172fb299fa2Sopenharmony_ci // then using cert from pkcs7 to verify hash data 173fb299fa2Sopenharmony_ci if (pkcs7_ == nullptr || pkcs7_->Verify(hash, sig, false) != 0) { 174fb299fa2Sopenharmony_ci PKG_LOGE("verify hash signed data for %s failed", fileName.c_str()); 175fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_SIGNATURE, fileName); 176fb299fa2Sopenharmony_ci return false; 177fb299fa2Sopenharmony_ci } 178fb299fa2Sopenharmony_ci PKG_LOGI("verify hash signed data for %s successfully", fileName.c_str()); 179fb299fa2Sopenharmony_ci return true; 180fb299fa2Sopenharmony_ci} 181fb299fa2Sopenharmony_ci} // namespace Hpackage 182