1 /*
2  * Copyright (c) 2023-2024 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_file.h"
17 
18 #include <cstdlib>
19 #include <fcntl.h>
20 #include <string>
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 "hex_string.h"
32 #include "ohos_account_kits.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, "DlpFile"};
44 const uint32_t FIRST = 1;
45 const uint32_t SECOND = 2;
46 const uint32_t HMAC_SIZE = 32;
47 const uint32_t DLP_CWD_MAX = 256;
48 const std::string DLP_GENERAL_INFO = "dlp_general_info";
49 const std::string DLP_CERT = "dlp_cert";
50 const std::string DLP_ENC_DATA = "encrypted_data";
51 const std::string DLP_OPENING_ENC_DATA = "opened_encrypted_data";
52 const std::string DLP_GEN_FILE = "gen_dlp_file";
53 } // namespace
54 std::mutex g_fileOpLock_;
55 
DlpFile(int32_t dlpFd,const std::string & workDir,int64_t index,bool isZip)56 DlpFile::DlpFile(int32_t dlpFd, const std::string &workDir, int64_t index, bool isZip) : dlpFd_(dlpFd),
57     workDir_(workDir), dirIndex_(std::to_string(index)), isZip_(isZip), isFuseLink_(false), authPerm_(READ_ONLY)
58 {
59     head_.magic = DLP_FILE_MAGIC;
60     head_.version = CURRENT_VERSION;
61     head_.offlineAccess = 0;
62     head_.txtOffset = INVALID_FILE_SIZE;
63     head_.txtSize = INVALID_FILE_SIZE;
64     head_.certOffset = sizeof(struct DlpHeader);
65     head_.certSize = 0;
66     head_.contactAccountOffset = 0;
67     head_.contactAccountSize = 0;
68     head_.offlineCertOffset = 0;
69     head_.offlineCertSize = 0;
70 
71     cert_.data = nullptr;
72     cert_.size = 0;
73 
74     offlineCert_.data = nullptr;
75     offlineCert_.size = 0;
76 
77     cipher_.tagIv.iv.data = nullptr;
78     cipher_.tagIv.iv.size = 0;
79     cipher_.encKey.data = nullptr;
80     cipher_.encKey.size = 0;
81     cipher_.usageSpec = { 0 };
82     cipher_.hmacKey.data = nullptr;
83     cipher_.hmacKey.size = 0;
84 
85     hmac_.data = nullptr;
86     hmac_.size = 0;
87 
88     encDataFd_ = -1;
89 }
90 
~DlpFile()91 DlpFile::~DlpFile()
92 {
93     // clear key
94     if (cipher_.encKey.data != nullptr) {
95         (void)memset_s(cipher_.encKey.data, cipher_.encKey.size, 0, cipher_.encKey.size);
96         delete[] cipher_.encKey.data;
97         cipher_.encKey.data = nullptr;
98     }
99 
100     // clear iv
101     if (cipher_.tagIv.iv.data != nullptr) {
102         (void)memset_s(cipher_.tagIv.iv.data, cipher_.tagIv.iv.size, 0, cipher_.tagIv.iv.size);
103         delete[] cipher_.tagIv.iv.data;
104         cipher_.tagIv.iv.data = nullptr;
105     }
106 
107     // clear encrypt cert
108     if (cert_.data != nullptr) {
109         (void)memset_s(cert_.data, head_.certSize, 0, head_.certSize);
110         delete[] cert_.data;
111         cert_.data = nullptr;
112     }
113 
114     if (offlineCert_.data != nullptr) {
115         (void)memset_s(offlineCert_.data, head_.offlineCertSize, 0, head_.offlineCertSize);
116         delete[] offlineCert_.data;
117         offlineCert_.data = nullptr;
118     }
119 
120     // clear hmacKey
121     if (cipher_.hmacKey.data != nullptr) {
122         (void)memset_s(cipher_.hmacKey.data, cipher_.hmacKey.size, 0, cipher_.hmacKey.size);
123         delete[] cipher_.hmacKey.data;
124         cipher_.hmacKey.data = nullptr;
125     }
126 
127     // clear hmac_
128     if (hmac_.data != nullptr) {
129         (void)memset_s(hmac_.data, hmac_.size, 0, hmac_.size);
130         delete[] hmac_.data;
131         hmac_.data = nullptr;
132     }
133 
134     CleanTmpFile();
135 }
136 
IsValidCipher(const struct DlpBlob & key,const struct DlpUsageSpec & spec,const struct DlpBlob & hmacKey) const137 bool DlpFile::IsValidCipher(const struct DlpBlob& key, const struct DlpUsageSpec& spec,
138     const struct DlpBlob& hmacKey) const
139 {
140     if (key.data == nullptr) {
141         DLP_LOG_ERROR(LABEL, "key data null");
142         return false;
143     }
144 
145     if (key.size != DLP_KEY_LEN_128 && key.size != DLP_KEY_LEN_192 && key.size != DLP_KEY_LEN_256) {
146         DLP_LOG_ERROR(LABEL, "key size invalid");
147         return false;
148     }
149 
150     if (spec.mode != DLP_MODE_CTR || spec.algParam == nullptr) {
151         DLP_LOG_ERROR(LABEL, "spec invalid");
152         return false;
153     }
154 
155     struct DlpBlob& iv = spec.algParam->iv;
156     if (iv.size != IV_SIZE || iv.data == nullptr) {
157         DLP_LOG_ERROR(LABEL, "iv invalid");
158         return false;
159     }
160 
161     if (hmacKey.data != nullptr && hmacKey.size != DLP_KEY_LEN_256) {
162         DLP_LOG_ERROR(LABEL, "hmacKey size invalid");
163         return false;
164     }
165     return true;
166 }
167 
CopyBlobParam(const struct DlpBlob & src,struct DlpBlob & dst) const168 int32_t DlpFile::CopyBlobParam(const struct DlpBlob& src, struct DlpBlob& dst) const
169 {
170     if (src.data == nullptr || src.size == 0 || src.size > DLP_MAX_CERT_SIZE) {
171         DLP_LOG_ERROR(LABEL, "src data null");
172         return DLP_PARSE_ERROR_VALUE_INVALID;
173     }
174 
175     uint8_t* blobData = new (std::nothrow)uint8_t[src.size];
176     if (blobData == nullptr) {
177         DLP_LOG_ERROR(LABEL, "blobData null");
178         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
179     }
180 
181     if (memcpy_s(blobData, src.size, src.data, src.size) != EOK) {
182         DLP_LOG_ERROR(LABEL, "memcpy_s error");
183         delete[] blobData;
184         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
185     }
186 
187     if (dst.data != nullptr) {
188         (void)memset_s(dst.data, dst.size, 0, dst.size);
189         delete[] dst.data;
190         dst.data = nullptr;
191     }
192     dst.data = blobData;
193     dst.size = src.size;
194     return DLP_OK;
195 }
196 
CleanBlobParam(struct DlpBlob & blob) const197 int32_t DlpFile::CleanBlobParam(struct DlpBlob& blob) const
198 {
199     if (blob.data == nullptr || blob.size == 0) {
200         DLP_LOG_ERROR(LABEL, "blobData null");
201         return DLP_PARSE_ERROR_VALUE_INVALID;
202     }
203 
204     (void)memset_s(blob.data, blob.size, 0, blob.size);
205     delete[] blob.data;
206     blob.data = nullptr;
207     blob.size = 0;
208     return DLP_OK;
209 }
210 
GetLocalAccountName(std::string & account) const211 int32_t DlpFile::GetLocalAccountName(std::string& account) const
212 {
213     std::pair<bool, AccountSA::OhosAccountInfo> accountInfo =
214         AccountSA::OhosAccountKits::GetInstance().QueryOhosAccountInfo();
215     if (accountInfo.first) {
216         account = accountInfo.second.name_;
217         return DLP_OK;
218     }
219     DLP_LOG_ERROR(LABEL, "QueryOhosAccountInfo accountInfo error");
220     return DLP_PARSE_ERROR_ACCOUNT_INVALID;
221 }
222 
GetDomainAccountName(std::string & account) const223 int32_t DlpFile::GetDomainAccountName(std::string& account) const
224 {
225 #ifdef DLP_PARSE_INNER
226     AccountSA::OsAccountInfo osAccountInfo;
227     if (OHOS::AccountSA::OsAccountManager::QueryCurrentOsAccount(osAccountInfo) != 0) {
228         DLP_LOG_ERROR(LABEL, "QueryCurrentOsAccount return not 0");
229         return DLP_PARSE_ERROR_ACCOUNT_INVALID;
230     }
231     AccountSA::DomainAccountInfo domainInfo;
232     osAccountInfo.GetDomainInfo(domainInfo);
233     if (domainInfo.accountName_.empty()) {
234         DLP_LOG_ERROR(LABEL, "accountName_ empty");
235         return DLP_PARSE_ERROR_ACCOUNT_INVALID;
236     }
237     account = domainInfo.accountName_;
238 #endif
239     return DLP_OK;
240 }
241 
UpdateDlpFilePermission()242 bool DlpFile::UpdateDlpFilePermission()
243 {
244     if (!policy_.accountName_.empty()) {
245         DLP_LOG_INFO(LABEL, "AccountName_ is not empty, perm is  %{public}d", policy_.perm_);
246         authPerm_ = policy_.perm_;
247         return true;
248     }
249     std::string accountName;
250     if (policy_.ownerAccountType_ == DOMAIN_ACCOUNT) {
251         if (GetDomainAccountName(accountName) != DLP_OK) {
252             DLP_LOG_ERROR(LABEL, "query GetDomainAccountName failed");
253             return false;
254         }
255     } else {
256         DLP_LOG_DEBUG(LABEL, "AuthPerm_ is readonly");
257         authPerm_ = READ_ONLY;
258         return true;
259     }
260 
261     if (accountName == policy_.ownerAccount_) {
262         DLP_LOG_DEBUG(LABEL, "current account is owner, it has full permission");
263         authPerm_ = FULL_CONTROL;
264         return true;
265     }
266 
267     if (policy_.supportEveryone_) {
268         DLP_LOG_DEBUG(LABEL, "everyone has perm permission %{public}d", policy_.everyonePerm_);
269         authPerm_ = policy_.everyonePerm_;
270     } else {
271         DLP_LOG_DEBUG(LABEL, "everyone has not perm permission %{public}d", policy_.everyonePerm_);
272     }
273 
274     for (int32_t i = 0; i < static_cast<int32_t>(policy_.authUsers_.size()); i++) {
275         if (accountName == policy_.authUsers_[i].authAccount) {
276             authPerm_ = policy_.authUsers_[i].authPerm;
277             DLP_LOG_DEBUG(LABEL, "current account match authUsers list, authPerm_ %{public}d",
278                 authPerm_);
279         }
280     }
281     return true;
282 }
283 
SetCipher(const struct DlpBlob & key,const struct DlpUsageSpec & spec,const struct DlpBlob & hmacKey)284 int32_t DlpFile::SetCipher(const struct DlpBlob& key, const struct DlpUsageSpec& spec, const struct DlpBlob& hmacKey)
285 {
286     if (!IsValidCipher(key, spec, hmacKey)) {
287         DLP_LOG_ERROR(LABEL, "dlp file cipher is invalid");
288         return DLP_PARSE_ERROR_VALUE_INVALID;
289     }
290 
291     // copy iv from param.
292     int32_t res = CopyBlobParam(spec.algParam->iv, cipher_.tagIv.iv);
293     if (res != DLP_OK) {
294         DLP_LOG_ERROR(LABEL, "dlp file copy iv param failed, res %{public}d", res);
295         return res;
296     }
297 
298     // copy key from param.
299     res = CopyBlobParam(key, cipher_.encKey);
300     if (res != DLP_OK) {
301         DLP_LOG_ERROR(LABEL, "dlp file copy key param failed, res %{public}d", res);
302         CleanBlobParam(cipher_.tagIv.iv);
303         return res;
304     }
305 
306     // copy hmacKey from param.
307     if (hmacKey.data != nullptr) {
308         res = CopyBlobParam(hmacKey, cipher_.hmacKey);
309         if (res != DLP_OK) {
310             DLP_LOG_ERROR(LABEL, "dlp file copy hmacKey param failed, res %{public}d", res);
311             CleanBlobParam(cipher_.tagIv.iv);
312             CleanBlobParam(cipher_.encKey);
313             return res;
314         }
315     }
316 
317     cipher_.usageSpec.mode = spec.mode;
318     cipher_.usageSpec.algParam = &cipher_.tagIv;
319     return DLP_OK;
320 }
321 
SetContactAccount(const std::string & contactAccount)322 int32_t DlpFile::SetContactAccount(const std::string& contactAccount)
323 {
324     if (contactAccount.size() == 0 || contactAccount.size() > DLP_MAX_CERT_SIZE) {
325         DLP_LOG_ERROR(LABEL, "contactAccount param failed");
326         return DLP_PARSE_ERROR_VALUE_INVALID;
327     }
328     contactAccount_ = contactAccount;
329     if (head_.certSize != 0) {
330         head_.contactAccountSize = static_cast<uint32_t>(contactAccount.size());
331         head_.contactAccountOffset = head_.certOffset + head_.certSize;
332         head_.txtOffset = head_.contactAccountOffset + head_.contactAccountSize;
333     }
334     return DLP_OK;
335 };
336 
SetPolicy(const PermissionPolicy & policy)337 int32_t DlpFile::SetPolicy(const PermissionPolicy& policy)
338 {
339     if (!policy.IsValid()) {
340         DLP_LOG_ERROR(LABEL, "invalid policy");
341         return DLP_PARSE_ERROR_VALUE_INVALID;
342     }
343     if (policy.dlpVersion_ != 0) {
344         head_.version = policy.dlpVersion_;
345     }
346     policy_.CopyPermissionPolicy(policy);
347     UpdateDlpFilePermission();
348     return DLP_OK;
349 };
350 
SetOfflineAccess(bool flag)351 void DlpFile::SetOfflineAccess(bool flag)
352 {
353     head_.offlineAccess = static_cast<uint32_t>(flag);
354 }
355 
GetOfflineAccess()356 bool DlpFile::GetOfflineAccess()
357 {
358     return !!head_.offlineAccess;
359 }
360 
IsValidDlpHeader(const struct DlpHeader & head) const361 bool DlpFile::IsValidDlpHeader(const struct DlpHeader& head) const
362 {
363     if (head.magic != DLP_FILE_MAGIC || head.certSize == 0 || head.certSize > DLP_MAX_CERT_SIZE ||
364         head.contactAccountSize == 0 || head.contactAccountSize > DLP_MAX_CERT_SIZE ||
365         head.certOffset != sizeof(struct DlpHeader) ||
366         head.contactAccountOffset != (sizeof(struct DlpHeader) + head.certSize) ||
367         head.txtOffset != (sizeof(struct DlpHeader) + head.certSize + head.contactAccountSize + head.offlineCertSize) ||
368         head.txtSize > DLP_MAX_CONTENT_SIZE || head.offlineCertSize > DLP_MAX_CERT_SIZE) {
369         DLP_LOG_ERROR(LABEL, "IsValidDlpHeader error");
370         return false;
371     }
372     return true;
373 }
374 
CheckDlpFile()375 int32_t DlpFile::CheckDlpFile()
376 {
377     if (dlpFd_ < 0) {
378         DLP_LOG_ERROR(LABEL, "dlp file fd is invalid");
379         return DLP_PARSE_ERROR_FD_ERROR;
380     }
381 
382     if (isFuseLink_) {
383         DLP_LOG_ERROR(LABEL, "current dlp file is linking, do not operate it.");
384         return DLP_PARSE_ERROR_FILE_LINKING;
385     }
386 
387     if (IsZipFile(dlpFd_)) {
388         return DLP_OK;
389     }
390 
391     if (lseek(dlpFd_, 0, SEEK_SET) == static_cast<off_t>(-1)) {
392         DLP_LOG_ERROR(LABEL, "seek dlp file start failed, %{public}s", strerror(errno));
393         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
394     }
395 
396     if (read(dlpFd_, &head_, sizeof(struct DlpHeader)) != sizeof(struct DlpHeader)) {
397         DLP_LOG_ERROR(LABEL, "can not read dlp file head, %{public}s", strerror(errno));
398         return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
399     }
400 
401     if (!IsValidDlpHeader(head_)) {
402         DLP_LOG_ERROR(LABEL, "parse dlp file header error.");
403         (void)memset_s(&head_, sizeof(struct DlpHeader), 0, sizeof(struct DlpHeader));
404         return DLP_PARSE_ERROR_FILE_NOT_DLP;
405     }
406 
407     if (head_.version > CURRENT_VERSION) {
408         DLP_LOG_ERROR(LABEL, "head_.version > CURRENT_VERSION can not open");
409         (void)memset_s(&head_, sizeof(struct DlpHeader), 0, sizeof(struct DlpHeader));
410         return DLP_PARSE_ERROR_FILE_VERSION_BIGGER_THAN_CURRENT;
411     }
412     return DLP_OK;
413 }
414 
NeedAdapter()415 bool DlpFile::NeedAdapter()
416 {
417     return head_.version == FIRST && CURRENT_VERSION != FIRST;
418 }
419 
IsExistFile(const std::string & path)420 static bool IsExistFile(const std::string& path)
421 {
422     if (path.empty()) {
423         return false;
424     }
425 
426     struct stat buf = {};
427     if (stat(path.c_str(), &buf) != 0) {
428         return false;
429     }
430 
431     return S_ISREG(buf.st_mode);
432 }
433 
GetFileContent(const std::string & path,std::string & content)434 static int32_t GetFileContent(const std::string& path, std::string& content)
435 {
436     if (!IsExistFile(path)) {
437         DLP_LOG_INFO(LABEL, "cannot find file, path = %{public}s", path.c_str());
438         return DLP_RETENTION_FILE_FIND_FILE_ERROR;
439     }
440     std::stringstream buffer;
441     std::ifstream i(path);
442     if (!i.is_open()) {
443         DLP_LOG_INFO(LABEL, "cannot open file %{public}s, errno %{public}d.", path.c_str(), errno);
444         return DLP_RETENTION_COMMON_FILE_OPEN_FAILED;
445     }
446     buffer << i.rdbuf();
447     content = buffer.str();
448     i.close();
449     return DLP_OK;
450 }
451 
ParseDlpInfo()452 bool DlpFile::ParseDlpInfo()
453 {
454     std::string content;
455     (void)GetFileContent(DLP_GENERAL_INFO, content);
456     GenerateInfoParams params;
457     int32_t res = ParseDlpGeneralInfo(content, params);
458     if (res != DLP_OK) {
459         DLP_LOG_ERROR(LABEL, "ParseDlpGeneralInfo %{public}s", content.c_str());
460         return false;
461     }
462     head_.version = params.version;
463     head_.offlineAccess = params.offlineAccessFlag;
464     extraInfo_ = params.extraInfo;
465     contactAccount_ = params.contactAccount;
466     if (!params.hmacVal.empty()) {
467         hmac_.size = params.hmacVal.size() / BYTE_TO_HEX_OPER_LENGTH;
468         if (hmac_.size > HMAC_SIZE) {
469             DLP_LOG_ERROR(LABEL, "hmac_.size is invalid");
470             return false;
471         }
472         CleanBlobParam(hmac_);
473         hmac_.data = new (std::nothrow)uint8_t[hmac_.size];
474         if (hmac_.data == nullptr) {
475             DLP_LOG_ERROR(LABEL, "New memory fail");
476             return false;
477         }
478         return HexStringToByte(params.hmacVal.c_str(), params.hmacVal.length(), hmac_.data, hmac_.size) == DLP_OK;
479     }
480     return true;
481 }
482 
ParseCert()483 bool DlpFile::ParseCert()
484 {
485     struct stat fz;
486     if (stat(DLP_CERT.c_str(), &fz) != 0) {
487         DLP_LOG_ERROR(LABEL, "ParseCert failed, %{public}s", strerror(errno));
488         return false;
489     }
490     CleanBlobParam(cert_);
491     if (fz.st_size == 0 || fz.st_size > DLP_MAX_CERT_SIZE) {
492         DLP_LOG_ERROR(LABEL, "Cert size is too large or equit to 0.");
493         return false;
494     }
495     cert_.data = new (std::nothrow) uint8_t[fz.st_size];
496     if (cert_.data == nullptr) {
497         DLP_LOG_ERROR(LABEL, "new failed");
498         return false;
499     }
500     cert_.size = static_cast<uint32_t>(fz.st_size);
501     int32_t fd = open(DLP_CERT.c_str(), O_RDONLY);
502     if (fd == -1) {
503         DLP_LOG_ERROR(LABEL, "open failed, %{public}s", strerror(errno));
504         return false;
505     }
506 
507     uint32_t size = static_cast<uint32_t>(read(fd, cert_.data, cert_.size));
508     (void)close(fd);
509     fd = -1;
510     if (size != cert_.size) {
511         DLP_LOG_ERROR(LABEL, "read failed, %{public}s", strerror(errno));
512         return false;
513     }
514     return true;
515 }
516 
ParseEncData()517 bool DlpFile::ParseEncData()
518 {
519     int32_t fd = open(DLP_OPENING_ENC_DATA.c_str(), O_RDWR);
520     if (fd == -1) {
521         DLP_LOG_ERROR(LABEL, "ParseEncData failed, %{public}s", strerror(errno));
522         return false;
523     }
524     encDataFd_ = fd;
525     return true;
526 }
527 
CleanTmpFile()528 bool DlpFile::CleanTmpFile()
529 {
530     if (!isZip_) {
531         return true;
532     }
533 
534     close(encDataFd_);
535     encDataFd_ = -1;
536     std::lock_guard<std::mutex> lock(g_fileOpLock_);
537     char cwd[DLP_CWD_MAX] = {0};
538     GETCWD_AND_CHECK(cwd, DLP_CWD_MAX, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
539     Defer p(nullptr, [&](...) {
540         if (chdir(cwd) != 0) {
541             DLP_LOG_ERROR(LABEL, "chdir failed, %{public}s", strerror(errno));
542         }
543     });
544 
545     if (chdir(workDir_.c_str()) != 0) {
546         DLP_LOG_ERROR(LABEL, "chdir failed, %{public}s", strerror(errno));
547         return false;
548     }
549 
550     if (chdir(dirIndex_.c_str()) != 0) {
551         DLP_LOG_ERROR(LABEL, "chdir failed, %{public}s", strerror(errno));
552         return false;
553     }
554 
555     if (unlink(DLP_GENERAL_INFO.c_str()) != 0) {
556         DLP_LOG_ERROR(LABEL, "unlink failed, %{public}s errno %{public}s", DLP_GENERAL_INFO.c_str(), strerror(errno));
557     }
558 
559     if (unlink(DLP_CERT.c_str()) != 0) {
560         DLP_LOG_ERROR(LABEL, "unlink failed, %{public}s errno %{public}s", DLP_CERT.c_str(), strerror(errno));
561     }
562 
563     if (unlink(DLP_OPENING_ENC_DATA.c_str()) != 0) {
564         DLP_LOG_ERROR(LABEL, "unlink failed, %{public}s errno %{public}s",
565             DLP_OPENING_ENC_DATA.c_str(), strerror(errno));
566     }
567 
568     if (chdir(workDir_.c_str()) != 0) {
569         DLP_LOG_ERROR(LABEL, "chdir failed, errno %{public}s", strerror(errno));
570     }
571 
572     if (rmdir(dirIndex_.c_str()) != 0) {
573         DLP_LOG_ERROR(LABEL, "rmdir failed, %{public}s errno %{public}s", dirIndex_.c_str(), strerror(errno));
574         return false;
575     }
576 
577     return true;
578 }
579 
UnzipDlpFile()580 int32_t DlpFile::UnzipDlpFile()
581 {
582     std::lock_guard<std::mutex> lock(g_fileOpLock_);
583     isZip_ = true;
584     head_.txtOffset = 0;
585     char cwd[DLP_CWD_MAX] = {0};
586     GETCWD_AND_CHECK(cwd, DLP_CWD_MAX, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
587     Defer p(nullptr, [&](...) {
588         if (chdir(cwd) != 0) {
589             DLP_LOG_ERROR(LABEL, "chdir failed, %{public}s", strerror(errno));
590         }
591     });
592 
593     CHDIR_AND_CHECK(workDir_.c_str(), DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
594     MKDIR_AND_CHECK(dirIndex_.c_str(), S_IRWXU, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
595     CHDIR_AND_CHECK(dirIndex_.c_str(), DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
596     if (!CheckUnzipFileInfo(dlpFd_)) {
597         return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
598     }
599     UnzipSpecificFile(dlpFd_, DLP_GENERAL_INFO.c_str(), DLP_GENERAL_INFO.c_str());
600     if (!ParseDlpInfo()) {
601         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
602     }
603     UnzipSpecificFile(dlpFd_, DLP_CERT.c_str(), DLP_CERT.c_str());
604     if (!ParseCert()) {
605         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
606     }
607     UnzipSpecificFile(dlpFd_, DLP_ENC_DATA.c_str(), DLP_OPENING_ENC_DATA.c_str());
608     if (!ParseEncData()) {
609         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
610     }
611 
612     return DLP_OK;
613 }
614 
ParseDlpHeaderInRaw()615 int32_t DlpFile::ParseDlpHeaderInRaw()
616 {
617     int32_t ret = CheckDlpFile();
618     if (ret != DLP_OK) {
619         return ret;
620     }
621 
622     // get cert encrypt context
623     uint8_t* buf = new (std::nothrow)uint8_t[head_.certSize];
624     if (buf == nullptr) {
625         DLP_LOG_WARN(LABEL, "alloc buffer failed.");
626         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
627     }
628     if (read(dlpFd_, buf, head_.certSize) != (ssize_t)head_.certSize) {
629         delete[] buf;
630         DLP_LOG_ERROR(LABEL, "can not read dlp file cert, %{public}s", strerror(errno));
631         return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
632     }
633     CleanBlobParam(cert_);
634     cert_.data = buf;
635     cert_.size = head_.certSize;
636 
637     uint8_t *tmpBuf = new (std::nothrow)uint8_t[head_.contactAccountSize];
638     if (tmpBuf == nullptr) {
639         DLP_LOG_WARN(LABEL, "alloc tmpBuf failed.");
640         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
641     }
642 
643     if (read(dlpFd_, tmpBuf, head_.contactAccountSize) != (ssize_t)head_.contactAccountSize) {
644         delete[] tmpBuf;
645         DLP_LOG_ERROR(LABEL, "can not read dlp contact account, %{public}s", strerror(errno));
646         return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
647     }
648 
649     contactAccount_ = std::string(tmpBuf, tmpBuf + head_.contactAccountSize);
650     delete[] tmpBuf;
651 
652     if (head_.offlineCertSize != 0) {
653         tmpBuf = new (std::nothrow)uint8_t[head_.offlineCertSize];
654         if (tmpBuf == nullptr) {
655             DLP_LOG_WARN(LABEL, "alloc tmpBuf failed.");
656             return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
657         }
658 
659         if (read(dlpFd_, tmpBuf, head_.offlineCertSize) != (ssize_t)head_.offlineCertSize) {
660             delete[] tmpBuf;
661             DLP_LOG_ERROR(LABEL, "can not read dlp contact account, %{public}s", strerror(errno));
662             return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
663         }
664         CleanBlobParam(offlineCert_);
665         offlineCert_.data = tmpBuf;
666         offlineCert_.size = head_.offlineCertSize;
667     }
668     return DLP_OK;
669 }
670 
ParseDlpHeader()671 int32_t DlpFile::ParseDlpHeader()
672 {
673     if (IsZipFile(dlpFd_)) {
674         return UnzipDlpFile();
675     } else {
676         return ParseDlpHeaderInRaw();
677     }
678 }
679 
GetEncryptCert(struct DlpBlob & cert) const680 void DlpFile::GetEncryptCert(struct DlpBlob& cert) const
681 {
682     cert.data = cert_.data;
683     cert.size = cert_.size;
684 }
685 
GetOfflineCert(struct DlpBlob & cert) const686 void DlpFile::GetOfflineCert(struct DlpBlob& cert) const
687 {
688     cert.data = offlineCert_.data;
689     cert.size = offlineCert_.size;
690 }
691 
SetEncryptCert(const struct DlpBlob & cert)692 int32_t DlpFile::SetEncryptCert(const struct DlpBlob& cert)
693 {
694     if (cert.data == nullptr || cert.size > DLP_MAX_CERT_SIZE) {
695         DLP_LOG_ERROR(LABEL, "Cert data invalid");
696         return DLP_PARSE_ERROR_VALUE_INVALID;
697     }
698 
699     if (cert_.data != nullptr) {
700         delete[] cert_.data;
701         cert_.data = nullptr;
702     }
703 
704     if (CopyBlobParam(cert, cert_) != DLP_OK) {
705         DLP_LOG_ERROR(LABEL, "Cert copy failed");
706         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
707     }
708 
709     head_.certOffset = sizeof(struct DlpHeader);
710     head_.certSize = cert_.size;
711     head_.txtOffset = sizeof(struct DlpHeader) + cert_.size;
712     return DLP_OK;
713 }
714 
UpdateFile(int32_t tmpFile,const std::vector<uint8_t> & cert,uint32_t oldTxtOffset)715 int32_t DlpFile::UpdateFile(int32_t tmpFile, const std::vector<uint8_t>& cert, uint32_t oldTxtOffset)
716 {
717     if (WriteHeadAndCert(tmpFile, cert) != DLP_OK) {
718         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
719     }
720     (void)lseek(dlpFd_, oldTxtOffset, SEEK_SET);
721     int32_t ret = DoDlpContentCopyOperation(dlpFd_, tmpFile, 0, head_.txtSize);
722     if (ret != DLP_OK) {
723         return ret;
724     }
725     int32_t fileSize = lseek(tmpFile, 0, SEEK_CUR);
726     (void)lseek(tmpFile, 0, SEEK_SET);
727     (void)lseek(dlpFd_, 0, SEEK_SET);
728     ret = DoDlpContentCopyOperation(tmpFile, dlpFd_, 0, fileSize);
729     if (ret != DLP_OK) {
730         return ret;
731     }
732 
733     FTRUNCATE_AND_CHECK(dlpFd_, fileSize, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
734     (void)fsync(dlpFd_);
735     return DLP_OK;
736 }
737 
GetTempFile(const std::string & workDir,int32_t & tempFile,std::string & path)738 int32_t DlpFile::GetTempFile(const std::string& workDir, int32_t& tempFile, std::string& path)
739 {
740     static uint32_t count = 0;
741     char realPath[PATH_MAX] = {0};
742     if ((realpath(workDir.c_str(), realPath) == nullptr) && (errno != ENOENT)) {
743         DLP_LOG_ERROR(LABEL, "realpath, %{public}s, workDir %{private}s", strerror(errno), workDir.c_str());
744         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
745     }
746     std::string rPath(realPath);
747     path = rPath + "/dlp" + std::to_string(count++) + ".txt";
748     tempFile = open(path.c_str(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
749     if (tempFile < 0) {
750         DLP_LOG_ERROR(LABEL, "open file fail, %{public}s, realPath %{private}s", strerror(errno), path.c_str());
751         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
752     }
753     return DLP_OK;
754 }
755 
UpdateCertAndText(const std::vector<uint8_t> & cert,const std::string & workDir,struct DlpBlob certBlob)756 int32_t DlpFile::UpdateCertAndText(const std::vector<uint8_t>& cert, const std::string& workDir,
757     struct DlpBlob certBlob)
758 {
759     if (CopyBlobParam(certBlob, cert_) != DLP_OK) {
760         DLP_LOG_ERROR(LABEL, "Cert copy failed");
761         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
762     }
763 
764     if (isZip_) {
765         return GenFileInZip(-1);
766     }
767 
768     int32_t tmpFile;
769     std::string path;
770     int32_t res = GetTempFile(workDir, tmpFile, path);
771     if (res != DLP_OK) {
772         return res;
773     }
774     Defer p(nullptr, [&](...) {
775         (void)close(tmpFile);
776         (void)unlink(path.c_str());
777     });
778 
779     head_.certSize = cert.size();
780     uint32_t oldTxtOffset = head_.txtOffset;
781     head_.contactAccountOffset = head_.certOffset + head_.certSize;
782     head_.txtOffset = head_.contactAccountOffset + head_.contactAccountSize;
783 
784     // version 1 single file auto convert to version 2 zip file, set version
785     head_.version = SECOND;
786     head_.offlineCertSize = 0;
787 
788     return UpdateFile(tmpFile, cert, oldTxtOffset);
789 }
790 
UpdateCert(struct DlpBlob certBlob)791 int32_t DlpFile::UpdateCert(struct DlpBlob certBlob)
792 {
793     DLP_LOG_DEBUG(LABEL, "enter");
794 
795     if (CopyBlobParam(certBlob, cert_) != DLP_OK) {
796         DLP_LOG_ERROR(LABEL, "Cert copy failed");
797         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
798     }
799 
800     if (isZip_) {
801         return GenFileInZip(-1);
802     }
803 
804     if (write(dlpFd_, cert_.data, head_.certSize) != (ssize_t)head_.certSize) {
805         DLP_LOG_ERROR(LABEL, "write dlp cert data failed, %{public}s", strerror(errno));
806         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
807     }
808     return DLP_OK;
809 }
810 
WriteHeadAndCert(int32_t tmpFile,const std::vector<uint8_t> & cert)811 int32_t DlpFile::WriteHeadAndCert(int32_t tmpFile, const std::vector<uint8_t>& cert)
812 {
813     if (write(tmpFile, &head_, sizeof(struct DlpHeader)) != sizeof(struct DlpHeader)) {
814         DLP_LOG_ERROR(LABEL, "write dlp head failed, %{public}s", strerror(errno));
815         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
816     }
817     if (write(tmpFile, cert_.data, head_.certSize) != (ssize_t)head_.certSize) {
818         DLP_LOG_ERROR(LABEL, "write dlp cert data failed, %{public}s", strerror(errno));
819         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
820     }
821     if (write(tmpFile, contactAccount_.c_str(), contactAccount_.size()) !=
822         static_cast<int32_t>(contactAccount_.size())) {
823         DLP_LOG_ERROR(LABEL, "write dlp contact data failed, %{public}s", strerror(errno));
824         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
825     }
826     return DLP_OK;
827 }
828 
PrepareBuff(struct DlpBlob & message1,struct DlpBlob & message2) const829 int32_t DlpFile::PrepareBuff(struct DlpBlob& message1, struct DlpBlob& message2) const
830 {
831     message1.size = DLP_BUFF_LEN;
832     message1.data = new (std::nothrow) uint8_t[DLP_BUFF_LEN];
833     if (message1.data == nullptr) {
834         DLP_LOG_ERROR(LABEL, "message1.data null");
835         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
836     }
837 
838     message2.size = DLP_BUFF_LEN;
839     message2.data = new (std::nothrow) uint8_t[DLP_BUFF_LEN];
840     if (message2.data == nullptr) {
841         DLP_LOG_ERROR(LABEL, "message2.data null");
842         delete[] message1.data;
843         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
844     }
845 
846     (void)memset_s(message1.data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
847     (void)memset_s(message2.data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
848     return DLP_OK;
849 }
850 
DupUsageSpec(struct DlpUsageSpec & spec)851 int32_t DlpFile::DupUsageSpec(struct DlpUsageSpec& spec)
852 {
853     if (cipher_.usageSpec.algParam == nullptr ||
854         cipher_.usageSpec.algParam->iv.data == nullptr ||
855         cipher_.usageSpec.algParam->iv.size != IV_SIZE) {
856         DLP_LOG_ERROR(LABEL, "chipher_ is invalid");
857         return DLP_PARSE_ERROR_VALUE_INVALID;
858     }
859     spec.mode = cipher_.usageSpec.mode;
860     spec.algParam = new (std::nothrow) struct DlpCipherParam;
861     if (spec.algParam == nullptr) {
862         DLP_LOG_ERROR(LABEL, "new alg param failed");
863         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
864     }
865     spec.algParam->iv.data = new (std::nothrow) uint8_t[IV_SIZE]();
866     if (spec.algParam->iv.data == nullptr) {
867         delete spec.algParam;
868         DLP_LOG_ERROR(LABEL, "new iv failed");
869         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
870     }
871     spec.algParam->iv.size = cipher_.usageSpec.algParam->iv.size;
872     if (memcpy_s(spec.algParam->iv.data, IV_SIZE,
873         cipher_.usageSpec.algParam->iv.data, cipher_.usageSpec.algParam->iv.size) != EOK) {
874         delete[] spec.algParam->iv.data;
875         delete spec.algParam;
876         DLP_LOG_ERROR(LABEL, "copy iv failed");
877         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
878     }
879     return DLP_OK;
880 }
881 
DoDlpBlockCryptOperation(struct DlpBlob & message1,struct DlpBlob & message2,uint32_t offset,bool isEncrypt)882 int32_t DlpFile::DoDlpBlockCryptOperation(struct DlpBlob& message1, struct DlpBlob& message2,
883     uint32_t offset, bool isEncrypt)
884 {
885     if (offset % DLP_BLOCK_SIZE != 0 || message1.data == nullptr || message1.size == 0
886         ||  message2.data == nullptr || message2.size == 0) {
887         DLP_LOG_ERROR(LABEL, "params is error");
888         return DLP_PARSE_ERROR_VALUE_INVALID;
889     }
890 
891     uint32_t counterIndex = offset / DLP_BLOCK_SIZE;
892     struct DlpUsageSpec spec;
893     if (DupUsageSpec(spec) != DLP_OK) {
894         DLP_LOG_ERROR(LABEL, "spec dup failed");
895         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
896     }
897 
898     DlpCtrModeIncreaeIvCounter(spec.algParam->iv, counterIndex);
899     int32_t ret = isEncrypt ? DlpOpensslAesEncrypt(&cipher_.encKey, &spec, &message1, &message2) :
900         DlpOpensslAesDecrypt(&cipher_.encKey, &spec, &message1, &message2);
901     delete[] spec.algParam->iv.data;
902     delete spec.algParam;
903     if (ret != 0) {
904         DLP_LOG_ERROR(LABEL, "do block crypt fail");
905         return DLP_PARSE_ERROR_CRYPT_FAIL;
906     }
907     return DLP_OK;
908 }
909 
DoDlpContentCryptyOperation(int32_t inFd,int32_t outFd,uint32_t inOffset,uint32_t inFileLen,bool isEncrypt)910 int32_t DlpFile::DoDlpContentCryptyOperation(int32_t inFd, int32_t outFd, uint32_t inOffset,
911     uint32_t inFileLen, bool isEncrypt)
912 {
913     struct DlpBlob message, outMessage;
914     if (PrepareBuff(message, outMessage) != DLP_OK) {
915         DLP_LOG_ERROR(LABEL, "prepare buff failed");
916         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
917     }
918 
919     uint32_t dlpContentOffset = inOffset;
920     int32_t ret = DLP_OK;
921     while (inOffset < inFileLen) {
922         uint32_t readLen = ((inFileLen - inOffset) < DLP_BUFF_LEN) ? (inFileLen - inOffset) : DLP_BUFF_LEN;
923         (void)memset_s(message.data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
924         (void)memset_s(outMessage.data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
925         if (read(inFd, message.data, readLen) != (ssize_t)readLen) {
926             DLP_LOG_ERROR(LABEL, "Read size do not equal readLen");
927             ret = DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
928             break;
929         }
930 
931         message.size = readLen;
932         outMessage.size = readLen;
933         // Implicit condition: DLP_BUFF_LEN must be DLP_BLOCK_SIZE aligned
934         ret = DoDlpBlockCryptOperation(message, outMessage, inOffset - dlpContentOffset, isEncrypt);
935         if (ret != DLP_OK) {
936             DLP_LOG_ERROR(LABEL, "do crypt operation fail");
937             break;
938         }
939 
940         if (write(outFd, outMessage.data, readLen) != (ssize_t)readLen) {
941             DLP_LOG_ERROR(LABEL, "write fd failed, %{public}s", strerror(errno));
942             ret = DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
943             break;
944         }
945         inOffset += readLen;
946     }
947 
948     delete[] message.data;
949     delete[] outMessage.data;
950     return ret;
951 }
952 
DoDlpContentCopyOperation(int32_t inFd,int32_t outFd,uint32_t inOffset,uint32_t inFileLen)953 int32_t DlpFile::DoDlpContentCopyOperation(int32_t inFd, int32_t outFd, uint32_t inOffset, uint32_t inFileLen)
954 {
955     if (inOffset > inFileLen) {
956         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
957     }
958     uint8_t *data = new (std::nothrow) uint8_t[DLP_BUFF_LEN];
959     if (data == nullptr) {
960         DLP_LOG_ERROR(LABEL, "prepare buff failed");
961         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
962     }
963 
964     int32_t ret = DLP_OK;
965     while (inOffset < inFileLen) {
966         uint32_t readLen = ((inFileLen - inOffset) < DLP_BUFF_LEN) ? (inFileLen - inOffset) : DLP_BUFF_LEN;
967         (void)memset_s(data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
968 
969         if (read(inFd, data, readLen) != (ssize_t)readLen) {
970             DLP_LOG_ERROR(LABEL, "Read size do not equal readLen");
971             ret = DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
972             break;
973         }
974 
975         if (write(outFd, data, readLen) != (ssize_t)readLen) {
976             DLP_LOG_ERROR(LABEL, "write fd failed, %{public}s", strerror(errno));
977             ret = DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
978             break;
979         }
980         inOffset += readLen;
981     }
982     delete[] data;
983     return ret;
984 }
985 
GetFileSize(int32_t fd)986 static int32_t GetFileSize(int32_t fd)
987 {
988     int32_t fileLen = lseek(fd, 0, SEEK_END);
989     (void)lseek(fd, 0, SEEK_SET);
990     return fileLen;
991 }
992 
SetDlpGeneralInfo(bool accessFlag,std::string & contactAccount,const std::string & hmacStr,const uint32_t & version,std::string & out)993 static void SetDlpGeneralInfo(bool accessFlag, std::string& contactAccount, const std::string& hmacStr,
994     const uint32_t& version, std::string& out)
995 {
996     GenerateInfoParams params = {
997         .version = version,
998         .offlineAccessFlag = accessFlag,
999         .contactAccount = contactAccount,
1000         .extraInfo = {"kia_info", "cert_info", "enc_data"},
1001         .hmacVal = hmacStr,
1002     };
1003     GenerateDlpGeneralInfo(params, out);
1004 }
1005 
GenEncData(int32_t inPlainFileFd)1006 int32_t DlpFile::GenEncData(int32_t inPlainFileFd)
1007 {
1008     int32_t encFile = -1;
1009     if (inPlainFileFd == -1) {
1010         encFile = open(DLP_OPENING_ENC_DATA.c_str(), O_RDWR);
1011     } else {
1012         int32_t fileLen = GetFileSize(inPlainFileFd);
1013         OPEN_AND_CHECK(encFile, DLP_OPENING_ENC_DATA.c_str(), O_RDWR | O_CREAT | O_TRUNC,
1014             S_IRUSR | S_IWUSR, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1015         encDataFd_ = encFile;
1016         int32_t ret = DoDlpContentCryptyOperation(inPlainFileFd, encFile, 0, fileLen, true);
1017         CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1018         LSEEK_AND_CHECK(encFile, 0, SEEK_SET, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1019     }
1020     return encFile;
1021 }
1022 
GenerateHmacVal(int32_t encFile,struct DlpBlob & out)1023 int32_t DlpFile::GenerateHmacVal(int32_t encFile, struct DlpBlob& out)
1024 {
1025     lseek(encFile, 0, SEEK_SET);
1026     int32_t fd = dup(encFile);
1027     int32_t fileLen = GetFileSize(fd);
1028     if (fileLen == 0) {
1029         (void)close(fd);
1030         CleanBlobParam(out);
1031         return DLP_OK;
1032     } else if (fileLen < 0) {
1033         (void)close(fd);
1034         DLP_LOG_ERROR(LABEL, "fileLen less than 0");
1035         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1036     }
1037 
1038     int ret = DlpHmacEncode(cipher_.hmacKey, fd, out);
1039     (void)close(fd);
1040     return ret;
1041 }
1042 
GetHmacVal(int32_t encFile,std::string & hmacStr)1043 int32_t DlpFile::GetHmacVal(int32_t encFile, std::string& hmacStr)
1044 {
1045     if (head_.version < HMAC_VERSION) {
1046         return DLP_OK;
1047     }
1048     if (hmac_.size == 0) {
1049         uint8_t* outBuf = new (std::nothrow) uint8_t[HMAC_SIZE];
1050         if (outBuf == nullptr) {
1051             DLP_LOG_ERROR(LABEL, "New memory fail");
1052             return DLP_SERVICE_ERROR_MEMORY_OPERATE_FAIL;
1053         }
1054         struct DlpBlob out = {
1055             .size = HMAC_SIZE,
1056             .data = outBuf,
1057         };
1058         int ret = GenerateHmacVal(encFile, out);
1059         if (ret != DLP_OK) {
1060             CleanBlobParam(out);
1061             return ret;
1062         }
1063         if (out.size == 0) {
1064             return DLP_OK;
1065         }
1066         hmac_.size = out.size;
1067         hmac_.data = out.data;
1068     }
1069     uint32_t hmacHexLen = hmac_.size * BYTE_TO_HEX_OPER_LENGTH + 1;
1070     char* hmacHex = new (std::nothrow) char[hmacHexLen];
1071     if (hmacHex == nullptr) {
1072         DLP_LOG_ERROR(LABEL, "New memory fail");
1073         return DLP_SERVICE_ERROR_MEMORY_OPERATE_FAIL;
1074     }
1075     int ret = ByteToHexString(hmac_.data, hmac_.size, hmacHex, hmacHexLen);
1076     if (ret != DLP_OK) {
1077         DLP_LOG_ERROR(LABEL, "Byte to hexstring fail");
1078         FreeCharBuffer(hmacHex, hmacHexLen);
1079         return ret;
1080     }
1081     hmacStr = hmacHex;
1082     FreeCharBuffer(hmacHex, hmacHexLen);
1083     return DLP_OK;
1084 }
1085 
AddGeneralInfoToBuff(int32_t encFile)1086 int32_t DlpFile::AddGeneralInfoToBuff(int32_t encFile)
1087 {
1088     std::string hmacStr;
1089     int ret = GetHmacVal(encFile, hmacStr);
1090     if (ret != DLP_OK) {
1091         DLP_LOG_ERROR(LABEL, "GetHmacVal fail");
1092         return ret;
1093     }
1094     std::string ja;
1095     SetDlpGeneralInfo(head_.offlineAccess, contactAccount_, hmacStr, head_.version, ja);
1096     ret = AddBuffToZip(reinterpret_cast<const void *>(ja.c_str()), ja.size(),
1097         DLP_GENERAL_INFO.c_str(), DLP_GEN_FILE.c_str());
1098     CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1099     return DLP_OK;
1100 }
1101 
GenFileInZip(int32_t inPlainFileFd)1102 int32_t DlpFile::GenFileInZip(int32_t inPlainFileFd)
1103 {
1104     if (isZip_ == false) {
1105         return DLP_OK;
1106     }
1107     char cwd[DLP_CWD_MAX] = {0};
1108     std::lock_guard<std::mutex> lock(g_fileOpLock_);
1109     GETCWD_AND_CHECK(cwd, DLP_CWD_MAX, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1110     Defer p(nullptr, [&](...) {
1111         (void)chdir(cwd);
1112     });
1113     CHDIR_AND_CHECK(workDir_.c_str(), DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1114     if (inPlainFileFd != -1) {
1115         MKDIR_AND_CHECK(dirIndex_.c_str(), S_IRWXU, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1116     }
1117     CHDIR_AND_CHECK(dirIndex_.c_str(), DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1118 
1119     int32_t tmpFile;
1120     OPEN_AND_CHECK(tmpFile, DLP_GEN_FILE.c_str(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR,
1121         DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1122     Defer p2(nullptr, [&](...) {
1123         (void)close(tmpFile);
1124         (void)unlink(DLP_GEN_FILE.c_str());
1125     });
1126     int32_t ret = AddBuffToZip(reinterpret_cast<const void *>(cert_.data), cert_.size,
1127         DLP_CERT.c_str(), DLP_GEN_FILE.c_str());
1128     CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1129 
1130     int32_t encFile = GenEncData(inPlainFileFd);
1131     Defer p3(nullptr, [&](...) {
1132         if (inPlainFileFd == -1) {
1133             (void)close(encFile);
1134         }
1135     });
1136 
1137     ret = AddFileContextToZip(encFile, DLP_ENC_DATA.c_str(), DLP_GEN_FILE.c_str());
1138     CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1139     ret = AddGeneralInfoToBuff(encFile);
1140     CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1141 
1142     int32_t zipSize = GetFileSize(tmpFile);
1143     LSEEK_AND_CHECK(dlpFd_, 0, SEEK_SET, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1144     ret = DoDlpContentCopyOperation(tmpFile, dlpFd_, 0, zipSize);
1145     CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1146 
1147     FTRUNCATE_AND_CHECK(dlpFd_, zipSize, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1148 
1149     (void)fsync(dlpFd_);
1150     return DLP_OK;
1151 }
1152 
GenFileInRaw(int32_t inPlainFileFd)1153 int32_t DlpFile::GenFileInRaw(int32_t inPlainFileFd)
1154 {
1155     off_t fileLen = lseek(inPlainFileFd, 0, SEEK_END);
1156     if (fileLen == static_cast<off_t>(-1) || fileLen > static_cast<off_t>(DLP_MAX_CONTENT_SIZE)) {
1157         DLP_LOG_ERROR(LABEL, "inFd len is invalid, %{public}s", strerror(errno));
1158         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1159     }
1160     head_.txtSize = static_cast<uint32_t>(fileLen);
1161     DLP_LOG_DEBUG(LABEL, "fileLen %{private}u", head_.txtSize);
1162 
1163     // clean dlpFile
1164     if (ftruncate(dlpFd_, 0) == -1) {
1165         DLP_LOG_ERROR(LABEL, "truncate dlp file to zero failed, %{public}s", strerror(errno));
1166         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1167     }
1168 
1169     if (lseek(inPlainFileFd, 0, SEEK_SET) == static_cast<off_t>(-1)) {
1170         DLP_LOG_ERROR(LABEL, "seek plain file start failed, %{public}s", strerror(errno));
1171         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1172     }
1173 
1174     if (lseek(dlpFd_, 0, SEEK_SET) == static_cast<off_t>(-1)) {
1175         DLP_LOG_ERROR(LABEL, "seek dlp file start failed, %{public}s", strerror(errno));
1176         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1177     }
1178 
1179     if (write(dlpFd_, &head_, sizeof(struct DlpHeader)) != sizeof(struct DlpHeader)) {
1180         DLP_LOG_ERROR(LABEL, "write dlp head failed, %{public}s", strerror(errno));
1181         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1182     }
1183 
1184     if (write(dlpFd_, cert_.data, head_.certSize) != (ssize_t)head_.certSize) {
1185         DLP_LOG_ERROR(LABEL, "write dlp cert data failed, %{public}s", strerror(errno));
1186         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1187     }
1188 
1189     if (write(dlpFd_, contactAccount_.c_str(), contactAccount_.size()) !=
1190         static_cast<int32_t>(contactAccount_.size())) {
1191         DLP_LOG_ERROR(LABEL, "write dlp contact data failed, %{public}s", strerror(errno));
1192         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1193     }
1194 
1195     if (fileLen == 0) {
1196         DLP_LOG_INFO(LABEL, "Plaintext file len is 0, do not need encrypt");
1197         return DLP_OK;
1198     }
1199     return DoDlpContentCryptyOperation(inPlainFileFd, dlpFd_, 0, fileLen, true);
1200 }
1201 
GenFile(int32_t inPlainFileFd)1202 int32_t DlpFile::GenFile(int32_t inPlainFileFd)
1203 {
1204     if (inPlainFileFd < 0 || dlpFd_ < 0 || !IsValidCipher(cipher_.encKey, cipher_.usageSpec, cipher_.hmacKey)) {
1205         DLP_LOG_ERROR(LABEL, "params is error");
1206         return DLP_PARSE_ERROR_VALUE_INVALID;
1207     }
1208     if (isZip_) {
1209         head_.txtOffset = 0;
1210         if (hmac_.size != 0) {
1211             CleanBlobParam(hmac_);
1212         }
1213         return GenFileInZip(inPlainFileFd);
1214     } else {
1215         return GenFileInRaw(inPlainFileFd);
1216     }
1217 }
1218 
RemoveDlpPermissionInZip(int32_t outPlainFileFd)1219 int32_t DlpFile::RemoveDlpPermissionInZip(int32_t outPlainFileFd)
1220 {
1221     std::lock_guard<std::mutex> lock(g_fileOpLock_);
1222     char cwd[DLP_CWD_MAX] = {0};
1223     GETCWD_AND_CHECK(cwd, DLP_CWD_MAX, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1224     Defer p(nullptr, [&](...) {
1225         if (chdir(cwd) != 0) {
1226             DLP_LOG_ERROR(LABEL, "chdir failed, %{public}s", strerror(errno));
1227         }
1228     });
1229 
1230     CHDIR_AND_CHECK(workDir_.c_str(), DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1231     CHDIR_AND_CHECK(dirIndex_.c_str(), DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1232 
1233     int32_t encFd = open(DLP_OPENING_ENC_DATA.c_str(), O_RDWR, S_IRUSR | S_IWUSR);
1234     Defer p2(nullptr, [&](...) {
1235         if (close(encFd) != 0) {
1236             DLP_LOG_ERROR(LABEL, "close failed, %{public}s", strerror(errno));
1237         }
1238     });
1239 
1240     int32_t fileSize = GetFileSize(encFd);
1241     int32_t ret = DoDlpContentCryptyOperation(encFd, outPlainFileFd, 0, fileSize, false);
1242     CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1243 
1244     return DLP_OK;
1245 }
1246 
RemoveDlpPermissionInRaw(int32_t outPlainFileFd)1247 int32_t DlpFile::RemoveDlpPermissionInRaw(int32_t outPlainFileFd)
1248 {
1249     off_t fileLen = lseek(dlpFd_, 0, SEEK_END);
1250     if (fileLen == static_cast<off_t>(-1) || fileLen > static_cast<off_t>(DLP_MAX_CONTENT_SIZE)) {
1251         DLP_LOG_ERROR(LABEL, "can not get dlp file len, %{public}s", strerror(errno));
1252         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1253     }
1254 
1255     // clean plainTxtFile
1256     if (ftruncate(outPlainFileFd, 0) == -1) {
1257         DLP_LOG_ERROR(LABEL, "truncate plain file to zero failed, %{public}s", strerror(errno));
1258         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1259     }
1260 
1261     if (lseek(outPlainFileFd, 0, SEEK_SET) == static_cast<off_t>(-1)) {
1262         DLP_LOG_ERROR(LABEL, "seek plain file start failed, %{public}s", strerror(errno));
1263         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1264     }
1265 
1266     if (lseek(dlpFd_, head_.txtOffset, SEEK_SET) == static_cast<off_t>(-1)) {
1267         DLP_LOG_ERROR(LABEL, "seek dlp file start failed, %{public}s", strerror(errno));
1268         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1269     }
1270 
1271     if (fileLen == head_.txtOffset) {
1272         DLP_LOG_INFO(LABEL, "Dlp file have no content");
1273         return DLP_OK;
1274     }
1275 
1276     return DoDlpContentCryptyOperation(dlpFd_, outPlainFileFd, head_.txtOffset, fileLen, false);
1277 }
1278 
RemoveDlpPermission(int32_t outPlainFileFd)1279 int32_t DlpFile::RemoveDlpPermission(int32_t outPlainFileFd)
1280 {
1281     if (isFuseLink_) {
1282         DLP_LOG_ERROR(LABEL, "current dlp file is linking, do not operate it.");
1283         return DLP_PARSE_ERROR_FILE_LINKING;
1284     }
1285 
1286     if (authPerm_ != FULL_CONTROL) {
1287         DLP_LOG_ERROR(LABEL, "check permission fail, remove dlp permission failed.");
1288         return DLP_PARSE_ERROR_FILE_READ_ONLY;
1289     }
1290 
1291     if (outPlainFileFd < 0 || dlpFd_ < 0) {
1292         DLP_LOG_ERROR(LABEL, "fd is invalid");
1293         return DLP_PARSE_ERROR_FD_ERROR;
1294     }
1295 
1296     if (!IsValidCipher(cipher_.encKey, cipher_.usageSpec, cipher_.hmacKey)) {
1297         DLP_LOG_ERROR(LABEL, "cipher params is invalid");
1298         return DLP_PARSE_ERROR_CIPHER_PARAMS_INVALID;
1299     }
1300 
1301     if (isZip_) {
1302         return RemoveDlpPermissionInZip(outPlainFileFd);
1303     } else {
1304         return RemoveDlpPermissionInRaw(outPlainFileFd);
1305     }
1306 }
1307 
DlpFileRead(uint32_t offset,void * buf,uint32_t size,bool & hasRead,int32_t uid)1308 int32_t DlpFile::DlpFileRead(uint32_t offset, void* buf, uint32_t size, bool& hasRead, int32_t uid)
1309 {
1310     int32_t opFd = isZip_ ? encDataFd_ : dlpFd_;
1311     if (buf == nullptr || size == 0 || size > DLP_FUSE_MAX_BUFFLEN ||
1312         (offset >= DLP_MAX_CONTENT_SIZE - size) ||
1313         opFd < 0 || !IsValidCipher(cipher_.encKey, cipher_.usageSpec, cipher_.hmacKey)) {
1314         DLP_LOG_ERROR(LABEL, "params is error");
1315         return DLP_PARSE_ERROR_VALUE_INVALID;
1316     }
1317 
1318     uint32_t alignOffset = (offset / DLP_BLOCK_SIZE) * DLP_BLOCK_SIZE;
1319     uint32_t prefixingSize = offset - alignOffset;
1320     uint32_t alignSize = size + prefixingSize;
1321 
1322     if (lseek(opFd, head_.txtOffset + alignOffset, SEEK_SET) == -1) {
1323         DLP_LOG_ERROR(LABEL, "lseek dlp file failed. %{public}s", strerror(errno));
1324         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1325     }
1326 
1327     auto encBuff = std::make_unique<uint8_t[]>(alignSize);
1328     auto outBuff = std::make_unique<uint8_t[]>(alignSize);
1329 
1330     int32_t readLen = read(opFd, encBuff.get(), alignSize);
1331     if (readLen == -1) {
1332         DLP_LOG_ERROR(LABEL, "read buff fail, %{public}s", strerror(errno));
1333         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1334     }
1335     if (readLen <= static_cast<int32_t>(prefixingSize)) {
1336         return 0;
1337     }
1338 
1339     struct DlpBlob message1 = {.size = readLen, .data = encBuff.get()};
1340     struct DlpBlob message2 = {.size = readLen, .data = outBuff.get()};
1341     if (DoDlpBlockCryptOperation(message1, message2, alignOffset, false) != DLP_OK) {
1342         DLP_LOG_ERROR(LABEL, "decrypt fail");
1343         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1344     }
1345 
1346     if (memcpy_s(buf, size, outBuff.get() + prefixingSize, message2.size - prefixingSize) != EOK) {
1347         DLP_LOG_ERROR(LABEL, "copy decrypt result failed");
1348         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
1349     }
1350     if (hasRead) {
1351         return message2.size - prefixingSize;
1352     }
1353     int32_t res = DlpPermissionKit::SetReadFlag(uid);
1354     if (res != DLP_OK) {
1355         return res;
1356     }
1357     hasRead = true;
1358     return message2.size - prefixingSize;
1359 }
1360 
WriteFirstBlockData(uint32_t offset,void * buf,uint32_t size)1361 int32_t DlpFile::WriteFirstBlockData(uint32_t offset, void* buf, uint32_t size)
1362 {
1363     uint32_t alignOffset = (offset / DLP_BLOCK_SIZE) * DLP_BLOCK_SIZE;
1364     uint32_t prefixingSize = offset % DLP_BLOCK_SIZE;
1365     uint32_t requestSize = (size < (DLP_BLOCK_SIZE - prefixingSize)) ? size : (DLP_BLOCK_SIZE - prefixingSize);
1366     uint32_t writtenSize = prefixingSize + requestSize;
1367     uint8_t enBuf[DLP_BLOCK_SIZE] = {0};
1368     uint8_t deBuf[DLP_BLOCK_SIZE] = {0};
1369     int32_t opFd = isZip_ ? encDataFd_ : dlpFd_;
1370 
1371     do {
1372         if (prefixingSize == 0) {
1373             break;
1374         }
1375         int32_t readLen = read(opFd, enBuf, prefixingSize);
1376         if (readLen == -1) {
1377             DLP_LOG_ERROR(LABEL, "read first block prefixing fail, %{public}s", strerror(errno));
1378             return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1379         }
1380         if (readLen == 0) {
1381             break;
1382         }
1383 
1384         struct DlpBlob message1 = {.size = prefixingSize, .data = enBuf};
1385         struct DlpBlob message2 = {.size = prefixingSize, .data = deBuf};
1386         if (DoDlpBlockCryptOperation(message1, message2, alignOffset, false) != DLP_OK) {
1387             DLP_LOG_ERROR(LABEL, "decrypt appending bytes fail, %{public}s", strerror(errno));
1388             return DLP_PARSE_ERROR_CRYPT_FAIL;
1389         }
1390     } while (false);
1391 
1392     if (memcpy_s(deBuf + prefixingSize, DLP_BLOCK_SIZE - prefixingSize, buf, requestSize) != EOK) {
1393         DLP_LOG_ERROR(LABEL, "copy write buffer first block failed, %{public}s", strerror(errno));
1394         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
1395     }
1396 
1397     struct DlpBlob message1 = {.size = writtenSize, .data = deBuf};
1398     struct DlpBlob message2 = {.size = writtenSize, .data = enBuf};
1399     if (DoDlpBlockCryptOperation(message1, message2, alignOffset, true) != DLP_OK) {
1400         DLP_LOG_ERROR(LABEL, "enrypt first block fail");
1401         return DLP_PARSE_ERROR_CRYPT_FAIL;
1402     }
1403 
1404     if (lseek(opFd, head_.txtOffset + alignOffset, SEEK_SET) == static_cast<off_t>(-1)) {
1405         DLP_LOG_ERROR(LABEL, "lseek failed, %{public}s", strerror(errno));
1406         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1407     }
1408 
1409     if (write(opFd, enBuf, writtenSize) != (ssize_t)writtenSize) {
1410         DLP_LOG_ERROR(LABEL, "write failed, %{public}s", strerror(errno));
1411         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1412     }
1413     return requestSize;
1414 }
1415 
DoDlpFileWrite(uint32_t offset,void * buf,uint32_t size)1416 int32_t DlpFile::DoDlpFileWrite(uint32_t offset, void* buf, uint32_t size)
1417 {
1418     int32_t opFd = isZip_ ? encDataFd_ : dlpFd_;
1419     uint32_t alignOffset = (offset / DLP_BLOCK_SIZE * DLP_BLOCK_SIZE);
1420     if (lseek(opFd, head_.txtOffset + alignOffset, SEEK_SET) == static_cast<off_t>(-1)) {
1421         DLP_LOG_ERROR(LABEL, "lseek dlp file offset %{public}d failed, %{public}s",
1422             head_.txtOffset + offset, strerror(errno));
1423         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1424     }
1425 
1426     /* write first block data, if it may be not aligned */
1427     int32_t writenSize = WriteFirstBlockData(offset, static_cast<uint8_t *>(buf), size);
1428     if (writenSize < 0) {
1429         DLP_LOG_ERROR(LABEL, "encrypt prefix data failed");
1430         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1431     }
1432     if (static_cast<uint32_t>(writenSize) >= size) {
1433         return writenSize;
1434     }
1435 
1436     uint8_t *restBlocksPtr = static_cast<uint8_t *>(buf) + writenSize;
1437     uint32_t restBlocksSize = size - static_cast<uint32_t>(writenSize);
1438     uint8_t* writeBuff = new (std::nothrow) uint8_t[restBlocksSize]();
1439     if (writeBuff == nullptr) {
1440         DLP_LOG_ERROR(LABEL, "alloc write buffer fail");
1441         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
1442     }
1443 
1444     /* first aligned block has been writen, write the rest */
1445     struct DlpBlob message1 = {.size = restBlocksSize, .data = restBlocksPtr};
1446     struct DlpBlob message2 = {.size = restBlocksSize, .data = writeBuff};
1447 
1448     int32_t ret = DoDlpBlockCryptOperation(message1, message2, alignOffset + DLP_BLOCK_SIZE, true);
1449     if (ret != DLP_OK) {
1450         DLP_LOG_ERROR(LABEL, "encrypt write buffer fail");
1451         delete[] writeBuff;
1452         return ret;
1453     }
1454 
1455     ret = write(opFd, writeBuff, restBlocksSize);
1456     delete[] writeBuff;
1457     if (ret <= 0) {
1458         DLP_LOG_ERROR(LABEL, "write buff failed, %{public}s", strerror(errno));
1459         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1460     }
1461 
1462     return ret + static_cast<int32_t>(writenSize);
1463 }
1464 
GetFsContentSize() const1465 uint32_t DlpFile::GetFsContentSize() const
1466 {
1467     struct stat fileStat;
1468     int32_t opFd = isZip_ ? encDataFd_ : dlpFd_;
1469     int32_t ret = fstat(opFd, &fileStat);
1470     if (ret != 0) {
1471         DLP_LOG_ERROR(LABEL, "fstat error %{public}d , errno %{public}d dlpfd: %{public}d ", ret, errno, opFd);
1472         return INVALID_FILE_SIZE;
1473     }
1474     if (head_.txtOffset > fileStat.st_size || fileStat.st_size >= static_cast<off_t>(INVALID_FILE_SIZE)) {
1475         DLP_LOG_ERROR(LABEL, "size error %{public}d %{public}d", head_.txtOffset,
1476             static_cast<uint32_t>(fileStat.st_size));
1477         return INVALID_FILE_SIZE;
1478     }
1479     if (static_cast<uint32_t>(fileStat.st_size) - head_.txtOffset == 0) {
1480         DLP_LOG_ERROR(LABEL, "linkFile size %{public}d %{public}d", static_cast<uint32_t>(fileStat.st_size),
1481             head_.txtOffset);
1482     }
1483     return static_cast<uint32_t>(fileStat.st_size) - head_.txtOffset;
1484 }
1485 
UpdateDlpFileContentSize()1486 int32_t DlpFile::UpdateDlpFileContentSize()
1487 {
1488     uint32_t contentSize = GetFsContentSize();
1489     if (contentSize == INVALID_FILE_SIZE) {
1490         DLP_LOG_ERROR(LABEL, "get fs content size failed");
1491         return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
1492     }
1493     head_.txtSize = contentSize;
1494     DLP_LOG_DEBUG(LABEL, "Update dlp file content size");
1495 
1496     if (isZip_ == false) {
1497         if (lseek(dlpFd_, 0, SEEK_SET) == static_cast<off_t>(-1)) {
1498             DLP_LOG_ERROR(LABEL, "Lseek failed, %{public}s", strerror(errno));
1499             return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1500         }
1501 
1502         if (write(dlpFd_, &head_, sizeof(head_)) != sizeof(head_)) {
1503             DLP_LOG_ERROR(LABEL, "Write failed, %{public}s", strerror(errno));
1504             return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1505         }
1506     }
1507 
1508     return DLP_OK;
1509 }
1510 
FillHoleData(uint32_t holeStart,uint32_t holeSize)1511 int32_t DlpFile::FillHoleData(uint32_t holeStart, uint32_t holeSize)
1512 {
1513     DLP_LOG_INFO(LABEL, "Need create a hole filled with 0s, hole start %{public}x size %{public}x",
1514         holeStart, holeSize);
1515     uint32_t holeBufSize = (holeSize < HOLE_BUFF_SMALL_SIZE) ? HOLE_BUFF_SMALL_SIZE : HOLE_BUFF_SIZE;
1516     std::unique_ptr<uint8_t[]> holeBuff(new (std::nothrow) uint8_t[holeBufSize]());
1517     if (holeBuff == nullptr) {
1518         DLP_LOG_ERROR(LABEL, "New buf failed.");
1519         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
1520     }
1521 
1522     uint32_t fillLen = 0;
1523     while (fillLen < holeSize) {
1524         uint32_t writeSize = ((holeSize - fillLen) < holeBufSize) ? (holeSize - fillLen) : holeBufSize;
1525         int32_t res = DoDlpFileWrite(holeStart + fillLen, holeBuff.get(), writeSize);
1526         if (res < 0) {
1527             DLP_LOG_ERROR(LABEL, "Write failed, error %{public}d.", res);
1528             return res;
1529         }
1530         fillLen += writeSize;
1531     }
1532     return DLP_OK;
1533 }
1534 
DlpFileWrite(uint32_t offset,void * buf,uint32_t size)1535 int32_t DlpFile::DlpFileWrite(uint32_t offset, void* buf, uint32_t size)
1536 {
1537     if (authPerm_ == READ_ONLY) {
1538         DLP_LOG_ERROR(LABEL, "Dlp file is readonly, write failed");
1539         return DLP_PARSE_ERROR_FILE_READ_ONLY;
1540     }
1541     int32_t opFd = isZip_ ? encDataFd_ : dlpFd_;
1542     if (buf == nullptr || size == 0 || size > DLP_FUSE_MAX_BUFFLEN ||
1543         (offset >= DLP_MAX_CONTENT_SIZE - size) ||
1544         opFd < 0 || !IsValidCipher(cipher_.encKey, cipher_.usageSpec, cipher_.hmacKey)) {
1545         DLP_LOG_ERROR(LABEL, "Dlp file param invalid");
1546         return DLP_PARSE_ERROR_VALUE_INVALID;
1547     }
1548 
1549     uint32_t curSize = GetFsContentSize();
1550     if (curSize != INVALID_FILE_SIZE && curSize < offset &&
1551         (FillHoleData(curSize, offset - curSize) != DLP_OK)) {
1552         DLP_LOG_ERROR(LABEL, "Fill hole data failed");
1553         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1554     }
1555     int32_t res = DoDlpFileWrite(offset, buf, size);
1556     UpdateDlpFileContentSize();
1557 
1558     // modify dlp file, clear old hmac value and will generate new
1559     if (hmac_.size != 0) {
1560         CleanBlobParam(hmac_);
1561     }
1562     GenFileInZip(-1);
1563     return res;
1564 }
1565 
Truncate(uint32_t size)1566 int32_t DlpFile::Truncate(uint32_t size)
1567 {
1568     DLP_LOG_INFO(LABEL, "Truncate file size %{public}u", size);
1569 
1570     if (authPerm_ == READ_ONLY) {
1571         DLP_LOG_ERROR(LABEL, "Dlp file is readonly, truncate failed");
1572         return DLP_PARSE_ERROR_FILE_READ_ONLY;
1573     }
1574     int32_t opFd = isZip_ ? encDataFd_ : dlpFd_;
1575     if (opFd < 0 || size >= DLP_MAX_CONTENT_SIZE) {
1576         DLP_LOG_ERROR(LABEL, "Param invalid");
1577         return DLP_PARSE_ERROR_VALUE_INVALID;
1578     }
1579 
1580     uint32_t curSize = GetFsContentSize();
1581     int32_t res = DLP_OK;
1582     if (size < curSize) {
1583         res = ftruncate(opFd, head_.txtOffset + size);
1584         UpdateDlpFileContentSize();
1585         GenFileInZip(-1);
1586     } else if (size > curSize) {
1587         res = FillHoleData(curSize, size - curSize);
1588         UpdateDlpFileContentSize();
1589         GenFileInZip(-1);
1590     } else {
1591         DLP_LOG_INFO(LABEL, "Truncate file size equals origin file");
1592     }
1593 
1594     if (res != DLP_OK) {
1595         DLP_LOG_ERROR(LABEL, "Truncate file size %{public}u failed, %{public}s", size, strerror(errno));
1596         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1597     }
1598     return DLP_OK;
1599 }
1600 
HmacCheck()1601 int32_t DlpFile::HmacCheck()
1602 {
1603     DLP_LOG_DEBUG(LABEL, "start HmacCheck, dlpVersion = %{public}d", head_.version);
1604     if (head_.version < HMAC_VERSION) {
1605         DLP_LOG_INFO(LABEL, "no hmac check");
1606         return DLP_OK;
1607     }
1608 
1609     uint8_t* outBuf = new (std::nothrow) uint8_t[HMAC_SIZE];
1610     if (outBuf == nullptr) {
1611         DLP_LOG_ERROR(LABEL, "New memory fail");
1612         return DLP_SERVICE_ERROR_MEMORY_OPERATE_FAIL;
1613     }
1614     struct DlpBlob out = {
1615         .size = HMAC_SIZE,
1616         .data = outBuf,
1617     };
1618     int ret = GenerateHmacVal(encDataFd_, out);
1619     if (ret != DLP_OK) {
1620         CleanBlobParam(out);
1621         return ret;
1622     }
1623 
1624     if (out.size == 0 || (out.size == hmac_.size && memcmp(hmac_.data, out.data, out.size) == 0)) {
1625         DLP_LOG_INFO(LABEL, "verify success");
1626         if (out.size != 0) {
1627             CleanBlobParam(out);
1628         }
1629         return DLP_OK;
1630     }
1631     DLP_LOG_ERROR(LABEL, "verify fail");
1632     CleanBlobParam(out);
1633     return DLP_PARSE_ERROR_FILE_VERIFICATION_FAIL;
1634 }
1635 }  // namespace DlpPermission
1636 }  // namespace Security
1637 }  // namespace OHOS
1638