| # Device Provisioning |
| |
| <p style="color: red; text-align: right;"> |
| Status: Pre-RFC |
| </p> |
| |
| |
| ## Overview |
| |
| This document describes the OpenTitan provisioning flow which is divided into |
| two stages: |
| |
| * [Personalization](#personalization): Covers initialization of the device |
| with an unique cryptographic identity known as the |
| [Creator Identity][creator_identity], its endorsement certificate, as well |
| as additional secrets required to configure defensive mechanisms. This |
| occurs only at manufacturing time. |
| * [Owner Personalization](#owner_personalization): Covers provisioning of |
| owner secrets and endorsement of the Owner Identity by the Silicon Owner. |
| This may occur either at manufacturing time or as part of a later in-field |
| ownership transfer. |
| |
| ## Security Scope |
| |
| The security scope is derived from the threats against the assets handled by the |
| provisioning infrastructure. |
| |
| ### Assets |
| |
| The wafer foundry and OSAT are untrusted to maintain the secrecy of the |
| following assets: |
| |
| * Device secrets |
| * Provisioning appliance secrets (e.g. certificate endorsement signing keys). |
| |
| ### Security Model |
| |
| The security model of the provisioning infrastructure is based on the following |
| requirements: |
| |
| * There is a provisioning appliance connected to an HSM in the manufacturing |
| floor. This device is the only component trusted with secrets other than |
| the Device Under Test (DUT). |
| * There is a pre-personalization device authentication function that can be |
| implemented by trusted components. |
| * The wafer foundry does not collude with the OSAT to attack the device |
| authentication function, although some mitigations are considered. |
| |
| ## Device Lifecycle and Personalization Stages |
| |
| ### Unlock Tokens {#unlock_tokens} |
| |
| OpenTitan provides a set of lock/unlock tokens to control the state of the |
| device in early manufacturing stages. See |
| [device lifecycle specification][device_lifecycle] for more details. |
| |
| * `RAW_UNLOCK` |
| * `TEST_UNLOCK` |
| * `TEST_EXIT` |
| * `RMA_UNLOCK` |
| |
| Test unlock tokens are used as part of the process to logically disable the |
| devices so that they can be safely transported between manufacturing stages. |
| Unlock operations do not require CPU intervention. A test exit token is used to |
| gate the device transition from TEST state into one of the final operational |
| states (`DEV`, `PROD_END`, `PROD`). |
| |
| ### Pre-Personalization |
| |
| The following steps illustrate the set of operations required prior to |
| personalization. |
| |
| #### Wafer Test - Electrical Die Sorting (EDS) |
| |
| * `RAW_UNLOCK`: Unlock TEST mode by providing unlock token via TAP interface. |
| * `ANALOG TRIM & TEST (EDS)`: Regular analog test, scan, calibration, trimming |
| and functional testing (EDS stage). |
| * `SET DEVICE_ID`: Program the device identifier fuses. `DEVICE_ID` export may |
| be required depending on the provisioning flow. |
| * `LOCK DEVICE`: (Optional) Program the TEST_UNLOCK (optional) and/or |
| TEST_EXIT tokens depending on the test flow configuration. |
| |
| Optional: If required by the manufacturing flow, lock the device for safe |
| transport into the next test stage. |
| |
| #### Package Test (TEST MODE) - Automated Test Equipment (ATE) |
| |
| * `TEST_UNLOCK`: Unlock TEST mode by providing TEST_UNLOCK token via TAP |
| interface. |
| * `ANALOG TRIM & TEST (OSAT)`: Regular analog test, scan, calibration, |
| trimming and functional testing (EDS stage). |
| * `LOG DEVICE_ID`: Record DEVICE_ID and test results. |
| * `LOCK DEVICE`: Program the TEST_UNLOCK (optional) and/or TEST_EXIT tokens |
| depending on test configuration. |
| |
| Optional: If required by the manufacturing flow, lock the device for safe |
| transport into the next test stage. |
| |
| #### Package Test (DEV or PROD MODE) - Automated Test Equipment (ATE) |
| |
| * `TEST_EXIT`: Unlock device and transition from TEST to one of the following |
| operational states: DEV, PROD_END, or PROD. |
| * `SKU SETTINGS`: SKU dependent fuse and info flash configuration. |
| * `PERSONALIZATION`: See [Personalization](#personalization) section for more |
| * `LOAD FW IMAGE`: Load factory image payload. |
| |
| ## Personalization {#personalization} |
| |
| ### Test Setup |
| |
| The following diagram shows the physical connections between test components. |
| |
| <table> |
| <tr> |
| <td> |
| <img src="img_ate_setup.svg" style="width: 800px;"> |
| </td> |
| </tr> |
| <tr><td style="text-align:center;">Figure: FT Connectivity</td></tr> |
| </table> |
| |
| #### Components |
| |
| * **Device Under Test**: An OpenTitan device being tested as part of its |
| manufacturing process. |
| * **ATE**: Automatic Test Equipment (ATE), used to perform tests on the |
| devices as part of the manufacturing process. |
| * **Provisioning Appliance**: A network connected local server with an |
| attached HSM. The server implements an OpenTitan compliant secure boot |
| implementation, and runs signed applications used to communicate with ATE |
| and cloud services. |
| * **Provisioning Service**: Cloud service used to authenticate and initialize |
| provisioning appliances. |
| |
| The provisioning service is used to provide initialization data to the |
| provisioning appliance once it has been authenticated. |
| |
| * **Registry Service**: A cloud service used to host a device registry |
| containing certificates and Certificate Revocations Lists (CRLs). |
| |
| #### Connectivity |
| |
| ATE - OpenTitan (DUT) |
| |
| * `RST_N`: OpenTitan reset pin. |
| * `STRAPS`: Pins used to control hardware and software test functionality. On |
| the hardware side, strap pins are used to configure TEST modes and select |
| TAP interfaces. On the software side, straps used to enable the SPI flash |
| bootstrap mode in ROM, as well as manufacturing test modes. Some strap |
| functionality is only available before entering DEV or PROD states. There is |
| also additional functionality that is disabled when the device reaches the |
| end of manufacturing. |
| * `SPI`: Bidirectional interface used to exchange payloads and status with the |
| device. |
| |
| Provisioning Appliance - ATE |
| |
| * Local network interface. |
| |
| Provisioning/Registry Services - Provisioning Appliance |
| |
| * External network interface. Connectivity between endpoints is authenticated |
| and encrypted. The Provisioning appliance uses service accounts to identify |
| itself. The Provisioning and Registration Services are authenticated via |
| TLS. The interface has to support unstable connections. The Provisioning |
| Appliance has to be able to buffer messages to be able to recover from |
| network disruptions. |
| |
| ### Overview |
| |
| The following diagram captures the life of a device throughout the manufacturing |
| flow with emphasis on the personalization process. |
| |
| <table> |
| <tr> |
| <td> |
| <img src="img_provisioning_overview.svg" style="width: 900px;"> |
| </td> |
| </tr> |
| <tr> |
| <td style="text-align:center;">Figure: Device personalization (high level)</td> |
| </tr> |
| </table> |
| |
| Steps: |
| |
| 1. [Device identifiers][device_id] (`device_id`) and |
| [unlock tokens](#unlock_tokens) are programmed into the device's One Time |
| Programmable (OTP) memory. The unlock tokens are delivered in cleartext form |
| to each OpenTitan die. |
| 2. (Optional) A provisioning appliance collects all device identifiers and |
| unlock tokens and sends them in encrypted form to a provisioning service |
| hosted in the cloud. |
| 3. Wafers are transported from wafer test (EDS) to the package test (ATE) |
| location. Devices are transported in `TEST_LOCKED` lifecycle state. |
| 4. The provisioning service authenticates the provisioning appliance(s) and |
| sends `appliance_secrets, and identifiers (device_ids)` in encrypted form. |
| 5. Devices are tested and switched to PROD or DEV mode before personalization. |
| The ATE test setup actuates the personalization flow in collaboration with |
| the provisioning appliance. |
| 1. There are two personalization approaches supported by OpenTitan. |
| 1. [Injection Process](#injection_process): The provisioning appliance |
| generates `device_secrets` (in the injection case) and endorsement |
| certificates. `appliance_secrets` are used to enable signing on |
| endorsement certificates with Silicon Creator intermediate CA keys. |
| 2. [Self-Generated Process](#self_generated_process): The device |
| generates its own `device_secrets` and the provisioning appliance is |
| used to sign the endorsement certificate. |
| 6. At the end of a successful provisioning flow, the provisioning appliance |
| sends the device certificates to a device registry. Silicon Owners can use |
| the registry as part of identity ingestion flows. |
| 7. The devices are shipped with a factory image and a Silicon Creator |
| endorsement certificate. The Silicon Creator may also provide |
| [Owner Personalization](#owner_personalization) services. All shipped |
| devices have secure boot enabled, which provides a logical locking mechanism |
| to restrict the use of open samples. |
| 8. The Silicon Creator may issue a Certificate Revocation List (CRL) to the |
| device registry. The registry is in charge of serving the CRL to downstream |
| consumers (Silicon Owners). |
| |
| ### Secure Boot |
| |
| Secure boot is always enforced by the ROM and cannot be disabled. |
| Personalization and factory software payloads are signed, and boot verification |
| is used to anchor the mechanism in which the device authenticates the |
| provisioning appliance during personalization. |
| |
| ### Injection Process |
| |
| This section describes the personalization injection mode in detail. |
| |
| <img src="img_provisioning_injection.svg" style="width: 900px;"> |
| |
| **P0. Get device identifier** |
| |
| The DEVICE is initially in LOCKED state before the start of production test. The |
| TESTER gets the Device ID via TAP interface. The provisioning appliance returns |
| unlock tokens associated with the Device ID. |
| |
| Note 1: The Device ID read requirement applies only if unlock tokens are unique |
| per device. |
| |
| Note 2: The manufacturer must document the unlock token usage plan, including |
| the proposed rotation plan. |
| |
| **P1. Unlock device and load personalization software** |
| |
| P1.1. The TESTER unlocks the DEVICE by sending the `TEST_UNLOCK` and `TEST_EXIT` |
| tokens via TAP interface. |
| |
| P1.2. The TESTER loads personalization software on the DEVICE using the SPI |
| bootstrap interface. The DEVICE verifies the personalization software |
| signature against one of the public keys stored in the ROM via secure boot. |
| |
| **P2. Device authentication and key exchange** |
| |
| P2.1 Authentication function |
| |
| The authentication function relies on the following assumptions: |
| |
| * The provisioning appliance (HSM) is the only component trusted with secrets |
| other than the Device Under Test (DUT) in the manufacturing floor. |
| * The authentication function can only be implemented by trusted components. |
| * The wafer manufacturer does not collude with the OSAT to attack the |
| authentication function, although some mitigations are considered. |
| |
| ``` |
| # Shared secret key between provisioning appliance and the DEVICE. |
| # The parameters of the authentication function are outside the |
| # classification scope of this document. |
| key_auth = authentication_function() |
| ``` |
| |
| P2.2. DEVICE sends authentication data to TESTER |
| |
| **The DEVICE will fail to generate an authentication payload if the device is |
| not in `PROD`, `PROD_END` or `DEV` state.** |
| |
| The DEVICE sends an authentication payload to the TESTER including: |
| |
| * Device ID (`device_id`). |
| * Static key (`receiver_pub_key`) used to derive session keys[^1]; and, |
| * MAC tag covering the authentication payload. |
| |
| The DEVICE sends the payload to the TESTER via SPI, repeating the message |
| continuously to simplify timing adjustments in the test sequence. |
| |
| Payload generation: |
| |
| ``` |
| // ECC key pair generation compliant to FIPS 186-4 appendix B.4. |
| // Curves under consideration: NIST_P256 and NIST_P386. |
| receiver_priv_key, receiver_pub_key = ECC_KDF(DRBG_context) |
| |
| key_auth = authentication_function() |
| |
| // data_size includes the size of the data + tag. |
| data = "OTAU" || receiver_pub_key || device_id || data_size |
| tag = MAC(key_auth, data) |
| |
| // Continuously broadcast via SPI device port. |
| return data || tag |
| ``` |
| |
| P2.3 TESTER verifies authentication data |
| |
| The TESTER calls the provisioning appliance to verify the tag attached to the |
| DEVICE authentication payload using the authentication key function from P2.1. |
| The TESTER aborts personalization on failure. |
| |
| Verification function: |
| |
| ``` |
| key_auth = authentication_function() |
| |
| data || tag = authentication_data |
| calculated_tag = MAC(key_auth, data) |
| RETURN_ERROR_IF(calculated_tag != tag) |
| ``` |
| |
| **P3: Inject secrets** |
| |
| P3.1 Get wrapped personalization payload from provisioning appliance |
| |
| The TESTER gets a personalization payload from the provisioning appliance. The |
| provisioning appliance is in charge of generating the device secrets. The |
| payload is associated with the Device ID and is wrapped with a key derived from |
| the `receiver_pub_key`extracted in step P2. |
| |
| Transport wrapping. See [ECIES Encryption](#ecies_encryption) for more details |
| on the `ECIES_ENC` input and output parameters. Some parameters are omitted for |
| simplicity. |
| |
| ``` |
| // OPEN: ctx_id in this case is set to a portion of the device_id. |
| // The manufacturer shall incorporate a monotonically incrementing counter |
| // into ctx_id. |
| ephemeral_pub_key || tag || ctx_id || sender_pub_key || |
| data_size || data_enc = |
| ECIES_ENC(key=sender_priv_key, receiver_pub_key, |
| data=(device_secrets || creator_certificate)) |
| |
| personalization_payload = "OTPL" || tag || ctx_id || |
| sender_pub_key || data_size || data_enc |
| ``` |
| |
| P3.2 TESTER sends personalization payload to DEVICE |
| |
| The personalization payload is sent to the device via SPI in 1KB frame chunks. |
| The payload is transferred from the DEVICE SPI RX FIFO into SRAM. |
| |
| **P4. DEVICE unwrap and install secrets** |
| |
| P4.1 DEVICE unwraps secrets and creator certificate |
| |
| Unwrap process. See [ECIES Decryption](#ecies_decryption) for more details on |
| the `ECIES_DEC` input and output parameters. Some parameters are omitted for |
| simplicity. |
| |
| ``` |
| // The following operation will verify the integrity of the encrypted |
| // blob. The sender_pub_key is verified against a whitelist stored |
| // in the personalization software. |
| device_secrets, creator_cerficate = |
| ECIES_DEC(key=receiver_priv_key, |
| ephemeral_pub_key, sender_key_pub, data=enc_payload) |
| ``` |
| |
| P4.2 Install secrets |
| |
| Secrets are installed in OTP and in Flash. See Device Secrets for a breakdown of |
| Silicon Creator level secrets. |
| |
| P4.3 Report install status |
| |
| Report install status to tester via SPI interface. The status code is repeated |
| continuously on the SPI interface to simplify the test implementation. |
| |
| **P5. Install factory image** |
| |
| The factory image is the software loaded on the device before shipping. It is |
| not expected to change frequently once the manufacturing flow is deployed for a |
| given SKU configuration. At a minimum, the factory image will contain a ROM |
| Extension (`ROM_EXT`) component. |
| |
| The TESTER programs the factory image on the DEVICE via SPI bootstrap interface |
| The hash of the `ROM_EXT` must match the value used to calculate the Creator |
| Identity as described in the |
| [Identities and Root Keys][identities_and_root_keys] document. |
| |
| **P6. Provisioning result** |
| |
| The DEVICE boots in identity UNOWNED state and in manufacturing mode. The |
| conditions used to trigger manufacturing mode are TBD. |
| |
| P6.1 Test Creator Identity |
| |
| The `ROM_EXT` uses the key manager to obtain the Creator Identity key. See the |
| [Asymmetric Keys section in the Attestation specification][attestation_keys] for |
| more details. |
| |
| The public portion of the Creator Identity is tested against the Creator |
| Certificate. The result is reported to the TESTER via SPI. |
| |
| ### Self-Generated Process {#self_generated_process} |
| |
| This section describes the personalization self-generate mode in detail. In this |
| mode, The device generates its own device secrets and the provisioning appliance |
| is used to sign the endorsement certificate. |
| |
| <img src="img_provisioning_self_gen.svg" style="width: 900px;"> |
| |
| **PS0. Get device identifier** |
| |
| The DEVICE is initially in LOCKED state. The TESTER gets the Device ID via TAP |
| interface. The provisioning appliance returns unlock tokens associated with the |
| Device ID. |
| |
| **PS1. Unlock device and load perso firmware** |
| |
| PS1.1. The TESTER unlocks the DEVICE by sending the `TEST_UNLOCK` and |
| `TEST_EXIT` tokens via TAP interface. |
| |
| PS1.2. The TESTER loads personalization software on the DEVICE using the SPI |
| bootstrap interface. The DEVICE verifies the personalization software signature |
| against one of the public keys stored in the ROM via secure boot. |
| |
| **PS2. Generate and install secrets** |
| |
| The device uses the available on-device entropy source to generate all the |
| device secrets. |
| |
| Secrets are installed in OTP and in Flash. Fuse locks are set as described in |
| the OTP specification. |
| |
| **PS3. Export public key** |
| |
| The device exports the Creator Identity public key via SPI. The authentication |
| function from P2.1 is used to generate an integrity digest over the exported |
| data. |
| |
| Payload with integrity tag: |
| |
| ``` |
| // Shared between device and provisioning appliance. |
| key_auth = authentication_function() |
| |
| // data_size includes the size of the data + tag. |
| data = "OTAU" || data_size || device_id || creator_identity_pub_key |
| tag = MAC(key_auth, data) |
| |
| // Continuously broadcast via SPI device port. |
| return data || tag |
| ``` |
| |
| **PS4. Generate certificate** |
| |
| PS4.1. Verify received data |
| |
| The provisioning appliance verifies the integrity of the received payload. The |
| verification of the payload is used to authenticate the device, since the key |
| used to calculate the digest tag is only known to the device and the |
| provisioning appliance. |
| |
| Verification function: |
| |
| ``` |
| key_auth = authentication_function() |
| |
| data || tag = authentication_data |
| calculated_tag = MAC(key_auth, data) |
| RETURN_ERROR_IF(calculated_tag != tag) |
| ``` |
| |
| PS4.2. Generate certificate |
| |
| The provisioning appliance generates an endorsement certificate as defined in |
| the [Certificate Format][attestation_certificate] section of the Attestation |
| specification. |
| |
| PS4.3. Send certificate |
| |
| The certificate is sent to the device via SPI in 1KB frames. An integrity tag is |
| added to the message using the same mechanism as in PS3. |
| |
| Provisioning service to device certificate payload. |
| |
| ``` |
| // Shared between device and provisioning appliance. |
| key_auth = authentication_function() |
| |
| // data_size includes the size of the data + tag. |
| data = "OTCI" || data_size || device_id || creator_identity_cert |
| tag = MAC(key_auth, data) |
| |
| // Continuously broadcast via SPI device port. |
| return data || tag |
| ``` |
| |
| **PS5. Install certificate** |
| |
| The device verifies the certificate payload sent by the provisioning appliance |
| and installs it in a flash block. |
| |
| **PS6. Install factory image** |
| |
| The factory image is the software loaded on the device before shipping. It is |
| not expected to change frequently once the manufacturing flow is deployed for a |
| given SKU configuration. At a minimum, the factory image will contain a ROM |
| Extension (`ROM_EXT`) component. |
| |
| The TESTER programs the factory image on the DEVICE via SPI bootstrap interface. |
| The hash of the `ROM_EXT` must match the value used to calculate the Creator |
| Identity as described in the |
| [Identities and Root Keys][identities_and_root_keys] document. |
| |
| **PS7. Provisioning result.** |
| |
| The `ROM_EXT` uses the key manager to obtain the Creator Identity key. See the |
| [Asymmetric Keys section in the Attestation specification][attestation_keys] for |
| more details. |
| |
| The public portion of the Creator Identity is tested against the Creator |
| Certificate. The result is reported to the TESTER via SPI. |
| |
| ## Owner Personalization {#owner_personalization} |
| |
| OpenTitan provides a mechanism to enable provisioning of Silicon Owner secrets |
| and endorsement certificates in manufacturing and post-manufacturing stages. |
| Owners are encouraged to create an implementation plan to perform |
| post-manufacturing provisioning to take full advantage of ownership transfer. |
| |
| Provisioning post-ownership transfer assumes that the OpenTitan device is |
| integrated into a system, and there is a HOST capable of communicating |
| synchronously or asynchronously with the DEVICE (OpenTitan) and a remote |
| registry and provisioning service. |
| |
| The physical transport layer between the DEVICE and the HOST is use-case |
| specific and managed at the OpenTitan SKU configuration level (e.g. different |
| `ROM_EXT` implementation per SKU). |
| |
| ### Overview |
| |
| The following diagram captures the Silicon Owner provisioning flow. Device |
| attestation requires the device to have a valid Creator Identity endorsed by the |
| Silicon Creator as described in the [Personalization](#personalization) section. |
| |
| The process can be implemented during manufacturing or post-manufacturing. If |
| implemented during manufacturing, the ATE and provisioning appliance fulfill the |
| role of the HOST. |
| |
| <table> |
| <tr> |
| <td> |
| <img src="img_provisioning_owner.svg" style="width: 900px;"> |
| </td> |
| </tr> |
| <tr> |
| <td style="text-align:center;">Figure: Owner personalization</td> |
| </tr> |
| </table> |
| |
| Steps: |
| |
| 1. [Device identifiers][device_id] (`device_id)` and Silicon [Creator |
| Certificates][attestation_certificate] are imported into the Silicon Owners |
| internal device registry. |
| 2. Ownership transfer is performed on the device to provision code verification |
| keys used as part of secure boot. Software signed by the Silicon Owner is |
| programmed on the device. |
| 3. The host verifies the attestation chain provided by the device and requests |
| a provisioning payload from the Silicon Owner's provisioning service. Data |
| in transit is encrypted with a key negotiated between the OpenTitan device |
| and the provisioning service. Provisioning data is divided into: |
| 1. Owner Certificate endorsed by the Silicon Owner. The owner can also |
| implement endorsement of additional certificates as part of the process. |
| 2. Additional Owner secrets required to provision application level |
| secrets. |
| 4. The host sends the provisioning payload to the device. The device unwraps |
| the secrets and installs them. |
| |
| ### Injection Process |
| |
| <table> |
| <tr> |
| <td> |
| <img src="img_provisioning_owner_injection.svg" style="width: 900px;"> |
| </td> |
| </tr> |
| <tr> |
| <td style="text-align:center;">Figure: Provisioning post-ownership transfer</td> |
| </tr> |
| </table> |
| |
| **RP0. Ownership transfer** |
| |
| The DEVICE is initially in UNOWNED state. The Silicon Owner triggers ownership |
| transfer and loads new software. Ownership transfer details are covered in a |
| separate document. |
| |
| See [Ownership Transfer][ownership_transfer] document for more details. |
| |
| **RP1. Get attestation certificates** |
| |
| The HOST requests attestation certificates from the DEVICE. A device that has |
| been transferred to a new owner has its attestation chain rooted in the Creator |
| Identity. See the [Attestation][attestation] documentation for more information. |
| |
| **RP2. Get `receiver_pub_key`** |
| |
| The DEVICE generates a `receiver` key pair and shares the `receiver_pub_key` |
| with the HOST. |
| |
| Additional data required to generate a new owner certificate and/or device |
| secrets is added to the payload. The payload is signed with the |
| `owner_identity_key` which can be verified against the DEVICE attestation chain |
| obtained in RP1. |
| |
| ``` |
| // ECC key pair generation compliant to FIPS 186-4 appendix B.4. |
| // Curves under consideration: NIST_P256 and NIST_P386. |
| receiver_priv_key, receiver_pub_key = ECC_KDF(DRBG_context) |
| |
| data = any additional data required to generate the owner cert. |
| hdr = ctx_id || receiver_pub_key || data |
| |
| // owner_identity_key is an ECC key as described in the Asymmetric |
| // Keys section of the Attestation document. |
| signature = ASYM_SIGN(key=owner_identity_priv_key, data=hdr) |
| |
| payload = hdr || signature |
| ``` |
| |
| **RP3. Get wrapped secrets and owner certificate** |
| |
| RP3.1. The provisioning service verifies the `receiver_pub_key` against the |
| attestation chain obtained in RP1 and the internal device registry. |
| |
| The provisioning service then generates a new `owner_certificate` with the |
| additional data provided by the DEVICE. The certificate is signed with a key |
| managed by the Silicon Owner (e.g. `owner_intermediate_ca_key`). The new |
| `owner_certificate` will be used as the root certificate in Attestation flows as |
| described in the [Attestation][attestation] document. |
| |
| RP3.2. The provisioning service performs ECIES encryption using the following |
| parameters: |
| |
| * `sender_priv_key`: Provisioning service private key. The public portion is |
| known to the DEVICE firmware. |
| * `receiver_pub_key`: DEVICE public key obtained in step RP2. |
| * `ctx_id`: Context ID provided by the device in step RP2. |
| * `owner_certificate`: New owner certificate generated in step RP3.1. |
| * `device_secrets`: Additional secrets bound to the device. May be generated |
| offline or as part of step RP3.1. |
| |
| ``` |
| payload = |
| ECIES_ENC(key=sender_priv_key, pub_key=receiver_pub_key, |
| data=(device_secrets | ctx_id)) |
| | owner_certificate |
| ``` |
| |
| RP3.3. The wrapped payload is sent to the DEVICE. |
| |
| **RP4. Unwrap and install secrets and owner certificate** |
| |
| Device performs ECIES decryption to unwrap the payload and install the new |
| `owner_certificate` and `device_secrets`. The owner has access to info flash |
| pages for storage of secrets. |
| |
| The `server_key_pub` and `ephemeral_pub_key` values are sent with the wrapped |
| payload. The public server key (`server_key_pub`) is also known to the software |
| running in the DEVICE. |
| |
| ``` |
| device_secrets || owner_certificate = |
| ECIES_DEC(key=receiver_priv_key, server_key_pub, |
| ephemeral_pub_key, data=enc_payload) |
| ``` |
| |
| **RP5: Get attestation certificates** |
| |
| The HOST issues a new attestation command to the DEVICE. The DEVICE responds |
| with an attestation chain rooted on the new `owner_certificate`. An additional |
| test command can be supported to test any functionality associated with the |
| `device_secrets`. |
| |
| ## ECIES Operations |
| |
| **Key Establishment** |
| |
| Key exchange is based on [NIST 800-56Ar3][nist_800_56r3] 6.2.1.2 Cofactor |
| One-Pass Unified Model Scheme, employing one ephemeral key, two secret keys and |
| ECC CDH. Both sender and receiver authentication are performed via public |
| crypto, thus one secret key is associated with the receiver, while the other one |
| is associated with the sender. |
| |
| **AEAD Modes of Operation** |
| |
| The following authenticated encryption schemes are supported by this |
| architecture: |
| |
| * AES-CTR-HMAC-12B-IV-32B-Tag (FIPS OK) |
| * AES-CTR-HMAC-16B-IV-32B-Tag (FIPS OK) |
| * AES-GCM (FIPS OK) |
| |
| ### Encryption |
| |
| <table> |
| <tr> |
| <td> |
| <img src="img_ecies_encryption.svg" style="width: 900px;"> |
| </td> |
| </tr> |
| <tr> |
| <td style="text-align:center;">Figure: ECIES Encryption, simplified diagram</td> |
| </tr> |
| </table> |
| |
| Inputs: |
| |
| * `receiver_pub_key`: ECC public key provided by the receiver point (e.g. |
| NIST_P256, NIST_P386 |
| * `sender_priv_key`: Sender ECC private key. |
| * `ctx_id`: Context identifier provided by the device. Used to control forward |
| secrecy of the protocol. For personalization this value is set to a portion |
| of the device identifier (`device_id`). |
| * `data`, `data_size`: Data to be encrypted and its size |
| * `ecies_key_length`: Target ECIES key length. Used as a configuration |
| parameter. |
| |
| Outputs: |
| |
| * `ephemeral_pub_key`: Ephemeral ECC shared key, required to perform |
| decryption. |
| * `tag`: MAC over payload. |
| * `ctx_id`: Context identifier provided by the device. |
| * `sender_pub_key`: Sender ECC public key. |
| * `data_enc`, `data_size`: Encrypted data and its size. |
| |
| Algorithm: |
| |
| ``` |
| // NIST 800-56Ar3 6.2.1.2 One-Pass Unified Model. This requires |
| // the creation of two shared secrets: shared_ephemeral and |
| // shared_static. |
| ephemeral_priv_key = GenerateEphemeralKey() |
| shared_ephemeral = |
| ECDH_compute_key(key_len, |
| EC_POINT(receiver_pub_key), ephemeral_priv_key) |
| shared_static = |
| ECDH_compute_key(key_len, |
| EC_POINT(receiver_pub_key), sender_priv_key) |
| |
| // Key derivation function used to calculate K and IV. |
| K, IV = key_and_iv_generaration( |
| ctx_id, data_size, shared_ephemeral, shared_static, |
| receiver_pub_key, sender_pub_key) |
| |
| // The following authenticated encryption approach follows encrypt |
| // then MAC approach. |
| // See also Alternative Authenticated Encryption Scheme |
| |
| // Ke length should be one of 128, 192, 256. |
| // Km length should be one of 256, 384, 512. |
| // K should have an entropy with a security strength equivalent to |
| // the one provided by Ke and Km when used with AES_CTR and MAC |
| // respectively. |
| [Ke || Km] = K |
| |
| data_enc = AES_CTR_ENC(Ke, IV, data) |
| tag = MAC(Km, ctx_id || sender_pub_key || data_size || data_enc) |
| |
| return [ |
| ephemeral_pub_key || tag || ctx_id || sender_pub_key || |
| data_size || data_enc] |
| ``` |
| |
| #### Alternative Authenticated Encryption Scheme |
| |
| The following implementation uses AES in GCM mode to obtain the ciphertext and |
| integrity tag. |
| |
| ``` |
| // The following authenticated encryption approach removes the need |
| // for separately calling a MAC function. In this case there is no |
| // need to split the key K into Ke and Km components. |
| |
| // All the parameters are taken from the main encryption pseudo-code |
| // block above. The following call replaces the AES_CTR and MAC |
| // calls. |
| data_enc, tag = |
| AES_GCM_ENC(K, IV, ctx_id || sender_pub_key || data_size || data) |
| ``` |
| |
| ### Decryption |
| |
| <table> |
| <tr> |
| <td> |
| <img src="img_ecies_decryption.svg" style="width: 900px;"> |
| </td> |
| </tr> |
| <tr> |
| <td style="text-align:center;">Figure: ECIES Decryption, simplified diagram</td> |
| </tr> |
| </table> |
| |
| Inputs: |
| |
| * `receiver_priv_key`: Receiver ECC private key. Generated by the device and |
| associated with the context identifier (`ctx_id`). |
| * `ephemeral_pub_key`: Ephemeral ECC shared key generated by the sender. |
| * `sender_pub_key`: Sender ECC public key. Embedded in payload sent to the |
| device. |
| * `ctx_id`: Context identifier provided by the device. |
| * `data`, `data_size`: Encrypted data and its size. |
| * `ecies_key_length`: Target ECIES key length. Used as a configuration |
| parameter. |
| |
| Outputs: |
| |
| The algorithm implementation currently includes authentication and integrity |
| checks, thus plaintext is the only documented output parameter. |
| |
| * `plaintext`, `size`: Plaintext data and its size. |
| |
| Algorithm: |
| |
| ``` |
| [ephemeral_pub_key || tag || ctx_id || |
| sender_pub_key || data_size || ciphertext ] = data |
| |
| // Check sender_pub_key against whitelist stored in device software. |
| check_sender_key(sender_pub_key) |
| |
| // NIST 800-56Ar3 6.2.1.2 One-Pass Unified Model. This requires |
| // the creation of two shared secrets: shared_ephemeral and |
| // shared_static. |
| ephemeral_key = GenerateEphemeralKey() |
| shared_ephemeral = |
| ECDH_compute_key(key_len, |
| EC_POINT(ephemeral_pub_key), ephemeral_priv_key) |
| shared_static = |
| ECDH_compute_key(key_len, |
| EC_POINT(sender_pub_key), ephemeral_priv_key) |
| |
| // Key derivation function used to calculate K and IV. |
| K, IV = key_and_iv_generaration( |
| ctx_id, data_size, shared_ephemeral, shared_static, |
| receiver_pub_key, sender_pub_key) |
| |
| // The following authenticated encryption approach follows encrypt |
| // then MAC approach. |
| // See also |
| |
| // Ke length should be one of 128, 192, 256. |
| // Km length should be one of 256, 384, 512. |
| // K should have an entropy with a security strength equivalent to |
| // the one provided by Ke and Km when used with AES_CTR and MAC |
| // respectively. |
| Ke || Km = K |
| |
| tag_expected = |
| MAC(Ke, ctx_id || sender_pub_key || data_size || data_enc) |
| |
| RETURN_ERROR_IF(tag != tag_expected) |
| RETURN_ERROR_IF(ctx_id != ctx_id_expected) |
| |
| plaintext = AES_CTR_DEC(Km, IV, data=ciphertext) |
| |
| return [plaintext] |
| ``` |
| |
| ### Key and IV Derivation |
| |
| Inputs: |
| |
| * `shared_ephemeral`: Derived ephemeral key. See Encryption and Decryption |
| algorithms for more details. |
| * `shared_static`: Derived static key. |
| * `ctx_id`: Context identifier provided by the device. |
| * `data_size`: Size of input data. |
| * `ecies_key_length`: Target ECIES key length. Used as a configuration |
| parameter. |
| |
| Outputs: |
| |
| * `K`: ECIES key of size equal to `ecies_key_length`. |
| * `IV`: `IV` parameter derived to use as AES decrypt parameter. |
| |
| Algorithm: |
| |
| ``` |
| shared_secret = shared_ephemeral || shared_static |
| salt = "shared_tag" || ctx_id || 00's padding |
| |
| // KDF based on NIST 800-56C 2-step key derivation. The extract and |
| // expand operations can be implemented via HMAC-SHA2. For SHA3 see |
| // Alternative KDF 1-step KMAC. |
| KDK = HKDF_extract(salt=salt, secret=shared_secret) |
| |
| L = ecies_key_length |
| label = "ot_encrypt" |
| context = receiver_pub_key || sender_pub_key |
| fixed_info = label || context || STRING(L) |
| |
| K = HKDF_expand(KDK, L, fixed_info) |
| |
| # IV generation using additional HKDF_expand |
| fixed_info_iv = "ot_iv" || context || STRING(12) |
| IV = HKDF_expand(KDK, 12, fixed_info_iv) |
| |
| return K, IV |
| ``` |
| |
| ##### Alternative KDF 1-step KMAC |
| |
| The following implementation uses a one-step key derivation function based on a |
| KMAC implementation (e.g. KMAC256). |
| |
| ``` |
| // KDF based on NIST 800-56C section 4.1 1-step key derivation. |
| // Using KMAC256 as specified in section 4.1 option 3. |
| L = ecies_key_length |
| label = "ot_encrypt" |
| context = receiver_pub_key || sender_pub_key |
| fixed_info = label || context || STRING(L) |
| |
| salt = |
| "shared_tag" || ctx_id || 00's padding up to key size |
| |
| other_input = salt || fixed_info |
| K = HKDF(secret=shared_secret, L, other_intput) |
| |
| |
| fixed_info_iv = "ot_iv" || context || STRING(12) |
| IV = HKDF(secret=shared_secret, 12, |
| other_input=salt || fixed_info_iv) |
| |
| return K, IV |
| ``` |
| |
| <!-- Footnotes themselves at the bottom. --> |
| |
| ## Notes |
| |
| |
| [^1]: This is a static key within the context of a personalization run. The key |
| is erased after personalization is complete. |
| |
| |
| [attestation]: ../attestation/README.md |
| [attestation_keys]: ../attestation/README.md#asymmetric-keys |
| [attestation_certificate]: ../attestation/README.md#certificate-format |
| [creator_identity]: ../identities_and_root_keys/README.md#creator-identity |
| [device_lifecycle]: ../device_life_cycle/README.md |
| [device_id]: ../identities_and_root_keys/README.md#device-identifier |
| [identities_and_root_keys]: ../identities_and_root_keys/README.md |
| [nist_800_56r3]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar3.pdf |
| [ownership_transfer]: ../ownership_transfer/README.md |