1 /*
2  * Copyright (c) 2022 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 NATIVE_RDB_RDB_SECURITY_MANAGER_H
17 #define NATIVE_RDB_RDB_SECURITY_MANAGER_H
18 
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22 
23 #include <atomic>
24 #include <climits>
25 #include <mutex>
26 #include <random>
27 #include <vector>
28 
29 #include "hks_type.h"
30 
31 namespace OHOS::NativeRdb {
32 struct RdbSecretKeyData {
33     uint8_t distributed = 0;
34     time_t timeValue {};
35     std::vector<uint8_t> secretKey {};
36     RdbSecretKeyData() = default;
~RdbSecretKeyDataRdbSecretKeyData37     ~RdbSecretKeyData()
38     {
39         secretKey.assign(secretKey.size(), 0);
40     }
41 };
42 
43 class RdbPassword final {
44 public:
45     RdbPassword();
46     ~RdbPassword();
47 
48     bool isKeyExpired = false;
49     bool operator==(const RdbPassword &input) const;
50     bool operator!=(const RdbPassword &input) const;
51 
52     size_t GetSize() const;
53     const uint8_t *GetData() const;
54     int SetValue(const uint8_t *inputData, size_t inputSize);
55     int Clear();
56     bool IsValid() const;
57 
58 private:
59     static constexpr size_t MAX_PASSWORD_SIZE = 128;
60     uint8_t data_[MAX_PASSWORD_SIZE] = { UCHAR_MAX };
61     size_t size_ = 0;
62 };
63 
64 class RdbSecurityManager {
65 public:
66     enum KeyFileType : int32_t {
67         PUB_KEY_FILE = 0,
68         PUB_KEY_FILE_NEW_KEY,
69         PUB_KEY_FILE_BUTT
70     };
71     class KeyFiles {
72     public:
73         KeyFiles(const std::string &dbPath, bool openFile = true);
74         ~KeyFiles();
75         const std::string &GetKeyFile(KeyFileType type);
76         int32_t InitKeyPath();
77         int32_t DestroyLock();
78         int32_t Lock();
79         int32_t Unlock();
80 
81     private:
82         int32_t lockFd_ = -1;
83         std::string lock_;
84         std::string keys_[PUB_KEY_FILE_BUTT];
85     };
86     static RdbSecurityManager &GetInstance();
87     int32_t Init(const std::string &bundleName);
88 
89     RdbPassword GetRdbPassword(const std::string &dbPath, KeyFileType keyFileType);
90     void DelAllKeyFiles(const std::string &dbPath);
91     void DelKeyFile(const std::string &dbPath, KeyFileType keyFileType);
92     void ChangeKeyFile(const std::string &dbPath);
93     int32_t RestoreKeyFile(const std::string &dbPath, const std::vector<uint8_t> &key);
94     bool IsKeyFileExists(const std::string &dbPath, KeyFileType keyFileType);
95 
96 private:
97     RdbSecurityManager();
98     ~RdbSecurityManager();
99 
100     bool HasRootKey();
101     int GenerateRootKey(const std::vector<uint8_t> &rootKeyAlias);
102     int32_t CheckRootKeyExists(std::vector<uint8_t> &rootKeyAlias);
103     std::vector<uint8_t> EncryptWorkKey(std::vector<uint8_t> &key);
104     bool DecryptWorkKey(std::vector<uint8_t> &source, std::vector<uint8_t> &key);
105     std::vector<uint8_t> GenerateRootKeyAlias(const std::string &bundleName);
106     static bool InitPath(const std::string &fileDir);
107     std::vector<uint8_t> GenerateRandomNum(int32_t len);
108     bool SaveSecretKeyToFile(const std::string &keyFile, const std::vector<uint8_t> &workey = {});
109     bool SaveSecretKeyToDisk(const std::string &keyPath, RdbSecretKeyData &keyData);
110     RdbPassword LoadSecretKeyFromFile(const std::string &keyFile);
111     bool LoadSecretKeyFromDisk(const std::string &keyPath, RdbSecretKeyData &keyData);
112     bool IsKeyFileEmpty(const std::string &keyFile);
113     static bool IsKeyExpired(const time_t &createTime) ;
114     int32_t HksLoopUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet,
115         const struct HksBlob *inData, struct HksBlob *outData);
116     int32_t HksEncryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet,
117         const struct HksBlob *plainText, struct HksBlob *cipherText);
118     int32_t HksDecryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet,
119         const struct HksBlob *cipherText, struct HksBlob *plainText);
120 
121     static constexpr char const *SUFFIX_KEY_LOCK = ".key_lock";
122     static constexpr char const *SUFFIX_PUB_KEY = ".pub_key";
123     static constexpr char const *SUFFIX_PUB_KEY_NEW = ".pub_key.new";
124     static constexpr const char *RDB_ROOT_KEY_ALIAS_PREFIX = "DistributedDataRdb";
125     static constexpr const char *RDB_HKS_BLOB_TYPE_NONCE = "Z5s0Bo571Koq";
126     static constexpr const char *RDB_HKS_BLOB_TYPE_AAD = "RdbClientAAD";
127     static constexpr uint32_t TIMES = 4;
128     static constexpr uint32_t MAX_UPDATE_SIZE = 64;
129     static constexpr uint32_t MAX_OUTDATA_SIZE = MAX_UPDATE_SIZE * TIMES;
130     static constexpr uint8_t AEAD_LEN = 16;
131     static constexpr int RDB_KEY_SIZE = 32;
132 
133     static constexpr int HOURS_PER_YEAR = (24 * 365);
134     static constexpr uint8_t UNDISTRIBUTED = 0;
135     static constexpr uint8_t DISTRIBUTED = 1;
136 
137     std::vector<uint8_t> rootKeyAlias_ {};
138     std::vector<uint8_t> nonce_;
139     std::vector<uint8_t> aad_;
140     std::mutex mutex_;
141     std::atomic<bool> hasRootKey_ = false;
142 };
143 
144 } // namespace OHOS::NativeRdb
145 #endif
146