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