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 "aes_common.h"
17 #include <fstream>
18 #include <iostream>
19 #include "securec.h"
20
21 #include "aes_openssl.h"
22 #include "blob.h"
23 #include "cipher.h"
24 #include "detailed_iv_params.h"
25 #include "detailed_gcm_params.h"
26 #include "detailed_ccm_params.h"
27 #include "log.h"
28 #include "memory.h"
29 #include "sym_common_defines.h"
30 #include "sym_key_generator.h"
31
32 using namespace std;
33
PrintfHex(const char * tag,uint8_t * in,int inLen)34 void PrintfHex(const char *tag, uint8_t *in, int inLen)
35 {
36 if (!IS_DEBUG) {
37 return;
38 }
39 printf("%s:\n", tag);
40 for (int i = 0; i < inLen; i++) {
41 printf("%02hhX", in[i]);
42 }
43 printf("\n");
44 }
45
GenerateSymKey(const char * algoName,HcfSymKey ** key)46 int32_t GenerateSymKey(const char *algoName, HcfSymKey **key)
47 {
48 HcfSymKeyGenerator *generator = nullptr;
49
50 int32_t ret = HcfSymKeyGeneratorCreate(algoName, &generator);
51 if (ret != 0) {
52 LOGE("HcfSymKeyGeneratorCreate failed!");
53 return ret;
54 }
55
56 ret = generator->generateSymKey(generator, key);
57 if (ret != 0) {
58 LOGE("generateSymKey failed!");
59 }
60 HcfObjDestroy(reinterpret_cast<HcfObjectBase *>(generator));
61 return ret;
62 }
63
ConvertSymKey(const char * algoName,HcfSymKey ** key)64 int32_t ConvertSymKey(const char *algoName, HcfSymKey **key)
65 {
66 HcfSymKeyGenerator *generator = nullptr;
67 uint8_t keyMaterial[] = {
68 0xba, 0x3b, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56,
69 0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c
70 };
71 HcfBlob keyTmpBlob = {.data = reinterpret_cast<uint8_t *>(keyMaterial), .len = 16};
72
73 int32_t ret = HcfSymKeyGeneratorCreate(algoName, &generator);
74 if (ret != 0) {
75 LOGE("HcfSymKeyGeneratorCreate failed!%d", ret);
76 return ret;
77 }
78
79 ret = generator->convertSymKey(generator, &keyTmpBlob, key);
80 if (ret != 0) {
81 LOGE("generateSymKey failed!");
82 }
83 PrintfHex("keybinary", keyTmpBlob.data, keyTmpBlob.len);
84 HcfObjDestroy(reinterpret_cast<HcfObjectBase *>(generator));
85 return ret;
86 }
87
88 /* just rand data fill file for test */
GeneratorFile(const char * fileName,int32_t genFileSize)89 int32_t GeneratorFile(const char *fileName, int32_t genFileSize)
90 {
91 if (genFileSize == 0) {
92 return 0;
93 }
94 std::ifstream file(fileName);
95
96 if (file.good()) {
97 file.close();
98 return 0;
99 }
100 ofstream outfile(fileName, ios::out|ios::binary|ios::app);
101 if (outfile.is_open()) {
102 uint8_t buffer[FILE_BLOCK_SIZE] = {0};
103 while (genFileSize) {
104 for (uint32_t i = 0; i < FILE_BLOCK_SIZE; i++) {
105 buffer[i] = (rand() % RAND_MAX_NUM) + 1;
106 }
107 genFileSize -= FILE_BLOCK_SIZE;
108 outfile.write(reinterpret_cast<const char *>(buffer), FILE_BLOCK_SIZE);
109 }
110 outfile.close();
111 }
112 return 0;
113 }
114
CompareFileContent()115 int32_t CompareFileContent()
116 {
117 int32_t ret = -1;
118 ifstream infile1;
119 ifstream infile2;
120 infile1.open("/data/test_aes.txt", ios::in|ios::binary);
121 infile1.seekg (0, infile1.end);
122 uint32_t length1 = infile1.tellg();
123 infile1.seekg (0, infile1.beg);
124
125 infile2.open("/data/test_aes_new.txt", ios::in|ios::binary);
126 infile2.seekg (0, infile2.end);
127 uint32_t length2 = infile2.tellg();
128 infile2.seekg (0, infile2.beg);
129 if (length1 != length2) {
130 return ret;
131 }
132 uint8_t buffer1[FILE_BLOCK_SIZE] = {0};
133 uint8_t buffer2[FILE_BLOCK_SIZE] = {0};
134 for (uint32_t i = 0; i < length1 / FILE_BLOCK_SIZE; i++) {
135 infile1.read(reinterpret_cast<char *>(buffer1), FILE_BLOCK_SIZE);
136 infile2.read(reinterpret_cast<char *>(buffer2), FILE_BLOCK_SIZE);
137 ret = memcmp(buffer1, buffer2, FILE_BLOCK_SIZE);
138 if (ret != 0) {
139 goto CLEAR_UP;
140 }
141 }
142 CLEAR_UP:
143 infile1.close();
144 infile2.close();
145 return ret;
146 }
147
AesMultiBlockEncrypt(HcfCipher * cipher,HcfSymKey * key,HcfParamsSpec * params)148 int32_t AesMultiBlockEncrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params)
149 {
150 HcfBlob output = {};
151 ifstream infile;
152 ofstream outfile;
153 infile.open("/data/test_aes.txt", ios::in|ios::binary);
154 infile.seekg (0, infile.end);
155 uint32_t length = infile.tellg();
156 infile.seekg (0, infile.beg);
157 uint8_t buffer[1024] = {0};
158 outfile.open("/data/test_aes_enc.txt", ios::out|ios::binary);
159 HcfBlob input = {.data = reinterpret_cast<uint8_t *>(buffer), .len = FILE_BLOCK_SIZE};
160 uint32_t count = length / FILE_BLOCK_SIZE;
161
162 int32_t ret = cipher->init(cipher, ENCRYPT_MODE, reinterpret_cast<HcfKey *>(key), params);
163 if (ret != 0) {
164 LOGE("init failed! %d", ret);
165 goto CLEAR_UP;
166 }
167 for (uint32_t i = 0; i < count; i++) {
168 infile.read(reinterpret_cast<char *>(buffer), FILE_BLOCK_SIZE);
169 ret = cipher->update(cipher, &input, &output);
170 if (ret != 0) {
171 LOGE("update failed!");
172 goto CLEAR_UP;
173 }
174 if (output.data != nullptr && output.len > 0) {
175 outfile.write(reinterpret_cast<const char *>(output.data), output.len);
176 }
177 if (output.data != nullptr) {
178 HcfFree(output.data);
179 output.data = nullptr;
180 }
181 }
182 ret = cipher->doFinal(cipher, nullptr, &output);
183 if (ret != 0) {
184 LOGE("doFinal failed!");
185 goto CLEAR_UP;
186 }
187 if (output.data != nullptr && output.len > 0) {
188 outfile.write(reinterpret_cast<const char *>(output.data), output.len);
189 }
190
191 if (output.data != nullptr) {
192 HcfFree(output.data);
193 output.data = nullptr;
194 }
195 CLEAR_UP:
196 outfile.close();
197 infile.close();
198
199 return ret;
200 }
201
AesMultiBlockDecrypt(HcfCipher * cipher,HcfSymKey * key,HcfParamsSpec * params)202 int32_t AesMultiBlockDecrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params)
203 {
204 HcfBlob output = {};
205 ifstream infile;
206 ofstream outfile;
207 infile.open("/data/test_aes_enc.txt", ios::in|ios::binary);
208 infile.seekg (0, infile.end);
209 uint32_t length = infile.tellg();
210 infile.seekg (0, infile.beg);
211 uint8_t buffer[1024] = {0};
212 outfile.open("/data/test_aes_new.txt", ios::out|ios::binary);
213 HcfBlob input = {.data = reinterpret_cast<uint8_t *>(buffer), .len = FILE_BLOCK_SIZE};
214
215 uint32_t count = length / FILE_BLOCK_SIZE;
216 int32_t ret = cipher->init(cipher, DECRYPT_MODE, reinterpret_cast<HcfKey *>(key), params);
217 if (ret != 0) {
218 LOGE("init failed! %d", ret);
219 goto CLEAR_UP;
220 }
221 for (uint32_t i = 0; i < count; i++) {
222 infile.read(reinterpret_cast<char *>(buffer), FILE_BLOCK_SIZE);
223 ret = cipher->update(cipher, &input, &output);
224 if (ret != 0) {
225 LOGE("update failed!");
226 goto CLEAR_UP;
227 }
228 if (output.data != nullptr && output.len > 0) {
229 outfile.write(reinterpret_cast<const char *>(output.data), output.len);
230 }
231 if (output.data != nullptr) {
232 HcfFree(output.data);
233 output.data = nullptr;
234 }
235 }
236 ret = cipher->doFinal(cipher, nullptr, &output);
237 if (ret != 0) {
238 LOGE("doFinal failed!");
239 goto CLEAR_UP;
240 }
241 if (output.data != nullptr && output.len > 0) {
242 outfile.write(reinterpret_cast<const char *>(output.data), output.len);
243 }
244
245 if (output.data != nullptr) {
246 HcfFree(output.data);
247 output.data = nullptr;
248 }
249 CLEAR_UP:
250 outfile.close();
251 infile.close();
252
253 return ret;
254 }
255
256 // use ECB, test abnormal input
AesEncryptWithInput(HcfCipher * cipher,HcfSymKey * key,HcfBlob * input,uint8_t * cipherText,int * cipherTextLen)257 int32_t AesEncryptWithInput(HcfCipher *cipher, HcfSymKey *key, HcfBlob *input,
258 uint8_t *cipherText, int *cipherTextLen)
259 {
260 HcfBlob output = { .data = nullptr, .len = 0 };
261 int32_t maxLen = *cipherTextLen;
262 int32_t ret = cipher->init(cipher, ENCRYPT_MODE, &(key->key), nullptr);
263 if (ret != 0) {
264 LOGE("init failed! %d", ret);
265 return ret;
266 }
267
268 ret = cipher->update(cipher, input, &output);
269 if (ret != 0) {
270 LOGE("update failed!");
271 return ret;
272 }
273 *cipherTextLen = output.len;
274 if (output.data != nullptr) {
275 if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) {
276 HcfBlobDataFree(&output);
277 return -1;
278 }
279 HcfBlobDataFree(&output);
280 }
281
282 ret = cipher->doFinal(cipher, nullptr, &output);
283 if (ret != 0) {
284 LOGE("doFinal failed!");
285 return ret;
286 }
287 if (output.data != nullptr) {
288 if (memcpy_s(cipherText + *cipherTextLen, maxLen - *cipherTextLen, output.data, output.len) != EOK) {
289 HcfBlobDataFree(&output);
290 return -1;
291 }
292 *cipherTextLen += output.len;
293 HcfBlobDataFree(&output);
294 }
295
296 PrintfHex("ciphertext", cipherText, *cipherTextLen);
297 return 0;
298 }
299
AesEncrypt(HcfCipher * cipher,HcfSymKey * key,HcfParamsSpec * params,uint8_t * cipherText,int * cipherTextLen)300 int32_t AesEncrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params,
301 uint8_t *cipherText, int *cipherTextLen)
302 {
303 uint8_t plainText[] = "this is test!";
304 HcfBlob input = {.data = reinterpret_cast<uint8_t *>(plainText), .len = 13};
305 HcfBlob output = {};
306 int32_t maxLen = *cipherTextLen;
307 int32_t ret = cipher->init(cipher, ENCRYPT_MODE, reinterpret_cast<HcfKey *>(key), params);
308 if (ret != 0) {
309 LOGE("init failed! %d", ret);
310 return ret;
311 }
312
313 ret = cipher->update(cipher, &input, &output);
314 if (ret != 0) {
315 LOGE("update failed!");
316 return ret;
317 }
318 *cipherTextLen = output.len;
319 if (output.data != nullptr) {
320 if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) {
321 HcfBlobDataFree(&output);
322 return -1;
323 }
324 HcfBlobDataFree(&output);
325 }
326
327 ret = cipher->doFinal(cipher, nullptr, &output);
328 if (ret != 0) {
329 LOGE("doFinal failed!");
330 return ret;
331 }
332 if (output.data != nullptr) {
333 if (memcpy_s(cipherText + *cipherTextLen, maxLen - *cipherTextLen, output.data, output.len) != EOK) {
334 HcfBlobDataFree(&output);
335 return -1;
336 }
337 *cipherTextLen += output.len;
338 HcfBlobDataFree(&output);
339 }
340
341 PrintfHex("ciphertext", cipherText, *cipherTextLen);
342 return 0;
343 }
344
AesDecrypt(HcfCipher * cipher,HcfSymKey * key,HcfParamsSpec * params,uint8_t * cipherText,int cipherTextLen)345 int32_t AesDecrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params,
346 uint8_t *cipherText, int cipherTextLen)
347 {
348 uint8_t plainText[] = "this is test!";
349 HcfBlob input = {.data = reinterpret_cast<uint8_t *>(cipherText), .len = cipherTextLen};
350 HcfBlob output = {};
351 int32_t maxLen = cipherTextLen;
352 int32_t ret = cipher->init(cipher, DECRYPT_MODE, reinterpret_cast<HcfKey *>(key), params);
353 if (ret != 0) {
354 LOGE("init failed! %d", ret);
355 return ret;
356 }
357
358 ret = cipher->update(cipher, &input, &output);
359 if (ret != 0) {
360 LOGE("update failed!");
361 return ret;
362 }
363 cipherTextLen = output.len;
364 if (output.data != nullptr) {
365 if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) {
366 HcfBlobDataFree(&output);
367 return -1;
368 }
369 HcfBlobDataFree(&output);
370 }
371
372 ret = cipher->doFinal(cipher, nullptr, &output);
373 if (ret != 0) {
374 LOGE("doFinal failed!");
375 return ret;
376 }
377 if (output.data != nullptr) {
378 if (memcpy_s(cipherText + cipherTextLen, maxLen - cipherTextLen, output.data, output.len) != EOK) {
379 HcfBlobDataFree(&output);
380 return -1;
381 }
382 cipherTextLen += output.len;
383 HcfBlobDataFree(&output);
384 }
385
386 PrintfHex("plainText", cipherText, cipherTextLen);
387 if (cipherTextLen != sizeof(plainText) - 1) {
388 return -1;
389 }
390 return memcmp(cipherText, plainText, cipherTextLen);
391 }
392
AesNoUpdateEncWithInput(HcfCipher * cipher,HcfSymKey * key,HcfBlob * input,uint8_t * cipherText,int * cipherTextLen)393 int32_t AesNoUpdateEncWithInput(HcfCipher *cipher, HcfSymKey *key, HcfBlob *input,
394 uint8_t *cipherText, int *cipherTextLen)
395 {
396 HcfBlob output = { .data = nullptr, .len = 0 };
397 int32_t maxLen = *cipherTextLen;
398 int32_t ret = cipher->init(cipher, ENCRYPT_MODE, &(key->key), nullptr);
399 if (ret != 0) {
400 LOGE("init failed! %d", ret);
401 return ret;
402 }
403
404 *cipherTextLen = 0;
405 ret = cipher->doFinal(cipher, input, &output);
406 if (ret != 0) {
407 LOGE("doFinal failed!");
408 return ret;
409 }
410 if (output.data != nullptr) {
411 if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) {
412 HcfBlobDataFree(&output);
413 return -1;
414 }
415 *cipherTextLen += output.len;
416 HcfBlobDataFree(&output);
417 }
418
419 PrintfHex("ciphertext", cipherText, *cipherTextLen);
420 return 0;
421 }
422
423 // test encrypt and decrypt with null plain text
AesDecryptEmptyMsg(HcfCipher * cipher,HcfSymKey * key,HcfParamsSpec * params,uint8_t * cipherText,int cipherTextLen)424 int32_t AesDecryptEmptyMsg(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params,
425 uint8_t *cipherText, int cipherTextLen)
426 {
427 HcfBlob input = { .data = cipherText, .len = cipherTextLen };
428 HcfBlob output = { .data = nullptr, .len = 0 };
429 int32_t ret = cipher->init(cipher, DECRYPT_MODE, &(key->key), params);
430 if (ret != 0) {
431 LOGE("init failed! %d", ret);
432 return ret;
433 }
434
435 ret = cipher->doFinal(cipher, &input, &output);
436 if (ret != 0) {
437 LOGE("doFinal failed!");
438 return ret;
439 }
440 if (output.len == 0 && output.data == nullptr) {
441 ret = 0;
442 } else {
443 ret = -1;
444 }
445 HcfBlobDataFree(&output);
446 return ret;
447 }
448
AesNoUpdateEncrypt(HcfCipher * cipher,HcfSymKey * key,HcfParamsSpec * params,uint8_t * cipherText,int * cipherTextLen)449 int32_t AesNoUpdateEncrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params,
450 uint8_t *cipherText, int *cipherTextLen)
451 {
452 uint8_t plainText[] = "this is test!";
453 HcfBlob input = {.data = reinterpret_cast<uint8_t *>(plainText), .len = 13};
454 HcfBlob output = {};
455 int32_t maxLen = *cipherTextLen;
456 int32_t ret = cipher->init(cipher, ENCRYPT_MODE, reinterpret_cast<HcfKey *>(key), params);
457 if (ret != 0) {
458 LOGE("init failed! %d", ret);
459 return ret;
460 }
461
462 *cipherTextLen = 0;
463 ret = cipher->doFinal(cipher, &input, &output);
464 if (ret != 0) {
465 LOGE("doFinal failed!");
466 return ret;
467 }
468 if (output.data != nullptr) {
469 if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) {
470 HcfBlobDataFree(&output);
471 return -1;
472 }
473 *cipherTextLen += output.len;
474 HcfBlobDataFree(&output);
475 }
476
477 PrintfHex("ciphertext", cipherText, *cipherTextLen);
478 return 0;
479 }
480
AesNoUpdateDecrypt(HcfCipher * cipher,HcfSymKey * key,HcfParamsSpec * params,uint8_t * cipherText,int cipherTextLen)481 int32_t AesNoUpdateDecrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params,
482 uint8_t *cipherText, int cipherTextLen)
483 {
484 uint8_t plainText[] = "this is test!";
485 HcfBlob input = {.data = reinterpret_cast<uint8_t *>(cipherText), .len = cipherTextLen};
486 HcfBlob output = {};
487 int32_t maxLen = cipherTextLen;
488 int32_t ret = cipher->init(cipher, DECRYPT_MODE, reinterpret_cast<HcfKey *>(key), params);
489 if (ret != 0) {
490 LOGE("init failed! %d", ret);
491 return ret;
492 }
493
494 cipherTextLen = 0;
495 ret = cipher->doFinal(cipher, &input, &output);
496 if (ret != 0) {
497 LOGE("doFinal failed!");
498 return ret;
499 }
500 if (output.data != nullptr) {
501 if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) {
502 HcfBlobDataFree(&output);
503 return -1;
504 }
505 cipherTextLen += output.len;
506 HcfBlobDataFree(&output);
507 }
508
509 PrintfHex("plainText", cipherText, cipherTextLen);
510 if (cipherTextLen != sizeof(plainText) - 1) {
511 return -1;
512 }
513 return memcmp(cipherText, plainText, cipherTextLen);
514 }