bootutil/crypto: Refactor the RSA signature verification and encryption

This patch refactor the RSA operations done by the signature verification
module and by the encrypted images decryption module. Previous solution is
tightly coupled with Mbed TLS, while this patch provides an abstraction of
the RSA functionalities in a dedicated crypto abstraction header, crypto/rsa.h
that supports both Mbed TLS APIs and PSA Crypto APIs. In case of PSA Crypto,
the verification scheme is directly provided by the crypto backend hence it
simplifies the operations done in the image verification module.

Signed-off-by: Antonio de Angelis <Antonio.deAngelis@arm.com>
Change-Id: I973bc3374b62eee2d7717c2368bce7611d37a0c8
diff --git a/boot/bootutil/src/image_rsa.c b/boot/bootutil/src/image_rsa.c
index 0e0782b..d3658fb 100644
--- a/boot/bootutil/src/image_rsa.c
+++ b/boot/bootutil/src/image_rsa.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2017-2018 Linaro LTD
  * Copyright (c) 2017-2019 JUUL Labs
- * Copyright (c) 2020-2021 Arm Limited
+ * Copyright (c) 2020-2023 Arm Limited
  *
  * Original license:
  *
@@ -30,20 +30,24 @@
 #include "mcuboot_config/mcuboot_config.h"
 
 #ifdef MCUBOOT_SIGN_RSA
-#include "bootutil/sign_key.h"
-#include "bootutil/crypto/sha256.h"
-#include "bootutil/crypto/common.h"
-
-#include "mbedtls/rsa.h"
-#include "mbedtls/asn1.h"
-#include "mbedtls/version.h"
-
 #include "bootutil_priv.h"
+#include "bootutil/sign_key.h"
 #include "bootutil/fault_injection_hardening.h"
 
+#define BOOTUTIL_CRYPTO_RSA_SIGN_ENABLED
+#include "bootutil/crypto/rsa.h"
+
+/* PSA Crypto APIs provide an integrated API to perform the verification
+ * while for other crypto backend we need to implement each step at this
+ * abstraction level
+ */
+#if !defined(MCUBOOT_USE_PSA_CRYPTO)
+
+#include "bootutil/crypto/sha256.h"
+
 /*
  * Constants for this particular constrained implementation of
- * RSA-PSS.  In particular, we support RSA 2048, with a SHA256 hash,
+ * RSA-PSS. In particular, we support RSA 2048, with a SHA256 hash,
  * and a 32-byte salt.  A signature with different parameters will be
  * rejected as invalid.
  */
@@ -72,54 +76,6 @@
 static const uint8_t pss_zeros[8] = {0};
 
 /*
- * Parse the public key used for signing. Simple RSA format.
- */
-static int
-bootutil_parse_rsakey(mbedtls_rsa_context *ctx, uint8_t **p, uint8_t *end)
-{
-    int rc;
-    size_t len;
-
-    if ((rc = mbedtls_asn1_get_tag(p, end, &len,
-          MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
-        return -1;
-    }
-
-    if (*p + len != end) {
-        return -2;
-    }
-
-    if ((rc = mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(N))) != 0 ||
-        (rc = mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(E))) != 0) {
-        return -3;
-    }
-
-    ctx->MBEDTLS_CONTEXT_MEMBER(len) = mbedtls_mpi_size(&ctx->MBEDTLS_CONTEXT_MEMBER(N));
-
-    if (*p != end) {
-        return -4;
-    }
-
-    /* The mbedtls version is more than 2.6.1 */
-#if MBEDTLS_VERSION_NUMBER > 0x02060100
-    rc = mbedtls_rsa_import(ctx, &ctx->MBEDTLS_CONTEXT_MEMBER(N), NULL,
-                            NULL, NULL, &ctx->MBEDTLS_CONTEXT_MEMBER(E));
-    if (rc != 0) {
-        return -5;
-    }
-#endif
-
-    rc = mbedtls_rsa_check_pubkey(ctx);
-    if (rc != 0) {
-        return -6;
-    }
-
-    ctx->MBEDTLS_CONTEXT_MEMBER(len) = mbedtls_mpi_size(&ctx->MBEDTLS_CONTEXT_MEMBER(N));
-
-    return 0;
-}
-
-/*
  * Compute the RSA-PSS mask-generation function, MGF1.  Assumptions
  * are that the mask length will be less than 256 * PSS_HLEN, and
  * therefore we never need to increment anything other than the low
@@ -159,11 +115,11 @@
 /*
  * Validate an RSA signature, using RSA-PSS, as described in PKCS #1
  * v2.2, section 9.1.2, with many parameters required to have fixed
- * values.
+ * values. RSASSA-PSS-VERIFY RFC8017 section 8.1.2
  */
 static fih_ret
-bootutil_cmp_rsasig(mbedtls_rsa_context *ctx, uint8_t *hash, uint32_t hlen,
-  uint8_t *sig)
+bootutil_cmp_rsasig(bootutil_rsa_context *ctx, uint8_t *hash, uint32_t hlen,
+  uint8_t *sig, size_t slen)
 {
     bootutil_sha256_context shactx;
     uint8_t em[MBEDTLS_MPI_MAX_SIZE];
@@ -172,7 +128,8 @@
     int i;
     FIH_DECLARE(fih_rc, FIH_FAILURE);
 
-    if (ctx->MBEDTLS_CONTEXT_MEMBER(len) != PSS_EMLEN ||
+    /* The caller has already verified that slen == bootutil_rsa_get_len(ctx) */
+    if (slen != PSS_EMLEN ||
         PSS_EMLEN > MBEDTLS_MPI_MAX_SIZE) {
         goto out;
     }
@@ -181,7 +138,8 @@
         goto out;
     }
 
-    if (mbedtls_rsa_public(ctx, sig, em)) {
+    /* Apply RSAVP1 to produce em = sig^E mod N using the public key */
+    if (bootutil_rsa_public(ctx, sig, em)) {
         goto out;
     }
 
@@ -278,34 +236,52 @@
     FIH_RET(fih_rc);
 }
 
+#else /* MCUBOOT_USE_PSA_CRYPTO */
+
+static fih_ret
+bootutil_cmp_rsasig(bootutil_rsa_context *ctx, uint8_t *hash, uint32_t hlen,
+  uint8_t *sig, size_t slen)
+{
+    int rc = -1;
+    FIH_DECLARE(fih_rc, FIH_FAILURE);
+
+    /* PSA Crypto APIs allow the verification in a single call */
+    rc = bootutil_rsassa_pss_verify(ctx, hash, hlen, sig, slen);
+
+    fih_rc = fih_ret_encode_zero_equality(rc);
+    if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
+        FIH_SET(fih_rc, FIH_FAILURE);
+    }
+
+    FIH_RET(fih_rc);
+}
+
+#endif /* MCUBOOT_USE_PSA_CRYPTO */
+
 fih_ret
 bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen,
   uint8_t key_id)
 {
-    mbedtls_rsa_context ctx;
+    bootutil_rsa_context ctx;
     int rc;
     FIH_DECLARE(fih_rc, FIH_FAILURE);
     uint8_t *cp;
     uint8_t *end;
 
-#if MBEDTLS_VERSION_NUMBER >= 0x03000000
-    mbedtls_rsa_init(&ctx);
-#else
-    mbedtls_rsa_init(&ctx, 0, 0);
-#endif
+    bootutil_rsa_init(&ctx);
 
     cp = (uint8_t *)bootutil_keys[key_id].key;
     end = cp + *bootutil_keys[key_id].len;
 
-    rc = bootutil_parse_rsakey(&ctx, &cp, end);
-    if (rc || slen != ctx.MBEDTLS_CONTEXT_MEMBER(len)) {
-        mbedtls_rsa_free(&ctx);
+    /* The key used for signature verification is a public RSA key */
+    rc = bootutil_rsa_parse_public_key(&ctx, &cp, end);
+    if (rc || slen != bootutil_rsa_get_len(&ctx)) {
         goto out;
     }
-    FIH_CALL(bootutil_cmp_rsasig, fih_rc, &ctx, hash, hlen, sig);
+    FIH_CALL(bootutil_cmp_rsasig, fih_rc, &ctx, hash, hlen, sig, slen);
 
 out:
-    mbedtls_rsa_free(&ctx);
+    bootutil_rsa_drop(&ctx);
 
     FIH_RET(fih_rc);
 }