Optiga data object configuration

The following table outlines the Optiga data object configuration used in Trezor Safe 3 and Trezor Safe 5.

OIDNameReadWriteExecuteType/UsageSize (bytes)NotesStorage version
E0E0CERT_INFAlwaysNeverAlwaysDEVCERTInfineon certificate.
E0E1CERT_DEVAlwaysNeverAlwaysDEVCERTDevice certificate chain.
E0E2CERT_FIDOAlwaysNeverAlwaysDEVCERTFIDO attestation certificate.
E0E3DEVCERT≤ 1728Unused public key certificate.
E0E8TA≤ 1200Unused root CA public key certificate.
E0E9TA≤ 1200Unused root CA public key certificate.
E0F0KEY_DEVNeverNeverConf(KEY_PAIRING)SignNIST P-256 device private key.
E0F1Unused private ECC key.
E0F2KEY_FIDONeverNeverConf(KEY_PAIRING)SignNIST P-256 FIDO attestation private key.
E0F3PIN_ECDHNeverAlwaysLuc(PIN_TOTAL_CTR)KeyAgreeNIST P-256 key for ECDH PIN stretching step.≥ 3
E120STRETCHED_PIN_CTRAlwaysAuto(PIN_SECRET)AlwaysUPCTR8Counter which limits the guesses at STRETCHED_PIN. Limit set to 16.≥ 3
E121PIN_TOTAL_CTRAlwaysNeverAlwaysUPCTR8Counter which limits the total number of PIN stretching operations over the lifetime of the device. Limit set to 600000, meaning 150000 unlock attempts.≥ 3
E122PIN_HMAC_CTRAlwaysAuto(STRETCHED_PIN)AlwaysUPCTR8Counter which limits the use of PIN_HMAC. Limit set to 16.≥ 5
E123UPCTR8Unused monotonic counter.
E140KEY_PAIRINGNeverNeverAlwaysPTFBIND32Shared platform binding secret.
E200PIN_CMACNeverAlwaysLuc(PIN_TOTAL_CTR)Enc32Key for AES-CMAC PIN stretching step.≥ 3
F1D0PIN_SECRETAuto(STRETCHED_PIN)AlwaysAlwaysAUTOREF32Counter-protected PIN secret and reset key for STRETCHED_PIN_CTR.≥ 3
F1D1PIN_HMAC_V4NeverNeverLuc(PIN_TOTAL_CTR)PRESSEC32Deprecated key for HMAC-SHA256 PIN stretching step.3, 4
F1D2≤ 140Unused data object.
F1D3≤ 140Unused data object.
F1D4STRETCHED_PINNeverAuto(PIN_SECRET)Luc(STRETCHED_PIN_CTR)AUTOREF32Digest of the stretched PIN.≥ 3
F1D5≤ 140Unused data object.
F1D6≤ 140Unused data object.
F1D7≤ 140Unused data object.
F1D8PIN_HMACNeverAuto(STRETCHED_PIN)Luc(PIN_HMAC_CTR)PRESSEC32Counter-protected key for HMAC-SHA256 PIN stretching step.≥ 5
F1D9≤ 140Unused data object.
F1DA≤ 140Unused data object.
F1DB≤ 140Unused data object.
F1E0≤ 1500Unused data object.
F1E1≤ 1500Unused data object.

Optiga PIN protection

The diagram below summarizes the main relationships between the data objects that play a role in PIN protection. An arrow from X to Y indicates that X authorizes the specified operation on Y.

  • If X is a monotonic counter, then the specified operation on Y is allowed only if the counter value is below the threshold. The operation causes X to be incremented.
  • If X is a secret, then the specified operation on Y is allowed only if the host MCU proves knowledge of the value stored in X.
  • If X is Always, then the specified operation is always allowed.
graph LR Always -- Write --> PIN_SECRET PIN_SECRET -- Write --> STRETCHED_PIN PIN_SECRET -- Write --> STRETCHED_PIN_CTR STRETCHED_PIN_CTR -- Execute --> STRETCHED_PIN STRETCHED_PIN -- Read --> PIN_SECRET STRETCHED_PIN -- Write --> PIN_HMAC_CTR PIN_HMAC_CTR -- Execute --> PIN_HMAC STRETCHED_PIN -- Write --> PIN_HMAC

Stretching pattern

The Optiga's role in PIN protection is to add a series of PIN stretching steps to the process of computing the storage key encryption key (KEK). All stretching operations are limited either by the global counter PIN_TOTAL_CTR or by one of the PIN attempt counters PIN_HMAC_CTR and STRETCHED_PIN_CTR. Each stretching step is wrapped in the following pattern:

digest = hmac_sha256(stretched_pin, "") output = optiga_operation(..., digest) stretched_pin = hmac_sha256(stretched_pin, output)

In this pattern, the stretched PIN is first processed using a one-way function before sending it to the Optiga. This ensures that in the unlikely case of an attacker recording communication between the MCU and Optiga or extracting the secret in STRETCHED_PIN, they will not gain knowledge of the stretched PIN, only its digest. Second, the digest is sent to the Optiga which uses it to generate an output. That output is then used to stretch the PIN. This method ensures that if the user chooses a high-entropy PIN or if at least one of the preceding stretching operations remains secure, then even if the communication link or the Optiga is completely compromised, possibly even malicious, it will not reduce the security of the Trezor any more than if the Optiga was not integrated into the Trezor in the first place.

Optiga stretching process

The following pseudocode outlines the process of stretching the PIN by Optiga.

optiga_pin_verify(stretched_pin): # Stretch the PIN with the secrets in PIN_CMAC and PIN_ECDH. PIN_STRETCH_ITERATIONS = 2 for _ in range(PIN_STRETCH_ITERATIONS): # Stretch the PIN with PIN_CMAC and PIN_ECDH secrets in the Optiga. digest = hmac_sha256(stretched_pin, "") cmac_out = encrypt_sym(SYM_MODE_CMAC, PIN_CMAC, digest) point = hash_to_curve(digest) ecdh_out = calc_ssec(CURVE_P256, PIN_ECDH, point) stretched_pin = hmac_sha256(stretched_pin, cmac_out + ecdh_out) # Stretch the PIN with the secret in PIN_HMAC. digest = hmac_sha256(stretched_pin, "") hmac_buffer = encrypt_sym(SYM_MODE_HMAC_SHA256, PIN_HMAC, digest) stretched_pin = hmac_sha256(stretched_pin, hmac_buffer) # Authorise using STRETCHED_PIN so that we can read from PIN_SECRET and reset PIN_HMAC_CTR. digest = hmac_sha256(stretched_pin, "") if not set_auto_state(STRETCHED_PIN, digest): raise InvalidPinError pin_secret = get_data_object(PIN_SECRET) stretched_pin = hmac_sha256(stretched_pin, pin_secret) set_data_object(PIN_HMAC_CTR, COUNTER_RESET) # Authorise using PIN_SECRET so that we can reset STRETCHED_PIN_CTR. set_auto_state(PIN_SECRET, pin_secret) set_data_object(STRETCHED_PIN_CTR, COUNTER_RESET) return stretched_pin

The first step of the stretching process hardens the PIN protection in case a vulnerability is discovered that allows the extraction of the secret value of a data object in Optiga that has a particular configuration, but does not allow extraction for other kinds of data objects. An attacker would need to be able to extract each of the secrets in PIN_CMAC, PIN_ECDH, PIN_HMAC and PIN_SECRET to conduct an offline brute-force search for the PIN. Thus it reduces the number of PIN values that the attacker can test in a unit of time by forcing them to involve the Optiga in each attempt, and restricts the overall number of attempts using PIN_TOTAL_CTR.

The rest of the process makes use of the data objects that are depicted in the diagram. The configuration of these data objects is designed with the goal of making the system resettable under all circumstances, i.e. even if the previous PIN is forgotten, flash storage is wiped and counters are depleted. There are two PIN attempt counters STRETCHED_PIN_CTR and PIN_HMAC_CTR, which both have a limit of 16 attempts and have identical values under normal circumstances.

PIN_HMAC_CTR limits the number of possible PIN attempts, but together with PIN_HMAC it also serves to mitigate a so called PIN-only attack. Without this counter it would be possible to partially reset the system by overwriting PIN_SECRET and resetting STRETCHED_PIN_CTR to gain an unlimited number of attempts at checking for the correct PIN, but without the possibility to derive the correct storage key encryption key, since the PIN_SECRET is overwritten. This attack is dangerous in case a user has two devices with the same PIN, because one of the devices could be used to determine the correct PIN and the other could then be unlocked. Note that in order for the mitigation to be effective, write access to PIN_HMAC_CTR must be authorized by STRETCHED_PIN. This implies that the attacker cannot reset PIN_HMAC_CTR without first overwriting STRETCHED_PIN, thus ruining the ability of checking for the correct PIN.

STRETCHED_PIN_CTR also limits the number of possible PIN attempts. Its presence is actually not necessary, but serves as an additional countermeasure in case a vulnerability is discovered that allows an attacker to read data objects of type PRESSEC, specifically PIN_HMAC. In that case, the attacker would still be restricted by the STRETCHED_PIN_CTR in the number of PIN attempts they can make. After they depleted the counter, the worst they could do is overwrite PIN_SECRET to execute the aforementioned PIN-only attack.

PIN_SECRET and STRETCHED_PIN play an essential role in making the system resettable, yet secure. Since PIN_SECRET is used in the last PIN stretching step, there needs to be a data object that grants read access to PIN_SECRET, which is why STRETCHED_PIN is needed in the system. Anyone attempting to reset the system must first overwrite PIN_SECRET thus losing the value that is necessary to complete the PIN stretching. Suppose there was no PIN_SECRET in the system and the PIN, stretched by PIN_HMAC, was used directly as the storage key encryption key. Then STRETCHED_PIN would have to be writable always, and an attacker could rewrite STRETCHED_PIN, reset the PIN_HMAC_CTR, and gain an unlimited number of attempts to guess the PIN.