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