]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/T-HEAD_CB2201_CDK/csi/csi_driver/csky/common/sha/ck_sha_v2.c
Introduce a port for T-HEAD CK802. A simple demo for T-HEAD CB2201 is also included.
[freertos] / FreeRTOS / Demo / T-HEAD_CB2201_CDK / csi / csi_driver / csky / common / sha / ck_sha_v2.c
1 /*
2  * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /******************************************************************************
18  * @file     ck_sha.c
19  * @brief    CSI Source File for SHA Driver
20  * @version  V1.0
21  * @date     02. June 2017
22  ******************************************************************************/
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdbool.h>
26 #include "csi_core.h"
27 #include "drv_sha.h"
28 #include "ck_sha_v2.h"
29
30 #ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
31 #define CONFIG_SHA_SUPPORT_MUL_THREAD   1
32 #endif
33
34 typedef struct {
35     uint32_t base;
36     uint32_t irq;
37     sha_event_cb_t cb;
38     sha_status_t status;
39     sha_mode_e mode;
40     sha_endian_mode_e endian;
41 #ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
42     uint8_t  state[64];
43     uint8_t sha_buffer[128];
44     uint32_t total;
45     uint32_t last_left;
46 #endif
47 } ck_sha_priv_t;
48
49 #ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
50 static ck_sha_priv_t sha_handle[CONFIG_SHA_NUM];
51 #endif
52 static uint32_t g_sha_context[CONFIG_SHA_NUM];
53 bool finish_flag = 0;
54
55 /* Driver Capabilities */
56 static const sha_capabilities_t driver_capabilities = {
57     .sha1 = 1, /* sha1 mode */
58     .sha224 = 1, /* sha224 mode */
59     .sha256 = 1, /* sha256 mode */
60     .sha384 = 1, /* sha384 mode */
61     .sha512 = 1, /* sha512 mode */
62     .sha512_224 = 1, /* sha512_224 mode */
63     .sha512_256 = 1, /* sha512_256 mode */
64     .endianmode = 1, /* endian mode */
65     .interruptmode = 1  /* interrupt mode */
66 };
67
68 #define ERR_SHA(errno) (CSI_DRV_ERRNO_SHA_BASE | errno)
69 #define SHA_NULL_PARAM_CHK(para)                         \
70         do {                                        \
71             if (para == NULL) {                     \
72                 return ERR_SHA(EDRV_PARAMETER);   \
73             }                                       \
74         } while (0)
75 //
76 // Functions
77 //
78
79 ck_sha_reg_t *sha_reg = NULL;
80 volatile static uint8_t sha_int_flag = 1;
81
82 extern int32_t target_get_sha_count(void);
83 extern int32_t target_get_sha(int32_t idx, uint32_t *base, uint32_t *irq);
84
85 static int32_t sha_set_mode(sha_mode_e mode)
86 {
87     sha_reg->SHA_CON &= ~0x7;
88     sha_reg->SHA_CON |= mode;
89     return 0;
90 }
91
92 #ifndef CONFIG_SHA_BLOCK_MODE
93 static int32_t sha_enable_interrupt(void)
94 {
95     sha_reg->SHA_CON |= 1 << SHA_INT_ENABLE_OFFSET;
96     return 0;
97 }
98
99 #ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
100 static int32_t sha_disable_interrupt(void)
101 {
102     sha_reg->SHA_CON &= ~(1 << SHA_INT_ENABLE_OFFSET);
103     return 0;
104 }
105 #endif
106 #endif
107
108 static void sha_clear_interrupt(void)
109 {
110     sha_reg->SHA_INTSTATE = 0;
111 }
112
113 static int32_t sha_enable_initial(void)
114 {
115     sha_reg->SHA_CON |= 1 << SHA_INIT_OFFSET;
116     return 0;
117 }
118
119 static int32_t sha_enable_calculate(void)
120 {
121     sha_reg->SHA_CON |= 1 << SHA_CAL_OFFSET;
122     return 0;
123 }
124
125 #ifdef CONFIG_SHA_BLOCK_MODE
126 static int32_t sha_message_done(void)
127 {
128     while((sha_reg->SHA_CON & 0x40));
129     return 0;
130 }
131 #endif
132
133 static int32_t sha_select_endian_mode(sha_endian_mode_e mode)
134 {
135     sha_reg->SHA_CON &= ~(1 << SHA_ENDIAN_OFFSET);
136     sha_reg->SHA_CON |= mode << SHA_ENDIAN_OFFSET;
137     return 0;
138 }
139
140 static int32_t sha_input_data(uint32_t *data, uint32_t length)
141 {
142     uint8_t i;
143     uint32_t tmp;
144     uint32_t *input_data = (uint32_t *) & (sha_reg->SHA_DATA1);
145
146     for (i = 0; i < length; i++) {
147         memcpy(&tmp, (uint8_t *)(data+i), 4);
148         *(input_data + i) = tmp;
149     }
150
151     return 0;
152 }
153
154 static int32_t sha_get_data(sha_handle_t handle, uint32_t *data)
155 {
156     ck_sha_priv_t *sha_priv = handle;
157
158     uint8_t len = 0;
159     uint8_t i;
160     uint32_t temp;
161     uint32_t *result = (uint32_t *)&sha_reg->SHA_H0L;
162     /* according to different mode to obtain the hash result */
163     if (sha_priv->mode == SHA_MODE_1 || sha_priv->mode == SHA_MODE_224 || sha_priv->mode == SHA_MODE_256) {
164         if (sha_priv->mode == SHA_MODE_1) {
165             len = 5;
166         } else if (sha_priv->mode == SHA_MODE_224) {
167             len = 7;
168         } else if (sha_priv->mode == SHA_MODE_256) {
169             len = 8;
170         }
171
172         for (i = 0; i < len; i++) {
173             temp = *(result + i);
174             memcpy(&data[i], &temp, 4);
175         }
176     } else {
177         if (sha_priv->mode == SHA_MODE_384) {
178             len = 6;
179         } else if (sha_priv->mode == SHA_MODE_512) {
180             len = 8;
181         }
182
183         uint32_t *resulth = (uint32_t *)&sha_reg->SHA_H0H;
184         for (i = 0; i < len; i++) {
185 //            data[i << 1] = *(resulth + i);
186 //            data[(i << 1) + 1] = *(result + i);
187             temp = *(resulth + i);
188             memcpy(&data[i<<1], &temp, 4);
189             temp = *(result + i);
190             memcpy(&data[(i<<1)+1], &temp, 4);
191         }
192     }
193
194     return 0;
195 }
196
197 #ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
198 static int32_t sha_set_data(sha_handle_t handle, uint32_t *data)
199 {
200     ck_sha_priv_t *sha_priv = handle;
201
202     uint8_t len = 0;
203     uint8_t i;
204     uint32_t *result = (uint32_t *)&sha_reg->SHA_H0L;
205     /* according to different mode to obtain the hash result */
206     if (sha_priv->mode == SHA_MODE_1 || sha_priv->mode == SHA_MODE_224 || sha_priv->mode == SHA_MODE_256) {
207         if (sha_priv->mode == SHA_MODE_1) {
208             len = 5;
209         } else if (sha_priv->mode == SHA_MODE_224) {
210             len = 7;
211         } else if (sha_priv->mode == SHA_MODE_256) {
212             len = 8;
213         }
214
215         for (i = 0; i < len; i++) {
216             *(result + i) = data[i];
217         }
218     } else {
219         if (sha_priv->mode == SHA_MODE_384) {
220             len = 6;
221         } else if (sha_priv->mode == SHA_MODE_512) {
222             len = 8;
223         }
224
225         uint32_t *resulth = (uint32_t *)&sha_reg->SHA_H0H;
226         for (i = 0; i < len; i++) {
227              *(resulth + i) = data[i << 1];
228              *(result + i) = data[(i << 1) + 1] ;
229         }
230     }
231
232     return 0;
233 }
234 #endif
235
236 static inline void sha_reverse_order(uint8_t *pdata, int32_t length)
237 {
238     uint8_t input_data[length];
239     uint8_t result[length];
240     uint32_t tmp = 0;
241     int32_t i = 0;
242     memcpy((void *)input_data, (void *)pdata, length);
243
244     for (i = 0; i < length; i++) {
245         tmp = i >> 2;
246         tmp = tmp << 3;
247         result[i] = input_data[tmp + 3 - i];
248     }
249
250     memcpy((void *)pdata, (void *)result, length);
251 }
252
253 void ck_sha_irqhandler(int32_t idx)
254 {
255     sha_int_flag = 0;
256     sha_clear_interrupt();      //clear sha interrupt
257
258 #ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
259     ck_sha_priv_t *sha_priv = &sha_handle[idx];
260 #else
261     ck_sha_priv_t *sha_priv = (ck_sha_priv_t *)g_sha_context[idx];
262 #endif
263     if (finish_flag != 0) {
264         if (sha_priv->cb != NULL) {
265             sha_priv->cb(SHA_EVENT_COMPLETE);       //execute the callback function
266         }
267     }
268 }
269
270 /**
271   \brief       get sha handle count.
272   \return      sha handle count
273 */
274 int32_t csi_sha_get_instance_count(void)
275 {
276     return target_get_sha_count();
277 }
278
279 /**
280   \brief       Initialize SHA Interface. 1. Initializes the resources needed for the SHA interface 2.registers event callback function
281   \param[in]   idx must not exceed return value of csi_sha_get_instance_count()
282   \param[in]   cb_event  Pointer to \ref sha_event_cb_t
283   \return      return sha handle if success
284 */
285 sha_handle_t csi_sha_initialize(sha_handle_t handle, sha_event_cb_t cb_event)
286 {
287
288 #ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
289     uint32_t base = 0u;
290     uint32_t irq;
291     /* obtain the sha information */
292     target_get_sha(0, &base, &irq);
293     ck_sha_priv_t *sha_priv = handle;
294     memset(sha_priv->state, 0, sizeof(sha_priv->state));
295     sha_priv->last_left = 0;
296     sha_priv->total = 0;
297     g_sha_context[0] = (uint32_t)handle;
298 #else
299     if (idx < 0 || idx >= CONFIG_SHA_NUM) {
300         return NULL;
301     }
302
303     uint32_t base = 0u;
304     uint32_t irq;
305     /* obtain the sha information */
306     int32_t real_idx = target_get_sha(idx, &base, &irq);
307
308     if (real_idx != idx) {
309         return NULL;
310     }
311     ck_sha_priv_t *sha_priv = &sha_handle[idx];
312 #endif
313     sha_priv->base = base;
314     sha_priv->irq  = irq;
315
316     /* initialize the sha context */
317     sha_priv->cb = cb_event;
318     sha_priv->status.busy = 0;
319
320 #ifndef CONFIG_SHA_BLOCK_MODE
321     drv_nvic_enable_irq(sha_priv->irq);
322 #endif
323
324     return (sha_handle_t)sha_priv;
325 }
326
327 /**
328   \brief       De-initialize SHA Interface. stops operation and releases the software resources used by the interface
329   \param[in]   handle  sha handle to operate.
330   \return      error code
331 */
332 int32_t csi_sha_uninitialize(sha_handle_t handle)
333 {
334     SHA_NULL_PARAM_CHK(handle);
335
336     ck_sha_priv_t *sha_priv = handle;
337     sha_priv->cb = NULL;
338
339 #ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
340 #ifndef CONFIG_SHA_BLOCK_MODE
341     sha_disable_interrupt();
342     drv_nvic_disable_irq(sha_priv->irq);
343 #endif
344 #endif
345
346     return 0;
347 }
348
349 /**
350   \brief       Get driver capabilities.
351   \param[in]   handle sha handle to operate.
352   \return      \ref sha_capabilities_t
353 */
354 sha_capabilities_t csi_sha_get_capabilities(sha_handle_t handle)
355 {
356     return driver_capabilities;
357 }
358
359 /**
360   \brief       config sha mode.
361   \param[in]   handle  sha handle to operate.
362   \param[in]   mode      \ref sha_mode_e
363   \param[in]   endian    \ref sha_endian_mode_e
364   \return      error code
365 */
366 int32_t csi_sha_config(sha_handle_t handle, sha_mode_e mode, sha_endian_mode_e endian_mode)
367 {
368     SHA_NULL_PARAM_CHK(handle);
369
370     ck_sha_priv_t *sha_priv = handle;
371     sha_reg = (ck_sha_reg_t *)(sha_priv->base);
372
373     /* config the sha mode */
374     switch (mode) {
375         case SHA_MODE_512_256:
376         case SHA_MODE_512_224:
377             return ERR_SHA(EDRV_UNSUPPORTED);
378
379         case SHA_MODE_1:
380         case SHA_MODE_224:
381         case SHA_MODE_256:
382         case SHA_MODE_384:
383         case SHA_MODE_512:
384             sha_priv->mode = mode;
385             break;
386
387         default:
388             return ERR_SHA(EDRV_PARAMETER);
389     }
390
391     sha_set_mode(mode);
392
393     /*config the sha endian mode */
394     if (endian_mode == SHA_ENDIAN_MODE_LITTLE) {
395         sha_priv->endian = endian_mode;
396         sha_select_endian_mode(endian_mode);
397     } else if (endian_mode == SHA_ENDIAN_MODE_BIG) {
398         sha_priv->endian = endian_mode;
399         sha_select_endian_mode(endian_mode);
400     } else {
401         return ERR_SHA(EDRV_PARAMETER);
402     }
403
404 #ifndef CONFIG_SHA_BLOCK_MODE
405     sha_enable_interrupt();
406 #endif
407
408     return 0;
409 }
410
411 /**
412   \brief       start the engine
413   \param[in]   handle  sha handle to operate.
414   \param[in]   context  Pointer to the sha context.
415   \return      error code
416 */
417 int32_t csi_sha_starts(sha_handle_t handle, void *context)
418 {
419     SHA_NULL_PARAM_CHK(handle);
420
421     ck_sha_priv_t *sha_priv = handle;
422     sha_enable_initial();
423     sha_priv->status.busy = 1;
424
425 #ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
426     sha_get_data(handle, (uint32_t *)sha_priv->state);
427 #endif
428
429     return 0;
430 }
431
432 /**
433   \brief       updata the engine
434   \param[in]   handle  sha handle to operate.
435   \param[in]   context  Pointer to the sha context.
436   \param[in]   input   Pointer to the Source data
437   \param[in]   len    the data len
438   \return      error code
439 */
440 #ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
441 static uint8_t sha_buffer[128];
442 static uint32_t total[2] = {0x0};
443 static uint32_t last_left = 0;
444 #endif
445 int32_t csi_sha_update(sha_handle_t handle, void *context, const void *input, uint32_t len)
446 {
447     SHA_NULL_PARAM_CHK(handle);
448     SHA_NULL_PARAM_CHK(input);
449     if (len <= 0) {
450         return ERR_SHA(EDRV_PARAMETER);
451     }
452     g_sha_context[0] = (uint32_t)handle;
453     ck_sha_priv_t *sha_priv = handle;
454     sha_reg = (ck_sha_reg_t *)(sha_priv->base);
455
456     uint32_t block_size;
457     if (sha_priv->mode < 4) {
458         block_size = 64;
459     } else {
460         block_size = 128;
461     }
462
463 #ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
464     uint8_t *sha_buffer = sha_priv->sha_buffer;
465     uint32_t last_left = sha_priv->last_left;
466     sha_set_mode(sha_priv->mode);
467     uint32_t left = sha_priv->total & (block_size - 1);
468     uint32_t fill = block_size - left;
469     uint32_t total_length = sha_priv->total << 3;
470
471     sha_priv->total += len;
472     sha_priv->total &= 0xffffffff;
473     uint32_t word_left = sha_priv->total & 0x3;
474 #else
475     uint32_t left = total[0] & (block_size - 1);
476     uint32_t fill = block_size - left;
477     uint32_t total_length = total[0] << 3;
478
479     total[0] += len;
480     total[0] &= 0xffffffff;
481     uint32_t word_left = total[0] & 0x3;
482 #endif
483     uint8_t temp_data[4];
484     uint32_t j;
485     if (finish_flag) {
486         /*calculate the final word*/
487         for (j = 0; j < 4; j++) {
488             temp_data[j] = (total_length >> (8 * j)) & 0xff;
489         }
490     }
491
492     uint8_t *p = (uint8_t *)input;
493     /* when the text is not aligned by block and len > fill */
494     if (left && len >= fill) {
495         if (finish_flag) {
496             if (sha_priv->endian == SHA_ENDIAN_MODE_BIG) {
497                 memset(&sha_buffer[left], 0x0, len);
498                 sha_buffer[left] = 0x80;
499                 for (j=0; j<4; j++) {
500                     sha_buffer[left + len - 4 + j] = temp_data[3 - j];
501                 }
502             } else {
503                 memset(&sha_buffer[left + 4 - last_left], 0x0, len - 4 + last_left);
504                 sha_buffer[left - last_left + 3 - last_left] = 0x80;
505                 for (j = 1; j < 4 - last_left; j++) {
506                     sha_buffer[left - last_left + 3 - last_left - j] = 0x00;
507                 }
508                 for (j=0; j<4; j++) {
509                     sha_buffer[left + len - 4 + j] = temp_data[j];
510                 }
511             }
512         } else {
513             if (last_left && sha_priv->endian == SHA_ENDIAN_MODE_LITTLE) {
514                 uint32_t i;
515                 for (i = 0; i < 4 - last_left; i++) {
516                     *(sha_buffer + left + 3 - last_left - i) = *((uint8_t *)p + 3 - last_left - i);
517                 }
518
519                 fill = fill - 4 + last_left;
520                 p = (p + 4 - last_left);
521             }
522             else if (last_left) {
523                 memcpy((void *)(sha_buffer + left + 4 - last_left), p, fill);
524             } else {
525                 memcpy((void *)(sha_buffer + left), p, fill);
526             }
527             p += fill;
528         }
529
530         /* set the input data */
531 #ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
532         sha_set_data(handle, (uint32_t *)sha_priv->state);
533 #endif
534         sha_input_data((uint32_t *)sha_buffer, block_size >> 2);
535         sha_enable_calculate();
536
537 #ifdef CONFIG_SHA_BLOCK_MODE
538         sha_message_done();
539
540 #else
541         while (sha_int_flag);
542
543         sha_int_flag = 1;
544 #endif
545
546 #ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
547         sha_get_data(handle, (uint32_t *)sha_priv->state);
548 #endif
549         len -= fill;
550         left = 0;
551     } else {
552         if (finish_flag) {
553 #ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
554             memset(sha_buffer, 0, sizeof(sha_priv->sha_buffer));
555 #else
556             memset(sha_buffer, 0, sizeof(sha_buffer));
557 #endif
558             if (sha_priv->endian == SHA_ENDIAN_MODE_BIG) {
559                 sha_buffer[0] = 0x80;
560                 for (j = 0; j < 4; j++) {
561                     sha_buffer[block_size - 4 + j] = temp_data[3 - j];
562                 }
563             } else {
564                 sha_buffer[3 - last_left] = 0x80;
565                 for (j = 0; j < 4; j++) {
566                     sha_buffer[block_size - 4 + j] = temp_data[j];
567                 }
568             }
569         }
570     }
571
572     /* calculate the hash by block */
573     while (len >= block_size) {
574 #ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
575         sha_set_data(handle, (uint32_t *)sha_priv->state);
576 #endif
577         if (finish_flag) {
578             if (fill == block_size) {
579                 sha_input_data((uint32_t *)sha_buffer, block_size >> 2);
580             } else {
581                 sha_input_data((uint32_t *)&sha_buffer[block_size], block_size >> 2);
582             }
583         }
584         else {
585             sha_input_data((uint32_t *)p, block_size >> 2);
586             p += block_size;
587         }
588         sha_enable_calculate();
589
590 #ifdef CONFIG_SHA_BLOCK_MODE
591         sha_message_done();
592
593 #else
594         while (sha_int_flag);
595
596         sha_int_flag = 1;
597 #endif
598
599 #ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
600         sha_get_data(handle, (uint32_t *)sha_priv->state);
601 #endif
602         len -= block_size;
603     }
604
605     /* when the text is not aligned by block and len < fill */
606     if (len > 0) {
607         if (sha_priv->endian == SHA_ENDIAN_MODE_BIG || word_left == 0) {
608             memcpy((void *)(sha_buffer + left), p, len);
609         } else {
610             memcpy((void *)(sha_buffer + left), p, len + 4 - word_left);
611 #ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
612             sha_priv->last_left = word_left;
613 #else
614             last_left = word_left;
615 #endif
616         }
617     }
618
619     sha_priv->status.busy = 0;
620
621     return 0;
622 }
623
624 /**
625   \brief       finish the engine
626   \param[in]   handle  sha handle to operate.
627   \param[in]   context  Pointer to the sha context.
628   \param[out]  output   Pointer to the dest data
629   \return      error code
630 */
631 //static uint32_t total_length;
632 int32_t csi_sha_finish(sha_handle_t handle, void *context, void *output)
633 {
634     SHA_NULL_PARAM_CHK(handle);
635     SHA_NULL_PARAM_CHK(output);
636
637     ck_sha_priv_t *sha_priv = handle;
638     uint32_t block_size;
639     uint8_t message_len;
640     if (sha_priv->mode < 4) {
641         block_size = 64;
642         message_len = 8;
643     } else {
644         block_size = 128;
645         message_len = 16;
646     }
647
648 #ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
649     uint32_t last = sha_priv->total & (block_size - 1);
650     uint32_t padn = (last < (block_size - message_len)) ? (block_size - last) : (block_size + block_size - last);
651
652 #else
653     uint32_t last = total[0] & (block_size - 1);
654     uint32_t padn = (last < (block_size - message_len)) ? (block_size - last) : (block_size + block_size - last);
655
656 #endif
657
658     finish_flag = 1;
659
660     csi_sha_update(handle, NULL, output, padn);
661
662     /* get the hash result */
663     sha_get_data(handle, (uint32_t *)output);
664
665     uint8_t *p = output;
666     /* convert the data endian according the sha mode */
667     if (sha_priv->mode == SHA_MODE_1) {
668         sha_reverse_order(p, 20);
669     } else if (sha_priv->mode == SHA_MODE_224) {
670         sha_reverse_order(p, 28);
671     } else if (sha_priv->mode == SHA_MODE_256) {
672         sha_reverse_order(p, 32);
673     } else if (sha_priv->mode == SHA_MODE_512) {
674         sha_reverse_order(p, 64);
675     } else if (sha_priv->mode == SHA_MODE_384) {
676         sha_reverse_order(p, 48);
677     }
678
679 #ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
680     sha_priv->total = 0;
681     sha_priv->last_left = 0;
682 #else
683     total[0] = 0;
684     last_left = 0;
685 #endif
686     finish_flag = 0;
687
688     return 0;
689 }
690
691 /**
692   \brief       Get SHA status.
693   \param[in]   handle  sha handle to operate.
694   \return      SHA status \ref sha_status_t
695 */
696 sha_status_t csi_sha_get_status(sha_handle_t handle)
697 {
698     ck_sha_priv_t *sha_priv = handle;
699     return sha_priv->status;
700 }