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 #ifndef INTERFACES_INNER_API_DLP_FILE_H
17 #define INTERFACES_INNER_API_DLP_FILE_H
18 
19 #include <string>
20 #include "dlp_crypt.h"
21 #include "permission_policy.h"
22 
23 namespace OHOS {
24 namespace Security {
25 namespace DlpPermission {
26 static constexpr uint32_t INVALID_FILE_SIZE = 0xffffffff;
27 static constexpr uint32_t DLP_BUFF_LEN = 4096;
28 static constexpr uint32_t IV_SIZE = 16;
29 static constexpr uint32_t DLP_FILE_MAGIC = 0x87f4922;
30 static constexpr uint32_t DLP_FUSE_MAX_BUFFLEN = (10 * 1024 * 1024); // 10M
31 static constexpr uint32_t DLP_BLOCK_SIZE = 16;
32 // dlp file only support 32bits size, apart from 10M max head size
33 static constexpr uint32_t DLP_MAX_CONTENT_SIZE = 0xffffffff - 0xA00000;
34 static constexpr uint32_t HOLE_BUFF_SIZE = 16 * 1024;
35 static constexpr uint32_t HOLE_BUFF_SMALL_SIZE = 1 * 1024;
36 static constexpr uint32_t MAX_HOLE_SIZE = 50 * 1024 * 1024; // 50M
37 
38 enum DlpOperation {
39     DLP_ENCRYPTION = 1,
40     DLP_DECRYPTION = 2,
41 };
42 
43 struct DlpCipher {
44     struct DlpBlob encKey;
45     struct DlpCipherParam tagIv;
46     struct DlpUsageSpec usageSpec;
47     struct DlpBlob hmacKey;
48 };
49 
50 struct DlpHeader {
51     uint32_t magic;
52     uint32_t version;
53     uint32_t offlineAccess;
54     uint32_t txtOffset;
55     uint32_t txtSize;
56     uint32_t certOffset;
57     uint32_t certSize;
58     uint32_t contactAccountOffset;
59     uint32_t contactAccountSize;
60     uint32_t offlineCertOffset;
61     uint32_t offlineCertSize;
62 };
63 
64 enum VALID_KEY_SIZE {
65     DLP_KEY_LEN_128 = 16,
66     DLP_KEY_LEN_192 = 24,
67     DLP_KEY_LEN_256 = 32,
68 };
69 
70 #define CHECK_RET(ret, expect, retcode, TAG)                            \
71     do {                                                                \
72         if ((ret) != (expect)) {                                            \
73             DLP_LOG_ERROR(TAG, "check fail ret %{public}d, expect %{public}d, errno %{public}s", \
74                 ret, expect, strerror(errno));                          \
75             return retcode;                                             \
76         }                                                               \
77     } while (0)                                                         \
78 
79 #define CHDIR_AND_CHECK(path, ret, TAG)                                 \
80     do {                                                                \
81         if (chdir(path) != 0) {                                         \
82             DLP_LOG_ERROR(TAG, "chdir fail path %{public}s, errno %{public}s", \
83                 path, strerror(errno));                                 \
84             return ret;                                                 \
85         }                                                               \
86     } while (0)                                                         \
87 
88 #define UNLINK_AND_CHECK(path, ret, TAG)                                \
89     do {                                                                \
90         if (unlink(path) != 0) {                                        \
91             DLP_LOG_ERROR(TAG, "unlink fail path %{public}s, errno %{public}s", \
92                 path, strerror(errno));                                 \
93             return ret;                                                 \
94         }                                                               \
95     } while (0)                                                         \
96 
97 #define MKDIR_AND_CHECK(path, mode, ret, TAG)                           \
98     do {                                                                \
99         if (mkdir(path, mode) != 0) {                                   \
100             DLP_LOG_ERROR(TAG, "mkdir fail path %{public}s, errno %{public}s", \
101                 path, strerror(errno));                                 \
102             return ret;                                                 \
103         }                                                               \
104     } while (0)                                                         \
105 
106 #define GETCWD_AND_CHECK(buf, size, ret, TAG)                           \
107     do {                                                                \
108         if (getcwd(buf, size) == nullptr) {                             \
109             DLP_LOG_ERROR(TAG, "getcwd fail errno %{public}s",          \
110                 strerror(errno));                                       \
111             return ret;                                                 \
112         }                                                               \
113     } while (0)                                                         \
114 
115 #define LSEEK_AND_CHECK(fd, size, flag, ret, TAG)                       \
116     do {                                                                \
117         if (lseek(fd, size, flag) == -1) {                              \
118             DLP_LOG_ERROR(TAG, "lseek failed, %{public}s",              \
119                 strerror(errno));                                       \
120             return ret;                                                 \
121         }                                                               \
122     } while (0)                                                         \
123 
124 #define OPEN_AND_CHECK(fd, path, flag, mode, ret, TAG)                  \
125     do {                                                                \
126         fd = open(path, flag, mode);                                    \
127         if ((fd) == -1) {                                                \
128             DLP_LOG_ERROR(TAG, "open failed, %{public}s",               \
129                 strerror(errno));                                       \
130             return ret;                                                 \
131         }                                                               \
132     } while (0)                                                         \
133 
134 #define FTRUNCATE_AND_CHECK(fd, size, ret, TAG)                         \
135     do {                                                                \
136         if (ftruncate(fd, size) == -1) {                                \
137             DLP_LOG_ERROR(TAG, "ftruncate failed, %{public}s",          \
138                 strerror(errno));                                       \
139             return ret;                                                 \
140         }                                                               \
141     } while (0)                                                         \
142 
143 
144 class DlpFile {
145 public:
146     DlpFile(int32_t dlpFd, const std::string &workDir, int64_t index, bool isZip);
147     ~DlpFile();
148 
149     int32_t SetCipher(const struct DlpBlob& key, const struct DlpUsageSpec& spec, const struct DlpBlob& hmacKey);
150     int32_t ParseDlpHeader();
151     void GetEncryptCert(struct DlpBlob& cert) const;
152     void GetOfflineCert(struct DlpBlob& cert) const;
153     int32_t UpdateCertAndText(const std::vector<uint8_t>& cert, const std::string& workDir, struct DlpBlob certBlob);
154     int32_t UpdateCert(struct DlpBlob certBlob);
155     int32_t SetEncryptCert(const struct DlpBlob& cert);
156     void SetOfflineAccess(bool flag);
157     bool GetOfflineAccess();
158     int32_t GenFile(int32_t inPlainFileFd);
159     int32_t RemoveDlpPermission(int outPlainFileFd);
160     int32_t DlpFileRead(uint32_t offset, void* buf, uint32_t size, bool& hasRead, int32_t uid);
161     int32_t DlpFileWrite(uint32_t offset, void* buf, uint32_t size);
162     uint32_t GetFsContentSize() const;
163     bool UpdateDlpFilePermission();
164     int32_t CheckDlpFile();
165     bool NeedAdapter();
166     bool CleanTmpFile();
167     int32_t HmacCheck();
168 
169     int32_t SetPolicy(const PermissionPolicy& policy);
GetPolicy(PermissionPolicy & policy)170     void GetPolicy(PermissionPolicy& policy) const
171     {
172         policy.CopyPermissionPolicy(policy_);
173     };
174 
175     int32_t SetContactAccount(const std::string& contactAccount);
GetContactAccount(std::string & contactAccount)176     void GetContactAccount(std::string& contactAccount) const
177     {
178         contactAccount = contactAccount_;
179     };
180 
SetLinkStatus()181     void SetLinkStatus()
182     {
183         isFuseLink_ = true;
184     };
185 
RemoveLinkStatus()186     void RemoveLinkStatus()
187     {
188         isFuseLink_ = false;
189     };
190 
GetAuthPerm()191     DLPFileAccess GetAuthPerm()
192     {
193         return authPerm_;
194     };
195 
196     int32_t Truncate(uint32_t size);
197     int32_t dlpFd_;
198 
199 private:
200     bool IsValidDlpHeader(const struct DlpHeader& head) const;
201     bool IsValidPadding(uint32_t padding);
202     bool IsValidCipher(const struct DlpBlob& key, const struct DlpUsageSpec& spec,
203         const struct DlpBlob& hmacKey) const;
204     int32_t CopyBlobParam(const struct DlpBlob& src, struct DlpBlob& dst) const;
205     int32_t CleanBlobParam(struct DlpBlob& blob) const;
206     int32_t UpdateFileCertData();
207     int32_t PrepareBuff(struct DlpBlob& message1, struct DlpBlob& message2) const;
208     int32_t GetLocalAccountName(std::string& account) const;
209     int32_t GetDomainAccountName(std::string& account) const;
210     int32_t DoDlpContentCryptyOperation(int32_t inFd, int32_t outFd, uint32_t inOffset,
211         uint32_t inFileLen, bool isEncrypt);
212     int32_t DoDlpContentCopyOperation(int32_t inFd, int32_t outFd, uint32_t inOffset, uint32_t inFileLen);
213     int32_t WriteHeadAndCert(int tmpFile, const std::vector<uint8_t>& offlineCert);
214     int32_t DupUsageSpec(struct DlpUsageSpec& spec);
215     int32_t DoDlpBlockCryptOperation(struct DlpBlob& message1,
216         struct DlpBlob& message2, uint32_t offset, bool isEncrypt);
217     int32_t WriteFirstBlockData(uint32_t offset, void* buf, uint32_t size);
218     int32_t FillHoleData(uint32_t holeStart, uint32_t holeSize);
219     int32_t DoDlpFileWrite(uint32_t offset, void* buf, uint32_t size);
220     int32_t UpdateDlpFileContentSize();
221     int32_t UpdateFile(int tmpFile, const std::vector<uint8_t>& cert, uint32_t oldTxtOffset);
222     int32_t GetTempFile(const std::string& workDir, int& tempFile, std::string& path);
223     bool ParseDlpInfo();
224     bool ParseCert();
225     bool ParseEncData();
226 
227     int32_t UnzipDlpFile();
228     int32_t ParseDlpHeaderInRaw();
229     int32_t GenEncData(int32_t inPlainFileFd);
230     int32_t GenFileInZip(int32_t inPlainFileFd);
231     int32_t GenFileInRaw(int32_t inPlainFileFd);
232     int32_t RemoveDlpPermissionInZip(int32_t outPlainFileFd);
233     int32_t RemoveDlpPermissionInRaw(int32_t outPlainFileFd);
234     int32_t GetHmacVal(int32_t encFile, std::string& hmacStr);
235     int32_t GenerateHmacVal(int32_t encFile, struct DlpBlob& out);
236     int32_t AddGeneralInfoToBuff(int32_t encFile);
237 
238     std::string workDir_ = "";
239     std::string dirIndex_;
240     bool isZip_ = false;
241     bool isFuseLink_;
242     DLPFileAccess authPerm_;
243 
244     std::vector<std::string> extraInfo_;
245     int32_t encDataFd_;
246 
247     // dlp parse format
248     struct DlpHeader head_;
249     struct DlpBlob cert_;
250     struct DlpBlob offlineCert_;
251     struct DlpBlob hmac_;
252 
253     struct DlpCipher cipher_;
254     // policy in certificate
255     PermissionPolicy policy_;
256     std::string contactAccount_;
257 };
258 }  // namespace DlpPermission
259 }  // namespace Security
260 }  // namespace OHOS
261 #endif /*  INTERFACES_INNER_API_DLP_FILE_H */
262