1 /*
2 * Copyright (c) 2025 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 "dlp_zip_file.h"
17 #include <cstdlib>
18 #include <fcntl.h>
19 #include <string>
20 #include <cstring>
21 #include <fstream>
22 #include <sstream>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 #include "dlp_permission.h"
27 #include "dlp_permission_kit.h"
28 #include "dlp_permission_public_interface.h"
29 #include "dlp_permission_log.h"
30 #include "dlp_zip.h"
31 #include "dlp_utils.h"
32 #include "hex_string.h"
33 #ifdef DLP_PARSE_INNER
34 #include "os_account_manager.h"
35 #endif // DLP_PARSE_INNER
36 #include "securec.h"
37
38 namespace OHOS {
39 namespace Security {
40 namespace DlpPermission {
41 using Defer = std::shared_ptr<void>;
42 namespace {
43 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION, "DlpZipFile"};
44 const uint32_t HMAC_SIZE = 32;
45 const uint32_t DLP_CWD_MAX = 256;
46 const std::string DLP_GENERAL_INFO = "dlp_general_info";
47 const std::string DLP_CERT = "dlp_cert";
48 const std::string DLP_ENC_DATA = "encrypted_data";
49 const std::string DLP_OPENING_ENC_DATA = "opened_encrypted_data";
50 const std::string DLP_GEN_FILE = "gen_dlp_file";
51 const std::string DEFAULT_STRINGS = "";
52
53 struct GenerInfoParams {
54 bool accessFlag;
55 std::string contactAccount;
56 std::string hmacStr;
57 uint32_t version;
58 std::string realType;
59 uint32_t certSize;
60 };
61 } // namespace
62
63 std::mutex g_fileOpLock_;
64
65 static int32_t GetFileSize(int32_t fd, uint64_t& fileLen);
66
DlpZipFile(int32_t dlpFd,const std::string & workDir,int64_t index,const std::string & realType)67 DlpZipFile::DlpZipFile(int32_t dlpFd, const std::string &workDir, int64_t index, const std::string &realType)
68 : DlpFile(dlpFd, realType), workDir_(workDir), dirIndex_(std::to_string(index))
69 {
70 certSize_ = 0;
71 }
72
~DlpZipFile()73 DlpZipFile::~DlpZipFile()
74 {
75 // clear key
76 if (cipher_.encKey.data != nullptr) {
77 (void)memset_s(cipher_.encKey.data, cipher_.encKey.size, 0, cipher_.encKey.size);
78 delete[] cipher_.encKey.data;
79 cipher_.encKey.data = nullptr;
80 }
81
82 // clear iv
83 if (cipher_.tagIv.iv.data != nullptr) {
84 (void)memset_s(cipher_.tagIv.iv.data, cipher_.tagIv.iv.size, 0, cipher_.tagIv.iv.size);
85 delete[] cipher_.tagIv.iv.data;
86 cipher_.tagIv.iv.data = nullptr;
87 }
88
89 // clear encrypt cert
90 if (cert_.data != nullptr) {
91 (void)memset_s(cert_.data, cert_.size, 0, cert_.size);
92 delete[] cert_.data;
93 cert_.data = nullptr;
94 }
95
96 if (offlineCert_.data != nullptr) {
97 (void)memset_s(offlineCert_.data, offlineCert_.size, 0, offlineCert_.size);
98 delete[] offlineCert_.data;
99 offlineCert_.data = nullptr;
100 }
101
102 // clear hmacKey
103 if (cipher_.hmacKey.data != nullptr) {
104 (void)memset_s(cipher_.hmacKey.data, cipher_.hmacKey.size, 0, cipher_.hmacKey.size);
105 delete[] cipher_.hmacKey.data;
106 cipher_.hmacKey.data = nullptr;
107 }
108
109 // clear hmac_
110 if (hmac_.data != nullptr) {
111 (void)memset_s(hmac_.data, hmac_.size, 0, hmac_.size);
112 delete[] hmac_.data;
113 hmac_.data = nullptr;
114 }
115
116 CleanTmpFile();
117 }
118
SetContactAccount(const std::string & contactAccount)119 int32_t DlpZipFile::SetContactAccount(const std::string& contactAccount)
120 {
121 if (contactAccount.size() == 0 || contactAccount.size() > DLP_MAX_CERT_SIZE) {
122 DLP_LOG_ERROR(LABEL, "contactAccount param failed");
123 return DLP_PARSE_ERROR_VALUE_INVALID;
124 }
125 contactAccount_ = contactAccount;
126 return DLP_OK;
127 };
128
SetOfflineAccess(bool flag)129 void DlpZipFile::SetOfflineAccess(bool flag)
130 {
131 offlineAccess_ = static_cast<uint32_t>(flag);
132 }
133
IsExistFile(const std::string & path)134 static bool IsExistFile(const std::string& path)
135 {
136 if (path.empty()) {
137 return false;
138 }
139
140 struct stat buf = {};
141 if (stat(path.c_str(), &buf) != 0) {
142 return false;
143 }
144
145 return S_ISREG(buf.st_mode);
146 }
147
GetFileContent(const std::string & path,std::string & content)148 static int32_t GetFileContent(const std::string& path, std::string& content)
149 {
150 if (!IsExistFile(path)) {
151 DLP_LOG_INFO(LABEL, "cannot find file, path = %{public}s", path.c_str());
152 return DLP_RETENTION_FILE_FIND_FILE_ERROR;
153 }
154 std::stringstream buffer;
155 std::ifstream i(path);
156 if (!i.is_open()) {
157 DLP_LOG_INFO(LABEL, "cannot open file %{public}s, errno %{public}d.", path.c_str(), errno);
158 return DLP_RETENTION_COMMON_FILE_OPEN_FAILED;
159 }
160 buffer << i.rdbuf();
161 content = buffer.str();
162 i.close();
163 return DLP_OK;
164 }
165
ParseDlpInfo()166 bool DlpZipFile::ParseDlpInfo()
167 {
168 std::string content;
169 (void)GetFileContent(DLP_GENERAL_INFO, content);
170 GenerateInfoParams params;
171 int32_t res = ParseDlpGeneralInfo(content, params);
172 if (res != DLP_OK) {
173 DLP_LOG_ERROR(LABEL, "ParseDlpGeneralInfo %{public}s", content.c_str());
174 return false;
175 }
176 version_ = params.version;
177 offlineAccess_ = params.offlineAccessFlag;
178 extraInfo_ = params.extraInfo;
179 contactAccount_ = params.contactAccount;
180 certSize_ = params.certSize;
181 if (!params.hmacVal.empty()) {
182 CleanBlobParam(hmac_);
183 hmac_.size = params.hmacVal.size() / BYTE_TO_HEX_OPER_LENGTH;
184 if (hmac_.size > HMAC_SIZE) {
185 DLP_LOG_ERROR(LABEL, "hmac_.size is invalid");
186 return false;
187 }
188 hmac_.data = new (std::nothrow)uint8_t[hmac_.size];
189 if (hmac_.data == nullptr) {
190 DLP_LOG_ERROR(LABEL, "New memory fail");
191 return false;
192 }
193 return HexStringToByte(params.hmacVal.c_str(), params.hmacVal.length(), hmac_.data, hmac_.size) == DLP_OK;
194 }
195 return true;
196 }
197
ParseCert()198 bool DlpZipFile::ParseCert()
199 {
200 struct stat fz;
201 if (stat(DLP_CERT.c_str(), &fz) != 0) {
202 DLP_LOG_ERROR(LABEL, "ParseCert failed, %{public}s", strerror(errno));
203 return false;
204 }
205 CleanBlobParam(cert_);
206 if (fz.st_size == 0 || fz.st_size > DLP_MAX_CERT_SIZE || certSize_ > DLP_MAX_CERT_SIZE) {
207 DLP_LOG_ERROR(LABEL, "Cert size is too large or equit to 0.");
208 return false;
209 }
210 uint32_t certSize = certSize_ ? certSize_ : static_cast<uint32_t>(fz.st_size);
211 cert_.data = new (std::nothrow) uint8_t[certSize];
212 if (cert_.data == nullptr) {
213 DLP_LOG_ERROR(LABEL, "new failed");
214 return false;
215 }
216 cert_.size = static_cast<uint32_t>(certSize);
217 int32_t fd = open(DLP_CERT.c_str(), O_RDONLY);
218 if (fd == -1) {
219 DLP_LOG_ERROR(LABEL, "open failed, %{public}s", strerror(errno));
220 return false;
221 }
222
223 uint32_t size = static_cast<uint32_t>(read(fd, cert_.data, cert_.size));
224 (void)close(fd);
225 fd = -1;
226 if (size != cert_.size) {
227 DLP_LOG_ERROR(LABEL, "read failed, %{public}s", strerror(errno));
228 return false;
229 }
230 return true;
231 }
232
ParseEncData()233 bool DlpZipFile::ParseEncData()
234 {
235 int32_t fd = open(DLP_OPENING_ENC_DATA.c_str(), O_RDWR);
236 if (fd == -1) {
237 DLP_LOG_ERROR(LABEL, "ParseEncData failed, %{public}s", strerror(errno));
238 return false;
239 }
240 encDataFd_ = fd;
241 return true;
242 }
243
CleanTmpFile()244 bool DlpZipFile::CleanTmpFile()
245 {
246 close(encDataFd_);
247 encDataFd_ = -1;
248 std::lock_guard<std::mutex> lock(g_fileOpLock_);
249 char cwd[DLP_CWD_MAX] = {0};
250 GETCWD_AND_CHECK(cwd, DLP_CWD_MAX, false, LABEL);
251 Defer p(nullptr, [&](...) {
252 if (chdir(cwd) != 0) {
253 DLP_LOG_ERROR(LABEL, "chdir failed, %{public}s", strerror(errno));
254 }
255 });
256
257 if (chdir(workDir_.c_str()) != 0) {
258 DLP_LOG_ERROR(LABEL, "chdir failed, %{public}s", strerror(errno));
259 return false;
260 }
261
262 if (chdir(dirIndex_.c_str()) != 0) {
263 DLP_LOG_ERROR(LABEL, "chdir failed, %{public}s", strerror(errno));
264 }
265
266 if (unlink(DLP_GENERAL_INFO.c_str()) != 0) {
267 DLP_LOG_ERROR(LABEL, "unlink failed, %{public}s errno %{public}s", DLP_GENERAL_INFO.c_str(), strerror(errno));
268 }
269
270 if (unlink(DLP_CERT.c_str()) != 0) {
271 DLP_LOG_ERROR(LABEL, "unlink failed, %{public}s errno %{public}s", DLP_CERT.c_str(), strerror(errno));
272 }
273
274 if (unlink(DLP_OPENING_ENC_DATA.c_str()) != 0) {
275 DLP_LOG_ERROR(LABEL, "unlink failed, %{public}s errno %{public}s",
276 DLP_OPENING_ENC_DATA.c_str(), strerror(errno));
277 }
278
279 if (chdir(workDir_.c_str()) != 0) {
280 DLP_LOG_ERROR(LABEL, "chdir failed, errno %{public}s", strerror(errno));
281 }
282
283 if (rmdir(dirIndex_.c_str()) != 0) {
284 DLP_LOG_ERROR(LABEL, "rmdir failed, %{public}s errno %{public}s", dirIndex_.c_str(), strerror(errno));
285 }
286
287 if (rmdir(workDir_.c_str()) != 0) {
288 DLP_LOG_ERROR(LABEL, "rmdir failed, %{public}s errno %{public}s", workDir_.c_str(), strerror(errno));
289 }
290
291 return true;
292 }
293
GetOfflineCertSize(void)294 uint32_t DlpZipFile::GetOfflineCertSize(void)
295 {
296 return certSize_;
297 }
298
ProcessDlpFile()299 int32_t DlpZipFile::ProcessDlpFile()
300 {
301 std::lock_guard<std::mutex> lock(g_fileOpLock_);
302 char cwd[DLP_CWD_MAX] = {0};
303 GETCWD_AND_CHECK(cwd, DLP_CWD_MAX, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
304 Defer p(nullptr, [&](...) {
305 if (chdir(cwd) != 0) {
306 DLP_LOG_ERROR(LABEL, "chdir failed, %{public}s", strerror(errno));
307 }
308 });
309
310 CHDIR_AND_CHECK(workDir_.c_str(), DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
311 MKDIR_AND_CHECK(dirIndex_.c_str(), S_IRWXU, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
312 CHDIR_AND_CHECK(dirIndex_.c_str(), DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
313 if (!CheckUnzipFileInfo(dlpFd_)) {
314 return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
315 }
316 UnzipSpecificFile(dlpFd_, DLP_GENERAL_INFO.c_str(), DLP_GENERAL_INFO.c_str());
317 if (!ParseDlpInfo()) {
318 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
319 }
320 UnzipSpecificFile(dlpFd_, DLP_CERT.c_str(), DLP_CERT.c_str());
321 if (!ParseCert()) {
322 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
323 }
324 UnzipSpecificFile(dlpFd_, DLP_ENC_DATA.c_str(), DLP_OPENING_ENC_DATA.c_str());
325 if (!ParseEncData()) {
326 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
327 }
328 return DLP_OK;
329 }
330
CheckDlpFile()331 int32_t DlpZipFile::CheckDlpFile()
332 {
333 if (dlpFd_ < 0) {
334 DLP_LOG_ERROR(LABEL, "dlp file fd is invalid");
335 return DLP_PARSE_ERROR_FD_ERROR;
336 }
337
338 if (isFuseLink_) {
339 DLP_LOG_ERROR(LABEL, "current dlp file is linking, do not operate it.");
340 return DLP_PARSE_ERROR_FILE_LINKING;
341 }
342 return DLP_OK;
343 }
344
SetEncryptCert(const struct DlpBlob & cert)345 int32_t DlpZipFile::SetEncryptCert(const struct DlpBlob& cert)
346 {
347 if (cert.data == nullptr || cert.size > DLP_MAX_CERT_SIZE) {
348 DLP_LOG_ERROR(LABEL, "Cert data invalid");
349 return DLP_PARSE_ERROR_VALUE_INVALID;
350 }
351
352 if (cert_.data != nullptr) {
353 delete[] cert_.data;
354 cert_.data = nullptr;
355 }
356
357 if (CopyBlobParam(cert, cert_) != DLP_OK) {
358 DLP_LOG_ERROR(LABEL, "Cert copy failed");
359 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
360 }
361 return DLP_OK;
362 }
363
UpdateCertAndText(const std::vector<uint8_t> & cert,struct DlpBlob certBlob)364 int32_t DlpZipFile::UpdateCertAndText(const std::vector<uint8_t>& cert, struct DlpBlob certBlob)
365 {
366 if (CopyBlobParam(certBlob, cert_) != DLP_OK) {
367 DLP_LOG_ERROR(LABEL, "Cert copy failed");
368 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
369 }
370 certSize_ = cert_.size;
371 return GenFileInZip(-1);
372 }
373
DoDlpContentCopyOperation(int32_t inFd,int32_t outFd,uint64_t inOffset,uint64_t inFileLen)374 int32_t DlpZipFile::DoDlpContentCopyOperation(int32_t inFd, int32_t outFd, uint64_t inOffset, uint64_t inFileLen)
375 {
376 if (inOffset > inFileLen) {
377 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
378 }
379 uint8_t *data = new (std::nothrow) uint8_t[DLP_BUFF_LEN];
380 if (data == nullptr) {
381 DLP_LOG_ERROR(LABEL, "prepare buff failed");
382 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
383 }
384
385 int32_t ret = DLP_OK;
386 while (inOffset < inFileLen) {
387 uint32_t readLen = ((inFileLen - inOffset) < DLP_BUFF_LEN) ? (inFileLen - inOffset) : DLP_BUFF_LEN;
388 (void)memset_s(data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
389
390 if (read(inFd, data, readLen) != (ssize_t)readLen) {
391 DLP_LOG_ERROR(LABEL, "Read size do not equal readLen");
392 ret = DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
393 break;
394 }
395
396 if (write(outFd, data, readLen) != (ssize_t)readLen) {
397 DLP_LOG_ERROR(LABEL, "write fd failed, %{public}s", strerror(errno));
398 if (outFd != -1 && errno == EBADF) {
399 break;
400 }
401 ret = DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
402 break;
403 }
404 inOffset += readLen;
405 }
406 delete[] data;
407 return ret;
408 }
409
GetFileSize(int32_t fd,uint64_t & fileLen)410 static int32_t GetFileSize(int32_t fd, uint64_t& fileLen)
411 {
412 int32_t ret = DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
413 off_t readLen = lseek(fd, 0, SEEK_END);
414 if (readLen == static_cast<off_t>(-1) || static_cast<uint64_t>(readLen) > UINT32_MAX) {
415 DLP_LOG_ERROR(LABEL, "get file size failed, %{public}s", strerror(errno));
416 } else {
417 fileLen = static_cast<uint64_t>(readLen);
418 ret = DLP_OK;
419 }
420 (void)lseek(fd, 0, SEEK_SET);
421 return ret;
422 }
423
SetDlpGeneralInfo(GenerInfoParams & genInfo)424 static std::string SetDlpGeneralInfo(GenerInfoParams &genInfo)
425 {
426 GenerateInfoParams params = {
427 .version = genInfo.version,
428 .offlineAccessFlag = genInfo.accessFlag,
429 .contactAccount = genInfo.contactAccount,
430 .extraInfo = {"kia_info", "cert_info", "enc_data"},
431 .hmacVal = genInfo.hmacStr,
432 .realType = genInfo.realType,
433 .certSize = genInfo.certSize,
434 };
435 std::string out;
436 GenerateDlpGeneralInfo(params, out);
437 return out;
438 }
439
GenEncData(int32_t inPlainFileFd)440 int32_t DlpZipFile::GenEncData(int32_t inPlainFileFd)
441 {
442 int32_t encFile = -1;
443 if (inPlainFileFd == -1) {
444 encFile = open(DLP_OPENING_ENC_DATA.c_str(), O_RDWR);
445 } else {
446 uint64_t fileLen = 0;
447 int32_t ret = GetFileSize(inPlainFileFd, fileLen);
448 CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
449
450 OPEN_AND_CHECK(encFile, DLP_OPENING_ENC_DATA.c_str(), O_RDWR | O_CREAT | O_TRUNC,
451 S_IRUSR | S_IWUSR, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
452 encDataFd_ = encFile;
453 ret = DoDlpContentCryptyOperation(inPlainFileFd, encFile, 0, fileLen, true);
454 CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
455 LSEEK_AND_CHECK(encFile, 0, SEEK_SET, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
456 }
457 return encFile;
458 }
459
GenerateHmacVal(int32_t encFile,struct DlpBlob & out)460 int32_t DlpZipFile::GenerateHmacVal(int32_t encFile, struct DlpBlob& out)
461 {
462 lseek(encFile, 0, SEEK_SET);
463 int32_t fd = dup(encFile);
464 uint64_t fileLen = 0;
465
466 int32_t ret = GetFileSize(fd, fileLen);
467 if (ret != DLP_OK) {
468 (void)close(fd);
469 DLP_LOG_ERROR(LABEL, "failed to get fileLen");
470 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
471 }
472 if (fileLen == 0) {
473 (void)close(fd);
474 CleanBlobParam(out);
475 return DLP_OK;
476 }
477
478 ret = DlpHmacEncode(cipher_.hmacKey, fd, out);
479 (void)close(fd);
480 return ret;
481 }
482
GetHmacVal(int32_t encFile,std::string & hmacStr)483 int32_t DlpZipFile::GetHmacVal(int32_t encFile, std::string& hmacStr)
484 {
485 if (version_ < HMAC_VERSION) {
486 return DLP_OK;
487 }
488 if (hmac_.size == 0) {
489 uint8_t* outBuf = new (std::nothrow) uint8_t[HMAC_SIZE];
490 if (outBuf == nullptr) {
491 DLP_LOG_ERROR(LABEL, "New memory fail");
492 return DLP_SERVICE_ERROR_MEMORY_OPERATE_FAIL;
493 }
494 struct DlpBlob out = {
495 .size = HMAC_SIZE,
496 .data = outBuf,
497 };
498 int ret = GenerateHmacVal(encFile, out);
499 if (ret != DLP_OK) {
500 CleanBlobParam(out);
501 return ret;
502 }
503 if (out.size == 0) {
504 return DLP_OK;
505 }
506 hmac_.size = out.size;
507 hmac_.data = out.data;
508 }
509 uint32_t hmacHexLen = hmac_.size * BYTE_TO_HEX_OPER_LENGTH + 1;
510 char* hmacHex = new (std::nothrow) char[hmacHexLen];
511 if (hmacHex == nullptr) {
512 DLP_LOG_ERROR(LABEL, "New memory fail");
513 return DLP_SERVICE_ERROR_MEMORY_OPERATE_FAIL;
514 }
515 int ret = ByteToHexString(hmac_.data, hmac_.size, hmacHex, hmacHexLen);
516 if (ret != DLP_OK) {
517 DLP_LOG_ERROR(LABEL, "Byte to hexstring fail");
518 FreeCharBuffer(hmacHex, hmacHexLen);
519 return ret;
520 }
521 hmacStr = hmacHex;
522 FreeCharBuffer(hmacHex, hmacHexLen);
523 return DLP_OK;
524 }
525
AddGeneralInfoToBuff(int32_t encFile)526 int32_t DlpZipFile::AddGeneralInfoToBuff(int32_t encFile)
527 {
528 std::string hmacStr;
529 int ret = GetHmacVal(encFile, hmacStr);
530 if (ret != DLP_OK) {
531 DLP_LOG_ERROR(LABEL, "GetHmacVal fail");
532 return ret;
533 }
534 GenerInfoParams genInfo = {
535 .accessFlag = static_cast<bool>(offlineAccess_),
536 .contactAccount = contactAccount_,
537 .hmacStr = hmacStr,
538 .version = version_,
539 .realType = realType_,
540 .certSize = cert_.size
541 };
542
543 std::string ja = SetDlpGeneralInfo(genInfo);
544 ret = AddBuffToZip(reinterpret_cast<const void *>(ja.c_str()), ja.size(),
545 DLP_GENERAL_INFO.c_str(), DLP_GEN_FILE.c_str());
546 CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
547 return DLP_OK;
548 }
549
GenFileInZip(int32_t inPlainFileFd)550 int32_t DlpZipFile::GenFileInZip(int32_t inPlainFileFd)
551 {
552 char cwd[DLP_CWD_MAX] = {0};
553 std::lock_guard<std::mutex> lock(g_fileOpLock_);
554 GETCWD_AND_CHECK(cwd, DLP_CWD_MAX, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
555 Defer p(nullptr, [&](...) {
556 (void)chdir(cwd);
557 });
558 CHDIR_AND_CHECK(workDir_.c_str(), DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
559 if (inPlainFileFd != -1) {
560 MKDIR_AND_CHECK(dirIndex_.c_str(), S_IRWXU, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
561 }
562 CHDIR_AND_CHECK(dirIndex_.c_str(), DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
563
564 int32_t tmpFile;
565 OPEN_AND_CHECK(tmpFile, DLP_GEN_FILE.c_str(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR,
566 DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
567 Defer p2(nullptr, [&](...) {
568 (void)close(tmpFile);
569 (void)unlink(DLP_GEN_FILE.c_str());
570 });
571 int32_t ret = AddBuffToZip(reinterpret_cast<const void *>(cert_.data), cert_.size,
572 DLP_CERT.c_str(), DLP_GEN_FILE.c_str());
573 CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
574
575 int32_t encFile = GenEncData(inPlainFileFd);
576 Defer p3(nullptr, [&](...) {
577 if (inPlainFileFd == -1) {
578 (void)close(encFile);
579 }
580 });
581
582 ret = AddFileContextToZip(encFile, DLP_ENC_DATA.c_str(), DLP_GEN_FILE.c_str());
583 CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
584 ret = AddGeneralInfoToBuff(encFile);
585 CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
586
587 uint64_t zipSize = 0;
588 ret = GetFileSize(tmpFile, zipSize);
589 CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
590 LSEEK_AND_CHECK(dlpFd_, 0, SEEK_SET, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
591 ret = DoDlpContentCopyOperation(tmpFile, dlpFd_, 0, zipSize);
592 CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
593
594 if (dlpFd_ != -1 && errno == EBADF) {
595 DLP_LOG_DEBUG(LABEL, "this dlp fd is readonly, unable write.");
596 return DLP_OK;
597 }
598 FTRUNCATE_AND_CHECK(dlpFd_, zipSize, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
599
600 (void)fsync(dlpFd_);
601 return DLP_OK;
602 }
603
GenFile(int32_t inPlainFileFd)604 int32_t DlpZipFile::GenFile(int32_t inPlainFileFd)
605 {
606 if (inPlainFileFd < 0 || dlpFd_ < 0 || !IsValidCipher(cipher_.encKey, cipher_.usageSpec, cipher_.hmacKey)) {
607 DLP_LOG_ERROR(LABEL, "params is error");
608 return DLP_PARSE_ERROR_VALUE_INVALID;
609 }
610
611 if (hmac_.size != 0) {
612 CleanBlobParam(hmac_);
613 }
614 return GenFileInZip(inPlainFileFd);
615 }
616
RemoveDlpPermissionInZip(int32_t outPlainFileFd)617 int32_t DlpZipFile::RemoveDlpPermissionInZip(int32_t outPlainFileFd)
618 {
619 std::lock_guard<std::mutex> lock(g_fileOpLock_);
620 char cwd[DLP_CWD_MAX] = {0};
621 GETCWD_AND_CHECK(cwd, DLP_CWD_MAX, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
622 Defer p(nullptr, [&](...) {
623 if (chdir(cwd) != 0) {
624 DLP_LOG_ERROR(LABEL, "chdir failed, %{public}s", strerror(errno));
625 }
626 });
627
628 CHDIR_AND_CHECK(workDir_.c_str(), DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
629 CHDIR_AND_CHECK(dirIndex_.c_str(), DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
630
631 int32_t encFd = open(DLP_OPENING_ENC_DATA.c_str(), O_RDWR, S_IRUSR | S_IWUSR);
632 Defer p2(nullptr, [&](...) {
633 if (close(encFd) != 0) {
634 DLP_LOG_ERROR(LABEL, "close failed, %{public}s", strerror(errno));
635 }
636 });
637
638 uint64_t fileSize = 0;
639 int32_t ret = GetFileSize(encFd, fileSize);
640 CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
641 ret = DoDlpContentCryptyOperation(encFd, outPlainFileFd, 0, fileSize, false);
642 CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
643
644 return DLP_OK;
645 }
646
RemoveDlpPermission(int32_t outPlainFileFd)647 int32_t DlpZipFile::RemoveDlpPermission(int32_t outPlainFileFd)
648 {
649 if (isFuseLink_) {
650 DLP_LOG_ERROR(LABEL, "current dlp file is linking, do not operate it.");
651 return DLP_PARSE_ERROR_FILE_LINKING;
652 }
653
654 if (authPerm_ != DLPFileAccess::FULL_CONTROL) {
655 DLP_LOG_ERROR(LABEL, "check permission fail, remove dlp permission failed.");
656 return DLP_PARSE_ERROR_FILE_READ_ONLY;
657 }
658
659 if (outPlainFileFd < 0 || dlpFd_ < 0) {
660 DLP_LOG_ERROR(LABEL, "fd is invalid");
661 return DLP_PARSE_ERROR_FD_ERROR;
662 }
663
664 if (!IsValidCipher(cipher_.encKey, cipher_.usageSpec, cipher_.hmacKey)) {
665 DLP_LOG_ERROR(LABEL, "cipher params is invalid");
666 return DLP_PARSE_ERROR_CIPHER_PARAMS_INVALID;
667 }
668
669 return RemoveDlpPermissionInZip(outPlainFileFd);
670 }
671
GetFsContentSize() const672 uint64_t DlpZipFile::GetFsContentSize() const
673 {
674 struct stat fileStat;
675 int32_t opFd = encDataFd_;
676 int32_t ret = fstat(opFd, &fileStat);
677 if (ret != 0) {
678 DLP_LOG_ERROR(LABEL, "fstat error %{public}d , errno %{public}d dlpfd: %{public}d ", ret, errno, opFd);
679 return INVALID_FILE_SIZE;
680 }
681 if (0 > fileStat.st_size || fileStat.st_size >= static_cast<off_t>(DLP_MAX_RAW_CONTENT_SIZE)) {
682 DLP_LOG_ERROR(LABEL, "size error %{public}s",
683 std::to_string(static_cast<uint64_t>(fileStat.st_size)).c_str());
684 return INVALID_FILE_SIZE;
685 }
686 return static_cast<uint64_t>(fileStat.st_size);
687 }
688
UpdateDlpFileContentSize()689 int32_t DlpZipFile::UpdateDlpFileContentSize()
690 {
691 uint64_t contentSize = GetFsContentSize();
692 if (contentSize == INVALID_FILE_SIZE) {
693 DLP_LOG_ERROR(LABEL, "get fs content size failed");
694 return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
695 }
696 DLP_LOG_DEBUG(LABEL, "Update dlp file content size");
697 return DLP_OK;
698 }
699
DlpFileRead(uint64_t offset,void * buf,uint32_t size,bool & hasRead,int32_t uid)700 int32_t DlpZipFile::DlpFileRead(uint64_t offset, void* buf, uint32_t size, bool& hasRead, int32_t uid)
701 {
702 int32_t opFd = encDataFd_;
703 if (buf == nullptr || size == 0 || size > DLP_FUSE_MAX_BUFFLEN ||
704 (offset >= DLP_MAX_CONTENT_SIZE - size) ||
705 opFd < 0 || !IsValidCipher(cipher_.encKey, cipher_.usageSpec, cipher_.hmacKey)) {
706 DLP_LOG_ERROR(LABEL, "params is error");
707 return DLP_PARSE_ERROR_VALUE_INVALID;
708 }
709
710 uint32_t alignOffset = (offset / DLP_BLOCK_SIZE) * DLP_BLOCK_SIZE;
711 uint32_t prefixingSize = offset - alignOffset;
712 uint32_t alignSize = size + prefixingSize;
713
714 if (lseek(opFd, alignOffset, SEEK_SET) == -1) {
715 DLP_LOG_ERROR(LABEL, "lseek dlp file failed. %{public}s", strerror(errno));
716 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
717 }
718
719 auto encBuff = std::make_unique<uint8_t[]>(alignSize);
720 auto outBuff = std::make_unique<uint8_t[]>(alignSize);
721
722 int32_t readLen = read(opFd, encBuff.get(), alignSize);
723 if (readLen == -1) {
724 DLP_LOG_ERROR(LABEL, "read buff fail, %{public}s", strerror(errno));
725 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
726 }
727 if (readLen <= static_cast<int32_t>(prefixingSize)) {
728 return 0;
729 }
730
731 struct DlpBlob message1 = {.size = readLen, .data = encBuff.get()};
732 struct DlpBlob message2 = {.size = readLen, .data = outBuff.get()};
733 if (DoDlpBlockCryptOperation(message1, message2, alignOffset, false) != DLP_OK) {
734 DLP_LOG_ERROR(LABEL, "decrypt fail");
735 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
736 }
737
738 if (memcpy_s(buf, size, outBuff.get() + prefixingSize, message2.size - prefixingSize) != EOK) {
739 DLP_LOG_ERROR(LABEL, "copy decrypt result failed");
740 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
741 }
742 if (hasRead) {
743 return message2.size - prefixingSize;
744 }
745 int32_t res = DlpPermissionKit::SetReadFlag(uid);
746 if (res != DLP_OK) {
747 return res;
748 }
749 hasRead = true;
750 return message2.size - prefixingSize;
751 }
752
WriteFirstBlockData(uint64_t offset,void * buf,uint32_t size)753 int32_t DlpZipFile::WriteFirstBlockData(uint64_t offset, void* buf, uint32_t size)
754 {
755 uint64_t alignOffset = (offset / DLP_BLOCK_SIZE) * DLP_BLOCK_SIZE;
756 uint32_t prefixingSize = offset % DLP_BLOCK_SIZE;
757 uint32_t requestSize = (size < (DLP_BLOCK_SIZE - prefixingSize)) ? size : (DLP_BLOCK_SIZE - prefixingSize);
758 uint32_t writtenSize = prefixingSize + requestSize;
759 uint8_t enBuf[DLP_BLOCK_SIZE] = {0};
760 uint8_t deBuf[DLP_BLOCK_SIZE] = {0};
761 int32_t opFd = encDataFd_;
762
763 do {
764 if (prefixingSize == 0) {
765 break;
766 }
767 int32_t readLen = read(opFd, enBuf, prefixingSize);
768 if (readLen == -1) {
769 DLP_LOG_ERROR(LABEL, "read first block prefixing fail, %{public}s", strerror(errno));
770 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
771 }
772 if (readLen == 0) {
773 break;
774 }
775
776 struct DlpBlob message1 = {.size = prefixingSize, .data = enBuf};
777 struct DlpBlob message2 = {.size = prefixingSize, .data = deBuf};
778 if (DoDlpBlockCryptOperation(message1, message2, alignOffset, false) != DLP_OK) {
779 DLP_LOG_ERROR(LABEL, "decrypt appending bytes fail, %{public}s", strerror(errno));
780 return DLP_PARSE_ERROR_CRYPT_FAIL;
781 }
782 } while (false);
783
784 if (memcpy_s(deBuf + prefixingSize, DLP_BLOCK_SIZE - prefixingSize, buf, requestSize) != EOK) {
785 DLP_LOG_ERROR(LABEL, "copy write buffer first block failed, %{public}s", strerror(errno));
786 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
787 }
788
789 struct DlpBlob message1 = {.size = writtenSize, .data = deBuf};
790 struct DlpBlob message2 = {.size = writtenSize, .data = enBuf};
791 if (DoDlpBlockCryptOperation(message1, message2, alignOffset, true) != DLP_OK) {
792 DLP_LOG_ERROR(LABEL, "enrypt first block fail");
793 return DLP_PARSE_ERROR_CRYPT_FAIL;
794 }
795
796 if (lseek(opFd, alignOffset, SEEK_SET) == static_cast<off_t>(-1)) {
797 DLP_LOG_ERROR(LABEL, "lseek failed, %{public}s", strerror(errno));
798 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
799 }
800
801 if (write(opFd, enBuf, writtenSize) != (ssize_t)writtenSize) {
802 DLP_LOG_ERROR(LABEL, "write failed, %{public}s", strerror(errno));
803 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
804 }
805 return requestSize;
806 }
807
DoDlpFileWrite(uint64_t offset,void * buf,uint32_t size)808 int32_t DlpZipFile::DoDlpFileWrite(uint64_t offset, void* buf, uint32_t size)
809 {
810 int32_t opFd = encDataFd_;
811 uint64_t alignOffset = (offset / DLP_BLOCK_SIZE * DLP_BLOCK_SIZE);
812 if (lseek(opFd, alignOffset, SEEK_SET) == static_cast<off_t>(-1)) {
813 DLP_LOG_ERROR(LABEL, "lseek dlp file offset %{public}s failed, %{public}s",
814 std::to_string(offset).c_str(), strerror(errno));
815 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
816 }
817
818 /* write first block data, if it may be not aligned */
819 int32_t writenSize = WriteFirstBlockData(offset, static_cast<uint8_t *>(buf), size);
820 if (writenSize < 0) {
821 DLP_LOG_ERROR(LABEL, "encrypt prefix data failed");
822 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
823 }
824 if (static_cast<uint32_t>(writenSize) >= size) {
825 return writenSize;
826 }
827
828 uint8_t *restBlocksPtr = static_cast<uint8_t *>(buf) + writenSize;
829 uint32_t restBlocksSize = size - static_cast<uint32_t>(writenSize);
830 uint8_t* writeBuff = new (std::nothrow) uint8_t[restBlocksSize]();
831 if (writeBuff == nullptr) {
832 DLP_LOG_ERROR(LABEL, "alloc write buffer fail");
833 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
834 }
835
836 /* first aligned block has been writen, write the rest */
837 struct DlpBlob message1 = {.size = restBlocksSize, .data = restBlocksPtr};
838 struct DlpBlob message2 = {.size = restBlocksSize, .data = writeBuff};
839
840 int32_t ret = DoDlpBlockCryptOperation(message1, message2, alignOffset + DLP_BLOCK_SIZE, true);
841 if (ret != DLP_OK) {
842 DLP_LOG_ERROR(LABEL, "encrypt write buffer fail");
843 delete[] writeBuff;
844 return ret;
845 }
846
847 ret = write(opFd, writeBuff, restBlocksSize);
848 delete[] writeBuff;
849 if (ret <= 0) {
850 DLP_LOG_ERROR(LABEL, "write buff failed, %{public}s", strerror(errno));
851 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
852 }
853
854 return ret + static_cast<int32_t>(writenSize);
855 }
856
DlpFileWrite(uint64_t offset,void * buf,uint32_t size)857 int32_t DlpZipFile::DlpFileWrite(uint64_t offset, void* buf, uint32_t size)
858 {
859 if (authPerm_ == DLPFileAccess::READ_ONLY) {
860 DLP_LOG_ERROR(LABEL, "Dlp file is readonly, write failed");
861 return DLP_PARSE_ERROR_FILE_READ_ONLY;
862 }
863 int32_t opFd = encDataFd_;
864 if (buf == nullptr || size == 0 || size > DLP_FUSE_MAX_BUFFLEN ||
865 (offset >= DLP_MAX_CONTENT_SIZE - size) ||
866 opFd < 0 || !IsValidCipher(cipher_.encKey, cipher_.usageSpec, cipher_.hmacKey)) {
867 DLP_LOG_ERROR(LABEL, "Dlp file param invalid");
868 return DLP_PARSE_ERROR_VALUE_INVALID;
869 }
870
871 uint64_t curSize = GetFsContentSize();
872 if (curSize != INVALID_FILE_SIZE && curSize < offset &&
873 (FillHoleData(curSize, offset - curSize) != DLP_OK)) {
874 DLP_LOG_ERROR(LABEL, "Fill hole data failed");
875 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
876 }
877 int32_t res = DoDlpFileWrite(offset, buf, size);
878 UpdateDlpFileContentSize();
879
880 // modify dlp file, clear old hmac value and will generate new
881 if (hmac_.size != 0) {
882 CleanBlobParam(hmac_);
883 }
884 GenFileInZip(-1);
885 return res;
886 }
887
Truncate(uint64_t size)888 int32_t DlpZipFile::Truncate(uint64_t size)
889 {
890 DLP_LOG_INFO(LABEL, "Truncate file size %{public}s", std::to_string(size).c_str());
891
892 if (authPerm_ == DLPFileAccess::READ_ONLY) {
893 DLP_LOG_ERROR(LABEL, "Dlp file is readonly, truncate failed");
894 return DLP_PARSE_ERROR_FILE_READ_ONLY;
895 }
896 int32_t opFd = encDataFd_;
897 if (opFd < 0 || size >= DLP_MAX_CONTENT_SIZE) {
898 DLP_LOG_ERROR(LABEL, "Param invalid");
899 return DLP_PARSE_ERROR_VALUE_INVALID;
900 }
901
902 uint64_t curSize = GetFsContentSize();
903 int32_t res = DLP_OK;
904 if (size < curSize) {
905 res = ftruncate(opFd, size);
906 UpdateDlpFileContentSize();
907 GenFileInZip(-1);
908 } else if (size > curSize) {
909 res = FillHoleData(curSize, size - curSize);
910 UpdateDlpFileContentSize();
911 GenFileInZip(-1);
912 } else {
913 DLP_LOG_INFO(LABEL, "Truncate file size equals origin file");
914 }
915
916 if (res != DLP_OK) {
917 DLP_LOG_ERROR(LABEL, "Truncate file size %{public}s failed, %{public}s",
918 std::to_string(size).c_str(), strerror(errno));
919 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
920 }
921 return DLP_OK;
922 }
923
HmacCheck()924 int32_t DlpZipFile::HmacCheck()
925 {
926 DLP_LOG_DEBUG(LABEL, "start HmacCheck, dlpVersion = %{public}d", version_);
927 if (version_ < HMAC_VERSION) {
928 DLP_LOG_INFO(LABEL, "no hmac check");
929 return DLP_OK;
930 }
931
932 uint8_t* outBuf = new (std::nothrow) uint8_t[HMAC_SIZE];
933 if (outBuf == nullptr) {
934 DLP_LOG_ERROR(LABEL, "New memory fail");
935 return DLP_SERVICE_ERROR_MEMORY_OPERATE_FAIL;
936 }
937 struct DlpBlob out = {
938 .size = HMAC_SIZE,
939 .data = outBuf,
940 };
941
942 int ret = GenerateHmacVal(encDataFd_, out);
943 if (ret != DLP_OK) {
944 CleanBlobParam(out);
945 return ret;
946 }
947
948 if ((out.size == 0 && hmac_.size == 0) ||
949 (out.size == hmac_.size && memcmp(hmac_.data, out.data, out.size) == 0)) {
950 DLP_LOG_INFO(LABEL, "verify success");
951 if (out.size != 0) {
952 CleanBlobParam(out);
953 }
954 return DLP_OK;
955 }
956 DLP_LOG_ERROR(LABEL, "verify fail");
957 CleanBlobParam(out);
958 return DLP_PARSE_ERROR_FILE_VERIFICATION_FAIL;
959 }
960
DoDlpContentCryptyOperation(int32_t inFd,int32_t outFd,uint64_t inOffset,uint64_t inFileLen,bool isEncrypt)961 int32_t DlpZipFile::DoDlpContentCryptyOperation(int32_t inFd, int32_t outFd, uint64_t inOffset,
962 uint64_t inFileLen, bool isEncrypt)
963 {
964 struct DlpBlob message;
965 struct DlpBlob outMessage;
966 if (PrepareBuff(message, outMessage) != DLP_OK) {
967 DLP_LOG_ERROR(LABEL, "prepare buff failed");
968 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
969 }
970
971 uint64_t dlpContentOffset = inOffset;
972 int32_t ret = DLP_OK;
973 while (inOffset < inFileLen) {
974 uint32_t readLen = ((inFileLen - inOffset) < DLP_BUFF_LEN) ? (inFileLen - inOffset) : DLP_BUFF_LEN;
975 (void)memset_s(message.data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
976 (void)memset_s(outMessage.data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
977 if (read(inFd, message.data, readLen) != (ssize_t)readLen) {
978 DLP_LOG_ERROR(LABEL, "Read size do not equal readLen");
979 ret = DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
980 break;
981 }
982
983 message.size = readLen;
984 outMessage.size = readLen;
985 // Implicit condition: DLP_BUFF_LEN must be DLP_BLOCK_SIZE aligned
986 ret = DoDlpBlockCryptOperation(message, outMessage, inOffset - dlpContentOffset, isEncrypt);
987 if (ret != DLP_OK) {
988 DLP_LOG_ERROR(LABEL, "do crypt operation fail");
989 break;
990 }
991
992 if (write(outFd, outMessage.data, readLen) != (ssize_t)readLen) {
993 DLP_LOG_ERROR(LABEL, "write fd failed, %{public}s", strerror(errno));
994 ret = DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
995 break;
996 }
997 inOffset += readLen;
998 }
999
1000 delete[] message.data;
1001 delete[] outMessage.data;
1002 return ret;
1003 }
1004 } // namespace DlpPermission
1005 } // namespace Security
1006 } // namespace OHOS
1007