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