1 /*
2 * Copyright (c) 2021 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 "pkg_algorithm.h"
16 #include "pkg_algo_deflate.h"
17 #include "pkg_algo_lz4.h"
18 #include "pkg_stream.h"
19 #include "pkg_utils.h"
20 #include "securec.h"
21
22 namespace Hpackage {
23 constexpr uint32_t MAX_BUFFER_SIZE = (4 * 1024 * 1024);
24
ReadData(const PkgStreamPtr inStream,size_t offset,PkgBuffer & buffer,size_t & remainSize,size_t & readLen) const25 int32_t PkgAlgorithm::ReadData(const PkgStreamPtr inStream, size_t offset, PkgBuffer &buffer,
26 size_t &remainSize, size_t &readLen) const
27 {
28 size_t readBytes = 0;
29 size_t remainBytes = (remainSize > buffer.length) ? buffer.length : remainSize;
30 if (remainBytes != 0) {
31 int32_t ret = inStream->Read(buffer, offset, remainBytes, readBytes);
32 if (ret != PKG_SUCCESS) {
33 PKG_LOGE("fail deflate write data ");
34 return ret;
35 }
36 }
37 remainSize -= readBytes;
38 readLen = readBytes;
39 return PKG_SUCCESS;
40 }
41
FinalDigest(DigestAlgorithm::DigestAlgorithmPtr algorithm,PkgAlgorithmContext & context,bool check) const42 int32_t PkgAlgorithm::FinalDigest(DigestAlgorithm::DigestAlgorithmPtr algorithm,
43 PkgAlgorithmContext &context, bool check) const
44 {
45 if (context.digestMethod == PKG_DIGEST_TYPE_SHA256) {
46 PkgBuffer digest(DIGEST_MAX_LEN);
47 algorithm->Final(digest);
48 if (check && memcmp(digest.buffer, context.digest, DIGEST_MAX_LEN) != 0) {
49 return PKG_INVALID_DIGEST;
50 }
51 if (memcpy_s(context.digest, sizeof(context.digest), digest.buffer, DIGEST_MAX_LEN) != EOK) {
52 PKG_LOGE("FinalDigest memcpy failed");
53 return PKG_NONE_MEMORY;
54 }
55 }
56 return PKG_SUCCESS;
57 }
58
Pack(const PkgStreamPtr inStream,const PkgStreamPtr outStream,PkgAlgorithmContext & context)59 int32_t PkgAlgorithm::Pack(const PkgStreamPtr inStream, const PkgStreamPtr outStream,
60 PkgAlgorithmContext &context)
61 {
62 DigestAlgorithm::DigestAlgorithmPtr algorithm = PkgAlgorithmFactory::GetDigestAlgorithm(context.digestMethod);
63 if (algorithm == nullptr) {
64 PKG_LOGE("Can not get digest algor");
65 return PKG_NOT_EXIST_ALGORITHM;
66 }
67 algorithm->Init();
68
69 PkgBuffer buffer(MAX_BUFFER_SIZE);
70 int32_t ret = PKG_SUCCESS;
71 size_t srcOffset = context.srcOffset;
72 size_t destOffset = context.destOffset;
73 size_t remainSize = context.unpackedSize;
74 size_t readLen = 0;
75 while (remainSize > 0) {
76 ret = ReadData(inStream, srcOffset, buffer, remainSize, readLen);
77 if (ret != PKG_SUCCESS) {
78 PKG_LOGE("Fail read data ");
79 break;
80 }
81
82 ret = outStream->Write(buffer, readLen, destOffset);
83 if (ret != PKG_SUCCESS) {
84 PKG_LOGE("Fail write data ");
85 break;
86 }
87
88 algorithm->Update(buffer, readLen);
89 srcOffset += readLen;
90 destOffset += readLen;
91 }
92
93 ret = FinalDigest(algorithm, context, true);
94 if (ret != 0) {
95 PKG_LOGE("Check digest fail");
96 return ret;
97 }
98 if (srcOffset - context.srcOffset != context.unpackedSize) {
99 PKG_LOGE("original size error %zu %zu", srcOffset, context.unpackedSize);
100 return PKG_INVALID_DIGEST;
101 }
102 context.packedSize = destOffset - context.destOffset;
103 return ret;
104 }
105
Unpack(const PkgStreamPtr inStream,const PkgStreamPtr outStream,PkgAlgorithmContext & context)106 int32_t PkgAlgorithm::Unpack(const PkgStreamPtr inStream, const PkgStreamPtr outStream,
107 PkgAlgorithmContext &context)
108 {
109 DigestAlgorithm::DigestAlgorithmPtr algorithm = PkgAlgorithmFactory::GetDigestAlgorithm(context.digestMethod);
110 if (algorithm == nullptr) {
111 PKG_LOGE("Can not get digest algor");
112 return PKG_NOT_EXIST_ALGORITHM;
113 }
114 algorithm->Init();
115 PkgBuffer buffer(nullptr, MAX_BUFFER_SIZE);
116 int32_t ret = PKG_SUCCESS;
117 size_t srcOffset = context.srcOffset;
118 size_t destOffset = context.destOffset;
119 size_t remainSize = context.packedSize;
120 size_t readLen = 0;
121 while (remainSize > 0) {
122 ret = ReadData(inStream, srcOffset, buffer, remainSize, readLen);
123 if (ret != PKG_SUCCESS) {
124 PKG_LOGE("Fail read data ");
125 break;
126 }
127
128 ret = outStream->Write(buffer, readLen, destOffset);
129 if (ret != PKG_SUCCESS) {
130 PKG_LOGE("Fail write data ");
131 break;
132 }
133
134 algorithm->Update(buffer, readLen);
135 srcOffset += readLen;
136 destOffset += readLen;
137 }
138
139 ret = FinalDigest(algorithm, context, true);
140 if (ret != 0) {
141 PKG_LOGE("Check digest fail");
142 return ret;
143 }
144 if (destOffset - context.destOffset != context.packedSize) {
145 PKG_LOGE("original size error %zu %zu", destOffset, context.packedSize);
146 return PKG_INVALID_DIGEST;
147 }
148 context.unpackedSize = srcOffset - context.srcOffset;
149 return ret;
150 }
151
UnpackWithVerify(const PkgStreamPtr inStream,const PkgStreamPtr outStream,PkgAlgorithmContext & context,VerifyFunction verifier)152 int32_t PkgAlgorithm::UnpackWithVerify(const PkgStreamPtr inStream, const PkgStreamPtr outStream,
153 PkgAlgorithmContext &context, VerifyFunction verifier)
154 {
155 DigestAlgorithm::DigestAlgorithmPtr algorithm = PkgAlgorithmFactory::GetDigestAlgorithm(context.digestMethod);
156 if (algorithm == nullptr) {
157 PKG_LOGE("Can not get digest algor");
158 return PKG_NOT_EXIST_ALGORITHM;
159 }
160 algorithm->Init();
161 PkgBuffer buffer(nullptr, MAX_BUFFER_SIZE);
162
163 int32_t ret = PKG_SUCCESS;
164 size_t srcOffset = context.srcOffset;
165 size_t destOffset = context.destOffset;
166 size_t remainSize = context.packedSize;
167 size_t readLen = 0;
168 while (remainSize > 0) {
169 ret = ReadData(inStream, srcOffset, buffer, remainSize, readLen);
170 if (ret != PKG_SUCCESS) {
171 PKG_LOGE("Fail read data ");
172 break;
173 }
174
175 if (verifier != nullptr) {
176 ret = verifier(buffer, readLen, destOffset);
177 if (ret != PKG_SUCCESS) {
178 PKG_LOGE("Fail verify read data");
179 break;
180 }
181 }
182
183 ret = outStream->Write(buffer, readLen, destOffset);
184 if (ret != PKG_SUCCESS) {
185 PKG_LOGE("Fail write data ");
186 break;
187 }
188
189 algorithm->Update(buffer, readLen);
190 srcOffset += readLen;
191 destOffset += readLen;
192 }
193
194 ret = FinalDigest(algorithm, context, true);
195 if (ret != 0) {
196 PKG_LOGE("Check digest fail");
197 return ret;
198 }
199 if (destOffset - context.destOffset != context.packedSize) {
200 PKG_LOGE("original size error %zu %zu", destOffset, context.packedSize);
201 return PKG_INVALID_DIGEST;
202 }
203 context.unpackedSize = srcOffset - context.srcOffset;
204 return ret;
205 }
206
GetAlgorithm(const PkgManager::FileInfoPtr config)207 PkgAlgorithm::PkgAlgorithmPtr PkgAlgorithmFactory::GetAlgorithm(const PkgManager::FileInfoPtr config)
208 {
209 if (config == nullptr) {
210 PKG_LOGE("Fail to get algorithm ");
211 return nullptr;
212 }
213 switch (config->packMethod) {
214 case PKG_COMPRESS_METHOD_ZIP:
215 case PKG_COMPRESS_METHOD_GZIP: {
216 if (config == nullptr) {
217 PKG_LOGE("Invalid param config");
218 return nullptr;
219 }
220 const ZipFileInfo *info = (ZipFileInfo *)config;
221 return std::make_shared<PkgAlgoDeflate>(*info);
222 }
223 case PKG_COMPRESS_METHOD_NONE:
224 return std::make_shared<PkgAlgorithm>();
225 case PKG_COMPRESS_METHOD_LZ4: {
226 if (config == nullptr) {
227 PKG_LOGE("Invalid param config");
228 return nullptr;
229 }
230 const Lz4FileInfo *info = (Lz4FileInfo *)config;
231 return std::make_shared<PkgAlgorithmLz4>(*info);
232 }
233 case PKG_COMPRESS_METHOD_LZ4_BLOCK: {
234 if (config == nullptr) {
235 PKG_LOGE("Invalid param config");
236 return nullptr;
237 }
238 const Lz4FileInfo *info = (Lz4FileInfo *)config;
239 return std::make_shared<PkgAlgorithmBlockLz4>(*info);
240 }
241 default:
242 break;
243 }
244 return nullptr;
245 }
246 } // namespace Hpackage
247