1 /*
2 * Copyright (C) 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 #include "vpn_encryption_util.h"
16
17 #include <iterator>
18 #include <securec.h>
19 #include <sstream>
20
21 #include "netmgr_ext_log_wrapper.h"
22 #include "net_manager_constants.h"
23
24 namespace OHOS {
25 namespace NetManagerStandard {
26 struct HksParam g_genParam[] = {
27 { .tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = 0 },
28 { .tag = HKS_TAG_KEY_STORAGE_FLAG, .uint32Param = HKS_STORAGE_PERSISTENT },
29 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
30 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
31 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT },
32 { .tag = HKS_TAG_DIGEST, .uint32Param = HKS_DIGEST_NONE },
33 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
34 { .tag = HKS_TAG_IS_KEY_ALIAS, .boolParam = true },
35 { .tag = HKS_TAG_KEY_GENERATE_TYPE, .uint32Param = HKS_KEY_GENERATE_TYPE_DEFAULT },
36 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
37 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_CE },
38 { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = { .size = AAD_SIZE, .data = (uint8_t *)AAD } },
39 };
40
ConvertArrayChar(uint8_t ch)41 static char ConvertArrayChar(uint8_t ch)
42 {
43 constexpr int maxDecNum = 9;
44 constexpr int numDiffForHexAlphabet = 10;
45 if (ch <= maxDecNum) {
46 return '0' + ch;
47 }
48 if (ch <= 0xf) {
49 return ch + 'a' - numDiffForHexAlphabet;
50 }
51 return '0';
52 }
53
IsValidHexCharAndConvert(char c)54 static int8_t IsValidHexCharAndConvert(char c)
55 {
56 if (c >= '0' && c <= '9') {
57 return c - '0';
58 }
59 if (c >= 'a' && c <= 'f') {
60 return c - 'a' + ('9' - '0' + 1);
61 }
62 if (c >= 'A' && c <= 'F') {
63 return c - 'A' + ('9' - '0' + 1);
64 }
65 return -1;
66 }
67
ConvertArrayToHex(const uint8_t plainText[],uint32_t size)68 std::string ConvertArrayToHex(const uint8_t plainText[], uint32_t size)
69 {
70 constexpr int bitWidth = 4;
71 std::stringstream ss;
72 for (uint32_t i = 0; i < size; i++) {
73 ss << ConvertArrayChar(plainText[i] >> bitWidth) << ConvertArrayChar (plainText[i] & 0xf);
74 }
75 return ss.str();
76 }
77
HexStringToVec(const std::string & str,std::vector<char> & vec)78 int HexStringToVec(const std::string &str, std::vector<char> &vec)
79 {
80 unsigned len = str.length();
81 if ((len & 1) != 0) {
82 return -1;
83 }
84 const int hexShiftNum = 4;
85 const int hexOffsetNum = 2;
86 for (unsigned i = 0; i + 1 < len;) {
87 uint8_t high = static_cast<uint8_t>(IsValidHexCharAndConvert(str[i]));
88 uint8_t low = static_cast<uint8_t>(IsValidHexCharAndConvert(str[i + 1]));
89 if (high < 0 || low < 0) {
90 return -1;
91 }
92 char tmp = ((high << hexShiftNum) | (low & 0x0F));
93 vec.push_back(tmp);
94 i += hexOffsetNum;
95 }
96 return 0;
97 }
98
HexStringToVec(const std::string & str,uint8_t plainText[],uint32_t plainLength,uint32_t & resultLength)99 int HexStringToVec(const std::string &str, uint8_t plainText[], uint32_t plainLength, uint32_t &resultLength)
100 {
101 std::vector<char> result;
102 result.clear();
103 int ret = HexStringToVec(str, result);
104 if (ret == -1 || result.size() > plainLength) {
105 return -1;
106 }
107 for (std::vector<char>::size_type i = 0; i < result.size(); ++i) {
108 plainText[i] = result[i];
109 }
110 resultLength = result.size();
111 return 0;
112 }
113
Split(const std::string & str,const std::string & sep)114 std::vector<std::string> Split(const std::string &str, const std::string &sep)
115 {
116 std::string s = str;
117 std::vector<std::string> res;
118 while (!s.empty()) {
119 size_t pos = s.find(sep);
120 if (pos == std::string::npos) {
121 res.emplace_back(s);
122 break;
123 }
124 res.emplace_back(s.substr(0, pos));
125 s = s.substr(pos + sep.size());
126 }
127 return res;
128 }
129
SetUpHks()130 int32_t SetUpHks()
131 {
132 int32_t ret = HksInitialize();
133 if (ret != HKS_SUCCESS) {
134 NETMGR_EXT_LOG_E("vpn encryption init failed");
135 }
136 return ret;
137 }
138
GetKeyByAlias(struct HksBlob * keyAlias,const struct HksParamSet * genParamSet)139 int32_t GetKeyByAlias(struct HksBlob *keyAlias, const struct HksParamSet *genParamSet)
140 {
141 if (keyAlias == nullptr || genParamSet == nullptr) {
142 NETMGR_EXT_LOG_E("%{public}s invalid param", __func__);
143 return -1;
144 }
145 int32_t keyExist = HksKeyExist(keyAlias, genParamSet);
146 if (keyExist == HKS_ERROR_NOT_EXIST) {
147 int32_t ret = HksGenerateKey(keyAlias, genParamSet, nullptr);
148 if (ret != HKS_SUCCESS) {
149 NETMGR_EXT_LOG_E("%{public}s generate key failed:%{public}d", __func__, keyExist);
150 }
151 return ret;
152 } else if (keyExist != HKS_SUCCESS) {
153 NETMGR_EXT_LOG_E("%{public}s search key failed:%{public}d", __func__, keyExist);
154 return keyExist;
155 }
156 return keyExist;
157 }
158
VpnBuildHksParamSet(struct HksParamSet ** paramSet,int32_t userId)159 int32_t VpnBuildHksParamSet(struct HksParamSet **paramSet, int32_t userId)
160 {
161 uint8_t nonce[NONCE_SIZE] = {0};
162 struct HksParam IVParam[] = {
163 { .tag = HKS_TAG_NONCE, .blob = { .size = NONCE_SIZE, .data = nonce } },
164 };
165 g_genParam[0].int32Param = userId;
166 int32_t ret = HksInitParamSet(paramSet);
167 if (ret != HKS_SUCCESS) {
168 NETMGR_EXT_LOG_E("HksInitParamSet failed");
169 return ret;
170 }
171 ret = HksAddParams(*paramSet, g_genParam, sizeof(g_genParam) / sizeof(HksParam));
172 if (ret != HKS_SUCCESS) {
173 NETMGR_EXT_LOG_E("HksAddParams g_genParam failed");
174 HksFreeParamSet(paramSet);
175 return ret;
176 }
177 ret = HksAddParams(*paramSet, IVParam, sizeof(IVParam) / sizeof(HksParam));
178 if (ret != HKS_SUCCESS) {
179 NETMGR_EXT_LOG_E("HksAddParams IVParam failed");
180 HksFreeParamSet(paramSet);
181 return ret;
182 }
183 ret = HksBuildParamSet(paramSet);
184 if (ret != HKS_SUCCESS) {
185 NETMGR_EXT_LOG_E("HksBuildParamSet failed");
186 HksFreeParamSet(paramSet);
187 return ret;
188 }
189 return ret;
190 }
191
VpnEncryptData(const VpnEncryptionInfo & vpnEncryptionInfo,std::string & data)192 int32_t VpnEncryptData(const VpnEncryptionInfo &vpnEncryptionInfo, std::string &data)
193 {
194 if (!data.empty()) {
195 EncryptedData encryptedData;
196 if (VpnEncryption(vpnEncryptionInfo, data, encryptedData) != HKS_SUCCESS) {
197 NETMGR_EXT_LOG_E("VpnEncryption failed");
198 return NETMANAGER_EXT_ERR_INTERNAL;
199 }
200 data = encryptedData.encryptedData_ + ENCRYT_SPLIT_SEP + encryptedData.iv_;
201 }
202 return NETMANAGER_EXT_SUCCESS;
203 }
204
VpnDecryptData(const VpnEncryptionInfo & vpnEncryptionInfo,std::string & data)205 int32_t VpnDecryptData(const VpnEncryptionInfo &vpnEncryptionInfo, std::string &data)
206 {
207 if (!data.empty()) {
208 const std::vector<std::string> encryedDataStrs = Split(data, ENCRYT_SPLIT_SEP);
209 if (encryedDataStrs.size() > 1) {
210 EncryptedData *encryptedData = new (std::nothrow) EncryptedData(encryedDataStrs[0], encryedDataStrs[1]);
211 if (encryptedData == nullptr) {
212 NETMGR_EXT_LOG_E("new EncryptedData failed");
213 return NETMANAGER_EXT_ERR_INTERNAL;
214 }
215 std::string decryptedData = "";
216 if (VpnDecryption(vpnEncryptionInfo, *encryptedData, decryptedData) != HKS_SUCCESS) {
217 NETMGR_EXT_LOG_E("VpnDecryption failed");
218 delete encryptedData;
219 encryptedData = nullptr;
220 return NETMANAGER_EXT_ERR_INTERNAL;
221 }
222 data = decryptedData;
223 delete encryptedData;
224 encryptedData = nullptr;
225 }
226 }
227 return NETMANAGER_EXT_SUCCESS;
228 }
229
VpnEncryption(const VpnEncryptionInfo & vpnEncryptionInfo,const std::string & inputString,EncryptedData & encryptedData)230 int32_t VpnEncryption(const VpnEncryptionInfo &vpnEncryptionInfo, const std::string &inputString,
231 EncryptedData &encryptedData)
232 {
233 if (inputString.length() == 0) {
234 return HKS_SUCCESS;
235 }
236 struct HksBlob authId = vpnEncryptionInfo.keyAlias;
237 struct HksBlob plainText = { inputString.length(), (uint8_t *)&inputString[0] };
238
239 uint8_t nonce[NONCE_SIZE] = {0};
240 struct HksBlob randomIV = {NONCE_SIZE, nonce};
241 int32_t ret = HksGenerateRandom(NULL, &randomIV);
242 if (ret != HKS_SUCCESS) {
243 NETMGR_EXT_LOG_E("vpn encryption generate IV failed");
244 return ret;
245 }
246
247 struct HksParamSet *encryParamSet = nullptr;
248 ret = VpnBuildHksParamSet(&encryParamSet, vpnEncryptionInfo.userId);
249 if (ret != HKS_SUCCESS) {
250 NETMGR_EXT_LOG_E("VpnBuildHksParamSet failed");
251 return ret;
252 }
253
254 ret = GetKeyByAlias(&authId, encryParamSet);
255 if (ret != HKS_SUCCESS) {
256 NETMGR_EXT_LOG_E("vpn encryption failed");
257 HksFreeParamSet(&encryParamSet);
258 return ret;
259 }
260
261 uint8_t cipherBuf[AES_COMMON_SIZE] = {0};
262 HksBlob cipherData = {
263 .size = AES_COMMON_SIZE,
264 .data = cipherBuf
265 };
266
267 ret = HksEncrypt(&authId, encryParamSet, &plainText, &cipherData);
268 if (ret != HKS_SUCCESS) {
269 NETMGR_EXT_LOG_E("Hks encryption failed");
270 HksFreeParamSet(&encryParamSet);
271 return ret;
272 }
273
274 encryptedData.encryptedData_ = ConvertArrayToHex(cipherBuf, cipherData.size);
275 encryptedData.iv_ = ConvertArrayToHex(nonce, NONCE_SIZE);
276 HksFreeParamSet(&encryParamSet);
277 return ret;
278 }
279
VpnDecryption(const VpnEncryptionInfo & vpnEncryptionInfo,const EncryptedData & encryptedData,std::string & decryptedData)280 int32_t VpnDecryption(const VpnEncryptionInfo &vpnEncryptionInfo, const EncryptedData &encryptedData,
281 std::string &decryptedData)
282 {
283 if (encryptedData.encryptedData_.size() == 0) {
284 return HKS_SUCCESS;
285 }
286 struct HksBlob authId = vpnEncryptionInfo.keyAlias;
287 uint8_t cipherBuf[AES_COMMON_SIZE] = {0};
288 uint32_t length = AES_COMMON_SIZE;
289 int32_t retStrToArrat = HexStringToVec(encryptedData.encryptedData_, cipherBuf, AES_COMMON_SIZE, length);
290 if (retStrToArrat != 0) {
291 return HKS_FAILURE;
292 }
293
294 uint8_t nonce[NONCE_SIZE] = {0};
295 uint32_t lengthIV = NONCE_SIZE;
296 retStrToArrat = HexStringToVec(encryptedData.iv_, nonce, NONCE_SIZE, lengthIV);
297 if (retStrToArrat != 0) {
298 return HKS_FAILURE;
299 }
300
301 struct HksBlob cipherData = { length, cipherBuf };
302 struct HksParamSet *decryParamSet = nullptr;
303 int32_t ret = VpnBuildHksParamSet(&decryParamSet, vpnEncryptionInfo.userId);
304 if (ret != HKS_SUCCESS) {
305 NETMGR_EXT_LOG_E("BuildHksParamSet failed");
306 return ret;
307 }
308
309 ret = HksKeyExist(&authId, decryParamSet);
310 if (ret != HKS_SUCCESS) {
311 NETMGR_EXT_LOG_E("vpn decryption key not exist");
312 HksFreeParamSet(&decryParamSet);
313 return ret;
314 }
315 uint8_t plainBuff[AES_COMMON_SIZE] = {0};
316 HksBlob plainText = {
317 .size = AES_COMMON_SIZE,
318 .data = plainBuff
319 };
320
321 ret = HksDecrypt(&authId, decryParamSet, &cipherData, &plainText);
322 if (ret != HKS_SUCCESS) {
323 NETMGR_EXT_LOG_E("Hks decryption failed");
324 HksFreeParamSet(&decryParamSet);
325 return ret;
326 }
327
328 std::string temp(plainText.data, plainText.data + plainText.size);
329 decryptedData = temp;
330 HksFreeParamSet(&decryParamSet);
331 return ret;
332 }
333
334 } // namespace NetManagerStandard
335 } // namespace OHOS