• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "pkg_verify_util.h"
17 #include <unistd.h>
18 #include "dump.h"
19 #include "openssl_util.h"
20 #include "pkcs7_signed_data.h"
21 #include "pkg_utils.h"
22 #include "securec.h"
23 #include "zip_pkg_parse.h"
24 
25 namespace Hpackage {
26 namespace {
27 constexpr uint32_t ZIP_EOCD_FIXED_PART_LEN = 22;
28 constexpr uint32_t PKG_FOOTER_SIZE = 6;
29 constexpr uint32_t PKG_HASH_CONTENT_LEN = SHA256_DIGEST_LENGTH;
30 }
31 
VerifyPackageSign(const PkgStreamPtr pkgStream) const32 int32_t PkgVerifyUtil::VerifyPackageSign(const PkgStreamPtr pkgStream) const
33 {
34     if (pkgStream == nullptr) {
35         UPDATER_LAST_WORD(PKG_INVALID_PARAM);
36         return PKG_INVALID_PARAM;
37     }
38     size_t signatureSize = 0;
39     std::vector<uint8_t> signature;
40     uint16_t commentTotalLenAll = 0;
41     if (GetSignature(pkgStream, signatureSize, signature, commentTotalLenAll) != PKG_SUCCESS) {
42         PKG_LOGE("get package signature fail!");
43         UPDATER_LAST_WORD(PKG_INVALID_SIGNATURE);
44         return PKG_INVALID_SIGNATURE;
45     }
46 
47     std::vector<uint8_t> hash;
48     int32_t ret = Pkcs7verify(signature, hash);
49     if (ret != PKG_SUCCESS) {
50         PKG_LOGE("pkcs7 verify fail!");
51         UPDATER_LAST_WORD(ret);
52         return ret;
53     }
54     size_t srcDataLen = pkgStream->GetFileLength() - commentTotalLenAll - 2;
55 
56     ret =  HashCheck(pkgStream, srcDataLen, hash);
57     if (ret != PKG_SUCCESS) {
58         srcDataLen = pkgStream->GetFileLength() - signatureSize - ZIP_EOCD_FIXED_PART_LEN;
59         ret = HashCheck(pkgStream, srcDataLen, hash);
60     }
61     return ret;
62 }
63 
GetSignature(const PkgStreamPtr pkgStream,size_t & signatureSize,std::vector<uint8_t> & signature,uint16_t & commentTotalLenAll) const64 int32_t PkgVerifyUtil::GetSignature(const PkgStreamPtr pkgStream, size_t &signatureSize,
65     std::vector<uint8_t> &signature, uint16_t &commentTotalLenAll) const
66 {
67     size_t signatureStart = 0;
68     int32_t ret = ParsePackage(pkgStream, signatureStart, signatureSize, commentTotalLenAll);
69     if (ret != PKG_SUCCESS || signatureSize < PKG_FOOTER_SIZE) {
70         PKG_LOGE("Parse package failed.");
71         UPDATER_LAST_WORD(-1);
72         return -1;
73     }
74 
75     size_t signDataLen = signatureSize - PKG_FOOTER_SIZE;
76     PkgBuffer signData(signDataLen);
77     size_t readLen = 0;
78     ret = pkgStream->Read(signData, signatureStart, signDataLen, readLen);
79     if (ret != PKG_SUCCESS) {
80         PKG_LOGE("read signature failed %s", pkgStream->GetFileName().c_str());
81         UPDATER_LAST_WORD(ret);
82         return ret;
83     }
84     signature.assign(signData.buffer, signData.buffer + readLen);
85 
86     size_t fileLen = pkgStream->GetFileLength();
87     if (fileLen < (signatureSize + ZIP_EOCD_FIXED_PART_LEN)) {
88         PKG_LOGE("Invalid fileLen[%zu] and signature size[%zu]", fileLen, signatureSize);
89         UPDATER_LAST_WORD(PKG_INVALID_PARAM, fileLen, signatureSize);
90         return PKG_INVALID_PARAM;
91     }
92 
93     return PKG_SUCCESS;
94 }
95 
ParsePackage(const PkgStreamPtr pkgStream,size_t & signatureStart,size_t & signatureSize,uint16_t & commentTotalLenAll) const96 int32_t PkgVerifyUtil::ParsePackage(const PkgStreamPtr pkgStream, size_t &signatureStart,
97     size_t &signatureSize, uint16_t &commentTotalLenAll) const
98 {
99     ZipPkgParse zipParse;
100     PkgSignComment pkgSignComment {};
101     int32_t ret = zipParse.ParseZipPkg(pkgStream, pkgSignComment);
102     if (ret != PKG_SUCCESS) {
103         PKG_LOGE("Parse zip package signature failed.");
104         UPDATER_LAST_WORD(ret);
105         return ret;
106     }
107     signatureStart = pkgStream->GetFileLength() - pkgSignComment.signCommentAppendLen;
108     signatureSize = pkgSignComment.signCommentAppendLen;
109     commentTotalLenAll = pkgSignComment.signCommentTotalLen;
110 
111     return PKG_SUCCESS;
112 }
113 
Pkcs7verify(std::vector<uint8_t> & signature,std::vector<uint8_t> & hash) const114 int32_t PkgVerifyUtil::Pkcs7verify(std::vector<uint8_t> &signature, std::vector<uint8_t> &hash) const
115 {
116     Pkcs7SignedData pkcs7;
117 
118     return pkcs7.GetHashFromSignBlock(signature.data(), signature.size(), hash);
119 }
120 
HashCheck(const PkgStreamPtr srcData,const size_t dataLen,const std::vector<uint8_t> & hash) const121 int32_t PkgVerifyUtil::HashCheck(const PkgStreamPtr srcData, const size_t dataLen,
122     const std::vector<uint8_t> &hash) const
123 {
124     Updater::UPDATER_INIT_RECORD;
125     if (srcData == nullptr || dataLen == 0) {
126         UPDATER_LAST_WORD(PKG_INVALID_PARAM);
127         return PKG_INVALID_PARAM;
128     }
129 
130     size_t digestLen = hash.size();
131     if (digestLen != PKG_HASH_CONTENT_LEN) {
132         PKG_LOGE("calc pkg sha256 digest failed.");
133         UPDATER_LAST_WORD(PKG_INVALID_PARAM);
134         return PKG_INVALID_PARAM;
135     }
136     std::vector<uint8_t> sourceDigest(digestLen);
137     int32_t ret = CalcSha256Digest(srcData, dataLen, sourceDigest);
138     if (ret != PKG_SUCCESS) {
139         PKG_LOGE("calc pkg sha256 digest failed.");
140         UPDATER_LAST_WORD(ret);
141         return ret;
142     }
143 
144     if (memcmp(hash.data(), sourceDigest.data(), digestLen) != EOK) {
145         PKG_LOGE("Failed to memcmp data.");
146         UPDATER_LAST_WORD(PKG_INVALID_DIGEST);
147         return PKG_INVALID_DIGEST;
148     }
149 
150     return PKG_SUCCESS;
151 }
152 } // namespace Hpackage
153