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