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