1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include "drv_osal_lib.h"
20 #include "cryp_hash.h"
21 #include "securec.h"
22
23 #ifdef SOFT_SM3_SUPPORT
24
25 /* ************************** Internal Structure Definition For SM3 *************************** */
rotate_left(hi_u32 x,hi_u32 n)26 static hi_u32 rotate_left(hi_u32 x, hi_u32 n)
27 {
28 n %= SHIFT_32BITS;
29
30 if (n == 0) {
31 return x;
32 }
33
34 return (x << n) | (x >> (SHIFT_32BITS - n));
35 }
36
37 #define p0(x) ((x) ^ rotate_left((x), SHIFT_9BITS) ^ rotate_left((x), SHIFT_17BITS))
38 #define p1(x) ((x) ^ rotate_left((x), SHIFT_15BITS) ^ rotate_left((x), SHIFT_23BITS))
39
40 #define ff0(x, y, z) ((x) ^ (y) ^ (z))
41 #define ff1(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
42
43 #define gg0(x, y, z) ((x) ^ (y) ^ (z))
44 #define gg1(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
45
46 #define SM3_BLOCK_SIZE 64
47 #define SM3_W_SIZE ((SM3_BLOCK_SIZE) + (WORD_WIDTH))
48 #define SM3_RESULT_SIZE_IN_WORD ((SM3_RESULT_SIZE) / (WORD_WIDTH))
49 #define SM3_PAD_MIN_SIZE 9
50 #define SM3_PAD_LEN_SIZE 8
51 #define SM3_BYTE_MSB 0x80
52
53 /* SM3, the initial hash value, sm3_h(0). */
54 #define SM3_H0 0x7380166F
55 #define SM3_H1 0x4914B2B9
56 #define SM3_H2 0x172442D7
57 #define SM3_H3 0xDA8A0600
58 #define SM3_H4 0xA96F30BC
59 #define SM3_H5 0x163138AA
60 #define SM3_H6 0xE38DEE4D
61 #define SM3_H7 0xB0FB0E4E
62
63 /* 64K */
64 #define HASH_MAX_BUFFER_SIZE 0x10000
65
66 /* brief aes ccm context structure */
67 typedef struct {
68 hi_u32 state[SM3_RESULT_SIZE_IN_WORD];
69 hi_u8 tail[SM3_BLOCK_SIZE];
70 hi_u32 tail_len;
71 hi_u32 total;
72 } ext_sm3_context;
73
74 /* ****************************** API Code for sm3 **************************** */
sm3_compress(hi_u32 digest[SM3_RESULT_SIZE_IN_WORD],const hi_u8 block[SM3_BLOCK_SIZE],hi_u32 block_len)75 static hi_s32 sm3_compress(hi_u32 digest[SM3_RESULT_SIZE_IN_WORD],
76 const hi_u8 block[SM3_BLOCK_SIZE], hi_u32 block_len)
77 {
78 hi_s32 j;
79 hi_u32 *sm3_w = HI_NULL;
80 hi_u32 *sm3_w1 = HI_NULL;
81 hi_u32 *sm3_t = HI_NULL;
82 const hi_u32 *local_block = (const hi_u32 *)block;
83 hi_u32 sm3_a = digest[WORD_IDX_0];
84 hi_u32 sm3_b = digest[WORD_IDX_1];
85 hi_u32 sm3_c = digest[WORD_IDX_2];
86 hi_u32 sm3_d = digest[WORD_IDX_3];
87 hi_u32 sm3_e = digest[WORD_IDX_4];
88 hi_u32 sm3_f = digest[WORD_IDX_5];
89 hi_u32 sm3_g = digest[WORD_IDX_6];
90 hi_u32 sm3_h = digest[WORD_IDX_7];
91 hi_u32 sm3_ss1, sm3_ss2, sm3_tt1, sm3_tt2;
92 hi_u32 *buf = HI_NULL;
93 hi_u32 buf_size;
94
95 if (block_len != SM3_BLOCK_SIZE) {
96 return HI_ERR_CIPHER_INVALID_LENGTH;
97 }
98
99 buf_size = sizeof(hi_u32) * (SM3_W_SIZE + SM3_BLOCK_SIZE + SM3_BLOCK_SIZE);
100 buf = (hi_u32 *)crypto_malloc(buf_size);
101 if (buf == HI_NULL) {
102 hi_log_error("sm3 compress crypto malloc buff failed!\n");
103 return HI_ERR_CIPHER_FAILED_MEM;
104 }
105 (hi_void)memset_s(buf, buf_size, 0, buf_size);
106 sm3_w = buf;
107 sm3_w1 = buf + SM3_W_SIZE;
108 sm3_t = buf + SM3_W_SIZE + SM3_BLOCK_SIZE;
109
110 for (j = 0; j < SM3_BLOCK_SIZE / WORD_WIDTH; j++) {
111 sm3_w[j] = crypto_cpu_to_be32(local_block[j]);
112 }
113 for (j = SM3_BLOCK_SIZE / WORD_WIDTH; j < SM3_W_SIZE; j++) {
114 sm3_w[j] = p1(sm3_w[j - 16] ^ sm3_w[j - 9] ^ \ /* soft sm3 alg:offset 16, 9. */
115 rotate_left(sm3_w[j - 3], 15)) ^ \ /* soft sm3 alg:offset 3, and rotate left 15. */
116 rotate_left(sm3_w[j - 13], 7) ^ sm3_w[j - 6]; /* soft sm3 alg:offset 13, 6 and rotate left 7. */
117 }
118 for (j = 0; j < SM3_BLOCK_SIZE; j++) {
119 sm3_w1[j] = sm3_w[j] ^ sm3_w[j + 4]; /* soft sm3 alg:offset 4. */
120 }
121
122 for (j = 0; j < SM3_BLOCK_SIZE / WORD_WIDTH; j++) {
123 sm3_t[j] = 0x79CC4519; /* soft sm3 alg: sm3_t init 0x79CC4519. */
124 sm3_ss1 = rotate_left((rotate_left(sm3_a, 12) + sm3_e + rotate_left(sm3_t[j], j)), 7); /* rotate left 12, 7. */
125 sm3_ss2 = sm3_ss1 ^ rotate_left(sm3_a, 12); /* soft sm3 alg:rotate left 12. */
126 sm3_tt1 = ff0(sm3_a, sm3_b, sm3_c) + sm3_d + sm3_ss2 + sm3_w1[j];
127 sm3_tt2 = gg0(sm3_e, sm3_f, sm3_g) + sm3_h + sm3_ss1 + sm3_w[j];
128 sm3_d = sm3_c;
129 sm3_c = rotate_left(sm3_b, 9); /* soft sm3 alg:rotate left 9. */
130 sm3_b = sm3_a;
131 sm3_a = sm3_tt1;
132 sm3_h = sm3_g;
133 sm3_g = rotate_left(sm3_f, 19); /* soft sm3 alg:rotate left 19. */
134 sm3_f = sm3_e;
135 sm3_e = p0(sm3_tt2);
136 }
137
138 for (j = SM3_BLOCK_SIZE / WORD_WIDTH; j < SM3_BLOCK_SIZE; j++) {
139 sm3_t[j] = 0x7A879D8A; /* soft sm3 alg: sm3_t init 0x7A879D8A. */
140 sm3_ss1 = rotate_left((rotate_left(sm3_a, 12) + sm3_e + rotate_left(sm3_t[j], j)), 7); /* rotate left 12, 7. */
141 sm3_ss2 = sm3_ss1 ^ rotate_left(sm3_a, 12); /* soft sm3 alg:rotate left 12. */
142 sm3_tt1 = ff1(sm3_a, sm3_b, sm3_c) + sm3_d + sm3_ss2 + sm3_w1[j];
143 sm3_tt2 = gg1(sm3_e, sm3_f, sm3_g) + sm3_h + sm3_ss1 + sm3_w[j];
144 sm3_d = sm3_c;
145 sm3_c = rotate_left(sm3_b, 9); /* soft sm3 alg:rotate left 9. */
146 sm3_b = sm3_a;
147 sm3_a = sm3_tt1;
148 sm3_h = sm3_g;
149 sm3_g = rotate_left(sm3_f, 19); /* soft sm3 alg:rotate left 19. */
150 sm3_f = sm3_e;
151 sm3_e = p0(sm3_tt2);
152 }
153
154 digest[WORD_IDX_0] ^= sm3_a;
155 digest[WORD_IDX_1] ^= sm3_b;
156 digest[WORD_IDX_2] ^= sm3_c;
157 digest[WORD_IDX_3] ^= sm3_d;
158 digest[WORD_IDX_4] ^= sm3_e;
159 digest[WORD_IDX_5] ^= sm3_f;
160 digest[WORD_IDX_6] ^= sm3_g;
161 digest[WORD_IDX_7] ^= sm3_h;
162
163 if (buf != HI_NULL) {
164 crypto_free(buf);
165 buf = HI_NULL;
166 }
167
168 return HI_SUCCESS;
169 }
170
sm3_init(ext_sm3_context * ctx)171 static hi_void sm3_init(ext_sm3_context *ctx)
172 {
173 hi_log_func_enter();
174
175 ctx->state[WORD_IDX_0] = SM3_H0;
176 ctx->state[WORD_IDX_1] = SM3_H1;
177 ctx->state[WORD_IDX_2] = SM3_H2;
178 ctx->state[WORD_IDX_3] = SM3_H3;
179 ctx->state[WORD_IDX_4] = SM3_H4;
180 ctx->state[WORD_IDX_5] = SM3_H5;
181 ctx->state[WORD_IDX_6] = SM3_H6;
182 ctx->state[WORD_IDX_7] = SM3_H7;
183
184 hi_log_func_exit();
185
186 return;
187 }
188
sm3_update(ext_sm3_context * ctx,const hi_u8 * data,hi_u32 data_len)189 static hi_s32 sm3_update(ext_sm3_context *ctx, const hi_u8 *data, hi_u32 data_len)
190 {
191 hi_u32 left;
192 hi_s32 ret;
193
194 hi_log_func_enter();
195
196 ctx->total += data_len;
197
198 if (ctx->tail_len) {
199 left = SM3_BLOCK_SIZE - ctx->tail_len;
200 if (data_len < left) {
201 if (memcpy_s(ctx->tail + ctx->tail_len, left, data, data_len) != EOK) {
202 hi_log_print_func_err(memcpy_s, HI_ERR_CIPHER_MEMCPY_S_FAILED);
203 return HI_ERR_CIPHER_MEMCPY_S_FAILED;
204 }
205 ctx->tail_len += data_len;
206 return HI_SUCCESS;
207 } else {
208 if (memcpy_s(ctx->tail + ctx->tail_len, left, data, left) != EOK) {
209 hi_log_print_func_err(memcpy_s, HI_ERR_CIPHER_MEMCPY_S_FAILED);
210 return HI_ERR_CIPHER_MEMCPY_S_FAILED;
211 }
212 ret = sm3_compress(ctx->state, ctx->tail, sizeof(ctx->tail));
213 if (ret != HI_SUCCESS) {
214 hi_log_print_func_err(sm3_compress, ret);
215 return ret;
216 }
217
218 data += left;
219 data_len -= left;
220 }
221 }
222
223 while (data_len >= SM3_BLOCK_SIZE) {
224 ret = sm3_compress(ctx->state, data, SM3_BLOCK_SIZE);
225 if (ret != HI_SUCCESS) {
226 hi_log_print_func_err(sm3_compress, ret);
227 return ret;
228 }
229
230 data += SM3_BLOCK_SIZE;
231 data_len -= SM3_BLOCK_SIZE;
232 }
233
234 ctx->tail_len = data_len;
235 if (data_len) {
236 if (memcpy_s(ctx->tail, SM3_BLOCK_SIZE, data, data_len) != EOK) {
237 hi_log_print_func_err(memcpy_s, HI_ERR_CIPHER_MEMCPY_S_FAILED);
238 return HI_ERR_CIPHER_MEMCPY_S_FAILED;
239 }
240 }
241
242 hi_log_func_exit();
243
244 return HI_SUCCESS;
245 }
246
sm3_final(ext_sm3_context * ctx,hi_u8 * digest,hi_u32 digest_len)247 static hi_s32 sm3_final(ext_sm3_context *ctx, hi_u8 *digest, hi_u32 digest_len)
248 {
249 hi_s32 i;
250 hi_s32 ret;
251 hi_u32 idx = 0;
252 hi_u32 hash[SM3_RESULT_SIZE_IN_WORD] = {0};
253
254 hi_log_func_enter();
255 hi_log_chk_param_return(digest_len < SM3_BLOCK_SIZE);
256
257 ctx->tail[ctx->tail_len] = SM3_BYTE_MSB;
258 idx++;
259
260 /* a block is enough */
261 if (ctx->tail_len + SM3_PAD_MIN_SIZE <= SM3_BLOCK_SIZE) {
262 (hi_void)memset_s(ctx->tail + ctx->tail_len + idx, SM3_BLOCK_SIZE - ctx->tail_len - idx,
263 0, SM3_BLOCK_SIZE - ctx->tail_len - idx);
264 } else {
265 /* 2 block is request */
266 (hi_void)memset_s(ctx->tail + ctx->tail_len + idx, SM3_BLOCK_SIZE - ctx->tail_len - idx,
267 0, SM3_BLOCK_SIZE - ctx->tail_len - idx);
268 ret = sm3_compress(ctx->state, ctx->tail, sizeof(ctx->tail));
269 if (ret != HI_SUCCESS) {
270 hi_log_print_func_err(sm3_compress, ret);
271 return ret;
272 }
273 (hi_void)memset_s(ctx->tail, SM3_BLOCK_SIZE, 0, SM3_BLOCK_SIZE);
274 }
275
276 /* write 8 bytes fix data length * 8 */
277 ctx->tail[SM3_BLOCK_SIZE - WORD_IDX_5] = (hi_u8)((ctx->total >> SHIFT_29BITS) & MAX_LOW_3BITS);
278 ctx->tail[SM3_BLOCK_SIZE - WORD_IDX_4] = (hi_u8)((ctx->total >> SHIFT_21BITS) & MAX_LOW_8BITS);
279 ctx->tail[SM3_BLOCK_SIZE - WORD_IDX_3] = (hi_u8)((ctx->total >> SHIFT_13BITS) & MAX_LOW_8BITS);
280 ctx->tail[SM3_BLOCK_SIZE - WORD_IDX_2] = (hi_u8)((ctx->total >> SHIFT_5BITS) & MAX_LOW_8BITS);
281 ctx->tail[SM3_BLOCK_SIZE - WORD_IDX_1] = (hi_u8)((ctx->total << SHIFT_3BITS) & MAX_LOW_8BITS);
282
283 ret = sm3_compress(ctx->state, ctx->tail, sizeof(ctx->tail));
284 if (ret != HI_SUCCESS) {
285 hi_log_print_func_err(sm3_compress, ret);
286 return ret;
287 }
288
289 for (i = 0; i < SM3_RESULT_SIZE_IN_WORD; i++) {
290 hash[i] = crypto_cpu_to_be32(ctx->state[i]);
291 }
292
293 if (memcpy_s(digest, digest_len, hash, SM3_RESULT_SIZE) != EOK) {
294 hi_log_print_func_err(memcpy_s, HI_ERR_CIPHER_MEMCPY_S_FAILED);
295 return HI_ERR_CIPHER_MEMCPY_S_FAILED;
296 }
297
298 hi_log_func_exit();
299
300 return HI_SUCCESS;
301 }
302
ext_sm3_create(hash_mode mode)303 hi_void *ext_sm3_create(hash_mode mode)
304 {
305 ext_sm3_context *ctx = HI_NULL;
306
307 hi_log_func_enter();
308
309 ctx = crypto_malloc(sizeof(ext_sm3_context));
310 if (ctx == HI_NULL) {
311 hi_log_error("malloc hash context buffer failed!");
312 return HI_NULL;
313 }
314 (hi_void)memset_s(ctx, sizeof(ext_sm3_context), 0, sizeof(ext_sm3_context));
315
316 sm3_init(ctx);
317
318 hi_log_func_exit();
319
320 return ctx;
321 }
322
ext_sm3_update(hi_void * ctx,const hi_u8 * chunk,hi_u32 chunk_len,hash_chunk_src src)323 hi_s32 ext_sm3_update(hi_void *ctx, const hi_u8 *chunk, hi_u32 chunk_len, hash_chunk_src src)
324 {
325 hi_u8 *ptr = HI_NULL;
326 hi_s32 ret;
327 hi_u32 offset = 0;
328 hi_u32 length;
329
330 hi_log_func_enter();
331
332 hi_log_chk_param_return(ctx == HI_NULL);
333
334 if (chunk_len == 0x00) {
335 return HI_SUCCESS;
336 }
337
338 if (src == HASH_CHUNCK_SRC_USER) {
339 ptr = crypto_calloc(HASH_MAX_BUFFER_SIZE);
340 if (ptr == HI_NULL) {
341 hi_log_print_func_err(crypto_calloc, HI_ERR_CIPHER_FAILED_MEM);
342 return HI_ERR_CIPHER_FAILED_MEM;
343 }
344
345 while (offset < chunk_len) {
346 length = chunk_len - offset;
347 if (length > HASH_MAX_BUFFER_SIZE) {
348 length = HASH_MAX_BUFFER_SIZE;
349 }
350
351 crypto_chk_err_goto(crypto_copy_from_user(ptr, HASH_MAX_BUFFER_SIZE, chunk + offset, length));
352 crypto_chk_err_goto(sm3_update(ctx, ptr, length));
353 crypto_msleep(1);
354 offset += length;
355 }
356 } else {
357 if (chunk == HI_NULL) {
358 hi_log_error("Invalid point, chunk is null!\n");
359 ret = HI_ERR_CIPHER_INVALID_POINT;
360 goto exit__;
361 }
362 crypto_chk_err_goto(sm3_update(ctx, chunk, chunk_len));
363 ret = HI_SUCCESS;
364 }
365
366 exit__:
367 if (ptr != HI_NULL) {
368 crypto_free(ptr);
369 ptr = HI_NULL;
370 }
371
372 hi_log_func_exit();
373 return ret;
374 }
375
ext_sm3_finish(hi_void * ctx,hi_void * hash,hi_u32 hash_buf_len,hi_u32 * hashlen)376 hi_s32 ext_sm3_finish(hi_void *ctx, hi_void *hash, hi_u32 hash_buf_len, hi_u32 *hashlen)
377 {
378 hi_s32 ret;
379 hi_log_func_enter();
380
381 hi_log_chk_param_return(ctx == HI_NULL);
382
383 ret = sm3_final(ctx, hash, hash_buf_len);
384 if (ret != HI_SUCCESS) {
385 hi_log_print_func_err(sm3_final, ret);
386 return ret;
387 }
388 *hashlen = SM3_RESULT_SIZE;
389
390 hi_log_func_exit();
391 return HI_SUCCESS;
392 }
393
ext_sm3_destory(hi_void * ctx)394 hi_s32 ext_sm3_destory(hi_void *ctx)
395 {
396 hi_log_func_enter();
397
398 hi_log_chk_param_return(ctx == HI_NULL);
399
400 crypto_free(ctx);
401 ctx = HI_NULL;
402
403 hi_log_func_exit();
404 return HI_SUCCESS;
405 }
406 #endif
407