1 /*
2  * Copyright (c) 2021-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 #ifndef STORAGE_DAEMON_CRYPTO_KEY_UTILS_H
16 #define STORAGE_DAEMON_CRYPTO_KEY_UTILS_H
17 
18 #include <memory>
19 #include <string>
20 #include <vector>
21 #include <linux/keyctl.h>
22 #include <linux/version.h>
23 
24 #include "hks_type.h"
25 #include "securec.h"
26 
27 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)
28 #include <linux/fscrypt.h>
29 #define SUPPORT_FSCRYPT_V2
30 #else
31 #include "libfscrypt/fscrypt_uapi.h"
32 #endif
33 
34 namespace OHOS {
35 namespace StorageDaemon {
36 constexpr uint32_t CRYPTO_KEY_SECDISC_SIZE = 16384;
37 constexpr uint32_t CRYPTO_KEY_ALIAS_SIZE = 16;
38 constexpr uint32_t CRYPTO_AES_AAD_LEN = 16;
39 constexpr uint32_t CRYPTO_AES_NONCE_LEN = 64;
40 constexpr uint32_t CRYPTO_HKS_NONCE_LEN = 12;
41 constexpr uint32_t CRYPTO_AES_256_XTS_KEY_SIZE = 64;
42 constexpr uint32_t CRYPTO_KEY_SHIELD_MAX_SIZE = 2048;
43 constexpr uint32_t CRYPTO_AES_256_KEY_ENCRYPTED_SIZE = 80;
44 constexpr uint32_t CRYPTO_TOKEN_SIZE = TOKEN_CHALLENGE_LEN; // 32
45 
46 using key_serial_t = int;
47 constexpr uint32_t CRYPTO_KEY_DESC_SIZE = FSCRYPT_KEY_DESCRIPTOR_SIZE;
48 static const std::string MNT_DATA = "/data";
49 static const std::string PATH_LATEST = "/latest";
50 static const std::string PATH_SHIELD = "/shield";
51 static const std::string PATH_SECDISC = "/sec_discard";
52 static const std::string PATH_ENCRYPTED = "/encrypted";
53 static const std::string PATH_KEYID = "/key_id";
54 static const std::string PATH_KEYDESC = "/key_desc";
55 
56 const std::string DATA_EL0_DIR = std::string() + "/data/service/el0";
57 const std::string STORAGE_DAEMON_DIR = DATA_EL0_DIR + "/storage_daemon";
58 const std::string DEVICE_EL1_DIR = STORAGE_DAEMON_DIR + "/sd";
59 
60 class KeyBlob {
61 public:
62     KeyBlob() = default;
KeyBlob(KeyBlob const & blob)63     KeyBlob(KeyBlob const &blob)
64     {
65         Alloc(blob.size);
66         auto ret = memcpy_s(data.get(), size, blob.data.get(), blob.size);
67         if (ret != EOK) {
68             Clear();
69         }
70     }
~KeyBlob()71     ~KeyBlob()
72     {
73         Clear();
74     }
KeyBlob(uint32_t len)75     KeyBlob(uint32_t len)
76     {
77         Alloc(len);
78         // may fail, need check IsEmpty() if needed
79     }
KeyBlob(KeyBlob && right)80     KeyBlob(KeyBlob &&right)
81     {
82         data = std::move(right.data);
83         size = right.size;
84     }
KeyBlob(const std::vector<uint8_t> & vec)85     KeyBlob(const std::vector<uint8_t> &vec)
86     {
87         if (Alloc(vec.size())) {
88             auto ret = memcpy_s(data.get(), size, vec.data(), vec.size());
89             if (ret != EOK) {
90                 Clear();
91             }
92         }
93     }
94     KeyBlob& operator=(KeyBlob &&right)
95     {
96         data = std::move(right.data);
97         size = right.size;
98         return *this;
99     }
Alloc(uint32_t len)100     bool Alloc(uint32_t len)
101     {
102         if (len > CRYPTO_KEY_SECDISC_SIZE) {
103             return false;
104         }
105         if (!IsEmpty()) {
106             Clear();
107         }
108 
109         data = std::make_unique<uint8_t[]>(len);
110         size = len;
111         (void)memset_s(data.get(), size, 0, size);
112         return true;
113     }
Clear()114     void Clear()
115     {
116         if (data != nullptr && size != 0) {
117             (void)memset_s(data.get(), size, 0, size);
118         }
119         size = 0;
120         data.reset(nullptr);
121     }
IsEmpty()122     bool IsEmpty() const
123     {
124         return size == 0 || data.get() == nullptr;
125     }
ToString()126     std::string ToString() const
127     {
128         std::string hex;
129         const char *hexMap = "0123456789abcdef";
130         static_assert(sizeof(data[0]) == sizeof(char));
131         for (size_t i = 0; i < size; i++) {
132             hex = hex + hexMap[(data[i] & 0xF0) >> 4] + hexMap[data[i] & 0x0F]; // higher 4 bits
133         }
134         return hex;
135     }
ToHksBlob()136     HksBlob ToHksBlob() const
137     {
138         return {size, data.get()};
139     }
140     uint32_t size { 0 };
141     std::unique_ptr<uint8_t[]> data { nullptr };
142 };
143 
144 struct KeyInfo {
145     uint8_t version { 0 };
146     KeyBlob key;
147     // the legacy interface use key_spec.u.descriptor
148     KeyBlob keyDesc;
149     // the v2 interface use the key_spec.u.identifier
150     KeyBlob keyId;
151 };
152 
153 struct KeyContext {
154     // secure discardable keyblob
155     KeyBlob secDiscard;
156     // encrypted huks key for encrypt/decrypt
157     KeyBlob shield;
158     // encrypted blob of rawkey
159     KeyBlob rndEnc;
160     // aes_gcm tags
161     KeyBlob nonce;
162     KeyBlob aad;
163 };
164 
165 struct UserAuth {
166     // when secure access enabled, token is needed to authenticate the user
167     KeyBlob token;
168     KeyBlob secret;
169     uint64_t secureUid { 0 };
170 };
171 } // namespace StorageDaemon
172 } // namespace OHOS
173 
174 #endif // STORAGE_DAEMON_CRYPTO_KEY_UTILS_H
175