diff mbox series

[2/5] arm-bsp/trusted-services: corstone1000: add fixes for private auth vars

Message ID 20240522160354.67342-3-bence.balogh@arm.com
State New
Headers show
Series Fix ACS test failures for corstone1000 | expand

Commit Message

bence.balogh@arm.com May 22, 2024, 4:03 p.m. UTC
From: Bence Balogh <bence.balogh@arm.com>

Signed-off-by: Bence Balogh <bence.balogh@arm.com>
---
 ...pi-to-create-uefi-priv-var-fingerpri.patch | 758 ++++++++++++++++++
 ...estamp-validation-for-uefi-variables.patch | 146 ++++
 ...n-uefi-variable-authentication-steps.patch | 282 +++++++
 ...e-Authenticated-Variable-verificatio.patch | 292 +++++++
 .../trusted-services/ts-arm-platforms.inc     |   4 +
 .../ts-sp-smm-gateway_%.bbappend              |   1 +
 6 files changed, 1483 insertions(+)
 create mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0014-Provide-crypto-api-to-create-uefi-priv-var-fingerpri.patch
 create mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0015-Add-timestamp-validation-for-uefi-variables.patch
 create mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0016-Isolate-common-uefi-variable-authentication-steps.patch
 create mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0017-Implement-Private-Authenticated-Variable-verificatio.patch
diff mbox series

Patch

diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0014-Provide-crypto-api-to-create-uefi-priv-var-fingerpri.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0014-Provide-crypto-api-to-create-uefi-priv-var-fingerpri.patch
new file mode 100644
index 00000000..ae9a53fa
--- /dev/null
+++ b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0014-Provide-crypto-api-to-create-uefi-priv-var-fingerpri.patch
@@ -0,0 +1,758 @@ 
+From 370811420cfa1c14146f45de308bbccf70408eb8 Mon Sep 17 00:00:00 2001
+From: Gabor Toth <gabor.toth2@arm.com>
+Date: Fri, 5 Apr 2024 11:19:37 +0200
+Subject: [PATCH] Provide crypto api to create uefi priv var fingerprint
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add new call to the crypto backend to calculate a hash of the common
+name of the signing certificate’s Subject and the tbsCertificate
+of the top-level issuer certificate.
+
+Signed-off-by: Gabor Toth <gabor.toth2@arm.com>
+Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TS/trusted-services/+/27953]
+---
+ .../client/caller/packed-c/crypto_caller.h    |   1 +
+ ...aller_get_uefi_priv_auth_var_fingerprint.h |  90 ++++++++
+ .../packed-c/packedc_crypto_client.cpp        |   8 +
+ .../protocol/packed-c/packedc_crypto_client.h |   4 +
+ .../service/crypto/client/psa/component.cmake |   1 +
+ .../service/crypto/client/psa/crypto_client.h |   5 +
+ .../psa/get_uefi_priv_auth_var_fingerprint.c  |  21 ++
+ .../service/crypto/provider/crypto_provider.c | 212 +++++++++++++++---
+ .../serializer/crypto_provider_serializer.h   |   8 +
+ .../packedc_crypto_provider_serializer.c      |  54 +++++
+ .../backend/direct/uefi_direct_backend.c      |  90 ++++++++
+ deployments/smm-gateway/smm-gateway.cmake     |   5 +
+ .../get_uefi_priv_auth_var_fingerprint.h      |  21 ++
+ protocols/service/crypto/packed-c/opcodes.h   |   1 +
+ 14 files changed, 488 insertions(+), 33 deletions(-)
+ create mode 100644 components/service/crypto/client/caller/packed-c/crypto_caller_get_uefi_priv_auth_var_fingerprint.h
+ create mode 100644 components/service/crypto/client/psa/get_uefi_priv_auth_var_fingerprint.c
+ create mode 100644 protocols/service/crypto/packed-c/get_uefi_priv_auth_var_fingerprint.h
+
+diff --git a/components/service/crypto/client/caller/packed-c/crypto_caller.h b/components/service/crypto/client/caller/packed-c/crypto_caller.h
+index d834bc207..d5dd0f70d 100644
+--- a/components/service/crypto/client/caller/packed-c/crypto_caller.h
++++ b/components/service/crypto/client/caller/packed-c/crypto_caller.h
+@@ -31,5 +31,6 @@
+ #include "crypto_caller_sign_hash.h"
+ #include "crypto_caller_verify_hash.h"
+ #include "crypto_caller_verify_pkcs7_signature.h"
++#include "crypto_caller_get_uefi_priv_auth_var_fingerprint.h"
+ 
+ #endif /* PACKEDC_CRYPTO_CALLER_H */
+diff --git a/components/service/crypto/client/caller/packed-c/crypto_caller_get_uefi_priv_auth_var_fingerprint.h b/components/service/crypto/client/caller/packed-c/crypto_caller_get_uefi_priv_auth_var_fingerprint.h
+new file mode 100644
+index 000000000..d3446e445
+--- /dev/null
++++ b/components/service/crypto/client/caller/packed-c/crypto_caller_get_uefi_priv_auth_var_fingerprint.h
+@@ -0,0 +1,90 @@
++/*
++ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PACKEDC_CRYPTO_CALLER_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_H
++#define PACKEDC_CRYPTO_CALLER_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_H
++
++#include <common/tlv/tlv.h>
++#include <protocols/common/efi/efi_status.h>
++#include <protocols/rpc/common/packed-c/status.h>
++#include <protocols/service/crypto/packed-c/opcodes.h>
++#include <protocols/service/crypto/packed-c/get_uefi_priv_auth_var_fingerprint.h>
++#include <service/common/client/service_client.h>
++#include <stdlib.h>
++#include <string.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++static inline int crypto_caller_get_uefi_priv_auth_var_fingerprint(struct service_client *context,
++						       const uint8_t *signature_cert,
++						       uint64_t signature_cert_len,
++						       uint8_t *output)
++{
++	efi_status_t efi_status = EFI_SUCCESS;
++	size_t req_len = 0;
++
++	if (signature_cert_len > UINT16_MAX)
++		return RPC_ERROR_INVALID_VALUE;
++
++	struct tlv_record signature_record = {
++		.tag = TS_CRYPTO_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_IN_TAG_SIGNATURE,
++		.length = (uint16_t)signature_cert_len,
++		.value = signature_cert
++	};
++
++	req_len += tlv_required_space(signature_record.length);
++
++	rpc_call_handle call_handle;
++	uint8_t *req_buf;
++
++	call_handle = rpc_caller_session_begin(context->session, &req_buf, req_len, 0);
++
++	if (call_handle) {
++		uint8_t *resp_buf;
++		size_t resp_len;
++		service_status_t service_status;
++		struct tlv_iterator req_iter;
++
++		tlv_iterator_begin(&req_iter, req_buf, req_len);
++		tlv_encode(&req_iter, &signature_record);
++
++		context->rpc_status = rpc_caller_session_invoke(
++			call_handle, TS_CRYPTO_OPCODE_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT, &resp_buf, &resp_len,
++			&service_status);
++
++		if (context->rpc_status == RPC_SUCCESS) {
++
++			if (service_status == EFI_SUCCESS) {
++
++				struct tlv_const_iterator resp_iter;
++				struct tlv_record decoded_record;
++				tlv_const_iterator_begin(&resp_iter, resp_buf, resp_len);
++
++				if (tlv_find_decode(&resp_iter,
++							TS_CRYPTO_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_OUT_TAG_IDENTIFIER, &decoded_record)) {
++
++					memcpy(output, decoded_record.value, PSA_HASH_MAX_SIZE);
++				}
++				else {
++					/* Mandatory response parameter missing */
++					efi_status = EFI_INVALID_PARAMETER;
++				}
++			}
++		}
++
++		rpc_caller_session_end(call_handle);
++	}
++
++	return efi_status;
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PACKEDC_CRYPTO_CALLER_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_H */
+diff --git a/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.cpp b/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.cpp
+index aaa71f0c8..e0f6a15a8 100644
+--- a/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.cpp
++++ b/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.cpp
+@@ -428,3 +428,11 @@ int packedc_crypto_client::verify_pkcs7_signature(const uint8_t *signature_cert,
+ 						    hash, hash_len, public_key_cert,
+ 						    public_key_cert_len);
+ }
++
++int packedc_crypto_client::get_uefi_priv_auth_var_fingerprint(const uint8_t *signature_cert,
++						  uint64_t signature_cert_len,
++						  uint8_t *output)
++{
++	return crypto_caller_get_uefi_priv_auth_var_fingerprint(&m_client, signature_cert, signature_cert_len,
++						    output);
++}
+diff --git a/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.h b/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.h
+index 8d4f60cf9..ec6c51c7f 100644
+--- a/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.h
++++ b/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.h
+@@ -236,6 +236,10 @@ public:
+ 	int verify_pkcs7_signature(const uint8_t *signature_cert, uint64_t signature_cert_len,
+ 				   const uint8_t *hash, uint64_t hash_len,
+ 				   const uint8_t *public_key_cert, uint64_t public_key_cert_len);
++
++	int get_uefi_priv_auth_var_fingerprint(const uint8_t *signature_cert,
++				    uint64_t signature_cert_len,
++				    uint8_t *output);
+ };
+ 
+ #endif /* PACKEDC_CRYPTO_CLIENT_H */
+diff --git a/components/service/crypto/client/psa/component.cmake b/components/service/crypto/client/psa/component.cmake
+index 359db3b4a..5bee0c652 100644
+--- a/components/service/crypto/client/psa/component.cmake
++++ b/components/service/crypto/client/psa/component.cmake
+@@ -32,4 +32,5 @@ target_sources(${TGT} PRIVATE
+ 	"${CMAKE_CURRENT_LIST_DIR}/psa_sign_message.c"
+ 	"${CMAKE_CURRENT_LIST_DIR}/psa_verify_message.c"
+ 	"${CMAKE_CURRENT_LIST_DIR}/verify_pkcs7_signature.c"
++	"${CMAKE_CURRENT_LIST_DIR}/get_uefi_priv_auth_var_fingerprint.c"
+ 	)
+diff --git a/components/service/crypto/client/psa/crypto_client.h b/components/service/crypto/client/psa/crypto_client.h
+index 4b59bbe32..af04df11e 100644
+--- a/components/service/crypto/client/psa/crypto_client.h
++++ b/components/service/crypto/client/psa/crypto_client.h
+@@ -7,10 +7,15 @@
+ #ifndef CRYPTO_CLIENT_H
+ #define CRYPTO_CLIENT_H
+ 
++#include <stddef.h>
+ #include <stdint.h>
+ 
+ int verify_pkcs7_signature(const uint8_t *signature_cert, uint64_t signature_cert_len,
+ 			   const uint8_t *hash, uint64_t hash_len, const uint8_t *public_key_cert,
+ 			   uint64_t public_key_cert_len);
+ 
++int get_uefi_priv_auth_var_fingerprint_handler(const uint8_t *signature_cert,
++				    uint64_t signature_cert_len,
++				    uint8_t *output);
++
+ #endif /* CRYPTO_CLIENT_H */
+diff --git a/components/service/crypto/client/psa/get_uefi_priv_auth_var_fingerprint.c b/components/service/crypto/client/psa/get_uefi_priv_auth_var_fingerprint.c
+new file mode 100644
+index 000000000..702aaa0c4
+--- /dev/null
++++ b/components/service/crypto/client/psa/get_uefi_priv_auth_var_fingerprint.c
+@@ -0,0 +1,21 @@
++/*
++ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#include "crypto_caller_selector.h"
++#include "crypto_client.h"
++#include "psa_crypto_client.h"
++
++int get_uefi_priv_auth_var_fingerprint_handler(const uint8_t *signature_cert,
++				    uint64_t signature_cert_len,
++				    uint8_t *output)
++{
++	if (psa_crypto_client_instance.init_status != PSA_SUCCESS)
++		return psa_crypto_client_instance.init_status;
++
++	return crypto_caller_get_uefi_priv_auth_var_fingerprint(&psa_crypto_client_instance.base,
++						    signature_cert, signature_cert_len,
++						    output);
++}
+diff --git a/components/service/crypto/provider/crypto_provider.c b/components/service/crypto/provider/crypto_provider.c
+index 9cd520859..4535d6dbe 100644
+--- a/components/service/crypto/provider/crypto_provider.c
++++ b/components/service/crypto/provider/crypto_provider.c
+@@ -3,12 +3,15 @@
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
++#include <protocols/common/efi/efi_status.h>
+ #include <protocols/rpc/common/packed-c/status.h>
+ #include <protocols/service/crypto/packed-c/opcodes.h>
+ #include <service/crypto/backend/crypto_backend.h>
+ #include <service/crypto/provider/crypto_provider.h>
++#include <compiler.h>
+ #include <stdint.h>
+ #include <stdlib.h>
++#include <string.h>
+ 
+ #include "crypto_partition.h"
+ #include "crypto_uuid.h"
+@@ -28,25 +31,27 @@ static rpc_status_t copy_key_handler(void *context, struct rpc_request *req);
+ static rpc_status_t purge_key_handler(void *context, struct rpc_request *req);
+ static rpc_status_t get_key_attributes_handler(void *context, struct rpc_request *req);
+ static rpc_status_t verify_pkcs7_signature_handler(void *context, struct rpc_request *req);
++static rpc_status_t get_uefi_priv_auth_var_fingerprint_handler(void *context, struct rpc_request *req);
+ 
+ /* Handler mapping table for service */
+ static const struct service_handler handler_table[] = {
+-	{ TS_CRYPTO_OPCODE_GENERATE_KEY,           generate_key_handler },
+-	{ TS_CRYPTO_OPCODE_DESTROY_KEY,            destroy_key_handler },
+-	{ TS_CRYPTO_OPCODE_EXPORT_KEY,             export_key_handler },
+-	{ TS_CRYPTO_OPCODE_EXPORT_PUBLIC_KEY,      export_public_key_handler },
+-	{ TS_CRYPTO_OPCODE_IMPORT_KEY,             import_key_handler },
+-	{ TS_CRYPTO_OPCODE_SIGN_HASH,              asymmetric_sign_handler },
+-	{ TS_CRYPTO_OPCODE_VERIFY_HASH,            asymmetric_verify_handler },
+-	{ TS_CRYPTO_OPCODE_ASYMMETRIC_DECRYPT,     asymmetric_decrypt_handler },
+-	{ TS_CRYPTO_OPCODE_ASYMMETRIC_ENCRYPT,     asymmetric_encrypt_handler },
+-	{ TS_CRYPTO_OPCODE_GENERATE_RANDOM,        generate_random_handler },
+-	{ TS_CRYPTO_OPCODE_COPY_KEY,               copy_key_handler },
+-	{ TS_CRYPTO_OPCODE_PURGE_KEY,              purge_key_handler },
+-	{ TS_CRYPTO_OPCODE_GET_KEY_ATTRIBUTES,     get_key_attributes_handler },
+-	{ TS_CRYPTO_OPCODE_SIGN_MESSAGE,           asymmetric_sign_handler },
+-	{ TS_CRYPTO_OPCODE_VERIFY_MESSAGE,         asymmetric_verify_handler },
+-	{ TS_CRYPTO_OPCODE_VERIFY_PKCS7_SIGNATURE, verify_pkcs7_signature_handler },
++	{ TS_CRYPTO_OPCODE_GENERATE_KEY,            generate_key_handler },
++	{ TS_CRYPTO_OPCODE_DESTROY_KEY,             destroy_key_handler },
++	{ TS_CRYPTO_OPCODE_EXPORT_KEY,              export_key_handler },
++	{ TS_CRYPTO_OPCODE_EXPORT_PUBLIC_KEY,       export_public_key_handler },
++	{ TS_CRYPTO_OPCODE_IMPORT_KEY,              import_key_handler },
++	{ TS_CRYPTO_OPCODE_SIGN_HASH,               asymmetric_sign_handler },
++	{ TS_CRYPTO_OPCODE_VERIFY_HASH,             asymmetric_verify_handler },
++	{ TS_CRYPTO_OPCODE_ASYMMETRIC_DECRYPT,      asymmetric_decrypt_handler },
++	{ TS_CRYPTO_OPCODE_ASYMMETRIC_ENCRYPT,      asymmetric_encrypt_handler },
++	{ TS_CRYPTO_OPCODE_GENERATE_RANDOM,         generate_random_handler },
++	{ TS_CRYPTO_OPCODE_COPY_KEY,                copy_key_handler },
++	{ TS_CRYPTO_OPCODE_PURGE_KEY,               purge_key_handler },
++	{ TS_CRYPTO_OPCODE_GET_KEY_ATTRIBUTES,      get_key_attributes_handler },
++	{ TS_CRYPTO_OPCODE_SIGN_MESSAGE,            asymmetric_sign_handler },
++	{ TS_CRYPTO_OPCODE_VERIFY_MESSAGE,          asymmetric_verify_handler },
++	{ TS_CRYPTO_OPCODE_VERIFY_PKCS7_SIGNATURE,  verify_pkcs7_signature_handler },
++	{ TS_CRYPTO_OPCODE_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT, get_uefi_priv_auth_var_fingerprint_handler },
+ };
+ 
+ struct rpc_service_interface *
+@@ -664,33 +669,44 @@ static rpc_status_t verify_pkcs7_signature_handler(void *context, struct rpc_req
+ 	}
+ 
+ 	if (rpc_status == RPC_SUCCESS) {
+-		/* Parse the public key certificate */
+-		mbedtls_x509_crt signer_certificate;
++		/* Parse the PKCS#7 DER encoded signature block */
++		mbedtls_pkcs7 pkcs7_structure;
+ 
+-		mbedtls_x509_crt_init(&signer_certificate);
++		mbedtls_pkcs7_init(&pkcs7_structure);
+ 
+-		mbedtls_status = mbedtls_x509_crt_parse_der(&signer_certificate, public_key_cert,
+-							    public_key_cert_len);
++		mbedtls_status = mbedtls_pkcs7_parse_der(&pkcs7_structure, signature_cert,
++								signature_cert_len);
+ 
+-		if (mbedtls_status == 0) {
+-			/* Parse the PKCS#7 DER encoded signature block */
+-			mbedtls_pkcs7 pkcs7_structure;
++		if (mbedtls_status == MBEDTLS_PKCS7_SIGNED_DATA) {
+ 
+-			mbedtls_pkcs7_init(&pkcs7_structure);
++			/*
++			 * If a separate public key is provided, verify the signature with it,
++			 * else use the key from the pkcs7 signature structure, because it is
++			 * a self-signed certificate.
++			 */
++			if(public_key_cert_len) {
++				/* Parse the public key certificate */
++				mbedtls_x509_crt signer_certificate;
+ 
+-			mbedtls_status = mbedtls_pkcs7_parse_der(&pkcs7_structure, signature_cert,
+-								 signature_cert_len);
++				mbedtls_x509_crt_init(&signer_certificate);
+ 
+-			if (mbedtls_status == MBEDTLS_PKCS7_SIGNED_DATA) {
+-				/* Verify hash against signed hash */
++				mbedtls_status = mbedtls_x509_crt_parse_der(&signer_certificate, public_key_cert,
++									public_key_cert_len);
++
++				if (mbedtls_status == 0) {
++					/* Verify hash against signed hash */
++					mbedtls_status = mbedtls_pkcs7_signed_hash_verify(
++						&pkcs7_structure, &signer_certificate, hash, hash_len);
++				}
++
++				mbedtls_x509_crt_free(&signer_certificate);
++			} else {
+ 				mbedtls_status = mbedtls_pkcs7_signed_hash_verify(
+-					&pkcs7_structure, &signer_certificate, hash, hash_len);
++					&pkcs7_structure, &pkcs7_structure.private_signed_data.private_certs, hash, hash_len);
+ 			}
+-
+-			mbedtls_pkcs7_free(&pkcs7_structure);
+ 		}
+ 
+-		mbedtls_x509_crt_free(&signer_certificate);
++		mbedtls_pkcs7_free(&pkcs7_structure);
+ 	}
+ 
+ 	free(signature_cert);
+@@ -702,6 +718,128 @@ static rpc_status_t verify_pkcs7_signature_handler(void *context, struct rpc_req
+ 
+ 	return rpc_status;
+ }
++
++/*
++ * Official value: http://www.oid-info.com/get/2.5.4.3
++ * Hex converter: https://misc.daniel-marschall.de/asn.1/oid-converter/online.php
++ */
++static const mbedtls_asn1_buf* findCommonName(const mbedtls_x509_name *name)
++{
++	uint8_t CN_oid_tag = 0x06;
++	uint8_t CN_oid_len = 0x03;
++	uint8_t CN_oid_val[3] = {0x55, 0x04, 0x03};
++
++	while (name)
++	{
++		if (name->oid.tag == CN_oid_tag && name->oid.len == CN_oid_len) {
++			if (name->oid.p != NULL) {
++				if (!memcmp(name->oid.p, CN_oid_val, CN_oid_len))
++					return &name->val;
++			}
++		}
++
++		name = name->next;
++	}
++
++	return NULL;
++}
++
++static rpc_status_t get_uefi_priv_auth_var_fingerprint_handler(void *context, struct rpc_request *req)
++{
++	rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
++	struct rpc_buffer *req_buf = &req->request;
++	const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
++
++	int mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
++
++	uint8_t *signature_cert = NULL;
++	uint64_t signature_cert_len = 0;
++
++	if (serializer) {
++		/* First collect the lengths of the field */
++		rpc_status = serializer->deserialize_get_uefi_priv_auth_var_fingerprint_req(
++			req_buf, NULL, &signature_cert_len);
++
++		if (rpc_status == RPC_SUCCESS) {
++			/* Allocate the needed space and get the data */
++			signature_cert = (uint8_t *)malloc(signature_cert_len);
++
++			if (signature_cert) {
++				rpc_status = serializer->deserialize_get_uefi_priv_auth_var_fingerprint_req(
++					req_buf, signature_cert, &signature_cert_len);
++			} else {
++				rpc_status = RPC_ERROR_RESOURCE_FAILURE;
++			}
++		}
++	}
++
++	if (rpc_status == RPC_SUCCESS) {
++		/* Parse the PKCS#7 DER encoded signature block */
++		mbedtls_pkcs7 pkcs7_structure;
++
++		mbedtls_pkcs7_init(&pkcs7_structure);
++
++		mbedtls_status = mbedtls_pkcs7_parse_der(&pkcs7_structure, signature_cert,
++								signature_cert_len);
++
++		if (mbedtls_status == MBEDTLS_PKCS7_SIGNED_DATA) {
++
++			uint8_t output_buffer[PSA_HASH_MAX_SIZE] =  { 0 };
++			size_t __maybe_unused output_size = 0;
++			const mbedtls_asn1_buf *signerCertCN = NULL;
++			const mbedtls_x509_crt *topLevelCert = &pkcs7_structure.private_signed_data.private_certs;
++			const mbedtls_x509_buf *toplevelCertTbs = NULL;
++			struct rpc_buffer *resp_buf = &req->response;;
++			psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
++
++			/* Find common name field of the signing certificate, which is the first in the chain */
++			signerCertCN = findCommonName(&topLevelCert->subject);
++			if (!signerCertCN)
++				mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
++
++			/* Get the TopLevel certificate which is the last in the chain */
++			while(topLevelCert->next)
++				topLevelCert = topLevelCert->next;
++			toplevelCertTbs = &topLevelCert->tbs;
++
++			/* Hash the data to create the fingerprint */
++			op = psa_hash_operation_init();
++
++			if (psa_hash_setup(&op, PSA_ALG_SHA_256) != PSA_SUCCESS)
++				mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
++
++			if (psa_hash_update(&op, signerCertCN->p, signerCertCN->len)) {
++				psa_hash_abort(&op);
++				mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
++			}
++
++			if (psa_hash_update(&op, toplevelCertTbs->p, toplevelCertTbs->len)) {
++				psa_hash_abort(&op);
++				mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
++			}
++
++			if (psa_hash_finish(&op, (uint8_t*)&output_buffer, PSA_HASH_MAX_SIZE, &output_size)) {
++				psa_hash_abort(&op);
++				mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
++			}
++
++			/* Clear the remaining part of the buffer for consistency */
++			memset(&output_buffer[output_size], 0, PSA_HASH_MAX_SIZE - output_size);
++
++			rpc_status = serializer->serialize_get_uefi_priv_auth_var_fingerprint_resp(
++				resp_buf, (uint8_t*)&output_buffer);
++		}
++
++		mbedtls_pkcs7_free(&pkcs7_structure);
++	}
++
++	free(signature_cert);
++
++	/* Provide the result of the verification */
++	req->service_status = (mbedtls_status == MBEDTLS_PKCS7_SIGNED_DATA) ? EFI_SUCCESS : EFI_COMPROMISED_DATA;
++
++	return rpc_status;
++}
+ #else
+ static rpc_status_t verify_pkcs7_signature_handler(void *context, struct rpc_request *req)
+ {
+@@ -710,4 +848,12 @@ static rpc_status_t verify_pkcs7_signature_handler(void *context, struct rpc_req
+ 
+ 	return RPC_ERROR_INTERNAL;
+ }
++
++static rpc_status_t get_uefi_priv_auth_var_fingerprint_handler(void *context, struct rpc_request *req)
++{
++	(void)context;
++	(void)req;
++
++	return RPC_ERROR_INTERNAL;
++}
+ #endif
+diff --git a/components/service/crypto/provider/serializer/crypto_provider_serializer.h b/components/service/crypto/provider/serializer/crypto_provider_serializer.h
+index bd5336c3d..2b965afdb 100644
+--- a/components/service/crypto/provider/serializer/crypto_provider_serializer.h
++++ b/components/service/crypto/provider/serializer/crypto_provider_serializer.h
+@@ -126,6 +126,14 @@ struct crypto_provider_serializer {
+ 							       uint8_t *hash, uint64_t *hash_len,
+ 							       uint8_t *public_key_cert,
+ 							       uint64_t *public_key_cert_len);
++
++	/* Operation: get_uefi_priv_auth_var_fingerprintentifier */
++	rpc_status_t (*deserialize_get_uefi_priv_auth_var_fingerprint_req)(const struct rpc_buffer *req_buf,
++								uint8_t *signed_data,
++								uint64_t *signed_data_len);
++
++	rpc_status_t (*serialize_get_uefi_priv_auth_var_fingerprint_resp)(struct rpc_buffer *resp_buf,
++							       const uint8_t *output);
+ };
+ 
+ #endif /* CRYPTO_PROVIDER_SERIALIZER_H */
+diff --git a/components/service/crypto/provider/serializer/packed-c/packedc_crypto_provider_serializer.c b/components/service/crypto/provider/serializer/packed-c/packedc_crypto_provider_serializer.c
+index 050ef2f7d..89e07e2c8 100644
+--- a/components/service/crypto/provider/serializer/packed-c/packedc_crypto_provider_serializer.c
++++ b/components/service/crypto/provider/serializer/packed-c/packedc_crypto_provider_serializer.c
+@@ -22,6 +22,7 @@
+ #include <protocols/service/crypto/packed-c/sign_hash.h>
+ #include <protocols/service/crypto/packed-c/verify_hash.h>
+ #include <protocols/service/crypto/packed-c/verify_pkcs7_signature.h>
++#include <protocols/service/crypto/packed-c/get_uefi_priv_auth_var_fingerprint.h>
+ #include <service/crypto/backend/crypto_backend.h>
+ #include <stdlib.h>
+ #include <string.h>
+@@ -675,6 +676,57 @@ static rpc_status_t deserialize_verify_pkcs7_signature_req(
+ 	return rpc_status;
+ }
+ 
++/* Operation: get_uefi_priv_auth_var_fingerprintentifier */
++static rpc_status_t deserialize_get_uefi_priv_auth_var_fingerprint_req(const struct rpc_buffer *req_buf,
++							uint8_t *signed_data,
++							uint64_t *signed_data_len)
++{
++	rpc_status_t rpc_status = RPC_ERROR_INVALID_REQUEST_BODY;
++
++	if (req_buf->data_length) {
++		struct tlv_const_iterator req_iter;
++		struct tlv_record decoded_record;
++
++		rpc_status = RPC_SUCCESS;
++
++		tlv_const_iterator_begin(&req_iter, (uint8_t *)req_buf->data, req_buf->data_length);
++
++		if (tlv_find_decode(&req_iter, TS_CRYPTO_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_IN_TAG_SIGNATURE,
++				    &decoded_record)) {
++			*signed_data_len = decoded_record.length;
++
++			if (signed_data)
++				memcpy(signed_data, decoded_record.value, decoded_record.length);
++		} else {
++			/* Default to a zero length */
++			*signed_data_len = 0;
++		}
++	}
++
++	return rpc_status;
++}
++
++static rpc_status_t serialize_get_uefi_priv_auth_var_fingerprint_resp(struct rpc_buffer *resp_buf,
++							const uint8_t *output)
++{
++	rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
++	struct tlv_iterator resp_iter;
++	struct tlv_record out_record;
++
++	out_record.tag = TS_CRYPTO_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_OUT_TAG_IDENTIFIER;
++	out_record.length = PSA_HASH_MAX_SIZE;
++	out_record.value = output;
++
++	tlv_iterator_begin(&resp_iter, resp_buf->data, resp_buf->size);
++
++	if (tlv_encode(&resp_iter, &out_record)) {
++		resp_buf->data_length = tlv_required_space(PSA_HASH_MAX_SIZE);
++		rpc_status = RPC_SUCCESS;
++	}
++
++	return rpc_status;
++}
++
+ /* Singleton method to provide access to the serializer instance */
+ const struct crypto_provider_serializer *packedc_crypto_provider_serializer_instance(void)
+ {
+@@ -704,6 +756,8 @@ const struct crypto_provider_serializer *packedc_crypto_provider_serializer_inst
+ 		deserialize_generate_random_req,
+ 		serialize_generate_random_resp,
+ 		deserialize_verify_pkcs7_signature_req,
++		deserialize_get_uefi_priv_auth_var_fingerprint_req,
++		serialize_get_uefi_priv_auth_var_fingerprint_resp
+ 	};
+ 
+ 	return &instance;
+diff --git a/components/service/uefi/smm_variable/backend/direct/uefi_direct_backend.c b/components/service/uefi/smm_variable/backend/direct/uefi_direct_backend.c
+index bf978c5dd..c7ca07254 100644
+--- a/components/service/uefi/smm_variable/backend/direct/uefi_direct_backend.c
++++ b/components/service/uefi/smm_variable/backend/direct/uefi_direct_backend.c
+@@ -9,6 +9,8 @@
+ #include <mbedtls/pkcs7.h>
+ #include <mbedtls/x509_crt.h>
+ #include <stdint.h>
++#include <string.h>
++#include <compiler.h>
+ 
+ int verify_pkcs7_signature(const uint8_t *signature_cert, uint64_t signature_cert_len,
+ 			   const uint8_t *hash, uint64_t hash_len, const uint8_t *public_key_cert,
+@@ -46,3 +48,91 @@ int verify_pkcs7_signature(const uint8_t *signature_cert, uint64_t signature_cer
+ 
+ 	return mbedtls_status;
+ }
++
++/*
++ * Official value: http://www.oid-info.com/get/2.5.4.3
++ * Hex converter: https://misc.daniel-marschall.de/asn.1/oid-converter/online.php
++ */
++static const mbedtls_asn1_buf* findCommonName(const mbedtls_x509_name *name)
++{
++	uint8_t CN_oid_tag = 0x06;
++	uint8_t CN_oid_len = 0x03;
++	uint8_t CN_oid_val[3] = {0x55, 0x04, 0x03};
++
++	while (name)
++	{
++		if (name->oid.tag == CN_oid_tag && name->oid.len == CN_oid_len) {
++			if (name->oid.p != NULL) {
++				if (!memcmp(name->oid.p, CN_oid_val, CN_oid_len))
++					return &name->val;
++			}
++		}
++
++		name = name->next;
++	}
++
++	return NULL;
++}
++
++int get_uefi_priv_auth_var_fingerprint_handler(const uint8_t *signature_cert,
++				    uint64_t signature_cert_len,
++				    uint8_t *output)
++{
++	int mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
++
++	/* Parse the PKCS#7 DER encoded signature block */
++	mbedtls_pkcs7 pkcs7_structure;
++
++	mbedtls_pkcs7_init(&pkcs7_structure);
++
++	mbedtls_status = mbedtls_pkcs7_parse_der(&pkcs7_structure, signature_cert,
++							signature_cert_len);
++
++	if (mbedtls_status == MBEDTLS_PKCS7_SIGNED_DATA) {
++
++		uint8_t output_buffer[PSA_HASH_MAX_SIZE] =  { 0 };
++		size_t __maybe_unused output_size = 0;
++		const mbedtls_asn1_buf *signerCertCN = NULL;
++		const mbedtls_x509_crt *topLevelCert = &pkcs7_structure.private_signed_data.private_certs;
++		const mbedtls_x509_buf *toplevelCertTbs = NULL;
++		psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
++
++		/* Find common name field of the signing certificate, which is the first in the chain */
++		signerCertCN = findCommonName(&topLevelCert->subject);
++		if (!signerCertCN)
++			mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
++
++		/* Get the TopLevel certificate which is the last in the chain */
++		while(topLevelCert->next)
++			topLevelCert = topLevelCert->next;
++		toplevelCertTbs = &topLevelCert->tbs;
++
++		/* Hash the data to create the fingerprint */
++		op = psa_hash_operation_init();
++
++		if (psa_hash_setup(&op, PSA_ALG_SHA_256) != PSA_SUCCESS)
++			mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
++
++		if (psa_hash_update(&op, signerCertCN->p, signerCertCN->len)) {
++			psa_hash_abort(&op);
++			mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
++		}
++
++		if (psa_hash_update(&op, toplevelCertTbs->p, toplevelCertTbs->len)) {
++			psa_hash_abort(&op);
++			mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
++		}
++
++		if (psa_hash_finish(&op, (uint8_t*)&output_buffer, PSA_HASH_MAX_SIZE, &output_size)) {
++			psa_hash_abort(&op);
++			mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
++		}
++
++		/* Clear the remaining part of the buffer for consistency */
++		memset(&output_buffer[output_size], 0, PSA_HASH_MAX_SIZE - output_size);
++	}
++
++	mbedtls_pkcs7_free(&pkcs7_structure);
++
++	return mbedtls_status;
++}
+diff --git a/deployments/smm-gateway/smm-gateway.cmake b/deployments/smm-gateway/smm-gateway.cmake
+index e5ee03b60..de519892d 100644
+--- a/deployments/smm-gateway/smm-gateway.cmake
++++ b/deployments/smm-gateway/smm-gateway.cmake
+@@ -17,6 +17,11 @@ include(${TS_ROOT}/external/MbedTLS/MbedTLS.cmake)
+ target_link_libraries(smm-gateway PRIVATE MbedTLS::mbedcrypto)
+ target_link_libraries(smm-gateway PRIVATE MbedTLS::mbedx509)
+ 
++# Pass the location of the mbedtls config file to C preprocessor.
++target_compile_definitions(smm-gateway PRIVATE
++		MBEDTLS_USER_CONFIG_FILE="${MBEDTLS_USER_CONFIG_FILE}"
++)
++
+ target_compile_definitions(smm-gateway PRIVATE
+ 	-DUEFI_INTERNAL_CRYPTO
+ )
+diff --git a/protocols/service/crypto/packed-c/get_uefi_priv_auth_var_fingerprint.h b/protocols/service/crypto/packed-c/get_uefi_priv_auth_var_fingerprint.h
+new file mode 100644
+index 000000000..29964b33c
+--- /dev/null
++++ b/protocols/service/crypto/packed-c/get_uefi_priv_auth_var_fingerprint.h
+@@ -0,0 +1,21 @@
++/*
++ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef TS_CRYPTO_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_H
++#define TS_CRYPTO_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_H
++
++#include <stdint.h>
++
++/* Variable length output parameter tags */
++enum {
++	TS_CRYPTO_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_OUT_TAG_IDENTIFIER = 1,
++};
++
++/* Variable length input parameter tags */
++enum {
++	TS_CRYPTO_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_IN_TAG_SIGNATURE = 1,
++};
++
++#endif /* TS_CRYPTO_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_H */
+diff --git a/protocols/service/crypto/packed-c/opcodes.h b/protocols/service/crypto/packed-c/opcodes.h
+index 35b81599b..8bc2b49b0 100644
+--- a/protocols/service/crypto/packed-c/opcodes.h
++++ b/protocols/service/crypto/packed-c/opcodes.h
+@@ -28,6 +28,7 @@
+ #define TS_CRYPTO_OPCODE_SIGN_MESSAGE           (TS_CRYPTO_OPCODE_BASE + 16)
+ #define TS_CRYPTO_OPCODE_VERIFY_MESSAGE         (TS_CRYPTO_OPCODE_BASE + 17)
+ #define TS_CRYPTO_OPCODE_VERIFY_PKCS7_SIGNATURE (TS_CRYPTO_OPCODE_BASE + 18)
++#define TS_CRYPTO_OPCODE_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT (TS_CRYPTO_OPCODE_BASE + 19)
+ 
+ /* Hash operations */
+ #define TS_CRYPTO_OPCODE_HASH_BASE              (0x0200)
+-- 
+2.25.1
+
diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0015-Add-timestamp-validation-for-uefi-variables.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0015-Add-timestamp-validation-for-uefi-variables.patch
new file mode 100644
index 00000000..26e7df5f
--- /dev/null
+++ b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0015-Add-timestamp-validation-for-uefi-variables.patch
@@ -0,0 +1,146 @@ 
+From 5b418e141aadcb6604406f75e156317bd143d898 Mon Sep 17 00:00:00 2001
+From: Gabor Toth <gabor.toth2@arm.com>
+Date: Fri, 5 Apr 2024 11:27:15 +0200
+Subject: [PATCH 1/3] Add timestamp validation for uefi variables
+
+Return failure if uefi variable creation or update is not
+requested with newer timestamp.
+
+Signed-off-by: Gabor Toth <gabor.toth2@arm.com>
+Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TS/trusted-services/+/27955]
+---
+ .../backend/uefi_variable_store.c             | 35 +++++++++++++++----
+ .../smm_variable/backend/variable_index.c     |  1 +
+ .../smm_variable/backend/variable_index.h     |  1 +
+ 3 files changed, 30 insertions(+), 7 deletions(-)
+
+diff --git a/components/service/uefi/smm_variable/backend/uefi_variable_store.c b/components/service/uefi/smm_variable/backend/uefi_variable_store.c
+index c1691dc8f..1b624f0c9 100644
+--- a/components/service/uefi/smm_variable/backend/uefi_variable_store.c
++++ b/components/service/uefi/smm_variable/backend/uefi_variable_store.c
+@@ -76,6 +76,7 @@ static efi_status_t verify_var_by_key_var(const efi_data_map *new_var,
+ 					  const uint8_t *hash_buffer, size_t hash_len);
+ 
+ static efi_status_t authenticate_variable(const struct uefi_variable_store *context,
++					  EFI_TIME *timestamp,
+ 					  SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *var);
+ #endif
+ 
+@@ -197,6 +198,7 @@ efi_status_t uefi_variable_store_set_variable(const struct uefi_variable_store *
+ 					      const SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *var)
+ {
+ 	bool should_sync_index = false;
++	EFI_TIME timestamp = { 0 };
+ 
+ 	/* Validate incoming request */
+ 	efi_status_t status = check_name_terminator(var->Name, var->NameSize);
+@@ -225,6 +227,9 @@ efi_status_t uefi_variable_store_set_variable(const struct uefi_variable_store *
+ 			return EFI_OUT_OF_RESOURCES;
+ 	}
+ 
++	/* Save the timestamp into a buffer, which can be overwritten by the authentication function */
++	memcpy(&timestamp, &info->metadata.timestamp, sizeof(EFI_TIME));
++
+ 	/* Control access */
+ 	status = check_access_permitted_on_set(context, info, var);
+ 
+@@ -240,7 +245,7 @@ efi_status_t uefi_variable_store_set_variable(const struct uefi_variable_store *
+ 			if (info->metadata.attributes &
+ 			    EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {
+ 				status = authenticate_variable(
+-					context, (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *)var);
++					context, &timestamp, (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *)var);
+ 
+ 				if (status != EFI_SUCCESS)
+ 					return status;
+@@ -326,7 +331,7 @@ efi_status_t uefi_variable_store_set_variable(const struct uefi_variable_store *
+ 			 */
+ 			if (var->Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {
+ 				status = authenticate_variable(
+-					context, (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *)var);
++					context, &timestamp, (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *)var);
+ 
+ 				if (status != EFI_SUCCESS)
+ 					return status;
+@@ -358,9 +363,11 @@ efi_status_t uefi_variable_store_set_variable(const struct uefi_variable_store *
+ 		if (should_sync_index)
+ 			status = sync_variable_index(context);
+ 
+-		/* Store any variable data to the storage backend */
+-		if (info->is_variable_set && (status == EFI_SUCCESS))
++		/* Store any variable data to the storage backend with the updated metadata */
++		if (info->is_variable_set && (status == EFI_SUCCESS)) {
++			memcpy(&info->metadata.timestamp, &timestamp, sizeof(EFI_TIME));
+ 			status = store_variable_data(context, info, var);
++		}
+ 	}
+ 
+ 	variable_index_remove_unused_entry(&context->variable_index, info);
+@@ -1106,6 +1113,7 @@ static efi_status_t verify_var_by_key_var(const efi_data_map *new_var,
+  * then verifies it.
+  */
+ static efi_status_t authenticate_variable(const struct uefi_variable_store *context,
++					  EFI_TIME *timestamp,
+ 					  SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *var)
+ {
+ 	efi_status_t status = EFI_SUCCESS;
+@@ -1223,9 +1231,7 @@ static efi_status_t authenticate_variable(const struct uefi_variable_store *cont
+ 	 *
+ 	 * UEFI: Page 253
+ 	 * 2. Verify that Pad1, Nanosecond, TimeZone, Daylight and Pad2 components
+-	 * of the TimeStamp value are set to zero. Unless the EFI_VARIABLE_APPEND_WRITE
+-	 * attribute is set, verify that the TimeStamp value is later than the current
+-	 * timestamp value associated with the variable
++	 * of the TimeStamp value are set to zero.
+ 	 */
+ 	if ((var_map.efi_auth_descriptor->TimeStamp.Pad1 != 0) ||
+ 	    (var_map.efi_auth_descriptor->TimeStamp.Pad2 != 0) ||
+@@ -1235,6 +1241,21 @@ static efi_status_t authenticate_variable(const struct uefi_variable_store *cont
+ 		return EFI_SECURITY_VIOLATION;
+ 	}
+ 
++	/**
++	 * UEFI: Page 253
++	 * Unless the EFI_VARIABLE_APPEND_WRITE attribute is set, verify
++	 * that the TimeStamp value is later than the current
++	 * timestamp value associated with the variable
++	 */
++	if (!(var->Attributes & EFI_VARIABLE_APPEND_WRITE)) {
++		if (memcmp(&var_map.efi_auth_descriptor->TimeStamp, timestamp, sizeof(EFI_GUID)) <= 0) {
++			EMSG("Timestamp violation");
++			return EFI_SECURITY_VIOLATION;
++		}
++
++		/* Save new timestamp */
++		memcpy(timestamp, &var_map.efi_auth_descriptor->TimeStamp, sizeof(EFI_TIME));
++	}
+ 	/* Calculate hash for the variable only once */
+ 	hash_result = calc_variable_hash(&var_map, (uint8_t *)&hash_buffer, sizeof(hash_buffer),
+ 					 &hash_len);
+diff --git a/components/service/uefi/smm_variable/backend/variable_index.c b/components/service/uefi/smm_variable/backend/variable_index.c
+index e2fe6dd38..f4194d2d3 100644
+--- a/components/service/uefi/smm_variable/backend/variable_index.c
++++ b/components/service/uefi/smm_variable/backend/variable_index.c
+@@ -198,6 +198,7 @@ static struct variable_entry *add_entry(const struct variable_index *context, co
+ 			/* Initialize metadata */
+ 			info->metadata.uid = generate_uid(context, guid, name_size, name);
+ 			info->metadata.guid = *guid;
++			memset(&info->metadata.timestamp, 0, sizeof(EFI_TIME));
+ 			info->metadata.attributes = 0;
+ 			info->metadata.name_size = name_size;
+ 			memcpy(info->metadata.name, name, name_size);
+diff --git a/components/service/uefi/smm_variable/backend/variable_index.h b/components/service/uefi/smm_variable/backend/variable_index.h
+index 5d3b7a7c6..7eef7b86b 100644
+--- a/components/service/uefi/smm_variable/backend/variable_index.h
++++ b/components/service/uefi/smm_variable/backend/variable_index.h
+@@ -32,6 +32,7 @@ extern "C" {
+  */
+ struct variable_metadata {
+ 	EFI_GUID guid;
++	EFI_TIME timestamp;
+ 	size_t name_size;
+ 	int16_t name[VARIABLE_INDEX_MAX_NAME_SIZE];
+ 	uint32_t attributes;
+-- 
+2.25.1
+
diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0016-Isolate-common-uefi-variable-authentication-steps.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0016-Isolate-common-uefi-variable-authentication-steps.patch
new file mode 100644
index 00000000..16ca63b3
--- /dev/null
+++ b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0016-Isolate-common-uefi-variable-authentication-steps.patch
@@ -0,0 +1,282 @@ 
+From 19e79008e0fa3193b54bf6499516dc75cb10f6ec Mon Sep 17 00:00:00 2001
+From: Gabor Toth <gabor.toth2@arm.com>
+Date: Thu, 11 Apr 2024 13:42:03 +0200
+Subject: [PATCH 2/3] Isolate common uefi variable authentication steps
+
+Currently all auth variables are authenticated with the secure boot
+keys. To introduce corrent check for Private Authenticated Variables
+first separate the common steps from the secure boot related steps.
+
+Signed-off-by: Gabor Toth <gabor.toth2@arm.com>
+Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TS/trusted-services/+/27956]
+---
+ .../backend/uefi_variable_store.c             | 191 ++++++++++--------
+ 1 file changed, 103 insertions(+), 88 deletions(-)
+
+diff --git a/components/service/uefi/smm_variable/backend/uefi_variable_store.c b/components/service/uefi/smm_variable/backend/uefi_variable_store.c
+index 1b624f0c9..1384d0def 100644
+--- a/components/service/uefi/smm_variable/backend/uefi_variable_store.c
++++ b/components/service/uefi/smm_variable/backend/uefi_variable_store.c
+@@ -78,6 +78,12 @@ static efi_status_t verify_var_by_key_var(const efi_data_map *new_var,
+ static efi_status_t authenticate_variable(const struct uefi_variable_store *context,
+ 					  EFI_TIME *timestamp,
+ 					  SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *var);
++
++static efi_status_t authenticate_secure_boot_variable(const struct uefi_variable_store *context,
++						      efi_data_map* var_map,
++						      uint8_t* hash_buffer,
++						      size_t hash_len,
++						      uint64_t max_variable_size);
+ #endif
+ 
+ static efi_status_t store_variable_data(const struct uefi_variable_store *context,
+@@ -1118,30 +1124,109 @@ static efi_status_t authenticate_variable(const struct uefi_variable_store *cont
+ {
+ 	efi_status_t status = EFI_SUCCESS;
+ 	EFI_GUID pkcs7_guid = EFI_CERT_TYPE_PKCS7_GUID;
+-	EFI_GUID global_variable_guid = EFI_GLOBAL_VARIABLE;
+-	EFI_GUID security_database_guid = EFI_IMAGE_SECURITY_DATABASE_GUID;
+ 	SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO variable_info = { 0, 0, 0, 0 };
+-	SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *pk_variable = NULL;
+-	size_t pk_payload_size = 0;
+ 	efi_data_map var_map = { NULL, NULL, NULL, 0, 0, NULL, 0, NULL };
+ 	uint8_t hash_buffer[PSA_HASH_MAX_SIZE];
+ 	size_t hash_len = 0;
+-	bool hash_result = false;
+ 
+ 	/* Create a map of the fields of the new variable including the auth header */
+ 	if (!init_efi_data_map(var, true, &var_map))
+ 		return EFI_SECURITY_VIOLATION;
+ 
+-	/* database variables can be verified by either PK or KEK while images
+-	 * should be checked by db and dbx so the length of two will be enough.
+-	 */
+-	SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *allowed_key_store_variables[] = { NULL, NULL };
+-
+ 	/* Find the maximal size of variables for the GetVariable operation */
+ 	status = uefi_variable_store_query_variable_info(context, &variable_info);
+ 	if (status != EFI_SUCCESS)
+ 		return EFI_SECURITY_VIOLATION;
+ 
++	/**
++	 * UEFI: Page 246
++	 * If the EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set in a
++	 * SetVariable() call, and firmware does not support signature type of the certificate
++	 * included in the EFI_VARIABLE_AUTHENTICATION_2 descriptor, then the SetVariable() call
++	 * shall return EFI_INVALID_PARAMETER. The list of signature types supported by the
++	 * firmware is defined by the SignatureSupport variable. Signature type of the certificate
++	 * is defined by its digest and encryption algorithms.
++	 */
++	/* TODO: Should support WIN_CERT_TYPE_PKCS_SIGNED_DATA and WIN_CERT_TYPE_EFI_PKCS115 */
++	if (var_map.efi_auth_descriptor->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID)
++		return EFI_INVALID_PARAMETER;
++
++	/* Only a CertType of EFI_CERT_TYPE_PKCS7_GUID is accepted */
++	if (!compare_guid(&var_map.efi_auth_descriptor->AuthInfo.CertType, &pkcs7_guid))
++		return EFI_SECURITY_VIOLATION;
++
++	/**
++	 * Time associated with the authentication descriptor. For the TimeStamp value,
++	 * components Pad1, Nanosecond, TimeZone, Daylight and Pad2 shall be set to 0.
++	 * This means that the time shall always be expressed in GMT.
++	 *
++	 * UEFI: Page 253
++	 * 2. Verify that Pad1, Nanosecond, TimeZone, Daylight and Pad2 components
++	 * of the TimeStamp value are set to zero.
++	 */
++	if ((var_map.efi_auth_descriptor->TimeStamp.Pad1 != 0) ||
++	    (var_map.efi_auth_descriptor->TimeStamp.Pad2 != 0) ||
++	    (var_map.efi_auth_descriptor->TimeStamp.Nanosecond != 0) ||
++	    (var_map.efi_auth_descriptor->TimeStamp.TimeZone != 0) ||
++	    (var_map.efi_auth_descriptor->TimeStamp.Daylight != 0)) {
++		return EFI_SECURITY_VIOLATION;
++	}
++
++	/**
++	 * UEFI: Page 253
++	 * Unless the EFI_VARIABLE_APPEND_WRITE attribute is set, verify
++	 * that the TimeStamp value is later than the current
++	 * timestamp value associated with the variable
++	 */
++	if (!(var->Attributes & EFI_VARIABLE_APPEND_WRITE)) {
++		if (memcmp(&var_map.efi_auth_descriptor->TimeStamp, timestamp, sizeof(EFI_GUID)) <= 0) {
++			EMSG("Timestamp violation");
++			return EFI_SECURITY_VIOLATION;
++		}
++
++		/* Save new timestamp */
++		memcpy(timestamp, &var_map.efi_auth_descriptor->TimeStamp, sizeof(EFI_TIME));
++	}
++	/* Calculate hash for the variable only once */
++	if (calc_variable_hash(&var_map, (uint8_t *)&hash_buffer, sizeof(hash_buffer), &hash_len) == 0) {
++		status = EFI_SECURITY_VIOLATION;
++	}
++
++	/* Run Secure Boot related authentication steps */
++	status = authenticate_secure_boot_variable(context, &var_map, (uint8_t*) &hash_buffer, hash_len, variable_info.MaximumVariableSize);
++
++	/* Remove the authentication header from the variable if the authentication is successful */
++	if (status == EFI_SUCCESS) {
++		uint8_t *smm_payload =
++			(uint8_t *)var + SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE_DATA_OFFSET(var);
++
++		memmove(smm_payload, var_map.payload, var_map.payload_len);
++		memset((uint8_t *)smm_payload + var_map.payload_len, 0,
++		       var_map.efi_auth_descriptor_len);
++
++		var->DataSize -= var_map.efi_auth_descriptor_len;
++	}
++
++	return status;
++}
++
++static efi_status_t authenticate_secure_boot_variable(const struct uefi_variable_store *context,
++						      efi_data_map* var_map,
++						      uint8_t* hash_buffer,
++						      size_t hash_len,
++						      uint64_t max_variable_size)
++{
++	efi_status_t status = EFI_SUCCESS;
++	EFI_GUID global_variable_guid = EFI_GLOBAL_VARIABLE;
++	EFI_GUID security_database_guid = EFI_IMAGE_SECURITY_DATABASE_GUID;
++	SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *pk_variable = NULL;
++	size_t pk_payload_size = 0;
++
++	/* database variables can be verified by either PK or KEK while images
++	 * should be checked by db and dbx so the length of two will be enough.
++	 */
++	SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *allowed_key_store_variables[] = { NULL, NULL };
++
+ 	/**
+ 	 * UEFI: Page 253
+ 	 * 3. If the variable SetupMode==1, and the variable is a secure
+@@ -1166,14 +1251,14 @@ static efi_status_t authenticate_variable(const struct uefi_variable_store *cont
+ 	 * Platform Key is checked to enable or disable authentication.
+ 	 */
+ 	create_smm_variable(&pk_variable, sizeof(EFI_PLATFORM_KEY_NAME),
+-			    variable_info.MaximumVariableSize, (uint8_t *)EFI_PLATFORM_KEY_NAME,
++			    max_variable_size, (uint8_t *)EFI_PLATFORM_KEY_NAME,
+ 			    &global_variable_guid);
+ 
+ 	if (!pk_variable)
+ 		return EFI_OUT_OF_RESOURCES;
+ 
+ 	status = uefi_variable_store_get_variable(
+-		context, pk_variable, variable_info.MaximumVariableSize, &pk_payload_size);
++		context, pk_variable, max_variable_size, &pk_payload_size);
+ 
+ 	/* If PK does not exist authentication is disabled */
+ 	if (status != EFI_SUCCESS) {
+@@ -1207,66 +1292,8 @@ static efi_status_t authenticate_variable(const struct uefi_variable_store *cont
+ 		goto end;
+ 	}
+ 
+-	/**
+-	 * UEFI: Page 246
+-	 * If the EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set in a
+-	 * SetVariable() call, and firmware does not support signature type of the certificate
+-	 * included in the EFI_VARIABLE_AUTHENTICATION_2 descriptor, then the SetVariable() call
+-	 * shall return EFI_INVALID_PARAMETER. The list of signature types supported by the
+-	 * firmware is defined by the SignatureSupport variable. Signature type of the certificate
+-	 * is defined by its digest and encryption algorithms.
+-	 */
+-	/* TODO: Should support WIN_CERT_TYPE_PKCS_SIGNED_DATA and WIN_CERT_TYPE_EFI_PKCS115 */
+-	if (var_map.efi_auth_descriptor->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID)
+-		return EFI_INVALID_PARAMETER;
+-
+-	/* Only a CertType of EFI_CERT_TYPE_PKCS7_GUID is accepted */
+-	if (!compare_guid(&var_map.efi_auth_descriptor->AuthInfo.CertType, &pkcs7_guid))
+-		return EFI_SECURITY_VIOLATION;
+-
+-	/**
+-	 * Time associated with the authentication descriptor. For the TimeStamp value,
+-	 * components Pad1, Nanosecond, TimeZone, Daylight and Pad2 shall be set to 0.
+-	 * This means that the time shall always be expressed in GMT.
+-	 *
+-	 * UEFI: Page 253
+-	 * 2. Verify that Pad1, Nanosecond, TimeZone, Daylight and Pad2 components
+-	 * of the TimeStamp value are set to zero.
+-	 */
+-	if ((var_map.efi_auth_descriptor->TimeStamp.Pad1 != 0) ||
+-	    (var_map.efi_auth_descriptor->TimeStamp.Pad2 != 0) ||
+-	    (var_map.efi_auth_descriptor->TimeStamp.Nanosecond != 0) ||
+-	    (var_map.efi_auth_descriptor->TimeStamp.TimeZone != 0) ||
+-	    (var_map.efi_auth_descriptor->TimeStamp.Daylight != 0)) {
+-		return EFI_SECURITY_VIOLATION;
+-	}
+-
+-	/**
+-	 * UEFI: Page 253
+-	 * Unless the EFI_VARIABLE_APPEND_WRITE attribute is set, verify
+-	 * that the TimeStamp value is later than the current
+-	 * timestamp value associated with the variable
+-	 */
+-	if (!(var->Attributes & EFI_VARIABLE_APPEND_WRITE)) {
+-		if (memcmp(&var_map.efi_auth_descriptor->TimeStamp, timestamp, sizeof(EFI_GUID)) <= 0) {
+-			EMSG("Timestamp violation");
+-			return EFI_SECURITY_VIOLATION;
+-		}
+-
+-		/* Save new timestamp */
+-		memcpy(timestamp, &var_map.efi_auth_descriptor->TimeStamp, sizeof(EFI_TIME));
+-	}
+-	/* Calculate hash for the variable only once */
+-	hash_result = calc_variable_hash(&var_map, (uint8_t *)&hash_buffer, sizeof(hash_buffer),
+-					 &hash_len);
+-
+-	if (!hash_result) {
+-		status = EFI_SECURITY_VIOLATION;
+-		goto end;
+-	}
+-
+-	status = select_verification_keys(var_map, global_variable_guid, security_database_guid,
+-					  variable_info.MaximumVariableSize,
++	status = select_verification_keys(*var_map, global_variable_guid, security_database_guid,
++					  max_variable_size,
+ 					  &allowed_key_store_variables[0]);
+ 
+ 	if (status != EFI_SUCCESS)
+@@ -1280,8 +1307,8 @@ static efi_status_t authenticate_variable(const struct uefi_variable_store *cont
+ 			continue;
+ 
+ 		status = uefi_variable_store_get_variable(context, allowed_key_store_variables[i],
+-							  variable_info.MaximumVariableSize,
+-							  &actual_variable_length);
++							max_variable_size,
++							&actual_variable_length);
+ 
+ 		if (status) {
+ 			/* When the parent does not exist it is considered verification failure */
+@@ -1297,8 +1324,8 @@ static efi_status_t authenticate_variable(const struct uefi_variable_store *cont
+ 			goto end;
+ 		}
+ 
+-		status = verify_var_by_key_var(&var_map, &allowed_key_store_var_map,
+-					       (uint8_t *)&hash_buffer, hash_len);
++		status = verify_var_by_key_var(var_map, &allowed_key_store_var_map,
++					hash_buffer, hash_len);
+ 
+ 		if (status == EFI_SUCCESS)
+ 			goto end;
+@@ -1311,18 +1338,6 @@ end:
+ 			free(allowed_key_store_variables[i]);
+ 	}
+ 
+-	/* Remove the authentication header from the variable if the authentication is successful */
+-	if (status == EFI_SUCCESS) {
+-		uint8_t *smm_payload =
+-			(uint8_t *)var + SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE_DATA_OFFSET(var);
+-
+-		memmove(smm_payload, var_map.payload, var_map.payload_len);
+-		memset((uint8_t *)smm_payload + var_map.payload_len, 0,
+-		       var_map.efi_auth_descriptor_len);
+-
+-		var->DataSize -= var_map.efi_auth_descriptor_len;
+-	}
+-
+ 	return status;
+ }
+ #endif
+-- 
+2.25.1
+
diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0017-Implement-Private-Authenticated-Variable-verificatio.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0017-Implement-Private-Authenticated-Variable-verificatio.patch
new file mode 100644
index 00000000..eb7852f0
--- /dev/null
+++ b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0017-Implement-Private-Authenticated-Variable-verificatio.patch
@@ -0,0 +1,292 @@ 
+From a172c6e8269915db1b25e2749bae06dc0220cfb8 Mon Sep 17 00:00:00 2001
+From: Gabor Toth <gabor.toth2@arm.com>
+Date: Thu, 11 Apr 2024 13:48:14 +0200
+Subject: [PATCH 3/3] Implement Private Authenticated Variable verification
+
+Refactor the implementation to only use the PK, KEK, DB authentication
+chain for boot variables, and implement the self authentication for
+private authenticated variables.
+
+Signed-off-by: Gabor Toth <gabor.toth2@arm.com>
+Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TS/trusted-services/+/27957]
+---
+ .../backend/uefi_variable_store.c             | 126 +++++++++++++++---
+ .../smm_variable/backend/variable_index.c     |   1 +
+ .../smm_variable/backend/variable_index.h     |   2 +
+ .../config/default-opteesp/CMakeLists.txt     |   2 +-
+ .../config/default-sp/CMakeLists.txt          |   2 +-
+ 5 files changed, 112 insertions(+), 21 deletions(-)
+
+diff --git a/components/service/uefi/smm_variable/backend/uefi_variable_store.c b/components/service/uefi/smm_variable/backend/uefi_variable_store.c
+index 1384d0def..97c43dc74 100644
+--- a/components/service/uefi/smm_variable/backend/uefi_variable_store.c
++++ b/components/service/uefi/smm_variable/backend/uefi_variable_store.c
+@@ -75,15 +75,25 @@ static efi_status_t verify_var_by_key_var(const efi_data_map *new_var,
+ 					  const efi_data_map *key_store_var,
+ 					  const uint8_t *hash_buffer, size_t hash_len);
+ 
++static bool isPrivateAuthVar(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *var);
++
+ static efi_status_t authenticate_variable(const struct uefi_variable_store *context,
+-					  EFI_TIME *timestamp,
+-					  SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *var);
++					  EFI_TIME *timestamp, uint8_t (*fingerprint)[FINGERPRINT_SIZE],
++					  bool new_variable, SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *var);
+ 
+ static efi_status_t authenticate_secure_boot_variable(const struct uefi_variable_store *context,
+ 						      efi_data_map* var_map,
+ 						      uint8_t* hash_buffer,
+ 						      size_t hash_len,
+ 						      uint64_t max_variable_size);
++
++static efi_status_t authenticate_private_variable(const struct uefi_variable_store *context,
++						  efi_data_map* var_map,
++						  uint8_t* hash_buffer,
++						  size_t hash_len,
++						  uint64_t max_variable_size,
++						  bool new_variable,
++						  uint8_t (*fingerprint)[FINGERPRINT_SIZE]);
+ #endif
+ 
+ static efi_status_t store_variable_data(const struct uefi_variable_store *context,
+@@ -205,6 +215,7 @@ efi_status_t uefi_variable_store_set_variable(const struct uefi_variable_store *
+ {
+ 	bool should_sync_index = false;
+ 	EFI_TIME timestamp = { 0 };
++	uint8_t fingerprint[FINGERPRINT_SIZE] = { 0 };
+ 
+ 	/* Validate incoming request */
+ 	efi_status_t status = check_name_terminator(var->Name, var->NameSize);
+@@ -233,8 +244,9 @@ efi_status_t uefi_variable_store_set_variable(const struct uefi_variable_store *
+ 			return EFI_OUT_OF_RESOURCES;
+ 	}
+ 
+-	/* Save the timestamp into a buffer, which can be overwritten by the authentication function */
++	/* Save the timestamp and fingerprints into a buffer, which can be overwritten by the authentication function */
+ 	memcpy(&timestamp, &info->metadata.timestamp, sizeof(EFI_TIME));
++	memcpy(&fingerprint, &info->metadata.fingerprint, FINGERPRINT_SIZE);
+ 
+ 	/* Control access */
+ 	status = check_access_permitted_on_set(context, info, var);
+@@ -251,7 +263,8 @@ efi_status_t uefi_variable_store_set_variable(const struct uefi_variable_store *
+ 			if (info->metadata.attributes &
+ 			    EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {
+ 				status = authenticate_variable(
+-					context, &timestamp, (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *)var);
++					context, &timestamp, &fingerprint, false,
++					(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *)var);
+ 
+ 				if (status != EFI_SUCCESS)
+ 					return status;
+@@ -337,7 +350,8 @@ efi_status_t uefi_variable_store_set_variable(const struct uefi_variable_store *
+ 			 */
+ 			if (var->Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {
+ 				status = authenticate_variable(
+-					context, &timestamp, (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *)var);
++					context, &timestamp, &fingerprint, true,
++					(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *)var);
+ 
+ 				if (status != EFI_SUCCESS)
+ 					return status;
+@@ -372,6 +386,7 @@ efi_status_t uefi_variable_store_set_variable(const struct uefi_variable_store *
+ 		/* Store any variable data to the storage backend with the updated metadata */
+ 		if (info->is_variable_set && (status == EFI_SUCCESS)) {
+ 			memcpy(&info->metadata.timestamp, &timestamp, sizeof(EFI_TIME));
++			memcpy(&info->metadata.fingerprint, &fingerprint, FINGERPRINT_SIZE);
+ 			status = store_variable_data(context, info, var);
+ 		}
+ 	}
+@@ -1030,15 +1045,6 @@ select_verification_keys(const efi_data_map new_var, EFI_GUID global_variable_gu
+ 		create_smm_variable(&(allowed_key_store_variables[1]),
+ 				    sizeof(EFI_KEY_EXCHANGE_KEY_NAME), maximum_variable_size,
+ 				    (uint8_t *)EFI_KEY_EXCHANGE_KEY_NAME, &global_variable_guid);
+-	} else {
+-		/*
+-		 * Any other variable is considered Private Authenticated Variable.
+-		 * These are verified by db
+-		 */
+-		create_smm_variable(&(allowed_key_store_variables[0]),
+-				    sizeof(EFI_IMAGE_SECURITY_DATABASE), maximum_variable_size,
+-				    (uint8_t *)EFI_IMAGE_SECURITY_DATABASE,
+-				    &security_database_guid);
+ 	}
+ 
+ 	return EFI_SUCCESS;
+@@ -1114,13 +1120,39 @@ static efi_status_t verify_var_by_key_var(const efi_data_map *new_var,
+ 	return EFI_SECURITY_VIOLATION;
+ }
+ 
+-/* Basic verification of the authentication header of the new variable.
++static bool isPrivateAuthVar(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *var)
++{
++	if (compare_name_to_key_store_name(var->Name,
++					   var->NameSize, EFI_PLATFORM_KEY_NAME,
++					   sizeof(EFI_PLATFORM_KEY_NAME)) ||
++		 compare_name_to_key_store_name(
++			   var->Name, var->NameSize,
++			   EFI_KEY_EXCHANGE_KEY_NAME, sizeof(EFI_KEY_EXCHANGE_KEY_NAME)) ||
++		 compare_name_to_key_store_name(
++			 var->Name, var->NameSize,
++			 EFI_IMAGE_SECURITY_DATABASE, sizeof(EFI_IMAGE_SECURITY_DATABASE)) ||
++		 compare_name_to_key_store_name(
++			 var->Name, var->NameSize,
++			 EFI_IMAGE_SECURITY_DATABASE1, sizeof(EFI_IMAGE_SECURITY_DATABASE1)) ||
++		 compare_name_to_key_store_name(
++			 var->Name, var->NameSize,
++			 EFI_IMAGE_SECURITY_DATABASE2, sizeof(EFI_IMAGE_SECURITY_DATABASE2)) ||
++		 compare_name_to_key_store_name(
++			 var->Name, var->NameSize,
++			 EFI_IMAGE_SECURITY_DATABASE3, sizeof(EFI_IMAGE_SECURITY_DATABASE3)))
++		return false;
++
++	return true;
++}
++
++/*
++ * Basic verification of the authentication header of the new variable.
+  * First finds the key variable responsible for the authentication of the new variable,
+  * then verifies it.
+  */
+ static efi_status_t authenticate_variable(const struct uefi_variable_store *context,
+-					  EFI_TIME *timestamp,
+-					  SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *var)
++					  EFI_TIME *timestamp, uint8_t (*fingerprint)[FINGERPRINT_SIZE],
++					  bool new_variable, SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *var)
+ {
+ 	efi_status_t status = EFI_SUCCESS;
+ 	EFI_GUID pkcs7_guid = EFI_CERT_TYPE_PKCS7_GUID;
+@@ -1192,8 +1224,13 @@ static efi_status_t authenticate_variable(const struct uefi_variable_store *cont
+ 		status = EFI_SECURITY_VIOLATION;
+ 	}
+ 
+-	/* Run Secure Boot related authentication steps */
+-	status = authenticate_secure_boot_variable(context, &var_map, (uint8_t*) &hash_buffer, hash_len, variable_info.MaximumVariableSize);
++	if (isPrivateAuthVar(var)) {
++		/* Run Private Authenticated Variable related authentication steps */
++		status = authenticate_private_variable(context, &var_map, (uint8_t*) &hash_buffer, hash_len, variable_info.MaximumVariableSize, new_variable, fingerprint);
++	} else {
++		/* Run Secure Boot related authentication steps */
++		status = authenticate_secure_boot_variable(context, &var_map, (uint8_t*) &hash_buffer, hash_len, variable_info.MaximumVariableSize);
++	}
+ 
+ 	/* Remove the authentication header from the variable if the authentication is successful */
+ 	if (status == EFI_SUCCESS) {
+@@ -1340,6 +1377,57 @@ end:
+ 
+ 	return status;
+ }
++
++static efi_status_t authenticate_private_variable(const struct uefi_variable_store *context,
++						  efi_data_map* var_map,
++						  uint8_t* hash_buffer,
++						  size_t hash_len,
++						  uint64_t max_variable_size,
++						  bool new_variable,
++						  uint8_t (*fingerprint)[FINGERPRINT_SIZE])
++{
++	efi_status_t status = EFI_SUCCESS;
++	uint8_t new_fingerprint[PSA_HASH_MAX_SIZE] = { 0 };
++
++	/* Verify the signature of the variable */
++	if (verify_pkcs7_signature(
++		var_map->efi_auth_descriptor->AuthInfo.CertData,
++		var_map->efi_auth_descriptor_certdata_len, hash_buffer,
++		hash_len, NULL, 0) == 0)
++		status = EFI_SUCCESS;
++	else
++		return EFI_SECURITY_VIOLATION;
++
++	/**
++	 * UEFI: Page 254
++	 * CN of the signing certificate’s Subject and the hash of the tbsCertificate of the top-level issuer certificate
++	 * (or the signing certificate itself if no other certificates are present or the certificate chain is of length 1)
++	 * in SignedData.certificates is registered for use in subsequent verifications of this variable. Implementations
++	 * may store just a single hash of these two elements to reduce storage requirements.
++	 */
++	if (get_uefi_priv_auth_var_fingerprint_handler(var_map->efi_auth_descriptor->AuthInfo.CertData,
++						       var_map->efi_auth_descriptor_certdata_len,
++						       (uint8_t*)&new_fingerprint)) {
++		EMSG("Failed to querry variable fingerprint input");
++		return EFI_SECURITY_VIOLATION;
++	}
++
++	/*
++	 * The hash is SHA256 so only 32 bytes contain non zero values.
++	 * Use only that part to decrease metadata size.
++	 */
++	if (!new_variable) {
++		if (memcmp(&new_fingerprint, fingerprint, FINGERPRINT_SIZE)) {
++			EMSG("Fingerprint verification failed");
++			return EFI_SECURITY_VIOLATION;
++		}
++	} else {
++		/* Save fingerprint */
++		memcpy(fingerprint, &new_fingerprint, FINGERPRINT_SIZE);
++	}
++
++	return status;
++}
+ #endif
+ 
+ static efi_status_t store_variable_data(const struct uefi_variable_store *context,
+diff --git a/components/service/uefi/smm_variable/backend/variable_index.c b/components/service/uefi/smm_variable/backend/variable_index.c
+index f4194d2d3..7f2fbe0ba 100644
+--- a/components/service/uefi/smm_variable/backend/variable_index.c
++++ b/components/service/uefi/smm_variable/backend/variable_index.c
+@@ -199,6 +199,7 @@ static struct variable_entry *add_entry(const struct variable_index *context, co
+ 			info->metadata.uid = generate_uid(context, guid, name_size, name);
+ 			info->metadata.guid = *guid;
+ 			memset(&info->metadata.timestamp, 0, sizeof(EFI_TIME));
++			memset(&info->metadata.fingerprint, 0, sizeof(FINGERPRINT_SIZE));
+ 			info->metadata.attributes = 0;
+ 			info->metadata.name_size = name_size;
+ 			memcpy(info->metadata.name, name, name_size);
+diff --git a/components/service/uefi/smm_variable/backend/variable_index.h b/components/service/uefi/smm_variable/backend/variable_index.h
+index 7eef7b86b..726bc985a 100644
+--- a/components/service/uefi/smm_variable/backend/variable_index.h
++++ b/components/service/uefi/smm_variable/backend/variable_index.h
+@@ -24,6 +24,7 @@ extern "C" {
+  * Implementation limits
+  */
+ #define VARIABLE_INDEX_MAX_NAME_SIZE (64)
++#define FINGERPRINT_SIZE             (32)
+ 
+ /**
+  * \brief variable_metadata structure definition
+@@ -33,6 +34,7 @@ extern "C" {
+ struct variable_metadata {
+ 	EFI_GUID guid;
+ 	EFI_TIME timestamp;
++	uint8_t fingerprint[FINGERPRINT_SIZE];
+ 	size_t name_size;
+ 	int16_t name[VARIABLE_INDEX_MAX_NAME_SIZE];
+ 	uint32_t attributes;
+diff --git a/deployments/smm-gateway/config/default-opteesp/CMakeLists.txt b/deployments/smm-gateway/config/default-opteesp/CMakeLists.txt
+index 0e281a377..d3df61ded 100644
+--- a/deployments/smm-gateway/config/default-opteesp/CMakeLists.txt
++++ b/deployments/smm-gateway/config/default-opteesp/CMakeLists.txt
+@@ -42,7 +42,7 @@ set(SP_BOOT_ORDER "8" CACHE STRING "Boot order of the SP")
+ add_platform(TARGET "smm-gateway")
+ 
+ # SMM variable and RPC caller settings
+-set(SMM_GATEWAY_MAX_UEFI_VARIABLES 40 CACHE STRING "Maximum UEFI variable count")
++set(SMM_GATEWAY_MAX_UEFI_VARIABLES 35 CACHE STRING "Maximum UEFI variable count")
+ set(SMM_RPC_CALLER_SESSION_SHARED_MEMORY_SIZE 2*4096 CACHE STRING "RPC caller buffer size in SMMGW")
+ if (UEFI_AUTH_VAR)
+ set(SMM_SP_HEAP_SIZE 64*1024 CACHE STRING "SMM gateway SP heap size")
+diff --git a/deployments/smm-gateway/config/default-sp/CMakeLists.txt b/deployments/smm-gateway/config/default-sp/CMakeLists.txt
+index 8df9256e4..bb97cf8e3 100644
+--- a/deployments/smm-gateway/config/default-sp/CMakeLists.txt
++++ b/deployments/smm-gateway/config/default-sp/CMakeLists.txt
+@@ -47,7 +47,7 @@ set(SP_BOOT_ORDER "8" CACHE STRING "Boot order of the SP")
+ add_platform(TARGET "smm-gateway")
+ 
+ # SMM variable and RPC caller settings
+-set(SMM_GATEWAY_MAX_UEFI_VARIABLES 40 CACHE STRING "Maximum UEFI variable count")
++set(SMM_GATEWAY_MAX_UEFI_VARIABLES 35 CACHE STRING "Maximum UEFI variable count")
+ set(SMM_RPC_CALLER_SESSION_SHARED_MEMORY_SIZE 2*4096 CACHE STRING "RPC caller buffer size in SMMGW")
+ if (UEFI_AUTH_VAR)
+ set(SMM_SP_HEAP_SIZE 64*1024 CACHE STRING "SMM gateway SP heap size")
+-- 
+2.25.1
+
diff --git a/meta-arm-bsp/recipes-security/trusted-services/ts-arm-platforms.inc b/meta-arm-bsp/recipes-security/trusted-services/ts-arm-platforms.inc
index f8a94750..84c40aa8 100644
--- a/meta-arm-bsp/recipes-security/trusted-services/ts-arm-platforms.inc
+++ b/meta-arm-bsp/recipes-security/trusted-services/ts-arm-platforms.inc
@@ -15,6 +15,10 @@  SRC_URI:append:corstone1000  = " \
     file://0011-Fix-Avoid-redefinition-of-variables.patch \
     file://0012-Fix-GetNextVariableName-NameSize-input.patch \
     file://0013-Fix-error-handling-of-variable-index-loading.patch \
+    file://0014-Provide-crypto-api-to-create-uefi-priv-var-fingerpri.patch \
+    file://0015-Add-timestamp-validation-for-uefi-variables.patch \
+    file://0016-Isolate-common-uefi-variable-authentication-steps.patch \
+    file://0017-Implement-Private-Authenticated-Variable-verificatio.patch \
     "
 
 COMPATIBLE_MACHINE:fvp-base = "fvp-base"
diff --git a/meta-arm-bsp/recipes-security/trusted-services/ts-sp-smm-gateway_%.bbappend b/meta-arm-bsp/recipes-security/trusted-services/ts-sp-smm-gateway_%.bbappend
index 931d567f..628dfb48 100644
--- a/meta-arm-bsp/recipes-security/trusted-services/ts-sp-smm-gateway_%.bbappend
+++ b/meta-arm-bsp/recipes-security/trusted-services/ts-sp-smm-gateway_%.bbappend
@@ -4,6 +4,7 @@  EXTRA_OECMAKE:append:corstone1000 = " -DMM_COMM_BUFFER_ADDRESS="0x00000000 0x81F
     -DMM_COMM_BUFFER_PAGE_COUNT="1" \
     -DUEFI_AUTH_VAR=ON \
     -DUEFI_INTERNAL_CRYPTO=ON \
+    -DSMM_GATEWAY_MAX_UEFI_VARIABLES=60 \
     "
 
 EXTRA_OECMAKE:append:fvp-base = " -DMM_COMM_BUFFER_ADDRESS="0x00000000 0x81000000" \