Commit 02bf072d authored by Antonio de Angelis's avatar Antonio de Angelis Committed by Dávid Vincze
Browse files

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: default avatarAntonio de Angelis <Antonio.deAngelis@arm.com>
Change-Id: I973bc3374b62eee2d7717c2368bce7611d37a0c8
parent ba5fb1ce
Loading
Loading
Loading
Loading
+356 −0
Original line number Diff line number Diff line
/*
 * SPDX-License-Identifier: Apache-2.0
 *
 * Copyright (c) 2023 Arm Limited
 */

/*
 * This module provides a thin abstraction over some of the crypto
 * primitives to make it easier to swap out the used crypto library.
 *
 * At this point, the choices are: MCUBOOT_USE_MBED_TLS and
 * MCUBOOT_USE_PSA_CRYPTO. Note that support for  MCUBOOT_USE_PSA_CRYPTO is
 * still experimental and it might not support all the crypto abstractions
 * that MCUBOOT_USE_MBED_TLS supports. For this reason, it's allowed to have
 * both of them defined, and for crypto modules that support both abstractions,
 * the MCUBOOT_USE_PSA_CRYPTO will take precedence.
 */

/*
 * Note: The source file that includes this header should either define one of the
 * two options BOOTUTIL_CRYPTO_RSA_CRYPT_ENABLED or BOOTUTIL_CRYPTO_RSA_SIGN_ENABLED
 * This will make the signature functions or encryption functions visible without
 * generating a "defined but not used" compiler warning
 */

#ifndef __BOOTUTIL_CRYPTO_RSA_H_
#define __BOOTUTIL_CRYPTO_RSA_H_

#include "mcuboot_config/mcuboot_config.h"

#if defined(MCUBOOT_USE_PSA_CRYPTO) || defined(MCUBOOT_USE_MBED_TLS)
#define MCUBOOT_USE_PSA_OR_MBED_TLS
#endif /* MCUBOOT_USE_PSA_CRYPTO || MCUBOOT_USE_MBED_TLS */

#if (defined(MCUBOOT_USE_PSA_OR_MBED_TLS)) != 1
    #error "One crypto backend must be defined: either MBED_TLS/PSA_CRYPTO"
#endif

#if defined(MCUBOOT_USE_PSA_CRYPTO)

#include <psa/crypto.h>
#include "bootutil/enc_key_public.h"

#elif defined(MCUBOOT_USE_MBED_TLS)

#include "mbedtls/rsa.h"
#include "mbedtls/version.h"
#if defined(BOOTUTIL_CRYPTO_RSA_CRYPT_ENABLED)
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
#include "rsa_alt_helpers.h"
#else
#include "mbedtls/rsa_internal.h"
#endif
#endif /* BOOTUTIL_CRYPTO_RSA_CRYPT_ENABLED */
#include "mbedtls/asn1.h"
#include "bootutil/crypto/common.h"

#endif /* MCUBOOT_USE_MBED_TLS */

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

#if defined(MCUBOOT_USE_PSA_CRYPTO)

typedef struct {
    psa_key_id_t key_id;
} bootutil_rsa_context;

static inline void bootutil_rsa_init(bootutil_rsa_context *ctx)
{
    ctx->key_id = PSA_KEY_ID_NULL;
}

static inline void bootutil_rsa_drop(bootutil_rsa_context *ctx)
{
    if (ctx->key_id != PSA_KEY_ID_NULL) {
        (void)psa_destroy_key(ctx->key_id);
    }
}

#if defined(BOOTUTIL_CRYPTO_RSA_CRYPT_ENABLED)
static int bootutil_rsa_oaep_decrypt(
    bootutil_rsa_context *ctx,
    size_t *olen,
    const uint8_t *input,
    uint8_t *output,
    size_t output_max_len)
{
    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;

    /* Perform an additional defensive check to compare the modulus of the RSA
     * key to the expected input to the decryption function, i.e. TLV_ENC_RSA_SZ
     */
    psa_key_attributes_t key_attr =  psa_key_attributes_init();
    status = psa_get_key_attributes(ctx->key_id, &key_attr);
    if (status != PSA_SUCCESS) {
        return -1;
    }
    size_t input_size = PSA_BITS_TO_BYTES(psa_get_key_bits(&key_attr));
    if (input_size != TLV_ENC_RSA_SZ) {
        return -1;
    }

    status = psa_asymmetric_decrypt(ctx->key_id, PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256),
                                    input, TLV_ENC_RSA_SZ, NULL, 0,
                                    output, output_max_len, olen);
    return (int)status;
}

/*
 * Parse a RSA private key with format specified in RFC3447 A.1.2
 *
 * The key is meant to be used for OAEP decrypt hence algorithm and usage are hardcoded
 */
static int
bootutil_rsa_parse_private_key(bootutil_rsa_context *ctx, uint8_t **p, uint8_t *end)
{
    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
    psa_key_attributes_t key_attributes = psa_key_attributes_init();

    /* Set attributes and import key */
    psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DECRYPT);
    psa_set_key_algorithm(&key_attributes, PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256));
    psa_set_key_type(&key_attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);

    status = psa_import_key(&key_attributes, *p, (end - *p), &ctx->key_id);
    return (int)status;
}

#endif /* BOOTUTIL_CRYPTO_RSA_CRYPT_ENABLED */

#if defined(BOOTUTIL_CRYPTO_RSA_SIGN_ENABLED)
/*
 * Parse a RSA public key with format specified in RFC3447 A.1.1
 *
 * The key is meant to be used for PSS signature verification hence algorithm and usage are hardcoded
 */
static int
bootutil_rsa_parse_public_key(bootutil_rsa_context *ctx, uint8_t **p, uint8_t *end)
{
    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
    psa_key_attributes_t key_attributes = psa_key_attributes_init();

    /* Set attributes and import key */
    psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_VERIFY_HASH);
    psa_set_key_algorithm(&key_attributes, PSA_ALG_RSA_PSS(PSA_ALG_SHA_256));
    psa_set_key_type(&key_attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY);

    status = psa_import_key(&key_attributes, *p, (end - *p), &ctx->key_id);
    return (int)status;
}

/* Get the modulus (N) length in bytes */
static size_t bootutil_rsa_get_len(const bootutil_rsa_context *ctx)
{
    psa_key_attributes_t key_attributes = psa_key_attributes_init();
    psa_status_t status = psa_get_key_attributes(ctx->key_id, &key_attributes);
    if (status != PSA_SUCCESS) {
        return 0;
    }
    return PSA_BITS_TO_BYTES(psa_get_key_bits(&key_attributes));
}

/* PSA Crypto has a dedicated API for RSASSA-PSS verification */
static inline int bootutil_rsassa_pss_verify(const bootutil_rsa_context *ctx,
    uint8_t *hash, size_t hlen, uint8_t *sig, size_t slen)
{
    return (int) psa_verify_hash(ctx->key_id, PSA_ALG_RSA_PSS(PSA_ALG_SHA_256),
                                 hash, hlen, sig, slen);
}
#endif /* BOOTUTIL_CRYPTO_RSA_SIGN_ENABLED */

#elif defined(MCUBOOT_USE_MBED_TLS)

typedef mbedtls_rsa_context bootutil_rsa_context;

static inline void bootutil_rsa_init(bootutil_rsa_context *ctx)
{
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
    mbedtls_rsa_init(ctx);
    mbedtls_rsa_set_padding(ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
#else
    mbedtls_rsa_init(ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
#endif
}

static inline void bootutil_rsa_drop(bootutil_rsa_context *ctx)
{
    mbedtls_rsa_free(ctx);
}

#if defined(BOOTUTIL_CRYPTO_RSA_CRYPT_ENABLED) && (MBEDTLS_VERSION_NUMBER >= 0x03000000)
static int fake_rng(void *p_rng, unsigned char *output, size_t len);
#endif /* BOOTUTIL_CRYPTO_RSA_CRYPT_ENABLED && MBEDTLS_VERSION_NUMBER >= 3.0 */

#if defined(BOOTUTIL_CRYPTO_RSA_CRYPT_ENABLED)
static inline int bootutil_rsa_oaep_decrypt(
    bootutil_rsa_context *ctx,
    size_t *olen,
    const uint8_t *input,
    uint8_t *output,
    size_t output_max_len)
{
    int rc = -1;
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
    rc = mbedtls_rsa_rsaes_oaep_decrypt(ctx, fake_rng, NULL,
            NULL, 0, olen, input, output, output_max_len);
#else
    rc = mbedtls_rsa_rsaes_oaep_decrypt(ctx, NULL, NULL, MBEDTLS_RSA_PRIVATE,
            NULL, 0, olen, input, output, output_max_len);
#endif
    return rc;
}

/*
 * Parse a RSA private key with format specified in RFC3447 A.1.2
 */
static int
bootutil_rsa_parse_private_key(bootutil_rsa_context *ctx, uint8_t **p, uint8_t *end)
{
    size_t len;

    if (mbedtls_asn1_get_tag(p, end, &len,
                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
        return -1;
    }

    if (*p + len != end) {
        return -2;
    }

    /* Non-optional fields. */
    if ( /* version */
        mbedtls_asn1_get_int(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(ver)) != 0 ||
         /* public modulus */
        mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(N)) != 0 ||
         /* public exponent */
        mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(E)) != 0 ||
         /* private exponent */
        mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(D)) != 0 ||
         /* primes */
        mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(P)) != 0 ||
        mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(Q)) != 0) {

        return -3;
    }

#if !defined(MBEDTLS_RSA_NO_CRT)
    /*
     * DP/DQ/QP are only used inside mbedTLS if it was built with the
     * Chinese Remainder Theorem enabled (default). In case it is disabled
     * we parse, or if not available, we calculate those values.
     */
    if (*p < end) {
        if ( /* d mod (p-1) and d mod (q-1) */
            mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(DP)) != 0 ||
            mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(DQ)) != 0 ||
             /* q ^ (-1) mod p */
            mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(QP)) != 0) {

            return -4;
        }
    } else {
        if (mbedtls_rsa_deduce_crt(&ctx->MBEDTLS_CONTEXT_MEMBER(P),
                                   &ctx->MBEDTLS_CONTEXT_MEMBER(Q),
                                   &ctx->MBEDTLS_CONTEXT_MEMBER(D),
                                   &ctx->MBEDTLS_CONTEXT_MEMBER(DP),
                                   &ctx->MBEDTLS_CONTEXT_MEMBER(DQ),
                                   &ctx->MBEDTLS_CONTEXT_MEMBER(QP)) != 0) {
            return -5;
        }
    }
#endif /* !MBEDTLS_RSA_NO_CRT */

    ctx->MBEDTLS_CONTEXT_MEMBER(len) = mbedtls_mpi_size(&ctx->MBEDTLS_CONTEXT_MEMBER(N));

    if (mbedtls_rsa_check_privkey(ctx) != 0) {
        return -6;
    }

    return 0;
}
#endif /* BOOTUTIL_CRYPTO_RSA_CRYPT_ENABLED */

#if defined(BOOTUTIL_CRYPTO_RSA_SIGN_ENABLED)
/*
 * Parse a RSA public key with format specified in RFC3447 A.1.1
 */
static int
bootutil_rsa_parse_public_key(bootutil_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 Mbed TLS 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;
}

/* Get the modulus (N) length in bytes */
static inline size_t bootutil_rsa_get_len(const bootutil_rsa_context *ctx)
{
    return mbedtls_rsa_get_len(ctx);
}

/* Performs modular exponentiation using the public key output = input^E mod N */
static inline int bootutil_rsa_public(bootutil_rsa_context *ctx, const uint8_t *input, uint8_t *output)
{
    return mbedtls_rsa_public(ctx, input, output);
}
#endif /* BOOTUTIL_CRYPTO_RSA_SIGN_ENABLED */

#endif /* MCUBOOT_USE_MBED_TLS */

#ifdef __cplusplus
}
#endif

#endif /* __BOOTUTIL_CRYPTO_RSA_H_ */
+19 −98
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
 * SPDX-License-Identifier: Apache-2.0
 *
 * Copyright (c) 2018-2019 JUUL Labs
 * Copyright (c) 2019-2021 Arm Limited
 * Copyright (c) 2019-2023 Arm Limited
 */

#include "mcuboot_config/mcuboot_config.h"
@@ -13,13 +13,8 @@
#include <string.h>

#if defined(MCUBOOT_ENCRYPT_RSA)
#include "mbedtls/rsa.h"
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
#include "rsa_alt_helpers.h"
#else
#include "mbedtls/rsa_internal.h"
#endif
#include "mbedtls/asn1.h"
#define BOOTUTIL_CRYPTO_RSA_CRYPT_ENABLED
#include "bootutil/crypto/rsa.h"
#endif

#if defined(MCUBOOT_ENCRYPT_KW)
@@ -93,74 +88,6 @@ done:
}
#endif /* MCUBOOT_ENCRYPT_KW */

#if defined(MCUBOOT_ENCRYPT_RSA)
static int
parse_rsa_enckey(mbedtls_rsa_context *ctx, uint8_t **p, uint8_t *end)
{
    size_t len;

    if (mbedtls_asn1_get_tag(p, end, &len,
                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
        return -1;
    }

    if (*p + len != end) {
        return -2;
    }

    /* Non-optional fields. */
    if ( /* version */
        mbedtls_asn1_get_int(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(ver)) != 0 ||
         /* public modulus */
        mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(N)) != 0 ||
         /* public exponent */
        mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(E)) != 0 ||
         /* private exponent */
        mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(D)) != 0 ||
         /* primes */
        mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(P)) != 0 ||
        mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(Q)) != 0) {

        return -3;
    }

#if !defined(MBEDTLS_RSA_NO_CRT)
    /*
     * DP/DQ/QP are only used inside mbedTLS if it was built with the
     * Chinese Remainder Theorem enabled (default). In case it is disabled
     * we parse, or if not available, we calculate those values.
     */
    if (*p < end) {
        if ( /* d mod (p-1) and d mod (q-1) */
            mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(DP)) != 0 ||
            mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(DQ)) != 0 ||
             /* q ^ (-1) mod p */
            mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(QP)) != 0) {

            return -4;
        }
    } else {
        if (mbedtls_rsa_deduce_crt(&ctx->MBEDTLS_CONTEXT_MEMBER(P),
                                   &ctx->MBEDTLS_CONTEXT_MEMBER(Q),
                                   &ctx->MBEDTLS_CONTEXT_MEMBER(D),
                                   &ctx->MBEDTLS_CONTEXT_MEMBER(DP),
                                   &ctx->MBEDTLS_CONTEXT_MEMBER(DQ),
                                   &ctx->MBEDTLS_CONTEXT_MEMBER(QP)) != 0) {
            return -5;
        }
    }
#endif

    ctx->MBEDTLS_CONTEXT_MEMBER(len) = mbedtls_mpi_size(&ctx->MBEDTLS_CONTEXT_MEMBER(N));

    if (mbedtls_rsa_check_privkey(ctx) != 0) {
        return -6;
    }

    return 0;
}
#endif

#if defined(MCUBOOT_ENCRYPT_EC256)
static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_EC_ALG_UNRESTRICTED;
static const uint8_t ec_secp256r1_oid[] = MBEDTLS_OID_EC_GRP_SECP256R1;
@@ -460,8 +387,8 @@ _Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN,
        "Please fix ECIES-X25519 component indexes");
#endif

#if defined(MCUBOOT_ENCRYPT_RSA) || \
    (defined(MCUBOOT_ENCRYPT_EC256) && defined(MCUBOOT_USE_MBED_TLS))
#if ( (defined(MCUBOOT_ENCRYPT_RSA) && defined(MCUBOOT_USE_MBED_TLS) && !defined(MCUBOOT_USE_PSA_CRYPTO)) || \
      (defined(MCUBOOT_ENCRYPT_EC256) && defined(MCUBOOT_USE_MBED_TLS)) )
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
static int fake_rng(void *p_rng, unsigned char *output, size_t len)
{
@@ -474,9 +401,9 @@ static int fake_rng(void *p_rng, unsigned char *output, size_t len)

    return 0;
}
#endif
#endif /* defined(MCUBOOT_ENCRYPT_RSA) ||
          defined(MCUBOOT_ENCRYPT_EC256) && defined(MCUBOOT_USE_MBED_TLS) */
#endif /* MBEDTLS_VERSION_NUMBER */
#endif /* (MCUBOOT_ENCRYPT_RSA && MCUBOOT_USE_MBED_TLS && !MCUBOOT_USE_PSA_CRYPTO) ||
          (MCUBOOT_ENCRYPT_EC256 && MCUBOOT_USE_MBED_TLS) */

/*
 * Decrypt an encryption key TLV.
@@ -488,7 +415,7 @@ int
boot_enc_decrypt(const uint8_t *buf, uint8_t *enckey)
{
#if defined(MCUBOOT_ENCRYPT_RSA)
    mbedtls_rsa_context rsa;
    bootutil_rsa_context rsa;
    uint8_t *cp;
    uint8_t *cpend;
    size_t olen;
@@ -515,28 +442,22 @@ boot_enc_decrypt(const uint8_t *buf, uint8_t *enckey)

#if defined(MCUBOOT_ENCRYPT_RSA)

#if MBEDTLS_VERSION_NUMBER >= 0x03000000
    mbedtls_rsa_init(&rsa);
    mbedtls_rsa_set_padding(&rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
#else
    mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
#endif
    bootutil_rsa_init(&rsa);
    cp = (uint8_t *)bootutil_enc_key.key;
    cpend = cp + *bootutil_enc_key.len;

    rc = parse_rsa_enckey(&rsa, &cp, cpend);
    /* The enckey is encrypted through RSA so for decryption we need the private key */
    rc = bootutil_rsa_parse_private_key(&rsa, &cp, cpend);
    if (rc) {
        bootutil_rsa_drop(&rsa);
        return rc;
    }

    rc = bootutil_rsa_oaep_decrypt(&rsa, &olen, buf, enckey, BOOT_ENC_KEY_SIZE);
    bootutil_rsa_drop(&rsa);
    if (rc) {
        mbedtls_rsa_free(&rsa);
        return rc;
    }
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
    rc = mbedtls_rsa_rsaes_oaep_decrypt(&rsa, fake_rng, NULL,
            NULL, 0, &olen, buf, enckey, BOOT_ENC_KEY_SIZE);
#else
    rc = mbedtls_rsa_rsaes_oaep_decrypt(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE,
            NULL, 0, &olen, buf, enckey, BOOT_ENC_KEY_SIZE);
#endif
    mbedtls_rsa_free(&rsa);

#endif /* defined(MCUBOOT_ENCRYPT_RSA) */

+49 −73
Original line number Diff line number Diff line
@@ -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,16 +30,20 @@
#include "mcuboot_config/mcuboot_config.h"

#ifdef MCUBOOT_SIGN_RSA
#include "bootutil_priv.h"
#include "bootutil/sign_key.h"
#include "bootutil/crypto/sha256.h"
#include "bootutil/crypto/common.h"
#include "bootutil/fault_injection_hardening.h"

#include "mbedtls/rsa.h"
#include "mbedtls/asn1.h"
#include "mbedtls/version.h"
#define BOOTUTIL_CRYPTO_RSA_SIGN_ENABLED
#include "bootutil/crypto/rsa.h"

#include "bootutil_priv.h"
#include "bootutil/fault_injection_hardening.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
@@ -71,54 +75,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
@@ -159,11 +115,11 @@ pss_mgf1(uint8_t *mask, const uint8_t *hash)
/*
 * 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 @@ bootutil_cmp_rsasig(mbedtls_rsa_context *ctx, uint8_t *hash, uint32_t hlen,
    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 @@ bootutil_cmp_rsasig(mbedtls_rsa_context *ctx, uint8_t *hash, uint32_t hlen,
        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 @@ out:
    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);
}
+1 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@ if (DEFINED CONFIG_ESP_USE_MBEDTLS)
        ${MBEDTLS_DIR}/library/rsa.c
        ${MBEDTLS_DIR}/library/bignum.c
        ${MBEDTLS_DIR}/library/asn1parse.c
        ${MBEDTLS_DIR}/library/md.c
        ${MBEDTLS_DIR}/library/memory_buffer_alloc.c
        )
    if (DEFINED MBEDTLS_CONFIG_FILE)
+2 −0
Original line number Diff line number Diff line
@@ -103,6 +103,8 @@ fn main() {
        conf.file("../../ext/mbedtls/library/platform.c");
        conf.file("../../ext/mbedtls/library/platform_util.c");
        conf.file("../../ext/mbedtls/library/asn1parse.c");
        conf.file("../../ext/mbedtls/library/md.c");

    } else if sig_ecdsa {
        conf.conf.define("MCUBOOT_SIGN_EC256", None);
        conf.conf.define("MCUBOOT_USE_TINYCRYPT", None);