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