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