uboot/arch/arm/mach-stm32mp/ecdsa_romapi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * STM32MP ECDSA verification via the ROM API
   4 *
   5 * Implements ECDSA signature verification via the STM32MP ROM.
   6 */
   7#include <asm/system.h>
   8#include <dm/device.h>
   9#include <linux/types.h>
  10#include <u-boot/ecdsa.h>
  11#include <crypto/ecdsa-uclass.h>
  12#include <linux/libfdt.h>
  13#include <dm/platdata.h>
  14
  15#define ROM_API_SUCCESS                         0x77
  16#define ROM_API_ECDSA_ALGO_PRIME_256V1          1
  17#define ROM_API_ECDSA_ALGO_BRAINPOOL_256        2
  18
  19#define ROM_API_OFFSET_ECDSA_VERIFY             0x60
  20
  21struct ecdsa_rom_api {
  22        uint32_t (*ecdsa_verify_signature)(const void *hash, const void *pubkey,
  23                                           const void *signature,
  24                                           uint32_t ecc_algo);
  25};
  26
  27static void stm32mp_rom_get_ecdsa_functions(struct ecdsa_rom_api *rom)
  28{
  29        uintptr_t verify_ptr = get_stm32mp_rom_api_table() +
  30                               ROM_API_OFFSET_ECDSA_VERIFY;
  31
  32        rom->ecdsa_verify_signature = *(void **)verify_ptr;
  33}
  34
  35static int ecdsa_key_algo(const char *curve_name)
  36{
  37        if (!strcmp(curve_name, "prime256v1"))
  38                return ROM_API_ECDSA_ALGO_PRIME_256V1;
  39        else if (!strcmp(curve_name, "brainpool256"))
  40                return ROM_API_ECDSA_ALGO_BRAINPOOL_256;
  41        else
  42                return -ENOPROTOOPT;
  43}
  44
  45static int romapi_ecdsa_verify(struct udevice *dev,
  46                               const struct ecdsa_public_key *pubkey,
  47                               const void *hash, size_t hash_len,
  48                               const void *signature, size_t sig_len)
  49{
  50        struct ecdsa_rom_api rom;
  51        uint8_t raw_key[64];
  52        uint32_t rom_ret;
  53        int algo;
  54
  55        /* The ROM API can only handle 256-bit ECDSA keys. */
  56        if (sig_len != 64 || hash_len != 32 || pubkey->size_bits != 256)
  57                return -EINVAL;
  58
  59        algo = ecdsa_key_algo(pubkey->curve_name);
  60        if (algo < 0)
  61                return algo;
  62
  63        /* The ROM API wants the (X, Y) coordinates concatenated. */
  64        memcpy(raw_key, pubkey->x, 32);
  65        memcpy(raw_key + 32, pubkey->y, 32);
  66
  67        stm32mp_rom_get_ecdsa_functions(&rom);
  68
  69        /* Mark BootROM region as executable. */
  70        mmu_set_region_dcache_behaviour(0, SZ_2M, DCACHE_DEFAULT_OPTION);
  71
  72        rom_ret = rom.ecdsa_verify_signature(hash, raw_key, signature, algo);
  73
  74        return rom_ret == ROM_API_SUCCESS ? 0 : -EPERM;
  75}
  76
  77static const struct ecdsa_ops rom_api_ops = {
  78        .verify = romapi_ecdsa_verify,
  79};
  80
  81U_BOOT_DRIVER(stm32mp_rom_api_ecdsa) = {
  82        .name   = "stm32mp_rom_api_ecdsa",
  83        .id     = UCLASS_ECDSA,
  84        .ops    = &rom_api_ops,
  85        .flags  = DM_FLAG_PRE_RELOC,
  86};
  87
  88U_BOOT_DRVINFO(stm32mp_rom_api_ecdsa) = {
  89        .name = "stm32mp_rom_api_ecdsa",
  90};
  91