• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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