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(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
GetAlgorithm(const PkgManager::FileInfoPtr config)152 PkgAlgorithm::PkgAlgorithmPtr PkgAlgorithmFactory::GetAlgorithm(const PkgManager::FileInfoPtr config)
153 {
154 if (config == nullptr) {
155 PKG_LOGE("Fail to get algorithm ");
156 return nullptr;
157 }
158 switch (config->packMethod) {
159 case PKG_COMPRESS_METHOD_ZIP:
160 case PKG_COMPRESS_METHOD_GZIP: {
161 if (config == nullptr) {
162 PKG_LOGE("Invalid param config");
163 return nullptr;
164 }
165 const ZipFileInfo *info = reinterpret_cast<ZipFileInfo *>(config);
166 return std::make_shared<PkgAlgoDeflate>(*info);
167 }
168 case PKG_COMPRESS_METHOD_NONE:
169 return std::make_shared<PkgAlgorithm>();
170 case PKG_COMPRESS_METHOD_LZ4: {
171 if (config == nullptr) {
172 PKG_LOGE("Invalid param config");
173 return nullptr;
174 }
175 const Lz4FileInfo *info = reinterpret_cast<Lz4FileInfo *>(config);
176 return std::make_shared<PkgAlgorithmLz4>(*info);
177 }
178 case PKG_COMPRESS_METHOD_LZ4_BLOCK: {
179 if (config == nullptr) {
180 PKG_LOGE("Invalid param config");
181 return nullptr;
182 }
183 const Lz4FileInfo *info = reinterpret_cast<Lz4FileInfo *>(config);
184 return std::make_shared<PkgAlgorithmBlockLz4>(*info);
185 }
186 default:
187 break;
188 }
189 return nullptr;
190 }
191 } // namespace Hpackage
192