1 /*
2  * Copyright (c) 2021-2024 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 #include "hpm_sdp_drv.h"
8 #include "hpm_soc_feature.h"
9 
10 /***********************************************************************************************************************
11  * Definitions
12  **********************************************************************************************************************/
13 /**
14  * AES Key source definition
15  */
16 #define AES_KEY_SRC_SDP_START_IDX 0U
17 #define AES128_KEY_SRC_SDP_END_IDX 0xFU
18 #define AES256_KEY_SRC_SDP_END_IDX 0x7U
19 #define AES_KEY_SRC_KEYMAN_START_IDX 0x20U
20 #define AES128_KEY_SRC_KEYMAN_END_IDX 0x2FU
21 #define AES256_KEY_SRC_KEYMAN_END_IDX 0x2FU
22 #define AES_KEY_SRC_UNIQUE_KEY_START_IDX 0x3EU
23 #define AES_KEY_SRC_OTP_KEY_START_IDX 0x3FU
24 
25 #define AES_256_KEY_SIZE_IN_WORDS (8U)
26 #define AES_256_KEY_SIZE_IN_BYTES (32U)
27 
28 #define CRC32_DIGEST_SIZE_IN_BYTES (4U)
29 #define SHA1_DIGEST_SIZE_IN_BYTES  (20U)
30 #define SHA256_DIGEST_SIZE_IN_BYTES (32U)
31 
32 #define AES_CTR_BLOCK_UNIT (16U)
33 
34 typedef enum {
35     sdp_state_hash_init, sdp_state_hash_update,
36 } sdp_hash_alg_state_t;
37 
38 #define AES_BLOCK_SIZE (16U)
39 #define HASH_BLOCK_SIZE (64U)
40 #define HASH_DIGEST_SIZE_MAX (32)
41 
42 #define SDP_CRYPTO_ALG_IDX_AES128 (0U)
43 #define SDP_CRYPTO_ALG_IDX_AES256 (1U)
44 #define SDP_CRYPTO_ALG_IDX_SM4 (8U)
45 
46 typedef struct {
47     union {
48         uint32_t words[HASH_BLOCK_SIZE / sizeof(uint32_t)];
49         uint8_t bytes[HASH_BLOCK_SIZE];
50     } block;
51     uint32_t blk_size;
52     uint32_t full_msg_size;
53     uint32_t running_hash[HASH_DIGEST_SIZE_MAX / sizeof(uint32_t)];
54     sdp_hash_alg_t alg;
55     sdp_hash_alg_state_t state;
56     bool hash_init;
57     bool hash_finish;
58 } sdp_hash_internal_ctx_t;
59 
60 /***********************************************************************************************************************
61  * Prototypes
62  **********************************************************************************************************************/
63 static void sdp_hash_internal_engine_init(SDP_Type *base, sdp_hash_ctx_t *hash_ctx);
64 
65 static hpm_stat_t sdp_hash_process_message(SDP_Type *base, sdp_hash_ctx_t *ctx, const uint8_t *msg, uint32_t msg_size);
66 
67 static hpm_stat_t sdp_hash_internal_update(SDP_Type *base, sdp_hash_ctx_t *ctx, const uint8_t *msg, uint32_t msg_size);
68 
69 static hpm_stat_t sdp_hash_finalize(SDP_Type *base, sdp_hash_ctx_t *hash_ctx);
70 
sdp_clear_error_status(SDP_Type * base)71 static inline void sdp_clear_error_status(SDP_Type *base)
72 {
73     base->STA = 0xFFFFFFFFUL;
74 }
75 
76 static void sdp_increment_bn(uint8_t *big_num, uint32_t bytes);
77 
78 static void uint32_to_be(uint8_t *dst, uint32_t len, uint32_t num);
79 
80 static hpm_stat_t aes_ccm_auth_crypt(SDP_Type *base,
81                                      sdp_aes_ctx_t *aes_ctx,
82                                      sdp_aes_op_t op,
83                                      uint32_t input_len,
84                                      const uint8_t *iv,
85                                      uint32_t iv_len,
86                                      const uint8_t *aad,
87                                      uint32_t aad_len,
88                                      const uint8_t *input,
89                                      uint8_t *output,
90                                      uint8_t *mac,
91                                      uint32_t mac_len);
92 
93 static void aes_ccm_format_b0(uint8_t *block,
94                               const uint8_t *iv,
95                               uint32_t iv_len,
96                               uint32_t mac_len,
97                               uint32_t aad_len,
98                               uint32_t input_len);
99 
100 static void aes_ccm_format_ctr0(uint8_t *ctr, const uint8_t *iv, uint8_t iv_len);
101 
102 static uint8_t sdp_constant_time_cmp(const void *dst, const void *src, uint32_t len);
103 
104 /***********************************************************************************************************************
105  * Codes
106  **********************************************************************************************************************/
sdp_wait_done(SDP_Type * base)107 hpm_stat_t sdp_wait_done(SDP_Type *base)
108 {
109     hpm_stat_t status;
110     uint32_t sdp_sta;
111     do {
112         sdp_sta = base->STA;
113         if (IS_HPM_BITMASK_SET(sdp_sta, SDP_STA_ERRSET_MASK)) {
114             status = status_sdp_error_setup;
115         } else if (IS_HPM_BITMASK_SET(sdp_sta, SDP_STA_ERRPKT_MASK)) {
116             status = status_sdp_error_packet;
117         } else if (IS_HPM_BITMASK_SET(sdp_sta, SDP_STA_ERRSRC_MASK)) {
118             status = status_sdp_error_src;
119         } else if (IS_HPM_BITMASK_SET(sdp_sta, SDP_STA_ERRDST_MASK)) {
120             status = status_sdp_error_dst;
121         } else if (IS_HPM_BITMASK_SET(sdp_sta, SDP_STA_ERRHAS_MASK)) {
122             status = status_sdp_error_hash;
123         } else if (IS_HPM_BITMASK_SET(sdp_sta, SDP_STA_ERRCHAIN_MASK)) {
124             status = status_sdp_error_chain;
125         } else {
126             status = status_success;
127         }
128     } while (IS_HPM_BITMASK_CLR(sdp_sta, SDP_STA_PKTCNT0_MASK));
129 
130     return status;
131 }
132 
sdp_init(SDP_Type * base)133 hpm_stat_t sdp_init(SDP_Type *base)
134 {
135     hpm_stat_t status = status_invalid_argument;
136     if (base != NULL) {
137         base->SDPCR &= ~(SDP_SDPCR_CLKGAT_MASK | SDP_SDPCR_SFTRST_MASK);
138 
139         status = status_success;
140     }
141 
142     return status;
143 }
144 
sdp_deinit(SDP_Type * base)145 hpm_stat_t sdp_deinit(SDP_Type *base)
146 {
147     hpm_stat_t status = status_invalid_argument;
148     if (base != NULL) {
149         base->SDPCR |= SDP_SDPCR_CLKGAT_MASK;
150         status = status_success;
151     }
152     return status;
153 }
154 
sdp_aes_set_key(SDP_Type * base,sdp_aes_ctx_t * aes_ctx,const uint8_t * key,sdp_aes_key_bits_t key_bits,uint32_t key_idx)155 hpm_stat_t sdp_aes_set_key(SDP_Type *base,
156                            sdp_aes_ctx_t *aes_ctx,
157                            const uint8_t *key,
158                            sdp_aes_key_bits_t key_bits,
159                            uint32_t key_idx)
160 {
161     union {
162         uint32_t words[AES_256_KEY_SIZE_IN_WORDS];
163         uint8_t bytes[AES_256_KEY_SIZE_IN_BYTES];
164     } aes_key;
165 
166     assert((base != NULL) && (aes_ctx != NULL) && (key_bits <= sdp_aes_keybits_256));
167 
168     hpm_stat_t status = status_invalid_argument;
169     do {
170         aes_ctx->crypto_algo = sdp_crypto_alg_aes;
171 
172         if (IS_HPM_BITMASK_SET(base->SDPCR, SDP_SDPCR_CIPDIS_MASK)) {
173             status = status_sdp_no_crypto_support;
174             break;
175         }
176 
177         HPM_BREAK_IF((key_bits != sdp_aes_keybits_128) && (key_bits != sdp_aes_keybits_256));
178 
179         aes_ctx->key_bits = key_bits;
180 
181         uint32_t key128_idx = key_idx;
182         if (key_bits == sdp_aes_keybits_256) {
183             if (key_idx <= AES256_KEY_SRC_SDP_END_IDX) {
184                 (void) memcpy(aes_key.bytes, key, 32);
185                 key128_idx = key_idx * 2U;
186                 uint32_t idx = 0;
187                 for (uint32_t i = 0; i < 2; i++) {
188                     base->KEYADDR = SDP_KEYADDR_INDEX_SET(key128_idx + i);
189                     for (uint32_t j = 0; j < 4; j++) {
190                         base->KEYDAT = aes_key.words[idx++];
191                     }
192                 }
193             } else if ((key_idx >= AES_KEY_SRC_KEYMAN_START_IDX) && (key_idx <= AES256_KEY_SRC_KEYMAN_END_IDX)) {
194                 key128_idx = (key_idx - AES_KEY_SRC_KEYMAN_START_IDX) * 2U + AES_KEY_SRC_KEYMAN_START_IDX;
195             }
196         } else {
197             if (key_idx <= AES128_KEY_SRC_SDP_END_IDX) {
198                 (void) memcpy(aes_key.bytes, key, 16);
199                 base->KEYADDR = SDP_KEYADDR_INDEX_SET(key_idx);
200                 for (uint32_t j = 0; j < 4; j++) {
201                     base->KEYDAT = aes_key.words[j];
202                 }
203             }
204         }
205 
206         aes_ctx->key_idx = key128_idx;
207         aes_ctx->key_bits = key_bits;
208         status = status_success;
209 
210     } while (false);
211 
212     return status;
213 }
214 
215 #if defined(SDP_HAS_SM4_SUPPORT) && (SDP_HAS_SM4_SUPPORT == 1)
216 
sdp_sm4_set_key(SDP_Type * base,sdp_sm4_ctx_t * sm4_ctx,const uint8_t * key,sdp_sm4_key_bits_t key_bits,uint32_t key_idx)217 hpm_stat_t sdp_sm4_set_key(SDP_Type *base,
218                            sdp_sm4_ctx_t *sm4_ctx,
219                            const uint8_t *key,
220                            sdp_sm4_key_bits_t key_bits,
221                            uint32_t key_idx)
222 {
223     hpm_stat_t status = status_invalid_argument;
224     if (key_bits != sdp_sm4_keybits_128) {
225         return status;
226     }
227     status = sdp_aes_set_key(base, sm4_ctx, key, (sdp_aes_key_bits_t) key_bits, key_idx);
228     if (status != status_success) {
229         return status;
230     }
231     sm4_ctx->crypto_algo = sdp_crypto_alg_sm4;
232 
233     return status;
234 }
235 
236 #endif
237 
sdp_aes_crypt_ecb(SDP_Type * base,sdp_aes_ctx_t * aes_ctx,sdp_aes_op_t op,uint32_t len,const uint8_t * in,uint8_t * out)238 hpm_stat_t sdp_aes_crypt_ecb(SDP_Type *base,
239                              sdp_aes_ctx_t *aes_ctx,
240                              sdp_aes_op_t op,
241                              uint32_t len,
242                              const uint8_t *in,
243                              uint8_t *out)
244 {
245     assert((base != NULL) && (aes_ctx != NULL));
246 
247     hpm_stat_t status;
248 
249     base->SDPCR = SDP_SDPCR_CIPHEN_MASK;
250 #if defined(SDP_REGISTER_DESCRIPTOR_COUNT) && SDP_REGISTER_DESCRIPTOR_COUNT
251     base->SDPCR |= HPM_BITSMASK(1, 8);
252     base->PKTCTL = SDP_PKT_CTRL_DERSEMA_MASK;
253     base->PKTSRC = (uint32_t) in;
254     base->PKTDST = (uint32_t) out;
255     base->PKTBUF = len;
256 #else
257     sdp_pkt_struct_t *pkt_desc = &aes_ctx->sdp_pkt;
258     pkt_desc->next_cmd = NULL;
259     pkt_desc->pkt_ctrl.PKT_CTRL = SDP_PKT_CTRL_DERSEMA_MASK;
260     pkt_desc->src_addr = (uint32_t) in;
261     pkt_desc->dst_addr = (uint32_t) out;
262     pkt_desc->buf_size = len;
263 
264 #endif
265     sdp_clear_error_status(base);
266 
267     if (aes_ctx->crypto_algo == sdp_crypto_alg_aes) {
268         if (aes_ctx->key_bits == sdp_aes_keybits_128) {
269             base->MODCTRL =
270             SDP_MODCTRL_AESALG_SET(SDP_CRYPTO_ALG_IDX_AES128) | SDP_MODCTRL_AESKS_SET(aes_ctx->key_idx) |
271             SDP_MODCTRL_AESDIR_SET(op);
272         } else {
273             base->MODCTRL =
274             SDP_MODCTRL_AESALG_SET(SDP_CRYPTO_ALG_IDX_AES256) | SDP_MODCTRL_AESKS_SET(aes_ctx->key_idx) |
275             SDP_MODCTRL_AESDIR_SET(op);
276         }
277     }
278 #if defined(SDP_HAS_SM4_SUPPORT) && (SDP_HAS_SM4_SUPPORT == 1)
279     else if (aes_ctx->crypto_algo == sdp_crypto_alg_sm4) {
280         base->MODCTRL = SDP_MODCTRL_AESALG_SET(SDP_CRYPTO_ALG_IDX_SM4) | SDP_MODCTRL_AESKS_SET(aes_ctx->key_idx) |
281                         SDP_MODCTRL_AESDIR_SET(op);
282     }
283 #endif
284     else {
285         return status_sdp_invalid_alg;
286     }
287 
288 #if defined(SDP_REGISTER_DESCRIPTOR_COUNT) && SDP_REGISTER_DESCRIPTOR_COUNT
289     base->CMDPTR = 0;
290 #else
291     base->CMDPTR = (uint32_t) pkt_desc;
292 #endif
293     base->PKTCNT = 1U;
294 
295     status = sdp_wait_done(base);
296 
297     return status;
298 }
299 
sdp_aes_crypt_cbc(SDP_Type * base,sdp_aes_ctx_t * aes_ctx,sdp_aes_op_t op,uint32_t length,const uint8_t iv[16],const uint8_t * input,uint8_t * output)300 hpm_stat_t sdp_aes_crypt_cbc(SDP_Type *base,
301                              sdp_aes_ctx_t *aes_ctx,
302                              sdp_aes_op_t op,
303                              uint32_t length,
304                              const uint8_t iv[16],
305                              const uint8_t *input,
306                              uint8_t *output)
307 {
308     assert((base != NULL) && (aes_ctx != NULL));
309     assert((op <= sdp_aes_op_decrypt) && (input != NULL) && (output != NULL));
310 
311     hpm_stat_t status;
312 
313     base->SDPCR = SDP_SDPCR_CIPHEN_MASK;
314 #if defined(SDP_REGISTER_DESCRIPTOR_COUNT) && SDP_REGISTER_DESCRIPTOR_COUNT
315     base->SDPCR |= HPM_BITSMASK(1, 8);
316     base->PKTCTL = SDP_PKT_CTRL_DERSEMA_MASK | SDP_PKT_CTRL_CIPHIV_MASK;
317     base->PKTSRC = (uint32_t) input;
318     base->PKTDST = (uint32_t) output;
319     base->PKTBUF = length;
320 #else
321     sdp_pkt_struct_t *pkt_desc = &aes_ctx->sdp_pkt;
322     pkt_desc->next_cmd = NULL;
323     pkt_desc->pkt_ctrl.PKT_CTRL = SDP_PKT_CTRL_DERSEMA_MASK | SDP_PKT_CTRL_CIPHIV_MASK;
324     pkt_desc->src_addr = (uint32_t) input;
325     pkt_desc->dst_addr = (uint32_t) output;
326     pkt_desc->buf_size = length;
327 #endif
328 
329     sdp_clear_error_status(base);
330 
331     if (aes_ctx->crypto_algo == sdp_crypto_alg_aes) {
332         if (aes_ctx->key_bits == sdp_aes_keybits_128) {
333             base->MODCTRL =
334             SDP_MODCTRL_AESALG_SET(SDP_CRYPTO_ALG_IDX_AES128) | SDP_MODCTRL_AESKS_SET(aes_ctx->key_idx) |
335             SDP_MODCTRL_AESDIR_SET(op) | SDP_MODCTRL_AESMOD_SET(1);
336         } else {
337             base->MODCTRL =
338             SDP_MODCTRL_AESALG_SET(SDP_CRYPTO_ALG_IDX_AES256) | SDP_MODCTRL_AESKS_SET(aes_ctx->key_idx) |
339             SDP_MODCTRL_AESDIR_SET(op) | SDP_MODCTRL_AESMOD_SET(1);
340         }
341     }
342 #if defined(SDP_HAS_SM4_SUPPORT) && (SDP_HAS_SM4_SUPPORT == 1)
343     else if (aes_ctx->crypto_algo == sdp_crypto_alg_sm4) {
344         base->MODCTRL = SDP_MODCTRL_AESALG_SET(SDP_CRYPTO_ALG_IDX_SM4) | SDP_MODCTRL_AESKS_SET(aes_ctx->key_idx) |
345                         SDP_MODCTRL_AESDIR_SET(op) | SDP_MODCTRL_AESMOD_SET(1);
346     }
347 #endif
348     else {
349         return status_sdp_invalid_alg;
350     }
351 
352     /* Set IV, copy the IV to the context first in case the IV address is not 32-bit aligned */
353     uint32_t iv_32[4];
354     (void) memcpy(iv_32, iv, 16);
355     for (uint32_t i = 0; i < 4; i++) {
356         base->CIPHIV[i] = iv_32[i];
357     }
358     (void) memset(iv_32, 0, sizeof(iv_32));
359 #if defined(SDP_REGISTER_DESCRIPTOR_COUNT) && SDP_REGISTER_DESCRIPTOR_COUNT
360     base->CMDPTR = 0;
361 #else
362     base->CMDPTR = (uint32_t) pkt_desc;
363 #endif
364     base->PKTCNT = 1U;
365 
366     status = sdp_wait_done(base);
367 
368     return status;
369 }
370 
371 /*
372  * In the AES-CTR algorithm, all the numbers are represented in big-endian format, namely, LSB is in last byte
373  */
sdp_increment_bn(uint8_t * big_num,uint32_t bytes)374 static void sdp_increment_bn(uint8_t *big_num, uint32_t bytes)
375 {
376     for (uint32_t i = bytes - 1; i > 0u; i--) {
377         big_num[i]++;
378         if (big_num[i] != 0) {
379             break;
380         }
381     }
382 }
383 
sdp_aes_crypt_ctr(SDP_Type * base,sdp_aes_ctx_t * aes_ctx,uint8_t * nonce_counter,uint8_t * input,uint8_t * output,uint32_t length)384 hpm_stat_t sdp_aes_crypt_ctr(SDP_Type *base,
385                              sdp_aes_ctx_t *aes_ctx,
386                              uint8_t *nonce_counter,
387                              uint8_t *input,
388                              uint8_t *output,
389                              uint32_t length)
390 {
391     hpm_stat_t status = status_invalid_argument;
392 
393     do {
394         HPM_BREAK_IF(
395         (base == NULL) || (aes_ctx == NULL) || (nonce_counter == NULL) || (input == NULL) || (output == NULL));
396 
397         uint32_t calc_len;
398         uint8_t *cipher_nonce = (uint8_t *) &aes_ctx->buf3;
399         while (length > 0) {
400             calc_len = (length < 16U) ? length : 16U;
401             status = sdp_aes_crypt_ecb(base, aes_ctx, sdp_aes_op_encrypt, 16, nonce_counter, cipher_nonce);
402             HPM_BREAK_IF(status != status_success);
403             uint8_t tmp;
404             for (uint32_t i = 0; i < calc_len; i++) {
405                 tmp = *input++;
406                 *output++ = (uint8_t) (tmp ^ cipher_nonce[i]);
407             }
408 
409             length -= calc_len;
410             /* Increment counter, (128-bit big-endian */
411             sdp_increment_bn(nonce_counter, AES_CTR_BLOCK_UNIT);
412         }
413 
414     } while (false);
415 
416     return status;
417 }
418 
uint32_to_be(uint8_t * dst,uint32_t len,uint32_t num)419 static void uint32_to_be(uint8_t *dst, uint32_t len, uint32_t num)
420 {
421     uint32_t i = 0;
422 
423     (void) memset(dst, 0, len);
424 
425     while (num > 0) {
426         dst[len - 1 - i] = num & 0xFF;
427         num >>= 8;
428         i++;
429     }
430 }
431 
432 /*
433  * See section A2.1 in NIST Special Publication 800-38C
434  * q + n = 15
435  * n - nonce / iv
436  * byte0 = FLAG
437  * bit[2:0] - (q-1)
438  * bit[5:3] - (t-2/2
439  * bit[6] - adata
440  * bit[7] - reserved
441  *
442  * byte (1... 15-q) nonce
443  * byte (16-q...15) input length
444  *
445  */
aes_ccm_format_b0(uint8_t * block,const uint8_t * iv,uint32_t iv_len,uint32_t mac_len,uint32_t aad_len,uint32_t input_len)446 static void aes_ccm_format_b0(uint8_t *block,
447                               const uint8_t *iv,
448                               uint32_t iv_len,
449                               uint32_t mac_len,
450                               uint32_t aad_len,
451                               uint32_t input_len)
452 {
453     uint8_t q = 15U - iv_len;
454     block[0] = 0;
455     block[0] |= (aad_len > 0) ? (1U << 6) : 0U;
456     block[0] |= ((mac_len - 2U) / 2U) << 3;
457     block[0] |= q - 1U;
458 
459     (void) memcpy(block + 1U, iv, iv_len);
460 
461     uint32_to_be(block + 1U + iv_len, q, input_len);
462 
463 }
464 
465 /*
466  * See section A2.3 in NIST Special Publication 800-38C
467  *  q + n = 15
468  *  n - nonce/iv
469  *  byte 0 = FLAG
470  *  bit[2:0] : (q - 1)
471  *  bit[5:3] : 0
472  *  bit[7:6] : 0
473  *
474  *  byte (1...15-q) nonce
475  *  byte (16-q ...15) i
476  */
aes_ccm_format_ctr0(uint8_t * ctr,const uint8_t * iv,uint8_t iv_len)477 static void aes_ccm_format_ctr0(uint8_t *ctr, const uint8_t *iv, uint8_t iv_len)
478 {
479     uint8_t q = 15U - iv_len;
480     (void) memset(ctr, 0, 16);
481     ctr[0] |= q - 1U;
482     (void) memcpy(ctr + 1U, iv, iv_len);
483 }
484 
aes_ccm_auth_crypt(SDP_Type * base,sdp_aes_ctx_t * aes_ctx,sdp_aes_op_t op,uint32_t input_len,const uint8_t * iv,uint32_t iv_len,const uint8_t * aad,uint32_t aad_len,const uint8_t * input,uint8_t * output,uint8_t * tag,uint32_t tag_len)485 static hpm_stat_t aes_ccm_auth_crypt(SDP_Type *base,
486                                      sdp_aes_ctx_t *aes_ctx,
487                                      sdp_aes_op_t op,
488                                      uint32_t input_len,
489                                      const uint8_t *iv,
490                                      uint32_t iv_len,
491                                      const uint8_t *aad,
492                                      uint32_t aad_len,
493                                      const uint8_t *input,
494                                      uint8_t *output,
495                                      uint8_t *tag,
496                                      uint32_t tag_len)
497 {
498     hpm_stat_t status = status_invalid_argument;
499 
500     do {
501         HPM_BREAK_IF((base == NULL) || (aes_ctx == NULL) || (input == NULL) || (output == NULL) || (tag == NULL));
502 
503 
504         /*See section A.1 in NIST Special Publication 800-38C */
505 
506         /* Valid Tlen is 4, 6, 8, 10, 12, 14, 16 */
507         HPM_BREAK_IF((tag_len % 2U != 0U) || (tag_len / 2U < 2) || (tag_len / 2U > 8));
508         /* Valid Nonce length is 7, 8, 9, 10, 11, 12, 13 */
509         HPM_BREAK_IF((iv_len < 7U) || (iv_len > 13U));
510 
511         /* Note, this API supports maximum 2^32 - 1 bytes of data, so the valid q value should be 2, 3, or 4  */
512         uint8_t *b = (uint8_t *) &aes_ctx->buf0;
513         uint8_t *y = (uint8_t *) &aes_ctx->buf1;
514         uint8_t *ctr = (uint8_t *) &aes_ctx->buf2;
515 
516         /* Format B0 */
517         aes_ccm_format_b0(b, iv, iv_len, tag_len, aad_len, input_len);
518 
519         /* Calculate Y0 */
520         sdp_aes_crypt_ecb(base, aes_ctx, sdp_aes_op_encrypt, 16, b, y);
521 
522 
523         /*
524          * Follow A2.2.2 in NIST Special Publication 800-38C, only supports up to 2^32 bytes
525          */
526         if (aad_len > 0U) {
527             uint32_t calc_len = 0U;
528             const uint8_t *aad_src = aad;
529             uint32_t remaining_len = aad_len;
530             (void) memset(b, 0, 16);
531             /* format B1
532              * Follow A2.2.2 in NIST Special Publication 800-38C, only supports up to 2^32 bytes
533              */
534             if (aad_len < ((1UL << 16) - (1U << 8))) {
535                 uint32_to_be(b, 2, aad_len);
536                 calc_len = MIN(remaining_len, 14U);
537                 (void) memcpy(&b[2], aad_src, calc_len);
538             } else {
539                 b[0] = 0xFFU;
540                 b[1] = 0xFEU;
541                 uint32_to_be(&b[6], 4, calc_len);
542                 calc_len = 10U;
543                 (void) memcpy(&b[2], aad_src, calc_len);
544             }
545             aad_src += calc_len;
546             remaining_len -= calc_len;
547             /* Calculate Y(i) = CIPHk(B(i) ^ Y(i-1)) */
548             sdp_aes_crypt_cbc(base, aes_ctx, sdp_aes_op_encrypt, 16, b, y, y);
549 
550             while (remaining_len > 0U) {
551                 calc_len = MIN(remaining_len, 16U);
552                 (void) memcpy(b, aad_src, calc_len);
553                 if (calc_len < 16U) {
554                     (void) memset(&b[calc_len], 0, 16U - calc_len);
555                 }
556                 aad_src += calc_len;
557                 remaining_len -= calc_len;
558                 /* Calculate Y(i) = CIPHk(B(i) ^ Y(i-1)) */
559                 sdp_aes_crypt_cbc(base, aes_ctx, sdp_aes_op_encrypt, 16, b, y, y);
560             }
561         }
562 
563         aes_ccm_format_ctr0(ctr, iv, iv_len);
564         /* Encryption/Decryption starts from CTR1 */
565         sdp_increment_bn(ctr, 16);
566         /* Continue CBC-MAC calculation + Encryption/Decryption */
567         uint32_t remaining_len = input_len;
568         uint8_t *src = (uint8_t *) input;
569         uint8_t *dst = output;
570         while (remaining_len > 0U) {
571             uint32_t calc_len = MIN(remaining_len, 16U);
572             if (op == sdp_aes_op_encrypt) {
573                 (void) memcpy(b, src, calc_len);
574                 if (calc_len < 16U) {
575                     (void) memset(&b[calc_len], 0, 16U - calc_len);
576                 }
577                 /* Calculate Y(i) = CIPHk(B(i) ^ Y(i-1)) */
578                 sdp_aes_crypt_cbc(base, aes_ctx, sdp_aes_op_encrypt, 16, b, y, y);
579             }
580             sdp_aes_crypt_ctr(base, aes_ctx, ctr, src, dst, calc_len);
581             if (op == sdp_aes_op_decrypt) {
582                 (void) memcpy(b, dst, calc_len);
583                 if (calc_len < 16U) {
584                     (void) memset(&b[calc_len], 0, 16U - calc_len);
585                 }
586                 /* Calculate Y(i) = CIPHk(B(i) ^ Y(i-1)) */
587                 sdp_aes_crypt_cbc(base, aes_ctx, sdp_aes_op_encrypt, 16, b, y, y);
588             }
589             src += calc_len;
590             dst += calc_len;
591             remaining_len -= calc_len;
592         }
593 
594         /* Get CTR0 */
595         aes_ccm_format_ctr0(ctr, iv, iv_len);
596         /* Get MAC */
597         sdp_aes_crypt_ctr(base, aes_ctx, ctr, y, b, 16);
598         /* Copy mac to the destination */
599         (void) memcpy(tag, b, tag_len);
600 
601         /* Wipe-out temporary data */
602         (void) memset(b, 0, 16U);
603         (void) memset(y, 0, 16);
604         (void) memset(ctr, 0, 16);
605 
606         status = status_success;
607 
608     } while (false);
609     return status;
610 }
611 
sdp_aes_ccm_generate_encrypt(SDP_Type * base,sdp_aes_ctx_t * aes_ctx,uint32_t input_len,const uint8_t * iv,uint32_t iv_len,const uint8_t * aad,uint32_t aad_len,const uint8_t * input,uint8_t * output,uint8_t * tag,uint32_t tag_len)612 hpm_stat_t sdp_aes_ccm_generate_encrypt(SDP_Type *base,
613                                         sdp_aes_ctx_t *aes_ctx,
614                                         uint32_t input_len,
615                                         const uint8_t *iv,
616                                         uint32_t iv_len,
617                                         const uint8_t *aad,
618                                         uint32_t aad_len,
619                                         const uint8_t *input,
620                                         uint8_t *output,
621                                         uint8_t *tag,
622                                         uint32_t tag_len)
623 {
624     return aes_ccm_auth_crypt(base,
625                               aes_ctx,
626                               sdp_aes_op_encrypt,
627                               input_len,
628                               iv,
629                               iv_len,
630                               aad,
631                               aad_len,
632                               input,
633                               output,
634                               tag,
635                               tag_len);
636 }
637 
sdp_constant_time_cmp(const void * dst,const void * src,uint32_t len)638 static uint8_t sdp_constant_time_cmp(const void *dst, const void *src, uint32_t len)
639 {
640     uint8_t result = 0U;
641 
642     const uint8_t *dst_8 = (const uint8_t *) dst;
643     const uint8_t *src_8 = (const uint8_t *) src;
644 
645     while (len-- > 0U) {
646         result |= *dst_8 ^ *src_8;
647         ++dst_8;
648         ++src_8;
649 
650     }
651     return result;
652 }
653 
sdp_aes_ccm_decrypt_verify(SDP_Type * base,sdp_aes_ctx_t * aes_ctx,uint32_t input_len,const uint8_t * iv,uint32_t iv_len,const uint8_t * aad,uint32_t aad_len,const uint8_t * input,uint8_t * output,const uint8_t * tag,uint32_t tag_len)654 hpm_stat_t sdp_aes_ccm_decrypt_verify(SDP_Type *base,
655                                       sdp_aes_ctx_t *aes_ctx,
656                                       uint32_t input_len,
657                                       const uint8_t *iv,
658                                       uint32_t iv_len,
659                                       const uint8_t *aad,
660                                       uint32_t aad_len,
661                                       const uint8_t *input,
662                                       uint8_t *output,
663                                       const uint8_t *tag,
664                                       uint32_t tag_len)
665 {
666     hpm_stat_t status;
667 
668     do {
669 
670         uint32_t calc_mac[4];
671 
672         status = aes_ccm_auth_crypt(base,
673                                     aes_ctx,
674                                     sdp_aes_op_decrypt,
675                                     input_len,
676                                     iv,
677                                     iv_len,
678                                     aad,
679                                     aad_len,
680                                     input,
681                                     output,
682                                     (uint8_t *) &calc_mac,
683                                     tag_len);
684         HPM_BREAK_IF(status != status_success);
685         if (sdp_constant_time_cmp(calc_mac, tag, tag_len) != 0U) {
686             status = status_sdp_error_invalid_mac;
687         } else {
688             status = status_success;
689         }
690 
691     } while (false);
692 
693     return status;
694 }
695 
sdp_hash_init(SDP_Type * base,sdp_hash_ctx_t * hash_ctx,sdp_hash_alg_t alg)696 hpm_stat_t sdp_hash_init(SDP_Type *base, sdp_hash_ctx_t *hash_ctx, sdp_hash_alg_t alg)
697 {
698     hpm_stat_t status = status_invalid_argument;
699     do {
700         if (IS_HPM_BITMASK_SET(base->SDPCR, SDP_SDPCR_HASDIS_MASK)) {
701             status = status_sdp_no_hash_support;
702             break;
703         }
704 
705         /* Initialize the SDP HASH context */
706         sdp_hash_internal_ctx_t *ctx_internal = (sdp_hash_internal_ctx_t *) &hash_ctx->internal;
707         (void) memset(ctx_internal, 0, sizeof(*ctx_internal));
708         ctx_internal->alg = alg;
709         ctx_internal->blk_size = 0;
710         ctx_internal->state = sdp_state_hash_init;
711         ctx_internal->full_msg_size = 0;
712 
713         status = status_success;
714 
715     } while (false);
716 
717     return status;
718 }
719 
sdp_hash_internal_engine_init(SDP_Type * base,sdp_hash_ctx_t * hash_ctx)720 static void sdp_hash_internal_engine_init(SDP_Type *base, sdp_hash_ctx_t *hash_ctx)
721 {
722     (void) base;
723     sdp_hash_internal_ctx_t *ctx_internal = (sdp_hash_internal_ctx_t *) &hash_ctx->internal;
724 
725     ctx_internal->hash_init = true;
726     ctx_internal->hash_finish = false;
727 }
728 
sdp_hash_internal_update(SDP_Type * base,sdp_hash_ctx_t * ctx,const uint8_t * msg,uint32_t msg_size)729 static hpm_stat_t sdp_hash_internal_update(SDP_Type *base, sdp_hash_ctx_t *ctx, const uint8_t *msg, uint32_t msg_size)
730 {
731     sdp_hash_internal_ctx_t *ctx_internal = (sdp_hash_internal_ctx_t *) &ctx->internal;
732     sdp_pkt_struct_t *pkt_desc = (sdp_pkt_struct_t *) &ctx->sdp_pkt;
733 
734     pkt_desc->next_cmd = NULL;
735     uint32_t pkt_ctrl = SDP_PKT_CTRL_DERSEMA_MASK;
736     if (ctx_internal->hash_init) {
737         pkt_ctrl |= SDP_PKT_CTRL_HASHINIT_MASK;
738         ctx_internal->hash_init = false;
739     }
740     if (ctx_internal->hash_finish) {
741         pkt_ctrl |= SDP_PKT_CTRL_HASHFINISH_MASK;
742         ctx_internal->hash_finish = false;
743     }
744 
745     base->SDPCR = SDP_SDPCR_HASHEN_MASK;
746 #if defined(SDP_REGISTER_DESCRIPTOR_COUNT) && SDP_REGISTER_DESCRIPTOR_COUNT
747     base->SDPCR |= HPM_BITSMASK(1, 8);
748     base->NPKTPTR = 0UL;
749     base->PKTCTL = pkt_ctrl;
750     base->PKTSRC = (uint32_t) msg;
751     base->PKTDST = (uint32_t) 0;
752     base->PKTBUF = msg_size;
753 #else
754     pkt_desc->pkt_ctrl.PKT_CTRL = pkt_ctrl;
755     pkt_desc->src_addr = (uint32_t) msg;
756     pkt_desc->dst_addr = 0;
757     pkt_desc->buf_size = msg_size;
758     pkt_desc->reserved[0] = 0;
759     pkt_desc->reserved[1] = 0;
760     pkt_desc->reserved[2] = 0;
761 #endif
762 
763     sdp_clear_error_status(base);
764     base->MODCTRL = SDP_MODCTRL_HASALG_SET(ctx_internal->alg);
765 #if defined(SDP_REGISTER_DESCRIPTOR_COUNT) && SDP_REGISTER_DESCRIPTOR_COUNT
766     base->CMDPTR = 0;
767 #else
768     base->CMDPTR = (uint32_t) pkt_desc;
769 #endif
770     base->PKTCNT = 1;
771 
772     hpm_stat_t status = sdp_wait_done(base);
773 
774     return status;
775 }
776 
sdp_hash_process_message(SDP_Type * base,sdp_hash_ctx_t * ctx,const uint8_t * msg,uint32_t msg_size)777 static hpm_stat_t sdp_hash_process_message(SDP_Type *base, sdp_hash_ctx_t *ctx, const uint8_t *msg, uint32_t msg_size)
778 {
779     hpm_stat_t status = status_invalid_argument;
780 
781     sdp_hash_internal_ctx_t *ctx_internal = (sdp_hash_internal_ctx_t *) &ctx->internal;
782     /* If there is partially filled internal buffer, fill it to full block */
783     if (ctx_internal->blk_size > 0U) {
784         uint32_t size_to_copy = HASH_BLOCK_SIZE - ctx_internal->blk_size;
785         (void) memcpy(&ctx_internal->block.bytes[ctx_internal->blk_size], msg, size_to_copy);
786         msg += size_to_copy;
787         msg_size -= size_to_copy;
788 
789         /* process the full internal block */
790         status = sdp_hash_internal_update(base, ctx, &ctx_internal->block.bytes[0], HASH_BLOCK_SIZE);
791         if (status != status_success) {
792             return status;
793         }
794     }
795 
796     /* Process all full blocks in message */
797     uint32_t full_blk_size = (msg_size >> 6) << 6;
798     if (full_blk_size > 0U) {
799         status = sdp_hash_internal_update(base, ctx, msg, full_blk_size);
800         if (status != status_success) {
801             return status;
802         }
803         msg += full_blk_size;
804         msg_size -= full_blk_size;
805     }
806 
807     (void) memcpy(&ctx_internal->block.bytes[0], msg, msg_size);
808     ctx_internal->blk_size = msg_size;
809 
810     return status;
811 }
812 
sdp_hash_update(SDP_Type * base,sdp_hash_ctx_t * hash_ctx,const uint8_t * data,uint32_t length)813 hpm_stat_t sdp_hash_update(SDP_Type *base, sdp_hash_ctx_t *hash_ctx, const uint8_t *data, uint32_t length)
814 {
815     assert((base != NULL) && (hash_ctx != NULL) && (data != NULL));
816     hpm_stat_t status = status_invalid_argument;
817     do {
818         if (length == 0) {
819             status = status_success;
820             break;
821         }
822 
823         sdp_hash_internal_ctx_t *ctx_internal = (sdp_hash_internal_ctx_t *) &hash_ctx->internal;
824         uint32_t block_size = HASH_BLOCK_SIZE;
825         ctx_internal->full_msg_size += length;
826         /* If the data is still less than HASH_BLOCK_SIZE, keep them only in the buffer */
827         if ((ctx_internal->blk_size + length) <= block_size) {
828             (void) memcpy(&ctx_internal->block.bytes[0] + ctx_internal->blk_size, data, length);
829             ctx_internal->blk_size += length;
830             status = status_success;
831             break;
832         } else {
833             if (ctx_internal->state != sdp_state_hash_update) {
834                 sdp_hash_internal_engine_init(base, hash_ctx);
835                 ctx_internal->state = sdp_state_hash_update;
836             }
837         }
838 
839         /* Process input data */
840         status = sdp_hash_process_message(base, hash_ctx, data, length);
841     } while (false);
842 
843     return status;
844 }
845 
sdp_hash_finalize(SDP_Type * base,sdp_hash_ctx_t * hash_ctx)846 static hpm_stat_t sdp_hash_finalize(SDP_Type *base, sdp_hash_ctx_t *hash_ctx)
847 {
848     sdp_hash_internal_ctx_t *ctx_internal = (sdp_hash_internal_ctx_t *) &hash_ctx->internal;
849     hpm_stat_t status;
850     ctx_internal->hash_finish = true;
851 
852     status = sdp_hash_internal_update(base, hash_ctx, &ctx_internal->block.bytes[0], ctx_internal->blk_size);
853 
854     return status;
855 }
856 
sdp_hash_finish(SDP_Type * base,sdp_hash_ctx_t * hash_ctx,uint8_t * digest)857 hpm_stat_t sdp_hash_finish(SDP_Type *base, sdp_hash_ctx_t *hash_ctx, uint8_t *digest)
858 {
859     assert((base != NULL) && (hash_ctx != NULL) && (digest != NULL));
860 
861     hpm_stat_t status = status_invalid_argument;
862     do {
863         sdp_hash_internal_ctx_t *ctx_internal = (sdp_hash_internal_ctx_t *) &hash_ctx->internal;
864         if (ctx_internal->state == sdp_state_hash_init) {
865             sdp_hash_internal_engine_init(base, hash_ctx);
866         }
867         status = sdp_hash_finalize(base, hash_ctx);
868         HPM_BREAK_IF(status != status_success);
869 
870         uint32_t copy_bytes = 0;
871         uint32_t digest_words = 0;
872         switch (ctx_internal->alg) {
873         case sdp_hash_alg_crc32:
874             copy_bytes = CRC32_DIGEST_SIZE_IN_BYTES;
875             ctx_internal->running_hash[0] = base->HASWRD[0];
876             break;
877         case sdp_hash_alg_sha1:
878             copy_bytes = SHA1_DIGEST_SIZE_IN_BYTES;
879             digest_words = copy_bytes / sizeof(uint32_t);
880             for (uint32_t i = 0; i < digest_words; i++) {
881                 ctx_internal->running_hash[i] = base->HASWRD[i];
882             }
883             break;
884         case sdp_hash_alg_sha256:
885 #if defined(SDP_HAS_SM3_SUPPORT) && (SDP_HAS_SM3_SUPPORT == 1)
886         case sdp_hash_alg_sm3:
887 #endif
888             copy_bytes = SHA256_DIGEST_SIZE_IN_BYTES;
889             digest_words = copy_bytes / sizeof(uint32_t);
890             for (uint32_t i = 0; i < digest_words; i++) {
891                 ctx_internal->running_hash[i] = base->HASWRD[i];
892             }
893             break;
894         default:
895             /* Never reach here */
896             break;
897         }
898         (void) memcpy(digest, ctx_internal->running_hash, copy_bytes);
899     } while (false);
900 
901     return status;
902 }
903 
sdp_memcpy(SDP_Type * base,sdp_dma_ctx_t * dma_ctx,void * dst,const void * src,uint32_t length)904 hpm_stat_t sdp_memcpy(SDP_Type *base, sdp_dma_ctx_t *dma_ctx, void *dst, const void *src, uint32_t length)
905 {
906     (void) dma_ctx;
907     hpm_stat_t status = status_invalid_argument;
908 
909     if (length == 0) {
910         status = status_success;
911         return status;
912     }
913 
914     base->SDPCR = SDP_SDPCR_MCPEN_MASK;
915 #if defined(SDP_REGISTER_DESCRIPTOR_COUNT) && SDP_REGISTER_DESCRIPTOR_COUNT
916     base->SDPCR |= HPM_BITSMASK(1, 8);
917     base->NPKTPTR = 0;
918     base->PKTCTL = SDP_PKT_CTRL_DERSEMA_MASK | SDP_PKTCTL_PKTTAG_SET(1);
919     base->PKTSRC = (uint32_t) src;
920     base->PKTDST = (uint32_t) dst;
921     base->PKTBUF = length;
922 #else
923     sdp_pkt_struct_t *pkt_desc = &dma_ctx->sdp_pkt;
924     pkt_desc->next_cmd = NULL;
925     pkt_desc->pkt_ctrl.PKT_CTRL = SDP_PKT_CTRL_DERSEMA_MASK;
926     pkt_desc->src_addr = (uint32_t) src;
927     pkt_desc->dst_addr = (uint32_t) dst;
928     pkt_desc->buf_size = length;
929 #endif
930 
931     sdp_clear_error_status(base);
932 
933     base->MODCTRL = 0;
934 #if defined(SDP_REGISTER_DESCRIPTOR_COUNT) && SDP_REGISTER_DESCRIPTOR_COUNT
935     base->CMDPTR = 0;
936 #else
937     base->CMDPTR = (uint32_t) pkt_desc;
938 #endif
939     base->PKTCNT = 1;
940 
941     status = sdp_wait_done(base);
942 
943     return status;
944 }
945 
sdp_memset(SDP_Type * base,sdp_dma_ctx_t * sdp_ctx,void * dst,uint8_t pattern,uint32_t length)946 hpm_stat_t sdp_memset(SDP_Type *base, sdp_dma_ctx_t *sdp_ctx, void *dst, uint8_t pattern, uint32_t length)
947 {
948     (void) sdp_ctx;
949     hpm_stat_t status;
950 
951     uint32_t
952     pattern_32 = (pattern) | ((uint32_t) pattern << 8) | ((uint32_t) pattern << 16) | ((uint32_t) pattern << 24);
953 
954     base->SDPCR = SDP_SDPCR_CONFEN_MASK;
955 #if defined(SDP_REGISTER_DESCRIPTOR_COUNT) && SDP_REGISTER_DESCRIPTOR_COUNT
956     base->SDPCR |= HPM_BITSMASK(1, 8);
957     base->PKTCTL = SDP_PKT_CTRL_DERSEMA_MASK;
958     base->PKTSRC = (uint32_t) pattern_32;
959     base->PKTDST = (uint32_t) dst;
960     base->PKTBUF = length;
961 #else
962     sdp_pkt_struct_t *pkt_desc = &sdp_ctx->sdp_pkt;
963     pkt_desc->next_cmd = NULL;
964     pkt_desc->pkt_ctrl.PKT_CTRL = SDP_PKT_CTRL_DERSEMA_MASK;
965     pkt_desc->src_addr = pattern_32;
966     pkt_desc->dst_addr = (uint32_t) dst;
967     pkt_desc->buf_size = length;
968 #endif
969 
970     sdp_clear_error_status(base);
971     base->MODCTRL = 0;
972 #if defined(SDP_REGISTER_DESCRIPTOR_COUNT) && SDP_REGISTER_DESCRIPTOR_COUNT
973     base->CMDPTR = 0;
974 #else
975     base->CMDPTR = (uint32_t) pkt_desc;
976 #endif
977     base->PKTCNT = 1;
978 
979     status = sdp_wait_done(base);
980 
981     return status;
982 }
983 
sdp_trigger_action(SDP_Type * base,const sdp_action_t * action,const sdp_pkt_struct_t * cmd_pkt)984 hpm_stat_t sdp_trigger_action(SDP_Type *base, const sdp_action_t *action, const sdp_pkt_struct_t *cmd_pkt)
985 {
986     hpm_stat_t status = status_invalid_argument;
987 
988     do {
989         if ((action == NULL) || (cmd_pkt == NULL) || (action->op == sdp_op_invalid)) {
990             break;
991         }
992 
993         bool has_cipher = false;
994         bool hash_hash = false;
995         uint32_t sdp_cr = action->op;
996         uint32_t sdp_mode_ctrl = 0;
997         switch (action->op) {
998         case sdp_op_cipher_only:
999             has_cipher = true;
1000             break;
1001         case sdp_op_hash_only:
1002             hash_hash = true;
1003             break;
1004         case sdp_op_cipher_hash:
1005             has_cipher = true;
1006             hash_hash = true;
1007             break;
1008         case sdp_op_copy_hash:
1009             hash_hash = true;
1010             break;
1011         default:
1012             break;
1013         }
1014 
1015         if (has_cipher) {
1016             sdp_mode_ctrl |= SDP_MODCTRL_AESDIR_SET(action->crypto_op) | SDP_MODCTRL_AESMOD_SET(action->crypto_mode) |
1017                              SDP_MODCTRL_AESKS_SET(action->key_index);
1018             uint32_t crypto_alg_idx = SDP_CRYPTO_ALG_IDX_AES128;
1019 #if defined(SDP_HAS_SM4_SUPPORT) && (SDP_HAS_SM4_SUPPORT == 1)
1020             if (action->crypto_alg == sdp_crypto_alg_sm4) {
1021                 crypto_alg_idx = SDP_CRYPTO_ALG_IDX_SM4;
1022             } else
1023 #endif
1024             {
1025                 if (action->key_bits == 256) {
1026                     crypto_alg_idx = SDP_CRYPTO_ALG_IDX_AES256;
1027                 }
1028             }
1029             sdp_mode_ctrl |= SDP_MODCTRL_AESALG_SET(crypto_alg_idx);
1030             sdp_mode_ctrl |= SDP_MODCTRL_KEYSWP_SET(action->key_swap_mode);
1031         }
1032         if (hash_hash) {
1033             sdp_mode_ctrl |= SDP_MODCTRL_HASALG_SET(action->hash_alg) | SDP_MODCTRL_HASCHK_SET(action->hash_check);
1034         }
1035         if (has_cipher && hash_hash) {
1036             sdp_mode_ctrl |= SDP_MODCTRL_HASOUT_SET(action->hash_mode);
1037         }
1038 
1039         sdp_mode_ctrl |= SDP_MODCTRL_DINSWP_SET(action->input_swap_mode);
1040         sdp_mode_ctrl |= SDP_MODCTRL_DOUTSWP_SET(action->output_swap_mode);
1041 
1042         base->SDPCR = (base->SDPCR & ~(SDP_SDPCR_CONFEN_MASK | SDP_SDPCR_HASHEN_MASK | SDP_SDPCR_CIPHEN_MASK |
1043                                        SDP_SDPCR_MCPEN_MASK)) | sdp_cr;
1044         base->MODCTRL = sdp_mode_ctrl;
1045 
1046         sdp_clear_status(HPM_SDP, ~0UL);
1047         base->CMDPTR = (uint32_t) cmd_pkt;
1048 
1049         /* Calculate the count of command packet in the command packet linked list */
1050         uint32_t pkt_cnt = 0;
1051         sdp_pkt_struct_t *pkt_list = (sdp_pkt_struct_t *) cmd_pkt;
1052         while (pkt_list != NULL) {
1053             if (pkt_list->pkt_ctrl.DCRSEMA != 0) {
1054                 ++pkt_cnt;
1055                 if (pkt_list->pkt_ctrl.CHAIN != 0) {
1056                     pkt_list = pkt_list->next_cmd;
1057                 } else {
1058                     break;
1059                 }
1060             } else {
1061                 break;
1062             }
1063         }
1064 #if defined(SDP_REGISTER_DESCRIPTOR_COUNT) && (SDP_REGISTER_DESCRIPTOR_COUNT == 1)
1065         if (pkt_cnt == 1) {
1066             base->SDPCR |= HPM_BITSMASK(1, 8);
1067             base->CMDPTR = 0;
1068             base->PKTCTL = cmd_pkt->pkt_ctrl.PKT_CTRL;
1069             base->PKTSRC = cmd_pkt->src_addr;
1070             base->PKTDST = cmd_pkt->dst_addr;
1071             base->PKTBUF = cmd_pkt->buf_size;
1072         }
1073 #endif
1074 
1075         base->PKTCNT = pkt_cnt; /* Start Action */
1076 
1077         status = status_success;
1078     } while (false);
1079 
1080     return status;
1081 }
1082