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