]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/T-HEAD_CB2201_CDK/csi/csi_driver/csky/common/rsa/ck_rsa.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 / rsa / ck_rsa.c
diff --git a/FreeRTOS/Demo/T-HEAD_CB2201_CDK/csi/csi_driver/csky/common/rsa/ck_rsa.c b/FreeRTOS/Demo/T-HEAD_CB2201_CDK/csi/csi_driver/csky/common/rsa/ck_rsa.c
new file mode 100644 (file)
index 0000000..c7d999c
--- /dev/null
@@ -0,0 +1,1285 @@
+/*
+ * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/******************************************************************************
+ * @file     ck_rsa.c
+ * @brief    CSI Source File for RSA Driver
+ * @version  V1.0
+ * @date     02. June 2017
+ ******************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include "drv_rsa.h"
+#include "ck_rsa.h"
+#include "irq.h"
+
+#define ERR_RSA(errno) (CSI_DRV_ERRNO_RSA_BASE | errno)
+#define RSA_NULL_PARAM_CHK(para)                         \
+    do {                                        \
+        if (para == NULL) {                     \
+            return ERR_RSA(EDRV_PARAMETER);   \
+        }                                       \
+    } while (0)
+
+
+typedef struct {
+    uint32_t base;
+    uint32_t irq;
+    rsa_event_cb_t cb;
+    rsa_data_bits_e data_bit;
+    rsa_endian_mode_e endian;
+    rsa_padding_t padding;
+    rsa_status_t status;
+} ck_rsa_priv_t;
+
+extern int32_t target_get_rsa_count(void);
+extern int32_t target_get_rsa(int32_t idx, uint32_t *base, uint32_t *irq);
+
+static ck_rsa_priv_t rsa_handle[CONFIG_RSA_NUM];
+
+extern uint8_t modulus[];
+static ck_rsa_reg_t *rsa_reg = NULL;
+/* Driver Capabilities */
+static const rsa_capabilities_t driver_capabilities = {
+    .bits_192 = 1, /* 192bits modular mode */
+    .bits_256 = 1, /* 256bits modular mode */
+    .bits_512 = 1, /* 512bits modular mode */
+    .bits_1024 = 1, /* 1024bits modular mode */
+    .bits_2048 = 1  /* 2048bits modular mode */
+};
+
+extern int32_t target_get_rsa(int32_t idx, uint32_t *base, uint32_t *irq);
+extern int32_t target_get_rsa_count(void);
+//
+// Functions
+//
+
+static uint32_t sw_exptmod_2_2m(const uint32_t *modulus, uint32_t words, uint32_t *tmp_c);
+static uint32_t get_valid_bits(const uint32_t *addr, uint32_t wordsize, uint32_t keywords);
+
+#ifdef RSA_USING_ID2KEY
+static uint32_t g_acc[RSA_KEY_WORD];
+#endif
+
+static inline void rsa_clear_int(void)
+{
+    rsa_reg->rsa_isr = 0xffff;
+    rsa_reg->rsa_imr = 0x0000;
+}
+
+static inline void rsa_setm_width(uint32_t width)
+{
+    rsa_reg->rsa_mwid = width;
+}
+
+static inline void rsa_setd_width(uint32_t width)
+{
+    rsa_reg->rsa_ckid = width;
+}
+
+static inline void rsa_setb_width(uint32_t width)
+{
+    rsa_reg->rsa_bwid = width;
+}
+
+static inline void rsa_cal_q(void)
+{
+    rsa_reg->rsa_ctrl = RAS_CALCULATE_Q;
+}
+
+static inline void rsa_opr_start(void)
+{
+    rsa_reg->rsa_ctrl = RSA_ENABLE_MODULE;
+}
+
+static inline void rsa_opr_reset(void)
+{
+    rsa_reg->rsa_ctrl = RSA_ENDIAN_MODE;
+    rsa_reg->rsa_rst |= RSA_RESET;
+
+    while (rsa_reg->rsa_rst);
+}
+
+static inline uint32_t rsa_loop_cnt(void)
+{
+    return rsa_reg->rsa_lp_cnt;
+}
+
+static inline uint32_t rsa_cal_q_done(void)
+{
+    return (rsa_reg->rsa_isr >> RSA_CAL_Q_DONE_OFFSET) & 0x1;
+}
+
+static inline uint32_t rsa_opr_done(void)
+{
+    return (rsa_reg->rsa_isr) & 0x1;
+}
+
+static inline uint32_t rsa_raise_exception(void)
+{
+    return (rsa_reg->rsa_isr) & 0x1E;
+}
+
+static inline uint32_t rsa_loadm(uint32_t *data, uint32_t length)
+{
+    uint32_t i;
+    uint32_t baseaddr = (uint32_t)&rsa_reg->rsa_rfm;
+
+    for (i = 0; i < length; i++) {
+        *(volatile uint32_t *)baseaddr = data[i];
+        baseaddr = baseaddr + 4;
+    }
+
+    return 0;
+}
+
+static void rsa_loadd(uint32_t *data, uint32_t length)
+{
+    uint32_t i;
+    uint32_t baseaddr = (uint32_t)&rsa_reg->rsa_rfd;
+
+    for (i = 0;  i < length; i++) {
+        *(volatile uint32_t *)baseaddr = data[i];
+        baseaddr = baseaddr + 4;
+    }
+}
+
+static void rsa_loadc(uint32_t *data, uint32_t length)
+{
+    uint32_t i;
+    uint32_t baseaddr = (uint32_t)&rsa_reg->rsa_rfc;
+
+    for (i = 1; i < length + 1; i++) {
+        *(volatile uint32_t *)baseaddr = data[i - 1];
+        baseaddr = baseaddr + 4;
+    }
+}
+
+static void rsa_loadb(uint32_t *data, uint32_t length)
+{
+    uint32_t i;
+    uint32_t baseaddr = (uint32_t)&rsa_reg->rsa_rfb;
+
+    for (i = 0; i < length; i++) {
+        *(volatile uint32_t *)baseaddr = data[i];
+        baseaddr = baseaddr + 4;
+    }
+}
+
+static void rsa_read_r(uint32_t data[], uint32_t length)
+{
+    uint32_t i;
+    uint32_t baseaddr = (uint32_t)&rsa_reg->rsa_rfr;
+
+    for (i = 0; i < length; i++) {
+        data[i] = *(uint32_t *)baseaddr;
+        baseaddr = baseaddr + 4;
+    }
+}
+
+#if (CONFIG_PLATFORM_HOBBIT1_2 > 0)
+// FIXME
+// Since there is a piece of memory hole in RSA engine. we should
+// jump the hold to continue run without disable interrupt
+#define RSA_SP_HOLE_DOWN    0x60000900
+#define RSA_SP_HOLE_UP      0x600009FF
+#define TEE_CONEXT_SIZE     128
+static uint32_t rsa_run_adjust_sp_if_need(uint32_t sp)
+{
+    uint32_t sp_chg;
+
+    // if current sp is in hole, adjust new sp
+    if ((sp < (RSA_SP_HOLE_UP + TEE_CONEXT_SIZE)) && (sp > RSA_SP_HOLE_DOWN))
+        sp_chg = 1;
+    else
+        sp_chg = 0;
+
+    return sp_chg;
+}
+
+static void rsa_run_by_assemble(void)
+{
+    __asm__ __volatile__ (
+                "subi   sp, 0x10   \n"
+                "stm    r4-r7, (sp) \n"
+
+                // update sp
+                "mov    r4, sp  \n"
+                "subi   r4, 0x180  \n"
+                "mov    sp, r4 \n"
+
+                // enable rsa engine
+                "lrw    r5, 0x4000a00c \n"
+                "movi   r6, 3 \n"
+                "stw    r6, (r5) \n"
+                // check rsa end
+                "__chk_loop:    \n"
+                "lrw    r5, 0x4000a020 \n"
+                "ldw    r6, (r5) \n"
+                "btsti  r6, 0 \n"
+                "bt     __chk_end \n"
+
+                "lrw    r5, 0x4000a020 \n"
+                "ldw    r6, (r5) \n"
+                "movi   r7, 0x1e \n"
+                "and    r6, r7 \n"
+                "cmpnei  r6, 0 \n"
+                "bf     __chk_loop  \n"
+
+                "lrw    r5, 0x4000a014 \n"
+                "ldw    r6, (r5) \n"
+                "cmplti r6, 0x40  \n"
+                "bt     __chk_loop  \n"
+
+                "__chk_end: \n"
+
+                // update sp
+                "mov    r4, sp  \n"
+                "addi   r4, 0x180  \n"
+                "mov    sp, r4 \n"
+
+                "ldm    r4-r7, (sp) \n"
+                "addi   sp, 0x10   \n"
+            );
+}
+#endif
+
+static uint32_t rsa_exptmod(const uint32_t *modulus, const uint32_t *exponent,
+                            const uint32_t *base, uint32_t *out, uint32_t keywords,
+                            uint32_t *tmp_c)
+{
+    uint32_t ret = 0;
+    if ((NULL == exponent) || (NULL == base) || (NULL == out)) {
+        return 1;
+    }
+
+#ifdef RSA_USING_ID2KEY
+    memcpy(tmp_c, g_acc, sizeof(g_acc));
+#endif
+
+    /* reset for safe */
+    rsa_opr_reset();
+    /* clear and disable int */
+    rsa_clear_int();
+    /* set m */
+    rsa_setm_width(keywords >> 1);
+    rsa_loadm((uint32_t *)modulus, keywords);
+    /* set d */
+    rsa_setd_width(get_valid_bits(exponent, keywords, keywords) - 1);
+    rsa_loadd((uint32_t *)exponent, keywords);
+    /* set b */
+    rsa_setb_width(keywords >> 1);
+    rsa_loadb((uint32_t *)base, keywords);
+    /* set c */
+#ifndef RSA_USING_ID2KEY
+    rsa_loadc(tmp_c, keywords);
+#else
+    rsa_loadc(g_acc, keywords);
+#endif
+
+    rsa_cal_q();
+
+    while (!rsa_cal_q_done() && (!rsa_raise_exception()));
+
+    if (!rsa_raise_exception()) {
+#if (CONFIG_PLATFORM_HOBBIT1_2 > 0)
+        ///////////////// FIXME ////////////////////////
+        if (rsa_run_adjust_sp_if_need(get_old_sp())) {
+            rsa_run_by_assemble();
+        } else {
+#endif
+            rsa_opr_start();
+            while ((!rsa_opr_done()) && (rsa_loop_cnt() < MAX_RSA_LP_CNT) && (!rsa_raise_exception()));
+#if (CONFIG_PLATFORM_HOBBIT1_2 > 0)
+        }
+#endif
+        if ((rsa_loop_cnt() >= MAX_RSA_LP_CNT)
+            || rsa_raise_exception()) {
+            ret = 1;
+        } else {
+            rsa_read_r(out, keywords);
+        }
+    } else {
+        ret = 1;
+    }
+
+    rsa_opr_reset();
+
+    return ret;
+
+}
+
+static uint32_t get_valid_bits(const uint32_t *addr, uint32_t wordsize, uint32_t keywords)
+{
+    uint32_t i = 0;
+    uint32_t j = 0;
+
+    for (i = wordsize; i > 0; i--) {
+        if (addr[i - 1]) {
+            break;
+        }
+    }
+
+    for (j = keywords; j > 0; j--) {
+        if (addr[i - 1] & (0x1 << (j - 1))) {
+            break;
+        }
+    }
+
+    return ((i - 1) << 5) + j;
+}
+
+static uint32_t get_first_nonzero_words(uint32_t *a, uint32_t max_words)
+{
+    uint32_t i = 0;
+
+    for (i = max_words; i > 0; i--) {
+        if (a[i - 1]) {
+            return i;
+        }
+    }
+
+    return 0;
+}
+
+static uint32_t word_array_left_shift(uint32_t *a, uint32_t words,
+                                      uint32_t shift_bits, uint32_t *r)
+{
+    uint32_t i = 0;
+    uint32_t w = shift_bits >> 5;
+    uint32_t b = shift_bits - (w << 5);
+
+    for (i = 0; i < w; i++) {
+        r[i] = 0;
+    }
+
+    uint32_t tmp = 0;
+
+    for (i = 0; i < words; i++) {
+        r[w + i] = (tmp | ((a[i] << b) & (~((0x1 << b) - 1))));
+        tmp = ((a[i] >> (32 - b)) & ((0x1 << b) - 1));
+    }
+
+    r[w + i] = tmp;
+
+    return 0;
+}
+
+/* r = a - b */
+static uint32_t _word_array_sub(uint32_t *a, uint32_t a_words,
+                                uint32_t *b, uint32_t b_words,
+                                uint32_t *r)
+{
+    uint32_t i;
+    uint64_t tmp = 0;
+    uint32_t borrow = 0;
+
+    for (i = 0; i < b_words; i++) {
+        tmp = UINT32_TO_UINT64(a[i]) - UINT32_TO_UINT64(b[i]) - UINT32_TO_UINT64(borrow);
+        r[i] = UINT64L_TO_UINT32(tmp);
+        borrow = ((UINT64H_TO_UINT32(tmp) == 0) ? (0) : (0xffffffff - UINT64H_TO_UINT32(tmp) + 1));
+    }
+
+    for (i = b_words; i < a_words; i++) {
+        tmp = UINT32_TO_UINT64(a[i]) - UINT32_TO_UINT64(borrow);
+        r[i] = UINT64L_TO_UINT32(tmp);
+        borrow = ((UINT64H_TO_UINT32(tmp) == 0) ? (0) : (0xffffffff - UINT64H_TO_UINT32(tmp) + 1));
+    }
+
+    if (borrow) {
+        return -1;
+    }
+
+    return 0;
+}
+
+static uint32_t word_array_mod(uint32_t *a, uint32_t a_words,
+                               uint32_t *b, uint32_t b_words,
+                               uint32_t *r, uint32_t keywords)
+{
+    uint32_t ret;
+    bignum_t tmpa;
+    bignum_t tmpb;
+
+    memset(&tmpa, 0, sizeof(tmpa));
+    memset(&tmpb, 0, sizeof(tmpa));
+
+    uint32_t b_valid_bits = get_valid_bits(b, b_words, keywords);
+
+    memcpy(tmpa.pdata, a, (a_words << 2));
+
+    do {
+        uint32_t tmpa_words = get_first_nonzero_words(tmpa.pdata, a_words);
+        uint32_t tmpa_valid_bits = get_valid_bits(tmpa.pdata, tmpa_words, keywords);
+
+        if (tmpa_valid_bits > b_valid_bits + 1) {
+            memset(tmpb.pdata, 0, (a_words << 2));
+            word_array_left_shift(b, b_words, tmpa_valid_bits - b_valid_bits - 1,
+                                  tmpb.pdata);
+            uint32_t tmpb_words = get_first_nonzero_words(tmpb.pdata, a_words);
+            ret = _word_array_sub(tmpa.pdata, tmpa_words, tmpb.pdata, tmpb_words, tmpa.pdata);
+        } else if (tmpa_words == b_words) {
+            memcpy(r, tmpa.pdata, (tmpa_words << 2));
+            ret = _word_array_sub(r, tmpa_words, b, b_words, tmpa.pdata);
+        } else {
+            ret = _word_array_sub(tmpa.pdata, tmpa_words, b, b_words, tmpa.pdata);
+        }
+    } while (ret == 0);
+
+    return 0;
+}
+
+static uint32_t sw_exptmod_2_2m(const uint32_t *modulus, uint32_t words, uint32_t *tmp_c)
+{
+    bignum_t tmp;
+
+    memset(&tmp, 0, sizeof(bignum_t));
+
+    uint32_t m_valid_bits = (words << 5);
+
+    uint32_t data1 = 0x1;
+    word_array_left_shift(&data1, 1, (m_valid_bits << 1), tmp.pdata);
+    tmp.words = get_first_nonzero_words(tmp.pdata, words * 2 + 1);
+
+    uint32_t ret = word_array_mod(tmp.pdata, tmp.words,
+                                  (uint32_t *)modulus, words, tmp_c, words);
+
+    if (ret != 0) {
+        return ret;
+    }
+
+    return 0;
+}
+
+static void convert_byte_array(uint8_t *in, uint8_t *out, uint32_t len)
+{
+    uint32_t idx, round = len >> 1;
+
+    for (idx = 0; idx < round; idx++) {
+        uint8_t tmp = *(in + idx);
+        *(out + idx) = *(in + len - 1 - idx);
+        *(out + len - 1 - idx) = tmp;
+    }
+
+    if (len & 0x1) {
+        *(out + round) = *(in + round);
+    }
+}
+
+static void convert_buf_to_bndata(const uint8_t *src, uint32_t src_bytes,
+                                  uint32_t *dst, uint32_t dst_words)
+{
+    memset(dst, 0, dst_words << 2);
+    convert_byte_array((uint8_t *)src, (uint8_t *)dst, src_bytes);
+}
+
+static void convert_bndata_to_buf(const uint32_t *src, uint32_t src_words,
+                                  uint8_t *dst, uint32_t dst_bytes)
+{
+    memset(dst, 0, dst_bytes);
+    convert_byte_array((uint8_t *)src, (uint8_t *)dst, dst_bytes);
+}
+
+static const uint8_t der_sha256_t[] = {
+    0x30, 0x31,
+    0x30, 0x0d,
+    0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */
+    0x05, 0x00,
+    0x04, 0x20
+};
+
+static const uint8_t der_sha1_t[] = {
+    0x30, 0x21,
+    0x30, 0x09,
+    0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
+    0x05, 0x00,
+    0x04, 0x14
+};
+
+static const uint8_t der_md5_t[] = {
+    0x30, 0x20, /* type Sequence, length 0x20 (32) */
+    0x30, 0x0c, /* type Sequence, length 0x09 */
+    0x06, 0x08, /* type OID, length 0x05 */
+    0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* id-md5 */
+    0x05, 0x00, /* NULL */
+    0x04, 0x10  /* Octet string, length 0x10 (16), followed by md5 hash */
+};
+
+static uint32_t rsa_padding_pkcs(uint8_t  *dgst,
+                                 uint8_t  *out,
+                                 uint32_t  type,
+                                 uint32_t  keybytes)
+
+{
+    uint32_t i;
+    uint8_t *p;
+    uint8_t *der;
+    uint32_t der_len;
+    uint32_t hashlen;
+    uint32_t pslen;
+
+    if (type == MD5_PADDING) {
+        der     = (uint8_t *)der_md5_t;
+        der_len = sizeof(der_md5_t);
+        hashlen = MD5_HASH_SZ;
+    } else if (type == SHA256_PADDING) {
+        der     = (uint8_t *)der_sha256_t;
+        der_len = sizeof(der_sha256_t);
+        hashlen = SHA256_HASH_SZ;
+    } else {
+        der     = (uint8_t *)der_sha1_t;
+        der_len = sizeof(der_sha1_t);
+        hashlen = SHA1_HASH_SZ;
+    }
+
+    p = (uint8_t *)out;
+
+    *(p++) = 0x00;
+    *(p++) = 0x01;
+
+    /* pad out with 0xff data */
+    pslen = keybytes - 3 - der_len - hashlen;
+
+    for (i = 0; i < pslen; i++) {
+        p[i] = 0xff; /* PS */
+    }
+
+    p += pslen;
+    *(p++) = 0x0;
+
+    for (i = 0; i < der_len; i++) {
+        p[i] = der[i];
+    }
+
+    p += der_len;
+
+    for (i = 0; i < hashlen; i++) {
+        p[i] = dgst[i];
+    }
+
+    return 0;
+}
+
+static uint32_t rsa_checking_pkcs(uint8_t *dgst,
+                                  uint8_t *in,
+                                  uint32_t inlen,
+                                  uint8_t *is_valid,
+                                  uint32_t type,
+                                  uint32_t keybytes)
+{
+    uint32_t i;
+    uint32_t ret;
+    const uint8_t *p;
+    uint8_t *der = NULL;
+    uint32_t der_len = 0;
+    uint32_t hashlen = 0;
+    uint32_t pslen;
+
+    if (type == MD5_PADDING) {
+        der     = (uint8_t *)der_md5_t;
+        der_len = sizeof(der_md5_t);
+        hashlen = MD5_HASH_SZ;
+    } else if (type == SHA1_PADDING) {
+        der     = (uint8_t *)der_sha1_t;
+        der_len = sizeof(der_sha1_t);
+        hashlen = SHA1_HASH_SZ;
+    } else if (type == SHA256_PADDING) {
+        der     = (uint8_t *)der_sha256_t;
+        der_len = sizeof(der_sha256_t);
+        hashlen = SHA256_HASH_SZ;
+    }
+
+    *is_valid = 0;
+
+    pslen = keybytes - 3 - der_len - hashlen;
+    p = in;
+    p++;
+
+    if (*(p) != 0x01) {
+        ret = -1;
+        goto _verify_fail;
+    }
+
+    p++;
+
+    /* scan PS */
+    for (i = 0; i < pslen; i++) {
+        if (*(p + i) != 0xff) {
+            ret = -2;
+            goto _verify_fail;
+        }
+    }
+
+    p += pslen;
+
+    if ((*p) != 0x00) {
+        ret = -1;
+        goto _verify_fail;
+    }
+
+    p++;
+
+    /* scan t */
+    for (i = 0; i < der_len; i++) {
+        if (*(p + i) != der[i]) {
+            ret = -3;
+            goto _verify_fail;
+        }
+    }
+
+    p += der_len;
+
+    for (i = 0; i < hashlen; i++) {
+        if (*(p + i) != dgst[i]) {
+            ret = -4;
+            goto _verify_fail;
+        }
+    }
+
+    *is_valid = 1;
+    ret = 0;
+
+_verify_fail:
+
+    return ret;
+}
+
+static uint32_t rsa_padding_es_pkcs(uint8_t *dgst,
+                                    uint32_t dgstlen,
+                                    uint8_t *out,
+                                    uint32_t padding,
+                                    uint32_t keybytes)
+
+{
+    uint32_t i;
+    uint8_t *p;
+    uint32_t pslen;
+
+    p = (uint8_t *)out;
+
+    *(p++) = 0x00;
+    *(p++) = 0x02;
+
+    /* pad out with 0xff data */
+    pslen = keybytes - 3 - dgstlen;
+
+    for (i = 0; i < pslen; i++) {
+        p[i] = 0xff; /* PS */
+    }
+
+    p += pslen;
+    *(p++) = 0x0;
+
+    for (i = 0; i < dgstlen; i++) {
+        p[i] = dgst[i];
+    }
+
+    return 0;
+}
+
+static uint32_t rsa_checking_es_pkcs(uint8_t *out,
+                                     uint32_t *out_size,
+                                     uint8_t *src,
+                                     uint32_t src_size,
+                                     uint32_t padding,
+                                     uint32_t keybytes)
+{
+    uint32_t i;
+    uint8_t *p;
+    uint8_t *p_src;
+    uint32_t pslen;
+
+    p = (uint8_t *)src;
+    p_src = p;
+    *(p++) = 0x00;
+
+    if (padding == PKCS1_PADDING) {
+        if (*(p++) != 0x02) {
+            return -1;
+        }
+    } else {
+        if (*(p++) != 0x01) {
+            return -2;
+        }
+    }
+
+    pslen = src_size - 2;
+
+    while (pslen--) {
+        if (*(p++) == 0x0) {
+            break;
+        }
+    }
+
+    if (padding == PKCS1_PADDING) {
+        *out_size = pslen;
+    } else {
+        *out_size = keybytes;
+    }
+
+    for (i = 0; i < *out_size; i++) {
+        if (padding == PKCS1_PADDING) {
+            out[i] = p[i];
+        } else {
+            out[i] = p_src[i];
+        }
+    }
+
+    return 0;
+}
+
+int rsa_encrypt(uint8_t *n,         uint8_t *e,
+                uint8_t *src,       uint32_t src_size,
+                uint8_t *out,       uint32_t *out_size,
+                uint32_t padding,   uint32_t keybits_len,
+                uint32_t *tmp_c)
+{
+    uint32_t ret;
+    uint32_t tmp_n[RSA_KEY_WORD];
+    uint32_t tmp_e[RSA_KEY_WORD];
+    uint32_t tmp_in_out[RSA_KEY_WORD];
+    uint32_t keywords = 0, keybytes = 0;
+
+    keywords = GET_KEY_WORD(keybits_len);
+    keybytes = GET_KEY_BYTE(keybits_len);
+
+    convert_buf_to_bndata(n, keybytes, tmp_n, keywords);
+    convert_buf_to_bndata(e, keybytes, tmp_e, keywords);
+
+    if (padding == PKCS1_PADDING) {
+        ret = rsa_padding_es_pkcs(src,
+                                  src_size,
+                                  (uint8_t *)tmp_in_out,
+                                  padding,
+                                  keybytes);
+
+        if (ret != 0) {
+            return ret;
+        }
+
+        convert_byte_array((uint8_t *)tmp_in_out, (uint8_t *)tmp_in_out, keybytes);
+    } else {
+        convert_byte_array((uint8_t *)src, (uint8_t *)tmp_in_out, keybytes);
+    }
+
+    ret = rsa_exptmod(tmp_n, tmp_e, tmp_in_out, tmp_in_out, keywords, tmp_c);
+
+    if (ret != 0) {
+        return ret;
+    }
+
+    convert_bndata_to_buf(tmp_in_out, keywords, out, keybytes);
+    *out_size = keybytes;
+    return ret;
+}
+
+int rsa_decrypt(uint8_t *n,         uint8_t *d,
+                uint8_t *src,       uint32_t src_size,
+                uint8_t *out,       uint32_t *out_size,
+                uint32_t padding,   uint32_t keybits_len,
+                uint32_t *tmp_c)
+{
+    uint32_t ret;
+    uint32_t tmp_n[RSA_KEY_WORD];
+    uint32_t tmp_d[RSA_KEY_WORD];
+    uint32_t tmp_in_out[RSA_KEY_WORD];
+    uint32_t keywords = 0, keybytes = 0;
+
+    keywords = GET_KEY_WORD(keybits_len);
+    keybytes = GET_KEY_BYTE(keybits_len);
+
+    convert_buf_to_bndata(n, keybytes, tmp_n, keywords);
+    convert_buf_to_bndata(d, keybytes, tmp_d, keywords);
+    convert_buf_to_bndata(src, src_size, tmp_in_out, keywords);
+
+    ret = rsa_exptmod(tmp_n, tmp_d, tmp_in_out, tmp_in_out, keywords, tmp_c);
+
+    if (ret != 0) {
+        return ret;
+    }
+
+    convert_byte_array((uint8_t *)tmp_in_out, (uint8_t *)tmp_in_out, keybytes);
+
+    ret = rsa_checking_es_pkcs(out,
+                               out_size,
+                               (uint8_t *)tmp_in_out,
+                               keybytes,
+                               padding,
+                               keybytes);
+
+    return ret;
+}
+
+int rsa_sign(uint8_t *n,        uint8_t *d,
+             uint8_t *src,      uint32_t src_size,
+             uint8_t *signature, uint32_t *sig_size,
+             uint32_t type,     uint32_t keybits_len,
+             uint32_t *tmp_c)
+{
+    uint32_t ret;
+    uint32_t tmp_n[RSA_KEY_WORD];
+    uint32_t tmp_d[RSA_KEY_WORD];
+    uint32_t tmp_in_out[RSA_KEY_WORD];
+
+    uint32_t keywords = 0, keybytes = 0;
+
+    keywords = GET_KEY_WORD(keybits_len);
+    keybytes = GET_KEY_BYTE(keybits_len);
+
+    convert_buf_to_bndata(n, keybytes, tmp_n, keywords);
+    convert_buf_to_bndata(d, keybytes, tmp_d, keywords);
+
+    ret = rsa_padding_pkcs(src,
+                           (uint8_t *)tmp_in_out,
+                           type,
+                           keybytes);
+
+    if (ret != 0) {
+        return ret;
+    }
+
+    convert_byte_array((uint8_t *)tmp_in_out, (uint8_t *)tmp_in_out, keybytes);
+
+    ret = rsa_exptmod(tmp_n, tmp_d, tmp_in_out, tmp_in_out, keywords, tmp_c);
+
+    if (ret != 0) {
+        return ret;
+    }
+
+    convert_bndata_to_buf(tmp_in_out, keywords, signature, keybytes);
+    *sig_size = keybytes;
+
+    return 0;
+}
+
+int rsa_verify(uint8_t *n,          uint8_t *e,
+               uint8_t *src,        uint32_t src_size,
+               uint8_t *signature,  uint32_t sig_size,
+               uint32_t type,       uint32_t keybits_len,
+               uint8_t *result,     uint32_t *tmp_c)
+{
+    uint32_t ret;
+    uint32_t tmp_n[RSA_KEY_WORD];
+    uint32_t tmp_e[RSA_KEY_WORD];
+    uint32_t tmp_in_out[RSA_KEY_WORD];
+    uint32_t keywords = 0, keybytes = 0;
+
+    *result = 0;
+
+    keywords = GET_KEY_WORD(keybits_len);
+    keybytes = GET_KEY_BYTE(keybits_len);
+
+    convert_buf_to_bndata(n, keybytes, tmp_n, keywords);
+    convert_buf_to_bndata(e, keybytes, tmp_e, keywords);
+    convert_buf_to_bndata(signature, sig_size, tmp_in_out, keywords);
+
+    ret = rsa_exptmod(tmp_n, tmp_e, tmp_in_out, tmp_in_out, keywords, tmp_c);
+
+    if (ret != 0) {
+        return ret;
+    }
+
+    convert_byte_array((uint8_t *)tmp_in_out, (uint8_t *)tmp_in_out, keybytes);
+
+    ret = rsa_checking_pkcs(src,
+                            (uint8_t *)tmp_in_out,
+                            keybytes,
+                            result,
+                            type,
+                            keybytes);
+
+    return ret;
+}
+
+static int rsa_sw_exptmod_2_2m(uint8_t *modulus, uint32_t keybits_len, uint32_t *tmp_c)
+{
+    uint32_t keywords = 0, keybytes = 0;
+    uint32_t tmp_n[RSA_KEY_WORD];
+
+    keywords = GET_KEY_WORD(keybits_len);
+    keybytes = GET_KEY_BYTE(keybits_len);
+
+    convert_buf_to_bndata(modulus, keybytes, tmp_n, keywords);
+
+    sw_exptmod_2_2m(tmp_n, keywords, tmp_c);
+    return 0;
+}
+
+int rsa_sw_calc_modulus(uint8_t *modulus, uint32_t keybits_len)
+{
+#ifdef RSA_USING_ID2KEY
+    static uint32_t current_keybits_len;
+
+    if (current_keybits_len != keybits_len) {
+        rsa_sw_exptmod_2_2m((uint8_t *)modulus, keybits_len, g_acc);
+        current_keybits_len = keybits_len;
+    }
+
+#endif
+    return 0;
+}
+
+/**
+  \brief       get rsa handle count.
+  \return      rsa handle count
+*/
+int32_t csi_rsa_get_instance_count(void)
+{
+    return target_get_rsa_count();
+}
+
+/**
+  \brief       Initialize RSA Interface. 1. Initializes the resources needed for the RSA interface 2.registers event callback function
+  \param[in]   idx  must not exceed return value of csi_rsa_get_instance_count()
+  \param[in]   cb_event  Pointer to \ref rsa_event_cb_t
+  \return      pointer to rsa handle
+*/
+rsa_handle_t csi_rsa_initialize(int32_t idx, rsa_event_cb_t cb_event)
+{
+    if (idx < 0 || idx >= CONFIG_RSA_NUM) {
+        return NULL;
+    }
+
+    /* obtain the rsa information */
+    uint32_t base = 0u;
+    uint32_t irq;
+    int32_t real_idx = target_get_rsa(idx, &base, &irq);
+
+    if (real_idx != idx) {
+        return NULL;
+    }
+
+    ck_rsa_priv_t *rsa_priv = &rsa_handle[idx];
+
+    rsa_priv->base = base;
+    rsa_priv->irq  = irq;
+
+    /* initialize the rsa context */
+    rsa_priv->cb = cb_event;
+    rsa_priv->data_bit = RSA_DATA_BITS_1024;
+    rsa_priv->endian = RSA_ENDIAN_MODE_LITTLE;
+    rsa_priv->padding.padding_type = RSA_PADDING_MODE_PKCS1;
+    rsa_priv->padding.hash_type = RSA_HASH_TYPE_SHA1;
+    rsa_priv->status.busy = 0;
+
+#ifdef RSA_USING_ID2KEY
+    memset(g_acc, 0x0, sizeof(g_acc));
+#endif
+
+    return (rsa_handle_t)rsa_priv;
+}
+
+/**
+  \brief       De-initialize RSA Interface. stops operation and releases the software resources used by the interface
+  \param[in]   handle  rsa handle to operate.
+  \return      error code
+*/
+int32_t csi_rsa_uninitialize(rsa_handle_t handle)
+{
+    RSA_NULL_PARAM_CHK(handle);
+
+    ck_rsa_priv_t *rsa_priv = handle;
+    rsa_priv->cb = NULL;
+
+    return 0;
+}
+
+/**
+  \brief       Get driver capabilities.
+  \param[in]   handle rsa handle to operate.
+  \return      \ref rsa_capabilities_t
+*/
+rsa_capabilities_t csi_rsa_get_capabilities(rsa_handle_t handle)
+{
+    return driver_capabilities;
+}
+
+/**
+  \brief       config rsa mode.
+  \param[in]   handle  rsa handle to operate.
+  \param[in]   data_bits \ref rsa_data_bits_e
+  \param[in]   endian    \ref rsa_endian_mode_e
+  \return      error code
+*/
+int32_t csi_rsa_config(rsa_handle_t handle,
+                       rsa_data_bits_e data_bits,
+                       rsa_endian_mode_e endian,
+                       void *arg
+                      )
+{
+    RSA_NULL_PARAM_CHK(handle);
+
+    ck_rsa_priv_t *rsa_priv = handle;
+    rsa_reg = (ck_rsa_reg_t *)(rsa_priv->base);
+
+    /* config the data bits */
+    switch (data_bits) {
+        case RSA_DATA_BITS_192:
+        case RSA_DATA_BITS_256:
+        case RSA_DATA_BITS_512:
+            return ERR_RSA(EDRV_UNSUPPORTED);
+
+        case RSA_DATA_BITS_1024:
+        case RSA_DATA_BITS_2048:
+            rsa_priv->data_bit = data_bits;
+            break;
+
+        default:
+            return ERR_RSA(EDRV_PARAMETER);
+    }
+
+    /* config the endian mode */
+    if (endian == RSA_ENDIAN_MODE_LITTLE) {
+        rsa_priv->endian = endian;
+    } else if (endian == RSA_ENDIAN_MODE_BIG) {
+        return ERR_RSA(EDRV_UNSUPPORTED);
+    } else {
+        return ERR_RSA(EDRV_PARAMETER);
+    }
+
+    if (arg != NULL) {
+#ifdef RSA_USING_ID2KEY
+        uint32_t keybits_len = 1024;
+
+        if (data_bits == RSA_DATA_BITS_2048) {
+            keybits_len = 2048;
+        }
+
+        rsa_sw_calc_modulus(arg, keybits_len);
+#else
+        //memcpy(g_acc, arg, sizeof(g_acc));
+#endif
+    }
+
+    return 0;
+}
+
+/**
+  \brief       encrypt
+  \param[in]   handle  rsa handle to operate.
+  \param[in]   n         Pointer to the public modulus
+  \param[in]   e         Pointer to the public exponent
+  \param[in]   src       Pointer to the source data.
+  \param[in]   src_size  the source data len
+  \param[out]  out       Pointer to the result buffer
+  \param[out]  out_size  the result size
+  \param[in]   padding   \ref  rsa_padding_t
+  \return      error code
+*/
+int32_t csi_rsa_encrypt(rsa_handle_t handle, void *n, void *e, void *src, int32_t src_size, void *out, uint32_t *out_size, rsa_padding_t padding)
+{
+#ifndef RSA_USING_ID2KEY
+    uint32_t tmp_c[RSA_KEY_WORD];
+#endif
+    RSA_NULL_PARAM_CHK(handle);
+    RSA_NULL_PARAM_CHK(n);
+    RSA_NULL_PARAM_CHK(e);
+    RSA_NULL_PARAM_CHK(src);
+    RSA_NULL_PARAM_CHK(out);
+    RSA_NULL_PARAM_CHK(out_size);
+
+    if (src_size <= 0 || (padding.padding_type != RSA_PADDING_MODE_PKCS1 && padding.padding_type != RSA_PADDING_MODE_NO)) {
+        return ERR_RSA(EDRV_PARAMETER);
+    }
+
+    ck_rsa_priv_t *rsa_priv = handle;
+    rsa_priv->status.busy = 1U;
+
+    uint32_t bit_length = 1024;
+
+    if (rsa_priv->data_bit == RSA_DATA_BITS_2048) {
+        bit_length = 2048;
+    }
+
+#ifndef RSA_USING_ID2KEY
+    rsa_sw_exptmod_2_2m(n, bit_length, tmp_c);
+#endif
+
+    rsa_encrypt((uint8_t *)n, (uint8_t *)e, (uint8_t *)src, (uint32_t)src_size, (uint8_t *)out, (uint32_t *)out_size, (uint32_t)(padding.padding_type), bit_length, tmp_c);
+    rsa_priv->status.busy = 0U;
+
+    if (rsa_priv->cb) {
+        rsa_priv->cb(RSA_EVENT_ENCRYPT_COMPLETE);
+    }
+
+    return 0;
+}
+
+/**
+  \brief       decrypt
+  \param[in]   handle  rsa handle to operate.
+  \param[in]   n         Pointer to the public modulus
+  \param[in]   d         Pointer to the privte exponent
+  \param[in]   src       Pointer to the source data.
+  \param[in]   src_size  the source data len
+  \param[out]  out       Pointer to the result buffer
+  \param[out]  out_size  the result size
+  \param[in]   padding   \ref rsa_padding_t
+  \return      error code
+*/
+int32_t csi_rsa_decrypt(rsa_handle_t handle, void *n, void *d, void *src, uint32_t src_size, void *out, uint32_t *out_size, rsa_padding_t padding)
+{
+#ifndef RSA_USING_ID2KEY
+    uint32_t tmp_c[RSA_KEY_WORD];
+#endif
+    RSA_NULL_PARAM_CHK(handle);
+    RSA_NULL_PARAM_CHK(n);
+    RSA_NULL_PARAM_CHK(d);
+    RSA_NULL_PARAM_CHK(src);
+    RSA_NULL_PARAM_CHK(out);
+    RSA_NULL_PARAM_CHK(out_size);
+
+    if (src_size <= 0 || (padding.padding_type != RSA_PADDING_MODE_PKCS1 && padding.padding_type != RSA_PADDING_MODE_NO)) {
+        return ERR_RSA(EDRV_PARAMETER);
+    }
+
+    ck_rsa_priv_t *rsa_priv = handle;
+    rsa_priv->status.busy = 1U;
+
+    uint32_t bit_length = 1024;
+
+    if (rsa_priv->data_bit == RSA_DATA_BITS_2048) {
+        bit_length = 2048;
+    }
+
+#ifndef RSA_USING_ID2KEY
+    rsa_sw_exptmod_2_2m(n, bit_length, tmp_c);
+#endif
+
+    rsa_decrypt((uint8_t *)n, (uint8_t *)d, (uint8_t *)src, (uint32_t)src_size, (uint8_t *)out, (uint32_t *)out_size, (uint32_t)(padding.padding_type), bit_length, tmp_c);
+    rsa_priv->status.busy = 0U;
+
+    if (rsa_priv->cb) {
+        rsa_priv->cb(RSA_EVENT_DECRYPT_COMPLETE);
+    }
+
+    return 0;
+}
+
+/**
+  \brief       rsa sign
+  \param[in]   handle  rsa handle to operate.
+  \param[in]   n         Pointer to the public modulus
+  \param[in]   d         Pointer to the privte exponent
+  \param[in]   src       Pointer to the source data.
+  \param[in]   src_size  the source data len
+  \param[out]  signature Pointer to the signature
+  \param[out]  sig_size  the signature size
+  \param[in]   padding   \ref rsa_padding_t
+  \return      error code
+*/
+int32_t csi_rsa_sign(rsa_handle_t handle, void *n, void *d, void *src, uint32_t src_size, void *signature, void *sig_size, rsa_padding_t padding)
+{
+#ifndef RSA_USING_ID2KEY
+    uint32_t tmp_c[RSA_KEY_WORD];
+#endif
+    RSA_NULL_PARAM_CHK(handle);
+    RSA_NULL_PARAM_CHK(n);
+    RSA_NULL_PARAM_CHK(d);
+    RSA_NULL_PARAM_CHK(src);
+    RSA_NULL_PARAM_CHK(signature);
+    RSA_NULL_PARAM_CHK(sig_size);
+
+    if (src_size <= 0 || (padding.hash_type != RSA_HASH_TYPE_MD5
+                          && padding.hash_type != RSA_HASH_TYPE_SHA1
+                          && padding.hash_type != RSA_HASH_TYPE_SHA256)) {
+        return ERR_RSA(EDRV_PARAMETER);
+    }
+
+    ck_rsa_priv_t *rsa_priv = handle;
+    rsa_priv->status.busy = 1U;
+    uint32_t bit_length = 1024;
+
+    if (rsa_priv->data_bit == RSA_DATA_BITS_2048) {
+        bit_length = 2048;
+    }
+
+#ifndef RSA_USING_ID2KEY
+    rsa_sw_exptmod_2_2m(n, bit_length, tmp_c);
+#endif
+
+    rsa_sign((uint8_t *)n, (uint8_t *)d, (uint8_t *)src, (uint32_t)src_size, (uint8_t *)signature, (uint32_t *)sig_size, (uint32_t)(padding.hash_type), bit_length, tmp_c);
+    rsa_priv->status.busy = 0U;
+
+    if (rsa_priv->cb) {
+        rsa_priv->cb(RSA_EVENT_SIGN_COMPLETE);
+    }
+
+    return 0;
+}
+
+/**
+  \brief       rsa verify
+  \param[in]   handle  rsa handle to operate.
+  \param[in]   n         Pointer to the public modulus
+  \param[in]   e         Pointer to the public exponent
+  \param[in]   src       Pointer to the source data.
+  \param[in]   src_size  the source data len
+  \param[in]   signature Pointer to the signature
+  \param[in]   sig_size  the signature size
+  \param[out]  result    Pointer to the result
+  \param[in]   padding   \ref rsa_padding_t
+  \return      error code
+*/
+int32_t csi_rsa_verify(rsa_handle_t handle, void *n, void *e, void *src, uint32_t src_size, void *signature, uint32_t sig_size, void *result, rsa_padding_t padding)
+{
+#ifndef RSA_USING_ID2KEY
+    uint32_t tmp_c[RSA_KEY_WORD];
+#endif
+    RSA_NULL_PARAM_CHK(handle);
+    RSA_NULL_PARAM_CHK(n);
+    RSA_NULL_PARAM_CHK(e);
+    RSA_NULL_PARAM_CHK(src);
+    RSA_NULL_PARAM_CHK(signature);
+    RSA_NULL_PARAM_CHK(result);
+
+    if (src_size <= 0 || sig_size <= 0 || (padding.hash_type != RSA_HASH_TYPE_MD5 && padding.hash_type != RSA_HASH_TYPE_SHA1 && padding.hash_type != RSA_HASH_TYPE_SHA256)) {
+        return ERR_RSA(EDRV_PARAMETER);
+    }
+
+    ck_rsa_priv_t *rsa_priv = handle;
+    rsa_priv->status.busy = 1U;
+
+    uint32_t bit_length = 1024;
+
+    if (rsa_priv->data_bit == RSA_DATA_BITS_2048) {
+        bit_length = 2048;
+    }
+
+#ifndef RSA_USING_ID2KEY
+    rsa_sw_exptmod_2_2m(n, bit_length, tmp_c);
+#endif
+
+    rsa_verify((uint8_t *)n, (uint8_t *)e, (uint8_t *)src, (uint32_t)src_size, (uint8_t *)signature, sig_size, (uint32_t)(padding.hash_type), bit_length, (uint8_t *)result, tmp_c);
+    rsa_priv->status.busy = 0U;
+
+    if (rsa_priv->cb) {
+        rsa_priv->cb(RSA_EVENT_VERIFY_COMPLETE);
+    }
+
+    return 0;
+}
+
+/**
+  \brief       Get RSA status.
+  \param[in]   handle  rsa handle to operate.
+  \return      RSA status \ref rsa_status_t
+*/
+rsa_status_t csi_rsa_get_status(rsa_handle_t handle)
+{
+    ck_rsa_priv_t *rsa_priv = handle;
+    return rsa_priv->status;
+}