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