From: Rupesh Chiluka <[email protected]> cn10k_tls_record_session_update() and cn20k_tls_record_session_update() forwarded the crypto_xform to tls_write_sa_fill() without running cnxk_tls_xform_verify(), unlike the create path.
Separately, the AEAD key-length guard in the SA fill routines used a single 16/32 check that incorrectly accepted a 16-byte ChaCha20-Poly1305 key (ChaCha requires 32), and both the AEAD and the read-side cipher paths copied key.data without a NULL check, so a malformed xform could crash in memcpy(). - Call cnxk_tls_xform_verify() on the update path. - Make the AEAD key-length validation algorithm-specific (AES-GCM 16/32, ChaCha20-Poly1305 32, reject others). - Reject NULL key pointers before the memcpy on both the AEAD and cipher paths, for cn10k and cn20k. Signed-off-by: Rupesh Chiluka <[email protected]> --- drivers/crypto/cnxk/cn10k_tls.c | 33 +++++++++++++++++++++---- drivers/crypto/cnxk/cn20k_tls.c | 44 +++++++++++++++++++++++++-------- 2 files changed, 62 insertions(+), 15 deletions(-) diff --git a/drivers/crypto/cnxk/cn10k_tls.c b/drivers/crypto/cnxk/cn10k_tls.c index 1a7b87e400..8aa6d5ad4b 100644 --- a/drivers/crypto/cnxk/cn10k_tls.c +++ b/drivers/crypto/cnxk/cn10k_tls.c @@ -358,19 +358,25 @@ tls_read_sa_fill(struct roc_ie_ot_tls_read_sa *read_sa, if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) { length = crypto_xfrm->aead.key.length; if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_AES_GCM) { + if (length != 16 && length != 32) + return -EINVAL; read_sa->w2.s.cipher_select = ROC_IE_OT_TLS_CIPHER_AES_GCM; if (length == 16) read_sa->w2.s.aes_key_len = ROC_IE_OT_TLS_AES_KEY_LEN_128; else read_sa->w2.s.aes_key_len = ROC_IE_OT_TLS_AES_KEY_LEN_256; - } - - if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) { + } else if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) { + if (length != 32) + return -EINVAL; read_sa->w2.s.cipher_select = ROC_IE_OT_TLS_CIPHER_CHACHA_POLY; read_sa->w2.s.aes_key_len = ROC_IE_OT_TLS_AES_KEY_LEN_256; + } else { + return -EINVAL; } key = crypto_xfrm->aead.key.data; + if (key == NULL) + return -EINVAL; memcpy(cipher_key, key, length); if (tls_ver == RTE_SECURITY_VERSION_TLS_1_2) @@ -395,6 +401,8 @@ tls_read_sa_fill(struct roc_ie_ot_tls_read_sa *read_sa, if (cipher_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_3DES_CBC) { read_sa->w2.s.cipher_select = ROC_IE_OT_TLS_CIPHER_3DES; length = cipher_xfrm->cipher.key.length; + if (length != 24) + return -EINVAL; } else if (cipher_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_AES_CBC) { read_sa->w2.s.cipher_select = ROC_IE_OT_TLS_CIPHER_AES_CBC; length = cipher_xfrm->cipher.key.length; @@ -409,6 +417,8 @@ tls_read_sa_fill(struct roc_ie_ot_tls_read_sa *read_sa, } key = cipher_xfrm->cipher.key.data; + if (key == NULL || length == 0) + return -EINVAL; memcpy(cipher_key, key, length); } @@ -515,18 +525,25 @@ tls_write_sa_fill(struct roc_ie_ot_tls_write_sa *write_sa, if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) { length = crypto_xfrm->aead.key.length; if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_AES_GCM) { + if (length != 16 && length != 32) + return -EINVAL; write_sa->w2.s.cipher_select = ROC_IE_OT_TLS_CIPHER_AES_GCM; if (length == 16) write_sa->w2.s.aes_key_len = ROC_IE_OT_TLS_AES_KEY_LEN_128; else write_sa->w2.s.aes_key_len = ROC_IE_OT_TLS_AES_KEY_LEN_256; - } - if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) { + } else if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) { + if (length != 32) + return -EINVAL; write_sa->w2.s.cipher_select = ROC_IE_OT_TLS_CIPHER_CHACHA_POLY; write_sa->w2.s.aes_key_len = ROC_IE_OT_TLS_AES_KEY_LEN_256; + } else { + return -EINVAL; } key = crypto_xfrm->aead.key.data; + if (key == NULL) + return -EINVAL; memcpy(cipher_key, key, length); if (tls_ver == RTE_SECURITY_VERSION_TLS_1_2) @@ -551,6 +568,8 @@ tls_write_sa_fill(struct roc_ie_ot_tls_write_sa *write_sa, if (cipher_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_3DES_CBC) { write_sa->w2.s.cipher_select = ROC_IE_OT_TLS_CIPHER_3DES; length = cipher_xfrm->cipher.key.length; + if (length != 24) + return -EINVAL; } else if (cipher_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_AES_CBC) { write_sa->w2.s.cipher_select = ROC_IE_OT_TLS_CIPHER_AES_CBC; length = cipher_xfrm->cipher.key.length; @@ -833,6 +852,10 @@ cn10k_tls_record_session_update(struct cnxk_cpt_vf *vf, struct cnxk_cpt_qp *qp, if (conf->tls_record.type == RTE_SECURITY_TLS_SESS_TYPE_READ) return -ENOTSUP; + ret = cnxk_tls_xform_verify(&conf->tls_record, conf->crypto_xform); + if (ret) + return ret; + roc_cpt = &vf->cpt; ret = cn10k_tls_write_sa_create(roc_cpt, &qp->lf, &conf->tls_record, conf->crypto_xform, (struct cn10k_sec_session *)sess); diff --git a/drivers/crypto/cnxk/cn20k_tls.c b/drivers/crypto/cnxk/cn20k_tls.c index 882d193c25..ac6f6d9c4b 100644 --- a/drivers/crypto/cnxk/cn20k_tls.c +++ b/drivers/crypto/cnxk/cn20k_tls.c @@ -249,19 +249,25 @@ tls_read_sa_fill(struct roc_ie_ow_tls_read_sa *read_sa, if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) { length = crypto_xfrm->aead.key.length; if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_AES_GCM) { + if (length != 16 && length != 32) + return -EINVAL; read_sa->w2.s.cipher_select = ROC_IE_OW_TLS_CIPHER_AES_GCM; if (length == 16) read_sa->w2.s.aes_key_len = ROC_IE_OW_TLS_AES_KEY_LEN_128; else read_sa->w2.s.aes_key_len = ROC_IE_OW_TLS_AES_KEY_LEN_256; - } - - if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) { + } else if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) { + if (length != 32) + return -EINVAL; read_sa->w2.s.cipher_select = ROC_IE_OW_TLS_CIPHER_CHACHA_POLY; read_sa->w2.s.aes_key_len = ROC_IE_OW_TLS_AES_KEY_LEN_256; + } else { + return -EINVAL; } key = crypto_xfrm->aead.key.data; + if (key == NULL) + return -EINVAL; memcpy(cipher_key, key, length); if (tls_ver == RTE_SECURITY_VERSION_TLS_1_2) @@ -286,6 +292,8 @@ tls_read_sa_fill(struct roc_ie_ow_tls_read_sa *read_sa, if (cipher_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_3DES_CBC) { read_sa->w2.s.cipher_select = ROC_IE_OW_TLS_CIPHER_3DES; length = cipher_xfrm->cipher.key.length; + if (length != 24) + return -EINVAL; } else if (cipher_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_AES_CBC) { read_sa->w2.s.cipher_select = ROC_IE_OW_TLS_CIPHER_AES_CBC; length = cipher_xfrm->cipher.key.length; @@ -300,6 +308,8 @@ tls_read_sa_fill(struct roc_ie_ow_tls_read_sa *read_sa, } key = cipher_xfrm->cipher.key.data; + if (key == NULL || length == 0) + return -EINVAL; memcpy(cipher_key, key, length); } @@ -576,18 +586,25 @@ tls_write_sa_fill(struct roc_ie_ow_tls_write_sa *write_sa, if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) { length = crypto_xfrm->aead.key.length; if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_AES_GCM) { + if (length != 16 && length != 32) + return -EINVAL; write_sa->w2.s.cipher_select = ROC_IE_OW_TLS_CIPHER_AES_GCM; if (length == 16) write_sa->w2.s.aes_key_len = ROC_IE_OW_TLS_AES_KEY_LEN_128; else write_sa->w2.s.aes_key_len = ROC_IE_OW_TLS_AES_KEY_LEN_256; - } - if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) { + } else if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) { + if (length != 32) + return -EINVAL; write_sa->w2.s.cipher_select = ROC_IE_OW_TLS_CIPHER_CHACHA_POLY; write_sa->w2.s.aes_key_len = ROC_IE_OW_TLS_AES_KEY_LEN_256; + } else { + return -EINVAL; } key = crypto_xfrm->aead.key.data; + if (key == NULL) + return -EINVAL; memcpy(cipher_key, key, length); if (tls_ver == RTE_SECURITY_VERSION_TLS_1_2) @@ -612,6 +629,8 @@ tls_write_sa_fill(struct roc_ie_ow_tls_write_sa *write_sa, if (cipher_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_3DES_CBC) { write_sa->w2.s.cipher_select = ROC_IE_OW_TLS_CIPHER_3DES; length = cipher_xfrm->cipher.key.length; + if (length != 24) + return -EINVAL; } else if (cipher_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_AES_CBC) { write_sa->w2.s.cipher_select = ROC_IE_OW_TLS_CIPHER_AES_CBC; length = cipher_xfrm->cipher.key.length; @@ -626,10 +645,9 @@ tls_write_sa_fill(struct roc_ie_ow_tls_write_sa *write_sa, } key = cipher_xfrm->cipher.key.data; - if (key != NULL && length != 0) { - /* Copy encryption key */ - memcpy(cipher_key, key, length); - } + if (key == NULL) + return -EINVAL; + memcpy(cipher_key, key, length); } if (auth_xfrm != NULL) { @@ -716,7 +734,6 @@ cn20k_tls_write_sa_create(struct roc_cpt *roc_cpt, struct roc_cpt_lf *lf, plt_err("Couldn't allocate memory for WRITE SA"); return -ENOMEM; } - tls->write_sa = write_sa; /* Allocate memory to be used as dptr for CPT ucode WRITE_SA op */ sa_dptr = plt_zmalloc(sizeof(struct roc_ie_ow_tls_write_sa), 8); @@ -782,6 +799,9 @@ cn20k_tls_write_sa_create(struct roc_cpt *roc_cpt, struct roc_cpt_lf *lf, rte_atomic_thread_fence(rte_memory_order_seq_cst); + if (tls->write_sa != NULL) + rte_free(tls->write_sa); + tls->write_sa = write_sa; sa_dptr_free: plt_free(sa_dptr); sa_cptr_free: @@ -834,6 +854,10 @@ cn20k_tls_record_session_update(struct cnxk_cpt_vf *vf, struct cnxk_cpt_qp *qp, if (conf->tls_record.type == RTE_SECURITY_TLS_SESS_TYPE_READ) return -ENOTSUP; + ret = cnxk_tls_xform_verify(&conf->tls_record, conf->crypto_xform); + if (ret) + return ret; + roc_cpt = &vf->cpt; ret = cn20k_tls_write_sa_create(roc_cpt, &qp->lf, &conf->tls_record, conf->crypto_xform, (struct cn20k_sec_session *)sess); -- 2.43.0

