1 /*
2 * Copyright (C) 2024 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 <fstream>
17 #include <iostream>
18 #include "securec.h"
19 #include "aes_openssl.h"
20 #include "aes_common.h"
21 #include "blob.h"
22 #include "cipher.h"
23 #include "detailed_iv_params.h"
24 #include "detailed_gcm_params.h"
25 #include "detailed_ccm_params.h"
26 #include "log.h"
27 #include "memory.h"
28 #include "sym_common_defines.h"
29 #include "sym_key_generator.h"
30 #include "sm4_common.h"
31 #include "sm4_openssl.h"
32
33 using namespace std;
34
GenerateSm4SymKey(HcfSymKey ** key)35 HcfResult GenerateSm4SymKey(HcfSymKey **key)
36 {
37 HcfSymKeyGenerator *generator = nullptr;
38
39 HcfResult ret = HcfSymKeyGeneratorCreate("SM4_128", &generator);
40 if (ret != HCF_SUCCESS || generator == nullptr) {
41 LOGE("HcfSymKeyGeneratorCreate failed!");
42 return ret;
43 }
44
45 ret = generator->generateSymKey(generator, key);
46 if (ret != HCF_SUCCESS) {
47 LOGE("generateSymKey failed!");
48 }
49 HcfObjDestroy(generator);
50 return ret;
51 }
52
GenerateSymKeyForSm4(const char * algoName,HcfSymKey ** key)53 int32_t GenerateSymKeyForSm4(const char *algoName, HcfSymKey **key)
54 {
55 HcfSymKeyGenerator *generator = nullptr;
56
57 int32_t ret = HcfSymKeyGeneratorCreate(algoName, &generator);
58 if (ret != 0 || generator == nullptr) {
59 LOGE("HcfSymKeyGeneratorCreate failed!");
60 return ret;
61 }
62
63 ret = generator->generateSymKey(generator, key);
64 if (ret != 0) {
65 LOGE("generateSymKey failed!");
66 }
67 HcfObjDestroy(reinterpret_cast<HcfObjectBase *>(generator));
68 return ret;
69 }
70
71
72 // use ECB, test abnormal input
Sm4EncryptWithInput(HcfCipher * cipher,HcfSymKey * key,HcfBlob * input,uint8_t * cipherText,int * cipherTextLen)73 int32_t Sm4EncryptWithInput(HcfCipher *cipher, HcfSymKey *key, HcfBlob *input,
74 uint8_t *cipherText, int *cipherTextLen)
75 {
76 HcfBlob output = { .data = nullptr, .len = 0 };
77 int32_t maxLen = *cipherTextLen;
78 int32_t ret = cipher->init(cipher, ENCRYPT_MODE, &(key->key), nullptr);
79 if (ret != 0) {
80 LOGE("init failed! %d", ret);
81 return ret;
82 }
83
84 ret = cipher->update(cipher, input, &output);
85 if (ret != 0) {
86 LOGE("update failed!");
87 return ret;
88 }
89 *cipherTextLen = output.len;
90 if (output.data != nullptr) {
91 if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) {
92 HcfBlobDataFree(&output);
93 return -1;
94 }
95 HcfBlobDataFree(&output);
96 }
97
98 ret = cipher->doFinal(cipher, nullptr, &output);
99 if (ret != 0) {
100 LOGE("doFinal failed!");
101 return ret;
102 }
103 if (output.data != nullptr) {
104 if (memcpy_s(cipherText + *cipherTextLen, maxLen - *cipherTextLen, output.data, output.len) != EOK) {
105 HcfBlobDataFree(&output);
106 return -1;
107 }
108 *cipherTextLen += output.len;
109 HcfBlobDataFree(&output);
110 }
111
112 return 0;
113 }
114
115 // test encrypt and decrypt with null plain text
Sm4DecryptEmptyMsg(HcfCipher * cipher,HcfSymKey * key,HcfParamsSpec * params,uint8_t * cipherText,int cipherTextLen)116 int32_t Sm4DecryptEmptyMsg(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params,
117 uint8_t *cipherText, int cipherTextLen)
118 {
119 HcfBlob input = { .data = cipherText, .len = cipherTextLen };
120 HcfBlob output = { .data = nullptr, .len = 0 };
121 int32_t ret = cipher->init(cipher, DECRYPT_MODE, &(key->key), params);
122 if (ret != 0) {
123 LOGE("init failed! %d", ret);
124 return ret;
125 }
126
127 ret = cipher->doFinal(cipher, &input, &output);
128 if (ret != 0) {
129 LOGE("doFinal failed!");
130 return ret;
131 }
132 if (output.len == 0 && output.data == nullptr) {
133 ret = 0;
134 } else {
135 ret = -1;
136 }
137 HcfBlobDataFree(&output);
138 return ret;
139 }
140
141
Sm4Encrypt(HcfCipher * cipher,HcfSymKey * key,HcfParamsSpec * params,uint8_t * cipherText,int * cipherTextLen)142 int32_t Sm4Encrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params,
143 uint8_t *cipherText, int *cipherTextLen)
144 {
145 uint8_t plainText[] = "this is test!";
146 HcfBlob input = {.data = reinterpret_cast<uint8_t *>(plainText), .len = 13};
147 HcfBlob output = {};
148 int32_t maxLen = *cipherTextLen;
149 int32_t ret = cipher->init(cipher, ENCRYPT_MODE, reinterpret_cast<HcfKey *>(key), params);
150 if (ret != 0) {
151 LOGE("init failed! ");
152 return ret;
153 }
154
155 ret = cipher->update(cipher, &input, &output);
156 if (ret != 0) {
157 LOGE("update failed!");
158 return ret;
159 }
160 *cipherTextLen = output.len;
161 if (output.data != nullptr) {
162 if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) {
163 HcfBlobDataFree(&output);
164 return -1;
165 }
166 HcfBlobDataFree(&output);
167 }
168
169 ret = cipher->doFinal(cipher, nullptr, &output);
170 if (ret != 0) {
171 LOGE("doFinal failed!");
172 return ret;
173 }
174 if (output.data != nullptr) {
175 if (memcpy_s(cipherText + *cipherTextLen, maxLen - *cipherTextLen, output.data, output.len) != EOK) {
176 HcfBlobDataFree(&output);
177 return -1;
178 }
179 *cipherTextLen += output.len;
180 HcfBlobDataFree(&output);
181 }
182 return 0;
183 }
184
Sm4Decrypt(HcfCipher * cipher,HcfSymKey * key,HcfParamsSpec * params,uint8_t * cipherText,int cipherTextLen)185 int32_t Sm4Decrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params,
186 uint8_t *cipherText, int cipherTextLen)
187 {
188 uint8_t plainText[] = "this is test!";
189 HcfBlob input = {.data = reinterpret_cast<uint8_t *>(cipherText), .len = cipherTextLen};
190 HcfBlob output = {};
191 int32_t maxLen = cipherTextLen;
192 int32_t ret = cipher->init(cipher, DECRYPT_MODE, reinterpret_cast<HcfKey *>(key), params);
193 if (ret != 0) {
194 LOGE("init failed! ");
195 return ret;
196 }
197
198 ret = cipher->update(cipher, &input, &output);
199 if (ret != 0) {
200 LOGE("update failed!");
201 return ret;
202 }
203 cipherTextLen = output.len;
204 if (output.data != nullptr) {
205 if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) {
206 HcfBlobDataFree(&output);
207 return -1;
208 }
209 HcfBlobDataFree(&output);
210 }
211
212 ret = cipher->doFinal(cipher, nullptr, &output);
213 if (ret != 0) {
214 LOGE("doFinal failed!");
215 return ret;
216 }
217 if (output.data != nullptr) {
218 if (memcpy_s(cipherText + cipherTextLen, maxLen - cipherTextLen, output.data, output.len) != EOK) {
219 HcfBlobDataFree(&output);
220 return -1;
221 }
222 cipherTextLen += output.len;
223 HcfBlobDataFree(&output);
224 }
225
226 if (cipherTextLen != sizeof(plainText) - 1) {
227 return -1;
228 }
229 return memcmp(cipherText, plainText, cipherTextLen);
230 }
231
Sm4NoUpdateEncrypt(HcfCipher * cipher,HcfSymKey * key,HcfParamsSpec * params,uint8_t * cipherText,int * cipherTextLen)232 int32_t Sm4NoUpdateEncrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params,
233 uint8_t *cipherText, int *cipherTextLen)
234 {
235 uint8_t plainText[] = "this is test!";
236 HcfBlob input = {.data = reinterpret_cast<uint8_t *>(plainText), .len = 13};
237 HcfBlob output = {};
238 int32_t maxLen = *cipherTextLen;
239 int32_t ret = cipher->init(cipher, ENCRYPT_MODE, reinterpret_cast<HcfKey *>(key), params);
240 if (ret != 0) {
241 LOGE("init failed! ");
242 return ret;
243 }
244
245 *cipherTextLen = 0;
246 ret = cipher->doFinal(cipher, &input, &output);
247 if (ret != 0) {
248 LOGE("doFinal failed!");
249 return ret;
250 }
251 if (output.data != nullptr) {
252 if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) {
253 HcfBlobDataFree(&output);
254 return -1;
255 }
256 *cipherTextLen += output.len;
257 HcfBlobDataFree(&output);
258 }
259 return 0;
260 }
261
Sm4NoUpdateDecrypt(HcfCipher * cipher,HcfSymKey * key,HcfParamsSpec * params,uint8_t * cipherText,int cipherTextLen)262 int32_t Sm4NoUpdateDecrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params,
263 uint8_t *cipherText, int cipherTextLen)
264 {
265 uint8_t plainText[] = "this is test!";
266 HcfBlob input = {.data = reinterpret_cast<uint8_t *>(cipherText), .len = cipherTextLen};
267 HcfBlob output = {};
268 int32_t maxLen = cipherTextLen;
269 int32_t ret = cipher->init(cipher, DECRYPT_MODE, reinterpret_cast<HcfKey *>(key), params);
270 if (ret != 0) {
271 LOGE("init failed! ");
272 return ret;
273 }
274
275 cipherTextLen = 0;
276 ret = cipher->doFinal(cipher, &input, &output);
277 if (ret != 0) {
278 LOGE("doFinal failed!");
279 return ret;
280 }
281 if (output.data != nullptr) {
282 if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) {
283 HcfBlobDataFree(&output);
284 return -1;
285 }
286 cipherTextLen += output.len;
287 HcfBlobDataFree(&output);
288 }
289
290 if (cipherTextLen != sizeof(plainText) - 1) {
291 return -1;
292 }
293 return memcmp(cipherText, plainText, cipherTextLen);
294 }
295
GetMockClass(void)296 const char *GetMockClass(void)
297 {
298 return "HcfMock";
299 }
300
301 HcfObjectBase obj = {
302 .getClass = GetMockClass,
303 .destroy = nullptr
304 };