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