blob: b2c8a7bb1bdf93b29b38ccb8657a27b622f7f1cc [file] [log] [blame]
UEFI SMM Services
=================
The Trusted Services project provides support for UEFI System Management Mode (SMM) services via the
SMM Gateway secure partition. The SMM Gateway adopts the API Gateway design pattern, popular in
microservices architecture. The pattern decouples clients from backend service providers using an
API gateway that presents a domain specific interface to clients while delegating operations to a
set of backend microservices. An API gateway will typically use multiple backend services and may
perform protocol translation while presenting a single service entry point for clients. The SMM
Gateway works in a similar manner - clients access SMM services using standard SMM protocol messages,
carried by an RPC mechanism. Service requests are forwarded by the SMM Gateway to backend service
providers for operations such as secure persistent storage and signature verification.
SMM Gateway is intended to be used on non-EDK2 platforms as an alternative to the EDK2 StandaloneMM
(StMM) component. The current SMM Gateway version only supports the SMM Variable service. Additional
SMM service providers may be added to SMM Gateway if required. By deliberately limiting functionality
and exploiting backend services, the SMM Gateway SP can be significantly lighter-weight than StMM.
This option is intended to be used on more resource constrained devices that tend to use u-boot.
There is of course the possibility that other SMM services will need to be supported in the future.
In such cases, a judgement should be made as to whether StMM should be used rather than extending the SP.
.. uml:: uml/SmmGatewayOverview.puml
SMM Variable Service
--------------------
Overview
''''''''
UEFI Variable support is provided by the *smm_variable* service provider component. This service provider
is structured in the same way as other service providers within the TS project. Features of this
component are:
* Source file location: ``components/service/uefi/smm_variable``
* Public interface definitions: ``protocols/service/smm_variable``
* Can be used with any RPC layer - not tied to MM Communicate RPC.
* Volatile and non-volatile storage is accessed via instances of the common *storage_backend* interface.
The *smm-gateway/opteesp* and *smm-gateway/sp* deployments integrate the *smm_variable* service provider with the following:
* An MM Communicate based RPC endpoint.
* A *mock_store* instance for volatile variables.
* A *secure_storage_client* for non-volatile variables.
* A *crypto client* for signature verification.
During SP initialization, the *smm-gateway* uses pre-configured information to discover a backend secure
storage SP for NV storage and a crypto SP to verify signatures needed for UEFI variable authentication.
Crypto SP is accessible only if UEFI_AUTH_VAR is enabled.
The following diagram illustrates how the *smm_variable* service provider is integrated into the *smm-gateway*.
.. image:: image/smm-gateway-layers.svg
Because the *smm_variable* service provider is independent of any particular environment, alternative deployments
are possible e.g.
* *smm_variable* service provider running within a GP TA with storage off-loaded to the GP TEE Internal API.
* *smm_variable* service provider running within a secure enclave with its own internal flash storage.
Supported Functions
'''''''''''''''''''
The *smm_variable* service provider supports the following functions:
.. list-table::
:header-rows: 1
* - SMM Variable Function
- Purpose
- Backend service interaction
* - SMM_VARIABLE_FUNCTION_GET_VARIABLE
- Get variable data identified by GUID/name.
- Query index and get object from appropriate storage backend.
* - SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME
- Called multiple times to enumerate stored variables.
- Find variable in index and return next.
* - SMM_VARIABLE_FUNCTION_SET_VARIABLE
- Adds a new variable or updates an existing one.
- | Sets object in storage backend and if necessary, updates index
| and syncs to storage.
* - SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO
- Returns information about the variable store.
- Iterates over stored variables to determine space used.
* - SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE
- Called by OS when boot phase is complete.
- | Updates view of runtime state held by smm_variable service provider.
| State variable used when implementing state dependent access control.
* - SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_SET
- | Set constraints that are checked on the SetVariable operation.
| Allows a platform to set check policy.
- | Variable index holds variable check constraints object for each variable.
| This is updated by this function.
* - SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_GET
- Get the variable check constraints.
- Reads the variable check constraints object.
* - SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE
- | Returns the maximum variable data size, excluding any
| auth header.
- | Considers size constraints imposed by backend stores and RPC response
| payload constraints.
Supported Variable Attributes
'''''''''''''''''''''''''''''
The following variable attributes are supported:
.. list-table::
:widths: 3 1 3
:header-rows: 1
* - SMM Variable Attribute
- Support
- Comment
* - EFI_VARIABLE_NON_VOLATILE
- yes
- Determines which storage backend is used.
* - EFI_VARIABLE_BOOTSERVICE_ACCESS
- yes
- Boot service access controlled by smm_variable service provider.
* - EFI_VARIABLE_RUNTIME_ACCESS
- yes
- Runtime access controlled by smm_variable service provider.
* - EFI_VARIABLE_HARDWARE_ERROR_RECORD
- no
- If the attribute contains this value, VariableName and VendorGuid must comply with the rules
stated in Section 8.2.4.2 and Appendix P of the standard.
* - EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
- no
- DEPRECATED
* - EFI_VARIABLE_ENHANCED_AUTHENTICATED_ACCESS
- no
- Authentication with EFI_VARIABLE_AUTHENTICATION_3 descriptor is enabled.
* - EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
- yes
- Authentication with EFI_VARIABLE_AUTHENTICATION_2 descriptor is enabled.
* - EFI_VARIABLE_APPEND_WRITE
- yes
- Implemented by overwriting entire variable data.
Limitations
'''''''''''
.. list-table::
:header-rows: 1
* - Description
- Value
* - Maximum size of a single variable
- 4096 bytes
* - Supported type of signature list element
- DER-encoded X.509 certificates
* - Supported type of public keys
- DER-encoded SignedData structure per PKCS#7 version 1.5, with or without a DER-encoded
ContentInfo structure per PKCS#7 version 1.5.
Variable authentication
'''''''''''''''''''''''
UEFI variable authentication is a method to ensure that a UEFI variable can only be modified
by those who has proper rights. This restricts only the writing of these variables, while reading
is only limited by the state of the system (boot versus runtime access).
Key Store Variables
```````````````````
Key Store variables store authentication keys, and have predefined special names to specify the
keys scope (area of effect). When a write access to a variable with an active
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is being made, the signature part of
the write access will be verified against the appropriate key Store variable.
Access will only be granted if the signature is valid.
The following table lists which Key Store variables defined by the UEFI standard are implemented.
.. list-table::
:header-rows: 1
* - Variable name
- Description
- Supported
* - Platform Key (PK)
- Root of trust. If it is not set the authentication is disabled, all write requests are successful.
- yes
* - Key Exchange Key Database (KEK)
- Protects key store databases from unauthorized modifications.
- yes
* - Signature Database (db)
- If a variable write request is signed by the public key whose private pair is
stored here the authentication will pass.
- yes
* - Blacklist Signature Database (dbx)
- Contains signatures of software that must not run on the platform.
- no
* - Authorized Recovery Signature Database (dbr)
- Contains signatures of software that can be run for recovery.
- no
* - Timestamp Signature Database (dbt)
- Same as db, but the timestamp of the certificate is also verified.
- no
There is no support for initializing the values of the read-only global variables containing
default values of the key store variables (e.g. PKDefault, KEKDefault, etc.).
The following diagram shows variable authentication hierarchy.
*A → B means A has the right to verify write request to B*
.. uml::
@startuml
[PK] --> [PK]
[PK] --> [KEK]
[PK] --> [db]
[KEK] --> [db]
[db] --> [Common Variable]
@enduml
Authenticated Variable Lifecycle
````````````````````````````````
.. uml::
@startuml
start
if (Is authentication enabled?)
if (Enable authentication?) then (yes)
:Key Provision
{{
hide empty description
state "Set PK" as keyprovision1
state "Set KEK (write request must be signed by PK)" as keyprovision2
state "Set db (write request must be signed with PK or KEK)" as keyprovision3
keyprovision1 --> keyprovision2
keyprovision2 --> keyprovision3
}}
;
endif
else (yes)
switch (Request)
case (Clear store\n(disable authentication))
:Clear Store
{{
hide empty description
state "Delete PK (write request must be signed with PK)" as delete1
state "Delete KEK or db (authentication is disabled, so signature is not verified)" as delete2
delete1 --> delete2
}}
;
case (Update keys)
:Key Update
{{
hide empty description
state "Set PK (write request must be signed by original PK)" as keyupdate1
state "Set KEK (write request must be signed by new PK)" as keyupdate2
state "Set db (write request must be signed with new PK or new KEK)" as keyupdate3
keyupdate1 --> keyupdate2
keyupdate2 --> keyupdate3
}}
;
case (Reset factory keys)
skinparam partitionBorderColor red
partition "**NOT IMPLEMENTED**" {
switch (Recovery method)
case ()
:Using Setup Mode
{{
hide empty description
state "Enter Setup Mode to disable authentication" as recovery1
state "Delete PK, KEK, db (signatures are not verified in this mode)" as recovery2
state "Leave setup mode, but authentication is still disabled, because PK is empty" as recovery3
recovery1 -->recovery2
recovery2 -->recovery3
}}
;
case ()
:Using default keystores (PKdefault, KEKDefault, dbDefault);
endswitch
}
case(None)
endswitch
endif
end
@enduml
Variable structure
``````````````````
.. image:: image/uefi-variable-structure.svg
|
* The elements of the signature verification are stored in or calculated from the fields of the variables:
#. Hash: Calculated on Name, GUID, Attributes, Timestamp, Payload fields of the write request
#. Public Key: Extracted from the 'Sign. Data' element of the Signature List field in the Payload
of the variable responsible for authenticating the request
(e.g. in case of KEK request, it will be extracted from PK)
#. Signature: Extracted from the 'CertData' field of the write request.
SMM Variable Tests
''''''''''''''''''
The following test components exist for the SMM Variable service:
.. list-table::
:header-rows: 1
* - Test Component
- Description
- Included in deployments
* - ``component/service/uefi/smm_variable/backend/test``
- | Component tests for the variable_index and variable_store backend
| components. Can be run in a native PC environment.
- ``deployments/component-test/*``
* - ``component/service/uefi/smm_variable/test/service``
- | End-to-end service level tests that call service operations from
| the perspective of a client.  Can be run in a native PC environment
| or on the Arm target platform.
- | ``deployments/ts-service-test/*``
| ``deployments/uefi-test/*``
SMM Gateway Build Configuration
-------------------------------
The smm-gateway SP image may be built using the default configuration parameters defined
within relevant source files. In practice, it is likely that at least some configuration
values will need to be overridden. The following table lists build-time configuration
parameters that may be overridden by global C pre-processor defines.
.. list-table::
:widths: 2 2 2 1
:header-rows: 1
* - Config define
- Usage
- File
- Default value
* - SMM_GATEWAY_MAX_UEFI_VARIABLES
- Maximum number of variables
- ``deployments/smm-gateway/common/smm_gateway.c``
- 40
* - UEFI_MAX_VARIABLE_SIZE
- Maximum size of the uefi variables in bytes
- ``components/service/uefi/smm_variable/backend/uefi_variable_store.c``
- 4096
* - SMM_GATEWAY_NV_STORE_SN
- The service ID for the backend NV variable store
- ``deployments/smm-gateway/common/smm_gateway.c``
- Protected Storage SP
* - SMM_GATEWAY_CRYPTO_SN
- The service ID for the crypto backend
- ``deployments/smm-gateway/common/smm_gateway.c``
- Crypto SP
* - UEFI_AUTH_VAR
- Enables or disables UEFI variable authentication
- ``components/service/uefi/smm_variable/backend/uefi_variable_store.c``
- OFF
MM Communicate RPC Layer
------------------------
To maintain compatibility with existing SMM service clients, an MM Communicate based RPC
layer has been developed that uses the same 'carveout' buffer scheme as StMM. When SMM
Gateway is used instead of StMM, existing SMM variable clients should interoperate seamlessly.
The MM Communicate RPC components implement the standard TS RPC interfaces and can be used as
a general purpose RPC for calls from normal world to secure world. The following MM Communicate
RPC components have been added:
* ``components/rpc/mm_communicate/endpoint/sp`` - an RPC endpoint that handles FFA direct
calls with MM Communicate and SMM message carried in a shared 'carveout' buffer. Call requests
are demultiplexed to the appropriate service interface based on the service GUID carried in
the MM Communicate header.  Suitable for use in SP deployments.
* ``components/rpc/mm_communicate/caller/linux`` - an RPC caller that calls service operations
associated with the destination service interface from Linux user-space. Uses the MM Communicate
protocol, sent over FFA using the Debug FFA kernel driver.  Service level tests that run against
the SMM Gateway use this RPC caller for invoking SMM service operations.
The following register mapping is assumed for FFA based direct calls to an SP that handles the MM
Communicate RPC protocol:
.. list-table::
:widths: 1 2 2 2
:header-rows: 1
* - Registers
- FF-A layer
- MM_COMMUNICATE Request
- MM_COMMUNICATE Response
* - W0
- Function ID
- | FFA_MSG_SEND_DIRECT_REQ
| (0x8400006F/0xC400006F)
- | FFA_MSG_SEND_DIRECT_RESP
| (0x84000070/0xC4000070)
* - W1
- Source/Destination ID
- Source/Destination ID
- Source/Destination ID
* - W2/X2
- Reserved
- 0x00000000
- 0x00000000
* - W3/X3
- Parameter[0]
- Data offset in the MM communication buffer
- SUCCESS/[MM communicate error code]
* - W4/X4
- Parameter[1]
- 0x00000000
- 0x00000000
* - W5/X5
- Parameter[2]
- 0x00000000
- 0x00000000
* - W6/X6
- Parameter[3]
- 0x00000000
- 0x00000000
* - W7/X7
- Parameter[4]
- 0x00000000
- 0x00000000
--------------
*Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved.*
SPDX-License-Identifier: BSD-3-Clause