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
30 namespace OHOS {
31 static bool g_testFlag = true;
32
AesEncrypt(HcfCipher * cipher,HcfSymKey * key,HcfParamsSpec * params,uint8_t * cipherText,int * cipherTextLen)33 static int32_t AesEncrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params,
34 uint8_t *cipherText, int *cipherTextLen)
35 {
36 uint8_t plainText[] = "this is test!";
37 HcfBlob input = {.data = reinterpret_cast<uint8_t *>(plainText), .len = 13};
38 HcfBlob output = {};
39 int32_t maxLen = *cipherTextLen;
40 int32_t ret = cipher->init(cipher, ENCRYPT_MODE, &(key->key), params);
41 if (ret != 0) {
42 return ret;
43 }
44
45 ret = cipher->update(cipher, &input, &output);
46 if (ret != 0) {
47 return ret;
48 }
49 *cipherTextLen = output.len;
50 if (output.len > 0 && output.data != nullptr) {
51 (void)memcpy_s(cipherText, maxLen, output.data, output.len);
52 }
53 if (output.data != nullptr) {
54 HcfBlobDataClearAndFree(&output);
55 output.data = nullptr;
56 }
57 ret = cipher->doFinal(cipher, nullptr, &output);
58 if (ret != 0) {
59 return ret;
60 }
61 if (output.len > 0 && output.data != nullptr) {
62 (void)memcpy_s(cipherText + *cipherTextLen, maxLen - *cipherTextLen, output.data, output.len);
63 }
64 *cipherTextLen += output.len;
65 if (output.data != nullptr) {
66 HcfBlobDataClearAndFree(&output);
67 output.data = nullptr;
68 }
69 return 0;
70 }
71
AesDecrypt(HcfCipher * cipher,HcfSymKey * key,HcfParamsSpec * params,uint8_t * cipherText,int cipherTextLen)72 static int32_t AesDecrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params,
73 uint8_t *cipherText, int cipherTextLen)
74 {
75 uint8_t plainText[] = "this is test!";
76 HcfBlob input = {.data = cipherText, .len = cipherTextLen};
77 HcfBlob output = {};
78 int32_t maxLen = cipherTextLen;
79 int32_t ret = cipher->init(cipher, DECRYPT_MODE, &(key->key), params);
80 if (ret != 0) {
81 return ret;
82 }
83
84 ret = cipher->update(cipher, &input, &output);
85 if (ret != 0) {
86 return ret;
87 }
88 if (output.len > 0 && output.data != nullptr) {
89 (void)memcpy_s(cipherText, maxLen, output.data, output.len);
90 }
91 cipherTextLen = output.len;
92 if (output.data != nullptr) {
93 HcfBlobDataClearAndFree(&output);
94 output.data = nullptr;
95 output.len = 0;
96 }
97 ret = cipher->doFinal(cipher, nullptr, &output);
98 if (ret != 0) {
99 return ret;
100 }
101 if (output.len > 0 && output.data != nullptr) {
102 (void)memcpy_s(cipherText + cipherTextLen, maxLen - cipherTextLen, output.data, output.len);
103 }
104 cipherTextLen += output.len;
105 if (output.data != nullptr) {
106 HcfBlobDataClearAndFree(&output);
107 output.data = nullptr;
108 output.len = 0;
109 }
110 ret = memcmp(cipherText, plainText, cipherTextLen);
111 ret = ret || (cipherTextLen == sizeof(plainText) - 1) ? 0 : 1;
112 return ret;
113 }
114
TestAesCipher(void)115 static void TestAesCipher(void)
116 {
117 int ret = 0;
118 uint8_t cipherText[128] = {0};
119 int cipherTextLen = 128;
120 HcfSymKeyGenerator *generator = nullptr;
121 HcfCipher *cipher = nullptr;
122 HcfSymKey *key = nullptr;
123 ret = HcfSymKeyGeneratorCreate("AES128", &generator);
124 if (ret != HCF_SUCCESS) {
125 return;
126 }
127 ret = generator->generateSymKey(generator, &key);
128 if (ret != HCF_SUCCESS) {
129 HcfObjDestroy(generator);
130 return;
131 }
132 ret = HcfCipherCreate("AES128|ECB|NoPadding", &cipher);
133 if (ret != HCF_SUCCESS) {
134 HcfObjDestroy(generator);
135 HcfObjDestroy(key);
136 return;
137 }
138
139 (void)AesEncrypt(cipher, key, nullptr, cipherText, &cipherTextLen);
140 (void)AesDecrypt(cipher, key, nullptr, cipherText, cipherTextLen);
141 HcfObjDestroy(generator);
142 HcfObjDestroy(key);
143 HcfObjDestroy(cipher);
144 }
145
TestRsaCipher(void)146 static void TestRsaCipher(void)
147 {
148 HcfResult res = HCF_SUCCESS;
149 uint8_t plan[] = "this is rsa cipher test!\0";
150 HcfAsyKeyGenerator *generator = nullptr;
151 res = HcfAsyKeyGeneratorCreate("RSA1024|PRIMES_2", &generator);
152 if (res != HCF_SUCCESS) {
153 return;
154 }
155 HcfKeyPair *keyPair = nullptr;
156 res = generator->generateKeyPair(generator, nullptr, &keyPair);
157 if (res != HCF_SUCCESS) {
158 HcfObjDestroy(generator);
159 return;
160 }
161
162 HcfBlob input = { .data = plan, .len = strlen(reinterpret_cast<char *>(plan)) };
163 HcfBlob encoutput = {.data = nullptr, .len = 0};
164 HcfCipher *cipher = nullptr;
165 res = HcfCipherCreate("RSA1024|PKCS1", &cipher);
166 if (res != HCF_SUCCESS) {
167 HcfObjDestroy(generator);
168 HcfObjDestroy(keyPair);
169 return;
170 }
171
172 (void)cipher->init(cipher, ENCRYPT_MODE, reinterpret_cast<HcfKey *>(keyPair->pubKey), nullptr);
173 (void)cipher->doFinal(cipher, &input, &encoutput);
174 HcfObjDestroy(cipher);
175
176 HcfBlob decoutput = {.data = nullptr, .len = 0};
177 cipher = nullptr;
178 res = HcfCipherCreate("RSA1024|PKCS1", &cipher);
179 if (res != HCF_SUCCESS) {
180 HcfObjDestroy(generator);
181 HcfObjDestroy(keyPair);
182 return;
183 }
184 (void)cipher->init(cipher, DECRYPT_MODE, reinterpret_cast<HcfKey *>(keyPair->priKey), nullptr);
185 (void)cipher->doFinal(cipher, &encoutput, &decoutput);
186 HcfBlobDataClearAndFree(&encoutput);
187 HcfBlobDataClearAndFree(&decoutput);
188 HcfObjDestroy(generator);
189 HcfObjDestroy(keyPair);
190 HcfObjDestroy(cipher);
191 }
192
HcfCipherCreateFuzzTest(const uint8_t * data,size_t size)193 bool HcfCipherCreateFuzzTest(const uint8_t* data, size_t size)
194 {
195 if (g_testFlag) {
196 TestRsaCipher();
197 TestAesCipher();
198 g_testFlag = false;
199 }
200 HcfCipher *cipher = nullptr;
201 std::string algoName(reinterpret_cast<const char *>(data), size);
202 HcfResult res = HcfCipherCreate(algoName.c_str(), &cipher);
203 if (res != HCF_SUCCESS) {
204 return false;
205 }
206 HcfObjDestroy(cipher);
207 return true;
208 }
209 }
210
211 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)212 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
213 {
214 /* Run your code on data */
215 OHOS::HcfCipherCreateFuzzTest(data, size);
216 return 0;
217 }
218