• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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_raw_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_utils.h"
31 #include "hex_string.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, "DlpRawFile"};
43 const uint32_t FILE_HEAD = 8;
44 const uint32_t HMAC_SIZE = 32;
45 const uint32_t MAX_CERT_SIZE = 30 * 1024;
46 const std::string DEFAULT_STRINGS = "";
47 } // namespace
48 
49 static int32_t GetFileSize(int32_t fd, uint64_t& fileLen);
50 
DlpRawFile(int32_t dlpFd,const std::string & realType)51 DlpRawFile::DlpRawFile(int32_t dlpFd, const std::string &realType) : DlpFile(dlpFd, realType)
52 {
53     head_.magic = DLP_FILE_MAGIC;
54     head_.fileType = 0;
55     head_.offlineAccess = 0;
56     head_.algType = DLP_MODE_CTR;
57     head_.txtOffset = INVALID_FILE_SIZE;
58     head_.txtSize = 0;
59     head_.hmacOffset = INVALID_FILE_SIZE;
60     head_.hmacSize = 0;
61     head_.certOffset = INVALID_FILE_SIZE;
62     head_.certSize = 0;
63     head_.contactAccountOffset = 0;
64     head_.contactAccountSize = 0;
65     head_.offlineCertOffset = INVALID_FILE_SIZE;
66     head_.offlineCertSize = 0;
67 }
68 
~DlpRawFile()69 DlpRawFile::~DlpRawFile()
70 {
71     // clear key
72     if (cipher_.encKey.data != nullptr) {
73         (void)memset_s(cipher_.encKey.data, cipher_.encKey.size, 0, cipher_.encKey.size);
74         delete[] cipher_.encKey.data;
75         cipher_.encKey.data = nullptr;
76     }
77 
78     // clear iv
79     if (cipher_.tagIv.iv.data != nullptr) {
80         (void)memset_s(cipher_.tagIv.iv.data, cipher_.tagIv.iv.size, 0, cipher_.tagIv.iv.size);
81         delete[] cipher_.tagIv.iv.data;
82         cipher_.tagIv.iv.data = nullptr;
83     }
84 
85     // clear encrypt cert
86     if (cert_.data != nullptr) {
87         (void)memset_s(cert_.data, cert_.size, 0, cert_.size);
88         delete[] cert_.data;
89         cert_.data = nullptr;
90     }
91 
92     if (offlineCert_.data != nullptr) {
93         (void)memset_s(offlineCert_.data, head_.offlineCertSize, 0, head_.offlineCertSize);
94         delete[] offlineCert_.data;
95         offlineCert_.data = nullptr;
96     }
97 
98     // clear hmacKey
99     if (cipher_.hmacKey.data != nullptr) {
100         (void)memset_s(cipher_.hmacKey.data, cipher_.hmacKey.size, 0, cipher_.hmacKey.size);
101         delete[] cipher_.hmacKey.data;
102         cipher_.hmacKey.data = nullptr;
103     }
104 
105     // clear hmac_
106     if (hmac_.data != nullptr) {
107         (void)memset_s(hmac_.data, hmac_.size, 0, hmac_.size);
108         delete[] hmac_.data;
109         hmac_.data = nullptr;
110     }
111 
112 #ifdef SUPPORT_DLP_CREDENTIAL
113     if (head_.algType == DLP_MODE_HIAE) {
114         ClearDlpHIAEMgr();
115     }
116 #endif
117 }
118 
SetContactAccount(const std::string & contactAccount)119 int32_t DlpRawFile::SetContactAccount(const std::string& contactAccount)
120 {
121     if (contactAccount.size() == 0 || contactAccount.size() > DLP_MAX_CERT_SIZE) {
122         DLP_LOG_ERROR(LABEL, "contactAccount param failed");
123         return DLP_PARSE_ERROR_VALUE_INVALID;
124     }
125     contactAccount_ = contactAccount;
126     if (head_.certSize != 0) {
127         head_.contactAccountSize = static_cast<uint32_t>(contactAccount.size());
128         head_.txtOffset = head_.contactAccountOffset + head_.contactAccountSize;
129     }
130     return DLP_OK;
131 };
132 
SetOfflineAccess(bool flag)133 void DlpRawFile::SetOfflineAccess(bool flag)
134 {
135     offlineAccess_ = static_cast<uint32_t>(flag);
136     head_.offlineAccess = static_cast<uint32_t>(flag);
137 }
138 
IsValidDlpHeader(const struct DlpHeader & head) const139 bool DlpRawFile::IsValidDlpHeader(const struct DlpHeader& head) const
140 {
141     if (head.magic != DLP_FILE_MAGIC || head.certSize == 0 || head.certSize > MAX_CERT_SIZE ||
142         head.contactAccountSize == 0 || head.contactAccountSize > DLP_MAX_CERT_SIZE ||
143         head.contactAccountOffset != sizeof(struct DlpHeader) + FILE_HEAD ||
144         head.txtOffset != head.contactAccountOffset + head.contactAccountSize ||
145         head.txtSize > DLP_MAX_CONTENT_SIZE || head.hmacOffset != head.txtOffset + head.txtSize ||
146         head.hmacSize != HMAC_SIZE * BYTE_TO_HEX_OPER_LENGTH || head.offlineCertSize > MAX_CERT_SIZE ||
147         !(head.certOffset == head.txtOffset || head.certOffset == head.hmacOffset + head.hmacSize)) {
148         DLP_LOG_ERROR(LABEL, "IsValidDlpHeader error");
149         return false;
150     }
151     return true;
152 }
153 
ParseRawDlpHeader(uint64_t fileLen,uint32_t dlpHeaderSize)154 int32_t DlpRawFile::ParseRawDlpHeader(uint64_t fileLen, uint32_t dlpHeaderSize)
155 {
156     if (fileLen - FILE_HEAD <= dlpHeaderSize || dlpHeaderSize >= DLP_MAX_CERT_SIZE) {
157         DLP_LOG_ERROR(LABEL, "dlp file error");
158         return DLP_PARSE_ERROR_FD_ERROR;
159     }
160 
161     if (read(dlpFd_, &head_, dlpHeaderSize) != dlpHeaderSize) {
162         DLP_LOG_ERROR(LABEL, "can not read dlp file head, %{public}s", strerror(errno));
163         return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
164     }
165     if (!IsValidDlpHeader(head_)) {
166         DLP_LOG_ERROR(LABEL, "file head is error");
167         (void)memset_s(&head_, dlpHeaderSize, 0, dlpHeaderSize);
168         return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
169     }
170 
171     offlineAccess_ = head_.offlineAccess;
172     if (head_.txtSize == 0) {
173         if (fileLen < head_.hmacOffset + head_.certSize) {
174             DLP_LOG_ERROR(LABEL, "file is error");
175             return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
176         }
177     } else if (fileLen < head_.hmacOffset + head_.hmacSize + head_.certSize) {
178         return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
179     }
180     if (version_ > CURRENT_VERSION) {
181         DLP_LOG_ERROR(LABEL, "version_ > CURRENT_VERSION");
182         (void)memset_s(&head_, dlpHeaderSize, 0, dlpHeaderSize);
183         return DLP_PARSE_ERROR_FILE_VERSION_BIGGER_THAN_CURRENT;
184     }
185 #ifdef SUPPORT_DLP_CREDENTIAL
186     if (head_.algType == DLP_MODE_CTR) {
187         DLP_LOG_INFO(LABEL, "support openssl");
188         return DLP_OK;
189     }
190     return InitDlpHIAEMgr();
191 #endif
192     return DLP_OK;
193 }
194 
CheckDlpFile()195 int32_t DlpRawFile::CheckDlpFile()
196 {
197     if (dlpFd_ < 0) {
198         DLP_LOG_ERROR(LABEL, "dlp file fd is invalid");
199         return DLP_PARSE_ERROR_FD_ERROR;
200     }
201 
202     if (isFuseLink_) {
203         DLP_LOG_ERROR(LABEL, "current dlp file is linking, do not operate it.");
204         return DLP_PARSE_ERROR_FILE_LINKING;
205     }
206 
207     if (lseek(dlpFd_, 0, SEEK_SET) == static_cast<off_t>(-1)) {
208         DLP_LOG_ERROR(LABEL, "seek dlp file start failed, %{public}s", strerror(errno));
209         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
210     }
211     uint64_t fileLen = 0;
212     int32_t ret = GetFileSize(dlpFd_, fileLen);
213     CHECK_RET(ret, 0, DLP_PARSE_ERROR_FILE_OPERATE_FAIL, LABEL);
214     if (fileLen <= FILE_HEAD || fileLen > DLP_MAX_RAW_CONTENT_SIZE) {
215         DLP_LOG_ERROR(LABEL, "dlp file error");
216         return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
217     }
218 
219     if (read(dlpFd_, &version_, sizeof(uint32_t)) != sizeof(uint32_t)) {
220         DLP_LOG_ERROR(LABEL, "can not read dlp file version_, %{public}s", strerror(errno));
221         return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
222     }
223     uint32_t dlpHeaderSize = 0;
224 
225     if (read(dlpFd_, &dlpHeaderSize, sizeof(uint32_t)) != sizeof(uint32_t)) {
226         DLP_LOG_ERROR(LABEL, "can not read dlp file dlpHeaderSize, %{public}s", strerror(errno));
227         return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
228     }
229 
230     if (version_ == CURRENT_VERSION && dlpHeaderSize == sizeof(struct DlpHeader)) {
231         return ParseRawDlpHeader(fileLen, dlpHeaderSize);
232     }
233 
234     DLP_LOG_ERROR(LABEL, "the version or HeaderSize is error");
235     return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
236 }
237 
GetOfflineCertSize(void)238 uint32_t DlpRawFile::GetOfflineCertSize(void)
239 {
240     return head_.offlineCertSize;
241 }
242 
GetRawDlpHmac(void)243 int32_t DlpRawFile::GetRawDlpHmac(void)
244 {
245     if (head_.txtSize == 0) {
246         CleanBlobParam(hmac_);
247         return DLP_OK;
248     }
249     (void)lseek(dlpFd_, head_.hmacOffset, SEEK_SET);
250     uint8_t *tempBufHmacStr = new (std::nothrow) uint8_t[head_.hmacSize + 1];
251     if (tempBufHmacStr == nullptr) {
252         DLP_LOG_ERROR(LABEL, "new tempBuf failed");
253         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
254     }
255     (void)memset_s(tempBufHmacStr, head_.hmacSize + 1, 0, head_.hmacSize + 1);
256     if (read(dlpFd_, tempBufHmacStr, head_.hmacSize) != (ssize_t)head_.hmacSize) {
257         DLP_LOG_ERROR(LABEL, "can not read tempBufHmacStr, %{public}s", strerror(errno));
258         delete[] tempBufHmacStr;
259         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
260     }
261 
262     CleanBlobParam(hmac_);
263     hmac_.size = head_.hmacSize / BYTE_TO_HEX_OPER_LENGTH;
264     hmac_.data = new (std::nothrow) uint8_t[hmac_.size];
265     if (hmac_.data == nullptr) {
266         DLP_LOG_ERROR(LABEL, "new hmac size failed");
267         delete[] tempBufHmacStr;
268         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
269     }
270 
271     if (HexStringToByte((char *)tempBufHmacStr, head_.hmacSize, hmac_.data, hmac_.size) != DLP_OK) {
272         delete[] tempBufHmacStr;
273         DLP_LOG_ERROR(LABEL, "HexStringToByte failed");
274         return DLP_SERVICE_ERROR_VALUE_INVALID;
275     }
276 
277     delete[] tempBufHmacStr;
278     return DLP_OK;
279 }
280 
ProcessDlpFile()281 int32_t DlpRawFile::ProcessDlpFile()
282 {
283     int32_t ret = CheckDlpFile();
284     if (ret != DLP_OK) {
285         return ret;
286     }
287     uint8_t* buf = new (std::nothrow)uint8_t[head_.certSize];
288     if (buf == nullptr) {
289         DLP_LOG_WARN(LABEL, "alloc buffer failed.");
290         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
291     }
292     (void)lseek(dlpFd_, head_.certOffset, SEEK_SET);
293     if (read(dlpFd_, buf, head_.certSize) != (ssize_t)head_.certSize) {
294         delete[] buf;
295         DLP_LOG_ERROR(LABEL, "can not read dlp file cert, %{public}s", strerror(errno));
296         return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
297     }
298     CleanBlobParam(cert_);
299     cert_.data = buf;
300     cert_.size = head_.certSize;
301     uint8_t *tmpBuf = new (std::nothrow)uint8_t[head_.contactAccountSize];
302     if (tmpBuf == nullptr) {
303         DLP_LOG_WARN(LABEL, "alloc tmpBuf failed.");
304         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
305     }
306     (void)lseek(dlpFd_, head_.contactAccountOffset, SEEK_SET);
307     if (read(dlpFd_, tmpBuf, head_.contactAccountSize) != (ssize_t)head_.contactAccountSize) {
308         delete[] tmpBuf;
309         DLP_LOG_ERROR(LABEL, "can not read dlp contact account, %{public}s", strerror(errno));
310         return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
311     }
312     contactAccount_ = std::string(tmpBuf, tmpBuf + head_.contactAccountSize);
313     delete[] tmpBuf;
314     if (head_.offlineCertSize != 0 && head_.offlineCertSize == head_.certSize) {
315         tmpBuf = new (std::nothrow)uint8_t[head_.offlineCertSize];
316         if (tmpBuf == nullptr) {
317             DLP_LOG_WARN(LABEL, "alloc tmpBuf failed.");
318             return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
319         }
320         (void)lseek(dlpFd_, head_.offlineCertOffset, SEEK_SET);
321         if (read(dlpFd_, tmpBuf, head_.offlineCertSize) != (ssize_t)head_.offlineCertSize) {
322             delete[] tmpBuf;
323             DLP_LOG_ERROR(LABEL, "can not read dlp offlineCert, %{public}s", strerror(errno));
324             return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
325         }
326         CleanBlobParam(offlineCert_);
327         offlineCert_.data = tmpBuf;
328         offlineCert_.size = head_.offlineCertSize;
329     }
330     return GetRawDlpHmac();
331 }
332 
SetEncryptCert(const struct DlpBlob & cert)333 int32_t DlpRawFile::SetEncryptCert(const struct DlpBlob& cert)
334 {
335     if (cert.data == nullptr || cert.size > DLP_MAX_CERT_SIZE) {
336         DLP_LOG_ERROR(LABEL, "Cert data invalid");
337         return DLP_PARSE_ERROR_VALUE_INVALID;
338     }
339 
340     if (cert_.data != nullptr) {
341         (void)memset_s(cert_.data, cert_.size, 0, cert_.size);
342         delete[] cert_.data;
343         cert_.data = nullptr;
344     }
345 
346     if (CopyBlobParam(cert, cert_) != DLP_OK) {
347         DLP_LOG_ERROR(LABEL, "Cert copy failed");
348         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
349     }
350     head_.contactAccountOffset = sizeof(struct DlpHeader) + FILE_HEAD;
351     head_.certSize = cert_.size;
352     return DLP_OK;
353 }
354 
UpdateCertAndText(const std::vector<uint8_t> & cert,struct DlpBlob certBlob)355 int32_t DlpRawFile::UpdateCertAndText(const std::vector<uint8_t>& cert, struct DlpBlob certBlob)
356 {
357     if (CopyBlobParam(certBlob, cert_) != DLP_OK) {
358         DLP_LOG_ERROR(LABEL, "Cert copy failed");
359         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
360     }
361 
362     // version 1 single file auto convert to version 2 zip file, set version
363     head_.offlineCertSize = cert.size();
364     head_.certSize = cert.size();
365 
366     (void)lseek(dlpFd_, FILE_HEAD, SEEK_SET);
367     if (write(dlpFd_, &head_, sizeof(struct DlpHeader)) != sizeof(struct DlpHeader)) {
368         DLP_LOG_ERROR(LABEL, "write dlp head_ data failed, %{public}s", strerror(errno));
369         if (dlpFd_ != -1 && errno == EBADF) {
370             DLP_LOG_DEBUG(LABEL, "this dlp fd is readonly, unable write.");
371             return DLP_OK;
372         }
373         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
374     }
375 
376     (void)lseek(dlpFd_, head_.offlineCertOffset, SEEK_SET);
377     if (write(dlpFd_, certBlob.data, certBlob.size) != (ssize_t)head_.offlineCertSize) {
378         DLP_LOG_ERROR(LABEL, "write dlp cert data failed, %{public}s", strerror(errno));
379         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
380     }
381     return DLP_OK;
382 }
383 
GetFileSize(int32_t fd,uint64_t & fileLen)384 static int32_t GetFileSize(int32_t fd, uint64_t& fileLen)
385 {
386     int32_t ret = DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
387     off_t readLen = lseek(fd, 0, SEEK_END);
388     if (readLen == static_cast<off_t>(-1) || static_cast<uint64_t>(readLen) > DLP_MAX_RAW_CONTENT_SIZE) {
389         DLP_LOG_ERROR(LABEL, "get file size failed, %{public}s", strerror(errno));
390     } else {
391         fileLen = static_cast<uint64_t>(readLen);
392         ret = DLP_OK;
393     }
394     (void)lseek(fd, 0, SEEK_SET);
395     return ret;
396 }
397 
DoWriteHmacAndCert(uint32_t hmacStrLen,std::string & hmacStr)398 int32_t DlpRawFile::DoWriteHmacAndCert(uint32_t hmacStrLen, std::string& hmacStr)
399 {
400     if (write(dlpFd_, hmacStr.c_str(), hmacStrLen) != static_cast<int32_t>(hmacStrLen)) {
401         DLP_LOG_ERROR(LABEL, "write hmacStr failed, %{public}s", strerror(errno));
402         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
403     }
404     if (write(dlpFd_, cert_.data, head_.certSize) != (ssize_t)head_.certSize) {
405         DLP_LOG_ERROR(LABEL, "write dlp cert data failed, %{public}s", strerror(errno));
406         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
407     }
408     if (MAX_CERT_SIZE < head_.certSize) {
409         DLP_LOG_ERROR(LABEL, "the cert size is error");
410         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
411     }
412     uint8_t* buffer = new (std::nothrow) uint8_t[MAX_CERT_SIZE - head_.certSize];
413     if (buffer == nullptr) {
414         DLP_LOG_ERROR(LABEL, "buffer is nullptr");
415         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
416     }
417     (void)memset_s(buffer, MAX_CERT_SIZE - head_.certSize, 0, MAX_CERT_SIZE - head_.certSize);
418     if (write(dlpFd_, buffer, MAX_CERT_SIZE - head_.certSize) != (ssize_t)(MAX_CERT_SIZE - head_.certSize)) {
419         DLP_LOG_ERROR(LABEL, "write buffer is error");
420         delete[] buffer;
421         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
422     }
423     delete[] buffer;
424     return DLP_OK;
425 }
426 
DoHmacAndCrypty(int32_t inPlainFileFd,off_t fileLen)427 int32_t DlpRawFile::DoHmacAndCrypty(int32_t inPlainFileFd, off_t fileLen)
428 {
429     if (DoDlpContentCryptyOperation(inPlainFileFd, dlpFd_, 0, fileLen, true) != DLP_OK) {
430         DLP_LOG_ERROR(LABEL, "DoDlpContentCryptyOperation error");
431         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
432     }
433     (void)lseek(dlpFd_, head_.txtOffset, SEEK_SET);
434     DLP_LOG_DEBUG(LABEL, "begin DlpHmacEncode");
435     uint8_t* outBuf = new (std::nothrow) uint8_t[HMAC_SIZE];
436     if (outBuf == nullptr) {
437         DLP_LOG_ERROR(LABEL, "New memory fail");
438         return DLP_SERVICE_ERROR_MEMORY_OPERATE_FAIL;
439     }
440     struct DlpBlob out = {
441         .size = HMAC_SIZE,
442         .data = outBuf,
443     };
444     int32_t ret = DlpHmacEncode(cipher_.hmacKey, dlpFd_, out);
445     if (ret != DLP_OK) {
446         DLP_LOG_ERROR(LABEL, "DlpHmacEncode fail: %{public}d", ret);
447         CleanBlobParam(out);
448         return ret;
449     }
450     hmac_.size = out.size;
451     hmac_.data = out.data;
452     uint32_t hmacHexLen = hmac_.size * BYTE_TO_HEX_OPER_LENGTH + 1;
453     char* hmacHex = new (std::nothrow) char[hmacHexLen];
454     if (hmacHex == nullptr) {
455         DLP_LOG_ERROR(LABEL, "New memory fail");
456         return DLP_SERVICE_ERROR_MEMORY_OPERATE_FAIL;
457     }
458     ret = ByteToHexString(hmac_.data, hmac_.size, hmacHex, hmacHexLen);
459     if (ret != DLP_OK) {
460         DLP_LOG_ERROR(LABEL, "ByteToHexString error");
461         FreeCharBuffer(hmacHex, hmacHexLen);
462         return ret;
463     }
464     std::string hmacStr = hmacHex;
465     FreeCharBuffer(hmacHex, hmacHexLen);
466     uint32_t hmacStrLen = hmacStr.size();
467     (void)lseek(dlpFd_, head_.hmacOffset, SEEK_SET);
468     return DoWriteHmacAndCert(hmacStrLen, hmacStr);
469 }
470 
DoWriteHeaderAndContactAccount(int32_t inPlainFileFd,uint64_t fileLen)471 int32_t DlpRawFile::DoWriteHeaderAndContactAccount(int32_t inPlainFileFd, uint64_t fileLen)
472 {
473     if (write(dlpFd_, &head_, sizeof(struct DlpHeader)) != sizeof(struct DlpHeader)) {
474         DLP_LOG_ERROR(LABEL, "write dlp head failed, %{public}s", strerror(errno));
475         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
476     }
477 
478     if (write(dlpFd_, contactAccount_.c_str(), contactAccount_.size()) !=
479         static_cast<int32_t>(contactAccount_.size())) {
480         DLP_LOG_ERROR(LABEL, "write dlp contact data failed, %{public}s", strerror(errno));
481         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
482     }
483 
484     if (head_.txtSize == 0) {
485         DLP_LOG_INFO(LABEL, "Plaintext file len is 0, do not need encrypt");
486         if (write(dlpFd_, cert_.data, head_.certSize) != (ssize_t)head_.certSize) {
487             DLP_LOG_ERROR(LABEL, "write dlp cert data failed, %{public}s", strerror(errno));
488             return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
489         }
490         return DLP_OK;
491     }
492     DLP_LOG_DEBUG(LABEL, "begin DoHmacAndCrypty");
493     return DoHmacAndCrypty(inPlainFileFd, fileLen);
494 }
495 
GenFileInRaw(int32_t inPlainFileFd)496 int32_t DlpRawFile::GenFileInRaw(int32_t inPlainFileFd)
497 {
498     off_t fileLen = lseek(inPlainFileFd, 0, SEEK_END);
499     head_.txtSize = static_cast<uint64_t>(fileLen);
500     if (fileLen == 0) {
501         head_.hmacOffset = head_.txtOffset + head_.txtSize;
502         head_.hmacSize = 0;
503         head_.certOffset = head_.hmacOffset + head_.hmacSize;
504         head_.offlineCertOffset = head_.hmacOffset + head_.hmacSize;
505     } else {
506         head_.hmacOffset = head_.txtOffset + head_.txtSize;
507         head_.hmacSize = HMAC_SIZE * BYTE_TO_HEX_OPER_LENGTH;
508         head_.certOffset = head_.hmacOffset + head_.hmacSize;
509         head_.offlineCertOffset = head_.hmacOffset + head_.hmacSize;
510     }
511     DLP_LOG_DEBUG(LABEL, "fileLen %{public}s", std::to_string(head_.txtSize).c_str());
512     auto iter = TYPE_TO_NUM_MAP.find(realType_);
513     if (iter != TYPE_TO_NUM_MAP.end()) {
514         head_.fileType = iter->second;
515     } else {
516         DLP_LOG_DEBUG(LABEL, "find %{public}s type fail", realType_.c_str());
517         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
518     }
519     // clean dlpFile
520     if (ftruncate(dlpFd_, 0) == -1) {
521         DLP_LOG_ERROR(LABEL, "truncate dlp file to zero failed, %{public}s", strerror(errno));
522         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
523     }
524 
525     if (lseek(inPlainFileFd, 0, SEEK_SET) == static_cast<off_t>(-1)) {
526         DLP_LOG_ERROR(LABEL, "seek plain file start failed, %{public}s", strerror(errno));
527         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
528     }
529 
530     if (lseek(dlpFd_, 0, SEEK_SET) == static_cast<off_t>(-1)) {
531         DLP_LOG_ERROR(LABEL, "seek dlp file start failed, %{public}s", strerror(errno));
532         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
533     }
534 
535     if (write(dlpFd_, &version_, sizeof(uint32_t)) != sizeof(uint32_t)) {
536         DLP_LOG_ERROR(LABEL, "write dlp dlpHeaderSize failed, %{public}s", strerror(errno));
537         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
538     }
539     uint32_t dlpHeaderSize = sizeof(struct DlpHeader);
540     if (write(dlpFd_, &dlpHeaderSize, sizeof(uint32_t)) != sizeof(uint32_t)) {
541         DLP_LOG_ERROR(LABEL, "write dlp dlpHeaderSize failed, %{public}s", strerror(errno));
542         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
543     }
544     return DoWriteHeaderAndContactAccount(inPlainFileFd, head_.txtSize);
545 }
546 
GenFile(int32_t inPlainFileFd)547 int32_t DlpRawFile::GenFile(int32_t inPlainFileFd)
548 {
549     if (inPlainFileFd < 0 || dlpFd_ < 0 || !IsValidCipher(cipher_.encKey, cipher_.usageSpec, cipher_.hmacKey)) {
550         DLP_LOG_ERROR(LABEL, "params is error");
551         return DLP_PARSE_ERROR_VALUE_INVALID;
552     }
553 
554     int32_t result = setAlgType(inPlainFileFd, realType_);
555     if (result != DLP_OK) {
556         DLP_LOG_ERROR(LABEL, "setAlgType fail, errno=%{public}d", result);
557         return result;
558     }
559 
560     return GenFileInRaw(inPlainFileFd);
561 }
562 
RemoveDlpPermissionInRaw(int32_t outPlainFileFd)563 int32_t DlpRawFile::RemoveDlpPermissionInRaw(int32_t outPlainFileFd)
564 {
565     off_t fileLen = lseek(dlpFd_, 0, SEEK_END);
566     if (fileLen == static_cast<off_t>(-1) || fileLen > static_cast<off_t>(DLP_MAX_RAW_CONTENT_SIZE)) {
567         DLP_LOG_ERROR(LABEL, "can not get dlp file len, %{public}s", strerror(errno));
568         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
569     }
570 
571     // clean plainTxtFile
572     if (ftruncate(outPlainFileFd, 0) == -1) {
573         DLP_LOG_ERROR(LABEL, "truncate plain file to zero failed, %{public}s", strerror(errno));
574         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
575     }
576 
577     if (lseek(outPlainFileFd, 0, SEEK_SET) == static_cast<off_t>(-1)) {
578         DLP_LOG_ERROR(LABEL, "seek plain file start failed, %{public}s", strerror(errno));
579         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
580     }
581 
582     if (lseek(dlpFd_, head_.txtOffset, SEEK_SET) == static_cast<off_t>(-1)) {
583         DLP_LOG_ERROR(LABEL, "seek dlp file start failed, %{public}s", strerror(errno));
584         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
585     }
586 
587     if (fileLen == static_cast<off_t>(head_.txtOffset)) {
588         DLP_LOG_INFO(LABEL, "Dlp file have no content");
589         return DLP_OK;
590     }
591 
592     return DoDlpContentCryptyOperation(dlpFd_, outPlainFileFd, head_.txtOffset, head_.txtSize, false);
593 }
594 
RemoveDlpPermission(int32_t outPlainFileFd)595 int32_t DlpRawFile::RemoveDlpPermission(int32_t outPlainFileFd)
596 {
597     if (isFuseLink_) {
598         DLP_LOG_ERROR(LABEL, "current dlp file is linking, do not operate it.");
599         return DLP_PARSE_ERROR_FILE_LINKING;
600     }
601 
602     if (authPerm_ != DLPFileAccess::FULL_CONTROL) {
603         DLP_LOG_ERROR(LABEL, "check permission fail, remove dlp permission failed.");
604         return DLP_PARSE_ERROR_FILE_READ_ONLY;
605     }
606 
607     if (outPlainFileFd < 0 || dlpFd_ < 0) {
608         DLP_LOG_ERROR(LABEL, "fd is invalid");
609         return DLP_PARSE_ERROR_FD_ERROR;
610     }
611 
612     if (!IsValidCipher(cipher_.encKey, cipher_.usageSpec, cipher_.hmacKey)) {
613         DLP_LOG_ERROR(LABEL, "cipher params is invalid");
614         return DLP_PARSE_ERROR_CIPHER_PARAMS_INVALID;
615     }
616 
617     return RemoveDlpPermissionInRaw(outPlainFileFd);
618 }
619 
DlpFileRead(uint64_t offset,void * buf,uint32_t size,bool & hasRead,int32_t uid)620 int32_t DlpRawFile::DlpFileRead(uint64_t offset, void* buf, uint32_t size, bool& hasRead, int32_t uid)
621 {
622     int32_t opFd = dlpFd_;
623     if (buf == nullptr || size == 0 || size > DLP_FUSE_MAX_BUFFLEN || (offset >= DLP_MAX_RAW_CONTENT_SIZE - size) ||
624         opFd < 0 || !IsValidCipher(cipher_.encKey, cipher_.usageSpec, cipher_.hmacKey)) {
625         DLP_LOG_ERROR(LABEL, "params is error");
626         return DLP_PARSE_ERROR_VALUE_INVALID;
627     }
628 
629     uint64_t alignOffset = (offset / DLP_BLOCK_SIZE) * DLP_BLOCK_SIZE;
630     uint64_t prefixingSize = offset - alignOffset;
631     uint64_t alignSize = size + prefixingSize;
632 
633     if (lseek(opFd, head_.txtOffset + alignOffset, SEEK_SET) == -1) {
634         DLP_LOG_ERROR(LABEL, "lseek dlp file failed. %{public}s", strerror(errno));
635         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
636     }
637 
638     auto encBuff = std::make_unique<uint8_t[]>(alignSize);
639     auto outBuff = std::make_unique<uint8_t[]>(alignSize);
640 
641     int32_t readLen = read(opFd, encBuff.get(), alignSize);
642     if (readLen == -1) {
643         DLP_LOG_ERROR(LABEL, "read buff fail, %{public}s", strerror(errno));
644         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
645     }
646     if (readLen <= static_cast<int32_t>(prefixingSize)) {
647         return 0;
648     }
649 
650     struct DlpBlob message1 = {.size = readLen, .data = encBuff.get()};
651     struct DlpBlob message2 = {.size = readLen, .data = outBuff.get()};
652     int32_t res = DLP_OK;
653     if (head_.algType == DLP_MODE_CTR) {
654         res = DoDlpBlockCryptOperation(message1, message2, alignOffset, false);
655     } else {
656         res = DoDlpHIAECryptOperation(message1, message2, alignOffset, false);
657     }
658     if (res != DLP_OK) {
659         DLP_LOG_ERROR(LABEL, "decrypt fail");
660         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
661     }
662 
663     if (memcpy_s(buf, size, outBuff.get() + prefixingSize, message2.size - prefixingSize) != EOK) {
664         DLP_LOG_ERROR(LABEL, "copy decrypt result failed");
665         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
666     }
667     if (hasRead) {
668         return message2.size - prefixingSize;
669     }
670     res = DlpPermissionKit::SetReadFlag(uid);
671     if (res != DLP_OK) {
672         return res;
673     }
674     hasRead = true;
675     return message2.size - prefixingSize;
676 }
677 
GetFsContentSize() const678 uint64_t DlpRawFile::GetFsContentSize() const
679 {
680     struct stat fileStat;
681     int32_t opFd = dlpFd_;
682     int32_t ret = fstat(opFd, &fileStat);
683     if (ret != 0) {
684         DLP_LOG_ERROR(LABEL, "fstat error %{public}d , errno %{public}d dlpfd: %{public}d ", ret, errno, opFd);
685         return INVALID_FILE_SIZE;
686     }
687     if (fileStat.st_size < static_cast<off_t>(head_.txtOffset) ||
688         fileStat.st_size - static_cast<off_t>(head_.txtOffset) <= head_.hmacSize ||
689         fileStat.st_size - static_cast<off_t>(head_.txtOffset) - head_.hmacSize < head_.certSize ||
690         fileStat.st_size > static_cast<off_t>(DLP_MAX_RAW_CONTENT_SIZE)) {
691         DLP_LOG_ERROR(LABEL, "size error %{public}s %{public}s", std::to_string(head_.txtOffset).c_str(),
692             std::to_string(static_cast<uint64_t>(fileStat.st_size)).c_str());
693         return INVALID_FILE_SIZE;
694     }
695 
696     return static_cast<uint64_t>(fileStat.st_size) - head_.txtOffset - head_.hmacSize - MAX_CERT_SIZE;
697 }
698 
UpdateDlpFileContentSize()699 int32_t DlpRawFile::UpdateDlpFileContentSize()
700 {
701     uint64_t contentSize = GetFsContentSize();
702     if (contentSize == INVALID_FILE_SIZE) {
703         DLP_LOG_ERROR(LABEL, "get fs content size failed");
704         return DLP_PARSE_ERROR_FILE_FORMAT_ERROR;
705     }
706     head_.txtSize = contentSize;
707     DLP_LOG_DEBUG(LABEL, "Update dlp file content size");
708 
709     if (lseek(dlpFd_, FILE_HEAD, SEEK_SET) == static_cast<off_t>(-1)) {
710         DLP_LOG_ERROR(LABEL, "Lseek failed, %{public}s", strerror(errno));
711         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
712     }
713 
714     if (write(dlpFd_, &head_, sizeof(head_)) != sizeof(head_)) {
715         DLP_LOG_ERROR(LABEL, "Write failed, %{public}s", strerror(errno));
716         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
717     }
718     return DLP_OK;
719 }
720 
WriteFirstBlockData(uint64_t offset,void * buf,uint32_t size)721 int32_t DlpRawFile::WriteFirstBlockData(uint64_t offset, void* buf, uint32_t size)
722 {
723     uint64_t alignOffset = (offset / DLP_BLOCK_SIZE) * DLP_BLOCK_SIZE;
724     uint32_t prefixingSize = offset % DLP_BLOCK_SIZE;
725     uint32_t requestSize = (size < (DLP_BLOCK_SIZE - prefixingSize)) ? size : (DLP_BLOCK_SIZE - prefixingSize);
726     uint32_t writtenSize = prefixingSize + requestSize;
727     uint8_t enBuf[DLP_BLOCK_SIZE] = {0};
728     uint8_t deBuf[DLP_BLOCK_SIZE] = {0};
729     int32_t opFd = dlpFd_;
730 
731     do {
732         if (prefixingSize == 0) {
733             break;
734         }
735         int32_t readLen = read(opFd, enBuf, prefixingSize);
736         if (readLen == -1) {
737             DLP_LOG_ERROR(LABEL, "read first block prefixing fail, %{public}s", strerror(errno));
738             return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
739         }
740         if (readLen == 0) {
741             break;
742         }
743 
744         struct DlpBlob message1 = {.size = prefixingSize, .data = enBuf};
745         struct DlpBlob message2 = {.size = prefixingSize, .data = deBuf};
746         if (DoDlpBlockCryptOperation(message1, message2, alignOffset, false) != DLP_OK) {
747             DLP_LOG_ERROR(LABEL, "decrypt appending bytes fail, %{public}s", strerror(errno));
748             return DLP_PARSE_ERROR_CRYPT_FAIL;
749         }
750     } while (false);
751 
752     if (memcpy_s(deBuf + prefixingSize, DLP_BLOCK_SIZE - prefixingSize, buf, requestSize) != EOK) {
753         DLP_LOG_ERROR(LABEL, "copy write buffer first block failed, %{public}s", strerror(errno));
754         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
755     }
756 
757     struct DlpBlob message1 = {.size = writtenSize, .data = deBuf};
758     struct DlpBlob message2 = {.size = writtenSize, .data = enBuf};
759     if (DoDlpBlockCryptOperation(message1, message2, alignOffset, true) != DLP_OK) {
760         DLP_LOG_ERROR(LABEL, "enrypt first block fail");
761         return DLP_PARSE_ERROR_CRYPT_FAIL;
762     }
763 
764     if (lseek(opFd, head_.txtOffset + alignOffset, SEEK_SET) == static_cast<off_t>(-1)) {
765         DLP_LOG_ERROR(LABEL, "lseek failed, %{public}s", strerror(errno));
766         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
767     }
768 
769     if (write(opFd, enBuf, writtenSize) != (ssize_t)writtenSize) {
770         DLP_LOG_ERROR(LABEL, "write failed, %{public}s", strerror(errno));
771         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
772     }
773     return requestSize;
774 }
775 
DoDlpFileWrite(uint64_t offset,void * buf,uint32_t size)776 int32_t DlpRawFile::DoDlpFileWrite(uint64_t offset, void* buf, uint32_t size)
777 {
778     int32_t opFd = dlpFd_;
779     uint64_t alignOffset = (offset / DLP_BLOCK_SIZE * DLP_BLOCK_SIZE);
780     if (lseek(opFd, head_.txtOffset + alignOffset, SEEK_SET) == static_cast<off_t>(-1)) {
781         DLP_LOG_ERROR(LABEL, "lseek dlp file offset %{public}s failed, %{public}s",
782             std::to_string(head_.txtOffset + offset).c_str(), strerror(errno));
783         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
784     }
785 
786     /* write first block data, if it may be not aligned */
787     int32_t writenSize = WriteFirstBlockData(offset, static_cast<uint8_t *>(buf), size);
788     if (writenSize < 0) {
789         DLP_LOG_ERROR(LABEL, "encrypt prefix data failed");
790         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
791     }
792     if (static_cast<uint32_t>(writenSize) >= size) {
793         return writenSize;
794     }
795 
796     uint8_t *restBlocksPtr = static_cast<uint8_t *>(buf) + writenSize;
797     uint32_t restBlocksSize = size - static_cast<uint32_t>(writenSize);
798     uint8_t* writeBuff = new (std::nothrow) uint8_t[restBlocksSize]();
799     if (writeBuff == nullptr) {
800         DLP_LOG_ERROR(LABEL, "alloc write buffer fail");
801         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
802     }
803 
804     /* first aligned block has been writen, write the rest */
805     struct DlpBlob message1 = {.size = restBlocksSize, .data = restBlocksPtr};
806     struct DlpBlob message2 = {.size = restBlocksSize, .data = writeBuff};
807 
808     int32_t ret = DoDlpBlockCryptOperation(message1, message2, alignOffset + DLP_BLOCK_SIZE, true);
809     if (ret != DLP_OK) {
810         DLP_LOG_ERROR(LABEL, "encrypt write buffer fail");
811         delete[] writeBuff;
812         return ret;
813     }
814 
815     ret = write(opFd, writeBuff, restBlocksSize);
816     delete[] writeBuff;
817     if (ret <= 0) {
818         DLP_LOG_ERROR(LABEL, "write buff failed, %{public}s", strerror(errno));
819         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
820     }
821 
822     return ret + static_cast<int32_t>(writenSize);
823 }
824 
DlpFileWrite(uint64_t offset,void * buf,uint32_t size)825 int32_t DlpRawFile::DlpFileWrite(uint64_t offset, void* buf, uint32_t size)
826 {
827     if (authPerm_ == DLPFileAccess::READ_ONLY) {
828         DLP_LOG_ERROR(LABEL, "Dlp file is readonly, write failed");
829         return DLP_PARSE_ERROR_FILE_READ_ONLY;
830     }
831     int32_t opFd = dlpFd_;
832     if (buf == nullptr || size == 0 || size > DLP_FUSE_MAX_BUFFLEN ||
833         (offset >= DLP_MAX_RAW_CONTENT_SIZE - size) ||
834         opFd < 0 || !IsValidCipher(cipher_.encKey, cipher_.usageSpec, cipher_.hmacKey)) {
835         DLP_LOG_ERROR(LABEL, "Dlp file param invalid");
836         return DLP_PARSE_ERROR_VALUE_INVALID;
837     }
838 
839     uint64_t curSize = GetFsContentSize();
840     if (curSize != INVALID_FILE_SIZE && curSize < offset &&
841         (FillHoleData(curSize, offset - curSize) != DLP_OK)) {
842         DLP_LOG_ERROR(LABEL, "Fill hole data failed");
843         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
844     }
845     int32_t res = DoDlpFileWrite(offset, buf, size);
846     UpdateDlpFileContentSize();
847 
848     // modify dlp file, clear old hmac value and will generate new
849     if (hmac_.size != 0) {
850         CleanBlobParam(hmac_);
851     }
852     return res;
853 }
854 
Truncate(uint64_t size)855 int32_t DlpRawFile::Truncate(uint64_t size)
856 {
857     DLP_LOG_INFO(LABEL, "Truncate file size %{public}s", std::to_string(size).c_str());
858 
859     if (authPerm_ == DLPFileAccess::READ_ONLY) {
860         DLP_LOG_ERROR(LABEL, "Dlp file is readonly, truncate failed");
861         return DLP_PARSE_ERROR_FILE_READ_ONLY;
862     }
863     int32_t opFd = dlpFd_;
864     if (opFd < 0 || size >= DLP_MAX_CONTENT_SIZE) {
865         DLP_LOG_ERROR(LABEL, "Param invalid");
866         return DLP_PARSE_ERROR_VALUE_INVALID;
867     }
868 
869     uint64_t curSize = GetFsContentSize();
870     int32_t res = DLP_OK;
871     if (size < curSize) {
872         res = ftruncate(opFd, head_.txtOffset + size);
873         UpdateDlpFileContentSize();
874     } else if (size > curSize) {
875         res = FillHoleData(curSize, size - curSize);
876         UpdateDlpFileContentSize();
877     } else {
878         DLP_LOG_INFO(LABEL, "Truncate file size equals origin file");
879     }
880 
881     if (res != DLP_OK) {
882         DLP_LOG_ERROR(LABEL, "Truncate file size %{public}s failed, %{public}s",
883             std::to_string(size).c_str(), strerror(errno));
884         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
885     }
886     return DLP_OK;
887 }
888 
HmacCheck()889 int32_t DlpRawFile::HmacCheck()
890 {
891     DLP_LOG_DEBUG(LABEL, "start HmacCheck, dlpVersion = %{public}d", version_);
892     if (version_ < HMAC_VERSION) {
893         DLP_LOG_INFO(LABEL, "no hmac check");
894         return DLP_OK;
895     }
896 
897     uint8_t* outBuf = new (std::nothrow) uint8_t[HMAC_SIZE];
898     if (outBuf == nullptr) {
899         DLP_LOG_ERROR(LABEL, "New memory fail");
900         return DLP_SERVICE_ERROR_MEMORY_OPERATE_FAIL;
901     }
902     struct DlpBlob out = {
903         .size = HMAC_SIZE,
904         .data = outBuf,
905     };
906 
907     (void)lseek(dlpFd_, head_.txtOffset, SEEK_SET);
908     DLP_LOG_DEBUG(LABEL, "start DlpHmacEncodeForRaw");
909     if (DlpHmacEncodeForRaw(cipher_.hmacKey, dlpFd_, head_.txtSize, out) != DLP_OK) {
910         DLP_LOG_ERROR(LABEL, "DlpHmacEncodeForRaw fail");
911         CleanBlobParam(out);
912         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
913     }
914     DLP_LOG_DEBUG(LABEL, "end DlpHmacEncodeForRaw");
915 
916     if ((out.size == 0 && hmac_.size == 0) ||
917         (out.size == hmac_.size && memcmp(hmac_.data, out.data, out.size) == 0)) {
918         DLP_LOG_INFO(LABEL, "verify success");
919         if (out.size != 0) {
920             CleanBlobParam(out);
921         }
922         return DLP_OK;
923     }
924     DLP_LOG_ERROR(LABEL, "verify fail");
925     CleanBlobParam(out);
926     return DLP_PARSE_ERROR_FILE_VERIFICATION_FAIL;
927 }
928 
setAlgType(int32_t inPlainFileFd,const std::string & realFileType)929 int32_t DlpRawFile::setAlgType(int32_t inPlainFileFd, const std::string& realFileType)
930 {
931     head_.algType = DLP_MODE_CTR;
932     off_t fileLen = lseek(inPlainFileFd, 0, SEEK_END);
933     if (fileLen == static_cast<off_t>(-1)) {
934         DLP_LOG_ERROR(LABEL, "inFd len is invalid, %{public}s", strerror(errno));
935         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
936     }
937 
938     if (lseek(inPlainFileFd, 0, SEEK_SET) == static_cast<off_t>(-1)) {
939         DLP_LOG_ERROR(LABEL, "seek inFd start failed, %{public}s", strerror(errno));
940         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
941     }
942 
943     if (fileLen > static_cast<off_t>(DLP_MIN_HIAE_SIZE) && DlpUtils::GetFileType(realFileType)) {
944         head_.algType = DLP_MODE_HIAE;
945     }
946     return DLP_OK;
947 }
948 
DoDlpHIAECryptOperation(struct DlpBlob & message1,struct DlpBlob & message2,uint64_t offset,bool isEncrypt)949 int32_t DlpRawFile::DoDlpHIAECryptOperation(struct DlpBlob& message1, struct DlpBlob& message2,
950     uint64_t offset, bool isEncrypt)
951 {
952 #ifndef SUPPORT_DLP_CREDENTIAL
953     return DoDlpBlockCryptOperation(message1, message2, offset, isEncrypt);
954 #endif
955 
956     if (offset % DLP_BLOCK_SIZE != 0 || message1.data == nullptr || message1.size == 0
957         ||  message2.data == nullptr || message2.size == 0) {
958         DLP_LOG_ERROR(LABEL, "params is error");
959         return DLP_PARSE_ERROR_VALUE_INVALID;
960     }
961 
962     uint32_t counterIndex = offset / DLP_BLOCK_SIZE;
963     struct DlpUsageSpec spec;
964     if (DupUsageSpec(spec) != DLP_OK) {
965         DLP_LOG_ERROR(LABEL, "spec dup failed");
966         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
967     }
968     DlpCtrModeIncreaeIvCounter(spec.algParam->iv, counterIndex);
969 
970     int32_t ret = DLP_OK;
971     uint32_t blockOffset = 0;
972     uint32_t blockNum = (message1.size + HIAE_BLOCK_SIZE - 1) / HIAE_BLOCK_SIZE;
973     for (uint32_t i = 0; i < blockNum; ++i) {
974         uint64_t blockLen =
975             ((message1.size - blockOffset) < HIAE_BLOCK_SIZE) ? (message1.size - blockOffset) : HIAE_BLOCK_SIZE;
976 
977         ret = isEncrypt ? DlpHIAEEncrypt(&cipher_.encKey, &spec, blockLen,
978             message1.data + blockOffset, message2.data + blockOffset)
979             : DlpHIAEDecrypt(&cipher_.encKey, &spec, blockLen,
980             message1.data + blockOffset, message2.data + blockOffset);
981         if (ret != DLP_OK) {
982             DLP_LOG_ERROR(LABEL, "do HIAE crypt operation failed, ret: %{public}d", ret);
983             break;
984         }
985 
986         DlpCtrModeIncreaeIvCounter(spec.algParam->iv, HIAE_BLOCK_SIZE / DLP_BLOCK_SIZE);
987         blockOffset += blockLen;
988     }
989     message2.size = message1.size;
990     delete[] spec.algParam->iv.data;
991     delete spec.algParam;
992     return ret;
993 }
994 
IsInitDlpContentCryptyOperation(uint32_t algType)995 static bool IsInitDlpContentCryptyOperation(uint32_t algType)
996 {
997 #ifdef SUPPORT_DLP_CREDENTIAL
998     if (algType == DLP_MODE_CTR) {
999         DLP_LOG_INFO(LABEL, "support openssl");
1000     } else {
1001         if (InitDlpHIAEMgr() != DLP_OK) {
1002             return false;
1003         }
1004     }
1005 #endif
1006     return true;
1007 }
1008 
DoDlpContentCryptyOperation(int32_t inFd,int32_t outFd,uint64_t inOffset,uint64_t inFileLen,bool isEncrypt)1009 int32_t DlpRawFile::DoDlpContentCryptyOperation(int32_t inFd, int32_t outFd, uint64_t inOffset,
1010     uint64_t inFileLen, bool isEncrypt)
1011 {
1012     if (!IsInitDlpContentCryptyOperation(head_.algType)) {
1013         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1014     }
1015     struct DlpBlob message;
1016     struct DlpBlob outMessage;
1017     if (PrepareBuff(message, outMessage) != DLP_OK) {
1018         DLP_LOG_ERROR(LABEL, "prepare buff failed");
1019         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
1020     }
1021     uint64_t dlpContentOffset = inOffset;
1022     int32_t ret = DLP_OK;
1023     while (inOffset < inFileLen) {
1024         uint32_t readLen = ((inFileLen - inOffset) < DLP_BUFF_LEN) ? (inFileLen - inOffset) : DLP_BUFF_LEN;
1025         (void)memset_s(message.data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
1026         (void)memset_s(outMessage.data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
1027         if (read(inFd, message.data, readLen) != (ssize_t)readLen) {
1028             DLP_LOG_ERROR(LABEL, "Read size do not equal readLen");
1029             ret = DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1030             break;
1031         }
1032         message.size = readLen;
1033         outMessage.size = readLen;
1034         // Implicit condition: DLP_BUFF_LEN must be DLP_BLOCK_SIZE aligned
1035         if (head_.algType == DLP_MODE_CTR) {
1036             ret = DoDlpBlockCryptOperation(message, outMessage, inOffset - dlpContentOffset, isEncrypt);
1037         } else {
1038             ret = DoDlpHIAECryptOperation(message, outMessage, inOffset - dlpContentOffset, isEncrypt);
1039         }
1040 
1041         if (ret != DLP_OK) {
1042             DLP_LOG_ERROR(LABEL, "do crypt operation fail");
1043             break;
1044         }
1045 
1046         if (write(outFd, outMessage.data, readLen) != (ssize_t)readLen) {
1047             DLP_LOG_ERROR(LABEL, "write fd failed, %{public}s", strerror(errno));
1048             if (dlpFd_ != -1 && errno == EBADF) {
1049                 DLP_LOG_DEBUG(LABEL, "this dlp fd is readonly, unable write.");
1050                 break;
1051             }
1052             ret = DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
1053             break;
1054         }
1055         inOffset += readLen;
1056     }
1057 
1058     delete[] message.data;
1059     delete[] outMessage.data;
1060     return ret;
1061 }
1062 }  // namespace DlpPermission
1063 }  // namespace Security
1064 }  // namespace OHOS
1065