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