"Das U-Boot" Source Tree

Merge patch series "aspeed: ast2700: Add Caliptra ECDSA driver"

Chia-Wei Wang <chiawei_wang@aspeedtech.com> says:

Aspeed AST2700 SoCs integrates the Caliptra secure IP, where an ECDSA384
signature verification HW interface is exported for SoC crypto needs.

This patch series firstly extends the FIT image signing/verify common
code to support the ECDSA384 algorithm. For better convenience, the
device tree for ECDSA public key storage is also revised by referring
to RSA implementations.

After the FIT common code revision, the driver is implemented for
AST2700 to leverage the Caliptra ECDSA384 signature verification.

These are verified by signed FIT images with the algorithm "sha384,ecdsa384".

Link: https://lore.kernel.org/r/20241014095620.216936-1-chiawei_wang@aspeedtech.com

+215 -4
+1 -1
boot/image-fit-sig.c
··· 95 95 info->required_keynode = required_keynode; 96 96 printf("%s:%s", algo_name, info->keyname); 97 97 98 - if (!info->checksum || !info->crypto || !info->padding) { 98 + if (!info->checksum || !info->crypto) { 99 99 *err_msgp = "Unknown signature algorithm"; 100 100 return -1; 101 101 }
+10
drivers/crypto/aspeed/Kconfig
··· 28 28 29 29 Enabling this allows the use of SHA operations in hardware. Note that only 30 30 SHA384 and SHA512 are supported by Caliptra 1.0. 31 + 32 + config ASPEED_CPTRA_ECDSA 33 + bool "Caliptra ECDSA384 signature verifier for Aspeed SoCs" 34 + depends on ECDSA_VERIFY || SPL_ECDSA_VERIFY 35 + help 36 + Select this option to enable a driver for using the ECDSA384_SIGNATURE_VERIFY 37 + feature of Caliptra, which is integrated in AST27xx BMC SoCs. 38 + 39 + Enabling this allows the use of ECDSA384 signature verification in hardware. 40 + Note that only ECDSA384 is supported by Caliptra.
+1
drivers/crypto/aspeed/Makefile
··· 1 1 obj-$(CONFIG_ASPEED_HACE) += aspeed_hace.o 2 2 obj-$(CONFIG_ASPEED_ACRY) += aspeed_acry.o 3 3 obj-$(CONFIG_ASPEED_CPTRA_SHA) += cptra_sha.o 4 + obj-$(CONFIG_ASPEED_CPTRA_ECDSA) += cptra_ecdsa.o
+184
drivers/crypto/aspeed/cptra_ecdsa.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Copyright 2024 ASPEED Technology Inc. 4 + */ 5 + #include <asm/io.h> 6 + #include <config.h> 7 + #include <crypto/ecdsa-uclass.h> 8 + #include <dm.h> 9 + #include <linux/bitfield.h> 10 + #include <linux/bitops.h> 11 + #include <linux/iopoll.h> 12 + #include <malloc.h> 13 + #include <u-boot/ecdsa.h> 14 + 15 + /* SCU register offsets */ 16 + #define SCU1_CPTRA 0x130 17 + #define SCU1_CPTRA_RDY_FOR_RT BIT(18) 18 + 19 + /* CPTRA MBOX register offsets */ 20 + #define CPTRA_MBOX_LOCK 0x00 21 + #define CPTRA_MBOX_USER 0x04 22 + #define CPTRA_MBOX_CMD 0x08 23 + #define CPTRA_MBOX_DLEN 0x0c 24 + #define CPTRA_MBOX_DATAIN 0x10 25 + #define CPTRA_MBOX_DATAOUT 0x14 26 + #define CPTRA_MBOX_EXEC 0x18 27 + #define CPTRA_MBOX_STS 0x1c 28 + #define CPTRA_MBOX_STS_SOC_LOCK BIT(9) 29 + #define CPTRA_MBOX_STS_FSM_PS GENMASK(8, 6) 30 + #define CPTRA_MBOX_STS_PS GENMASK(3, 0) 31 + #define CPTRA_MBOX_UNLOCK 0x20 32 + 33 + #define CPTRA_ECDSA_SIG_LEN 96 /* ECDSA384 */ 34 + #define CPTRA_ECDSA_SHA_LEN 48 /* SHA384 */ 35 + 36 + #define CPTRA_MBCMD_ECDSA384_SIGNATURE_VERIFY 0x53494756 37 + 38 + enum cptra_mbox_sts { 39 + CPTRA_MBSTS_CMD_BUSY, 40 + CPTRA_MBSTS_DATA_READY, 41 + CPTRA_MBSTS_CMD_COMPLETE, 42 + CPTRA_MBSTS_CMD_FAILURE, 43 + }; 44 + 45 + enum cptra_mbox_fsm { 46 + CPTRA_MBFSM_IDLE, 47 + CPTRA_MBFSM_RDY_FOR_CMD, 48 + CPTRA_MBFSM_RDY_FOR_DLEN, 49 + CPTRA_MBFSM_RDY_FOR_DATA, 50 + CPTRA_MBFSM_EXEC_UC, 51 + CPTRA_MBFSM_EXEC_SOC, 52 + CPTRA_MBFSM_ERROR, 53 + }; 54 + 55 + struct cptra_ecdsa { 56 + void *regs; 57 + }; 58 + 59 + static uint32_t mbox_csum(uint32_t csum, uint8_t *data, uint32_t dlen) 60 + { 61 + uint32_t i; 62 + 63 + for (i = 0; i < dlen; ++i) 64 + csum -= data[i]; 65 + 66 + return csum; 67 + } 68 + 69 + static int cptra_ecdsa_verify(struct udevice *dev, const struct ecdsa_public_key *pubkey, 70 + const void *hash, size_t hash_len, 71 + const void *signature, size_t sig_len) 72 + { 73 + struct cptra_ecdsa *ce; 74 + uint8_t *x, *y, *r, *s; 75 + uint32_t cmd, csum; 76 + uint32_t reg, sts; 77 + uint32_t *p32; 78 + int i; 79 + 80 + if (hash_len != CPTRA_ECDSA_SHA_LEN || sig_len != CPTRA_ECDSA_SIG_LEN) 81 + return -EINVAL; 82 + 83 + if ((strcmp(pubkey->curve_name, "secp384r1") && strcmp(pubkey->curve_name, "prime384v1")) || 84 + pubkey->size_bits != ((CPTRA_ECDSA_SIG_LEN / 2) << 3)) 85 + return -EINVAL; 86 + 87 + ce = dev_get_priv(dev); 88 + 89 + /* get CPTRA MBOX lock */ 90 + if (readl_poll_timeout(ce->regs + CPTRA_MBOX_LOCK, reg, reg == 0, 1000000)) 91 + return -EBUSY; 92 + 93 + /* check MBOX is ready for command */ 94 + sts = readl(ce->regs + CPTRA_MBOX_STS); 95 + if (FIELD_GET(CPTRA_MBOX_STS_FSM_PS, sts) != CPTRA_MBFSM_RDY_FOR_CMD) 96 + return -EACCES; 97 + 98 + /* init mbox parameters */ 99 + cmd = CPTRA_MBCMD_ECDSA384_SIGNATURE_VERIFY; 100 + csum = 0; 101 + x = (uint8_t *)pubkey->x; 102 + y = (uint8_t *)pubkey->y; 103 + r = (uint8_t *)signature; 104 + s = (uint8_t *)signature + (CPTRA_ECDSA_SIG_LEN / 2); 105 + 106 + /* calculate checksum */ 107 + csum = mbox_csum(csum, (uint8_t *)&cmd, sizeof(cmd)); 108 + csum = mbox_csum(csum, x, CPTRA_ECDSA_SIG_LEN / 2); 109 + csum = mbox_csum(csum, y, CPTRA_ECDSA_SIG_LEN / 2); 110 + csum = mbox_csum(csum, r, CPTRA_ECDSA_SIG_LEN / 2); 111 + csum = mbox_csum(csum, s, CPTRA_ECDSA_SIG_LEN / 2); 112 + 113 + /* write command, data length */ 114 + writel(cmd, ce->regs + CPTRA_MBOX_CMD); 115 + writel(sizeof(csum) + (CPTRA_ECDSA_SIG_LEN << 1), ce->regs + CPTRA_MBOX_DLEN); 116 + 117 + /* write ECDSA384_SIGNATURE_VERIFY command parameters */ 118 + writel(csum, ce->regs + CPTRA_MBOX_DATAIN); 119 + 120 + for (i = 0, p32 = (uint32_t *)x; i < ((CPTRA_ECDSA_SIG_LEN / 2) / sizeof(*p32)); ++i) 121 + writel(p32[i], ce->regs + CPTRA_MBOX_DATAIN); 122 + 123 + for (i = 0, p32 = (uint32_t *)y; i < ((CPTRA_ECDSA_SIG_LEN / 2) / sizeof(*p32)); ++i) 124 + writel(p32[i], ce->regs + CPTRA_MBOX_DATAIN); 125 + 126 + for (i = 0, p32 = (uint32_t *)r; i < ((CPTRA_ECDSA_SIG_LEN / 2) / sizeof(*p32)); ++i) 127 + writel(p32[i], ce->regs + CPTRA_MBOX_DATAIN); 128 + 129 + for (i = 0, p32 = (uint32_t *)s; i < ((CPTRA_ECDSA_SIG_LEN / 2) / sizeof(*p32)); ++i) 130 + writel(p32[i], ce->regs + CPTRA_MBOX_DATAIN); 131 + 132 + /* trigger mbox command */ 133 + writel(0x1, ce->regs + CPTRA_MBOX_EXEC); 134 + 135 + /* poll for result */ 136 + while (1) { 137 + sts = FIELD_GET(CPTRA_MBOX_STS_PS, readl(ce->regs + CPTRA_MBOX_STS)); 138 + if (sts != CPTRA_MBSTS_CMD_BUSY) 139 + break; 140 + } 141 + 142 + /* unlock mbox */ 143 + writel(0x0, ce->regs + CPTRA_MBOX_EXEC); 144 + 145 + return (sts == CPTRA_MBSTS_CMD_FAILURE) ? sts : 0; 146 + } 147 + 148 + static int cptra_ecdsa_probe(struct udevice *dev) 149 + { 150 + struct cptra_ecdsa *ce = dev_get_priv(dev); 151 + 152 + ce->regs = (void *)devfdt_get_addr(dev); 153 + if (ce->regs == (void *)FDT_ADDR_T_NONE) { 154 + debug("cannot map Caliptra mailbox registers\n"); 155 + return -EINVAL; 156 + } 157 + 158 + return 0; 159 + } 160 + 161 + static int cptra_ecdsa_remove(struct udevice *dev) 162 + { 163 + return 0; 164 + } 165 + 166 + static const struct ecdsa_ops cptra_ecdsa_ops = { 167 + .verify = cptra_ecdsa_verify, 168 + }; 169 + 170 + static const struct udevice_id cptra_ecdsa_ids[] = { 171 + { .compatible = "aspeed,ast2700-cptra-ecdsa" }, 172 + { } 173 + }; 174 + 175 + U_BOOT_DRIVER(aspeed_cptra_ecdsa) = { 176 + .name = "aspeed_cptra_ecdsa", 177 + .id = UCLASS_ECDSA, 178 + .of_match = cptra_ecdsa_ids, 179 + .ops = &cptra_ecdsa_ops, 180 + .probe = cptra_ecdsa_probe, 181 + .remove = cptra_ecdsa_remove, 182 + .priv_auto = sizeof(struct cptra_ecdsa), 183 + .flags = DM_FLAG_PRE_RELOC, 184 + };
+1
include/u-boot/ecdsa.h
··· 65 65 /** @} */ 66 66 67 67 #define ECDSA256_BYTES (256 / 8) 68 + #define ECDSA384_BYTES (384 / 8) 68 69 #define ECDSA521_BYTES ((521 + 7) / 8) 69 70 70 71 #endif
+11 -3
lib/ecdsa/ecdsa-verify.c
··· 22 22 { 23 23 if (!strcmp(curve_name, "prime256v1")) 24 24 return 256; 25 - else 26 - return 0; 25 + else if (!strcmp(curve_name, "secp384r1")) 26 + return 384; 27 + 28 + return 0; 27 29 } 28 30 29 31 static int fdt_get_key(struct ecdsa_public_key *key, const void *fdt, int node) ··· 121 123 return ecdsa_verify_hash(dev, info, hash, sig, sig_len); 122 124 } 123 125 124 - U_BOOT_CRYPTO_ALGO(ecdsa) = { 126 + U_BOOT_CRYPTO_ALGO(ecdsa256) = { 125 127 .name = "ecdsa256", 126 128 .key_len = ECDSA256_BYTES, 129 + .verify = ecdsa_verify, 130 + }; 131 + 132 + U_BOOT_CRYPTO_ALGO(ecdsa384) = { 133 + .name = "ecdsa384", 134 + .key_len = ECDSA384_BYTES, 127 135 .verify = ecdsa_verify, 128 136 }; 129 137
+7
tools/image-sig-host.c
··· 77 77 .verify = ecdsa_verify, 78 78 }, 79 79 { 80 + .name = "ecdsa384", 81 + .key_len = ECDSA384_BYTES, 82 + .sign = ecdsa_sign, 83 + .add_verify_data = ecdsa_add_verify_data, 84 + .verify = ecdsa_verify, 85 + }, 86 + { 80 87 .name = "secp521r1", 81 88 .key_len = ECDSA521_BYTES, 82 89 .sign = ecdsa_sign,