Merge changes If9672598,I219c49d3 into integration

* changes:
  feat(cert-create): add pkcs11 engine support
  fix(cert-create): key: Avoid having a temporary value for pkey in key_load
diff --git a/docs/design/trusted-board-boot.rst b/docs/design/trusted-board-boot.rst
index 46177d7..fed202a 100644
--- a/docs/design/trusted-board-boot.rst
+++ b/docs/design/trusted-board-boot.rst
@@ -216,10 +216,11 @@
 
 The ``cert_create`` tool is built and runs on the host machine as part of the
 TF-A build process when ``GENERATE_COT=1``. It takes the boot loader images
-and keys as inputs (keys must be in PEM format) and generates the
-certificates (in DER format) required to establish the CoT. New keys can be
-generated by the tool in case they are not provided. The certificates are then
-passed as inputs to the ``fiptool`` utility for creating the FIP.
+and keys as inputs and generates the certificates (in DER format) required to
+establish the CoT. The input keys must either be a file in PEM format or a
+PKCS11 URI in case a HSM is used. New keys can be generated by the tool in
+case they are not provided. The certificates are then passed as inputs to
+the ``fiptool`` utility for creating the FIP.
 
 The certificates are also stored individually in the output build directory.
 
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 2c018c3..1da2738 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -80,9 +80,9 @@
    BL31 image for the ``fip`` target. In this case, the BL31 in TF-A will not
    be built.
 
--  ``BL31_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the
-   file that contains the BL31 private key in PEM format. If ``SAVE_KEYS=1``,
-   this file name will be used to save the key.
+-  ``BL31_KEY``: This option is used when ``GENERATE_COT=1``. It specifies a
+   file that contains the BL31 private key in PEM format or a PKCS11 URI. If
+   ``SAVE_KEYS=1``, only a file is accepted and it will be used to save the key.
 
 -  ``BL32``: This is an optional build option which specifies the path to
    BL32 image for the ``fip`` target. In this case, the BL32 in TF-A will not
@@ -94,16 +94,16 @@
 -  ``BL32_EXTRA2``: This is an optional build option which specifies the path to
    Trusted OS Extra2 image for the ``fip`` target.
 
--  ``BL32_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the
-   file that contains the BL32 private key in PEM format. If ``SAVE_KEYS=1``,
-   this file name will be used to save the key.
+-  ``BL32_KEY``: This option is used when ``GENERATE_COT=1``. It specifies a
+   file that contains the BL32 private key in PEM format or a PKCS11 URI. If
+   ``SAVE_KEYS=1``, only a file is accepted and it will be used to save the key.
 
 -  ``BL33``: Path to BL33 image in the host file system. This is mandatory for
    ``fip`` target in case TF-A BL2 is used.
 
--  ``BL33_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the
-   file that contains the BL33 private key in PEM format. If ``SAVE_KEYS=1``,
-   this file name will be used to save the key.
+-  ``BL33_KEY``: This option is used when ``GENERATE_COT=1``. It specifies a
+   file that contains the BL33 private key in PEM format or a PKCS11 URI. If
+   ``SAVE_KEYS=1``, only a file is accepted and it will be used to save the key.
 
 -  ``BRANCH_PROTECTION``: Numeric value to enable ARMv8.3 Pointer Authentication
    and ARMv8.5 Branch Target Identification support for TF-A BL images themselves.
@@ -749,8 +749,9 @@
       MARCH_DIRECTIVE := -march=armv8.5-a
 
 -  ``NON_TRUSTED_WORLD_KEY``: This option is used when ``GENERATE_COT=1``. It
-   specifies the file that contains the Non-Trusted World private key in PEM
-   format. If ``SAVE_KEYS=1``, this file name will be used to save the key.
+   specifies a file that contains the Non-Trusted World private key in PEM
+   format or a PKCS11 URI. If ``SAVE_KEYS=1``, only a file is accepted and it
+   will be used to save the key.
 
 -  ``NS_BL2U``: Path to NS_BL2U image in the host file system. This image is
    optional. It is only needed if the platform makefile specifies that it
@@ -827,10 +828,10 @@
    instead of the BL1 entrypoint. It can take the value 0 (CPU reset to BL1
    entrypoint) or 1 (CPU reset to SP_MIN entrypoint). The default value is 0.
 
--  ``ROT_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the
-   file that contains the ROT private key in PEM format and enforces public key
-   hash generation. If ``SAVE_KEYS=1``, this
-   file name will be used to save the key.
+-  ``ROT_KEY``: This option is used when ``GENERATE_COT=1``. It specifies a
+   file that contains the ROT private key in PEM format or a PKCS11 URI and
+   enforces public key hash generation. If ``SAVE_KEYS=1``, only a file is
+   accepted and it will be used to save the key.
 
 -  ``SAVE_KEYS``: This option is used when ``GENERATE_COT=1``. It tells the
    certificate generation tool to save the keys used to establish the Chain of
@@ -840,9 +841,9 @@
    If a SCP_BL2 image is present then this option must be passed for the ``fip``
    target.
 
--  ``SCP_BL2_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the
-   file that contains the SCP_BL2 private key in PEM format. If ``SAVE_KEYS=1``,
-   this file name will be used to save the key.
+-  ``SCP_BL2_KEY``: This option is used when ``GENERATE_COT=1``. It specifies a
+   file that contains the SCP_BL2 private key in PEM format or a PKCS11 URI.
+   If ``SAVE_KEYS=1``, only a file is accepted and it will be used to save the key.
 
 -  ``SCP_BL2U``: Path to SCP_BL2U image in the host file system. This image is
    optional. It is only needed if the platform makefile specifies that it
@@ -959,8 +960,9 @@
       already exist in disk, they will be overwritten without further notice.
 
 -  ``TRUSTED_WORLD_KEY``: This option is used when ``GENERATE_COT=1``. It
-   specifies the file that contains the Trusted World private key in PEM
-   format. If ``SAVE_KEYS=1``, this file name will be used to save the key.
+   specifies a file that contains the Trusted World private key in PEM
+   format or a PKCS11 URI. If ``SAVE_KEYS=1``, only a file is accepted and
+   it will be used to save the key.
 
 -  ``TSP_INIT_ASYNC``: Choose BL32 initialization method as asynchronous or
    synchronous, (see "Initializing a BL32 Image" section in
diff --git a/tools/cert_create/src/cca/cot.c b/tools/cert_create/src/cca/cot.c
index e39b036..372d908 100644
--- a/tools/cert_create/src/cca/cot.c
+++ b/tools/cert_create/src/cca/cot.c
@@ -414,35 +414,35 @@
 	[ROT_KEY] = {
 		.id = ROT_KEY,
 		.opt = "rot-key",
-		.help_msg = "Root Of Trust key (input/output file)",
+		.help_msg = "Root Of Trust key file or PKCS11 URI",
 		.desc = "Root Of Trust key"
 	},
 
 	[SWD_ROT_KEY] = {
 		.id = SWD_ROT_KEY,
 		.opt = "swd-rot-key",
-		.help_msg = "Secure World Root of Trust key",
+		.help_msg = "Secure World Root of Trust key file or PKCS11 URI",
 		.desc = "Secure World Root of Trust key"
 	},
 
 	[CORE_SWD_KEY] = {
 		.id = CORE_SWD_KEY,
 		.opt = "core-swd-key",
-		.help_msg = "Core Secure World key",
+		.help_msg = "Core Secure World key file or PKCS11 URI",
 		.desc = "Core Secure World key"
 	},
 
 	[PROT_KEY] = {
 		.id = PROT_KEY,
 		.opt = "prot-key",
-		.help_msg = "Platform Root of Trust key",
+		.help_msg = "Platform Root of Trust key file or PKCS11 URI",
 		.desc = "Platform Root of Trust key"
 	},
 
 	[PLAT_KEY] = {
 		.id = PLAT_KEY,
 		.opt = "plat-key",
-		.help_msg = "Platform key",
+		.help_msg = "Platform key file or PKCS11 URI",
 		.desc = "Platform key"
 	},
 };
diff --git a/tools/cert_create/src/dualroot/cot.c b/tools/cert_create/src/dualroot/cot.c
index 4dd4cf0..81a7d75 100644
--- a/tools/cert_create/src/dualroot/cot.c
+++ b/tools/cert_create/src/dualroot/cot.c
@@ -540,42 +540,42 @@
 	[ROT_KEY] = {
 		.id = ROT_KEY,
 		.opt = "rot-key",
-		.help_msg = "Root Of Trust key (input/output file)",
+		.help_msg = "Root Of Trust key file or PKCS11 URI",
 		.desc = "Root Of Trust key"
 	},
 
 	[TRUSTED_WORLD_KEY] = {
 		.id = TRUSTED_WORLD_KEY,
 		.opt = "trusted-world-key",
-		.help_msg = "Trusted World key (input/output file)",
+		.help_msg = "Trusted World key file or PKCS11 URI",
 		.desc = "Trusted World key"
 	},
 
 	[SCP_FW_CONTENT_CERT_KEY] = {
 		.id = SCP_FW_CONTENT_CERT_KEY,
 		.opt = "scp-fw-key",
-		.help_msg = "SCP Firmware Content Certificate key (input/output file)",
+		.help_msg = "SCP Firmware Content Certificate key file or PKCS11 URI",
 		.desc = "SCP Firmware Content Certificate key"
 	},
 
 	[SOC_FW_CONTENT_CERT_KEY] = {
 		.id = SOC_FW_CONTENT_CERT_KEY,
 		.opt = "soc-fw-key",
-		.help_msg = "SoC Firmware Content Certificate key (input/output file)",
+		.help_msg = "SoC Firmware Content Certificate key file or PKCS11 URI",
 		.desc = "SoC Firmware Content Certificate key"
 	},
 
 	[TRUSTED_OS_FW_CONTENT_CERT_KEY] = {
 		.id = TRUSTED_OS_FW_CONTENT_CERT_KEY,
 		.opt = "tos-fw-key",
-		.help_msg = "Trusted OS Firmware Content Certificate key (input/output file)",
+		.help_msg = "Trusted OS Firmware Content Certificate key file or PKCS11 URI",
 		.desc = "Trusted OS Firmware Content Certificate key"
 	},
 
 	[PROT_KEY] = {
 		.id = PROT_KEY,
 		.opt = "prot-key",
-		.help_msg = "Platform Root of Trust key",
+		.help_msg = "Platform Root of Trust key file or PKCS11 URI",
 		.desc = "Platform Root of Trust key"
 	},
 };
diff --git a/tools/cert_create/src/key.c b/tools/cert_create/src/key.c
index 27ec979..32229d1 100644
--- a/tools/cert_create/src/key.c
+++ b/tools/cert_create/src/key.c
@@ -9,7 +9,11 @@
 #include <stdlib.h>
 #include <string.h>
 
+/* Suppress OpenSSL engine deprecation warnings */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
 #include <openssl/conf.h>
+#include <openssl/engine.h>
 #include <openssl/evp.h>
 #include <openssl/pem.h>
 
@@ -189,30 +193,69 @@
 	return 0;
 }
 
+static EVP_PKEY *key_load_pkcs11(const char *uri)
+{
+	char *key_pass;
+	EVP_PKEY *pkey;
+	ENGINE *e;
+
+	ENGINE_load_builtin_engines();
+	e = ENGINE_by_id("pkcs11");
+	if (!e) {
+		fprintf(stderr, "Cannot Load PKCS#11 ENGINE\n");
+		return NULL;
+	}
+
+	if (!ENGINE_init(e)) {
+		fprintf(stderr, "Cannot ENGINE_init\n");
+		goto err;
+	}
+
+	key_pass = getenv("PKCS11_PIN");
+	if (key_pass) {
+		if (!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0)) {
+			fprintf(stderr, "Cannot Set PKCS#11 PIN\n");
+			goto err;
+		}
+	}
+
+	pkey = ENGINE_load_private_key(e, uri, NULL, NULL);
+	if (pkey)
+		return pkey;
+err:
+	ENGINE_free(e);
+	return NULL;
+
+}
+
 int key_load(key_t *key, unsigned int *err_code)
 {
 	FILE *fp;
-	EVP_PKEY *k;
 
 	if (key->fn) {
-		/* Load key from file */
-		fp = fopen(key->fn, "r");
-		if (fp) {
-			k = PEM_read_PrivateKey(fp, &key->key, NULL, NULL);
-			fclose(fp);
-			if (k) {
-				*err_code = KEY_ERR_NONE;
-				return 1;
-			} else {
-				ERROR("Cannot load key from %s\n", key->fn);
-				*err_code = KEY_ERR_LOAD;
-			}
+		if (!strncmp(key->fn, "pkcs11:", 7)) {
+			/* Load key through pkcs11 */
+			key->key = key_load_pkcs11(key->fn);
 		} else {
-			WARN("Cannot open file %s\n", key->fn);
-			*err_code = KEY_ERR_OPEN;
+			/* Load key from file */
+			fp = fopen(key->fn, "r");
+			if (fp) {
+				key->key = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
+				fclose(fp);
+			} else {
+				WARN("Cannot open file %s\n", key->fn);
+				*err_code = KEY_ERR_OPEN;
+			}
+		}
+		if (key->key) {
+			*err_code = KEY_ERR_NONE;
+			return 1;
+		} else {
+			ERROR("Cannot load key from %s\n", key->fn);
+			*err_code = KEY_ERR_LOAD;
 		}
 	} else {
-		VERBOSE("Key filename not specified\n");
+		VERBOSE("Key not specified\n");
 		*err_code = KEY_ERR_FILENAME;
 	}
 
@@ -224,6 +267,10 @@
 	FILE *fp;
 
 	if (key->fn) {
+		if (!strncmp(key->fn, "pkcs11:", 7)) {
+			ERROR("PKCS11 URI provided instead of a file");
+			return 0;
+		}
 		fp = fopen(key->fn, "w");
 		if (fp) {
 			PEM_write_PrivateKey(fp, key->key,
diff --git a/tools/cert_create/src/tbbr/tbb_key.c b/tools/cert_create/src/tbbr/tbb_key.c
index a81f0e4..5b84b6e 100644
--- a/tools/cert_create/src/tbbr/tbb_key.c
+++ b/tools/cert_create/src/tbbr/tbb_key.c
@@ -15,43 +15,43 @@
 	[ROT_KEY] = {
 		.id = ROT_KEY,
 		.opt = "rot-key",
-		.help_msg = "Root Of Trust key (input/output file)",
+		.help_msg = "Root Of Trust key file or PKCS11 URI",
 		.desc = "Root Of Trust key"
 	},
 	[TRUSTED_WORLD_KEY] = {
 		.id = TRUSTED_WORLD_KEY,
 		.opt = "trusted-world-key",
-		.help_msg = "Trusted World key (input/output file)",
+		.help_msg = "Trusted World key file or PKCS11 URI",
 		.desc = "Trusted World key"
 	},
 	[NON_TRUSTED_WORLD_KEY] = {
 		.id = NON_TRUSTED_WORLD_KEY,
 		.opt = "non-trusted-world-key",
-		.help_msg = "Non Trusted World key (input/output file)",
+		.help_msg = "Non Trusted World key file or PKCS11 URI",
 		.desc = "Non Trusted World key"
 	},
 	[SCP_FW_CONTENT_CERT_KEY] = {
 		.id = SCP_FW_CONTENT_CERT_KEY,
 		.opt = "scp-fw-key",
-		.help_msg = "SCP Firmware Content Certificate key (input/output file)",
+		.help_msg = "SCP Firmware Content Certificate key file or PKCS11 URI",
 		.desc = "SCP Firmware Content Certificate key"
 	},
 	[SOC_FW_CONTENT_CERT_KEY] = {
 		.id = SOC_FW_CONTENT_CERT_KEY,
 		.opt = "soc-fw-key",
-		.help_msg = "SoC Firmware Content Certificate key (input/output file)",
+		.help_msg = "SoC Firmware Content Certificate key file or PKCS11 URI",
 		.desc = "SoC Firmware Content Certificate key"
 	},
 	[TRUSTED_OS_FW_CONTENT_CERT_KEY] = {
 		.id = TRUSTED_OS_FW_CONTENT_CERT_KEY,
 		.opt = "tos-fw-key",
-		.help_msg = "Trusted OS Firmware Content Certificate key (input/output file)",
+		.help_msg = "Trusted OS Firmware Content Certificate key file or PKCS11 URI",
 		.desc = "Trusted OS Firmware Content Certificate key"
 	},
 	[NON_TRUSTED_FW_CONTENT_CERT_KEY] = {
 		.id = NON_TRUSTED_FW_CONTENT_CERT_KEY,
 		.opt = "nt-fw-key",
-		.help_msg = "Non Trusted Firmware Content Certificate key (input/output file)",
+		.help_msg = "Non Trusted Firmware Content Certificate key file or PKCS11 URI",
 		.desc = "Non Trusted Firmware Content Certificate key"
 	}
 };