Julian Hall | cac3150 | 2021-12-15 17:35:25 +0000 | [diff] [blame] | 1 | UEFI SMM Services |
| 2 | ================= |
| 3 | The Trusted Services project provides support for UEFI System Management Mode (SMM) services via the |
| 4 | SMM Gateway secure partition. The SMM Gateway adopts the API Gateway design pattern, popular in |
| 5 | microservices architecture. The pattern decouples clients from backend service providers using an |
| 6 | API gateway that presents a domain specific interface to clients while delegating operations to a |
| 7 | set of backend microservices. An API gateway will typically use multiple backend services and may |
| 8 | perform protocol translation while presenting a single service entry point for clients. The SMM |
| 9 | Gateway works in a similar manner - clients access SMM services using standard SMM protocol messages, |
| 10 | carried by an RPC mechanism. Service requests are forwarded by the SMM Gateway to backend service |
| 11 | providers for operations such as secure persistent storage and signature verification. |
| 12 | |
| 13 | SMM Gateway is intended to be used on non-EDK2 platforms as an alternative to the EDK2 StandaloneMM |
| 14 | (StMM) component. The current SMM Gateway version only supports the SMM Variable service. Additional |
| 15 | SMM service providers may be added to SMM Gateway if required. By deliberately limiting functionality |
| 16 | and exploiting backend services, the SMM Gateway SP can be significantly lighter-weight than StMM. |
| 17 | This option is intended to be used on more resource constrained devices that tend to use u-boot. |
| 18 | There is of course the possibility that other SMM services will need to be supported in the future. |
| 19 | In such cases, a judgement should be made as to whether StMM should be used rather than extending the SP. |
| 20 | |
| 21 | .. uml:: uml/SmmGatewayOverview.puml |
| 22 | |
| 23 | SMM Variable Service |
| 24 | -------------------- |
| 25 | Overview |
| 26 | '''''''' |
| 27 | UEFI Variable support is provided by the *smm_variable* service provider component. This service provider |
| 28 | is structured in the same way as other service providers within the TS project. Features of this |
| 29 | component are: |
| 30 | |
Gabor Toth | e01504e | 2023-09-22 08:39:12 +0200 | [diff] [blame] | 31 | * Source file location: ``components/service/uefi/smm_variable`` |
Imre Kis | ee4345c | 2024-01-23 12:36:43 +0100 | [diff] [blame] | 32 | * Public interface definitions: ``protocols/service/smm_variable`` |
Julian Hall | cac3150 | 2021-12-15 17:35:25 +0000 | [diff] [blame] | 33 | * Can be used with any RPC layer - not tied to MM Communicate RPC. |
| 34 | * Volatile and non-volatile storage is accessed via instances of the common *storage_backend* interface. |
| 35 | |
Imre Kis | 3d6848d | 2023-01-04 15:36:19 +0100 | [diff] [blame] | 36 | The *smm-gateway/opteesp* and *smm-gateway/sp* deployments integrate the *smm_variable* service provider with the following: |
Julian Hall | cac3150 | 2021-12-15 17:35:25 +0000 | [diff] [blame] | 37 | |
| 38 | * An MM Communicate based RPC endpoint. |
| 39 | * A *mock_store* instance for volatile variables. |
| 40 | * A *secure_storage_client* for non-volatile variables. |
Gabor Toth | e01504e | 2023-09-22 08:39:12 +0200 | [diff] [blame] | 41 | * A *crypto client* for signature verification. |
Julian Hall | cac3150 | 2021-12-15 17:35:25 +0000 | [diff] [blame] | 42 | |
| 43 | During SP initialization, the *smm-gateway* uses pre-configured information to discover a backend secure |
Gabor Toth | e01504e | 2023-09-22 08:39:12 +0200 | [diff] [blame] | 44 | storage SP for NV storage and a crypto SP to verify signatures needed for UEFI variable authentication. |
| 45 | Crypto SP is accessible only if UEFI_AUTH_VAR is enabled. |
Julian Hall | cac3150 | 2021-12-15 17:35:25 +0000 | [diff] [blame] | 46 | |
| 47 | The following diagram illustrates how the *smm_variable* service provider is integrated into the *smm-gateway*. |
| 48 | |
| 49 | .. image:: image/smm-gateway-layers.svg |
| 50 | |
| 51 | Because the *smm_variable* service provider is independent of any particular environment, alternative deployments |
| 52 | are possible e.g. |
| 53 | |
| 54 | * *smm_variable* service provider running within a GP TA with storage off-loaded to the GP TEE Internal API. |
| 55 | * *smm_variable* service provider running within a secure enclave with its own internal flash storage. |
| 56 | |
| 57 | Supported Functions |
| 58 | ''''''''''''''''''' |
| 59 | The *smm_variable* service provider supports the following functions: |
| 60 | |
| 61 | .. list-table:: |
| 62 | :header-rows: 1 |
| 63 | |
| 64 | * - SMM Variable Function |
| 65 | - Purpose |
| 66 | - Backend service interaction |
| 67 | * - SMM_VARIABLE_FUNCTION_GET_VARIABLE |
| 68 | - Get variable data identified by GUID/name. |
| 69 | - Query index and get object from appropriate storage backend. |
| 70 | * - SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME |
| 71 | - Called multiple times to enumerate stored variables. |
| 72 | - Find variable in index and return next. |
| 73 | * - SMM_VARIABLE_FUNCTION_SET_VARIABLE |
| 74 | - Adds a new variable or updates an existing one. |
| 75 | - | Sets object in storage backend and if necessary, updates index |
| 76 | | and syncs to storage. |
| 77 | * - SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO |
| 78 | - Returns information about the variable store. |
| 79 | - Iterates over stored variables to determine space used. |
| 80 | * - SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE |
| 81 | - Called by OS when boot phase is complete. |
| 82 | - | Updates view of runtime state held by smm_variable service provider. |
| 83 | | State variable used when implementing state dependent access control. |
| 84 | * - SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_SET |
| 85 | - | Set constraints that are checked on the SetVariable operation. |
| 86 | | Allows a platform to set check policy. |
| 87 | - | Variable index holds variable check constraints object for each variable. |
| 88 | | This is updated by this function. |
| 89 | * - SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_GET |
| 90 | - Get the variable check constraints. |
| 91 | - Reads the variable check constraints object. |
| 92 | * - SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE |
| 93 | - | Returns the maximum variable data size, excluding any |
| 94 | | auth header. |
| 95 | - | Considers size constraints imposed by backend stores and RPC response |
| 96 | | payload constraints. |
| 97 | |
| 98 | Supported Variable Attributes |
| 99 | ''''''''''''''''''''''''''''' |
| 100 | The following variable attributes are supported: |
| 101 | |
| 102 | .. list-table:: |
| 103 | :widths: 3 1 3 |
| 104 | :header-rows: 1 |
| 105 | |
| 106 | * - SMM Variable Attribute |
| 107 | - Support |
| 108 | - Comment |
| 109 | * - EFI_VARIABLE_NON_VOLATILE |
| 110 | - yes |
| 111 | - Determines which storage backend is used. |
| 112 | * - EFI_VARIABLE_BOOTSERVICE_ACCESS |
| 113 | - yes |
| 114 | - Boot service access controlled by smm_variable service provider. |
| 115 | * - EFI_VARIABLE_RUNTIME_ACCESS |
| 116 | - yes |
| 117 | - Runtime access controlled by smm_variable service provider. |
| 118 | * - EFI_VARIABLE_HARDWARE_ERROR_RECORD |
| 119 | - no |
Gabor Toth | e01504e | 2023-09-22 08:39:12 +0200 | [diff] [blame] | 120 | - If the attribute contains this value, VariableName and VendorGuid must comply with the rules |
| 121 | stated in Section 8.2.4.2 and Appendix P of the standard. |
Julian Hall | cac3150 | 2021-12-15 17:35:25 +0000 | [diff] [blame] | 122 | * - EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS |
| 123 | - no |
Gabor Toth | e01504e | 2023-09-22 08:39:12 +0200 | [diff] [blame] | 124 | - DEPRECATED |
| 125 | * - EFI_VARIABLE_ENHANCED_AUTHENTICATED_ACCESS |
| 126 | - no |
| 127 | - Authentication with EFI_VARIABLE_AUTHENTICATION_3 descriptor is enabled. |
Julian Hall | cac3150 | 2021-12-15 17:35:25 +0000 | [diff] [blame] | 128 | * - EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS |
Gabor Toth | e01504e | 2023-09-22 08:39:12 +0200 | [diff] [blame] | 129 | - yes |
| 130 | - Authentication with EFI_VARIABLE_AUTHENTICATION_2 descriptor is enabled. |
Julian Hall | cac3150 | 2021-12-15 17:35:25 +0000 | [diff] [blame] | 131 | * - EFI_VARIABLE_APPEND_WRITE |
| 132 | - yes |
| 133 | - Implemented by overwriting entire variable data. |
| 134 | |
Gabor Toth | e01504e | 2023-09-22 08:39:12 +0200 | [diff] [blame] | 135 | Limitations |
| 136 | ''''''''''' |
| 137 | |
| 138 | .. list-table:: |
| 139 | :header-rows: 1 |
| 140 | |
| 141 | * - Description |
| 142 | - Value |
| 143 | * - Maximum size of a single variable |
| 144 | - 4096 bytes |
| 145 | * - Supported type of signature list element |
| 146 | - DER-encoded X.509 certificates |
| 147 | * - Supported type of public keys |
| 148 | - DER-encoded SignedData structure per PKCS#7 version 1.5, with or without a DER-encoded |
| 149 | ContentInfo structure per PKCS#7 version 1.5. |
| 150 | |
| 151 | Variable authentication |
| 152 | ''''''''''''''''''''''' |
| 153 | |
| 154 | UEFI variable authentication is a method to ensure that a UEFI variable can only be modified |
| 155 | by those who has proper rights. This restricts only the writing of these variables, while reading |
| 156 | is only limited by the state of the system (boot versus runtime access). |
| 157 | |
| 158 | Key Store Variables |
| 159 | ``````````````````` |
| 160 | Key Store variables store authentication keys, and have predefined special names to specify the |
| 161 | keys scope (area of effect). When a write access to a variable with an active |
| 162 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is being made, the signature part of |
| 163 | the write access will be verified against the appropriate key Store variable. |
| 164 | Access will only be granted if the signature is valid. |
| 165 | |
| 166 | The following table lists which Key Store variables defined by the UEFI standard are implemented. |
| 167 | |
| 168 | .. list-table:: |
| 169 | :header-rows: 1 |
| 170 | |
| 171 | * - Variable name |
| 172 | - Description |
| 173 | - Supported |
| 174 | * - Platform Key (PK) |
| 175 | - Root of trust. If it is not set the authentication is disabled, all write requests are successful. |
| 176 | - yes |
| 177 | * - Key Exchange Key Database (KEK) |
| 178 | - Protects key store databases from unauthorized modifications. |
| 179 | - yes |
| 180 | * - Signature Database (db) |
| 181 | - If a variable write request is signed by the public key whose private pair is |
| 182 | stored here the authentication will pass. |
| 183 | - yes |
| 184 | * - Blacklist Signature Database (dbx) |
| 185 | - Contains signatures of software that must not run on the platform. |
| 186 | - no |
| 187 | * - Authorized Recovery Signature Database (dbr) |
| 188 | - Contains signatures of software that can be run for recovery. |
| 189 | - no |
| 190 | * - Timestamp Signature Database (dbt) |
| 191 | - Same as db, but the timestamp of the certificate is also verified. |
| 192 | - no |
| 193 | |
| 194 | There is no support for initializing the values of the read-only global variables containing |
| 195 | default values of the key store variables (e.g. PKDefault, KEKDefault, etc.). |
| 196 | |
| 197 | The following diagram shows variable authentication hierarchy. |
| 198 | |
| 199 | *A → B means A has the right to verify write request to B* |
| 200 | |
| 201 | .. uml:: |
| 202 | |
| 203 | @startuml |
| 204 | [PK] --> [PK] |
| 205 | [PK] --> [KEK] |
| 206 | [PK] --> [db] |
| 207 | [KEK] --> [db] |
| 208 | [db] --> [Common Variable] |
| 209 | @enduml |
| 210 | |
| 211 | Authenticated Variable Lifecycle |
| 212 | ```````````````````````````````` |
| 213 | |
| 214 | .. uml:: |
| 215 | |
| 216 | @startuml |
| 217 | |
| 218 | start |
| 219 | if (Is authentication enabled?) |
| 220 | if (Enable authentication?) then (yes) |
| 221 | :Key Provision |
| 222 | {{ |
| 223 | hide empty description |
| 224 | |
| 225 | state "Set PK" as keyprovision1 |
| 226 | state "Set KEK (write request must be signed by PK)" as keyprovision2 |
| 227 | state "Set db (write request must be signed with PK or KEK)" as keyprovision3 |
| 228 | |
| 229 | keyprovision1 --> keyprovision2 |
| 230 | keyprovision2 --> keyprovision3 |
| 231 | }} |
| 232 | ; |
| 233 | endif |
| 234 | else (yes) |
| 235 | switch (Request) |
| 236 | case (Clear store\n(disable authentication)) |
| 237 | :Clear Store |
| 238 | {{ |
| 239 | hide empty description |
| 240 | |
| 241 | state "Delete PK (write request must be signed with PK)" as delete1 |
| 242 | state "Delete KEK or db (authentication is disabled, so signature is not verified)" as delete2 |
| 243 | |
| 244 | delete1 --> delete2 |
| 245 | }} |
| 246 | ; |
| 247 | case (Update keys) |
| 248 | :Key Update |
| 249 | {{ |
| 250 | hide empty description |
| 251 | |
| 252 | state "Set PK (write request must be signed by original PK)" as keyupdate1 |
| 253 | state "Set KEK (write request must be signed by new PK)" as keyupdate2 |
| 254 | state "Set db (write request must be signed with new PK or new KEK)" as keyupdate3 |
| 255 | |
| 256 | keyupdate1 --> keyupdate2 |
| 257 | keyupdate2 --> keyupdate3 |
| 258 | }} |
| 259 | ; |
| 260 | case (Reset factory keys) |
| 261 | |
| 262 | skinparam partitionBorderColor red |
| 263 | partition "**NOT IMPLEMENTED**" { |
| 264 | switch (Recovery method) |
| 265 | case () |
| 266 | :Using Setup Mode |
| 267 | {{ |
| 268 | hide empty description |
| 269 | |
| 270 | state "Enter Setup Mode to disable authentication" as recovery1 |
| 271 | state "Delete PK, KEK, db (signatures are not verified in this mode)" as recovery2 |
| 272 | state "Leave setup mode, but authentication is still disabled, because PK is empty" as recovery3 |
| 273 | |
| 274 | recovery1 -->recovery2 |
| 275 | recovery2 -->recovery3 |
| 276 | }} |
| 277 | ; |
| 278 | case () |
| 279 | :Using default keystores (PKdefault, KEKDefault, dbDefault); |
| 280 | |
| 281 | endswitch |
| 282 | } |
| 283 | |
| 284 | case(None) |
| 285 | endswitch |
| 286 | endif |
| 287 | |
| 288 | end |
| 289 | |
| 290 | @enduml |
| 291 | |
| 292 | Variable structure |
| 293 | `````````````````` |
| 294 | |
| 295 | .. image:: image/uefi-variable-structure.svg |
| 296 | |
| 297 | | |
| 298 | |
| 299 | * The elements of the signature verification are stored in or calculated from the fields of the variables: |
| 300 | #. Hash: Calculated on Name, GUID, Attributes, Timestamp, Payload fields of the write request |
| 301 | #. Public Key: Extracted from the 'Sign. Data' element of the Signature List field in the Payload |
| 302 | of the variable responsible for authenticating the request |
| 303 | (e.g. in case of KEK request, it will be extracted from PK) |
| 304 | #. Signature: Extracted from the 'CertData' field of the write request. |
| 305 | |
Julian Hall | cac3150 | 2021-12-15 17:35:25 +0000 | [diff] [blame] | 306 | SMM Variable Tests |
| 307 | '''''''''''''''''' |
| 308 | The following test components exist for the SMM Variable service: |
| 309 | |
| 310 | .. list-table:: |
| 311 | :header-rows: 1 |
| 312 | |
| 313 | * - Test Component |
| 314 | - Description |
| 315 | - Included in deployments |
Gabor Toth | e01504e | 2023-09-22 08:39:12 +0200 | [diff] [blame] | 316 | * - ``component/service/uefi/smm_variable/backend/test`` |
Julian Hall | cac3150 | 2021-12-15 17:35:25 +0000 | [diff] [blame] | 317 | - | Component tests for the variable_index and variable_store backend |
| 318 | | components. Can be run in a native PC environment. |
| 319 | - ``deployments/component-test/*`` |
Gabor Toth | e01504e | 2023-09-22 08:39:12 +0200 | [diff] [blame] | 320 | * - ``component/service/uefi/smm_variable/test/service`` |
Julian Hall | cac3150 | 2021-12-15 17:35:25 +0000 | [diff] [blame] | 321 | - | End-to-end service level tests that call service operations from |
| 322 | | the perspective of a client. Can be run in a native PC environment |
| 323 | | or on the Arm target platform. |
Gabor Toth | e01504e | 2023-09-22 08:39:12 +0200 | [diff] [blame] | 324 | - | ``deployments/ts-service-test/*`` |
| 325 | | ``deployments/uefi-test/*`` |
Julian Hall | cac3150 | 2021-12-15 17:35:25 +0000 | [diff] [blame] | 326 | |
| 327 | SMM Gateway Build Configuration |
| 328 | ------------------------------- |
| 329 | The smm-gateway SP image may be built using the default configuration parameters defined |
| 330 | within relevant source files. In practice, it is likely that at least some configuration |
| 331 | values will need to be overridden. The following table lists build-time configuration |
| 332 | parameters that may be overridden by global C pre-processor defines. |
| 333 | |
| 334 | .. list-table:: |
| 335 | :widths: 2 2 2 1 |
| 336 | :header-rows: 1 |
| 337 | |
| 338 | * - Config define |
| 339 | - Usage |
| 340 | - File |
| 341 | - Default value |
| 342 | * - SMM_GATEWAY_MAX_UEFI_VARIABLES |
| 343 | - Maximum number of variables |
Gabor Toth | e01504e | 2023-09-22 08:39:12 +0200 | [diff] [blame] | 344 | - ``deployments/smm-gateway/common/smm_gateway.c`` |
Julian Hall | cac3150 | 2021-12-15 17:35:25 +0000 | [diff] [blame] | 345 | - 40 |
Gabor Toth | e01504e | 2023-09-22 08:39:12 +0200 | [diff] [blame] | 346 | * - UEFI_MAX_VARIABLE_SIZE |
| 347 | - Maximum size of the uefi variables in bytes |
| 348 | - ``components/service/uefi/smm_variable/backend/uefi_variable_store.c`` |
| 349 | - 4096 |
Julian Hall | cac3150 | 2021-12-15 17:35:25 +0000 | [diff] [blame] | 350 | * - SMM_GATEWAY_NV_STORE_SN |
| 351 | - The service ID for the backend NV variable store |
Gabor Toth | e01504e | 2023-09-22 08:39:12 +0200 | [diff] [blame] | 352 | - ``deployments/smm-gateway/common/smm_gateway.c`` |
Julian Hall | cac3150 | 2021-12-15 17:35:25 +0000 | [diff] [blame] | 353 | - Protected Storage SP |
Gabor Toth | e01504e | 2023-09-22 08:39:12 +0200 | [diff] [blame] | 354 | * - SMM_GATEWAY_CRYPTO_SN |
| 355 | - The service ID for the crypto backend |
| 356 | - ``deployments/smm-gateway/common/smm_gateway.c`` |
| 357 | - Crypto SP |
| 358 | * - UEFI_AUTH_VAR |
| 359 | - Enables or disables UEFI variable authentication |
| 360 | - ``components/service/uefi/smm_variable/backend/uefi_variable_store.c`` |
| 361 | - OFF |
Julian Hall | cac3150 | 2021-12-15 17:35:25 +0000 | [diff] [blame] | 362 | |
| 363 | MM Communicate RPC Layer |
| 364 | ------------------------ |
| 365 | To maintain compatibility with existing SMM service clients, an MM Communicate based RPC |
| 366 | layer has been developed that uses the same 'carveout' buffer scheme as StMM. When SMM |
| 367 | Gateway is used instead of StMM, existing SMM variable clients should interoperate seamlessly. |
| 368 | The MM Communicate RPC components implement the standard TS RPC interfaces and can be used as |
| 369 | a general purpose RPC for calls from normal world to secure world. The following MM Communicate |
| 370 | RPC components have been added: |
| 371 | |
| 372 | * ``components/rpc/mm_communicate/endpoint/sp`` - an RPC endpoint that handles FFA direct |
| 373 | calls with MM Communicate and SMM message carried in a shared 'carveout' buffer. Call requests |
| 374 | are demultiplexed to the appropriate service interface based on the service GUID carried in |
| 375 | the MM Communicate header. Suitable for use in SP deployments. |
| 376 | * ``components/rpc/mm_communicate/caller/linux`` - an RPC caller that calls service operations |
| 377 | associated with the destination service interface from Linux user-space. Uses the MM Communicate |
| 378 | protocol, sent over FFA using the Debug FFA kernel driver. Service level tests that run against |
| 379 | the SMM Gateway use this RPC caller for invoking SMM service operations. |
| 380 | |
| 381 | The following register mapping is assumed for FFA based direct calls to an SP that handles the MM |
| 382 | Communicate RPC protocol: |
| 383 | |
| 384 | .. list-table:: |
| 385 | :widths: 1 2 2 2 |
| 386 | :header-rows: 1 |
| 387 | |
| 388 | * - Registers |
| 389 | - FF-A layer |
| 390 | - MM_COMMUNICATE Request |
| 391 | - MM_COMMUNICATE Response |
| 392 | * - W0 |
| 393 | - Function ID |
| 394 | - | FFA_MSG_SEND_DIRECT_REQ |
| 395 | | (0x8400006F/0xC400006F) |
| 396 | - | FFA_MSG_SEND_DIRECT_RESP |
| 397 | | (0x84000070/0xC4000070) |
| 398 | * - W1 |
| 399 | - Source/Destination ID |
| 400 | - Source/Destination ID |
| 401 | - Source/Destination ID |
| 402 | * - W2/X2 |
| 403 | - Reserved |
| 404 | - 0x00000000 |
| 405 | - 0x00000000 |
| 406 | * - W3/X3 |
| 407 | - Parameter[0] |
Imre Kis | ee4345c | 2024-01-23 12:36:43 +0100 | [diff] [blame] | 408 | - Data offset in the MM communication buffer |
| 409 | - SUCCESS/[MM communicate error code] |
Julian Hall | cac3150 | 2021-12-15 17:35:25 +0000 | [diff] [blame] | 410 | * - W4/X4 |
| 411 | - Parameter[1] |
Imre Kis | ee4345c | 2024-01-23 12:36:43 +0100 | [diff] [blame] | 412 | - 0x00000000 |
| 413 | - 0x00000000 |
Julian Hall | cac3150 | 2021-12-15 17:35:25 +0000 | [diff] [blame] | 414 | * - W5/X5 |
| 415 | - Parameter[2] |
| 416 | - 0x00000000 |
| 417 | - 0x00000000 |
| 418 | * - W6/X6 |
| 419 | - Parameter[3] |
| 420 | - 0x00000000 |
| 421 | - 0x00000000 |
| 422 | * - W7/X7 |
| 423 | - Parameter[4] |
| 424 | - 0x00000000 |
| 425 | - 0x00000000 |
| 426 | |
| 427 | -------------- |
| 428 | |
Imre Kis | ee4345c | 2024-01-23 12:36:43 +0100 | [diff] [blame] | 429 | *Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved.* |
Julian Hall | cac3150 | 2021-12-15 17:35:25 +0000 | [diff] [blame] | 430 | |
| 431 | SPDX-License-Identifier: BSD-3-Clause |