• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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