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, false, 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 if (rmdir(workDir_.c_str()) != 0) {
578 DLP_LOG_ERROR(LABEL, "rmdir failed, %{public}s errno %{public}s", workDir_.c_str(), strerror(errno));
579 }
580
581 return true;
582 }
583
UnzipDlpFile()584 int32_t DlpFile::UnzipDlpFile()
585 {
586 std::lock_guard<std::mutex> lock(g_fileOpLock_);
587 isZip_ = true;
588 head_.txtOffset = 0;
589 char cwd[DLP_CWD_MAX] = {0};
590 GETCWD_AND_CHECK(cwd, DLP_CWD_MAX, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
591 Defer p(nullptr, [&](...) {
592 if (chdir(cwd) != 0) {
593 DLP_LOG_ERROR(LABEL, "chdir failed, %{public}s", strerror(errno));
594 }
595 });
596
597 CHDIR_AND_CHECK(workDir_.c_str(), DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
598 MKDIR_AND_CHECK(dirIndex_.c_str(), S_IRWXU, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
599 CHDIR_AND_CHECK(dirIndex_.c_str(), DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
600 if (!CheckUnzipFileInfo(dlpFd_)) {
601 return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
602 }
603 UnzipSpecificFile(dlpFd_, DLP_GENERAL_INFO.c_str(), DLP_GENERAL_INFO.c_str());
604 if (!ParseDlpInfo()) {
605 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
606 }
607 UnzipSpecificFile(dlpFd_, DLP_CERT.c_str(), DLP_CERT.c_str());
608 if (!ParseCert()) {
609 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
610 }
611 UnzipSpecificFile(dlpFd_, DLP_ENC_DATA.c_str(), DLP_OPENING_ENC_DATA.c_str());
612 if (!ParseEncData()) {
613 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
614 }
615
616 return DLP_OK;
617 }
618
ParseDlpHeaderInRaw()619 int32_t DlpFile::ParseDlpHeaderInRaw()
620 {
621 int32_t ret = CheckDlpFile();
622 if (ret != DLP_OK) {
623 return ret;
624 }
625
626 // get cert encrypt context
627 uint8_t* buf = new (std::nothrow)uint8_t[head_.certSize];
628 if (buf == nullptr) {
629 DLP_LOG_WARN(LABEL, "alloc buffer failed.");
630 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
631 }
632 if (read(dlpFd_, buf, head_.certSize) != (ssize_t)head_.certSize) {
633 delete[] buf;
634 DLP_LOG_ERROR(LABEL, "can not read dlp file cert, %{public}s", strerror(errno));
635 return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
636 }
637 CleanBlobParam(cert_);
638 cert_.data = buf;
639 cert_.size = head_.certSize;
640
641 uint8_t *tmpBuf = new (std::nothrow)uint8_t[head_.contactAccountSize];
642 if (tmpBuf == nullptr) {
643 DLP_LOG_WARN(LABEL, "alloc tmpBuf failed.");
644 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
645 }
646
647 if (read(dlpFd_, tmpBuf, head_.contactAccountSize) != (ssize_t)head_.contactAccountSize) {
648 delete[] tmpBuf;
649 DLP_LOG_ERROR(LABEL, "can not read dlp contact account, %{public}s", strerror(errno));
650 return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
651 }
652
653 contactAccount_ = std::string(tmpBuf, tmpBuf + head_.contactAccountSize);
654 delete[] tmpBuf;
655
656 if (head_.offlineCertSize != 0) {
657 tmpBuf = new (std::nothrow)uint8_t[head_.offlineCertSize];
658 if (tmpBuf == nullptr) {
659 DLP_LOG_WARN(LABEL, "alloc tmpBuf failed.");
660 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
661 }
662
663 if (read(dlpFd_, tmpBuf, head_.offlineCertSize) != (ssize_t)head_.offlineCertSize) {
664 delete[] tmpBuf;
665 DLP_LOG_ERROR(LABEL, "can not read dlp contact account, %{public}s", strerror(errno));
666 return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
667 }
668 CleanBlobParam(offlineCert_);
669 offlineCert_.data = tmpBuf;
670 offlineCert_.size = head_.offlineCertSize;
671 }
672 return DLP_OK;
673 }
674
ParseDlpHeader()675 int32_t DlpFile::ParseDlpHeader()
676 {
677 if (IsZipFile(dlpFd_)) {
678 return UnzipDlpFile();
679 } else {
680 return ParseDlpHeaderInRaw();
681 }
682 }
683
GetEncryptCert(struct DlpBlob & cert) const684 void DlpFile::GetEncryptCert(struct DlpBlob& cert) const
685 {
686 cert.data = cert_.data;
687 cert.size = cert_.size;
688 }
689
GetOfflineCert(struct DlpBlob & cert) const690 void DlpFile::GetOfflineCert(struct DlpBlob& cert) const
691 {
692 cert.data = offlineCert_.data;
693 cert.size = offlineCert_.size;
694 }
695
SetEncryptCert(const struct DlpBlob & cert)696 int32_t DlpFile::SetEncryptCert(const struct DlpBlob& cert)
697 {
698 if (cert.data == nullptr || cert.size > DLP_MAX_CERT_SIZE) {
699 DLP_LOG_ERROR(LABEL, "Cert data invalid");
700 return DLP_PARSE_ERROR_VALUE_INVALID;
701 }
702
703 if (cert_.data != nullptr) {
704 delete[] cert_.data;
705 cert_.data = nullptr;
706 }
707
708 if (CopyBlobParam(cert, cert_) != DLP_OK) {
709 DLP_LOG_ERROR(LABEL, "Cert copy failed");
710 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
711 }
712
713 head_.certOffset = sizeof(struct DlpHeader);
714 head_.certSize = cert_.size;
715 head_.txtOffset = sizeof(struct DlpHeader) + cert_.size;
716 return DLP_OK;
717 }
718
UpdateFile(int32_t tmpFile,const std::vector<uint8_t> & cert,uint32_t oldTxtOffset)719 int32_t DlpFile::UpdateFile(int32_t tmpFile, const std::vector<uint8_t>& cert, uint32_t oldTxtOffset)
720 {
721 if (WriteHeadAndCert(tmpFile, cert) != DLP_OK) {
722 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
723 }
724 (void)lseek(dlpFd_, oldTxtOffset, SEEK_SET);
725 int32_t ret = DoDlpContentCopyOperation(dlpFd_, tmpFile, 0, head_.txtSize);
726 if (ret != DLP_OK) {
727 return ret;
728 }
729 int32_t fileSize = lseek(tmpFile, 0, SEEK_CUR);
730 (void)lseek(tmpFile, 0, SEEK_SET);
731 (void)lseek(dlpFd_, 0, SEEK_SET);
732 ret = DoDlpContentCopyOperation(tmpFile, dlpFd_, 0, fileSize);
733 if (ret != DLP_OK) {
734 return ret;
735 }
736
737 FTRUNCATE_AND_CHECK(dlpFd_, fileSize, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
738 (void)fsync(dlpFd_);
739 return DLP_OK;
740 }
741
GetTempFile(const std::string & workDir,int32_t & tempFile,std::string & path)742 int32_t DlpFile::GetTempFile(const std::string& workDir, int32_t& tempFile, std::string& path)
743 {
744 static uint32_t count = 0;
745 char realPath[PATH_MAX] = {0};
746 if ((realpath(workDir.c_str(), realPath) == nullptr) && (errno != ENOENT)) {
747 DLP_LOG_ERROR(LABEL, "realpath, %{public}s, workDir %{private}s", strerror(errno), workDir.c_str());
748 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
749 }
750 std::string rPath(realPath);
751 path = rPath + "/dlp" + std::to_string(count++) + ".txt";
752 tempFile = open(path.c_str(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
753 if (tempFile < 0) {
754 DLP_LOG_ERROR(LABEL, "open file fail, %{public}s, realPath %{private}s", strerror(errno), path.c_str());
755 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
756 }
757 return DLP_OK;
758 }
759
UpdateCertAndText(const std::vector<uint8_t> & cert,const std::string & workDir,struct DlpBlob certBlob)760 int32_t DlpFile::UpdateCertAndText(const std::vector<uint8_t>& cert, const std::string& workDir,
761 struct DlpBlob certBlob)
762 {
763 if (CopyBlobParam(certBlob, cert_) != DLP_OK) {
764 DLP_LOG_ERROR(LABEL, "Cert copy failed");
765 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
766 }
767
768 if (isZip_) {
769 return GenFileInZip(-1);
770 }
771
772 int32_t tmpFile;
773 std::string path;
774 int32_t res = GetTempFile(workDir, tmpFile, path);
775 if (res != DLP_OK) {
776 return res;
777 }
778 Defer p(nullptr, [&](...) {
779 (void)close(tmpFile);
780 (void)unlink(path.c_str());
781 });
782
783 head_.certSize = cert.size();
784 uint32_t oldTxtOffset = head_.txtOffset;
785 head_.contactAccountOffset = head_.certOffset + head_.certSize;
786 head_.txtOffset = head_.contactAccountOffset + head_.contactAccountSize;
787
788 // version 1 single file auto convert to version 2 zip file, set version
789 head_.version = SECOND;
790 head_.offlineCertSize = 0;
791
792 return UpdateFile(tmpFile, cert, oldTxtOffset);
793 }
794
UpdateCert(struct DlpBlob certBlob)795 int32_t DlpFile::UpdateCert(struct DlpBlob certBlob)
796 {
797 DLP_LOG_DEBUG(LABEL, "enter");
798
799 if (CopyBlobParam(certBlob, cert_) != DLP_OK) {
800 DLP_LOG_ERROR(LABEL, "Cert copy failed");
801 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
802 }
803
804 if (isZip_) {
805 return GenFileInZip(-1);
806 }
807
808 if (write(dlpFd_, cert_.data, head_.certSize) != (ssize_t)head_.certSize) {
809 DLP_LOG_ERROR(LABEL, "write dlp cert data failed, %{public}s", strerror(errno));
810 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
811 }
812 return DLP_OK;
813 }
814
WriteHeadAndCert(int32_t tmpFile,const std::vector<uint8_t> & cert)815 int32_t DlpFile::WriteHeadAndCert(int32_t tmpFile, const std::vector<uint8_t>& cert)
816 {
817 if (write(tmpFile, &head_, sizeof(struct DlpHeader)) != sizeof(struct DlpHeader)) {
818 DLP_LOG_ERROR(LABEL, "write dlp head failed, %{public}s", strerror(errno));
819 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
820 }
821 if (write(tmpFile, cert_.data, head_.certSize) != (ssize_t)head_.certSize) {
822 DLP_LOG_ERROR(LABEL, "write dlp cert data failed, %{public}s", strerror(errno));
823 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
824 }
825 if (write(tmpFile, contactAccount_.c_str(), contactAccount_.size()) !=
826 static_cast<int32_t>(contactAccount_.size())) {
827 DLP_LOG_ERROR(LABEL, "write dlp contact data failed, %{public}s", strerror(errno));
828 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
829 }
830 return DLP_OK;
831 }
832
PrepareBuff(struct DlpBlob & message1,struct DlpBlob & message2) const833 int32_t DlpFile::PrepareBuff(struct DlpBlob& message1, struct DlpBlob& message2) const
834 {
835 message1.size = DLP_BUFF_LEN;
836 message1.data = new (std::nothrow) uint8_t[DLP_BUFF_LEN];
837 if (message1.data == nullptr) {
838 DLP_LOG_ERROR(LABEL, "message1.data null");
839 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
840 }
841
842 message2.size = DLP_BUFF_LEN;
843 message2.data = new (std::nothrow) uint8_t[DLP_BUFF_LEN];
844 if (message2.data == nullptr) {
845 DLP_LOG_ERROR(LABEL, "message2.data null");
846 delete[] message1.data;
847 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
848 }
849
850 (void)memset_s(message1.data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
851 (void)memset_s(message2.data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
852 return DLP_OK;
853 }
854
DupUsageSpec(struct DlpUsageSpec & spec)855 int32_t DlpFile::DupUsageSpec(struct DlpUsageSpec& spec)
856 {
857 if (cipher_.usageSpec.algParam == nullptr ||
858 cipher_.usageSpec.algParam->iv.data == nullptr ||
859 cipher_.usageSpec.algParam->iv.size != IV_SIZE) {
860 DLP_LOG_ERROR(LABEL, "chipher_ is invalid");
861 return DLP_PARSE_ERROR_VALUE_INVALID;
862 }
863 spec.mode = cipher_.usageSpec.mode;
864 spec.algParam = new (std::nothrow) struct DlpCipherParam;
865 if (spec.algParam == nullptr) {
866 DLP_LOG_ERROR(LABEL, "new alg param failed");
867 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
868 }
869 spec.algParam->iv.data = new (std::nothrow) uint8_t[IV_SIZE]();
870 if (spec.algParam->iv.data == nullptr) {
871 delete spec.algParam;
872 DLP_LOG_ERROR(LABEL, "new iv failed");
873 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
874 }
875 spec.algParam->iv.size = cipher_.usageSpec.algParam->iv.size;
876 if (memcpy_s(spec.algParam->iv.data, IV_SIZE,
877 cipher_.usageSpec.algParam->iv.data, cipher_.usageSpec.algParam->iv.size) != EOK) {
878 delete[] spec.algParam->iv.data;
879 delete spec.algParam;
880 DLP_LOG_ERROR(LABEL, "copy iv failed");
881 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
882 }
883 return DLP_OK;
884 }
885
DoDlpBlockCryptOperation(struct DlpBlob & message1,struct DlpBlob & message2,uint32_t offset,bool isEncrypt)886 int32_t DlpFile::DoDlpBlockCryptOperation(struct DlpBlob& message1, struct DlpBlob& message2,
887 uint32_t offset, bool isEncrypt)
888 {
889 if (offset % DLP_BLOCK_SIZE != 0 || message1.data == nullptr || message1.size == 0
890 || message2.data == nullptr || message2.size == 0) {
891 DLP_LOG_ERROR(LABEL, "params is error");
892 return DLP_PARSE_ERROR_VALUE_INVALID;
893 }
894
895 uint32_t counterIndex = offset / DLP_BLOCK_SIZE;
896 struct DlpUsageSpec spec;
897 if (DupUsageSpec(spec) != DLP_OK) {
898 DLP_LOG_ERROR(LABEL, "spec dup failed");
899 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
900 }
901
902 DlpCtrModeIncreaeIvCounter(spec.algParam->iv, counterIndex);
903 int32_t ret = isEncrypt ? DlpOpensslAesEncrypt(&cipher_.encKey, &spec, &message1, &message2) :
904 DlpOpensslAesDecrypt(&cipher_.encKey, &spec, &message1, &message2);
905 delete[] spec.algParam->iv.data;
906 delete spec.algParam;
907 if (ret != 0) {
908 DLP_LOG_ERROR(LABEL, "do block crypt fail");
909 return DLP_PARSE_ERROR_CRYPT_FAIL;
910 }
911 return DLP_OK;
912 }
913
DoDlpContentCryptyOperation(int32_t inFd,int32_t outFd,uint32_t inOffset,uint32_t inFileLen,bool isEncrypt)914 int32_t DlpFile::DoDlpContentCryptyOperation(int32_t inFd, int32_t outFd, uint32_t inOffset,
915 uint32_t inFileLen, bool isEncrypt)
916 {
917 struct DlpBlob message, outMessage;
918 if (PrepareBuff(message, outMessage) != DLP_OK) {
919 DLP_LOG_ERROR(LABEL, "prepare buff failed");
920 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
921 }
922
923 uint32_t dlpContentOffset = inOffset;
924 int32_t ret = DLP_OK;
925 while (inOffset < inFileLen) {
926 uint32_t readLen = ((inFileLen - inOffset) < DLP_BUFF_LEN) ? (inFileLen - inOffset) : DLP_BUFF_LEN;
927 (void)memset_s(message.data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
928 (void)memset_s(outMessage.data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
929 if (read(inFd, message.data, readLen) != (ssize_t)readLen) {
930 DLP_LOG_ERROR(LABEL, "Read size do not equal readLen");
931 ret = DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
932 break;
933 }
934
935 message.size = readLen;
936 outMessage.size = readLen;
937 // Implicit condition: DLP_BUFF_LEN must be DLP_BLOCK_SIZE aligned
938 ret = DoDlpBlockCryptOperation(message, outMessage, inOffset - dlpContentOffset, isEncrypt);
939 if (ret != DLP_OK) {
940 DLP_LOG_ERROR(LABEL, "do crypt operation fail");
941 break;
942 }
943
944 if (write(outFd, outMessage.data, readLen) != (ssize_t)readLen) {
945 DLP_LOG_ERROR(LABEL, "write fd failed, %{public}s", strerror(errno));
946 ret = DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
947 break;
948 }
949 inOffset += readLen;
950 }
951
952 delete[] message.data;
953 delete[] outMessage.data;
954 return ret;
955 }
956
DoDlpContentCopyOperation(int32_t inFd,int32_t outFd,uint32_t inOffset,uint32_t inFileLen)957 int32_t DlpFile::DoDlpContentCopyOperation(int32_t inFd, int32_t outFd, uint32_t inOffset, uint32_t inFileLen)
958 {
959 if (inOffset > inFileLen) {
960 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
961 }
962 uint8_t *data = new (std::nothrow) uint8_t[DLP_BUFF_LEN];
963 if (data == nullptr) {
964 DLP_LOG_ERROR(LABEL, "prepare buff failed");
965 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
966 }
967
968 int32_t ret = DLP_OK;
969 while (inOffset < inFileLen) {
970 uint32_t readLen = ((inFileLen - inOffset) < DLP_BUFF_LEN) ? (inFileLen - inOffset) : DLP_BUFF_LEN;
971 (void)memset_s(data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
972
973 if (read(inFd, data, readLen) != (ssize_t)readLen) {
974 DLP_LOG_ERROR(LABEL, "Read size do not equal readLen");
975 ret = DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
976 break;
977 }
978
979 if (write(outFd, data, readLen) != (ssize_t)readLen) {
980 DLP_LOG_ERROR(LABEL, "write fd failed, %{public}s", strerror(errno));
981 ret = DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
982 break;
983 }
984 inOffset += readLen;
985 }
986 delete[] data;
987 return ret;
988 }
989
GetFileSize(int32_t fd)990 static int32_t GetFileSize(int32_t fd)
991 {
992 int32_t fileLen = lseek(fd, 0, SEEK_END);
993 (void)lseek(fd, 0, SEEK_SET);
994 return fileLen;
995 }
996
SetDlpGeneralInfo(bool accessFlag,std::string & contactAccount,const std::string & hmacStr,const uint32_t & version,std::string & out)997 static void SetDlpGeneralInfo(bool accessFlag, std::string& contactAccount, const std::string& hmacStr,
998 const uint32_t& version, std::string& out)
999 {
1000 GenerateInfoParams params = {
1001 .version = version,
1002 .offlineAccessFlag = accessFlag,
1003 .contactAccount = contactAccount,
1004 .extraInfo = {"kia_info", "cert_info", "enc_data"},
1005 .hmacVal = hmacStr,
1006 };
1007 GenerateDlpGeneralInfo(params, out);
1008 }
1009
GenEncData(int32_t inPlainFileFd)1010 int32_t DlpFile::GenEncData(int32_t inPlainFileFd)
1011 {
1012 int32_t encFile = -1;
1013 if (inPlainFileFd == -1) {
1014 encFile = open(DLP_OPENING_ENC_DATA.c_str(), O_RDWR);
1015 } else {
1016 int32_t fileLen = GetFileSize(inPlainFileFd);
1017 OPEN_AND_CHECK(encFile, DLP_OPENING_ENC_DATA.c_str(), O_RDWR | O_CREAT | O_TRUNC,
1018 S_IRUSR | S_IWUSR, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1019 encDataFd_ = encFile;
1020 int32_t ret = DoDlpContentCryptyOperation(inPlainFileFd, encFile, 0, fileLen, true);
1021 CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1022 LSEEK_AND_CHECK(encFile, 0, SEEK_SET, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1023 }
1024 return encFile;
1025 }
1026
GenerateHmacVal(int32_t encFile,struct DlpBlob & out)1027 int32_t DlpFile::GenerateHmacVal(int32_t encFile, struct DlpBlob& out)
1028 {
1029 lseek(encFile, 0, SEEK_SET);
1030 int32_t fd = dup(encFile);
1031 int32_t fileLen = GetFileSize(fd);
1032 if (fileLen == 0) {
1033 (void)close(fd);
1034 CleanBlobParam(out);
1035 return DLP_OK;
1036 } else if (fileLen < 0) {
1037 (void)close(fd);
1038 DLP_LOG_ERROR(LABEL, "fileLen less than 0");
1039 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1040 }
1041
1042 int ret = DlpHmacEncode(cipher_.hmacKey, fd, out);
1043 (void)close(fd);
1044 return ret;
1045 }
1046
GetHmacVal(int32_t encFile,std::string & hmacStr)1047 int32_t DlpFile::GetHmacVal(int32_t encFile, std::string& hmacStr)
1048 {
1049 if (head_.version < HMAC_VERSION) {
1050 return DLP_OK;
1051 }
1052 if (hmac_.size == 0) {
1053 uint8_t* outBuf = new (std::nothrow) uint8_t[HMAC_SIZE];
1054 if (outBuf == nullptr) {
1055 DLP_LOG_ERROR(LABEL, "New memory fail");
1056 return DLP_SERVICE_ERROR_MEMORY_OPERATE_FAIL;
1057 }
1058 struct DlpBlob out = {
1059 .size = HMAC_SIZE,
1060 .data = outBuf,
1061 };
1062 int ret = GenerateHmacVal(encFile, out);
1063 if (ret != DLP_OK) {
1064 CleanBlobParam(out);
1065 return ret;
1066 }
1067 if (out.size == 0) {
1068 return DLP_OK;
1069 }
1070 hmac_.size = out.size;
1071 hmac_.data = out.data;
1072 }
1073 uint32_t hmacHexLen = hmac_.size * BYTE_TO_HEX_OPER_LENGTH + 1;
1074 char* hmacHex = new (std::nothrow) char[hmacHexLen];
1075 if (hmacHex == nullptr) {
1076 DLP_LOG_ERROR(LABEL, "New memory fail");
1077 return DLP_SERVICE_ERROR_MEMORY_OPERATE_FAIL;
1078 }
1079 int ret = ByteToHexString(hmac_.data, hmac_.size, hmacHex, hmacHexLen);
1080 if (ret != DLP_OK) {
1081 DLP_LOG_ERROR(LABEL, "Byte to hexstring fail");
1082 FreeCharBuffer(hmacHex, hmacHexLen);
1083 return ret;
1084 }
1085 hmacStr = hmacHex;
1086 FreeCharBuffer(hmacHex, hmacHexLen);
1087 return DLP_OK;
1088 }
1089
AddGeneralInfoToBuff(int32_t encFile)1090 int32_t DlpFile::AddGeneralInfoToBuff(int32_t encFile)
1091 {
1092 std::string hmacStr;
1093 int ret = GetHmacVal(encFile, hmacStr);
1094 if (ret != DLP_OK) {
1095 DLP_LOG_ERROR(LABEL, "GetHmacVal fail");
1096 return ret;
1097 }
1098 std::string ja;
1099 SetDlpGeneralInfo(head_.offlineAccess, contactAccount_, hmacStr, head_.version, ja);
1100 ret = AddBuffToZip(reinterpret_cast<const void *>(ja.c_str()), ja.size(),
1101 DLP_GENERAL_INFO.c_str(), DLP_GEN_FILE.c_str());
1102 CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1103 return DLP_OK;
1104 }
1105
GenFileInZip(int32_t inPlainFileFd)1106 int32_t DlpFile::GenFileInZip(int32_t inPlainFileFd)
1107 {
1108 if (isZip_ == false) {
1109 return DLP_OK;
1110 }
1111 char cwd[DLP_CWD_MAX] = {0};
1112 std::lock_guard<std::mutex> lock(g_fileOpLock_);
1113 GETCWD_AND_CHECK(cwd, DLP_CWD_MAX, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1114 Defer p(nullptr, [&](...) {
1115 (void)chdir(cwd);
1116 });
1117 CHDIR_AND_CHECK(workDir_.c_str(), DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1118 if (inPlainFileFd != -1) {
1119 MKDIR_AND_CHECK(dirIndex_.c_str(), S_IRWXU, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1120 }
1121 CHDIR_AND_CHECK(dirIndex_.c_str(), DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1122
1123 int32_t tmpFile;
1124 OPEN_AND_CHECK(tmpFile, DLP_GEN_FILE.c_str(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR,
1125 DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1126 Defer p2(nullptr, [&](...) {
1127 (void)close(tmpFile);
1128 (void)unlink(DLP_GEN_FILE.c_str());
1129 });
1130 int32_t ret = AddBuffToZip(reinterpret_cast<const void *>(cert_.data), cert_.size,
1131 DLP_CERT.c_str(), DLP_GEN_FILE.c_str());
1132 CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1133
1134 int32_t encFile = GenEncData(inPlainFileFd);
1135 Defer p3(nullptr, [&](...) {
1136 if (inPlainFileFd == -1) {
1137 (void)close(encFile);
1138 }
1139 });
1140
1141 ret = AddFileContextToZip(encFile, DLP_ENC_DATA.c_str(), DLP_GEN_FILE.c_str());
1142 CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1143 ret = AddGeneralInfoToBuff(encFile);
1144 CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1145
1146 int32_t zipSize = GetFileSize(tmpFile);
1147 LSEEK_AND_CHECK(dlpFd_, 0, SEEK_SET, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1148 ret = DoDlpContentCopyOperation(tmpFile, dlpFd_, 0, zipSize);
1149 CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1150
1151 FTRUNCATE_AND_CHECK(dlpFd_, zipSize, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1152
1153 (void)fsync(dlpFd_);
1154 return DLP_OK;
1155 }
1156
GenFileInRaw(int32_t inPlainFileFd)1157 int32_t DlpFile::GenFileInRaw(int32_t inPlainFileFd)
1158 {
1159 off_t fileLen = lseek(inPlainFileFd, 0, SEEK_END);
1160 if (fileLen == static_cast<off_t>(-1) || fileLen > static_cast<off_t>(DLP_MAX_CONTENT_SIZE)) {
1161 DLP_LOG_ERROR(LABEL, "inFd len is invalid, %{public}s", strerror(errno));
1162 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1163 }
1164 head_.txtSize = static_cast<uint32_t>(fileLen);
1165 DLP_LOG_DEBUG(LABEL, "fileLen %{private}u", head_.txtSize);
1166
1167 // clean dlpFile
1168 if (ftruncate(dlpFd_, 0) == -1) {
1169 DLP_LOG_ERROR(LABEL, "truncate dlp file to zero failed, %{public}s", strerror(errno));
1170 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1171 }
1172
1173 if (lseek(inPlainFileFd, 0, SEEK_SET) == static_cast<off_t>(-1)) {
1174 DLP_LOG_ERROR(LABEL, "seek plain file start failed, %{public}s", strerror(errno));
1175 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1176 }
1177
1178 if (lseek(dlpFd_, 0, SEEK_SET) == static_cast<off_t>(-1)) {
1179 DLP_LOG_ERROR(LABEL, "seek dlp file start failed, %{public}s", strerror(errno));
1180 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1181 }
1182
1183 if (write(dlpFd_, &head_, sizeof(struct DlpHeader)) != sizeof(struct DlpHeader)) {
1184 DLP_LOG_ERROR(LABEL, "write dlp head failed, %{public}s", strerror(errno));
1185 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1186 }
1187
1188 if (write(dlpFd_, cert_.data, head_.certSize) != (ssize_t)head_.certSize) {
1189 DLP_LOG_ERROR(LABEL, "write dlp cert data failed, %{public}s", strerror(errno));
1190 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1191 }
1192
1193 if (write(dlpFd_, contactAccount_.c_str(), contactAccount_.size()) !=
1194 static_cast<int32_t>(contactAccount_.size())) {
1195 DLP_LOG_ERROR(LABEL, "write dlp contact data failed, %{public}s", strerror(errno));
1196 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1197 }
1198
1199 if (fileLen == 0) {
1200 DLP_LOG_INFO(LABEL, "Plaintext file len is 0, do not need encrypt");
1201 return DLP_OK;
1202 }
1203 return DoDlpContentCryptyOperation(inPlainFileFd, dlpFd_, 0, fileLen, true);
1204 }
1205
GenFile(int32_t inPlainFileFd)1206 int32_t DlpFile::GenFile(int32_t inPlainFileFd)
1207 {
1208 if (inPlainFileFd < 0 || dlpFd_ < 0 || !IsValidCipher(cipher_.encKey, cipher_.usageSpec, cipher_.hmacKey)) {
1209 DLP_LOG_ERROR(LABEL, "params is error");
1210 return DLP_PARSE_ERROR_VALUE_INVALID;
1211 }
1212 if (isZip_) {
1213 head_.txtOffset = 0;
1214 if (hmac_.size != 0) {
1215 CleanBlobParam(hmac_);
1216 }
1217 return GenFileInZip(inPlainFileFd);
1218 } else {
1219 return GenFileInRaw(inPlainFileFd);
1220 }
1221 }
1222
RemoveDlpPermissionInZip(int32_t outPlainFileFd)1223 int32_t DlpFile::RemoveDlpPermissionInZip(int32_t outPlainFileFd)
1224 {
1225 std::lock_guard<std::mutex> lock(g_fileOpLock_);
1226 char cwd[DLP_CWD_MAX] = {0};
1227 GETCWD_AND_CHECK(cwd, DLP_CWD_MAX, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1228 Defer p(nullptr, [&](...) {
1229 if (chdir(cwd) != 0) {
1230 DLP_LOG_ERROR(LABEL, "chdir failed, %{public}s", strerror(errno));
1231 }
1232 });
1233
1234 CHDIR_AND_CHECK(workDir_.c_str(), DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1235 CHDIR_AND_CHECK(dirIndex_.c_str(), DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1236
1237 int32_t encFd = open(DLP_OPENING_ENC_DATA.c_str(), O_RDWR, S_IRUSR | S_IWUSR);
1238 Defer p2(nullptr, [&](...) {
1239 if (close(encFd) != 0) {
1240 DLP_LOG_ERROR(LABEL, "close failed, %{public}s", strerror(errno));
1241 }
1242 });
1243
1244 int32_t fileSize = GetFileSize(encFd);
1245 int32_t ret = DoDlpContentCryptyOperation(encFd, outPlainFileFd, 0, fileSize, false);
1246 CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
1247
1248 return DLP_OK;
1249 }
1250
RemoveDlpPermissionInRaw(int32_t outPlainFileFd)1251 int32_t DlpFile::RemoveDlpPermissionInRaw(int32_t outPlainFileFd)
1252 {
1253 off_t fileLen = lseek(dlpFd_, 0, SEEK_END);
1254 if (fileLen == static_cast<off_t>(-1) || fileLen > static_cast<off_t>(DLP_MAX_CONTENT_SIZE)) {
1255 DLP_LOG_ERROR(LABEL, "can not get dlp file len, %{public}s", strerror(errno));
1256 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1257 }
1258
1259 // clean plainTxtFile
1260 if (ftruncate(outPlainFileFd, 0) == -1) {
1261 DLP_LOG_ERROR(LABEL, "truncate plain file to zero failed, %{public}s", strerror(errno));
1262 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1263 }
1264
1265 if (lseek(outPlainFileFd, 0, SEEK_SET) == static_cast<off_t>(-1)) {
1266 DLP_LOG_ERROR(LABEL, "seek plain file start failed, %{public}s", strerror(errno));
1267 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1268 }
1269
1270 if (lseek(dlpFd_, head_.txtOffset, SEEK_SET) == static_cast<off_t>(-1)) {
1271 DLP_LOG_ERROR(LABEL, "seek dlp file start failed, %{public}s", strerror(errno));
1272 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1273 }
1274
1275 if (fileLen == head_.txtOffset) {
1276 DLP_LOG_INFO(LABEL, "Dlp file have no content");
1277 return DLP_OK;
1278 }
1279
1280 return DoDlpContentCryptyOperation(dlpFd_, outPlainFileFd, head_.txtOffset, fileLen, false);
1281 }
1282
RemoveDlpPermission(int32_t outPlainFileFd)1283 int32_t DlpFile::RemoveDlpPermission(int32_t outPlainFileFd)
1284 {
1285 if (isFuseLink_) {
1286 DLP_LOG_ERROR(LABEL, "current dlp file is linking, do not operate it.");
1287 return DLP_PARSE_ERROR_FILE_LINKING;
1288 }
1289
1290 if (authPerm_ != FULL_CONTROL) {
1291 DLP_LOG_ERROR(LABEL, "check permission fail, remove dlp permission failed.");
1292 return DLP_PARSE_ERROR_FILE_READ_ONLY;
1293 }
1294
1295 if (outPlainFileFd < 0 || dlpFd_ < 0) {
1296 DLP_LOG_ERROR(LABEL, "fd is invalid");
1297 return DLP_PARSE_ERROR_FD_ERROR;
1298 }
1299
1300 if (!IsValidCipher(cipher_.encKey, cipher_.usageSpec, cipher_.hmacKey)) {
1301 DLP_LOG_ERROR(LABEL, "cipher params is invalid");
1302 return DLP_PARSE_ERROR_CIPHER_PARAMS_INVALID;
1303 }
1304
1305 if (isZip_) {
1306 return RemoveDlpPermissionInZip(outPlainFileFd);
1307 } else {
1308 return RemoveDlpPermissionInRaw(outPlainFileFd);
1309 }
1310 }
1311
DlpFileRead(uint32_t offset,void * buf,uint32_t size,bool & hasRead,int32_t uid)1312 int32_t DlpFile::DlpFileRead(uint32_t offset, void* buf, uint32_t size, bool& hasRead, int32_t uid)
1313 {
1314 int32_t opFd = isZip_ ? encDataFd_ : dlpFd_;
1315 if (buf == nullptr || size == 0 || size > DLP_FUSE_MAX_BUFFLEN ||
1316 (offset >= DLP_MAX_CONTENT_SIZE - size) ||
1317 opFd < 0 || !IsValidCipher(cipher_.encKey, cipher_.usageSpec, cipher_.hmacKey)) {
1318 DLP_LOG_ERROR(LABEL, "params is error");
1319 return DLP_PARSE_ERROR_VALUE_INVALID;
1320 }
1321
1322 uint32_t alignOffset = (offset / DLP_BLOCK_SIZE) * DLP_BLOCK_SIZE;
1323 uint32_t prefixingSize = offset - alignOffset;
1324 uint32_t alignSize = size + prefixingSize;
1325
1326 if (lseek(opFd, head_.txtOffset + alignOffset, SEEK_SET) == -1) {
1327 DLP_LOG_ERROR(LABEL, "lseek dlp file failed. %{public}s", strerror(errno));
1328 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1329 }
1330
1331 auto encBuff = std::make_unique<uint8_t[]>(alignSize);
1332 auto outBuff = std::make_unique<uint8_t[]>(alignSize);
1333
1334 int32_t readLen = read(opFd, encBuff.get(), alignSize);
1335 if (readLen == -1) {
1336 DLP_LOG_ERROR(LABEL, "read buff fail, %{public}s", strerror(errno));
1337 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1338 }
1339 if (readLen <= static_cast<int32_t>(prefixingSize)) {
1340 return 0;
1341 }
1342
1343 struct DlpBlob message1 = {.size = readLen, .data = encBuff.get()};
1344 struct DlpBlob message2 = {.size = readLen, .data = outBuff.get()};
1345 if (DoDlpBlockCryptOperation(message1, message2, alignOffset, false) != DLP_OK) {
1346 DLP_LOG_ERROR(LABEL, "decrypt fail");
1347 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1348 }
1349
1350 if (memcpy_s(buf, size, outBuff.get() + prefixingSize, message2.size - prefixingSize) != EOK) {
1351 DLP_LOG_ERROR(LABEL, "copy decrypt result failed");
1352 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
1353 }
1354 if (hasRead) {
1355 return message2.size - prefixingSize;
1356 }
1357 int32_t res = DlpPermissionKit::SetReadFlag(uid);
1358 if (res != DLP_OK) {
1359 return res;
1360 }
1361 hasRead = true;
1362 return message2.size - prefixingSize;
1363 }
1364
WriteFirstBlockData(uint32_t offset,void * buf,uint32_t size)1365 int32_t DlpFile::WriteFirstBlockData(uint32_t offset, void* buf, uint32_t size)
1366 {
1367 uint32_t alignOffset = (offset / DLP_BLOCK_SIZE) * DLP_BLOCK_SIZE;
1368 uint32_t prefixingSize = offset % DLP_BLOCK_SIZE;
1369 uint32_t requestSize = (size < (DLP_BLOCK_SIZE - prefixingSize)) ? size : (DLP_BLOCK_SIZE - prefixingSize);
1370 uint32_t writtenSize = prefixingSize + requestSize;
1371 uint8_t enBuf[DLP_BLOCK_SIZE] = {0};
1372 uint8_t deBuf[DLP_BLOCK_SIZE] = {0};
1373 int32_t opFd = isZip_ ? encDataFd_ : dlpFd_;
1374
1375 do {
1376 if (prefixingSize == 0) {
1377 break;
1378 }
1379 int32_t readLen = read(opFd, enBuf, prefixingSize);
1380 if (readLen == -1) {
1381 DLP_LOG_ERROR(LABEL, "read first block prefixing fail, %{public}s", strerror(errno));
1382 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1383 }
1384 if (readLen == 0) {
1385 break;
1386 }
1387
1388 struct DlpBlob message1 = {.size = prefixingSize, .data = enBuf};
1389 struct DlpBlob message2 = {.size = prefixingSize, .data = deBuf};
1390 if (DoDlpBlockCryptOperation(message1, message2, alignOffset, false) != DLP_OK) {
1391 DLP_LOG_ERROR(LABEL, "decrypt appending bytes fail, %{public}s", strerror(errno));
1392 return DLP_PARSE_ERROR_CRYPT_FAIL;
1393 }
1394 } while (false);
1395
1396 if (memcpy_s(deBuf + prefixingSize, DLP_BLOCK_SIZE - prefixingSize, buf, requestSize) != EOK) {
1397 DLP_LOG_ERROR(LABEL, "copy write buffer first block failed, %{public}s", strerror(errno));
1398 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
1399 }
1400
1401 struct DlpBlob message1 = {.size = writtenSize, .data = deBuf};
1402 struct DlpBlob message2 = {.size = writtenSize, .data = enBuf};
1403 if (DoDlpBlockCryptOperation(message1, message2, alignOffset, true) != DLP_OK) {
1404 DLP_LOG_ERROR(LABEL, "enrypt first block fail");
1405 return DLP_PARSE_ERROR_CRYPT_FAIL;
1406 }
1407
1408 if (lseek(opFd, head_.txtOffset + alignOffset, SEEK_SET) == static_cast<off_t>(-1)) {
1409 DLP_LOG_ERROR(LABEL, "lseek failed, %{public}s", strerror(errno));
1410 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1411 }
1412
1413 if (write(opFd, enBuf, writtenSize) != (ssize_t)writtenSize) {
1414 DLP_LOG_ERROR(LABEL, "write failed, %{public}s", strerror(errno));
1415 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1416 }
1417 return requestSize;
1418 }
1419
DoDlpFileWrite(uint32_t offset,void * buf,uint32_t size)1420 int32_t DlpFile::DoDlpFileWrite(uint32_t offset, void* buf, uint32_t size)
1421 {
1422 int32_t opFd = isZip_ ? encDataFd_ : dlpFd_;
1423 uint32_t alignOffset = (offset / DLP_BLOCK_SIZE * DLP_BLOCK_SIZE);
1424 if (lseek(opFd, head_.txtOffset + alignOffset, SEEK_SET) == static_cast<off_t>(-1)) {
1425 DLP_LOG_ERROR(LABEL, "lseek dlp file offset %{public}d failed, %{public}s",
1426 head_.txtOffset + offset, strerror(errno));
1427 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1428 }
1429
1430 /* write first block data, if it may be not aligned */
1431 int32_t writenSize = WriteFirstBlockData(offset, static_cast<uint8_t *>(buf), size);
1432 if (writenSize < 0) {
1433 DLP_LOG_ERROR(LABEL, "encrypt prefix data failed");
1434 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1435 }
1436 if (static_cast<uint32_t>(writenSize) >= size) {
1437 return writenSize;
1438 }
1439
1440 uint8_t *restBlocksPtr = static_cast<uint8_t *>(buf) + writenSize;
1441 uint32_t restBlocksSize = size - static_cast<uint32_t>(writenSize);
1442 uint8_t* writeBuff = new (std::nothrow) uint8_t[restBlocksSize]();
1443 if (writeBuff == nullptr) {
1444 DLP_LOG_ERROR(LABEL, "alloc write buffer fail");
1445 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
1446 }
1447
1448 /* first aligned block has been writen, write the rest */
1449 struct DlpBlob message1 = {.size = restBlocksSize, .data = restBlocksPtr};
1450 struct DlpBlob message2 = {.size = restBlocksSize, .data = writeBuff};
1451
1452 int32_t ret = DoDlpBlockCryptOperation(message1, message2, alignOffset + DLP_BLOCK_SIZE, true);
1453 if (ret != DLP_OK) {
1454 DLP_LOG_ERROR(LABEL, "encrypt write buffer fail");
1455 delete[] writeBuff;
1456 return ret;
1457 }
1458
1459 ret = write(opFd, writeBuff, restBlocksSize);
1460 delete[] writeBuff;
1461 if (ret <= 0) {
1462 DLP_LOG_ERROR(LABEL, "write buff failed, %{public}s", strerror(errno));
1463 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1464 }
1465
1466 return ret + static_cast<int32_t>(writenSize);
1467 }
1468
GetFsContentSize() const1469 uint32_t DlpFile::GetFsContentSize() const
1470 {
1471 struct stat fileStat;
1472 int32_t opFd = isZip_ ? encDataFd_ : dlpFd_;
1473 int32_t ret = fstat(opFd, &fileStat);
1474 if (ret != 0) {
1475 DLP_LOG_ERROR(LABEL, "fstat error %{public}d , errno %{public}d dlpfd: %{public}d ", ret, errno, opFd);
1476 return INVALID_FILE_SIZE;
1477 }
1478 if (head_.txtOffset > fileStat.st_size || fileStat.st_size >= static_cast<off_t>(INVALID_FILE_SIZE)) {
1479 DLP_LOG_ERROR(LABEL, "size error %{public}d %{public}d", head_.txtOffset,
1480 static_cast<uint32_t>(fileStat.st_size));
1481 return INVALID_FILE_SIZE;
1482 }
1483 if (static_cast<uint32_t>(fileStat.st_size) - head_.txtOffset == 0) {
1484 DLP_LOG_ERROR(LABEL, "linkFile size %{public}d %{public}d", static_cast<uint32_t>(fileStat.st_size),
1485 head_.txtOffset);
1486 }
1487 return static_cast<uint32_t>(fileStat.st_size) - head_.txtOffset;
1488 }
1489
UpdateDlpFileContentSize()1490 int32_t DlpFile::UpdateDlpFileContentSize()
1491 {
1492 uint32_t contentSize = GetFsContentSize();
1493 if (contentSize == INVALID_FILE_SIZE) {
1494 DLP_LOG_ERROR(LABEL, "get fs content size failed");
1495 return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
1496 }
1497 head_.txtSize = contentSize;
1498 DLP_LOG_DEBUG(LABEL, "Update dlp file content size");
1499
1500 if (isZip_ == false) {
1501 if (lseek(dlpFd_, 0, SEEK_SET) == static_cast<off_t>(-1)) {
1502 DLP_LOG_ERROR(LABEL, "Lseek failed, %{public}s", strerror(errno));
1503 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1504 }
1505
1506 if (write(dlpFd_, &head_, sizeof(head_)) != sizeof(head_)) {
1507 DLP_LOG_ERROR(LABEL, "Write failed, %{public}s", strerror(errno));
1508 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1509 }
1510 }
1511
1512 return DLP_OK;
1513 }
1514
FillHoleData(uint32_t holeStart,uint32_t holeSize)1515 int32_t DlpFile::FillHoleData(uint32_t holeStart, uint32_t holeSize)
1516 {
1517 DLP_LOG_INFO(LABEL, "Need create a hole filled with 0s, hole start %{public}x size %{public}x",
1518 holeStart, holeSize);
1519 uint32_t holeBufSize = (holeSize < HOLE_BUFF_SMALL_SIZE) ? HOLE_BUFF_SMALL_SIZE : HOLE_BUFF_SIZE;
1520 std::unique_ptr<uint8_t[]> holeBuff(new (std::nothrow) uint8_t[holeBufSize]());
1521 if (holeBuff == nullptr) {
1522 DLP_LOG_ERROR(LABEL, "New buf failed.");
1523 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
1524 }
1525
1526 uint32_t fillLen = 0;
1527 while (fillLen < holeSize) {
1528 uint32_t writeSize = ((holeSize - fillLen) < holeBufSize) ? (holeSize - fillLen) : holeBufSize;
1529 int32_t res = DoDlpFileWrite(holeStart + fillLen, holeBuff.get(), writeSize);
1530 if (res < 0) {
1531 DLP_LOG_ERROR(LABEL, "Write failed, error %{public}d.", res);
1532 return res;
1533 }
1534 fillLen += writeSize;
1535 }
1536 return DLP_OK;
1537 }
1538
DlpFileWrite(uint32_t offset,void * buf,uint32_t size)1539 int32_t DlpFile::DlpFileWrite(uint32_t offset, void* buf, uint32_t size)
1540 {
1541 if (authPerm_ == READ_ONLY) {
1542 DLP_LOG_ERROR(LABEL, "Dlp file is readonly, write failed");
1543 return DLP_PARSE_ERROR_FILE_READ_ONLY;
1544 }
1545 int32_t opFd = isZip_ ? encDataFd_ : dlpFd_;
1546 if (buf == nullptr || size == 0 || size > DLP_FUSE_MAX_BUFFLEN ||
1547 (offset >= DLP_MAX_CONTENT_SIZE - size) ||
1548 opFd < 0 || !IsValidCipher(cipher_.encKey, cipher_.usageSpec, cipher_.hmacKey)) {
1549 DLP_LOG_ERROR(LABEL, "Dlp file param invalid");
1550 return DLP_PARSE_ERROR_VALUE_INVALID;
1551 }
1552
1553 uint32_t curSize = GetFsContentSize();
1554 if (curSize != INVALID_FILE_SIZE && curSize < offset &&
1555 (FillHoleData(curSize, offset - curSize) != DLP_OK)) {
1556 DLP_LOG_ERROR(LABEL, "Fill hole data failed");
1557 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1558 }
1559 int32_t res = DoDlpFileWrite(offset, buf, size);
1560 UpdateDlpFileContentSize();
1561
1562 // modify dlp file, clear old hmac value and will generate new
1563 if (hmac_.size != 0) {
1564 CleanBlobParam(hmac_);
1565 }
1566 GenFileInZip(-1);
1567 return res;
1568 }
1569
Truncate(uint32_t size)1570 int32_t DlpFile::Truncate(uint32_t size)
1571 {
1572 DLP_LOG_INFO(LABEL, "Truncate file size %{public}u", size);
1573
1574 if (authPerm_ == READ_ONLY) {
1575 DLP_LOG_ERROR(LABEL, "Dlp file is readonly, truncate failed");
1576 return DLP_PARSE_ERROR_FILE_READ_ONLY;
1577 }
1578 int32_t opFd = isZip_ ? encDataFd_ : dlpFd_;
1579 if (opFd < 0 || size >= DLP_MAX_CONTENT_SIZE) {
1580 DLP_LOG_ERROR(LABEL, "Param invalid");
1581 return DLP_PARSE_ERROR_VALUE_INVALID;
1582 }
1583
1584 uint32_t curSize = GetFsContentSize();
1585 int32_t res = DLP_OK;
1586 if (size < curSize) {
1587 res = ftruncate(opFd, head_.txtOffset + size);
1588 UpdateDlpFileContentSize();
1589 GenFileInZip(-1);
1590 } else if (size > curSize) {
1591 res = FillHoleData(curSize, size - curSize);
1592 UpdateDlpFileContentSize();
1593 GenFileInZip(-1);
1594 } else {
1595 DLP_LOG_INFO(LABEL, "Truncate file size equals origin file");
1596 }
1597
1598 if (res != DLP_OK) {
1599 DLP_LOG_ERROR(LABEL, "Truncate file size %{public}u failed, %{public}s", size, strerror(errno));
1600 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1601 }
1602 return DLP_OK;
1603 }
1604
HmacCheck()1605 int32_t DlpFile::HmacCheck()
1606 {
1607 DLP_LOG_DEBUG(LABEL, "start HmacCheck, dlpVersion = %{public}d", head_.version);
1608 if (head_.version < HMAC_VERSION) {
1609 DLP_LOG_INFO(LABEL, "no hmac check");
1610 return DLP_OK;
1611 }
1612
1613 uint8_t* outBuf = new (std::nothrow) uint8_t[HMAC_SIZE];
1614 if (outBuf == nullptr) {
1615 DLP_LOG_ERROR(LABEL, "New memory fail");
1616 return DLP_SERVICE_ERROR_MEMORY_OPERATE_FAIL;
1617 }
1618 struct DlpBlob out = {
1619 .size = HMAC_SIZE,
1620 .data = outBuf,
1621 };
1622 int ret = GenerateHmacVal(encDataFd_, out);
1623 if (ret != DLP_OK) {
1624 CleanBlobParam(out);
1625 return ret;
1626 }
1627
1628 if (out.size == 0 || (out.size == hmac_.size && memcmp(hmac_.data, out.data, out.size) == 0)) {
1629 DLP_LOG_INFO(LABEL, "verify success");
1630 if (out.size != 0) {
1631 CleanBlobParam(out);
1632 }
1633 return DLP_OK;
1634 }
1635 DLP_LOG_ERROR(LABEL, "verify fail");
1636 CleanBlobParam(out);
1637 return DLP_PARSE_ERROR_FILE_VERIFICATION_FAIL;
1638 }
1639 } // namespace DlpPermission
1640 } // namespace Security
1641 } // namespace OHOS
1642