• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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