All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] arm: stm32mp: adapt the command stm32key for STM32MP13x
@ 2022-09-15 16:11 Patrick Delaunay
  2022-09-15 16:11 ` [PATCH 1/4] arm: stm32mp: add defines for BSEC_LOCK status in stm32key command Patrick Delaunay
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Patrick Delaunay @ 2022-09-15 16:11 UTC (permalink / raw)
  To: u-boot; +Cc: Patrick Delaunay, Patrice Chotard, Tom Rini, U-Boot STM32


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(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/4] arm: stm32mp: add defines for BSEC_LOCK status in stm32key command
  2022-09-15 16:11 [PATCH 0/4] arm: stm32mp: adapt the command stm32key for STM32MP13x Patrick Delaunay
@ 2022-09-15 16:11 ` Patrick Delaunay
  2022-09-19  6:52   ` Patrice CHOTARD
  2022-09-15 16:11 ` [PATCH 2/4] arm: stm32mp: introduced read_close_status function " Patrick Delaunay
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Patrick Delaunay @ 2022-09-15 16:11 UTC (permalink / raw)
  To: u-boot; +Cc: Patrick Delaunay, Patrice Chotard, Tom Rini, U-Boot STM32

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);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/4] arm: stm32mp: introduced read_close_status function in stm32key command
  2022-09-15 16:11 [PATCH 0/4] arm: stm32mp: adapt the command stm32key for STM32MP13x Patrick Delaunay
  2022-09-15 16:11 ` [PATCH 1/4] arm: stm32mp: add defines for BSEC_LOCK status in stm32key command Patrick Delaunay
@ 2022-09-15 16:11 ` Patrick Delaunay
  2022-09-19  6:52   ` Patrice CHOTARD
  2022-09-15 16:11 ` [PATCH 3/4] arm: stm32mp: support several key in command stm32key Patrick Delaunay
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Patrick Delaunay @ 2022-09-15 16:11 UTC (permalink / raw)
  To: u-boot; +Cc: Patrick Delaunay, Patrice Chotard, Tom Rini, U-Boot STM32

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) {
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/4] arm: stm32mp: support several key in command stm32key
  2022-09-15 16:11 [PATCH 0/4] arm: stm32mp: adapt the command stm32key for STM32MP13x Patrick Delaunay
  2022-09-15 16:11 ` [PATCH 1/4] arm: stm32mp: add defines for BSEC_LOCK status in stm32key command Patrick Delaunay
  2022-09-15 16:11 ` [PATCH 2/4] arm: stm32mp: introduced read_close_status function " Patrick Delaunay
@ 2022-09-15 16:11 ` Patrick Delaunay
  2022-09-19  6:52   ` Patrice CHOTARD
  2022-09-15 16:11 ` [PATCH 4/4] arm: stm32mp: adapt the command stm32key for STM32MP13x Patrick Delaunay
  2022-09-23 12:32 ` [PATCH 0/4] " Patrice CHOTARD
  4 siblings, 1 reply; 10+ messages in thread
From: Patrick Delaunay @ 2022-09-15 16:11 UTC (permalink / raw)
  To: u-boot; +Cc: Patrick Delaunay, Patrice Chotard, Tom Rini, U-Boot STM32

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));
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/4] arm: stm32mp: adapt the command stm32key for STM32MP13x
  2022-09-15 16:11 [PATCH 0/4] arm: stm32mp: adapt the command stm32key for STM32MP13x Patrick Delaunay
                   ` (2 preceding siblings ...)
  2022-09-15 16:11 ` [PATCH 3/4] arm: stm32mp: support several key in command stm32key Patrick Delaunay
@ 2022-09-15 16:11 ` Patrick Delaunay
  2022-09-19  6:53   ` Patrice CHOTARD
  2022-09-23 12:32 ` [PATCH 0/4] " Patrice CHOTARD
  4 siblings, 1 reply; 10+ messages in thread
From: Patrick Delaunay @ 2022-09-15 16:11 UTC (permalink / raw)
  To: u-boot; +Cc: Patrick Delaunay, Patrice Chotard, Tom Rini, U-Boot STM32

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);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/4] arm: stm32mp: add defines for BSEC_LOCK status in stm32key command
  2022-09-15 16:11 ` [PATCH 1/4] arm: stm32mp: add defines for BSEC_LOCK status in stm32key command Patrick Delaunay
@ 2022-09-19  6:52   ` Patrice CHOTARD
  0 siblings, 0 replies; 10+ messages in thread
From: Patrice CHOTARD @ 2022-09-19  6:52 UTC (permalink / raw)
  To: Patrick Delaunay, u-boot; +Cc: Tom Rini, U-Boot STM32

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;
> +			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);
Reviewed-by: Patrice Chotard <patrice.chotard@foss.st.com>

Thanks
Patrice

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/4] arm: stm32mp: introduced read_close_status function in stm32key command
  2022-09-15 16:11 ` [PATCH 2/4] arm: stm32mp: introduced read_close_status function " Patrick Delaunay
@ 2022-09-19  6:52   ` Patrice CHOTARD
  0 siblings, 0 replies; 10+ messages in thread
From: Patrice CHOTARD @ 2022-09-19  6:52 UTC (permalink / raw)
  To: Patrick Delaunay, u-boot; +Cc: Tom Rini, U-Boot STM32

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/4] arm: stm32mp: support several key in command stm32key
  2022-09-15 16:11 ` [PATCH 3/4] arm: stm32mp: support several key in command stm32key Patrick Delaunay
@ 2022-09-19  6:52   ` Patrice CHOTARD
  0 siblings, 0 replies; 10+ messages in thread
From: Patrice CHOTARD @ 2022-09-19  6:52 UTC (permalink / raw)
  To: Patrick Delaunay, u-boot; +Cc: Tom Rini, U-Boot STM32

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, __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));
Reviewed-by: Patrice Chotard <patrice.chotard@foss.st.com>

Thanks
Patrice

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/4] arm: stm32mp: adapt the command stm32key for STM32MP13x
  2022-09-15 16:11 ` [PATCH 4/4] arm: stm32mp: adapt the command stm32key for STM32MP13x Patrick Delaunay
@ 2022-09-19  6:53   ` Patrice CHOTARD
  0 siblings, 0 replies; 10+ messages in thread
From: Patrice CHOTARD @ 2022-09-19  6:53 UTC (permalink / raw)
  To: Patrick Delaunay, u-boot; +Cc: Tom Rini, U-Boot STM32

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/4] arm: stm32mp: adapt the command stm32key for STM32MP13x
  2022-09-15 16:11 [PATCH 0/4] arm: stm32mp: adapt the command stm32key for STM32MP13x Patrick Delaunay
                   ` (3 preceding siblings ...)
  2022-09-15 16:11 ` [PATCH 4/4] arm: stm32mp: adapt the command stm32key for STM32MP13x Patrick Delaunay
@ 2022-09-23 12:32 ` Patrice CHOTARD
  4 siblings, 0 replies; 10+ messages in thread
From: Patrice CHOTARD @ 2022-09-23 12:32 UTC (permalink / raw)
  To: Patrick Delaunay, u-boot; +Cc: Tom Rini, U-Boot STM32

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2022-09-23 12:32 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-15 16:11 [PATCH 0/4] arm: stm32mp: adapt the command stm32key for STM32MP13x Patrick Delaunay
2022-09-15 16:11 ` [PATCH 1/4] arm: stm32mp: add defines for BSEC_LOCK status in stm32key command Patrick Delaunay
2022-09-19  6:52   ` Patrice CHOTARD
2022-09-15 16:11 ` [PATCH 2/4] arm: stm32mp: introduced read_close_status function " Patrick Delaunay
2022-09-19  6:52   ` Patrice CHOTARD
2022-09-15 16:11 ` [PATCH 3/4] arm: stm32mp: support several key in command stm32key Patrick Delaunay
2022-09-19  6:52   ` Patrice CHOTARD
2022-09-15 16:11 ` [PATCH 4/4] arm: stm32mp: adapt the command stm32key for STM32MP13x Patrick Delaunay
2022-09-19  6:53   ` Patrice CHOTARD
2022-09-23 12:32 ` [PATCH 0/4] " Patrice CHOTARD

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.