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 #include "hcfciphercreate_fuzzer.h"
17
18 #include <cstddef>
19 #include <cstdint>
20 #include <string>
21 #include "securec.h"
22
23 #include "asy_key_generator.h"
24 #include "blob.h"
25 #include "cipher.h"
26 #include "mac.h"
27 #include "result.h"
28 #include "memory.h"
29 #include "sym_key_generator.h"
30 #include "detailed_gcm_params.h"
31
32 namespace OHOS {
AesEncrypt(HcfCipher * cipher,HcfSymKey * key,HcfBlob * input,uint8_t ** cipherText,int * cipherTextLen)33 static int32_t AesEncrypt(HcfCipher *cipher, HcfSymKey *key, HcfBlob *input,
34 uint8_t **cipherText, int *cipherTextLen)
35 {
36 HcfBlob output = {};
37 int32_t maxLen = input->len + 16;
38 int32_t ret = cipher->init(cipher, ENCRYPT_MODE, &(key->key), nullptr);
39 if (ret != 0) {
40 return ret;
41 }
42
43 ret = cipher->update(cipher, input, &output);
44 if (ret != 0) {
45 if (output.data != nullptr) {
46 HcfBlobDataClearAndFree(&output);
47 }
48 return ret;
49 }
50 *cipherTextLen = output.len;
51 *cipherText = static_cast<uint8_t *>(HcfMalloc(maxLen, 0));
52 if (output.len > 0 && output.data != nullptr) {
53 (void)memcpy_s(*cipherText, maxLen, output.data, output.len);
54 }
55 if (output.data != nullptr) {
56 HcfBlobDataClearAndFree(&output);
57 output.data = nullptr;
58 }
59 ret = cipher->doFinal(cipher, nullptr, &output);
60 if (ret != 0) {
61 HcfBlobDataClearAndFree(&output);
62 return ret;
63 }
64 if (output.len > 0 && output.data != nullptr) {
65 (void)memcpy_s(*cipherText + *cipherTextLen, output.len, output.data, output.len);
66 }
67 *cipherTextLen += output.len;
68 if (output.data != nullptr) {
69 HcfBlobDataClearAndFree(&output);
70 output.data = nullptr;
71 }
72 return 0;
73 }
74
AesDecrypt(HcfCipher * cipher,HcfSymKey * key,HcfBlob * input,uint8_t * cipherText,int cipherTextLen)75 static int32_t AesDecrypt(HcfCipher *cipher, HcfSymKey *key, HcfBlob *input, uint8_t *cipherText, int cipherTextLen)
76 {
77 HcfBlob output = {};
78 HcfBlob decryptedData = {};
79 if (cipherTextLen <= 0) {
80 return -1;
81 }
82
83 int32_t ret = cipher->init(cipher, DECRYPT_MODE, &(key->key), nullptr);
84 if (ret != 0) {
85 return ret;
86 }
87
88 HcfBlob cipherBlob = { .data = cipherText, .len = cipherTextLen };
89 ret = cipher->update(cipher, &cipherBlob, &output);
90 if (ret != 0) {
91 goto EXIT;
92 }
93 decryptedData.data = (uint8_t *)HcfMalloc(cipherTextLen, 0);
94 if (decryptedData.data == nullptr) {
95 ret = -1;
96 goto EXIT;
97 }
98 if (output.len > 0 && output.data != nullptr) {
99 (void)memcpy_s(decryptedData.data, cipherTextLen, output.data, output.len);
100 decryptedData.len = output.len;
101 }
102 HcfBlobDataClearAndFree(&output);
103 ret = cipher->doFinal(cipher, nullptr, &output);
104 if (ret != 0) {
105 goto EXIT;
106 }
107 if (output.len > 0 && output.data != nullptr) {
108 (void)memcpy_s(decryptedData.data + decryptedData.len, output.len, output.data, output.len);
109 decryptedData.len += output.len;
110 }
111 if (decryptedData.len != input->len - 1 || memcmp(decryptedData.data, input->data, decryptedData.len) != 0) {
112 ret = 1;
113 } else {
114 ret = 0;
115 }
116 EXIT:
117 if (output.data != nullptr) {
118 HcfBlobDataClearAndFree(&output);
119 }
120 if (decryptedData.data != nullptr) {
121 HcfBlobDataClearAndFree(&decryptedData);
122 }
123 return ret;
124 }
125
Sm4Encrypt(HcfCipher * cipher,HcfSymKey * key,HcfBlob * input,uint8_t ** cipherText,int * cipherTextLen)126 static int32_t Sm4Encrypt(HcfCipher *cipher, HcfSymKey *key, HcfBlob *input,
127 uint8_t **cipherText, int *cipherTextLen)
128 {
129 HcfBlob output = {};
130 int32_t maxLen = input->len + 16;
131 int32_t ret = cipher->init(cipher, ENCRYPT_MODE, reinterpret_cast<HcfKey *>(key), nullptr);
132 if (ret != 0) {
133 return ret;
134 }
135
136 ret = cipher->update(cipher, input, &output);
137 if (ret != 0) {
138 if (output.data != nullptr) {
139 HcfBlobDataClearAndFree(&output);
140 }
141 return ret;
142 }
143 *cipherTextLen = output.len;
144 *cipherText = static_cast<uint8_t *>(HcfMalloc(maxLen, 0));
145 if (output.data != nullptr) {
146 if (memcpy_s(*cipherText, output.len, output.data, output.len) != EOK) {
147 HcfBlobDataFree(&output);
148 return -1;
149 }
150 HcfBlobDataFree(&output);
151 }
152
153 ret = cipher->doFinal(cipher, nullptr, &output);
154 if (ret != 0) {
155 HcfFree(*cipherText);
156 return ret;
157 }
158 if (output.len > 0 && output.data != nullptr) {
159 if (memcpy_s(*cipherText + *cipherTextLen, output.len, output.data, output.len) != EOK) {
160 HcfBlobDataFree(&output);
161 return -1;
162 }
163 *cipherTextLen += output.len;
164 HcfBlobDataFree(&output);
165 }
166 return 0;
167 }
168
Sm4Decrypt(HcfCipher * cipher,HcfSymKey * key,HcfBlob * input,uint8_t * cipherText,int cipherTextLen)169 static int32_t Sm4Decrypt(HcfCipher *cipher, HcfSymKey *key, HcfBlob *input,
170 uint8_t *cipherText, int cipherTextLen)
171 {
172 HcfBlob output = {};
173 HcfBlob decryptedData = {};
174 int32_t ret;
175
176 if (cipherTextLen <= 0) {
177 return -1;
178 }
179 ret = cipher->init(cipher, DECRYPT_MODE, reinterpret_cast<HcfKey *>(key), nullptr);
180 if (ret != 0) {
181 return ret;
182 }
183
184 HcfBlob cipherBlob = { .data = cipherText, .len = cipherTextLen };
185 ret = cipher->update(cipher, &cipherBlob, &output);
186 if (ret != 0) {
187 goto EXIT;
188 }
189
190 decryptedData.data = (uint8_t *)HcfMalloc(cipherTextLen, 0);
191 if (decryptedData.data == nullptr) {
192 ret = -1;
193 goto EXIT;
194 }
195
196 if (output.len > 0 && output.data != nullptr) {
197 (void)memcpy_s(decryptedData.data, output.len, output.data, output.len);
198 decryptedData.len = output.len;
199 }
200 HcfBlobDataClearAndFree(&output);
201 ret = cipher->doFinal(cipher, nullptr, &output);
202 if (ret != 0) {
203 goto EXIT;
204 }
205
206 if (output.len > 0 && output.data != nullptr) {
207 (void)memcpy_s(decryptedData.data + decryptedData.len, output.len, output.data, output.len);
208 decryptedData.len += output.len;
209 }
210
211 if (decryptedData.len != input->len - 1 ||
212 memcmp(decryptedData.data, input->data, decryptedData.len) != 0) {
213 ret = 1;
214 } else {
215 ret = 0;
216 }
217
218 EXIT:
219 if (output.data != nullptr) {
220 HcfBlobDataClearAndFree(&output);
221 }
222 if (decryptedData.data != nullptr) {
223 HcfBlobDataClearAndFree(&decryptedData);
224 }
225 return ret;
226 }
227
TestAesCipher(const uint8_t * plan,size_t size)228 static void TestAesCipher(const uint8_t* plan, size_t size)
229 {
230 int ret = 0;
231 HcfBlob input = {.data = const_cast<uint8_t *>(plan), .len = size};
232 uint8_t *cipherText = nullptr;
233 int cipherTextLen = 0;
234 HcfSymKeyGenerator *generator = nullptr;
235 HcfCipher *cipher = nullptr;
236 HcfSymKey *key = nullptr;
237 ret = HcfSymKeyGeneratorCreate("AES128", &generator);
238 if (ret != HCF_SUCCESS) {
239 return;
240 }
241 ret = generator->generateSymKey(generator, &key);
242 if (ret != HCF_SUCCESS) {
243 HcfObjDestroy(generator);
244 return;
245 }
246 ret = HcfCipherCreate("AES128|ECB|NoPadding", &cipher);
247 if (ret != HCF_SUCCESS) {
248 HcfObjDestroy(generator);
249 HcfObjDestroy(key);
250 return;
251 }
252 (void)AesEncrypt(cipher, key, &input, &cipherText, &cipherTextLen);
253 (void)AesDecrypt(cipher, key, &input, cipherText, cipherTextLen);
254 HcfFree(cipherText);
255 HcfObjDestroy(generator);
256 HcfObjDestroy(key);
257 HcfObjDestroy(cipher);
258 }
259
TestSm4Cipher(const uint8_t * plan,size_t size)260 static void TestSm4Cipher(const uint8_t* plan, size_t size)
261 {
262 int ret = 0;
263 HcfBlob input = {.data = const_cast<uint8_t *>(plan), .len = size};
264 uint8_t *cipherText = nullptr;
265 int cipherTextLen = 0;
266 HcfSymKeyGenerator *generator = nullptr;
267 HcfCipher *cipher = nullptr;
268 HcfSymKey *key = nullptr;
269 ret = HcfSymKeyGeneratorCreate("SM4_128", &generator);
270 if (ret != HCF_SUCCESS) {
271 return;
272 }
273 ret = generator->generateSymKey(generator, &key);
274 if (ret != HCF_SUCCESS) {
275 HcfObjDestroy(generator);
276 return;
277 }
278 ret = HcfCipherCreate("SM4_128|ECB|PKCS5", &cipher);
279 if (ret != HCF_SUCCESS) {
280 HcfObjDestroy(generator);
281 HcfObjDestroy(key);
282 return;
283 }
284
285 (void)Sm4Encrypt(cipher, key, &input, &cipherText, &cipherTextLen);
286 (void)Sm4Decrypt(cipher, key, &input, cipherText, cipherTextLen);
287 HcfFree(cipherText);
288 HcfObjDestroy(generator);
289 HcfObjDestroy(key);
290 HcfObjDestroy(cipher);
291 }
292
TestSm4GcmCipher(const uint8_t * plan,size_t size)293 static void TestSm4GcmCipher(const uint8_t* plan, size_t size)
294 {
295 int ret = 0;
296 HcfBlob input = {.data = const_cast<uint8_t *>(plan), .len = size};
297 uint8_t aad[8] = {0};
298 uint8_t tag[16] = {0};
299 uint8_t iv[12] = {0}; // openssl only support nonce 12 bytes, tag 16bytes
300 uint8_t *cipherText = nullptr;
301 int cipherTextLen = 0;
302
303 HcfGcmParamsSpec spec = {};
304 spec.aad.data = aad;
305 spec.aad.len = sizeof(aad);
306 spec.tag.data = tag;
307 spec.tag.len = sizeof(tag);
308 spec.iv.data = iv;
309 spec.iv.len = sizeof(iv);
310 HcfSymKeyGenerator *generator = nullptr;
311 HcfCipher *cipher = nullptr;
312 HcfSymKey *key = nullptr;
313 ret = HcfSymKeyGeneratorCreate("SM4_128", &generator);
314 if (ret != HCF_SUCCESS) {
315 return;
316 }
317 ret = generator->generateSymKey(generator, &key);
318 if (ret != HCF_SUCCESS) {
319 HcfObjDestroy(generator);
320 return;
321 }
322 ret = HcfCipherCreate("SM4_128|GCM|PKCS5", &cipher);
323 if (ret != HCF_SUCCESS) {
324 HcfObjDestroy(generator);
325 HcfObjDestroy(key);
326 return;
327 }
328
329 (void)Sm4Encrypt(cipher, key, &input, &cipherText, &cipherTextLen);
330 (void)Sm4Decrypt(cipher, key, &input, cipherText, cipherTextLen);
331 HcfObjDestroy(generator);
332 HcfObjDestroy(key);
333 HcfObjDestroy(cipher);
334 }
335
TestRsaCipher(const uint8_t * plan,size_t size)336 static void TestRsaCipher(const uint8_t* plan, size_t size)
337 {
338 HcfResult res = HCF_SUCCESS;
339 HcfAsyKeyGenerator *generator = nullptr;
340 res = HcfAsyKeyGeneratorCreate("RSA1024|PRIMES_2", &generator);
341 if (res != HCF_SUCCESS) {
342 return;
343 }
344 HcfKeyPair *keyPair = nullptr;
345 res = generator->generateKeyPair(generator, nullptr, &keyPair);
346 if (res != HCF_SUCCESS) {
347 HcfObjDestroy(generator);
348 return;
349 }
350
351 HcfBlob input = { .data = const_cast<uint8_t *>(plan), .len = size };
352 HcfBlob encoutput = {.data = nullptr, .len = 0};
353 HcfCipher *cipher = nullptr;
354 res = HcfCipherCreate("RSA1024|PKCS1", &cipher);
355 if (res != HCF_SUCCESS) {
356 HcfObjDestroy(generator);
357 HcfObjDestroy(keyPair);
358 return;
359 }
360
361 (void)cipher->init(cipher, ENCRYPT_MODE, reinterpret_cast<HcfKey *>(keyPair->pubKey), nullptr);
362 (void)cipher->doFinal(cipher, &input, &encoutput);
363 HcfObjDestroy(cipher);
364
365 HcfBlob decoutput = {.data = nullptr, .len = 0};
366 cipher = nullptr;
367 res = HcfCipherCreate("RSA1024|PKCS1", &cipher);
368 if (res != HCF_SUCCESS) {
369 HcfObjDestroy(generator);
370 HcfObjDestroy(keyPair);
371 HcfBlobDataClearAndFree(&encoutput);
372 return;
373 }
374 (void)cipher->init(cipher, DECRYPT_MODE, reinterpret_cast<HcfKey *>(keyPair->priKey), nullptr);
375 (void)cipher->doFinal(cipher, &encoutput, &decoutput);
376 HcfBlobDataClearAndFree(&encoutput);
377 HcfBlobDataClearAndFree(&decoutput);
378 HcfObjDestroy(generator);
379 HcfObjDestroy(keyPair);
380 HcfObjDestroy(cipher);
381 }
382
HcfCipherCreateFuzzTest(const uint8_t * data,size_t size)383 bool HcfCipherCreateFuzzTest(const uint8_t* data, size_t size)
384 {
385 TestRsaCipher(data, size);
386 TestAesCipher(data, size);
387 TestSm4Cipher(data, size);
388 TestSm4GcmCipher(data, size);
389 HcfCipher *cipher = nullptr;
390 std::string algoName(reinterpret_cast<const char *>(data), size);
391 HcfResult res = HcfCipherCreate(algoName.c_str(), &cipher);
392 if (res != HCF_SUCCESS) {
393 return false;
394 }
395 HcfObjDestroy(cipher);
396 return true;
397 }
398 }
399
400 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)401 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
402 {
403 /* Run your code on data */
404 OHOS::HcfCipherCreateFuzzTest(data, size);
405 return 0;
406 }
407