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