• 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 <sys/stat.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include "dlp_permission.h"
25 #include "dlp_permission_log.h"
26 #include "ohos_account_kits.h"
27 #ifdef DLP_PARSE_INNER
28 #include "os_account_manager.h"
29 #endif // DLP_PARSE_INNER
30 #include "securec.h"
31 
32 namespace OHOS {
33 namespace Security {
34 namespace DlpPermission {
35 using Defer = std::shared_ptr<void>;
36 namespace {
37 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION, "DlpFile"};
38 const uint32_t CURRENT_VERSION = 1;
39 } // namespace
40 
DlpFile(int32_t dlpFd)41 DlpFile::DlpFile(int32_t dlpFd) : dlpFd_(dlpFd), isFuseLink_(false), authPerm_(READ_ONLY)
42 {
43     head_.magic = DLP_FILE_MAGIC;
44     head_.version = 1;
45     head_.offlineAccess = 0;
46     head_.txtOffset = INVALID_FILE_SIZE;
47     head_.txtSize = INVALID_FILE_SIZE;
48     head_.certOffset = sizeof(struct DlpHeader);
49     head_.certSize = 0;
50     head_.contactAccountOffset = 0;
51     head_.contactAccountSize = 0;
52     head_.offlineCertOffset = 0;
53     head_.offlineCertSize = 0;
54 
55     cert_.data = nullptr;
56     cert_.size = 0;
57 
58     offlineCert_.data = nullptr;
59     offlineCert_.size = 0;
60 
61     cipher_.tagIv.iv.data = nullptr;
62     cipher_.tagIv.iv.size = 0;
63     cipher_.encKey.data = nullptr;
64     cipher_.encKey.size = 0;
65     cipher_.usageSpec = { 0 };
66 }
67 
~DlpFile()68 DlpFile::~DlpFile()
69 {
70     // clear key
71     if (cipher_.encKey.data != nullptr) {
72         (void)memset_s(cipher_.encKey.data, cipher_.encKey.size, 0, cipher_.encKey.size);
73         delete[] cipher_.encKey.data;
74         cipher_.encKey.data = nullptr;
75     }
76 
77     // clear iv
78     if (cipher_.tagIv.iv.data != nullptr) {
79         (void)memset_s(cipher_.tagIv.iv.data, cipher_.tagIv.iv.size, 0, cipher_.tagIv.iv.size);
80         delete[] cipher_.tagIv.iv.data;
81         cipher_.tagIv.iv.data = nullptr;
82     }
83 
84     // clear encrypt cert
85     if (cert_.data != nullptr) {
86         (void)memset_s(cert_.data, head_.certSize, 0, head_.certSize);
87         delete[] cert_.data;
88         cert_.data = nullptr;
89     }
90 
91     if (offlineCert_.data != nullptr) {
92         (void)memset_s(offlineCert_.data, head_.offlineCertSize, 0, head_.offlineCertSize);
93         delete[] offlineCert_.data;
94         offlineCert_.data = nullptr;
95     }
96 }
97 
IsValidCipher(const struct DlpBlob & key,const struct DlpUsageSpec & spec) const98 bool DlpFile::IsValidCipher(const struct DlpBlob& key, const struct DlpUsageSpec& spec) const
99 {
100     if (key.data == nullptr) {
101         DLP_LOG_ERROR(LABEL, "key data null");
102         return false;
103     }
104 
105     if (key.size != DLP_KEY_LEN_128 && key.size != DLP_KEY_LEN_192 && key.size != DLP_KEY_LEN_256) {
106         DLP_LOG_ERROR(LABEL, "key size invalid");
107         return false;
108     }
109 
110     if (spec.mode != DLP_MODE_CTR || spec.algParam == nullptr) {
111         DLP_LOG_ERROR(LABEL, "spec invalid");
112         return false;
113     }
114 
115     struct DlpBlob& iv = spec.algParam->iv;
116     if (iv.size != IV_SIZE || iv.data == nullptr) {
117         DLP_LOG_ERROR(LABEL, "iv invalid");
118         return false;
119     }
120     return true;
121 }
122 
CopyBlobParam(const struct DlpBlob & src,struct DlpBlob & dst) const123 int32_t DlpFile::CopyBlobParam(const struct DlpBlob& src, struct DlpBlob& dst) const
124 {
125     if (src.data == nullptr || src.size == 0 || src.size > DLP_MAX_CERT_SIZE) {
126         DLP_LOG_ERROR(LABEL, "src data null");
127         return DLP_PARSE_ERROR_VALUE_INVALID;
128     }
129 
130     uint8_t* blobData = new (std::nothrow)uint8_t[src.size];
131     if (blobData == nullptr) {
132         DLP_LOG_ERROR(LABEL, "blobData null");
133         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
134     }
135 
136     if (memcpy_s(blobData, src.size, src.data, src.size) != EOK) {
137         DLP_LOG_ERROR(LABEL, "memcpy_s error");
138         delete[] blobData;
139         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
140     }
141 
142     dst.data = blobData;
143     dst.size = src.size;
144     return DLP_OK;
145 }
146 
CleanBlobParam(struct DlpBlob & blob) const147 int32_t DlpFile::CleanBlobParam(struct DlpBlob& blob) const
148 {
149     if (blob.data == nullptr || blob.size == 0) {
150         DLP_LOG_ERROR(LABEL, "blobData null");
151         return DLP_PARSE_ERROR_VALUE_INVALID;
152     }
153 
154     (void)memset_s(blob.data, blob.size, 0, blob.size);
155     delete[] blob.data;
156     blob.data = nullptr;
157     blob.size = 0;
158     return DLP_OK;
159 }
160 
GetLocalAccountName(std::string & account) const161 int32_t DlpFile::GetLocalAccountName(std::string& account) const
162 {
163     std::pair<bool, AccountSA::OhosAccountInfo> accountInfo =
164         AccountSA::OhosAccountKits::GetInstance().QueryOhosAccountInfo();
165     if (accountInfo.first) {
166         account = accountInfo.second.name_;
167         return DLP_OK;
168     }
169     DLP_LOG_ERROR(LABEL, "QueryOhosAccountInfo accountInfo error");
170     return DLP_PARSE_ERROR_ACCOUNT_INVALID;
171 }
172 
GetDomainAccountName(std::string & account) const173 int32_t DlpFile::GetDomainAccountName(std::string& account) const
174 {
175 #ifdef DLP_PARSE_INNER
176     std::vector<int32_t> ids;
177     if (OHOS::AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids) != 0) {
178         DLP_LOG_ERROR(LABEL, "QueryActiveOsAccountIds return not 0");
179         return DLP_PARSE_ERROR_ACCOUNT_INVALID;
180     }
181     if (ids.size() != 1) {
182         DLP_LOG_ERROR(LABEL, "QueryActiveOsAccountIds size not 1");
183         return DLP_PARSE_ERROR_ACCOUNT_INVALID;
184     }
185     int32_t userId = ids[0];
186     AccountSA::OsAccountInfo osAccountInfo;
187     if (OHOS::AccountSA::OsAccountManager::QueryOsAccountById(userId, osAccountInfo) != 0) {
188         DLP_LOG_ERROR(LABEL, "GetOsAccountLocalIdFromDomain return not 0");
189         return DLP_PARSE_ERROR_ACCOUNT_INVALID;
190     }
191     AccountSA::DomainAccountInfo domainInfo;
192     osAccountInfo.GetDomainInfo(domainInfo);
193     if (domainInfo.accountName_.empty()) {
194         DLP_LOG_ERROR(LABEL, "accountName_ empty");
195         return DLP_PARSE_ERROR_ACCOUNT_INVALID;
196     }
197     account = domainInfo.accountName_;
198 #endif
199     return DLP_OK;
200 }
201 
UpdateDlpFilePermission()202 void DlpFile::UpdateDlpFilePermission()
203 {
204     std::string accountName;
205     if (policy_.ownerAccountType_ == DOMAIN_ACCOUNT) {
206         if (GetDomainAccountName(accountName) != DLP_OK) {
207             DLP_LOG_ERROR(LABEL, "query GetDomainAccountName failed");
208             return;
209         }
210     } else {
211         if (GetLocalAccountName(accountName) != DLP_OK) {
212             DLP_LOG_ERROR(LABEL, "query GetLocalAccountName failed");
213             return;
214         }
215     }
216 
217     DLP_LOG_DEBUG(LABEL, "current account Name %{private}s", accountName.c_str());
218 
219     if (accountName == policy_.ownerAccount_) {
220         DLP_LOG_DEBUG(LABEL, "current account is owner, it has full permission");
221         authPerm_ = FULL_CONTROL;
222         return;
223     }
224 
225     if (policy_.supportEveryone_) {
226         DLP_LOG_DEBUG(LABEL, "everyone has perm permission %{public}d", policy_.everyonePerm_);
227         authPerm_ = policy_.everyonePerm_;
228     } else {
229         DLP_LOG_DEBUG(LABEL, "everyone has not perm permission %{public}d", policy_.everyonePerm_);
230     }
231 
232     for (int32_t i = 0; i < static_cast<int32_t>(policy_.authUsers_.size()); i++) {
233         if (accountName == policy_.authUsers_[i].authAccount) {
234             authPerm_ = policy_.authUsers_[i].authPerm;
235             DLP_LOG_DEBUG(LABEL, "current account match authUsers list, authPerm_ %{public}d",
236                 authPerm_);
237         }
238     }
239 }
240 
SetCipher(const struct DlpBlob & key,const struct DlpUsageSpec & spec)241 int32_t DlpFile::SetCipher(const struct DlpBlob& key, const struct DlpUsageSpec& spec)
242 {
243     if (!IsValidCipher(key, spec)) {
244         DLP_LOG_ERROR(LABEL, "dlp file cipher is invalid");
245         return DLP_PARSE_ERROR_VALUE_INVALID;
246     }
247 
248     // copy iv from param.
249     int32_t res = CopyBlobParam(spec.algParam->iv, cipher_.tagIv.iv);
250     if (res != DLP_OK) {
251         DLP_LOG_ERROR(LABEL, "dlp file copy iv param failed, res %{public}d", res);
252         return res;
253     }
254 
255     // copy key from param.
256     res = CopyBlobParam(key, cipher_.encKey);
257     if (res != DLP_OK) {
258         DLP_LOG_ERROR(LABEL, "dlp file copy key param failed, res %{public}d", res);
259         CleanBlobParam(cipher_.tagIv.iv);
260         return res;
261     }
262 
263     cipher_.usageSpec.mode = spec.mode;
264     cipher_.usageSpec.algParam = &cipher_.tagIv;
265     return DLP_OK;
266 }
267 
SetContactAccount(const std::string & contactAccount)268 int32_t DlpFile::SetContactAccount(const std::string& contactAccount)
269 {
270     if (contactAccount.size() == 0 || contactAccount.size() > DLP_MAX_CERT_SIZE) {
271         DLP_LOG_ERROR(LABEL, "contactAccount param failed");
272         return DLP_PARSE_ERROR_VALUE_INVALID;
273     }
274     contactAccount_ = contactAccount;
275     if (head_.certSize != 0) {
276         head_.contactAccountSize = static_cast<uint32_t>(contactAccount.size());
277         head_.contactAccountOffset = head_.certOffset + head_.certSize;
278         head_.txtOffset = head_.contactAccountOffset + head_.contactAccountSize;
279     }
280     return DLP_OK;
281 };
282 
SetPolicy(const PermissionPolicy & policy)283 int32_t DlpFile::SetPolicy(const PermissionPolicy& policy)
284 {
285     if (!policy.IsValid()) {
286         DLP_LOG_ERROR(LABEL, "invalid policy");
287         return DLP_PARSE_ERROR_VALUE_INVALID;
288     }
289     policy_.CopyPermissionPolicy(policy);
290     UpdateDlpFilePermission();
291     return DLP_OK;
292 };
293 
SetOfflineAccess(bool flag)294 void DlpFile::SetOfflineAccess(bool flag)
295 {
296     head_.offlineAccess = static_cast<uint32_t>(flag);
297 }
298 
GetOfflineAccess()299 bool DlpFile::GetOfflineAccess()
300 {
301     return !!head_.offlineAccess;
302 }
303 
IsValidDlpHeader(const struct DlpHeader & head) const304 bool DlpFile::IsValidDlpHeader(const struct DlpHeader& head) const
305 {
306     if (head.magic != DLP_FILE_MAGIC || head.certSize == 0 || head.certSize > DLP_MAX_CERT_SIZE ||
307         head.contactAccountSize == 0 || head.contactAccountSize > DLP_MAX_CERT_SIZE ||
308         head.certOffset != sizeof(struct DlpHeader) ||
309         head.contactAccountOffset != (sizeof(struct DlpHeader) + head.certSize) ||
310         head.txtOffset != (sizeof(struct DlpHeader) + head.certSize + head.contactAccountSize + head.offlineCertSize) ||
311         head.txtSize > DLP_MAX_CONTENT_SIZE || head.offlineCertSize > DLP_MAX_CERT_SIZE) {
312         DLP_LOG_ERROR(LABEL, "IsValidDlpHeader error");
313         return false;
314     }
315     return true;
316 }
317 
CheckDlpFile()318 int32_t DlpFile::CheckDlpFile()
319 {
320     if (dlpFd_ < 0) {
321         DLP_LOG_ERROR(LABEL, "dlp file fd is invalid");
322         return DLP_PARSE_ERROR_FD_ERROR;
323     }
324 
325     if (isFuseLink_) {
326         DLP_LOG_ERROR(LABEL, "current dlp file is linking, do not operate it.");
327         return DLP_PARSE_ERROR_FILE_LINKING;
328     }
329 
330     if (lseek(dlpFd_, 0, SEEK_SET) == static_cast<off_t>(-1)) {
331         DLP_LOG_ERROR(LABEL, "seek dlp file start failed, %{public}s", strerror(errno));
332         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
333     }
334 
335     if (read(dlpFd_, &head_, sizeof(struct DlpHeader)) != sizeof(struct DlpHeader)) {
336         DLP_LOG_ERROR(LABEL, "can not read dlp file head, %{public}s", strerror(errno));
337         return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
338     }
339 
340     if (!IsValidDlpHeader(head_)) {
341         DLP_LOG_ERROR(LABEL, "parse dlp file header error.");
342         (void)memset_s(&head_, sizeof(struct DlpHeader), 0, sizeof(struct DlpHeader));
343         return DLP_PARSE_ERROR_FILE_NOT_DLP;
344     }
345 
346     if (head_.version > CURRENT_VERSION) {
347         DLP_LOG_ERROR(LABEL, "head_.version > CURRENT_VERSION can not open");
348         (void)memset_s(&head_, sizeof(struct DlpHeader), 0, sizeof(struct DlpHeader));
349         return DLP_PARSE_ERROR_FILE_VERSION_BIGGER_THAN_CURRENT;
350     }
351     return DLP_OK;
352 }
353 
ParseDlpHeader()354 int32_t DlpFile::ParseDlpHeader()
355 {
356     int ret = CheckDlpFile();
357     if (ret != DLP_OK) {
358         return ret;
359     }
360 
361     // get cert encrypt context
362     uint8_t* buf = new (std::nothrow)uint8_t[head_.certSize];
363     if (buf == nullptr) {
364         DLP_LOG_WARN(LABEL, "alloc buffer failed.");
365         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
366     }
367     if (read(dlpFd_, buf, head_.certSize) != (ssize_t)head_.certSize) {
368         delete[] buf;
369         DLP_LOG_ERROR(LABEL, "can not read dlp file cert, %{public}s", strerror(errno));
370         return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
371     }
372     cert_.data = buf;
373     cert_.size = head_.certSize;
374 
375     uint8_t *tmpBuf = new (std::nothrow)uint8_t[head_.contactAccountSize];
376     if (tmpBuf == nullptr) {
377         DLP_LOG_WARN(LABEL, "alloc tmpBuf failed.");
378         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
379     }
380 
381     if (read(dlpFd_, tmpBuf, head_.contactAccountSize) != (ssize_t)head_.contactAccountSize) {
382         delete[] tmpBuf;
383         DLP_LOG_ERROR(LABEL, "can not read dlp contact account, %{public}s", strerror(errno));
384         return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
385     }
386 
387     contactAccount_ = std::string(tmpBuf, tmpBuf + head_.contactAccountSize);
388     delete[] tmpBuf;
389 
390     if (head_.offlineCertSize != 0) {
391         tmpBuf = new (std::nothrow)uint8_t[head_.offlineCertSize];
392         if (tmpBuf == nullptr) {
393             DLP_LOG_WARN(LABEL, "alloc tmpBuf failed.");
394             return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
395         }
396 
397         if (read(dlpFd_, tmpBuf, head_.offlineCertSize) != (ssize_t)head_.offlineCertSize) {
398             delete[] tmpBuf;
399             DLP_LOG_ERROR(LABEL, "can not read dlp contact account, %{public}s", strerror(errno));
400             return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
401         }
402         offlineCert_.data = tmpBuf;
403         offlineCert_.size = head_.offlineCertSize;
404     }
405 
406     return DLP_OK;
407 }
408 
GetEncryptCert(struct DlpBlob & cert) const409 void DlpFile::GetEncryptCert(struct DlpBlob& cert) const
410 {
411     cert.data = cert_.data;
412     cert.size = cert_.size;
413 }
414 
GetOfflineCert(struct DlpBlob & cert) const415 void DlpFile::GetOfflineCert(struct DlpBlob& cert) const
416 {
417     cert.data = offlineCert_.data;
418     cert.size = offlineCert_.size;
419 }
420 
SetEncryptCert(const struct DlpBlob & cert)421 int32_t DlpFile::SetEncryptCert(const struct DlpBlob& cert)
422 {
423     if (cert.data == nullptr || cert.size > DLP_MAX_CERT_SIZE) {
424         DLP_LOG_ERROR(LABEL, "Cert data invalid");
425         return DLP_PARSE_ERROR_VALUE_INVALID;
426     }
427 
428     if (cert_.data != nullptr) {
429         delete[] cert_.data;
430         cert_.data = nullptr;
431     }
432 
433     if (CopyBlobParam(cert, cert_) != DLP_OK) {
434         DLP_LOG_ERROR(LABEL, "Cert copy failed");
435         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
436     }
437 
438     head_.certOffset = sizeof(struct DlpHeader);
439     head_.certSize = cert_.size;
440     head_.txtOffset = sizeof(struct DlpHeader) + cert_.size;
441     return DLP_OK;
442 }
443 
AddOfflineCert(std::vector<uint8_t> & offlineCert,const std::string & workDir)444 int32_t DlpFile::AddOfflineCert(std::vector<uint8_t>& offlineCert, const std::string& workDir)
445 {
446     static uint32_t count = 0;
447 
448     char realPath[PATH_MAX] = {0};
449     if ((realpath(workDir.c_str(), realPath) == nullptr) && (errno != ENOENT)) {
450         DLP_LOG_ERROR(LABEL, "realpath, %{public}s, workDir %{private}s", strerror(errno), workDir.c_str());
451         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
452     }
453     std::string rPath(realPath);
454     std::string path = rPath + "/dlp" + std::to_string(count++) + ".txt";
455     int tmpFile = open(path.c_str(), O_RDWR | O_CREAT | O_TRUNC, S_IRWXU);
456     if (tmpFile < 0) {
457         DLP_LOG_ERROR(LABEL, "open file fail, %{public}s, realPath %{private}s", strerror(errno), path.c_str());
458         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
459     }
460 
461     Defer p(nullptr, [&](...) {
462         (void)close(tmpFile);
463         (void)unlink(path.c_str());
464     });
465 
466     head_.offlineCertOffset = head_.contactAccountOffset + head_.contactAccountSize;
467     head_.offlineCertSize = offlineCert.size();
468 
469     uint32_t oldTxtOffset = head_.txtOffset;
470     head_.txtOffset = head_.offlineCertOffset + head_.offlineCertSize;
471     if (WriteHeadAndCert(tmpFile, offlineCert) != DLP_OK) {
472         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
473     }
474     (void)lseek(dlpFd_, oldTxtOffset, SEEK_SET);
475     int32_t ret = DoDlpContentCopyOperation(dlpFd_, tmpFile, 0, head_.txtSize);
476     if (ret != DLP_OK) {
477         return ret;
478     }
479     int fileSize = lseek(tmpFile, 0, SEEK_CUR);
480     (void)lseek(tmpFile, 0, SEEK_SET);
481     (void)lseek(dlpFd_, 0, SEEK_SET);
482     ret = DoDlpContentCopyOperation(tmpFile, dlpFd_, 0, fileSize);
483     if (ret != DLP_OK) {
484         return ret;
485     }
486     if (ftruncate(dlpFd_, fileSize) == -1) {
487         DLP_LOG_ERROR(LABEL, "truncate plain file to zero failed, %{public}s", strerror(errno));
488         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
489     }
490     (void)fsync(dlpFd_);
491     return DLP_OK;
492 }
493 
WriteHeadAndCert(int tmpFile,std::vector<uint8_t> & offlineCert)494 int32_t DlpFile::WriteHeadAndCert(int tmpFile, std::vector<uint8_t>& offlineCert)
495 {
496     if (write(tmpFile, &head_, sizeof(struct DlpHeader)) != sizeof(struct DlpHeader)) {
497         DLP_LOG_ERROR(LABEL, "write dlp head failed, %{public}s", strerror(errno));
498         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
499     }
500     if (write(tmpFile, cert_.data, head_.certSize) != (ssize_t)head_.certSize) {
501         DLP_LOG_ERROR(LABEL, "write dlp cert data failed, %{public}s", strerror(errno));
502         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
503     }
504     if (write(tmpFile, contactAccount_.c_str(), contactAccount_.size()) !=
505         static_cast<int32_t>(contactAccount_.size())) {
506         DLP_LOG_ERROR(LABEL, "write dlp contact data failed, %{public}s", strerror(errno));
507         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
508     }
509     if (write(tmpFile, &offlineCert[0], offlineCert.size()) !=
510         static_cast<int32_t>(offlineCert.size())) {
511         DLP_LOG_ERROR(LABEL, "write offlineCert data failed, %{public}s", strerror(errno));
512         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
513     }
514     return DLP_OK;
515 }
516 
PrepareBuff(struct DlpBlob & message1,struct DlpBlob & message2) const517 int32_t DlpFile::PrepareBuff(struct DlpBlob& message1, struct DlpBlob& message2) const
518 {
519     message1.size = DLP_BUFF_LEN;
520     message1.data = new (std::nothrow) uint8_t[DLP_BUFF_LEN];
521     if (message1.data == nullptr) {
522         DLP_LOG_ERROR(LABEL, "message1.data null");
523         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
524     }
525 
526     message2.size = DLP_BUFF_LEN;
527     message2.data = new (std::nothrow) uint8_t[DLP_BUFF_LEN];
528     if (message2.data == nullptr) {
529         DLP_LOG_ERROR(LABEL, "message2.data null");
530         delete[] message1.data;
531         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
532     }
533 
534     (void)memset_s(message1.data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
535     (void)memset_s(message2.data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
536     return DLP_OK;
537 }
538 
DupUsageSpec(struct DlpUsageSpec & spec)539 int32_t DlpFile::DupUsageSpec(struct DlpUsageSpec& spec)
540 {
541     if (cipher_.usageSpec.algParam == nullptr ||
542         cipher_.usageSpec.algParam->iv.data == nullptr ||
543         cipher_.usageSpec.algParam->iv.size != IV_SIZE) {
544         DLP_LOG_ERROR(LABEL, "chipher_ is invalid");
545         return DLP_PARSE_ERROR_VALUE_INVALID;
546     }
547     spec.mode = cipher_.usageSpec.mode;
548     spec.algParam = new (std::nothrow) struct DlpCipherParam;
549     if (spec.algParam == nullptr) {
550         DLP_LOG_ERROR(LABEL, "new alg param failed");
551         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
552     }
553     spec.algParam->iv.data = new (std::nothrow) uint8_t[IV_SIZE]();
554     if (spec.algParam->iv.data == nullptr) {
555         delete spec.algParam;
556         DLP_LOG_ERROR(LABEL, "new iv failed");
557         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
558     }
559     spec.algParam->iv.size = cipher_.usageSpec.algParam->iv.size;
560     if (memcpy_s(spec.algParam->iv.data, IV_SIZE,
561         cipher_.usageSpec.algParam->iv.data, cipher_.usageSpec.algParam->iv.size) != EOK) {
562         delete[] spec.algParam->iv.data;
563         delete spec.algParam;
564         DLP_LOG_ERROR(LABEL, "copy iv failed");
565         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
566     }
567     return DLP_OK;
568 }
569 
DoDlpBlockCryptOperation(struct DlpBlob & message1,struct DlpBlob & message2,uint32_t offset,bool isEncrypt)570 int32_t DlpFile::DoDlpBlockCryptOperation(struct DlpBlob& message1, struct DlpBlob& message2,
571     uint32_t offset, bool isEncrypt)
572 {
573     if (offset % DLP_BLOCK_SIZE != 0 || message1.data == nullptr || message1.size == 0
574         ||  message2.data == nullptr || message2.size == 0) {
575         DLP_LOG_ERROR(LABEL, "params is error");
576         return DLP_PARSE_ERROR_VALUE_INVALID;
577     }
578 
579     uint32_t counterIndex = offset / DLP_BLOCK_SIZE;
580     struct DlpUsageSpec spec;
581     if (DupUsageSpec(spec) != DLP_OK) {
582         DLP_LOG_ERROR(LABEL, "spec dup failed");
583         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
584     }
585 
586     DlpCtrModeIncreaeIvCounter(spec.algParam->iv, counterIndex);
587     int32_t ret = isEncrypt ? DlpOpensslAesEncrypt(&cipher_.encKey, &spec, &message1, &message2) :
588         DlpOpensslAesDecrypt(&cipher_.encKey, &spec, &message1, &message2);
589     delete[] spec.algParam->iv.data;
590     delete spec.algParam;
591     if (ret != 0) {
592         DLP_LOG_ERROR(LABEL, "do block crypt fail");
593         return DLP_PARSE_ERROR_CRYPT_FAIL;
594     }
595     return DLP_OK;
596 }
597 
DoDlpContentCryptyOperation(int32_t inFd,int32_t outFd,uint32_t inOffset,uint32_t inFileLen,bool isEncrypt)598 int32_t DlpFile::DoDlpContentCryptyOperation(int32_t inFd, int32_t outFd, uint32_t inOffset,
599     uint32_t inFileLen, bool isEncrypt)
600 {
601     struct DlpBlob message, outMessage;
602     if (PrepareBuff(message, outMessage) != DLP_OK) {
603         DLP_LOG_ERROR(LABEL, "prepare buff failed");
604         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
605     }
606 
607     uint32_t dlpContentOffset = inOffset;
608     int32_t ret = DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
609     while (inOffset < inFileLen) {
610         uint32_t readLen = ((inFileLen - inOffset) < DLP_BUFF_LEN) ? (inFileLen - inOffset) : DLP_BUFF_LEN;
611         (void)memset_s(message.data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
612         (void)memset_s(outMessage.data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
613         if (read(inFd, message.data, readLen) != (ssize_t)readLen) {
614             DLP_LOG_ERROR(LABEL, "Read size do not equal readLen");
615             ret = DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
616             break;
617         }
618 
619         message.size = readLen;
620         outMessage.size = readLen;
621         // Implicit condition: DLP_BUFF_LEN must be DLP_BLOCK_SIZE aligned
622         ret = DoDlpBlockCryptOperation(message, outMessage, inOffset - dlpContentOffset, isEncrypt);
623         if (ret != DLP_OK) {
624             DLP_LOG_ERROR(LABEL, "do crypt operation fail");
625             break;
626         }
627 
628         if (write(outFd, outMessage.data, readLen) != (ssize_t)readLen) {
629             DLP_LOG_ERROR(LABEL, "write fd failed, %{public}s", strerror(errno));
630             ret = DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
631             break;
632         }
633         inOffset += readLen;
634     }
635 
636     delete[] message.data;
637     delete[] outMessage.data;
638     return ret;
639 }
640 
DoDlpContentCopyOperation(int32_t inFd,int32_t outFd,uint32_t inOffset,uint32_t inFileLen)641 int32_t DlpFile::DoDlpContentCopyOperation(int32_t inFd, int32_t outFd, uint32_t inOffset, uint32_t inFileLen)
642 {
643     if (inOffset >= inFileLen) {
644         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
645     }
646     uint8_t *data = new (std::nothrow) uint8_t[DLP_BUFF_LEN];
647     if (data == nullptr) {
648         DLP_LOG_ERROR(LABEL, "prepare buff failed");
649         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
650     }
651 
652     int32_t ret = DLP_OK;
653     while (inOffset < inFileLen) {
654         uint32_t readLen = ((inFileLen - inOffset) < DLP_BUFF_LEN) ? (inFileLen - inOffset) : DLP_BUFF_LEN;
655         (void)memset_s(data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
656 
657         if (read(inFd, data, readLen) != (ssize_t)readLen) {
658             DLP_LOG_ERROR(LABEL, "Read size do not equal readLen");
659             ret = DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
660             break;
661         }
662 
663         if (write(outFd, data, readLen) != (ssize_t)readLen) {
664             DLP_LOG_ERROR(LABEL, "write fd failed, %{public}s", strerror(errno));
665             ret = DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
666             break;
667         }
668         inOffset += readLen;
669     }
670 
671     delete[] data;
672     return ret;
673 }
674 
GenFile(int32_t inPlainFileFd)675 int32_t DlpFile::GenFile(int32_t inPlainFileFd)
676 {
677     if (inPlainFileFd < 0 || dlpFd_ < 0 || !IsValidCipher(cipher_.encKey, cipher_.usageSpec)) {
678         DLP_LOG_ERROR(LABEL, "params is error");
679         return DLP_PARSE_ERROR_VALUE_INVALID;
680     }
681 
682     off_t fileLen = lseek(inPlainFileFd, 0, SEEK_END);
683     if (fileLen == static_cast<off_t>(-1) || fileLen > static_cast<off_t>(DLP_MAX_CONTENT_SIZE)) {
684         DLP_LOG_ERROR(LABEL, "inFd len is invalid, %{public}s", strerror(errno));
685         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
686     }
687     head_.txtSize = static_cast<uint32_t>(fileLen);
688     DLP_LOG_DEBUG(LABEL, "fileLen %{private}u", head_.txtSize);
689 
690     // clean dlpFile
691     if (ftruncate(dlpFd_, 0) == -1) {
692         DLP_LOG_ERROR(LABEL, "truncate dlp file to zero failed, %{public}s", strerror(errno));
693         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
694     }
695 
696     if (lseek(inPlainFileFd, 0, SEEK_SET) == static_cast<off_t>(-1)) {
697         DLP_LOG_ERROR(LABEL, "seek plain file start failed, %{public}s", strerror(errno));
698         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
699     }
700 
701     if (lseek(dlpFd_, 0, SEEK_SET) == static_cast<off_t>(-1)) {
702         DLP_LOG_ERROR(LABEL, "seek dlp file start failed, %{public}s", strerror(errno));
703         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
704     }
705 
706     if (write(dlpFd_, &head_, sizeof(struct DlpHeader)) != sizeof(struct DlpHeader)) {
707         DLP_LOG_ERROR(LABEL, "write dlp head failed, %{public}s", strerror(errno));
708         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
709     }
710 
711     if (write(dlpFd_, cert_.data, head_.certSize) != (ssize_t)head_.certSize) {
712         DLP_LOG_ERROR(LABEL, "write dlp cert data failed, %{public}s", strerror(errno));
713         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
714     }
715 
716     if (write(dlpFd_, contactAccount_.c_str(), contactAccount_.size()) !=
717         static_cast<int32_t>(contactAccount_.size())) {
718         DLP_LOG_ERROR(LABEL, "write dlp contact data failed, %{public}s", strerror(errno));
719         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
720     }
721 
722     if (fileLen == 0) {
723         DLP_LOG_INFO(LABEL, "Plaintext file len is 0, do not need encrypt");
724         return DLP_OK;
725     }
726     return DoDlpContentCryptyOperation(inPlainFileFd, dlpFd_, 0, fileLen, true);
727 }
728 
RemoveDlpPermission(int32_t outPlainFileFd)729 int32_t DlpFile::RemoveDlpPermission(int32_t outPlainFileFd)
730 {
731     if (isFuseLink_) {
732         DLP_LOG_ERROR(LABEL, "current dlp file is linking, do not operate it.");
733         return DLP_PARSE_ERROR_FILE_LINKING;
734     }
735 
736     if (authPerm_ != FULL_CONTROL) {
737         DLP_LOG_ERROR(LABEL, "check permission fail, remove dlp permission failed.");
738         return DLP_PARSE_ERROR_FILE_READ_ONLY;
739     }
740 
741     if (outPlainFileFd < 0 || dlpFd_ < 0) {
742         DLP_LOG_ERROR(LABEL, "fd is invalid");
743         return DLP_PARSE_ERROR_FD_ERROR;
744     }
745 
746     if (!IsValidCipher(cipher_.encKey, cipher_.usageSpec)) {
747         DLP_LOG_ERROR(LABEL, "cipher params is invalid");
748         return DLP_PARSE_ERROR_CIPHER_PARAMS_INVALID;
749     }
750 
751     off_t fileLen = lseek(dlpFd_, 0, SEEK_END);
752     if (fileLen == static_cast<off_t>(-1) || fileLen > static_cast<off_t>(DLP_MAX_CONTENT_SIZE)) {
753         DLP_LOG_ERROR(LABEL, "can not get dlp file len, %{public}s", strerror(errno));
754         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
755     }
756 
757     // clean plainTxtFile
758     if (ftruncate(outPlainFileFd, 0) == -1) {
759         DLP_LOG_ERROR(LABEL, "truncate plain file to zero failed, %{public}s", strerror(errno));
760         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
761     }
762 
763     if (lseek(outPlainFileFd, 0, SEEK_SET) == static_cast<off_t>(-1)) {
764         DLP_LOG_ERROR(LABEL, "seek plain file start failed, %{public}s", strerror(errno));
765         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
766     }
767 
768     if (lseek(dlpFd_, head_.txtOffset, SEEK_SET) == static_cast<off_t>(-1)) {
769         DLP_LOG_ERROR(LABEL, "seek dlp file start failed, %{public}s", strerror(errno));
770         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
771     }
772 
773     if (fileLen == head_.txtOffset) {
774         DLP_LOG_INFO(LABEL, "Dlp file have no content");
775         return DLP_OK;
776     }
777 
778     return DoDlpContentCryptyOperation(dlpFd_, outPlainFileFd, head_.txtOffset, fileLen, false);
779 }
780 
DeleteBufs(uint8_t * buff1,uint8_t * buff2)781 static void DeleteBufs(uint8_t* buff1, uint8_t* buff2)
782 {
783     if (buff1 != nullptr) {
784         delete[] buff1;
785     }
786     if (buff2 != nullptr) {
787         delete[] buff2;
788     }
789 }
790 
DlpFileRead(uint32_t offset,void * buf,uint32_t size)791 int32_t DlpFile::DlpFileRead(uint32_t offset, void* buf, uint32_t size)
792 {
793     if (buf == nullptr || size == 0 || size > DLP_FUSE_MAX_BUFFLEN ||
794         (offset >= DLP_MAX_CONTENT_SIZE - size) ||
795         dlpFd_ < 0 || !IsValidCipher(cipher_.encKey, cipher_.usageSpec)) {
796         DLP_LOG_ERROR(LABEL, "params is error");
797         return DLP_PARSE_ERROR_VALUE_INVALID;
798     }
799 
800     uint32_t alignOffset = (offset / DLP_BLOCK_SIZE) * DLP_BLOCK_SIZE;
801     uint32_t prefixingSize = offset - alignOffset;
802     uint32_t alignSize = size + prefixingSize;
803     if (lseek(dlpFd_, head_.txtOffset + alignOffset, SEEK_SET) == -1) {
804         DLP_LOG_ERROR(LABEL, "lseek dlp file failed. %{public}s", strerror(errno));
805         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
806     }
807 
808     uint8_t* encBuff = new (std::nothrow) uint8_t[alignSize]();
809     if (encBuff == nullptr) {
810         DLP_LOG_ERROR(LABEL, "new buff fail");
811         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
812     }
813 
814     uint8_t* outBuff = new (std::nothrow) uint8_t[alignSize]();
815     if (outBuff == nullptr) {
816         DeleteBufs(encBuff, nullptr);
817         DLP_LOG_ERROR(LABEL, "new buff fail");
818         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
819     }
820 
821     int32_t readLen = read(dlpFd_, encBuff, alignSize);
822     if (readLen == -1) {
823         DeleteBufs(encBuff, outBuff);
824         DLP_LOG_ERROR(LABEL, "read buff fail, %{public}s", strerror(errno));
825         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
826     }
827     if (readLen <= static_cast<int32_t>(prefixingSize)) {
828         DeleteBufs(encBuff, outBuff);
829         return 0;
830     }
831 
832     struct DlpBlob message1 = {.size = readLen, .data = encBuff};
833     struct DlpBlob message2 = {.size = readLen, .data = static_cast<uint8_t*>(outBuff)};
834     if (DoDlpBlockCryptOperation(message1, message2, alignOffset, false) != DLP_OK) {
835         DLP_LOG_ERROR(LABEL, "decrypt fail");
836         DeleteBufs(encBuff, outBuff);
837         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
838     }
839 
840     if (memcpy_s(buf, size, outBuff + prefixingSize, message2.size - prefixingSize) != EOK) {
841         DeleteBufs(encBuff, outBuff);
842         DLP_LOG_ERROR(LABEL, "copy decrypt result failed");
843         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
844     }
845     DeleteBufs(encBuff, outBuff);
846     return message2.size - prefixingSize;
847 }
848 
WriteFirstBlockData(uint32_t offset,void * buf,uint32_t size)849 int32_t DlpFile::WriteFirstBlockData(uint32_t offset, void* buf, uint32_t size)
850 {
851     uint32_t alignOffset = (offset / DLP_BLOCK_SIZE) * DLP_BLOCK_SIZE;
852     uint32_t prefixingSize = offset % DLP_BLOCK_SIZE;
853     uint32_t requestSize = (size < (DLP_BLOCK_SIZE - prefixingSize)) ? size : (DLP_BLOCK_SIZE - prefixingSize);
854     uint32_t writtenSize = prefixingSize + requestSize;
855     uint8_t enBuf[DLP_BLOCK_SIZE] = {0};
856     uint8_t deBuf[DLP_BLOCK_SIZE] = {0};
857 
858     do {
859         if (prefixingSize == 0) {
860             break;
861         }
862         int32_t readLen = read(dlpFd_, enBuf, prefixingSize);
863         if (readLen == -1) {
864             DLP_LOG_ERROR(LABEL, "read first block prefixing fail, %{public}s", strerror(errno));
865             return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
866         }
867         if (readLen == 0) {
868             break;
869         }
870 
871         struct DlpBlob message1 = {.size = prefixingSize, .data = enBuf};
872         struct DlpBlob message2 = {.size = prefixingSize, .data = deBuf};
873         if (DoDlpBlockCryptOperation(message1, message2, alignOffset, false) != DLP_OK) {
874             DLP_LOG_ERROR(LABEL, "decrypt appending bytes fail, %{public}s", strerror(errno));
875             return DLP_PARSE_ERROR_CRYPT_FAIL;
876         }
877     } while (false);
878 
879     if (memcpy_s(deBuf + prefixingSize, DLP_BLOCK_SIZE, buf, requestSize) != EOK) {
880         DLP_LOG_ERROR(LABEL, "copy write buffer first block failed, %{public}s", strerror(errno));
881         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
882     }
883 
884     struct DlpBlob message1 = {.size = writtenSize, .data = deBuf};
885     struct DlpBlob message2 = {.size = writtenSize, .data = enBuf};
886     if (DoDlpBlockCryptOperation(message1, message2, alignOffset, true) != DLP_OK) {
887         DLP_LOG_ERROR(LABEL, "enrypt first block fail");
888         return DLP_PARSE_ERROR_CRYPT_FAIL;
889     }
890 
891     if (lseek(dlpFd_, head_.txtOffset + alignOffset, SEEK_SET) == static_cast<off_t>(-1)) {
892         DLP_LOG_ERROR(LABEL, "lseek failed, %{public}s", strerror(errno));
893         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
894     }
895 
896     if (write(dlpFd_, enBuf, writtenSize) != (ssize_t)writtenSize) {
897         DLP_LOG_ERROR(LABEL, "write failed, %{public}s", strerror(errno));
898         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
899     }
900     return requestSize;
901 }
902 
DoDlpFileWrite(uint32_t offset,void * buf,uint32_t size)903 int32_t DlpFile::DoDlpFileWrite(uint32_t offset, void* buf, uint32_t size)
904 {
905     uint32_t alignOffset = (offset / DLP_BLOCK_SIZE * DLP_BLOCK_SIZE);
906     if (lseek(dlpFd_, head_.txtOffset + alignOffset, SEEK_SET) == static_cast<off_t>(-1)) {
907         DLP_LOG_ERROR(LABEL, "lseek dlp file offset %{public}d failed, %{public}s",
908             head_.txtOffset + offset, strerror(errno));
909         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
910     }
911 
912     /* write first block data, if it may be not aligned */
913     int32_t writenSize = WriteFirstBlockData(offset, static_cast<uint8_t *>(buf), size);
914     if (writenSize < 0) {
915         DLP_LOG_ERROR(LABEL, "encrypt prefix data failed");
916         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
917     }
918     if (static_cast<uint32_t>(writenSize) >= size) {
919         return writenSize;
920     }
921 
922     uint8_t *restBlocksPtr = static_cast<uint8_t *>(buf) + writenSize;
923     uint32_t restBlocksSize = size - static_cast<uint32_t>(writenSize);
924     uint8_t* writeBuff = new (std::nothrow) uint8_t[restBlocksSize]();
925     if (writeBuff == nullptr) {
926         DLP_LOG_ERROR(LABEL, "alloc write buffer fail");
927         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
928     }
929 
930     /* first aligned block has been writen, write the rest */
931     struct DlpBlob message1 = {.size = restBlocksSize, .data = restBlocksPtr};
932     struct DlpBlob message2 = {.size = restBlocksSize, .data = writeBuff};
933 
934     int ret = DoDlpBlockCryptOperation(message1, message2, alignOffset + DLP_BLOCK_SIZE, true);
935     if (ret != DLP_OK) {
936         DLP_LOG_ERROR(LABEL, "encrypt write buffer fail");
937         delete[] writeBuff;
938         return ret;
939     }
940 
941     ret = write(dlpFd_, writeBuff, restBlocksSize);
942     delete[] writeBuff;
943     if (ret <= 0) {
944         DLP_LOG_ERROR(LABEL, "write buff failed, %{public}s", strerror(errno));
945         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
946     }
947 
948     return ret + static_cast<int32_t>(writenSize);
949 }
950 
GetFsContentSize() const951 uint32_t DlpFile::GetFsContentSize() const
952 {
953     struct stat fileStat;
954     int32_t ret = fstat(dlpFd_, &fileStat);
955     if (ret != 0) {
956         DLP_LOG_ERROR(LABEL, "fstat error %{public}d , errno %{public}d dlpfd: %{public}d ", ret, errno, dlpFd_);
957         return INVALID_FILE_SIZE;
958     }
959     if (head_.txtOffset > fileStat.st_size || fileStat.st_size >= static_cast<off_t>(INVALID_FILE_SIZE)) {
960         DLP_LOG_ERROR(LABEL, "size error %{public}d %{public}d", head_.txtOffset,
961             static_cast<uint32_t>(fileStat.st_size));
962         return INVALID_FILE_SIZE;
963     }
964     if (static_cast<uint32_t>(fileStat.st_size) - head_.txtOffset == 0) {
965         DLP_LOG_ERROR(LABEL, "linkFile size %{public}d %{public}d", static_cast<uint32_t>(fileStat.st_size),
966             head_.txtOffset);
967     }
968     return static_cast<uint32_t>(fileStat.st_size) - head_.txtOffset;
969 }
970 
UpdateDlpFileContentSize()971 int32_t DlpFile::UpdateDlpFileContentSize()
972 {
973     uint32_t contentSize = GetFsContentSize();
974     if (contentSize == INVALID_FILE_SIZE) {
975         DLP_LOG_ERROR(LABEL, "get fs content size failed");
976         return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
977     }
978     head_.txtSize = contentSize;
979     DLP_LOG_DEBUG(LABEL, "Update dlp file content size");
980 
981     if (lseek(dlpFd_, 0, SEEK_SET) == static_cast<off_t>(-1)) {
982         DLP_LOG_ERROR(LABEL, "Lseek failed, %{public}s", strerror(errno));
983         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
984     }
985 
986     if (write(dlpFd_, &head_, sizeof(head_)) != sizeof(head_)) {
987         DLP_LOG_ERROR(LABEL, "Write failed, %{public}s", strerror(errno));
988         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
989     }
990     return DLP_OK;
991 }
992 
FillHoleData(uint32_t holeStart,uint32_t holeSize)993 int32_t DlpFile::FillHoleData(uint32_t holeStart, uint32_t holeSize)
994 {
995     DLP_LOG_INFO(LABEL, "Need create a hole filled with 0s, hole start %{public}x size %{public}x",
996         holeStart, holeSize);
997     uint32_t holeBufSize = (holeSize < HOLE_BUFF_SMALL_SIZE) ? HOLE_BUFF_SMALL_SIZE : HOLE_BUFF_SIZE;
998     std::unique_ptr<uint8_t[]> holeBuff(new (std::nothrow) uint8_t[holeBufSize]());
999     if (holeBuff == nullptr) {
1000         DLP_LOG_ERROR(LABEL, "New buf failed.");
1001         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
1002     }
1003 
1004     uint32_t fillLen = 0;
1005     while (fillLen < holeSize) {
1006         uint32_t writeSize = ((holeSize - fillLen) < holeBufSize) ? (holeSize - fillLen) : holeBufSize;
1007         int32_t res = DoDlpFileWrite(holeStart + fillLen, holeBuff.get(), writeSize);
1008         if (res < 0) {
1009             DLP_LOG_ERROR(LABEL, "Write failed, error %{public}d.", res);
1010             return res;
1011         }
1012         fillLen += writeSize;
1013     }
1014     return DLP_OK;
1015 }
1016 
DlpFileWrite(uint32_t offset,void * buf,uint32_t size)1017 int32_t DlpFile::DlpFileWrite(uint32_t offset, void* buf, uint32_t size)
1018 {
1019     if (authPerm_ == READ_ONLY) {
1020         DLP_LOG_ERROR(LABEL, "Dlp file is readonly, write failed");
1021         return DLP_PARSE_ERROR_FILE_READ_ONLY;
1022     }
1023 
1024     if (buf == nullptr || size == 0 || size > DLP_FUSE_MAX_BUFFLEN ||
1025         (offset >= DLP_MAX_CONTENT_SIZE - size) ||
1026         dlpFd_ < 0 || !IsValidCipher(cipher_.encKey, cipher_.usageSpec)) {
1027         DLP_LOG_ERROR(LABEL, "Dlp file param invalid");
1028         return DLP_PARSE_ERROR_VALUE_INVALID;
1029     }
1030 
1031     uint32_t curSize = GetFsContentSize();
1032     if (curSize != INVALID_FILE_SIZE && curSize < offset &&
1033         (FillHoleData(curSize, offset - curSize) != DLP_OK)) {
1034         DLP_LOG_ERROR(LABEL, "Fill hole data failed");
1035         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1036     }
1037     int32_t res = DoDlpFileWrite(offset, buf, size);
1038     UpdateDlpFileContentSize();
1039     return res;
1040 }
1041 
Truncate(uint32_t size)1042 int32_t DlpFile::Truncate(uint32_t size)
1043 {
1044     DLP_LOG_INFO(LABEL, "Truncate file size %{public}u", size);
1045 
1046     if (authPerm_ == READ_ONLY) {
1047         DLP_LOG_ERROR(LABEL, "Dlp file is readonly, truncate failed");
1048         return DLP_PARSE_ERROR_FILE_READ_ONLY;
1049     }
1050 
1051     if (dlpFd_ < 0 || size >= DLP_MAX_CONTENT_SIZE) {
1052         DLP_LOG_ERROR(LABEL, "Param invalid");
1053         return DLP_PARSE_ERROR_VALUE_INVALID;
1054     }
1055 
1056     uint32_t curSize = GetFsContentSize();
1057     int res = DLP_OK;
1058     if (size < curSize) {
1059         res = ftruncate(dlpFd_, head_.txtOffset + size);
1060         UpdateDlpFileContentSize();
1061     } else if (size > curSize) {
1062         res = FillHoleData(curSize, size - curSize);
1063         UpdateDlpFileContentSize();
1064     } else {
1065         DLP_LOG_INFO(LABEL, "Truncate file size equals origin file");
1066     }
1067 
1068     if (res != DLP_OK) {
1069         DLP_LOG_ERROR(LABEL, "Truncate file size %{public}u failed, %{public}s", size, strerror(errno));
1070         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1071     }
1072     return DLP_OK;
1073 }
1074 }  // namespace DlpPermission
1075 }  // namespace Security
1076 }  // namespace OHOS
1077