1From 370811420cfa1c14146f45de308bbccf70408eb8 Mon Sep 17 00:00:00 2001
2From: Gabor Toth <gabor.toth2@arm.com>
3Date: Fri, 5 Apr 2024 11:19:37 +0200
4Subject: [PATCH] Provide crypto api to create uefi priv var fingerprint
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9Add new call to the crypto backend to calculate a hash of the common
10name of the signing certificate’s Subject and the tbsCertificate
11of the top-level issuer certificate.
12
13Signed-off-by: Gabor Toth <gabor.toth2@arm.com>
14Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TS/trusted-services/+/27953]
15---
16 .../client/caller/packed-c/crypto_caller.h    |   1 +
17 ...aller_get_uefi_priv_auth_var_fingerprint.h |  90 ++++++++
18 .../packed-c/packedc_crypto_client.cpp        |   8 +
19 .../protocol/packed-c/packedc_crypto_client.h |   4 +
20 .../service/crypto/client/psa/component.cmake |   1 +
21 .../service/crypto/client/psa/crypto_client.h |   5 +
22 .../psa/get_uefi_priv_auth_var_fingerprint.c  |  21 ++
23 .../service/crypto/provider/crypto_provider.c | 212 +++++++++++++++---
24 .../serializer/crypto_provider_serializer.h   |   8 +
25 .../packedc_crypto_provider_serializer.c      |  54 +++++
26 .../backend/direct/uefi_direct_backend.c      |  90 ++++++++
27 deployments/smm-gateway/smm-gateway.cmake     |   5 +
28 .../get_uefi_priv_auth_var_fingerprint.h      |  21 ++
29 protocols/service/crypto/packed-c/opcodes.h   |   1 +
30 14 files changed, 488 insertions(+), 33 deletions(-)
31 create mode 100644 components/service/crypto/client/caller/packed-c/crypto_caller_get_uefi_priv_auth_var_fingerprint.h
32 create mode 100644 components/service/crypto/client/psa/get_uefi_priv_auth_var_fingerprint.c
33 create mode 100644 protocols/service/crypto/packed-c/get_uefi_priv_auth_var_fingerprint.h
34
35diff --git a/components/service/crypto/client/caller/packed-c/crypto_caller.h b/components/service/crypto/client/caller/packed-c/crypto_caller.h
36index d834bc207..d5dd0f70d 100644
37--- a/components/service/crypto/client/caller/packed-c/crypto_caller.h
38+++ b/components/service/crypto/client/caller/packed-c/crypto_caller.h
39@@ -31,5 +31,6 @@
40 #include "crypto_caller_sign_hash.h"
41 #include "crypto_caller_verify_hash.h"
42 #include "crypto_caller_verify_pkcs7_signature.h"
43+#include "crypto_caller_get_uefi_priv_auth_var_fingerprint.h"
44
45 #endif /* PACKEDC_CRYPTO_CALLER_H */
46diff --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
47new file mode 100644
48index 000000000..d3446e445
49--- /dev/null
50+++ b/components/service/crypto/client/caller/packed-c/crypto_caller_get_uefi_priv_auth_var_fingerprint.h
51@@ -0,0 +1,90 @@
52+/*
53+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
54+ *
55+ * SPDX-License-Identifier: BSD-3-Clause
56+ */
57+
58+#ifndef PACKEDC_CRYPTO_CALLER_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_H
59+#define PACKEDC_CRYPTO_CALLER_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_H
60+
61+#include <common/tlv/tlv.h>
62+#include <protocols/common/efi/efi_status.h>
63+#include <protocols/rpc/common/packed-c/status.h>
64+#include <protocols/service/crypto/packed-c/opcodes.h>
65+#include <protocols/service/crypto/packed-c/get_uefi_priv_auth_var_fingerprint.h>
66+#include <service/common/client/service_client.h>
67+#include <stdlib.h>
68+#include <string.h>
69+
70+#ifdef __cplusplus
71+extern "C" {
72+#endif
73+
74+static inline int crypto_caller_get_uefi_priv_auth_var_fingerprint(struct service_client *context,
75+						       const uint8_t *signature_cert,
76+						       uint64_t signature_cert_len,
77+						       uint8_t *output)
78+{
79+	efi_status_t efi_status = EFI_SUCCESS;
80+	size_t req_len = 0;
81+
82+	if (signature_cert_len > UINT16_MAX)
83+		return RPC_ERROR_INVALID_VALUE;
84+
85+	struct tlv_record signature_record = {
86+		.tag = TS_CRYPTO_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_IN_TAG_SIGNATURE,
87+		.length = (uint16_t)signature_cert_len,
88+		.value = signature_cert
89+	};
90+
91+	req_len += tlv_required_space(signature_record.length);
92+
93+	rpc_call_handle call_handle;
94+	uint8_t *req_buf;
95+
96+	call_handle = rpc_caller_session_begin(context->session, &req_buf, req_len, 0);
97+
98+	if (call_handle) {
99+		uint8_t *resp_buf;
100+		size_t resp_len;
101+		service_status_t service_status;
102+		struct tlv_iterator req_iter;
103+
104+		tlv_iterator_begin(&req_iter, req_buf, req_len);
105+		tlv_encode(&req_iter, &signature_record);
106+
107+		context->rpc_status = rpc_caller_session_invoke(
108+			call_handle, TS_CRYPTO_OPCODE_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT, &resp_buf, &resp_len,
109+			&service_status);
110+
111+		if (context->rpc_status == RPC_SUCCESS) {
112+
113+			if (service_status == EFI_SUCCESS) {
114+
115+				struct tlv_const_iterator resp_iter;
116+				struct tlv_record decoded_record;
117+				tlv_const_iterator_begin(&resp_iter, resp_buf, resp_len);
118+
119+				if (tlv_find_decode(&resp_iter,
120+							TS_CRYPTO_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_OUT_TAG_IDENTIFIER, &decoded_record)) {
121+
122+					memcpy(output, decoded_record.value, PSA_HASH_MAX_SIZE);
123+				}
124+				else {
125+					/* Mandatory response parameter missing */
126+					efi_status = EFI_INVALID_PARAMETER;
127+				}
128+			}
129+		}
130+
131+		rpc_caller_session_end(call_handle);
132+	}
133+
134+	return efi_status;
135+}
136+
137+#ifdef __cplusplus
138+}
139+#endif
140+
141+#endif /* PACKEDC_CRYPTO_CALLER_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_H */
142diff --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
143index aaa71f0c8..e0f6a15a8 100644
144--- a/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.cpp
145+++ b/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.cpp
146@@ -428,3 +428,11 @@ int packedc_crypto_client::verify_pkcs7_signature(const uint8_t *signature_cert,
147 						    hash, hash_len, public_key_cert,
148 						    public_key_cert_len);
149 }
150+
151+int packedc_crypto_client::get_uefi_priv_auth_var_fingerprint(const uint8_t *signature_cert,
152+						  uint64_t signature_cert_len,
153+						  uint8_t *output)
154+{
155+	return crypto_caller_get_uefi_priv_auth_var_fingerprint(&m_client, signature_cert, signature_cert_len,
156+						    output);
157+}
158diff --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
159index 8d4f60cf9..ec6c51c7f 100644
160--- a/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.h
161+++ b/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.h
162@@ -236,6 +236,10 @@ public:
163 	int verify_pkcs7_signature(const uint8_t *signature_cert, uint64_t signature_cert_len,
164 				   const uint8_t *hash, uint64_t hash_len,
165 				   const uint8_t *public_key_cert, uint64_t public_key_cert_len);
166+
167+	int get_uefi_priv_auth_var_fingerprint(const uint8_t *signature_cert,
168+				    uint64_t signature_cert_len,
169+				    uint8_t *output);
170 };
171
172 #endif /* PACKEDC_CRYPTO_CLIENT_H */
173diff --git a/components/service/crypto/client/psa/component.cmake b/components/service/crypto/client/psa/component.cmake
174index 359db3b4a..5bee0c652 100644
175--- a/components/service/crypto/client/psa/component.cmake
176+++ b/components/service/crypto/client/psa/component.cmake
177@@ -32,4 +32,5 @@ target_sources(${TGT} PRIVATE
178 	"${CMAKE_CURRENT_LIST_DIR}/psa_sign_message.c"
179 	"${CMAKE_CURRENT_LIST_DIR}/psa_verify_message.c"
180 	"${CMAKE_CURRENT_LIST_DIR}/verify_pkcs7_signature.c"
181+	"${CMAKE_CURRENT_LIST_DIR}/get_uefi_priv_auth_var_fingerprint.c"
182 	)
183diff --git a/components/service/crypto/client/psa/crypto_client.h b/components/service/crypto/client/psa/crypto_client.h
184index 4b59bbe32..af04df11e 100644
185--- a/components/service/crypto/client/psa/crypto_client.h
186+++ b/components/service/crypto/client/psa/crypto_client.h
187@@ -7,10 +7,15 @@
188 #ifndef CRYPTO_CLIENT_H
189 #define CRYPTO_CLIENT_H
190
191+#include <stddef.h>
192 #include <stdint.h>
193
194 int verify_pkcs7_signature(const uint8_t *signature_cert, uint64_t signature_cert_len,
195 			   const uint8_t *hash, uint64_t hash_len, const uint8_t *public_key_cert,
196 			   uint64_t public_key_cert_len);
197
198+int get_uefi_priv_auth_var_fingerprint_handler(const uint8_t *signature_cert,
199+				    uint64_t signature_cert_len,
200+				    uint8_t *output);
201+
202 #endif /* CRYPTO_CLIENT_H */
203diff --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
204new file mode 100644
205index 000000000..702aaa0c4
206--- /dev/null
207+++ b/components/service/crypto/client/psa/get_uefi_priv_auth_var_fingerprint.c
208@@ -0,0 +1,21 @@
209+/*
210+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
211+ *
212+ * SPDX-License-Identifier: BSD-3-Clause
213+ */
214+
215+#include "crypto_caller_selector.h"
216+#include "crypto_client.h"
217+#include "psa_crypto_client.h"
218+
219+int get_uefi_priv_auth_var_fingerprint_handler(const uint8_t *signature_cert,
220+				    uint64_t signature_cert_len,
221+				    uint8_t *output)
222+{
223+	if (psa_crypto_client_instance.init_status != PSA_SUCCESS)
224+		return psa_crypto_client_instance.init_status;
225+
226+	return crypto_caller_get_uefi_priv_auth_var_fingerprint(&psa_crypto_client_instance.base,
227+						    signature_cert, signature_cert_len,
228+						    output);
229+}
230diff --git a/components/service/crypto/provider/crypto_provider.c b/components/service/crypto/provider/crypto_provider.c
231index 9cd520859..4535d6dbe 100644
232--- a/components/service/crypto/provider/crypto_provider.c
233+++ b/components/service/crypto/provider/crypto_provider.c
234@@ -3,12 +3,15 @@
235  *
236  * SPDX-License-Identifier: BSD-3-Clause
237  */
238+#include <protocols/common/efi/efi_status.h>
239 #include <protocols/rpc/common/packed-c/status.h>
240 #include <protocols/service/crypto/packed-c/opcodes.h>
241 #include <service/crypto/backend/crypto_backend.h>
242 #include <service/crypto/provider/crypto_provider.h>
243+#include <compiler.h>
244 #include <stdint.h>
245 #include <stdlib.h>
246+#include <string.h>
247
248 #include "crypto_partition.h"
249 #include "crypto_uuid.h"
250@@ -28,25 +31,27 @@ static rpc_status_t copy_key_handler(void *context, struct rpc_request *req);
251 static rpc_status_t purge_key_handler(void *context, struct rpc_request *req);
252 static rpc_status_t get_key_attributes_handler(void *context, struct rpc_request *req);
253 static rpc_status_t verify_pkcs7_signature_handler(void *context, struct rpc_request *req);
254+static rpc_status_t get_uefi_priv_auth_var_fingerprint_handler(void *context, struct rpc_request *req);
255
256 /* Handler mapping table for service */
257 static const struct service_handler handler_table[] = {
258-	{ TS_CRYPTO_OPCODE_GENERATE_KEY,           generate_key_handler },
259-	{ TS_CRYPTO_OPCODE_DESTROY_KEY,            destroy_key_handler },
260-	{ TS_CRYPTO_OPCODE_EXPORT_KEY,             export_key_handler },
261-	{ TS_CRYPTO_OPCODE_EXPORT_PUBLIC_KEY,      export_public_key_handler },
262-	{ TS_CRYPTO_OPCODE_IMPORT_KEY,             import_key_handler },
263-	{ TS_CRYPTO_OPCODE_SIGN_HASH,              asymmetric_sign_handler },
264-	{ TS_CRYPTO_OPCODE_VERIFY_HASH,            asymmetric_verify_handler },
265-	{ TS_CRYPTO_OPCODE_ASYMMETRIC_DECRYPT,     asymmetric_decrypt_handler },
266-	{ TS_CRYPTO_OPCODE_ASYMMETRIC_ENCRYPT,     asymmetric_encrypt_handler },
267-	{ TS_CRYPTO_OPCODE_GENERATE_RANDOM,        generate_random_handler },
268-	{ TS_CRYPTO_OPCODE_COPY_KEY,               copy_key_handler },
269-	{ TS_CRYPTO_OPCODE_PURGE_KEY,              purge_key_handler },
270-	{ TS_CRYPTO_OPCODE_GET_KEY_ATTRIBUTES,     get_key_attributes_handler },
271-	{ TS_CRYPTO_OPCODE_SIGN_MESSAGE,           asymmetric_sign_handler },
272-	{ TS_CRYPTO_OPCODE_VERIFY_MESSAGE,         asymmetric_verify_handler },
273-	{ TS_CRYPTO_OPCODE_VERIFY_PKCS7_SIGNATURE, verify_pkcs7_signature_handler },
274+	{ TS_CRYPTO_OPCODE_GENERATE_KEY,            generate_key_handler },
275+	{ TS_CRYPTO_OPCODE_DESTROY_KEY,             destroy_key_handler },
276+	{ TS_CRYPTO_OPCODE_EXPORT_KEY,              export_key_handler },
277+	{ TS_CRYPTO_OPCODE_EXPORT_PUBLIC_KEY,       export_public_key_handler },
278+	{ TS_CRYPTO_OPCODE_IMPORT_KEY,              import_key_handler },
279+	{ TS_CRYPTO_OPCODE_SIGN_HASH,               asymmetric_sign_handler },
280+	{ TS_CRYPTO_OPCODE_VERIFY_HASH,             asymmetric_verify_handler },
281+	{ TS_CRYPTO_OPCODE_ASYMMETRIC_DECRYPT,      asymmetric_decrypt_handler },
282+	{ TS_CRYPTO_OPCODE_ASYMMETRIC_ENCRYPT,      asymmetric_encrypt_handler },
283+	{ TS_CRYPTO_OPCODE_GENERATE_RANDOM,         generate_random_handler },
284+	{ TS_CRYPTO_OPCODE_COPY_KEY,                copy_key_handler },
285+	{ TS_CRYPTO_OPCODE_PURGE_KEY,               purge_key_handler },
286+	{ TS_CRYPTO_OPCODE_GET_KEY_ATTRIBUTES,      get_key_attributes_handler },
287+	{ TS_CRYPTO_OPCODE_SIGN_MESSAGE,            asymmetric_sign_handler },
288+	{ TS_CRYPTO_OPCODE_VERIFY_MESSAGE,          asymmetric_verify_handler },
289+	{ TS_CRYPTO_OPCODE_VERIFY_PKCS7_SIGNATURE,  verify_pkcs7_signature_handler },
290+	{ TS_CRYPTO_OPCODE_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT, get_uefi_priv_auth_var_fingerprint_handler },
291 };
292
293 struct rpc_service_interface *
294@@ -664,33 +669,44 @@ static rpc_status_t verify_pkcs7_signature_handler(void *context, struct rpc_req
295 	}
296
297 	if (rpc_status == RPC_SUCCESS) {
298-		/* Parse the public key certificate */
299-		mbedtls_x509_crt signer_certificate;
300+		/* Parse the PKCS#7 DER encoded signature block */
301+		mbedtls_pkcs7 pkcs7_structure;
302
303-		mbedtls_x509_crt_init(&signer_certificate);
304+		mbedtls_pkcs7_init(&pkcs7_structure);
305
306-		mbedtls_status = mbedtls_x509_crt_parse_der(&signer_certificate, public_key_cert,
307-							    public_key_cert_len);
308+		mbedtls_status = mbedtls_pkcs7_parse_der(&pkcs7_structure, signature_cert,
309+								signature_cert_len);
310
311-		if (mbedtls_status == 0) {
312-			/* Parse the PKCS#7 DER encoded signature block */
313-			mbedtls_pkcs7 pkcs7_structure;
314+		if (mbedtls_status == MBEDTLS_PKCS7_SIGNED_DATA) {
315
316-			mbedtls_pkcs7_init(&pkcs7_structure);
317+			/*
318+			 * If a separate public key is provided, verify the signature with it,
319+			 * else use the key from the pkcs7 signature structure, because it is
320+			 * a self-signed certificate.
321+			 */
322+			if(public_key_cert_len) {
323+				/* Parse the public key certificate */
324+				mbedtls_x509_crt signer_certificate;
325
326-			mbedtls_status = mbedtls_pkcs7_parse_der(&pkcs7_structure, signature_cert,
327-								 signature_cert_len);
328+				mbedtls_x509_crt_init(&signer_certificate);
329
330-			if (mbedtls_status == MBEDTLS_PKCS7_SIGNED_DATA) {
331-				/* Verify hash against signed hash */
332+				mbedtls_status = mbedtls_x509_crt_parse_der(&signer_certificate, public_key_cert,
333+									public_key_cert_len);
334+
335+				if (mbedtls_status == 0) {
336+					/* Verify hash against signed hash */
337+					mbedtls_status = mbedtls_pkcs7_signed_hash_verify(
338+						&pkcs7_structure, &signer_certificate, hash, hash_len);
339+				}
340+
341+				mbedtls_x509_crt_free(&signer_certificate);
342+			} else {
343 				mbedtls_status = mbedtls_pkcs7_signed_hash_verify(
344-					&pkcs7_structure, &signer_certificate, hash, hash_len);
345+					&pkcs7_structure, &pkcs7_structure.private_signed_data.private_certs, hash, hash_len);
346 			}
347-
348-			mbedtls_pkcs7_free(&pkcs7_structure);
349 		}
350
351-		mbedtls_x509_crt_free(&signer_certificate);
352+		mbedtls_pkcs7_free(&pkcs7_structure);
353 	}
354
355 	free(signature_cert);
356@@ -702,6 +718,128 @@ static rpc_status_t verify_pkcs7_signature_handler(void *context, struct rpc_req
357
358 	return rpc_status;
359 }
360+
361+/*
362+ * Official value: http://www.oid-info.com/get/2.5.4.3
363+ * Hex converter: https://misc.daniel-marschall.de/asn.1/oid-converter/online.php
364+ */
365+static const mbedtls_asn1_buf* findCommonName(const mbedtls_x509_name *name)
366+{
367+	uint8_t CN_oid_tag = 0x06;
368+	uint8_t CN_oid_len = 0x03;
369+	uint8_t CN_oid_val[3] = {0x55, 0x04, 0x03};
370+
371+	while (name)
372+	{
373+		if (name->oid.tag == CN_oid_tag && name->oid.len == CN_oid_len) {
374+			if (name->oid.p != NULL) {
375+				if (!memcmp(name->oid.p, CN_oid_val, CN_oid_len))
376+					return &name->val;
377+			}
378+		}
379+
380+		name = name->next;
381+	}
382+
383+	return NULL;
384+}
385+
386+static rpc_status_t get_uefi_priv_auth_var_fingerprint_handler(void *context, struct rpc_request *req)
387+{
388+	rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
389+	struct rpc_buffer *req_buf = &req->request;
390+	const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
391+
392+	int mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
393+
394+	uint8_t *signature_cert = NULL;
395+	uint64_t signature_cert_len = 0;
396+
397+	if (serializer) {
398+		/* First collect the lengths of the field */
399+		rpc_status = serializer->deserialize_get_uefi_priv_auth_var_fingerprint_req(
400+			req_buf, NULL, &signature_cert_len);
401+
402+		if (rpc_status == RPC_SUCCESS) {
403+			/* Allocate the needed space and get the data */
404+			signature_cert = (uint8_t *)malloc(signature_cert_len);
405+
406+			if (signature_cert) {
407+				rpc_status = serializer->deserialize_get_uefi_priv_auth_var_fingerprint_req(
408+					req_buf, signature_cert, &signature_cert_len);
409+			} else {
410+				rpc_status = RPC_ERROR_RESOURCE_FAILURE;
411+			}
412+		}
413+	}
414+
415+	if (rpc_status == RPC_SUCCESS) {
416+		/* Parse the PKCS#7 DER encoded signature block */
417+		mbedtls_pkcs7 pkcs7_structure;
418+
419+		mbedtls_pkcs7_init(&pkcs7_structure);
420+
421+		mbedtls_status = mbedtls_pkcs7_parse_der(&pkcs7_structure, signature_cert,
422+								signature_cert_len);
423+
424+		if (mbedtls_status == MBEDTLS_PKCS7_SIGNED_DATA) {
425+
426+			uint8_t output_buffer[PSA_HASH_MAX_SIZE] =  { 0 };
427+			size_t __maybe_unused output_size = 0;
428+			const mbedtls_asn1_buf *signerCertCN = NULL;
429+			const mbedtls_x509_crt *topLevelCert = &pkcs7_structure.private_signed_data.private_certs;
430+			const mbedtls_x509_buf *toplevelCertTbs = NULL;
431+			struct rpc_buffer *resp_buf = &req->response;;
432+			psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
433+
434+			/* Find common name field of the signing certificate, which is the first in the chain */
435+			signerCertCN = findCommonName(&topLevelCert->subject);
436+			if (!signerCertCN)
437+				mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
438+
439+			/* Get the TopLevel certificate which is the last in the chain */
440+			while(topLevelCert->next)
441+				topLevelCert = topLevelCert->next;
442+			toplevelCertTbs = &topLevelCert->tbs;
443+
444+			/* Hash the data to create the fingerprint */
445+			op = psa_hash_operation_init();
446+
447+			if (psa_hash_setup(&op, PSA_ALG_SHA_256) != PSA_SUCCESS)
448+				mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
449+
450+			if (psa_hash_update(&op, signerCertCN->p, signerCertCN->len)) {
451+				psa_hash_abort(&op);
452+				mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
453+			}
454+
455+			if (psa_hash_update(&op, toplevelCertTbs->p, toplevelCertTbs->len)) {
456+				psa_hash_abort(&op);
457+				mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
458+			}
459+
460+			if (psa_hash_finish(&op, (uint8_t*)&output_buffer, PSA_HASH_MAX_SIZE, &output_size)) {
461+				psa_hash_abort(&op);
462+				mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
463+			}
464+
465+			/* Clear the remaining part of the buffer for consistency */
466+			memset(&output_buffer[output_size], 0, PSA_HASH_MAX_SIZE - output_size);
467+
468+			rpc_status = serializer->serialize_get_uefi_priv_auth_var_fingerprint_resp(
469+				resp_buf, (uint8_t*)&output_buffer);
470+		}
471+
472+		mbedtls_pkcs7_free(&pkcs7_structure);
473+	}
474+
475+	free(signature_cert);
476+
477+	/* Provide the result of the verification */
478+	req->service_status = (mbedtls_status == MBEDTLS_PKCS7_SIGNED_DATA) ? EFI_SUCCESS : EFI_COMPROMISED_DATA;
479+
480+	return rpc_status;
481+}
482 #else
483 static rpc_status_t verify_pkcs7_signature_handler(void *context, struct rpc_request *req)
484 {
485@@ -710,4 +848,12 @@ static rpc_status_t verify_pkcs7_signature_handler(void *context, struct rpc_req
486
487 	return RPC_ERROR_INTERNAL;
488 }
489+
490+static rpc_status_t get_uefi_priv_auth_var_fingerprint_handler(void *context, struct rpc_request *req)
491+{
492+	(void)context;
493+	(void)req;
494+
495+	return RPC_ERROR_INTERNAL;
496+}
497 #endif
498diff --git a/components/service/crypto/provider/serializer/crypto_provider_serializer.h b/components/service/crypto/provider/serializer/crypto_provider_serializer.h
499index bd5336c3d..2b965afdb 100644
500--- a/components/service/crypto/provider/serializer/crypto_provider_serializer.h
501+++ b/components/service/crypto/provider/serializer/crypto_provider_serializer.h
502@@ -126,6 +126,14 @@ struct crypto_provider_serializer {
503 							       uint8_t *hash, uint64_t *hash_len,
504 							       uint8_t *public_key_cert,
505 							       uint64_t *public_key_cert_len);
506+
507+	/* Operation: get_uefi_priv_auth_var_fingerprintentifier */
508+	rpc_status_t (*deserialize_get_uefi_priv_auth_var_fingerprint_req)(const struct rpc_buffer *req_buf,
509+								uint8_t *signed_data,
510+								uint64_t *signed_data_len);
511+
512+	rpc_status_t (*serialize_get_uefi_priv_auth_var_fingerprint_resp)(struct rpc_buffer *resp_buf,
513+							       const uint8_t *output);
514 };
515
516 #endif /* CRYPTO_PROVIDER_SERIALIZER_H */
517diff --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
518index 050ef2f7d..89e07e2c8 100644
519--- a/components/service/crypto/provider/serializer/packed-c/packedc_crypto_provider_serializer.c
520+++ b/components/service/crypto/provider/serializer/packed-c/packedc_crypto_provider_serializer.c
521@@ -22,6 +22,7 @@
522 #include <protocols/service/crypto/packed-c/sign_hash.h>
523 #include <protocols/service/crypto/packed-c/verify_hash.h>
524 #include <protocols/service/crypto/packed-c/verify_pkcs7_signature.h>
525+#include <protocols/service/crypto/packed-c/get_uefi_priv_auth_var_fingerprint.h>
526 #include <service/crypto/backend/crypto_backend.h>
527 #include <stdlib.h>
528 #include <string.h>
529@@ -675,6 +676,57 @@ static rpc_status_t deserialize_verify_pkcs7_signature_req(
530 	return rpc_status;
531 }
532
533+/* Operation: get_uefi_priv_auth_var_fingerprintentifier */
534+static rpc_status_t deserialize_get_uefi_priv_auth_var_fingerprint_req(const struct rpc_buffer *req_buf,
535+							uint8_t *signed_data,
536+							uint64_t *signed_data_len)
537+{
538+	rpc_status_t rpc_status = RPC_ERROR_INVALID_REQUEST_BODY;
539+
540+	if (req_buf->data_length) {
541+		struct tlv_const_iterator req_iter;
542+		struct tlv_record decoded_record;
543+
544+		rpc_status = RPC_SUCCESS;
545+
546+		tlv_const_iterator_begin(&req_iter, (uint8_t *)req_buf->data, req_buf->data_length);
547+
548+		if (tlv_find_decode(&req_iter, TS_CRYPTO_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_IN_TAG_SIGNATURE,
549+				    &decoded_record)) {
550+			*signed_data_len = decoded_record.length;
551+
552+			if (signed_data)
553+				memcpy(signed_data, decoded_record.value, decoded_record.length);
554+		} else {
555+			/* Default to a zero length */
556+			*signed_data_len = 0;
557+		}
558+	}
559+
560+	return rpc_status;
561+}
562+
563+static rpc_status_t serialize_get_uefi_priv_auth_var_fingerprint_resp(struct rpc_buffer *resp_buf,
564+							const uint8_t *output)
565+{
566+	rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
567+	struct tlv_iterator resp_iter;
568+	struct tlv_record out_record;
569+
570+	out_record.tag = TS_CRYPTO_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_OUT_TAG_IDENTIFIER;
571+	out_record.length = PSA_HASH_MAX_SIZE;
572+	out_record.value = output;
573+
574+	tlv_iterator_begin(&resp_iter, resp_buf->data, resp_buf->size);
575+
576+	if (tlv_encode(&resp_iter, &out_record)) {
577+		resp_buf->data_length = tlv_required_space(PSA_HASH_MAX_SIZE);
578+		rpc_status = RPC_SUCCESS;
579+	}
580+
581+	return rpc_status;
582+}
583+
584 /* Singleton method to provide access to the serializer instance */
585 const struct crypto_provider_serializer *packedc_crypto_provider_serializer_instance(void)
586 {
587@@ -704,6 +756,8 @@ const struct crypto_provider_serializer *packedc_crypto_provider_serializer_inst
588 		deserialize_generate_random_req,
589 		serialize_generate_random_resp,
590 		deserialize_verify_pkcs7_signature_req,
591+		deserialize_get_uefi_priv_auth_var_fingerprint_req,
592+		serialize_get_uefi_priv_auth_var_fingerprint_resp
593 	};
594
595 	return &instance;
596diff --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
597index bf978c5dd..c7ca07254 100644
598--- a/components/service/uefi/smm_variable/backend/direct/uefi_direct_backend.c
599+++ b/components/service/uefi/smm_variable/backend/direct/uefi_direct_backend.c
600@@ -9,6 +9,8 @@
601 #include <mbedtls/pkcs7.h>
602 #include <mbedtls/x509_crt.h>
603 #include <stdint.h>
604+#include <string.h>
605+#include <compiler.h>
606
607 int verify_pkcs7_signature(const uint8_t *signature_cert, uint64_t signature_cert_len,
608 			   const uint8_t *hash, uint64_t hash_len, const uint8_t *public_key_cert,
609@@ -46,3 +48,91 @@ int verify_pkcs7_signature(const uint8_t *signature_cert, uint64_t signature_cer
610
611 	return mbedtls_status;
612 }
613+
614+/*
615+ * Official value: http://www.oid-info.com/get/2.5.4.3
616+ * Hex converter: https://misc.daniel-marschall.de/asn.1/oid-converter/online.php
617+ */
618+static const mbedtls_asn1_buf* findCommonName(const mbedtls_x509_name *name)
619+{
620+	uint8_t CN_oid_tag = 0x06;
621+	uint8_t CN_oid_len = 0x03;
622+	uint8_t CN_oid_val[3] = {0x55, 0x04, 0x03};
623+
624+	while (name)
625+	{
626+		if (name->oid.tag == CN_oid_tag && name->oid.len == CN_oid_len) {
627+			if (name->oid.p != NULL) {
628+				if (!memcmp(name->oid.p, CN_oid_val, CN_oid_len))
629+					return &name->val;
630+			}
631+		}
632+
633+		name = name->next;
634+	}
635+
636+	return NULL;
637+}
638+
639+int get_uefi_priv_auth_var_fingerprint_handler(const uint8_t *signature_cert,
640+				    uint64_t signature_cert_len,
641+				    uint8_t *output)
642+{
643+	int mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
644+
645+	/* Parse the PKCS#7 DER encoded signature block */
646+	mbedtls_pkcs7 pkcs7_structure;
647+
648+	mbedtls_pkcs7_init(&pkcs7_structure);
649+
650+	mbedtls_status = mbedtls_pkcs7_parse_der(&pkcs7_structure, signature_cert,
651+							signature_cert_len);
652+
653+	if (mbedtls_status == MBEDTLS_PKCS7_SIGNED_DATA) {
654+
655+		uint8_t output_buffer[PSA_HASH_MAX_SIZE] =  { 0 };
656+		size_t __maybe_unused output_size = 0;
657+		const mbedtls_asn1_buf *signerCertCN = NULL;
658+		const mbedtls_x509_crt *topLevelCert = &pkcs7_structure.private_signed_data.private_certs;
659+		const mbedtls_x509_buf *toplevelCertTbs = NULL;
660+		psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
661+
662+		/* Find common name field of the signing certificate, which is the first in the chain */
663+		signerCertCN = findCommonName(&topLevelCert->subject);
664+		if (!signerCertCN)
665+			mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
666+
667+		/* Get the TopLevel certificate which is the last in the chain */
668+		while(topLevelCert->next)
669+			topLevelCert = topLevelCert->next;
670+		toplevelCertTbs = &topLevelCert->tbs;
671+
672+		/* Hash the data to create the fingerprint */
673+		op = psa_hash_operation_init();
674+
675+		if (psa_hash_setup(&op, PSA_ALG_SHA_256) != PSA_SUCCESS)
676+			mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
677+
678+		if (psa_hash_update(&op, signerCertCN->p, signerCertCN->len)) {
679+			psa_hash_abort(&op);
680+			mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
681+		}
682+
683+		if (psa_hash_update(&op, toplevelCertTbs->p, toplevelCertTbs->len)) {
684+			psa_hash_abort(&op);
685+			mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
686+		}
687+
688+		if (psa_hash_finish(&op, (uint8_t*)&output_buffer, PSA_HASH_MAX_SIZE, &output_size)) {
689+			psa_hash_abort(&op);
690+			mbedtls_status = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
691+		}
692+
693+		/* Clear the remaining part of the buffer for consistency */
694+		memset(&output_buffer[output_size], 0, PSA_HASH_MAX_SIZE - output_size);
695+	}
696+
697+	mbedtls_pkcs7_free(&pkcs7_structure);
698+
699+	return mbedtls_status;
700+}
701diff --git a/deployments/smm-gateway/smm-gateway.cmake b/deployments/smm-gateway/smm-gateway.cmake
702index e5ee03b60..de519892d 100644
703--- a/deployments/smm-gateway/smm-gateway.cmake
704+++ b/deployments/smm-gateway/smm-gateway.cmake
705@@ -17,6 +17,11 @@ include(${TS_ROOT}/external/MbedTLS/MbedTLS.cmake)
706 target_link_libraries(smm-gateway PRIVATE MbedTLS::mbedcrypto)
707 target_link_libraries(smm-gateway PRIVATE MbedTLS::mbedx509)
708
709+# Pass the location of the mbedtls config file to C preprocessor.
710+target_compile_definitions(smm-gateway PRIVATE
711+		MBEDTLS_USER_CONFIG_FILE="${MBEDTLS_USER_CONFIG_FILE}"
712+)
713+
714 target_compile_definitions(smm-gateway PRIVATE
715 	-DUEFI_INTERNAL_CRYPTO
716 )
717diff --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
718new file mode 100644
719index 000000000..29964b33c
720--- /dev/null
721+++ b/protocols/service/crypto/packed-c/get_uefi_priv_auth_var_fingerprint.h
722@@ -0,0 +1,21 @@
723+/*
724+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
725+ * SPDX-License-Identifier: BSD-3-Clause
726+ */
727+
728+#ifndef TS_CRYPTO_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_H
729+#define TS_CRYPTO_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_H
730+
731+#include <stdint.h>
732+
733+/* Variable length output parameter tags */
734+enum {
735+	TS_CRYPTO_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_OUT_TAG_IDENTIFIER = 1,
736+};
737+
738+/* Variable length input parameter tags */
739+enum {
740+	TS_CRYPTO_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_IN_TAG_SIGNATURE = 1,
741+};
742+
743+#endif /* TS_CRYPTO_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT_H */
744diff --git a/protocols/service/crypto/packed-c/opcodes.h b/protocols/service/crypto/packed-c/opcodes.h
745index 35b81599b..8bc2b49b0 100644
746--- a/protocols/service/crypto/packed-c/opcodes.h
747+++ b/protocols/service/crypto/packed-c/opcodes.h
748@@ -28,6 +28,7 @@
749 #define TS_CRYPTO_OPCODE_SIGN_MESSAGE           (TS_CRYPTO_OPCODE_BASE + 16)
750 #define TS_CRYPTO_OPCODE_VERIFY_MESSAGE         (TS_CRYPTO_OPCODE_BASE + 17)
751 #define TS_CRYPTO_OPCODE_VERIFY_PKCS7_SIGNATURE (TS_CRYPTO_OPCODE_BASE + 18)
752+#define TS_CRYPTO_OPCODE_GET_UEFI_PRIV_AUTH_VAR_FINGERPRINT (TS_CRYPTO_OPCODE_BASE + 19)
753
754 /* Hash operations */
755 #define TS_CRYPTO_OPCODE_HASH_BASE              (0x0200)
756--
7572.25.1
758
759