• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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