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
16 #include "tel_aes_crypto_util.h"
17
18 #include <algorithm>
19
20 #include "securec.h"
21 #include "tel_profile_util.h"
22 #include "telephony_log_wrapper.h"
23
24 namespace OHOS {
25 namespace Telephony {
26 constexpr uint32_t MAX_UPDATE_SIZE = 1024;
27 constexpr uint32_t AAD_SIZE = 16;
28 constexpr uint32_t NONCE_SIZE = 12;
29 constexpr uint32_t AEAD_SIZE = 16;
30 constexpr uint8_t AAD[AAD_SIZE] = {0};
31 constexpr uint8_t NONCE[NONCE_SIZE] = {0};
32 constexpr uint8_t AEAD[AEAD_SIZE] = {0};
33 constexpr const char TEL_AES_KEY_ALIAS[] = "TelAesKeyAlias";
34
35 constexpr size_t HEX_UNIT_LEN = 2;
36 constexpr int32_t ENCODE_UNIT_LEN = 3;
37 constexpr int32_t HEX_OFFSET = 16;
38 constexpr int32_t DEC_OFFSET = 10;
39
40 #define AES_ALGORITHM_PARAM \
41 { \
42 .tag = HKS_TAG_ALGORITHM, \
43 .uint32Param = HKS_ALG_AES \
44 }, { \
45 .tag = HKS_TAG_KEY_SIZE, \
46 .uint32Param = HKS_AES_KEY_SIZE_128 \
47 }, { \
48 .tag = HKS_TAG_PADDING, \
49 .uint32Param = HKS_PADDING_NONE \
50 }, { \
51 .tag = HKS_TAG_BLOCK_MODE, \
52 .uint32Param = HKS_MODE_GCM \
53 }, { \
54 .tag = HKS_TAG_AUTH_STORAGE_LEVEL, \
55 .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE \
56 }
57
58 #define GCM_MODE_PARAM \
59 { \
60 .tag = HKS_TAG_DIGEST, \
61 .uint32Param = HKS_DIGEST_NONE \
62 }, { \
63 .tag = HKS_TAG_ASSOCIATED_DATA, \
64 .blob = { \
65 .size = AAD_SIZE, \
66 .data = (uint8_t *)AAD \
67 } \
68 }, { \
69 .tag = HKS_TAG_NONCE, \
70 .blob = { \
71 .size = NONCE_SIZE, \
72 .data = (uint8_t *)NONCE \
73 } \
74 }
75
SaveEncryptString(const std::string & key,int32_t id,const std::string & rawData)76 int TelAesCryptoUtils::SaveEncryptString(const std::string &key, int32_t id, const std::string &rawData)
77 {
78 auto telProfileUtil = DelayedSingleton<TelProfileUtil>::GetInstance();
79 std::string encryptValue = AesCryptoEncrypt(rawData);
80 return telProfileUtil->SaveString(key + std::to_string(id), encryptValue);
81 }
82
ObtainDecryptString(const std::string & key,int32_t id,const std::string & defValue)83 std::string TelAesCryptoUtils::ObtainDecryptString(const std::string &key, int32_t id, const std::string &defValue)
84 {
85 auto telProfileUtil = DelayedSingleton<TelProfileUtil>::GetInstance();
86 std::string encryptValue = telProfileUtil->ObtainString(key + std::to_string(id), defValue);
87 std::string str = AesCryptoDecrypt(encryptValue);
88 return str;
89 }
90
AesCryptoEncrypt(const std::string & srcData)91 std::string TelAesCryptoUtils::AesCryptoEncrypt(const std::string &srcData)
92 {
93 if (srcData.empty()) {
94 return "";
95 }
96 struct HksBlob keyAlias = { strlen(TEL_AES_KEY_ALIAS), (uint8_t *)TEL_AES_KEY_ALIAS };
97
98 struct HksParamSet *genParamSet = nullptr;
99 struct HksParam genParams[] = {
100 {
101 .tag = HKS_TAG_PURPOSE,
102 .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT
103 },
104 AES_ALGORITHM_PARAM
105 };
106 int32_t ret = InitParamSet(&genParamSet, genParams, sizeof(genParams) / sizeof(HksParam));
107 if (ret != 0) {
108 HksFreeParamSet(&genParamSet);
109 TELEPHONY_LOGE("InitParamSet genParamSet failed");
110 return "";
111 }
112
113 struct HksParamSet *encryptParamSet = nullptr;
114 static struct HksParam encryptParams[] = {
115 {
116 .tag = HKS_TAG_PURPOSE,
117 .uint32Param = HKS_KEY_PURPOSE_ENCRYPT
118 }, {
119 .tag = HKS_TAG_AE_TAG,
120 .blob = {
121 .size = AEAD_SIZE,
122 .data = (uint8_t *)AEAD
123 }
124 },
125 AES_ALGORITHM_PARAM,
126 GCM_MODE_PARAM
127 };
128 ret = InitParamSet(&encryptParamSet, encryptParams, sizeof(encryptParams) / sizeof(HksParam));
129 if (ret != 0) {
130 TELEPHONY_LOGE("InitParamSet encryptParamSet failed");
131 HksFreeParamSet(&genParamSet);
132 HksFreeParamSet(&encryptParamSet);
133 return "";
134 }
135
136 std::string encryptData = AesCryptoEncryptInner(&keyAlias, genParamSet, encryptParamSet, srcData);
137 HksFreeParamSet(&genParamSet);
138 HksFreeParamSet(&encryptParamSet);
139 return encryptData;
140 }
141
AesCryptoDecrypt(std::string & srcData)142 std::string TelAesCryptoUtils::AesCryptoDecrypt(std::string &srcData)
143 {
144 if (srcData.empty()) {
145 return "";
146 }
147 struct HksBlob keyAlias = { strlen(TEL_AES_KEY_ALIAS), (uint8_t *)TEL_AES_KEY_ALIAS };
148
149 struct HksParamSet *decryptGcmParamSet = nullptr;
150 static struct HksParam decryptGcmParams[] = {
151 {
152 .tag = HKS_TAG_PURPOSE,
153 .uint32Param = HKS_KEY_PURPOSE_DECRYPT
154 },
155 AES_ALGORITHM_PARAM,
156 GCM_MODE_PARAM,
157 {
158 .tag = HKS_TAG_AE_TAG,
159 .blob = {
160 .size = AEAD_SIZE,
161 .data = (uint8_t *)AEAD
162 }
163 }
164 };
165 int32_t ret = InitParamSet(&decryptGcmParamSet, decryptGcmParams, sizeof(decryptGcmParams) / sizeof(HksParam));
166 if (ret != 0) {
167 TELEPHONY_LOGE("InitParamSet decryptGcmParamSet failed");
168 HksFreeParamSet(&decryptGcmParamSet);
169 return "";
170 }
171 std::string decryptData = AesCryptoDecryptInner(&keyAlias, decryptGcmParamSet, srcData);
172 HksFreeParamSet(&decryptGcmParamSet);
173 return decryptData;
174 }
175
InitParamSet(struct HksParamSet ** paramSet,const struct HksParam * params,uint32_t paramCount)176 int32_t TelAesCryptoUtils::InitParamSet(struct HksParamSet **paramSet, const struct HksParam *params,
177 uint32_t paramCount)
178 {
179 int32_t ret = HksInitParamSet(paramSet);
180 if (ret != 0) {
181 TELEPHONY_LOGE("HksInitParamSet failed");
182 return ret;
183 }
184
185 ret = HksAddParams(*paramSet, params, paramCount);
186 if (ret != 0) {
187 TELEPHONY_LOGE("HksAddParams failed");
188 return ret;
189 }
190
191 ret = HksBuildParamSet(paramSet);
192 if (ret != 0) {
193 TELEPHONY_LOGE("HksBuildParamSet failed");
194 return ret;
195 }
196 return ret;
197 }
198
AesCryptoEncryptInner(const struct HksBlob * keyAlias,struct HksParamSet * genParamSet,struct HksParamSet * encryptParamSet,const std::string & srcData)199 std::string TelAesCryptoUtils::AesCryptoEncryptInner(const struct HksBlob *keyAlias,
200 struct HksParamSet *genParamSet, struct HksParamSet *encryptParamSet, const std::string &srcData)
201 {
202 struct HksBlob inData = {
203 srcData.length(),
204 const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(srcData.c_str()))
205 };
206
207 // 1. Generate Key
208 int32_t ret;
209 if (HksKeyExist(keyAlias, genParamSet) != 0) {
210 ret = HksGenerateKey(keyAlias, genParamSet, nullptr);
211 if (ret != 0) {
212 TELEPHONY_LOGE("HksGenerateKey failed");
213 return "";
214 }
215 }
216
217 // 2. Encrypt
218 uint8_t handleData[sizeof(uint64_t)] = {0};
219 struct HksBlob handle = { sizeof(uint64_t), handleData };
220 ret = HksInit(keyAlias, encryptParamSet, &handle, nullptr);
221 if (ret != 0) {
222 TELEPHONY_LOGE("HksInit failed");
223 return "";
224 }
225
226 uint8_t *cipher = (uint8_t *)calloc(srcData.length() + AEAD_SIZE, sizeof(uint8_t));
227 if (cipher == nullptr) {
228 return "";
229 }
230 struct HksBlob cipherText = { srcData.length() + AEAD_SIZE, cipher };
231 ret = AesCryptoLoopUpdate(&handle, encryptParamSet, &inData, &cipherText);
232 if (ret != 0) {
233 TELEPHONY_LOGE("AesCryptoLoopUpdate failed");
234 free(cipher);
235 return "";
236 }
237 std::string encryptStr = DecToHexString(cipherText.data, cipherText.size);
238 free(cipher);
239 return encryptStr;
240 }
241
AesCryptoDecryptInner(const struct HksBlob * keyAlias,struct HksParamSet * decryptGcmParamSet,std::string & srcData)242 std::string TelAesCryptoUtils::AesCryptoDecryptInner(const struct HksBlob *keyAlias,
243 struct HksParamSet *decryptGcmParamSet, std::string &srcData)
244 {
245 std::pair<uint8_t *, size_t> decryptDataPair = HexToDecString(srcData);
246 if (decryptDataPair.first == nullptr || decryptDataPair.second <= 0) {
247 TELEPHONY_LOGE("decryptDataPair is invalid");
248 if (decryptDataPair.first != nullptr) {
249 free(decryptDataPair.first);
250 }
251 return "";
252 }
253 struct HksBlob inData = { decryptDataPair.second, decryptDataPair.first };
254
255 inData.size -= AEAD_SIZE;
256 for (uint32_t i = 0; i < decryptGcmParamSet->paramsCnt; i++) {
257 if (decryptGcmParamSet->params[i].tag == HKS_TAG_AE_TAG) {
258 if (memcpy_s(decryptGcmParamSet->params[i].blob.data, AEAD_SIZE,
259 inData.data + inData.size, AEAD_SIZE) != 0) {
260 TELEPHONY_LOGE("AesCryptoDecryptInner memcpy_s failed");
261 free(inData.data);
262 return "";
263 }
264 break;
265 }
266 }
267
268 uint8_t handleData[sizeof(uint64_t)] = {0};
269 struct HksBlob handle = { sizeof(uint64_t), handleData };
270 int32_t ret = HksInit(keyAlias, decryptGcmParamSet, &handle, nullptr);
271 if (ret != 0) {
272 TELEPHONY_LOGE("AesCryptoDecryptInner HksInit failed");
273 free(inData.data);
274 return "";
275 }
276
277 // Update & Finish
278 uint8_t *plain = (uint8_t *)calloc(decryptDataPair.second, sizeof(uint8_t));
279 if (plain == nullptr) {
280 TELEPHONY_LOGE("AesCryptoDecryptInner calloc failed");
281 free(inData.data);
282 return "";
283 }
284 struct HksBlob plainText = { decryptDataPair.second, plain };
285 ret = AesCryptoLoopUpdate(&handle, decryptGcmParamSet, &inData, &plainText);
286 free(inData.data);
287 if (ret != 0) {
288 TELEPHONY_LOGE("AesCryptoLoopUpdate failed");
289 free(plain);
290 return "";
291 }
292
293 std::string decryptStr((char *)plainText.data);
294 free(plain);
295 return decryptStr;
296 }
297
AesCryptoLoopUpdate(const struct HksBlob * handle,const struct HksParamSet * paramSet,const struct HksBlob * inData,struct HksBlob * outData)298 int32_t TelAesCryptoUtils::AesCryptoLoopUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet,
299 const struct HksBlob *inData, struct HksBlob *outData)
300 {
301 uint32_t inDataSize = inData->size;
302 uint32_t handledInDataSize = 0;
303 struct HksBlob inDataSeg = *inData;
304 struct HksBlob outDataSeg = { MAX_UPDATE_SIZE, NULL };
305 uint8_t *cur = outData->data;
306 outData->size = 0;
307
308 while (handledInDataSize < inDataSize) {
309 uint32_t aesDataLen = std::min(MAX_UPDATE_SIZE, (inDataSize - handledInDataSize));
310 inDataSeg.size = aesDataLen;
311 outDataSeg.size = aesDataLen + AEAD_SIZE;
312 outDataSeg.data = (uint8_t *)malloc(outDataSeg.size);
313 if (outDataSeg.data == nullptr) {
314 return HKS_FAILURE;
315 }
316 int32_t hksResult = 0;
317 if (handledInDataSize + aesDataLen < inDataSize) {
318 hksResult = HksUpdate(handle, paramSet, &inDataSeg, &outDataSeg);
319 } else {
320 hksResult = HksFinish(handle, paramSet, &inDataSeg, &outDataSeg);
321 }
322
323 if (hksResult != 0) {
324 TELEPHONY_LOGE("AesCryptoDecryptInner HksUpdate failed");
325 free(outDataSeg.data);
326 return HKS_FAILURE;
327 }
328 if (memcpy_s(cur, outDataSeg.size, outDataSeg.data, outDataSeg.size) != EOK) {
329 free(outDataSeg.data);
330 return HKS_FAILURE;
331 }
332 cur += outDataSeg.size;
333 outData->size += outDataSeg.size;
334 free(outDataSeg.data);
335 inDataSeg.data += aesDataLen;
336 handledInDataSize += aesDataLen;
337 }
338 return 0;
339 }
340
HexToDec(char hex,uint8_t & decodeValue)341 bool TelAesCryptoUtils::HexToDec(char hex, uint8_t &decodeValue)
342 {
343 if (hex >= '0' && hex <= '9') {
344 decodeValue = static_cast<uint8_t>(hex - '0');
345 return true;
346 }
347 if (hex >= 'a' && hex <= 'f') {
348 decodeValue = static_cast<uint8_t>(hex - 'a' + DEC_OFFSET);
349 return true;
350 }
351 return false;
352 }
353
DecToHexString(const uint8_t * data,size_t len)354 std::string TelAesCryptoUtils::DecToHexString(const uint8_t *data, size_t len)
355 {
356 if (data == nullptr || len == 0) {
357 return "";
358 }
359
360 std::string hexString;
361 char encodeUnit[ENCODE_UNIT_LEN] = {0};
362 for (size_t i = 0; i < len; i++) {
363 if (sprintf_s(encodeUnit, ENCODE_UNIT_LEN, "%02x", data[i]) <= 0) {
364 TELEPHONY_LOGE("DecToHexString failed");
365 return "";
366 }
367 hexString.push_back(encodeUnit[0]);
368 hexString.push_back(encodeUnit[1]);
369 }
370
371 return hexString;
372 }
373
HexToDecString(const std::string & hexString)374 std::pair<uint8_t *, size_t> TelAesCryptoUtils::HexToDecString(const std::string &hexString)
375 {
376 if (hexString.empty() || hexString.length() % HEX_UNIT_LEN != 0) {
377 TELEPHONY_LOGE("HexToDecString failed");
378 return std::make_pair(nullptr, 0);
379 }
380
381 size_t pos = 0;
382 size_t len = hexString.length() / HEX_UNIT_LEN;
383 uint8_t *data = reinterpret_cast<uint8_t *>(calloc(len + 1, sizeof(uint8_t)));
384 if (data == nullptr) {
385 TELEPHONY_LOGE("HexToDecString failed");
386 return std::make_pair(nullptr, 0);
387 }
388 uint8_t decodeUnitFirst;
389 uint8_t decodeUnitSecond;
390 for (size_t i = 0; i < len; i++) {
391 if (!HexToDec(hexString.at(pos), decodeUnitFirst) || !HexToDec(hexString.at(pos + 1), decodeUnitSecond)) {
392 free(data);
393 TELEPHONY_LOGE("HexToDecString failed");
394 return std::make_pair(nullptr, 0);
395 }
396 data[i] = static_cast<uint8_t>(decodeUnitFirst * HEX_OFFSET + decodeUnitSecond);
397 pos += HEX_UNIT_LEN;
398 }
399 return std::make_pair(data, len);
400 }
401 } // namespace UpdateEngine
402 } // namespace OHOS