pk_wrap: use PSA util functions for ECDSA conversion instead of PK ones
Signed-off-by: Valerio Setti <valerio.setti@nordicsemi.no>
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index c232650..9a29d92 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -29,6 +29,7 @@
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa_util_internal.h"
#include "psa/crypto.h"
+#include "mbedtls/psa_util.h"
#if defined(MBEDTLS_RSA_C)
#include "pkwrite.h"
@@ -536,66 +537,6 @@
#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY)
#if defined(MBEDTLS_USE_PSA_CRYPTO)
-/*
- * An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of
- * those integers and convert it to the fixed-length encoding expected by PSA.
- */
-static int extract_ecdsa_sig_int(unsigned char **from, const unsigned char *end,
- unsigned char *to, size_t to_len)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t unpadded_len, padding_len;
-
- if ((ret = mbedtls_asn1_get_tag(from, end, &unpadded_len,
- MBEDTLS_ASN1_INTEGER)) != 0) {
- return ret;
- }
-
- while (unpadded_len > 0 && **from == 0x00) {
- (*from)++;
- unpadded_len--;
- }
-
- if (unpadded_len > to_len || unpadded_len == 0) {
- return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
- }
-
- padding_len = to_len - unpadded_len;
- memset(to, 0x00, padding_len);
- memcpy(to + padding_len, *from, unpadded_len);
- (*from) += unpadded_len;
-
- return 0;
-}
-
-/*
- * Convert a signature from an ASN.1 sequence of two integers
- * to a raw {r,s} buffer. Note: the provided sig buffer must be at least
- * twice as big as int_size.
- */
-static int extract_ecdsa_sig(unsigned char **p, const unsigned char *end,
- unsigned char *sig, size_t int_size)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t tmp_size;
-
- if ((ret = mbedtls_asn1_get_tag(p, end, &tmp_size,
- MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
- return ret;
- }
-
- /* Extract r */
- if ((ret = extract_ecdsa_sig_int(p, end, sig, int_size)) != 0) {
- return ret;
- }
- /* Extract s */
- if ((ret = extract_ecdsa_sig_int(p, end, sig + int_size, int_size)) != 0) {
- return ret;
- }
-
- return 0;
-}
-
/* Common helper for ECDSA verify using PSA functions. */
static int ecdsa_verify_psa(unsigned char *key, size_t key_len,
psa_ecc_family_t curve, size_t curve_bits,
@@ -607,6 +548,7 @@
mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY;
size_t signature_len = PSA_ECDSA_SIGNATURE_SIZE(curve_bits);
+ size_t converted_sig_len;
unsigned char extracted_sig[PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE];
unsigned char *p;
psa_status_t status;
@@ -631,11 +573,15 @@
}
p = (unsigned char *) sig;
- /* extract_ecdsa_sig's last parameter is the size
- * of each integer to be parsed, so it's actually half
- * the size of the signature. */
- if ((ret = extract_ecdsa_sig(&p, sig + sig_len, extracted_sig,
- signature_len/2)) != 0) {
+ ret = mbedtls_ecdsa_der_to_raw(p, sig_len, extracted_sig,
+ sizeof(extracted_sig), &converted_sig_len,
+ curve_bits);
+ if (ret != 0) {
+ goto cleanup;
+ }
+
+ if (converted_sig_len != signature_len) {
+ ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;
goto cleanup;
}
@@ -646,10 +592,6 @@
goto cleanup;
}
- if (p != sig + sig_len) {
- ret = MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
- goto cleanup;
- }
ret = 0;
cleanup:
@@ -751,90 +693,6 @@
#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
#if defined(MBEDTLS_USE_PSA_CRYPTO)
-/*
- * Simultaneously convert and move raw MPI from the beginning of a buffer
- * to an ASN.1 MPI at the end of the buffer.
- * See also mbedtls_asn1_write_mpi().
- *
- * p: pointer to the end of the output buffer
- * start: start of the output buffer, and also of the mpi to write at the end
- * n_len: length of the mpi to read from start
- */
-static int asn1_write_mpibuf(unsigned char **p, unsigned char *start,
- size_t n_len)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t len = 0;
-
- if ((size_t) (*p - start) < n_len) {
- return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
- }
-
- len = n_len;
- *p -= len;
- memmove(*p, start, len);
-
- /* ASN.1 DER encoding requires minimal length, so skip leading 0s.
- * Neither r nor s should be 0, but as a failsafe measure, still detect
- * that rather than overflowing the buffer in case of a PSA error. */
- while (len > 0 && **p == 0x00) {
- ++(*p);
- --len;
- }
-
- /* this is only reached if the signature was invalid */
- if (len == 0) {
- return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
- }
-
- /* if the msb is 1, ASN.1 requires that we prepend a 0.
- * Neither r nor s can be 0, so we can assume len > 0 at all times. */
- if (**p & 0x80) {
- if (*p - start < 1) {
- return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
- }
-
- *--(*p) = 0x00;
- len += 1;
- }
-
- MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
- MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,
- MBEDTLS_ASN1_INTEGER));
-
- return (int) len;
-}
-
-/* Transcode signature from PSA format to ASN.1 sequence.
- * See ecdsa_signature_to_asn1 in ecdsa.c, but with byte buffers instead of
- * MPIs, and in-place.
- *
- * [in/out] sig: the signature pre- and post-transcoding
- * [in/out] sig_len: signature length pre- and post-transcoding
- * [int] buf_len: the available size the in/out buffer
- */
-static int pk_ecdsa_sig_asn1_from_psa(unsigned char *sig, size_t *sig_len,
- size_t buf_len)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t len = 0;
- const size_t rs_len = *sig_len / 2;
- unsigned char *p = sig + buf_len;
-
- MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig + rs_len, rs_len));
- MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig, rs_len));
-
- MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, sig, len));
- MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, sig,
- MBEDTLS_ASN1_CONSTRUCTED |
- MBEDTLS_ASN1_SEQUENCE));
-
- memmove(sig, p, len);
- *sig_len = len;
-
- return 0;
-}
-
/* Common helper for ECDSA sign using PSA functions.
* Instead of extracting key's properties in order to check which kind of ECDSA
* signature it supports, we try both deterministic and non-deterministic.
@@ -845,6 +703,15 @@
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
psa_status_t status;
+ psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
+ size_t key_bits = 0;
+
+ status = psa_get_key_attributes(key_id, &key_attr);
+ if (status != PSA_SUCCESS) {
+ return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
+ }
+ key_bits = psa_get_key_bits(&key_attr);
+ psa_reset_key_attributes(&key_attr);
status = psa_sign_hash(key_id,
PSA_ALG_DETERMINISTIC_ECDSA(mbedtls_md_psa_alg_from_type(md_alg)),
@@ -863,7 +730,7 @@
}
done:
- ret = pk_ecdsa_sig_asn1_from_psa(sig, sig_len, sig_size);
+ ret = mbedtls_ecdsa_raw_to_der(sig, sig_size, sig, sig_size, sig_len, key_bits);
return ret;
}