[PATCH 0/4] arm: stm32mp: adapt the command stm32key for STM32MP13x

And support the 2 keys for STM32MP13x - PKHTH : Hash of the 8 ECC Public Keys Hashes Table (ECDSA is the authentication algorithm) - EDMK : Encryption/Decryption Master Key
Only one key is supported for STM32MP15x - PKH : Hash of the ECC Public Key (ECDSA is the authentication algorithm)
This STM32KEY command is used in STM32MP SoCs to provision the keys in the correct OTP needed to activate secure boot features: authentication and encryption.
See [1] for details
[1] STM32 MPU wiki https://wiki.st.com/stm32mpu/wiki/How_to_use_U-Boot_stm32key_command
Patrick Delaunay (4): arm: stm32mp: add defines for BSEC_LOCK status in stm32key command arm: stm32mp: introduced read_close_status function in stm32key command arm: stm32mp: support several key in command stm32key arm: stm32mp: adapt the command stm32key for STM32MP13x
arch/arm/mach-stm32mp/cmd_stm32key.c | 331 ++++++++++++++++++++------- 1 file changed, 249 insertions(+), 82 deletions(-)

Add defines for value used in stm32key for BSEC permanent lock status and error.
This patch is a preliminary step to support more lock status in BSEC driver.
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com ---
arch/arm/mach-stm32mp/cmd_stm32key.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/arch/arm/mach-stm32mp/cmd_stm32key.c b/arch/arm/mach-stm32mp/cmd_stm32key.c index 68f28922d1e..1899d91ecb5 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32key.c +++ b/arch/arm/mach-stm32mp/cmd_stm32key.c @@ -19,6 +19,9 @@ #define STM32_OTP_HASH_KEY_START 24 #define STM32_OTP_HASH_KEY_SIZE 8
+#define BSEC_LOCK_ERROR (-1) +#define BSEC_LOCK_PERM BIT(0) + static int get_misc_dev(struct udevice **dev) { int ret; @@ -60,14 +63,14 @@ static int read_hash_otp(bool print, bool *locked, bool *closed) val = ~0x0; ret = misc_read(dev, STM32_BSEC_LOCK(word), &lock, 4); if (ret != 4) - lock = -1; + lock = BSEC_LOCK_ERROR; if (print) - printf("OTP HASH %i: %x lock : %d\n", word, val, lock); + printf("OTP HASH %i: %x lock : %x\n", word, val, lock); if (val == ~0x0) nb_invalid++; else if (val == 0x0) nb_zero++; - if (lock == 1) + if (lock & BSEC_LOCK_PERM) nb_lock++; }
@@ -77,13 +80,13 @@ static int read_hash_otp(bool print, bool *locked, bool *closed) val = 0x0; ret = misc_read(dev, STM32_BSEC_LOCK(word), &lock, 4); if (ret != 4) - lock = -1; + lock = BSEC_LOCK_ERROR;
status = (val & STM32_OTP_CLOSE_MASK) == STM32_OTP_CLOSE_MASK; if (closed) *closed = status; if (print) - printf("OTP %d: closed status: %d lock : %d\n", word, status, lock); + printf("OTP %d: closed status: %d lock : %x\n", word, status, lock);
status = (nb_lock == STM32_OTP_HASH_KEY_SIZE); if (locked) @@ -128,7 +131,7 @@ static int fuse_hash_value(u32 addr, bool print) return ret; } /* on success, lock the OTP for HASH key */ - val = 1; + val = BSEC_LOCK_PERM; ret = misc_write(dev, STM32_BSEC_LOCK(word), &val, 4); if (ret != 4) { log_err("Lock OTP %i failed\n", word);

Hi Patrick
On 9/15/22 18:11, Patrick Delaunay wrote:
Add defines for value used in stm32key for BSEC permanent lock status and error.
This patch is a preliminary step to support more lock status in BSEC driver.
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com
arch/arm/mach-stm32mp/cmd_stm32key.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/arch/arm/mach-stm32mp/cmd_stm32key.c b/arch/arm/mach-stm32mp/cmd_stm32key.c index 68f28922d1e..1899d91ecb5 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32key.c +++ b/arch/arm/mach-stm32mp/cmd_stm32key.c @@ -19,6 +19,9 @@ #define STM32_OTP_HASH_KEY_START 24 #define STM32_OTP_HASH_KEY_SIZE 8
+#define BSEC_LOCK_ERROR (-1) +#define BSEC_LOCK_PERM BIT(0)
static int get_misc_dev(struct udevice **dev) { int ret; @@ -60,14 +63,14 @@ static int read_hash_otp(bool print, bool *locked, bool *closed) val = ~0x0; ret = misc_read(dev, STM32_BSEC_LOCK(word), &lock, 4); if (ret != 4)
lock = -1;
if (print)lock = BSEC_LOCK_ERROR;
printf("OTP HASH %i: %x lock : %d\n", word, val, lock);
if (val == ~0x0) nb_invalid++; else if (val == 0x0) nb_zero++;printf("OTP HASH %i: %x lock : %x\n", word, val, lock);
if (lock == 1)
}if (lock & BSEC_LOCK_PERM) nb_lock++;
@@ -77,13 +80,13 @@ static int read_hash_otp(bool print, bool *locked, bool *closed) val = 0x0; ret = misc_read(dev, STM32_BSEC_LOCK(word), &lock, 4); if (ret != 4)
lock = -1;
lock = BSEC_LOCK_ERROR;
status = (val & STM32_OTP_CLOSE_MASK) == STM32_OTP_CLOSE_MASK; if (closed) *closed = status; if (print)
printf("OTP %d: closed status: %d lock : %d\n", word, status, lock);
printf("OTP %d: closed status: %d lock : %x\n", word, status, lock);
status = (nb_lock == STM32_OTP_HASH_KEY_SIZE); if (locked)
@@ -128,7 +131,7 @@ static int fuse_hash_value(u32 addr, bool print) return ret; } /* on success, lock the OTP for HASH key */
val = 1;
ret = misc_write(dev, STM32_BSEC_LOCK(word), &val, 4); if (ret != 4) { log_err("Lock OTP %i failed\n", word);val = BSEC_LOCK_PERM;
Reviewed-by: Patrice Chotard patrice.chotard@foss.st.com
Thanks Patrice

Split the read_hash_otp function and introduce the helper function read_close_status to read the close status in OTP separately of the PKH.
This patch is a preliminary step for STM32MP13 support.
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com ---
arch/arm/mach-stm32mp/cmd_stm32key.c | 107 ++++++++++++++++----------- 1 file changed, 65 insertions(+), 42 deletions(-)
diff --git a/arch/arm/mach-stm32mp/cmd_stm32key.c b/arch/arm/mach-stm32mp/cmd_stm32key.c index 1899d91ecb5..68f9b1a9a59 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32key.c +++ b/arch/arm/mach-stm32mp/cmd_stm32key.c @@ -45,18 +45,13 @@ static void read_hash_value(u32 addr) } }
-static int read_hash_otp(bool print, bool *locked, bool *closed) +static int read_hash_otp(struct udevice *dev, bool print, bool *locked) { - struct udevice *dev; int i, word, ret; int nb_invalid = 0, nb_zero = 0, nb_lock = 0; u32 val, lock; bool status;
- ret = get_misc_dev(&dev); - if (ret) - return ret; - for (i = 0, word = STM32_OTP_HASH_KEY_START; i < STM32_OTP_HASH_KEY_SIZE; i++, word++) { ret = misc_read(dev, STM32_BSEC_OTP(word), &val, 4); if (ret != 4) @@ -74,20 +69,6 @@ static int read_hash_otp(bool print, bool *locked, bool *closed) nb_lock++; }
- word = STM32_OTP_CLOSE_ID; - ret = misc_read(dev, STM32_BSEC_OTP(word), &val, 4); - if (ret != 4) - val = 0x0; - ret = misc_read(dev, STM32_BSEC_LOCK(word), &lock, 4); - if (ret != 4) - lock = BSEC_LOCK_ERROR; - - status = (val & STM32_OTP_CLOSE_MASK) == STM32_OTP_CLOSE_MASK; - if (closed) - *closed = status; - if (print) - printf("OTP %d: closed status: %d lock : %x\n", word, status, lock); - status = (nb_lock == STM32_OTP_HASH_KEY_SIZE); if (locked) *locked = status; @@ -108,16 +89,40 @@ static int read_hash_otp(bool print, bool *locked, bool *closed) return 0; }
-static int fuse_hash_value(u32 addr, bool print) +static int read_close_status(struct udevice *dev, bool print, bool *closed) +{ + int word, ret, result; + u32 val, lock; + bool status; + + result = 0; + word = STM32_OTP_CLOSE_ID; + ret = misc_read(dev, STM32_BSEC_OTP(word), &val, 4); + if (ret < 0) + result = ret; + if (ret != 4) + val = 0x0; + + ret = misc_read(dev, STM32_BSEC_LOCK(word), &lock, 4); + if (ret < 0) + result = ret; + if (ret != 4) + lock = BSEC_LOCK_ERROR; + + status = (val & STM32_OTP_CLOSE_MASK) == STM32_OTP_CLOSE_MASK; + if (closed) + *closed = status; + if (print) + printf("OTP %d: closed status: %d lock : %x\n", word, status, lock); + + return result; +} + +static int fuse_hash_value(struct udevice *dev, u32 addr, bool print) { - struct udevice *dev; u32 word, val; int i, ret;
- ret = get_misc_dev(&dev); - if (ret) - return ret; - for (i = 0, word = STM32_OTP_HASH_KEY_START; i < STM32_OTP_HASH_KEY_SIZE; i++, word++, addr += 4) { @@ -158,10 +163,20 @@ static int confirm_prog(void)
static int do_stm32key_read(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { + struct udevice *dev; u32 addr; + int ret; + + ret = get_misc_dev(&dev);
if (argc == 1) { - read_hash_otp(true, NULL, NULL); + if (ret) + return CMD_RET_FAILURE; + read_hash_otp(dev, true, NULL); + ret = read_close_status(dev, true, NULL); + if (ret) + return CMD_RET_FAILURE; + return CMD_RET_SUCCESS; }
@@ -176,8 +191,10 @@ static int do_stm32key_read(struct cmd_tbl *cmdtp, int flag, int argc, char *con
static int do_stm32key_fuse(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { + struct udevice *dev; u32 addr; - bool yes = false, lock, closed; + int ret; + bool yes = false, lock;
if (argc < 2) return CMD_RET_USAGE; @@ -192,20 +209,23 @@ static int do_stm32key_fuse(struct cmd_tbl *cmdtp, int flag, int argc, char *con if (!addr) return CMD_RET_USAGE;
- if (read_hash_otp(!yes, &lock, &closed) != -ENOENT) { + ret = get_misc_dev(&dev); + if (ret) + return CMD_RET_FAILURE; + + if (read_hash_otp(dev, !yes, &lock) != -ENOENT) { printf("Error: can't fuse again the OTP\n"); return CMD_RET_FAILURE; } - - if (lock || closed) { - printf("Error: invalid OTP configuration (lock=%d, closed=%d)\n", lock, closed); + if (lock) { + printf("Error: PKH is locked\n"); return CMD_RET_FAILURE; }
if (!yes && !confirm_prog()) return CMD_RET_FAILURE;
- if (fuse_hash_value(addr, !yes)) + if (fuse_hash_value(dev, addr, !yes)) return CMD_RET_FAILURE;
printf("Hash key updated !\n"); @@ -227,28 +247,31 @@ static int do_stm32key_close(struct cmd_tbl *cmdtp, int flag, int argc, char *co yes = true; }
- ret = read_hash_otp(!yes, &lock, &closed); - if (ret) { - if (ret == -ENOENT) - printf("Error: OTP not programmed!\n"); + ret = get_misc_dev(&dev); + if (ret) + return CMD_RET_FAILURE; + + if (read_close_status(dev, !yes, &closed)) return CMD_RET_FAILURE; - }
if (closed) { printf("Error: already closed!\n"); return CMD_RET_FAILURE; }
+ /* check PKH status before to close */ + ret = read_hash_otp(dev, !yes, &lock); + if (ret) { + if (ret == -ENOENT) + printf("Error: OTP not programmed!\n"); + return CMD_RET_FAILURE; + } if (!lock) printf("Warning: OTP not locked!\n");
if (!yes && !confirm_prog()) return CMD_RET_FAILURE;
- ret = get_misc_dev(&dev); - if (ret) - return CMD_RET_FAILURE; - val = STM32_OTP_CLOSE_MASK; ret = misc_write(dev, STM32_BSEC_OTP(STM32_OTP_CLOSE_ID), &val, 4); if (ret != 4) {

Hi Patrick
On 9/15/22 18:11, Patrick Delaunay wrote:
Split the read_hash_otp function and introduce the helper function read_close_status to read the close status in OTP separately of the PKH.
This patch is a preliminary step for STM32MP13 support.
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com
arch/arm/mach-stm32mp/cmd_stm32key.c | 107 ++++++++++++++++----------- 1 file changed, 65 insertions(+), 42 deletions(-)
diff --git a/arch/arm/mach-stm32mp/cmd_stm32key.c b/arch/arm/mach-stm32mp/cmd_stm32key.c index 1899d91ecb5..68f9b1a9a59 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32key.c +++ b/arch/arm/mach-stm32mp/cmd_stm32key.c @@ -45,18 +45,13 @@ static void read_hash_value(u32 addr) } }
-static int read_hash_otp(bool print, bool *locked, bool *closed) +static int read_hash_otp(struct udevice *dev, bool print, bool *locked) {
struct udevice *dev; int i, word, ret; int nb_invalid = 0, nb_zero = 0, nb_lock = 0; u32 val, lock; bool status;
ret = get_misc_dev(&dev);
if (ret)
return ret;
for (i = 0, word = STM32_OTP_HASH_KEY_START; i < STM32_OTP_HASH_KEY_SIZE; i++, word++) { ret = misc_read(dev, STM32_BSEC_OTP(word), &val, 4); if (ret != 4)
@@ -74,20 +69,6 @@ static int read_hash_otp(bool print, bool *locked, bool *closed) nb_lock++; }
- word = STM32_OTP_CLOSE_ID;
- ret = misc_read(dev, STM32_BSEC_OTP(word), &val, 4);
- if (ret != 4)
val = 0x0;
- ret = misc_read(dev, STM32_BSEC_LOCK(word), &lock, 4);
- if (ret != 4)
lock = BSEC_LOCK_ERROR;
- status = (val & STM32_OTP_CLOSE_MASK) == STM32_OTP_CLOSE_MASK;
- if (closed)
*closed = status;
- if (print)
printf("OTP %d: closed status: %d lock : %x\n", word, status, lock);
- status = (nb_lock == STM32_OTP_HASH_KEY_SIZE); if (locked) *locked = status;
@@ -108,16 +89,40 @@ static int read_hash_otp(bool print, bool *locked, bool *closed) return 0; }
-static int fuse_hash_value(u32 addr, bool print) +static int read_close_status(struct udevice *dev, bool print, bool *closed) +{
- int word, ret, result;
- u32 val, lock;
- bool status;
- result = 0;
- word = STM32_OTP_CLOSE_ID;
- ret = misc_read(dev, STM32_BSEC_OTP(word), &val, 4);
- if (ret < 0)
result = ret;
- if (ret != 4)
val = 0x0;
- ret = misc_read(dev, STM32_BSEC_LOCK(word), &lock, 4);
- if (ret < 0)
result = ret;
- if (ret != 4)
lock = BSEC_LOCK_ERROR;
- status = (val & STM32_OTP_CLOSE_MASK) == STM32_OTP_CLOSE_MASK;
- if (closed)
*closed = status;
- if (print)
printf("OTP %d: closed status: %d lock : %x\n", word, status, lock);
- return result;
+}
+static int fuse_hash_value(struct udevice *dev, u32 addr, bool print) {
struct udevice *dev; u32 word, val; int i, ret;
ret = get_misc_dev(&dev);
if (ret)
return ret;
for (i = 0, word = STM32_OTP_HASH_KEY_START; i < STM32_OTP_HASH_KEY_SIZE; i++, word++, addr += 4) {
@@ -158,10 +163,20 @@ static int confirm_prog(void)
static int do_stm32key_read(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) {
struct udevice *dev; u32 addr;
int ret;
ret = get_misc_dev(&dev);
if (argc == 1) {
read_hash_otp(true, NULL, NULL);
if (ret)
return CMD_RET_FAILURE;
read_hash_otp(dev, true, NULL);
ret = read_close_status(dev, true, NULL);
if (ret)
return CMD_RET_FAILURE;
- return CMD_RET_SUCCESS; }
@@ -176,8 +191,10 @@ static int do_stm32key_read(struct cmd_tbl *cmdtp, int flag, int argc, char *con
static int do_stm32key_fuse(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) {
- struct udevice *dev; u32 addr;
- bool yes = false, lock, closed;
int ret;
bool yes = false, lock;
if (argc < 2) return CMD_RET_USAGE;
@@ -192,20 +209,23 @@ static int do_stm32key_fuse(struct cmd_tbl *cmdtp, int flag, int argc, char *con if (!addr) return CMD_RET_USAGE;
- if (read_hash_otp(!yes, &lock, &closed) != -ENOENT) {
- ret = get_misc_dev(&dev);
- if (ret)
return CMD_RET_FAILURE;
- if (read_hash_otp(dev, !yes, &lock) != -ENOENT) { printf("Error: can't fuse again the OTP\n"); return CMD_RET_FAILURE; }
- if (lock || closed) {
printf("Error: invalid OTP configuration (lock=%d, closed=%d)\n", lock, closed);
if (lock) {
printf("Error: PKH is locked\n");
return CMD_RET_FAILURE; }
if (!yes && !confirm_prog()) return CMD_RET_FAILURE;
- if (fuse_hash_value(addr, !yes))
if (fuse_hash_value(dev, addr, !yes)) return CMD_RET_FAILURE;
printf("Hash key updated !\n");
@@ -227,28 +247,31 @@ static int do_stm32key_close(struct cmd_tbl *cmdtp, int flag, int argc, char *co yes = true; }
- ret = read_hash_otp(!yes, &lock, &closed);
- if (ret) {
if (ret == -ENOENT)
printf("Error: OTP not programmed!\n");
- ret = get_misc_dev(&dev);
- if (ret)
return CMD_RET_FAILURE;
- if (read_close_status(dev, !yes, &closed)) return CMD_RET_FAILURE;
}
if (closed) { printf("Error: already closed!\n"); return CMD_RET_FAILURE; }
/* check PKH status before to close */
ret = read_hash_otp(dev, !yes, &lock);
if (ret) {
if (ret == -ENOENT)
printf("Error: OTP not programmed!\n");
return CMD_RET_FAILURE;
} if (!lock) printf("Warning: OTP not locked!\n");
if (!yes && !confirm_prog()) return CMD_RET_FAILURE;
- ret = get_misc_dev(&dev);
- if (ret)
return CMD_RET_FAILURE;
- val = STM32_OTP_CLOSE_MASK; ret = misc_write(dev, STM32_BSEC_OTP(STM32_OTP_CLOSE_ID), &val, 4); if (ret != 4) {
Reviewed-by: Patrice Chotard patrice.chotard@foss.st.com
Thanks Patrice

Update the command stm32key to support several keys selected by key name and managed by the new sub-command:
stm32key list stm32key select [<key>] stm32key read -a
This patch doesn't change the STM32MP15 behavior, only PKH is supported, but it is a preliminary patch for STM32MP13 support.
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com ---
arch/arm/mach-stm32mp/cmd_stm32key.c | 195 ++++++++++++++++++++------- 1 file changed, 149 insertions(+), 46 deletions(-)
diff --git a/arch/arm/mach-stm32mp/cmd_stm32key.c b/arch/arm/mach-stm32mp/cmd_stm32key.c index 68f9b1a9a59..4eac56082db 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32key.c +++ b/arch/arm/mach-stm32mp/cmd_stm32key.c @@ -15,9 +15,37 @@ #define STM32_OTP_CLOSE_ID 0 #define STM32_OTP_CLOSE_MASK BIT(6)
-/* HASH of key: 8 OTPs, starting with OTP24) */ -#define STM32_OTP_HASH_KEY_START 24 -#define STM32_OTP_HASH_KEY_SIZE 8 +/* PKH is the first element of the key list */ +#define STM32KEY_PKH 0 + +struct stm32key { + char *name; + char *desc; + u8 start; + u8 size; +}; + +const struct stm32key stm32mp15_list[] = { + [STM32KEY_PKH] = { + .name = "PKH", + .desc = "Hash of the ECC Public Key (ECDSA is the authentication algorithm)", + .start = 24, + .size = 8, + } +}; + +/* index of current selected key in stm32key list, 0 = PKH by default */ +static u8 stm32key_index; + +static u8 get_key_nb(void) +{ + return ARRAY_SIZE(stm32mp15_list); +} + +static const struct stm32key *get_key(u8 index) +{ + return &stm32mp15_list[index]; +}
#define BSEC_LOCK_ERROR (-1) #define BSEC_LOCK_PERM BIT(0) @@ -33,26 +61,25 @@ static int get_misc_dev(struct udevice **dev) return ret; }
-static void read_hash_value(u32 addr) +static void read_key_value(const struct stm32key *key, u32 addr) { int i;
- printf("Read KEY at 0x%x\n", addr); - for (i = 0; i < STM32_OTP_HASH_KEY_SIZE; i++) { - printf("OTP value %i: %x\n", STM32_OTP_HASH_KEY_START + i, - __be32_to_cpu(*(u32 *)addr)); + for (i = 0; i < key->size; i++) { + printf("%s OTP %i: [%08x] %08x\n", key->name, key->start + i, + addr, __be32_to_cpu(*(u32 *)addr)); addr += 4; } }
-static int read_hash_otp(struct udevice *dev, bool print, bool *locked) +static int read_key_otp(struct udevice *dev, const struct stm32key *key, bool print, bool *locked) { int i, word, ret; - int nb_invalid = 0, nb_zero = 0, nb_lock = 0; + int nb_invalid = 0, nb_zero = 0, nb_lock = 0, nb_lock_err = 0; u32 val, lock; bool status;
- for (i = 0, word = STM32_OTP_HASH_KEY_START; i < STM32_OTP_HASH_KEY_SIZE; i++, word++) { + for (i = 0, word = key->start; i < key->size; i++, word++) { ret = misc_read(dev, STM32_BSEC_OTP(word), &val, 4); if (ret != 4) val = ~0x0; @@ -60,29 +87,33 @@ static int read_hash_otp(struct udevice *dev, bool print, bool *locked) if (ret != 4) lock = BSEC_LOCK_ERROR; if (print) - printf("OTP HASH %i: %x lock : %x\n", word, val, lock); + printf("%s OTP %i: %08x lock : %08x\n", key->name, word, val, lock); if (val == ~0x0) nb_invalid++; else if (val == 0x0) nb_zero++; if (lock & BSEC_LOCK_PERM) nb_lock++; + if (lock & BSEC_LOCK_ERROR) + nb_lock_err++; }
- status = (nb_lock == STM32_OTP_HASH_KEY_SIZE); + status = nb_lock_err || (nb_lock == key->size); if (locked) *locked = status; - if (!status && print) - printf("Hash of key is not locked!\n"); + if (nb_lock_err && print) + printf("%s lock is invalid!\n", key->name); + else if (!status && print) + printf("%s is not locked!\n", key->name);
- if (nb_invalid == STM32_OTP_HASH_KEY_SIZE) { + if (nb_invalid == key->size) { if (print) - printf("Hash of key is invalid!\n"); + printf("%s is invalid!\n", key->name); return -EINVAL; } - if (nb_zero == STM32_OTP_HASH_KEY_SIZE) { + if (nb_zero == key->size) { if (print) - printf("Hash of key is free!\n"); + printf("%s is free!\n", key->name); return -ENOENT; }
@@ -113,33 +144,31 @@ static int read_close_status(struct udevice *dev, bool print, bool *closed) if (closed) *closed = status; if (print) - printf("OTP %d: closed status: %d lock : %x\n", word, status, lock); + printf("OTP %d: closed status: %d lock : %08x\n", word, status, lock);
return result; }
-static int fuse_hash_value(struct udevice *dev, u32 addr, bool print) +static int fuse_key_value(struct udevice *dev, const struct stm32key *key, u32 addr, bool print) { u32 word, val; int i, ret;
- for (i = 0, word = STM32_OTP_HASH_KEY_START; - i < STM32_OTP_HASH_KEY_SIZE; - i++, word++, addr += 4) { + for (i = 0, word = key->start; i < key->size; i++, word++, addr += 4) { val = __be32_to_cpu(*(u32 *)addr); if (print) - printf("Fuse OTP %i : %x\n", word, val); + printf("Fuse %s OTP %i : %08x\n", key->name, word, val);
ret = misc_write(dev, STM32_BSEC_OTP(word), &val, 4); if (ret != 4) { - log_err("Fuse OTP %i failed\n", word); + log_err("Fuse %s OTP %i failed\n", key->name, word); return ret; } - /* on success, lock the OTP for HASH key */ + /* on success, lock the OTP for the key */ val = BSEC_LOCK_PERM; ret = misc_write(dev, STM32_BSEC_LOCK(word), &val, 4); if (ret != 4) { - log_err("Lock OTP %i failed\n", word); + log_err("Lock %s OTP %i failed\n", key->name, word); return ret; } } @@ -161,36 +190,99 @@ static int confirm_prog(void) return 0; }
+static void display_key_info(const struct stm32key *key) +{ + printf("%s : %s\n", key->name, key->desc); + printf("\tOTP%d..%d\n", key->start, key->start + key->size); +} + +static int do_stm32key_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + int i; + + for (i = 0; i < get_key_nb(); i++) + display_key_info(get_key(i)); + + return CMD_RET_SUCCESS; +} + +static int do_stm32key_select(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + const struct stm32key *key; + int i; + + if (argc == 1) { + printf("Selected key:\n"); + key = get_key(stm32key_index); + display_key_info(key); + return CMD_RET_SUCCESS; + } + + for (i = 0; i < get_key_nb(); i++) { + key = get_key(i); + if (!strcmp(key->name, argv[1])) { + printf("%s selected\n", key->name); + stm32key_index = i; + return CMD_RET_SUCCESS; + } + } + + printf("Unknown key %s\n", argv[1]); + + return CMD_RET_FAILURE; +} + static int do_stm32key_read(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { + const struct stm32key *key; struct udevice *dev; u32 addr; - int ret; + int ret, i; + int result;
ret = get_misc_dev(&dev);
if (argc == 1) { if (ret) return CMD_RET_FAILURE; - read_hash_otp(dev, true, NULL); - ret = read_close_status(dev, true, NULL); + key = get_key(stm32key_index); + ret = read_key_otp(dev, key, true, NULL); + if (ret != -ENOENT) + return CMD_RET_FAILURE; + return CMD_RET_SUCCESS; + } + + if (!strcmp("-a", argv[1])) { if (ret) return CMD_RET_FAILURE; + result = CMD_RET_SUCCESS; + for (i = 0; i < get_key_nb(); i++) { + key = get_key(i); + ret = read_key_otp(dev, key, true, NULL); + if (ret != -ENOENT) + result = CMD_RET_FAILURE; + } + ret = read_close_status(dev, true, NULL); + if (ret) + result = CMD_RET_FAILURE;
- return CMD_RET_SUCCESS; + return result; }
addr = hextoul(argv[1], NULL); if (!addr) return CMD_RET_USAGE;
- read_hash_value(addr); + key = get_key(stm32key_index); + printf("Read %s at 0x%08x\n", key->name, addr); + read_key_value(key, addr);
return CMD_RET_SUCCESS; }
static int do_stm32key_fuse(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { + const struct stm32key *key = get_key(stm32key_index); struct udevice *dev; u32 addr; int ret; @@ -213,28 +305,34 @@ static int do_stm32key_fuse(struct cmd_tbl *cmdtp, int flag, int argc, char *con if (ret) return CMD_RET_FAILURE;
- if (read_hash_otp(dev, !yes, &lock) != -ENOENT) { + if (read_key_otp(dev, key, !yes, &lock) != -ENOENT) { printf("Error: can't fuse again the OTP\n"); return CMD_RET_FAILURE; } if (lock) { - printf("Error: PKH is locked\n"); + printf("Error: %s is locked\n", key->name); return CMD_RET_FAILURE; }
+ if (!yes) { + printf("Writing %s with\n", key->name); + read_key_value(key, addr); + } + if (!yes && !confirm_prog()) return CMD_RET_FAILURE;
- if (fuse_hash_value(dev, addr, !yes)) + if (fuse_key_value(dev, key, addr, !yes)) return CMD_RET_FAILURE;
- printf("Hash key updated !\n"); + printf("%s updated !\n", key->name);
return CMD_RET_SUCCESS; }
static int do_stm32key_close(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { + const struct stm32key *key; bool yes, lock, closed; struct udevice *dev; u32 val; @@ -260,14 +358,15 @@ static int do_stm32key_close(struct cmd_tbl *cmdtp, int flag, int argc, char *co }
/* check PKH status before to close */ - ret = read_hash_otp(dev, !yes, &lock); + key = get_key(STM32KEY_PKH); + ret = read_key_otp(dev, key, !yes, &lock); if (ret) { if (ret == -ENOENT) - printf("Error: OTP not programmed!\n"); + printf("Error: %s not programmed!\n", key->name); return CMD_RET_FAILURE; } if (!lock) - printf("Warning: OTP not locked!\n"); + printf("Warning: %s not locked!\n", key->name);
if (!yes && !confirm_prog()) return CMD_RET_FAILURE; @@ -275,7 +374,7 @@ static int do_stm32key_close(struct cmd_tbl *cmdtp, int flag, int argc, char *co val = STM32_OTP_CLOSE_MASK; ret = misc_write(dev, STM32_BSEC_OTP(STM32_OTP_CLOSE_ID), &val, 4); if (ret != 4) { - printf("Error: can't update OTP\n"); + printf("Error: can't update OTP %d\n", STM32_OTP_CLOSE_ID); return CMD_RET_FAILURE; }
@@ -285,11 +384,15 @@ static int do_stm32key_close(struct cmd_tbl *cmdtp, int flag, int argc, char *co }
static char stm32key_help_text[] = - "read [<addr>]: Read the hash stored at addr in memory or in OTP\n" - "stm32key fuse [-y] <addr> : Fuse hash stored at addr in OTP\n" - "stm32key close [-y] : Close the device, the hash stored in OTP\n"; - -U_BOOT_CMD_WITH_SUBCMDS(stm32key, "Fuse ST Hash key", stm32key_help_text, + "list : list the supported key with description\n" + "stm32key select [<key>] : Select the key identified by <key> or display the key used for read/fuse command\n" + "stm32key read [<addr> | -a ] : Read the curent key at <addr> or current / all (-a) key in OTP\n" + "stm32key fuse [-y] <addr> : Fuse the current key at addr in OTP\n" + "stm32key close [-y] : Close the device\n"; + +U_BOOT_CMD_WITH_SUBCMDS(stm32key, "Manage key on STM32", stm32key_help_text, + U_BOOT_SUBCMD_MKENT(list, 1, 0, do_stm32key_list), + U_BOOT_SUBCMD_MKENT(select, 2, 0, do_stm32key_select), U_BOOT_SUBCMD_MKENT(read, 2, 0, do_stm32key_read), U_BOOT_SUBCMD_MKENT(fuse, 3, 0, do_stm32key_fuse), U_BOOT_SUBCMD_MKENT(close, 2, 0, do_stm32key_close));

HI Patrick
On 9/15/22 18:11, Patrick Delaunay wrote:
Update the command stm32key to support several keys selected by key name and managed by the new sub-command:
stm32key list stm32key select [<key>] stm32key read -a
This patch doesn't change the STM32MP15 behavior, only PKH is supported, but it is a preliminary patch for STM32MP13 support.
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com
arch/arm/mach-stm32mp/cmd_stm32key.c | 195 ++++++++++++++++++++------- 1 file changed, 149 insertions(+), 46 deletions(-)
diff --git a/arch/arm/mach-stm32mp/cmd_stm32key.c b/arch/arm/mach-stm32mp/cmd_stm32key.c index 68f9b1a9a59..4eac56082db 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32key.c +++ b/arch/arm/mach-stm32mp/cmd_stm32key.c @@ -15,9 +15,37 @@ #define STM32_OTP_CLOSE_ID 0 #define STM32_OTP_CLOSE_MASK BIT(6)
-/* HASH of key: 8 OTPs, starting with OTP24) */ -#define STM32_OTP_HASH_KEY_START 24 -#define STM32_OTP_HASH_KEY_SIZE 8 +/* PKH is the first element of the key list */ +#define STM32KEY_PKH 0
+struct stm32key {
- char *name;
- char *desc;
- u8 start;
- u8 size;
+};
+const struct stm32key stm32mp15_list[] = {
- [STM32KEY_PKH] = {
.name = "PKH",
.desc = "Hash of the ECC Public Key (ECDSA is the authentication algorithm)",
.start = 24,
.size = 8,
- }
+};
+/* index of current selected key in stm32key list, 0 = PKH by default */ +static u8 stm32key_index;
+static u8 get_key_nb(void) +{
- return ARRAY_SIZE(stm32mp15_list);
+}
+static const struct stm32key *get_key(u8 index) +{
- return &stm32mp15_list[index];
+}
#define BSEC_LOCK_ERROR (-1) #define BSEC_LOCK_PERM BIT(0) @@ -33,26 +61,25 @@ static int get_misc_dev(struct udevice **dev) return ret; }
-static void read_hash_value(u32 addr) +static void read_key_value(const struct stm32key *key, u32 addr) { int i;
- printf("Read KEY at 0x%x\n", addr);
- for (i = 0; i < STM32_OTP_HASH_KEY_SIZE; i++) {
printf("OTP value %i: %x\n", STM32_OTP_HASH_KEY_START + i,
__be32_to_cpu(*(u32 *)addr));
- for (i = 0; i < key->size; i++) {
printf("%s OTP %i: [%08x] %08x\n", key->name, key->start + i,
addr += 4; }addr, __be32_to_cpu(*(u32 *)addr));
}
-static int read_hash_otp(struct udevice *dev, bool print, bool *locked) +static int read_key_otp(struct udevice *dev, const struct stm32key *key, bool print, bool *locked) { int i, word, ret;
- int nb_invalid = 0, nb_zero = 0, nb_lock = 0;
- int nb_invalid = 0, nb_zero = 0, nb_lock = 0, nb_lock_err = 0; u32 val, lock; bool status;
- for (i = 0, word = STM32_OTP_HASH_KEY_START; i < STM32_OTP_HASH_KEY_SIZE; i++, word++) {
- for (i = 0, word = key->start; i < key->size; i++, word++) { ret = misc_read(dev, STM32_BSEC_OTP(word), &val, 4); if (ret != 4) val = ~0x0;
@@ -60,29 +87,33 @@ static int read_hash_otp(struct udevice *dev, bool print, bool *locked) if (ret != 4) lock = BSEC_LOCK_ERROR; if (print)
printf("OTP HASH %i: %x lock : %x\n", word, val, lock);
if (val == ~0x0) nb_invalid++; else if (val == 0x0) nb_zero++; if (lock & BSEC_LOCK_PERM) nb_lock++;printf("%s OTP %i: %08x lock : %08x\n", key->name, word, val, lock);
if (lock & BSEC_LOCK_ERROR)
}nb_lock_err++;
- status = (nb_lock == STM32_OTP_HASH_KEY_SIZE);
- status = nb_lock_err || (nb_lock == key->size); if (locked) *locked = status;
- if (!status && print)
printf("Hash of key is not locked!\n");
- if (nb_lock_err && print)
printf("%s lock is invalid!\n", key->name);
- else if (!status && print)
printf("%s is not locked!\n", key->name);
- if (nb_invalid == STM32_OTP_HASH_KEY_SIZE) {
- if (nb_invalid == key->size) { if (print)
printf("Hash of key is invalid!\n");
return -EINVAL; }printf("%s is invalid!\n", key->name);
- if (nb_zero == STM32_OTP_HASH_KEY_SIZE) {
- if (nb_zero == key->size) { if (print)
printf("Hash of key is free!\n");
return -ENOENT; }printf("%s is free!\n", key->name);
@@ -113,33 +144,31 @@ static int read_close_status(struct udevice *dev, bool print, bool *closed) if (closed) *closed = status; if (print)
printf("OTP %d: closed status: %d lock : %x\n", word, status, lock);
printf("OTP %d: closed status: %d lock : %08x\n", word, status, lock);
return result;
}
-static int fuse_hash_value(struct udevice *dev, u32 addr, bool print) +static int fuse_key_value(struct udevice *dev, const struct stm32key *key, u32 addr, bool print) { u32 word, val; int i, ret;
- for (i = 0, word = STM32_OTP_HASH_KEY_START;
i < STM32_OTP_HASH_KEY_SIZE;
i++, word++, addr += 4) {
- for (i = 0, word = key->start; i < key->size; i++, word++, addr += 4) { val = __be32_to_cpu(*(u32 *)addr); if (print)
printf("Fuse OTP %i : %x\n", word, val);
printf("Fuse %s OTP %i : %08x\n", key->name, word, val);
ret = misc_write(dev, STM32_BSEC_OTP(word), &val, 4); if (ret != 4) {
log_err("Fuse OTP %i failed\n", word);
}log_err("Fuse %s OTP %i failed\n", key->name, word); return ret;
/* on success, lock the OTP for HASH key */
val = BSEC_LOCK_PERM; ret = misc_write(dev, STM32_BSEC_LOCK(word), &val, 4); if (ret != 4) {/* on success, lock the OTP for the key */
log_err("Lock OTP %i failed\n", word);
} }log_err("Lock %s OTP %i failed\n", key->name, word); return ret;
@@ -161,36 +190,99 @@ static int confirm_prog(void) return 0; }
+static void display_key_info(const struct stm32key *key) +{
- printf("%s : %s\n", key->name, key->desc);
- printf("\tOTP%d..%d\n", key->start, key->start + key->size);
+}
+static int do_stm32key_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{
- int i;
- for (i = 0; i < get_key_nb(); i++)
display_key_info(get_key(i));
- return CMD_RET_SUCCESS;
+}
+static int do_stm32key_select(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{
- const struct stm32key *key;
- int i;
- if (argc == 1) {
printf("Selected key:\n");
key = get_key(stm32key_index);
display_key_info(key);
return CMD_RET_SUCCESS;
- }
- for (i = 0; i < get_key_nb(); i++) {
key = get_key(i);
if (!strcmp(key->name, argv[1])) {
printf("%s selected\n", key->name);
stm32key_index = i;
return CMD_RET_SUCCESS;
}
- }
- printf("Unknown key %s\n", argv[1]);
- return CMD_RET_FAILURE;
+}
static int do_stm32key_read(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) {
- const struct stm32key *key; struct udevice *dev; u32 addr;
- int ret;
int ret, i;
int result;
ret = get_misc_dev(&dev);
if (argc == 1) { if (ret) return CMD_RET_FAILURE;
read_hash_otp(dev, true, NULL);
ret = read_close_status(dev, true, NULL);
key = get_key(stm32key_index);
ret = read_key_otp(dev, key, true, NULL);
if (ret != -ENOENT)
return CMD_RET_FAILURE;
return CMD_RET_SUCCESS;
- }
- if (!strcmp("-a", argv[1])) { if (ret) return CMD_RET_FAILURE;
result = CMD_RET_SUCCESS;
for (i = 0; i < get_key_nb(); i++) {
key = get_key(i);
ret = read_key_otp(dev, key, true, NULL);
if (ret != -ENOENT)
result = CMD_RET_FAILURE;
}
ret = read_close_status(dev, true, NULL);
if (ret)
result = CMD_RET_FAILURE;
return CMD_RET_SUCCESS;
return result;
}
addr = hextoul(argv[1], NULL); if (!addr) return CMD_RET_USAGE;
- read_hash_value(addr);
key = get_key(stm32key_index);
printf("Read %s at 0x%08x\n", key->name, addr);
read_key_value(key, addr);
return CMD_RET_SUCCESS;
}
static int do_stm32key_fuse(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) {
- const struct stm32key *key = get_key(stm32key_index); struct udevice *dev; u32 addr; int ret;
@@ -213,28 +305,34 @@ static int do_stm32key_fuse(struct cmd_tbl *cmdtp, int flag, int argc, char *con if (ret) return CMD_RET_FAILURE;
- if (read_hash_otp(dev, !yes, &lock) != -ENOENT) {
- if (read_key_otp(dev, key, !yes, &lock) != -ENOENT) { printf("Error: can't fuse again the OTP\n"); return CMD_RET_FAILURE; } if (lock) {
printf("Error: PKH is locked\n");
printf("Error: %s is locked\n", key->name);
return CMD_RET_FAILURE; }
if (!yes) {
printf("Writing %s with\n", key->name);
read_key_value(key, addr);
}
if (!yes && !confirm_prog()) return CMD_RET_FAILURE;
- if (fuse_hash_value(dev, addr, !yes))
- if (fuse_key_value(dev, key, addr, !yes)) return CMD_RET_FAILURE;
- printf("Hash key updated !\n");
printf("%s updated !\n", key->name);
return CMD_RET_SUCCESS;
}
static int do_stm32key_close(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) {
- const struct stm32key *key; bool yes, lock, closed; struct udevice *dev; u32 val;
@@ -260,14 +358,15 @@ static int do_stm32key_close(struct cmd_tbl *cmdtp, int flag, int argc, char *co }
/* check PKH status before to close */
- ret = read_hash_otp(dev, !yes, &lock);
- key = get_key(STM32KEY_PKH);
- ret = read_key_otp(dev, key, !yes, &lock); if (ret) { if (ret == -ENOENT)
printf("Error: OTP not programmed!\n");
return CMD_RET_FAILURE; } if (!lock)printf("Error: %s not programmed!\n", key->name);
printf("Warning: OTP not locked!\n");
printf("Warning: %s not locked!\n", key->name);
if (!yes && !confirm_prog()) return CMD_RET_FAILURE;
@@ -275,7 +374,7 @@ static int do_stm32key_close(struct cmd_tbl *cmdtp, int flag, int argc, char *co val = STM32_OTP_CLOSE_MASK; ret = misc_write(dev, STM32_BSEC_OTP(STM32_OTP_CLOSE_ID), &val, 4); if (ret != 4) {
printf("Error: can't update OTP\n");
return CMD_RET_FAILURE; }printf("Error: can't update OTP %d\n", STM32_OTP_CLOSE_ID);
@@ -285,11 +384,15 @@ static int do_stm32key_close(struct cmd_tbl *cmdtp, int flag, int argc, char *co }
static char stm32key_help_text[] =
- "read [<addr>]: Read the hash stored at addr in memory or in OTP\n"
- "stm32key fuse [-y] <addr> : Fuse hash stored at addr in OTP\n"
- "stm32key close [-y] : Close the device, the hash stored in OTP\n";
-U_BOOT_CMD_WITH_SUBCMDS(stm32key, "Fuse ST Hash key", stm32key_help_text,
- "list : list the supported key with description\n"
- "stm32key select [<key>] : Select the key identified by <key> or display the key used for read/fuse command\n"
- "stm32key read [<addr> | -a ] : Read the curent key at <addr> or current / all (-a) key in OTP\n"
- "stm32key fuse [-y] <addr> : Fuse the current key at addr in OTP\n"
- "stm32key close [-y] : Close the device\n";
+U_BOOT_CMD_WITH_SUBCMDS(stm32key, "Manage key on STM32", stm32key_help_text,
- U_BOOT_SUBCMD_MKENT(list, 1, 0, do_stm32key_list),
- U_BOOT_SUBCMD_MKENT(select, 2, 0, do_stm32key_select), U_BOOT_SUBCMD_MKENT(read, 2, 0, do_stm32key_read), U_BOOT_SUBCMD_MKENT(fuse, 3, 0, do_stm32key_fuse), U_BOOT_SUBCMD_MKENT(close, 2, 0, do_stm32key_close));
Reviewed-by: Patrice Chotard patrice.chotard@foss.st.com
Thanks Patrice

Change the mask of OTP0 used to close the device on STM32MP - STM32MP15x: bit 6 of OPT0 - STM32MP13x: 0b111111 = 0x3F for OTP_SECURED closed device
And support the 2 keys for STM32MP13x - PKHTH : Hash of the 8 ECC Public Keys Hashes Table (ECDSA is the authentication algorithm) - EDMK : Encryption/Decryption Master Key
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com ---
arch/arm/mach-stm32mp/cmd_stm32key.c | 52 ++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 7 deletions(-)
diff --git a/arch/arm/mach-stm32mp/cmd_stm32key.c b/arch/arm/mach-stm32mp/cmd_stm32key.c index 4eac56082db..278253e472f 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32key.c +++ b/arch/arm/mach-stm32mp/cmd_stm32key.c @@ -11,9 +11,14 @@ #include <dm/device.h> #include <dm/uclass.h>
-/* Closed device : bit 6 of OPT0*/ +/* + * Closed device: OTP0 + * STM32MP15x: bit 6 of OPT0 + * STM32MP13x: 0b111111 = 0x3F for OTP_SECURED closed device + */ #define STM32_OTP_CLOSE_ID 0 -#define STM32_OTP_CLOSE_MASK BIT(6) +#define STM32_OTP_STM32MP13x_CLOSE_MASK 0x3F +#define STM32_OTP_STM32MP15x_CLOSE_MASK BIT(6)
/* PKH is the first element of the key list */ #define STM32KEY_PKH 0 @@ -25,6 +30,21 @@ struct stm32key { u8 size; };
+const struct stm32key stm32mp13_list[] = { + [STM32KEY_PKH] = { + .name = "PKHTH", + .desc = "Hash of the 8 ECC Public Keys Hashes Table (ECDSA is the authentication algorithm)", + .start = 24, + .size = 8, + }, + { + .name = "EDMK", + .desc = "Encryption/Decryption Master Key", + .start = 92, + .size = 4, + } +}; + const struct stm32key stm32mp15_list[] = { [STM32KEY_PKH] = { .name = "PKH", @@ -39,12 +59,29 @@ static u8 stm32key_index;
static u8 get_key_nb(void) { - return ARRAY_SIZE(stm32mp15_list); + if (IS_ENABLED(CONFIG_STM32MP13x)) + return ARRAY_SIZE(stm32mp13_list); + + if (IS_ENABLED(CONFIG_STM32MP15x)) + return ARRAY_SIZE(stm32mp15_list); }
static const struct stm32key *get_key(u8 index) { - return &stm32mp15_list[index]; + if (IS_ENABLED(CONFIG_STM32MP13x)) + return &stm32mp13_list[index]; + + if (IS_ENABLED(CONFIG_STM32MP15x)) + return &stm32mp15_list[index]; +} + +static u32 get_otp_close_mask(void) +{ + if (IS_ENABLED(CONFIG_STM32MP13x)) + return STM32_OTP_STM32MP13x_CLOSE_MASK; + + if (IS_ENABLED(CONFIG_STM32MP15x)) + return STM32_OTP_STM32MP15x_CLOSE_MASK; }
#define BSEC_LOCK_ERROR (-1) @@ -123,7 +160,7 @@ static int read_key_otp(struct udevice *dev, const struct stm32key *key, bool pr static int read_close_status(struct udevice *dev, bool print, bool *closed) { int word, ret, result; - u32 val, lock; + u32 val, lock, mask; bool status;
result = 0; @@ -140,7 +177,8 @@ static int read_close_status(struct udevice *dev, bool print, bool *closed) if (ret != 4) lock = BSEC_LOCK_ERROR;
- status = (val & STM32_OTP_CLOSE_MASK) == STM32_OTP_CLOSE_MASK; + mask = get_otp_close_mask(); + status = (val & mask) == mask; if (closed) *closed = status; if (print) @@ -371,7 +409,7 @@ static int do_stm32key_close(struct cmd_tbl *cmdtp, int flag, int argc, char *co if (!yes && !confirm_prog()) return CMD_RET_FAILURE;
- val = STM32_OTP_CLOSE_MASK; + val = get_otp_close_mask(); ret = misc_write(dev, STM32_BSEC_OTP(STM32_OTP_CLOSE_ID), &val, 4); if (ret != 4) { printf("Error: can't update OTP %d\n", STM32_OTP_CLOSE_ID);

HI Patrick
On 9/15/22 18:11, Patrick Delaunay wrote:
Change the mask of OTP0 used to close the device on STM32MP
- STM32MP15x: bit 6 of OPT0
- STM32MP13x: 0b111111 = 0x3F for OTP_SECURED closed device
And support the 2 keys for STM32MP13x
- PKHTH : Hash of the 8 ECC Public Keys Hashes Table (ECDSA is the authentication algorithm)
- EDMK : Encryption/Decryption Master Key
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com
arch/arm/mach-stm32mp/cmd_stm32key.c | 52 ++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 7 deletions(-)
diff --git a/arch/arm/mach-stm32mp/cmd_stm32key.c b/arch/arm/mach-stm32mp/cmd_stm32key.c index 4eac56082db..278253e472f 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32key.c +++ b/arch/arm/mach-stm32mp/cmd_stm32key.c @@ -11,9 +11,14 @@ #include <dm/device.h> #include <dm/uclass.h>
-/* Closed device : bit 6 of OPT0*/ +/*
- Closed device: OTP0
- STM32MP15x: bit 6 of OPT0
- STM32MP13x: 0b111111 = 0x3F for OTP_SECURED closed device
- */
#define STM32_OTP_CLOSE_ID 0 -#define STM32_OTP_CLOSE_MASK BIT(6) +#define STM32_OTP_STM32MP13x_CLOSE_MASK 0x3F +#define STM32_OTP_STM32MP15x_CLOSE_MASK BIT(6)
/* PKH is the first element of the key list */ #define STM32KEY_PKH 0 @@ -25,6 +30,21 @@ struct stm32key { u8 size; };
+const struct stm32key stm32mp13_list[] = {
- [STM32KEY_PKH] = {
.name = "PKHTH",
.desc = "Hash of the 8 ECC Public Keys Hashes Table (ECDSA is the authentication algorithm)",
.start = 24,
.size = 8,
- },
- {
.name = "EDMK",
.desc = "Encryption/Decryption Master Key",
.start = 92,
.size = 4,
- }
+};
const struct stm32key stm32mp15_list[] = { [STM32KEY_PKH] = { .name = "PKH", @@ -39,12 +59,29 @@ static u8 stm32key_index;
static u8 get_key_nb(void) {
- return ARRAY_SIZE(stm32mp15_list);
- if (IS_ENABLED(CONFIG_STM32MP13x))
return ARRAY_SIZE(stm32mp13_list);
- if (IS_ENABLED(CONFIG_STM32MP15x))
return ARRAY_SIZE(stm32mp15_list);
}
static const struct stm32key *get_key(u8 index) {
- return &stm32mp15_list[index];
- if (IS_ENABLED(CONFIG_STM32MP13x))
return &stm32mp13_list[index];
- if (IS_ENABLED(CONFIG_STM32MP15x))
return &stm32mp15_list[index];
+}
+static u32 get_otp_close_mask(void) +{
- if (IS_ENABLED(CONFIG_STM32MP13x))
return STM32_OTP_STM32MP13x_CLOSE_MASK;
- if (IS_ENABLED(CONFIG_STM32MP15x))
return STM32_OTP_STM32MP15x_CLOSE_MASK;
}
#define BSEC_LOCK_ERROR (-1) @@ -123,7 +160,7 @@ static int read_key_otp(struct udevice *dev, const struct stm32key *key, bool pr static int read_close_status(struct udevice *dev, bool print, bool *closed) { int word, ret, result;
- u32 val, lock;
u32 val, lock, mask; bool status;
result = 0;
@@ -140,7 +177,8 @@ static int read_close_status(struct udevice *dev, bool print, bool *closed) if (ret != 4) lock = BSEC_LOCK_ERROR;
- status = (val & STM32_OTP_CLOSE_MASK) == STM32_OTP_CLOSE_MASK;
- mask = get_otp_close_mask();
- status = (val & mask) == mask; if (closed) *closed = status; if (print)
@@ -371,7 +409,7 @@ static int do_stm32key_close(struct cmd_tbl *cmdtp, int flag, int argc, char *co if (!yes && !confirm_prog()) return CMD_RET_FAILURE;
- val = STM32_OTP_CLOSE_MASK;
- val = get_otp_close_mask(); ret = misc_write(dev, STM32_BSEC_OTP(STM32_OTP_CLOSE_ID), &val, 4); if (ret != 4) { printf("Error: can't update OTP %d\n", STM32_OTP_CLOSE_ID);
Reviewed-by: Patrice Chotard patrice.chotard@foss.st.com
Thanks Patrice

Hi Patrick
On 9/15/22 18:11, Patrick Delaunay wrote:
And support the 2 keys for STM32MP13x
- PKHTH : Hash of the 8 ECC Public Keys Hashes Table (ECDSA is the authentication algorithm)
- EDMK : Encryption/Decryption Master Key
Only one key is supported for STM32MP15x
- PKH : Hash of the ECC Public Key (ECDSA is the authentication algorithm)
This STM32KEY command is used in STM32MP SoCs to provision the keys in the correct OTP needed to activate secure boot features: authentication and encryption.
See [1] for details
[1] STM32 MPU wiki https://wiki.st.com/stm32mpu/wiki/How_to_use_U-Boot_stm32key_command
Patrick Delaunay (4): arm: stm32mp: add defines for BSEC_LOCK status in stm32key command arm: stm32mp: introduced read_close_status function in stm32key command arm: stm32mp: support several key in command stm32key arm: stm32mp: adapt the command stm32key for STM32MP13x
arch/arm/mach-stm32mp/cmd_stm32key.c | 331 ++++++++++++++++++++------- 1 file changed, 249 insertions(+), 82 deletions(-)
For the series:
Applied on u-boot-stm32/next
Thanks Patrice
participants (2)
-
Patrice CHOTARD
-
Patrick Delaunay