From 32ad12b43b1e21149dedcdb93332240cb7a2c163 Mon Sep 17 00:00:00 2001 From: Lionel Debieve <lionel.debieve@foss.st.com> Date: Thu, 19 May 2022 11:37:24 +0200 Subject: [PATCH] fix(stm32mp1): fix missing padding to verify signature ECDSA signatures can not guarantee the exact 32 bits that must be given to the hardware. We must check the ASN1 sequence and adapt the R,S tuple to manage a proper 2 * 32 bytes whatever the certificate content. Signed-off-by: Lionel Debieve <lionel.debieve@foss.st.com> Change-Id: I456c32aa1d081562c2787866894f3be3b6f8cb9d Reviewed-on: https://gerrit.st.com/c/mpu/oe/st/tf-a/+/252923 Reviewed-by: CITOOLS <MDG-smet-aci-reviews@list.st.com> --- plat/st/common/stm32mp_crypto_lib.c | 42 +++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/plat/st/common/stm32mp_crypto_lib.c b/plat/st/common/stm32mp_crypto_lib.c index 958216281..dbb1169de 100644 --- a/plat/st/common/stm32mp_crypto_lib.c +++ b/plat/st/common/stm32mp_crypto_lib.c @@ -288,11 +288,14 @@ static int crypto_verify_signature(void *data_ptr, unsigned int data_len, int ret; size_t len; mbedtls_asn1_sequence seq; + mbedtls_asn1_sequence *cur; unsigned char *p, *end; int curve_id; mbedtls_asn1_buf sig_oid, sig_params; mbedtls_md_type_t md_alg; mbedtls_pk_type_t pk_alg; + size_t bignum_len = sizeof(sig) / 2U; + unsigned int seq_num = 0U; /* Get pointers to signature OID and parameters */ p = (unsigned char *)sig_alg; @@ -350,7 +353,7 @@ static int crypto_verify_signature(void *data_ptr, unsigned int data_len, /* We expect only 2 integers (r and s) from the sequence */ if (seq.next->next != NULL) { - mbedtls_asn1_sequence *cur = seq.next; + cur = seq.next; mbedtls_asn1_sequence *next; VERBOSE("%s: nb seq != 2\n", __func__); @@ -364,14 +367,37 @@ static int crypto_verify_signature(void *data_ptr, unsigned int data_len, return CRYPTO_ERR_SIGNATURE; } - /* Integer sequence may (sometime) start with 0x00 as MSB, but we can only - * manage exactly 2*32 bytes, we remove this higher byte - * if there are not 00, we will fail either. + /* + * ECDSA signatures are composed of a tuple (R,S) where R and S are between 0 and n. + * This means that the R and S can have a maximum of 32 each, but can also be smaller. + * Also seen the integer sequence may (sometime) start with 0x00 as MSB, but we can only + * manage exactly 2*32 bytes, we remove this higher byte if there are not 00, + * we will fail either. */ - memcpy(sig, seq.buf.p + seq.buf.len - sizeof(sig) / 2U, sizeof(sig) / 2U); - memcpy(sig + sizeof(sig) / 2U, - seq.next->buf.p + seq.next->buf.len - sizeof(sig) / 2U, - sizeof(sig) / 2U); + cur = &seq; + memset(sig, 0U, sizeof(sig)); + + while (cur != NULL) { + size_t skip = 0U; + size_t seek = seq_num * bignum_len; + + if (cur->buf.len > bignum_len) { + /* Remove extra 0x00 bytes */ + skip = cur->buf.len - bignum_len; + } else if (cur->buf.len < bignum_len) { + /* Add padding to match HW required size */ + seek += (bignum_len % cur->buf.len); + } + + if (seek + cur->buf.len > sizeof(sig) + skip) { + panic(); + } + + memcpy(sig + seek, cur->buf.p + skip, cur->buf.len - skip); + cur = cur->next; + seq_num++; + } + /* Need to free allocated 'next' in mbedtls_asn1_get_sequence_of */ mbedtls_free(seq.next); -- GitLab