blob: f7279fa213d08d805199ebbe0a3b64bef3584f1a [file] [log] [blame]
/*
* Copyright (c) 2021-2023, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stddef.h>
#include <protocols/rpc/common/packed-c/encoding.h>
#include <service/uefi/smm_variable/provider/smm_variable_provider.h>
#include <service/crypto/client/psa/psa_crypto_client.h>
#include "psa/crypto.h"
#include <service/secure_storage/backend/secure_storage_client/secure_storage_client.h>
#include <service/secure_storage/backend/mock_store/mock_store.h>
#include <service_locator.h>
/* Build-time default configuration */
/* Default to using the Protected Storage SP */
#ifndef SMM_GATEWAY_NV_STORE_SN
#define SMM_GATEWAY_NV_STORE_SN "sn:ffa:751bf801-3dde-4768-a514-0f10aeed1790:0"
#endif
#if defined(UEFI_AUTH_VAR) && !defined(UEFI_INTERNAL_CRYPTO)
/* Default to using the Crypto SP */
#ifndef SMM_GATEWAY_CRYPTO_SN
#define SMM_GATEWAY_CRYPTO_SN "sn:ffa:d9df52d5-16a2-4bb2-9aa4-d26d3b84e8c0:0"
#endif
#endif
/* Default maximum number of UEFI variables */
#ifndef SMM_GATEWAY_MAX_UEFI_VARIABLES
#define SMM_GATEWAY_MAX_UEFI_VARIABLES (40)
#endif
/* The smm_gateway instance - it's a singleton */
static struct smm_gateway
{
struct smm_variable_provider smm_variable_provider;
struct secure_storage_client nv_store_client;
struct mock_store volatile_store;
struct service_context *nv_storage_service_context;
struct rpc_caller_session *nv_storage_session;
#if defined(UEFI_AUTH_VAR) && !defined(UEFI_INTERNAL_CRYPTO)
struct service_context *crypto_service_context;
struct rpc_caller_session *crypto_session;
#endif
} smm_gateway_instance;
#if defined(UEFI_AUTH_VAR) && !defined(UEFI_INTERNAL_CRYPTO)
bool create_crypto_binding(void)
{
psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
smm_gateway_instance.crypto_service_context = NULL;
smm_gateway_instance.crypto_session = NULL;
smm_gateway_instance.crypto_service_context = service_locator_query(SMM_GATEWAY_CRYPTO_SN);
if (!smm_gateway_instance.crypto_service_context)
goto err;
smm_gateway_instance.crypto_session =
service_context_open(smm_gateway_instance.crypto_service_context);
if (!smm_gateway_instance.crypto_session)
goto err;
/* Initialize the crypto client */
psa_status = psa_crypto_client_init(smm_gateway_instance.crypto_session);
if (psa_status != PSA_SUCCESS)
goto err;
psa_status = psa_crypto_init();
if (psa_status != PSA_SUCCESS)
goto err;
return true;
err:
if (smm_gateway_instance.crypto_session != NULL)
{
service_context_close(smm_gateway_instance.crypto_service_context, smm_gateway_instance.crypto_session);
smm_gateway_instance.crypto_session = NULL;
}
if (smm_gateway_instance.crypto_service_context != NULL)
{
service_context_relinquish(smm_gateway_instance.crypto_service_context);
smm_gateway_instance.crypto_service_context = NULL;
}
return false;
}
#else
#define create_crypto_binding(a) (true)
#endif
struct rpc_service_interface *smm_gateway_create(uint32_t owner_id)
{
service_locator_envinit();
/* todo - add option to use configurable service location */
smm_gateway_instance.nv_storage_service_context =
service_locator_query(SMM_GATEWAY_NV_STORE_SN);
if (!smm_gateway_instance.nv_storage_service_context)
return NULL;
smm_gateway_instance.nv_storage_session = service_context_open(
smm_gateway_instance.nv_storage_service_context);
if (!smm_gateway_instance.nv_storage_session)
return NULL;
/* Initialize a storage client to access the remote NV store */
struct storage_backend *persistent_backend = secure_storage_client_init(
&smm_gateway_instance.nv_store_client,
smm_gateway_instance.nv_storage_session);
if (!persistent_backend)
return NULL;
/* Initialize the volatile storage backend */
struct storage_backend *volatile_backend = mock_store_init(
&smm_gateway_instance.volatile_store);
if (!volatile_backend)
return NULL;
/* Initialize the smm_variable service provider */
struct rpc_service_interface *service_iface = smm_variable_provider_init(
&smm_gateway_instance.smm_variable_provider,
owner_id,
SMM_GATEWAY_MAX_UEFI_VARIABLES,
persistent_backend,
volatile_backend);
if (!create_crypto_binding())
return NULL;
return service_iface;
}