Skip to content

Commit 6aa8470

Browse files
committed
drivers: crypto: stm32: h7: support AES CCM
Adds AES CCM support for: * H723XX * H725XX * H730XX, H730XXQ * H735XX Signed-off-by: Georgij Černyšiov <[email protected]>
1 parent 1667ea8 commit 6aa8470

File tree

1 file changed

+179
-0
lines changed

1 file changed

+179
-0
lines changed

drivers/crypto/crypto_stm32.c

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ typedef status_t (*hal_cryp_aes_op_func_t)(CRYP_HandleTypeDef *hcryp, uint8_t *i
9191
#ifdef STM32_CRYPTO_GCM_CCM_SUPPORTED
9292
#define hal_gcm_encrypt_op hal_encrypt
9393
#define hal_gcm_decrypt_op hal_decrypt
94+
#define hal_ccm_encrypt_op hal_encrypt
95+
#define hal_ccm_decrypt_op hal_decrypt
9496
#endif /* STM32_CRYPTO_GCM_CCM_SUPPORTED */
9597
#endif /* !DT_HAS_COMPAT_STATUS_OKAY(st_stm32l4_aes) */
9698

@@ -437,6 +439,175 @@ static int crypto_stm32_gcm_decrypt(struct cipher_ctx *ctx, struct cipher_aead_p
437439

438440
return ret;
439441
}
442+
443+
static int crypto_stm32_ccm(struct cipher_ctx *ctx, hal_cryp_aes_op_func_t fn,
444+
struct cipher_aead_pkt *apkt, uint8_t *nonce, uint8_t **b1)
445+
{
446+
struct crypto_stm32_session *const session = CRYPTO_STM32_SESSN(ctx);
447+
size_t b1_padded_len;
448+
uint8_t b0[BLOCK_LEN_BYTES] = {0};
449+
uint8_t q;
450+
int ret;
451+
452+
/* tag length: 4, 6, 8, 10, 12, 14, 16 */
453+
if ((ctx->mode_params.ccm_info.tag_len < 4) ||
454+
(ctx->mode_params.ccm_info.tag_len > 16) ||
455+
(ctx->mode_params.ccm_info.tag_len % 2) != 0) {
456+
return -EINVAL;
457+
}
458+
459+
/* nonce length [7, 13] */
460+
if ((ctx->mode_params.ccm_info.nonce_len < 7) ||
461+
(ctx->mode_params.ccm_info.nonce_len > 13)) {
462+
return -EINVAL;
463+
}
464+
465+
/* bytes left for payload length */
466+
q = (15 - ctx->mode_params.ccm_info.nonce_len);
467+
468+
/* check if payload length fits into q bytes */
469+
if (apkt->pkt->in_len > BIT_MASK(8U * q)) {
470+
return -EINVAL;
471+
}
472+
473+
if (apkt->ad_len == 0) {
474+
session->config.Header = NULL;
475+
session->config.HeaderSize = 0U;
476+
} else {
477+
uint8_t header_len;
478+
479+
if (apkt->ad_len < 0xFF00U) {
480+
header_len = 2;
481+
} else if (apkt->ad_len < 0xFFFFFFFFU) {
482+
header_len = 6;
483+
} else {
484+
return -ENOTSUP;
485+
}
486+
487+
b1_padded_len =
488+
(((apkt->ad_len + header_len) / BLOCK_LEN_BYTES) + 1) * BLOCK_LEN_BYTES;
489+
490+
*b1 = k_calloc(1, b1_padded_len);
491+
if (*b1 == NULL) {
492+
return -ENOMEM;
493+
}
494+
495+
if (header_len == 2) {
496+
sys_put_be16(apkt->ad_len, *b1);
497+
} else {
498+
*b1[0] = 0xFFU;
499+
*b1[1] = 0xFEU;
500+
sys_put_be32(apkt->ad_len, *b1 + 2);
501+
}
502+
503+
memcpy(*b1 + header_len, apkt->ad, apkt->ad_len);
504+
505+
/* blocks (B) associated to the Associated Data (A) */
506+
session->config.Header = CAST_VEC(*b1);
507+
session->config.HeaderSize = b1_padded_len / sizeof(uint32_t);
508+
session->config.HeaderWidthUnit = CRYP_HEADERWIDTHUNIT_WORD;
509+
510+
/* set AD presence flag */
511+
b0[0] = BIT(6);
512+
}
513+
514+
/* encode leftover flags */
515+
b0[0] |= ((ctx->mode_params.gcm_info.tag_len - 2) / 2) << 3;
516+
b0[0] |= q - 1;
517+
518+
/* encode nonce */
519+
memcpy(&b0[1], nonce, ctx->mode_params.ccm_info.nonce_len);
520+
521+
/* encode payload length */
522+
for (unsigned int i = 0; i < q; i++) {
523+
b0[15 - i] = (uint8_t)((apkt->pkt->in_len >> (8U * i)) & 0xFFU);
524+
}
525+
526+
/* set B0 */
527+
for (unsigned int i = 0; i < sizeof(b0); i += sizeof(uint32_t)) {
528+
sys_mem_swap(&b0[i], sizeof(uint32_t));
529+
}
530+
531+
session->config.B0 = CAST_VEC(b0);
532+
533+
ret = do_aes(ctx, fn, apkt->pkt->in_buf, apkt->pkt->in_len, apkt->pkt->out_buf);
534+
if (ret < 0) {
535+
k_free(*b1);
536+
*b1 = NULL;
537+
}
538+
539+
return ret;
540+
}
541+
542+
static int crypto_stm32_ccm_encrypt(struct cipher_ctx *ctx, struct cipher_aead_pkt *apkt,
543+
uint8_t *nonce)
544+
{
545+
struct crypto_stm32_data *const data = CRYPTO_STM32_DATA(ctx->device);
546+
uint8_t *b1 = NULL;
547+
int ret;
548+
549+
k_sem_take(&data->device_sem, K_FOREVER);
550+
551+
ret = crypto_stm32_ccm(ctx, hal_ccm_encrypt_op, apkt, nonce, &b1);
552+
if (ret < 0) {
553+
/* crypto_stm32_ccm deallocates b1 upon error */
554+
k_sem_give(&data->device_sem);
555+
return ret;
556+
}
557+
558+
if (HAL_CRYPEx_AESCCM_GenerateAuthTAG(&data->hcryp, CAST_VEC(apkt->tag),
559+
HAL_MAX_DELAY) != HAL_OK) {
560+
ret = -EIO;
561+
}
562+
563+
k_sem_give(&data->device_sem);
564+
565+
k_free(b1);
566+
567+
if (ret < 0) {
568+
apkt->pkt->out_len = 0;
569+
} else {
570+
apkt->pkt->out_len = apkt->pkt->in_len;
571+
}
572+
573+
return ret;
574+
}
575+
576+
static int crypto_stm32_ccm_decrypt(struct cipher_ctx *ctx, struct cipher_aead_pkt *apkt,
577+
uint8_t *nonce)
578+
{
579+
struct crypto_stm32_data *const data = CRYPTO_STM32_DATA(ctx->device);
580+
uint8_t *b1 = NULL;
581+
uint32_t tag[BLOCK_LEN_WORDS] = {0};
582+
int ret;
583+
584+
k_sem_take(&data->device_sem, K_FOREVER);
585+
586+
ret = crypto_stm32_ccm(ctx, hal_ccm_decrypt_op, apkt, nonce, &b1);
587+
if (ret < 0) {
588+
k_sem_give(&data->device_sem);
589+
return ret;
590+
}
591+
592+
if (HAL_CRYPEx_AESCCM_GenerateAuthTAG(&data->hcryp, CAST_VEC(tag), HAL_MAX_DELAY) !=
593+
HAL_OK) {
594+
ret = -EIO;
595+
}
596+
597+
k_sem_give(&data->device_sem);
598+
599+
k_free(b1);
600+
601+
if (memcmp(tag, apkt->tag, ctx->mode_params.ccm_info.tag_len) != 0) {
602+
/* auth/tag verification fails */
603+
apkt->pkt->out_len = 0;
604+
ret = -EFAULT;
605+
} else {
606+
apkt->pkt->out_len = apkt->pkt->in_len;
607+
}
608+
609+
return ret;
610+
}
440611
#endif /* STM32_CRYPTO_GCM_CCM_SUPPORTED */
441612

442613
static int crypto_stm32_get_unused_session_index(const struct device *dev)
@@ -558,6 +729,10 @@ static int crypto_stm32_session_setup(const struct device *dev,
558729
session->config.Algorithm = CRYP_AES_GCM;
559730
ctx->ops.gcm_crypt_hndlr = crypto_stm32_gcm_encrypt;
560731
break;
732+
case CRYPTO_CIPHER_MODE_CCM:
733+
session->config.Algorithm = CRYP_AES_CCM;
734+
ctx->ops.ccm_crypt_hndlr = crypto_stm32_ccm_encrypt;
735+
break;
561736
#endif /* STM32_CRYPTO_GCM_CCM_SUPPORTED */
562737
default:
563738
return -EINVAL;
@@ -587,6 +762,10 @@ static int crypto_stm32_session_setup(const struct device *dev,
587762
session->config.Algorithm = CRYP_AES_GCM;
588763
ctx->ops.gcm_crypt_hndlr = crypto_stm32_gcm_decrypt;
589764
break;
765+
case CRYPTO_CIPHER_MODE_CCM:
766+
session->config.Algorithm = CRYP_AES_CCM;
767+
ctx->ops.ccm_crypt_hndlr = crypto_stm32_ccm_decrypt;
768+
break;
590769
#endif /* STM32_CRYPTO_GCM_CCM_SUPPORTED */
591770
default:
592771
return -EINVAL;

0 commit comments

Comments
 (0)