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 "zip_pkg_parse.h" 17fb299fa2Sopenharmony_ci#include <vector> 18fb299fa2Sopenharmony_ci#include "dump.h" 19fb299fa2Sopenharmony_ci#include "pkg_utils.h" 20fb299fa2Sopenharmony_ci 21fb299fa2Sopenharmony_cinamespace Hpackage { 22fb299fa2Sopenharmony_cistruct Footer { 23fb299fa2Sopenharmony_ci uint16_t signDataStart; 24fb299fa2Sopenharmony_ci uint16_t signDataFlag; 25fb299fa2Sopenharmony_ci uint16_t signDataSize; 26fb299fa2Sopenharmony_ci}; 27fb299fa2Sopenharmony_ci 28fb299fa2Sopenharmony_cinamespace { 29fb299fa2Sopenharmony_ciconstexpr uint32_t ZIP_EOCD_LEN_EXCLUDE_COMMENT = 20; 30fb299fa2Sopenharmony_ciconstexpr uint32_t ZIP_EOCD_FIXED_PART_LEN = 22; 31fb299fa2Sopenharmony_ciconstexpr uint32_t PKG_FOOTER_SIZE = 6; 32fb299fa2Sopenharmony_ciconstexpr uint32_t PKG_ZIP_EOCD_MIN_LEN = ZIP_EOCD_FIXED_PART_LEN + PKG_FOOTER_SIZE; 33fb299fa2Sopenharmony_ciconstexpr uint32_t ZIP_EOCD_SIGNATURE = 0x06054b50; 34fb299fa2Sopenharmony_ciconstexpr uint16_t PKG_ZIP_EOCD_FOOTER_FLAG = 0xFFFF; 35fb299fa2Sopenharmony_ciconst uint8_t ZIP_EOCD_SIGNATURE_BIG_ENDIAN[4] = {0x50, 0x4b, 0x05, 0x06}; 36fb299fa2Sopenharmony_ci} 37fb299fa2Sopenharmony_ci 38fb299fa2Sopenharmony_ci/* 39fb299fa2Sopenharmony_ci * ZIP: File Entry(1..n) + CD(1..n) + EOCD(1) 40fb299fa2Sopenharmony_ci * 41fb299fa2Sopenharmony_ci * EOCD: FLAG(4 bytes) + FIX PART1(16 bytes) + comment length(2 bytes) + comment('comment length' bytes) 42fb299fa2Sopenharmony_ci * 43fb299fa2Sopenharmony_ci * EOCD comment: RESERVED(18 bytes) + SIGNATYRE(variable size) + FOOTER (6 bytes) 44fb299fa2Sopenharmony_ci * 45fb299fa2Sopenharmony_ci * FOOTER 6 bytes (little endian) 46fb299fa2Sopenharmony_ci * append signed result length 2 bytes (SIGNATYRE's length + FOOTER's length) = SIGNATYRE reversed offset 47fb299fa2Sopenharmony_ci * 0xFFFF 2 bytes 48fb299fa2Sopenharmony_ci * = .ZIP file comment length 2 bytes 49fb299fa2Sopenharmony_ci */ 50fb299fa2Sopenharmony_ci 51fb299fa2Sopenharmony_ciint32_t ZipPkgParse::DoParseZipPkg(PkgStreamPtr pkgStream, PkgSignComment &pkgSignComment, 52fb299fa2Sopenharmony_ci size_t &readLen, const uint16_t &signCommentAppendLen, uint16_t &signCommentTotalLen) const 53fb299fa2Sopenharmony_ci{ 54fb299fa2Sopenharmony_ci size_t fileLen = pkgStream->GetFileLength(); 55fb299fa2Sopenharmony_ci size_t eocdTotalLen = ZIP_EOCD_FIXED_PART_LEN + signCommentTotalLen; 56fb299fa2Sopenharmony_ci if (fileLen <= eocdTotalLen) { 57fb299fa2Sopenharmony_ci PKG_LOGE("Invalid eocd len[%zu]", eocdTotalLen); 58fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_PKG_FORMAT); 59fb299fa2Sopenharmony_ci return PKG_INVALID_PKG_FORMAT; 60fb299fa2Sopenharmony_ci } 61fb299fa2Sopenharmony_ci 62fb299fa2Sopenharmony_ci size_t zipEocdStart = fileLen - eocdTotalLen; 63fb299fa2Sopenharmony_ci PkgBuffer zipEocd(eocdTotalLen); 64fb299fa2Sopenharmony_ci int32_t ret = pkgStream->Read(zipEocd, zipEocdStart, eocdTotalLen, readLen); 65fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 66fb299fa2Sopenharmony_ci PKG_LOGE("read zip eocd failed %s", pkgStream->GetFileName().c_str()); 67fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_PKG_FORMAT); 68fb299fa2Sopenharmony_ci return ret; 69fb299fa2Sopenharmony_ci } 70fb299fa2Sopenharmony_ci 71fb299fa2Sopenharmony_ci ret = CheckZipEocd(zipEocd.buffer, eocdTotalLen, signCommentTotalLen); 72fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 73fb299fa2Sopenharmony_ci PKG_LOGE("CheckZipEocd() error, ret[%d]", ret); 74fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_PKG_FORMAT); 75fb299fa2Sopenharmony_ci return ret; 76fb299fa2Sopenharmony_ci } 77fb299fa2Sopenharmony_ci 78fb299fa2Sopenharmony_ci if (fileLen <= signCommentTotalLen) { 79fb299fa2Sopenharmony_ci PKG_LOGE("file len[%zu] < signCommentTotalLen[%zu]", fileLen, signCommentTotalLen); 80fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_PKG_FORMAT, fileLen, signCommentTotalLen); 81fb299fa2Sopenharmony_ci return PKG_INVALID_FILE; 82fb299fa2Sopenharmony_ci } 83fb299fa2Sopenharmony_ci pkgSignComment.signCommentTotalLen = signCommentTotalLen; 84fb299fa2Sopenharmony_ci pkgSignComment.signCommentAppendLen = signCommentAppendLen; 85fb299fa2Sopenharmony_ci 86fb299fa2Sopenharmony_ci return PKG_SUCCESS; 87fb299fa2Sopenharmony_ci} 88fb299fa2Sopenharmony_ci 89fb299fa2Sopenharmony_ciint32_t ZipPkgParse::ParseZipPkg(PkgStreamPtr pkgStream, PkgSignComment &pkgSignComment) const 90fb299fa2Sopenharmony_ci{ 91fb299fa2Sopenharmony_ci if (pkgStream == nullptr) { 92fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_PARAM); 93fb299fa2Sopenharmony_ci return PKG_INVALID_PARAM; 94fb299fa2Sopenharmony_ci } 95fb299fa2Sopenharmony_ci size_t fileLen = pkgStream->GetFileLength(); 96fb299fa2Sopenharmony_ci size_t footerSize = PKG_FOOTER_SIZE; 97fb299fa2Sopenharmony_ci if (fileLen <= footerSize) { 98fb299fa2Sopenharmony_ci PKG_LOGE("file len[%zu] < footerSize.", pkgStream->GetFileLength()); 99fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_FILE, fileLen); 100fb299fa2Sopenharmony_ci return PKG_INVALID_FILE; 101fb299fa2Sopenharmony_ci } 102fb299fa2Sopenharmony_ci size_t footerStart = fileLen - footerSize; 103fb299fa2Sopenharmony_ci size_t readLen = 0; 104fb299fa2Sopenharmony_ci PkgBuffer footer(footerSize); 105fb299fa2Sopenharmony_ci int32_t ret = pkgStream->Read(footer, footerStart, footerSize, readLen); 106fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 107fb299fa2Sopenharmony_ci PKG_LOGE("read FOOTER struct failed %s", pkgStream->GetFileName().c_str()); 108fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(ret); 109fb299fa2Sopenharmony_ci return ret; 110fb299fa2Sopenharmony_ci } 111fb299fa2Sopenharmony_ci 112fb299fa2Sopenharmony_ci uint16_t signCommentAppendLen = 0; 113fb299fa2Sopenharmony_ci uint16_t signCommentTotalLen = 0; 114fb299fa2Sopenharmony_ci ret = ParsePkgFooter(footer.buffer, PKG_FOOTER_SIZE, signCommentAppendLen, signCommentTotalLen); 115fb299fa2Sopenharmony_ci if (ret != PKG_SUCCESS) { 116fb299fa2Sopenharmony_ci PKG_LOGE("ParsePkgFooter() error, ret[%d]", ret); 117fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(ret); 118fb299fa2Sopenharmony_ci return ret; 119fb299fa2Sopenharmony_ci } 120fb299fa2Sopenharmony_ci return DoParseZipPkg(pkgStream, pkgSignComment, readLen, signCommentAppendLen, signCommentTotalLen); 121fb299fa2Sopenharmony_ci} 122fb299fa2Sopenharmony_ci 123fb299fa2Sopenharmony_ciint32_t ZipPkgParse::ParsePkgFooter(const uint8_t *footer, size_t length, 124fb299fa2Sopenharmony_ci uint16_t &signCommentAppendLen, uint16_t &signCommentTotalLen) const 125fb299fa2Sopenharmony_ci{ 126fb299fa2Sopenharmony_ci Updater::UPDATER_INIT_RECORD; 127fb299fa2Sopenharmony_ci if (length < PKG_FOOTER_SIZE) { 128fb299fa2Sopenharmony_ci PKG_LOGE("length[%d] < Footer Size[%d]", length, PKG_FOOTER_SIZE); 129fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_PARAM, length); 130fb299fa2Sopenharmony_ci return PKG_INVALID_PARAM; 131fb299fa2Sopenharmony_ci } 132fb299fa2Sopenharmony_ci 133fb299fa2Sopenharmony_ci Footer signFooter = {0}; 134fb299fa2Sopenharmony_ci size_t offset = 0; 135fb299fa2Sopenharmony_ci signFooter.signDataStart = ReadLE16(footer); 136fb299fa2Sopenharmony_ci offset += sizeof(uint16_t); 137fb299fa2Sopenharmony_ci signFooter.signDataFlag = ReadLE16(footer + offset); 138fb299fa2Sopenharmony_ci offset += sizeof(uint16_t); 139fb299fa2Sopenharmony_ci signFooter.signDataSize = ReadLE16(footer + offset); 140fb299fa2Sopenharmony_ci if (signFooter.signDataFlag != PKG_ZIP_EOCD_FOOTER_FLAG) { 141fb299fa2Sopenharmony_ci PKG_LOGE("error FooterFlag[0x%04X]", signFooter.signDataFlag); 142fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_PKG_FORMAT, signFooter.signDataFlag); 143fb299fa2Sopenharmony_ci return PKG_INVALID_PKG_FORMAT; 144fb299fa2Sopenharmony_ci } 145fb299fa2Sopenharmony_ci 146fb299fa2Sopenharmony_ci signCommentAppendLen = signFooter.signDataStart; 147fb299fa2Sopenharmony_ci signCommentTotalLen = signFooter.signDataSize; 148fb299fa2Sopenharmony_ci if ((signCommentAppendLen < PKG_FOOTER_SIZE) || (signCommentTotalLen < PKG_FOOTER_SIZE) || 149fb299fa2Sopenharmony_ci (signCommentAppendLen > signCommentTotalLen)) { 150fb299fa2Sopenharmony_ci PKG_LOGE("bad footer length: append[0x%04X], total[0x%04X]", 151fb299fa2Sopenharmony_ci signCommentAppendLen, signCommentTotalLen); 152fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_PKG_FORMAT, signCommentAppendLen, signCommentTotalLen); 153fb299fa2Sopenharmony_ci return PKG_INVALID_PKG_FORMAT; 154fb299fa2Sopenharmony_ci } 155fb299fa2Sopenharmony_ci 156fb299fa2Sopenharmony_ci return PKG_SUCCESS; 157fb299fa2Sopenharmony_ci} 158fb299fa2Sopenharmony_ci 159fb299fa2Sopenharmony_ciint32_t ZipPkgParse::CheckZipEocd(const uint8_t *eocd, size_t length, 160fb299fa2Sopenharmony_ci uint16_t signCommentTotalLen) const 161fb299fa2Sopenharmony_ci{ 162fb299fa2Sopenharmony_ci Updater::UPDATER_INIT_RECORD; 163fb299fa2Sopenharmony_ci if (length < PKG_ZIP_EOCD_MIN_LEN) { 164fb299fa2Sopenharmony_ci PKG_LOGE("bad eocd length: append[0x%04X]", length); 165fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_PKG_FORMAT); 166fb299fa2Sopenharmony_ci return PKG_INVALID_PKG_FORMAT; 167fb299fa2Sopenharmony_ci } 168fb299fa2Sopenharmony_ci 169fb299fa2Sopenharmony_ci uint32_t eocdSignature = ReadLE32(eocd); 170fb299fa2Sopenharmony_ci if (eocdSignature != ZIP_EOCD_SIGNATURE) { 171fb299fa2Sopenharmony_ci PKG_LOGE("bad zip eocd flag[%zu]", eocdSignature); 172fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_PKG_FORMAT); 173fb299fa2Sopenharmony_ci return PKG_INVALID_PKG_FORMAT; 174fb299fa2Sopenharmony_ci } 175fb299fa2Sopenharmony_ci 176fb299fa2Sopenharmony_ci /* the beginning 4 chars are already checked before, so begin with i = 4; (length - 3) in case for overflow */ 177fb299fa2Sopenharmony_ci for (size_t i = 4; i < length - 3; i++) { 178fb299fa2Sopenharmony_ci /* every 4 byte check if eocd, if eocd[i] = 0x50, eocd[i + 1] = 0x4b, eocd[i + 2] = 0x05, eocd[i + 3] = 0x06 */ 179fb299fa2Sopenharmony_ci /* the zip contain another ecod, we can consider it's invalid zip */ 180fb299fa2Sopenharmony_ci if (eocd[i] == ZIP_EOCD_SIGNATURE_BIG_ENDIAN[0] && 181fb299fa2Sopenharmony_ci eocd[i + 1] == ZIP_EOCD_SIGNATURE_BIG_ENDIAN[1] && 182fb299fa2Sopenharmony_ci eocd[i + 2] == ZIP_EOCD_SIGNATURE_BIG_ENDIAN[2] && /* eocd[i + 2] = 0x05 */ 183fb299fa2Sopenharmony_ci eocd[i + 3] == ZIP_EOCD_SIGNATURE_BIG_ENDIAN[3]) { /* eocd[i + 3] = 0x06 */ 184fb299fa2Sopenharmony_ci PKG_LOGE("EOCD marker occurs after start of EOCD"); 185fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_PKG_FORMAT); 186fb299fa2Sopenharmony_ci return PKG_INVALID_PKG_FORMAT; 187fb299fa2Sopenharmony_ci } 188fb299fa2Sopenharmony_ci } 189fb299fa2Sopenharmony_ci 190fb299fa2Sopenharmony_ci const uint8_t *zipSignCommentAddr = eocd + ZIP_EOCD_LEN_EXCLUDE_COMMENT; 191fb299fa2Sopenharmony_ci uint16_t tempLen = ReadLE16(zipSignCommentAddr); 192fb299fa2Sopenharmony_ci if (signCommentTotalLen != tempLen) { 193fb299fa2Sopenharmony_ci PKG_LOGE("compare sign comment length: eocd[0x%04X], footer[0x%04X] error", tempLen, signCommentTotalLen); 194fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(PKG_INVALID_PKG_FORMAT); 195fb299fa2Sopenharmony_ci return PKG_INVALID_PKG_FORMAT; 196fb299fa2Sopenharmony_ci } 197fb299fa2Sopenharmony_ci 198fb299fa2Sopenharmony_ci return PKG_SUCCESS; 199fb299fa2Sopenharmony_ci} 200fb299fa2Sopenharmony_ci} // namespace Hpackage 201