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 "dlp_utils.h"
32 #include "hex_string.h"
33 #include "ohos_account_kits.h"
34 #ifdef DLP_PARSE_INNER
35 #include "os_account_manager.h"
36 #endif // DLP_PARSE_INNER
37 #include "securec.h"
38
39 namespace OHOS {
40 namespace Security {
41 namespace DlpPermission {
42 using Defer = std::shared_ptr<void>;
43 namespace {
44 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION, "DlpFile"};
45 const uint32_t FIRST = 1;
46 } // namespace
47
DlpFile(int32_t dlpFd,const std::string & realType)48 DlpFile::DlpFile(int32_t dlpFd, const std::string &realType)
49 : dlpFd_(dlpFd), realType_(realType), isFuseLink_(false), authPerm_(DLPFileAccess::READ_ONLY)
50 {
51 cert_.data = nullptr;
52 cert_.size = 0;
53
54 offlineCert_.data = nullptr;
55 offlineCert_.size = 0;
56
57 cipher_.tagIv.iv.data = nullptr;
58 cipher_.tagIv.iv.size = 0;
59 cipher_.encKey.data = nullptr;
60 cipher_.encKey.size = 0;
61 cipher_.usageSpec = { 0 };
62 cipher_.hmacKey.data = nullptr;
63 cipher_.hmacKey.size = 0;
64
65 hmac_.data = nullptr;
66 hmac_.size = 0;
67
68 encDataFd_ = -1;
69 offlineAccess_ = 0;
70 version_ = CURRENT_VERSION;
71 }
72
73 DlpFile::~DlpFile() = default;
74
IsValidCipher(const struct DlpBlob & key,const struct DlpUsageSpec & spec,const struct DlpBlob & hmacKey) const75 bool DlpFile::IsValidCipher(const struct DlpBlob& key, const struct DlpUsageSpec& spec,
76 const struct DlpBlob& hmacKey) const
77 {
78 if (key.data == nullptr) {
79 DLP_LOG_ERROR(LABEL, "key data null");
80 return false;
81 }
82
83 if (key.size != DLP_KEY_LEN_128 && key.size != DLP_KEY_LEN_192 && key.size != DLP_KEY_LEN_256) {
84 DLP_LOG_ERROR(LABEL, "key size invalid");
85 return false;
86 }
87
88 if (spec.mode != DLP_MODE_CTR || spec.algParam == nullptr) {
89 DLP_LOG_ERROR(LABEL, "spec invalid");
90 return false;
91 }
92
93 struct DlpBlob& iv = spec.algParam->iv;
94 if (iv.size != IV_SIZE || iv.data == nullptr) {
95 DLP_LOG_ERROR(LABEL, "iv invalid");
96 return false;
97 }
98
99 if (hmacKey.data != nullptr && hmacKey.size != DLP_KEY_LEN_256) {
100 DLP_LOG_ERROR(LABEL, "hmacKey size invalid");
101 return false;
102 }
103 return true;
104 }
105
CopyBlobParam(const struct DlpBlob & src,struct DlpBlob & dst) const106 int32_t DlpFile::CopyBlobParam(const struct DlpBlob& src, struct DlpBlob& dst) const
107 {
108 if (src.data == nullptr || src.size == 0 || src.size > DLP_MAX_CERT_SIZE) {
109 DLP_LOG_ERROR(LABEL, "src data null");
110 return DLP_PARSE_ERROR_VALUE_INVALID;
111 }
112
113 uint8_t* blobData = new (std::nothrow)uint8_t[src.size];
114 if (blobData == nullptr) {
115 DLP_LOG_ERROR(LABEL, "blobData null");
116 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
117 }
118
119 if (memcpy_s(blobData, src.size, src.data, src.size) != EOK) {
120 DLP_LOG_ERROR(LABEL, "memcpy_s error");
121 delete[] blobData;
122 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
123 }
124
125 if (dst.data != nullptr) {
126 (void)memset_s(dst.data, dst.size, 0, dst.size);
127 delete[] dst.data;
128 dst.data = nullptr;
129 }
130 dst.data = blobData;
131 dst.size = src.size;
132 return DLP_OK;
133 }
134
CleanBlobParam(struct DlpBlob & blob) const135 int32_t DlpFile::CleanBlobParam(struct DlpBlob& blob) const
136 {
137 if (blob.data == nullptr || blob.size == 0) {
138 DLP_LOG_ERROR(LABEL, "blobData null");
139 return DLP_PARSE_ERROR_VALUE_INVALID;
140 }
141
142 (void)memset_s(blob.data, blob.size, 0, blob.size);
143 delete[] blob.data;
144 blob.data = nullptr;
145 blob.size = 0;
146 return DLP_OK;
147 }
148
GetLocalAccountName(std::string & account) const149 int32_t DlpFile::GetLocalAccountName(std::string& account) const
150 {
151 std::pair<bool, AccountSA::OhosAccountInfo> accountInfo =
152 AccountSA::OhosAccountKits::GetInstance().QueryOhosAccountInfo();
153 if (accountInfo.first) {
154 account = accountInfo.second.name_;
155 return DLP_OK;
156 }
157 DLP_LOG_ERROR(LABEL, "QueryOhosAccountInfo accountInfo error");
158 return DLP_PARSE_ERROR_ACCOUNT_INVALID;
159 }
160
GetDomainAccountName(std::string & account) const161 int32_t DlpFile::GetDomainAccountName(std::string& account) const
162 {
163 #ifdef DLP_PARSE_INNER
164 AccountSA::OsAccountInfo osAccountInfo;
165 if (OHOS::AccountSA::OsAccountManager::QueryCurrentOsAccount(osAccountInfo) != 0) {
166 DLP_LOG_ERROR(LABEL, "QueryCurrentOsAccount return not 0");
167 return DLP_PARSE_ERROR_ACCOUNT_INVALID;
168 }
169 AccountSA::DomainAccountInfo domainInfo;
170 osAccountInfo.GetDomainInfo(domainInfo);
171 if (domainInfo.accountName_.empty()) {
172 DLP_LOG_ERROR(LABEL, "accountName_ empty");
173 return DLP_PARSE_ERROR_ACCOUNT_INVALID;
174 }
175 account = domainInfo.accountName_;
176 #endif
177 return DLP_OK;
178 }
179
UpdateDlpFilePermission()180 bool DlpFile::UpdateDlpFilePermission()
181 {
182 if (!policy_.accountName_.empty()) {
183 DLP_LOG_INFO(LABEL, "AccountName_ is not empty, perm is %{public}d", policy_.perm_);
184 authPerm_ = policy_.perm_;
185 return true;
186 }
187 std::string accountName;
188 if (policy_.ownerAccountType_ == DOMAIN_ACCOUNT) {
189 if (GetDomainAccountName(accountName) != DLP_OK) {
190 DLP_LOG_ERROR(LABEL, "query GetDomainAccountName failed");
191 return false;
192 }
193 } else {
194 DLP_LOG_DEBUG(LABEL, "AuthPerm_ is readonly");
195 authPerm_ = DLPFileAccess::READ_ONLY;
196 return true;
197 }
198
199 if (accountName == policy_.ownerAccount_) {
200 DLP_LOG_DEBUG(LABEL, "current account is owner, it has full permission");
201 authPerm_ = DLPFileAccess::FULL_CONTROL;
202 return true;
203 }
204
205 if (policy_.supportEveryone_) {
206 DLP_LOG_DEBUG(LABEL, "everyone has perm permission %{public}d", policy_.everyonePerm_);
207 authPerm_ = policy_.everyonePerm_;
208 } else {
209 DLP_LOG_DEBUG(LABEL, "everyone has not perm permission %{public}d", policy_.everyonePerm_);
210 }
211
212 for (int32_t i = 0; i < static_cast<int32_t>(policy_.authUsers_.size()); i++) {
213 if (accountName == policy_.authUsers_[i].authAccount) {
214 authPerm_ = policy_.authUsers_[i].authPerm;
215 DLP_LOG_DEBUG(LABEL, "current account match authUsers list, authPerm_ %{public}d",
216 authPerm_);
217 }
218 }
219 return true;
220 }
221
SetCipher(const struct DlpBlob & key,const struct DlpUsageSpec & spec,const struct DlpBlob & hmacKey)222 int32_t DlpFile::SetCipher(const struct DlpBlob& key, const struct DlpUsageSpec& spec, const struct DlpBlob& hmacKey)
223 {
224 if (!IsValidCipher(key, spec, hmacKey)) {
225 DLP_LOG_ERROR(LABEL, "dlp file cipher is invalid");
226 return DLP_PARSE_ERROR_VALUE_INVALID;
227 }
228
229 // copy iv from param.
230 int32_t res = CopyBlobParam(spec.algParam->iv, cipher_.tagIv.iv);
231 if (res != DLP_OK) {
232 DLP_LOG_ERROR(LABEL, "dlp file copy iv param failed, res %{public}d", res);
233 return res;
234 }
235
236 // copy key from param.
237 res = CopyBlobParam(key, cipher_.encKey);
238 if (res != DLP_OK) {
239 DLP_LOG_ERROR(LABEL, "dlp file copy key param failed, res %{public}d", res);
240 CleanBlobParam(cipher_.tagIv.iv);
241 return res;
242 }
243
244 // copy hmacKey from param.
245 if (hmacKey.data != nullptr) {
246 res = CopyBlobParam(hmacKey, cipher_.hmacKey);
247 if (res != DLP_OK) {
248 DLP_LOG_ERROR(LABEL, "dlp file copy hmacKey param failed, res %{public}d", res);
249 CleanBlobParam(cipher_.tagIv.iv);
250 CleanBlobParam(cipher_.encKey);
251 return res;
252 }
253 }
254
255 cipher_.usageSpec.mode = spec.mode;
256 cipher_.usageSpec.algParam = &cipher_.tagIv;
257 return DLP_OK;
258 }
259
SetPolicy(const PermissionPolicy & policy)260 int32_t DlpFile::SetPolicy(const PermissionPolicy& policy)
261 {
262 if (!policy.IsValid()) {
263 DLP_LOG_ERROR(LABEL, "invalid policy");
264 return DLP_PARSE_ERROR_VALUE_INVALID;
265 }
266 if (policy.dlpVersion_ != 0) {
267 version_ = policy.dlpVersion_;
268 }
269 policy_.CopyPermissionPolicy(policy);
270 UpdateDlpFilePermission();
271 return DLP_OK;
272 };
273
GetOfflineAccess()274 bool DlpFile::GetOfflineAccess()
275 {
276 return !!offlineAccess_;
277 }
278
NeedAdapter()279 bool DlpFile::NeedAdapter()
280 {
281 return version_ == FIRST && CURRENT_VERSION != FIRST;
282 }
283
GetEncryptCert(struct DlpBlob & cert) const284 void DlpFile::GetEncryptCert(struct DlpBlob& cert) const
285 {
286 cert.data = cert_.data;
287 cert.size = cert_.size;
288 }
289
GetOfflineCert(struct DlpBlob & cert) const290 void DlpFile::GetOfflineCert(struct DlpBlob& cert) const
291 {
292 cert.data = offlineCert_.data;
293 cert.size = offlineCert_.size;
294 }
295
PrepareBuff(struct DlpBlob & message1,struct DlpBlob & message2) const296 int32_t DlpFile::PrepareBuff(struct DlpBlob& message1, struct DlpBlob& message2) const
297 {
298 message1.size = DLP_BUFF_LEN;
299 message1.data = new (std::nothrow) uint8_t[DLP_BUFF_LEN];
300 if (message1.data == nullptr) {
301 DLP_LOG_ERROR(LABEL, "message1.data null");
302 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
303 }
304
305 message2.size = DLP_BUFF_LEN;
306 message2.data = new (std::nothrow) uint8_t[DLP_BUFF_LEN];
307 if (message2.data == nullptr) {
308 DLP_LOG_ERROR(LABEL, "message2.data null");
309 delete[] message1.data;
310 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
311 }
312
313 (void)memset_s(message1.data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
314 (void)memset_s(message2.data, DLP_BUFF_LEN, 0, DLP_BUFF_LEN);
315 return DLP_OK;
316 }
317
DupUsageSpec(struct DlpUsageSpec & spec)318 int32_t DlpFile::DupUsageSpec(struct DlpUsageSpec& spec)
319 {
320 if (cipher_.usageSpec.algParam == nullptr ||
321 cipher_.usageSpec.algParam->iv.data == nullptr ||
322 cipher_.usageSpec.algParam->iv.size != IV_SIZE) {
323 DLP_LOG_ERROR(LABEL, "chipher_ is invalid");
324 return DLP_PARSE_ERROR_VALUE_INVALID;
325 }
326 spec.mode = cipher_.usageSpec.mode;
327 spec.algParam = new (std::nothrow) struct DlpCipherParam;
328 if (spec.algParam == nullptr) {
329 DLP_LOG_ERROR(LABEL, "new alg param failed");
330 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
331 }
332 spec.algParam->iv.data = new (std::nothrow) uint8_t[IV_SIZE]();
333 if (spec.algParam->iv.data == nullptr) {
334 delete spec.algParam;
335 DLP_LOG_ERROR(LABEL, "new iv failed");
336 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
337 }
338 spec.algParam->iv.size = cipher_.usageSpec.algParam->iv.size;
339 if (memcpy_s(spec.algParam->iv.data, IV_SIZE,
340 cipher_.usageSpec.algParam->iv.data, cipher_.usageSpec.algParam->iv.size) != EOK) {
341 delete[] spec.algParam->iv.data;
342 delete spec.algParam;
343 DLP_LOG_ERROR(LABEL, "copy iv failed");
344 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
345 }
346 return DLP_OK;
347 }
348
DoDlpBlockCryptOperation(struct DlpBlob & message1,struct DlpBlob & message2,uint64_t offset,bool isEncrypt)349 int32_t DlpFile::DoDlpBlockCryptOperation(struct DlpBlob& message1, struct DlpBlob& message2,
350 uint64_t offset, bool isEncrypt)
351 {
352 if (offset % DLP_BLOCK_SIZE != 0 || message1.data == nullptr || message1.size == 0
353 || message2.data == nullptr || message2.size == 0) {
354 DLP_LOG_ERROR(LABEL, "params is error");
355 return DLP_PARSE_ERROR_VALUE_INVALID;
356 }
357
358 uint32_t counterIndex = offset / DLP_BLOCK_SIZE;
359 struct DlpUsageSpec spec;
360 if (DupUsageSpec(spec) != DLP_OK) {
361 DLP_LOG_ERROR(LABEL, "spec dup failed");
362 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
363 }
364
365 DlpCtrModeIncreaeIvCounter(spec.algParam->iv, counterIndex);
366 int32_t ret = isEncrypt ? DlpOpensslAesEncrypt(&cipher_.encKey, &spec, &message1, &message2) :
367 DlpOpensslAesDecrypt(&cipher_.encKey, &spec, &message1, &message2);
368 delete[] spec.algParam->iv.data;
369 delete spec.algParam;
370 if (ret != 0) {
371 DLP_LOG_ERROR(LABEL, "do block crypt fail");
372 return DLP_PARSE_ERROR_CRYPT_FAIL;
373 }
374 return DLP_OK;
375 }
376
FillHoleData(uint64_t holeStart,uint64_t holeSize)377 int32_t DlpFile::FillHoleData(uint64_t holeStart, uint64_t holeSize)
378 {
379 DLP_LOG_INFO(LABEL, "Need create a hole filled with 0s, hole start %{public}s size %{public}s",
380 std::to_string(holeStart).c_str(), std::to_string(holeSize).c_str());
381 uint32_t holeBufSize = (holeSize < HOLE_BUFF_SMALL_SIZE) ? HOLE_BUFF_SMALL_SIZE : HOLE_BUFF_SIZE;
382 std::unique_ptr<uint8_t[]> holeBuff(new (std::nothrow) uint8_t[holeBufSize]());
383 if (holeBuff == nullptr) {
384 DLP_LOG_ERROR(LABEL, "New buf failed.");
385 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
386 }
387
388 uint64_t fillLen = 0;
389 while (fillLen < holeSize) {
390 uint32_t writeSize = ((holeSize - fillLen) < holeBufSize) ? (holeSize - fillLen) : holeBufSize;
391 int32_t res = DoDlpFileWrite(holeStart + fillLen, holeBuff.get(), writeSize);
392 if (res < 0) {
393 DLP_LOG_ERROR(LABEL, "Write failed, error %{public}d.", res);
394 return res;
395 }
396 fillLen += writeSize;
397 }
398 return DLP_OK;
399 }
400 } // namespace DlpPermission
401 } // namespace Security
402 } // namespace OHOS
403