OP-TEE / optee_os

Trusted side of the TEE
Other
1.53k stars 1.03k forks source link

RPMB: SOLVING the problem with two different set of TEE images #2887

Closed dashemsec closed 4 years ago

dashemsec commented 5 years ago

With the current RPMB implementation, there is a flaw, which has been discussed in thread https://github.com/OP-TEE/optee_os/issues/975, to avoid the attack w.r.t the RPMB, one should generate to sets of OPTEE image: factory and production. But again the problem will arise. Let’s say in your mobile device emmc get damaged and you go to the service center to replace the emmc. Then from where you will get the factory image.

Here I am proposing a solution with a Proof-of-concept done and submitted in my OPTEE forked branch.

Looking to the patch, you will find the tee_rpmb_ctx has been modified: _struct tee_rpmb_ctx { uint8_t key[RPMB_KEY_MAC_SIZE]; uint8_t cid[RPMB_EMMC_CID_SIZE]; uint32_t wr_cnt; uint16_t max_blk_idx; uint16_t rel_wr_blkcnt; uint16_t dev_id; uint8_t key_data[RPMB_STORAGE_KEY_DATA_LENGTH]; bool key_data_written; bool wr_cnt_synced; bool key_derived; bool key_verified; bool dev_infosynced; };

Step 1 Provisioning of RPMB key: We can use the some dedicated block in the RPMB (let’s say block 1 after the partition data), to generate and store some critical key data.

image

The whole key generation & write process will go something like this on a fresh RPMB device:

  1. Initialize HMAC-256 with the Hardware Unique Key.
  2. HMAC update with the EMMC CID data.
  3. Generate a pseudo random number and HMAC update the same.
  4. HMAC final the RPMB key and write the key to RPMB OTP.
  5. RPMB write the random number generated in Step 3 to the RPMB KEY DATA PARTITION (256).

Step 2 On a device reboot When you reboot the target this is expected to happen:

  1. Expecting RPMB key data is already written, Initialize HMAC-256 with the Hardware Unique Key.
  2. HMAC update with the EMMC CID data.
  3. Read the key random data from the KEY DATA area of RPMB. Don’t verify it since we haven’t read the write count from partition data.
  4. HMAC final the RPMB key.
  5. Verify the same with tee_rpmb_verify_key_sync_counter().

image

The above POC is tested with tee-supplicant built with RPMB-EMU mode with the following changes.https://github.com/dashemsec/optee_client/commit/adcb1cccd2ceebf4c88da5115ae3ffa0f5ff4b2e

jbech-linaro commented 5 years ago

Hi @dashemsec ,

Thanks for the proposal and gold star to you for the nice and clean diagrams explaining it all. I probably need some more time thinking about this, but my initial reflections are:

Main use cases / threats

  1. I resolder/replace the eMMC
    1. This initiates a new setup from scratch.
    2. No old data is leaked, since we will generate a new random number. I.e., you cannot do this, re-mount the old eMMC and get access to the RPMB data.
  2. I snoop the connection on a regular boot (after initial boot)
    1. No issues, we will only see the (same) random number being shared and without knowing HUK + CID, the attacker cannot figure out the the correct HMAC key.

My initial impression is that your proposal solves "1" above, but we still have to deal with programming the initial RPMB authentication key in a controlled environment. But, I'm having issues with understanding how to be able to read out the RPMB KEY DATA, without any authentication?

bingzhux commented 5 years ago

you're solving one of issues: the RPMB key will be different in the same platform after eMMC is replaced with a blank/fresh one.

but why is CID alone not sufficient, I meant that why do you need to add "random number"? I believe the CID will be different across different emmc devices. If you think someone (adversary) can modify the eMMC with physical tamper methods or spoof bus to alter the CID, they can do it the same for random number because when you're reading the "random number" from device without verification, the "random value" is not trusted either (just like CID).

@jbech-linaro i'm not sure if i understand your question correctly. here is what i think: without key programming into RPMB, any read/write request will be denied; without RPMB key (after key is programmed into RPMB), anyone can read the data from RPMB, but data is not authenticated, so it may be or may not be trusted; without RPMB key, write access will be denied.

Notes: some of bits in CID probably will be updated after a RPMB firmware in-field upgrade. so even for the same eMMC device, the CID would be different under this case.

dashemsec commented 5 years ago

Hi @jbech-linaro to solve the circular dependency, I have defined a function that reads the data without authentication. @bzhu5 "random number" is generated by the OPTEE (generally using TRNG protected from normal world access). Now let's say the emmc is spoofed (to act as new emmc), so according to my changes tee_rpmb_key_gen() will fail so do tee_rpmb_verify_key_sync_counter(), thus ultimately it will go for tee_rpmb_write_and_verify_key() which will re-generate the key with a new random number, thus the key programmed in the spoofed device will not be the same as the original emmc device.

Even if the attacker read the random number (refered to as RPMB KEY DATA in above diagram), he/she cannot get the rpmb key using the rpmb key data and emmc CID.

jenswi-linaro commented 5 years ago

How can you do unauthenticated access to RPMB? Are we talking about some new RPMB feature?

jbech-linaro commented 5 years ago

How can you do unauthenticated access to RPMB? Are we talking about some new RPMB feature?

Exactly, that was my question also. If I read the eMMC spec (I've looked at both 4.4 and 5.1) it says that a read operation is started by sending a read request with 0x04: Authenticated data read request.

types

Then the spec says: After successful data fetch the MAC is calculated from response type, nonce, address, data and result . If the MAC calculation fails then returned result is 0x02 (Authentication failure). The data itself is read out with the Read Multiple Block command, CMD18. In prior to the read command ... indicated. The data information itself is delivered in the read data packet. The packet size is 512B and it is including the response type information, the block count, a copy of the nonce received in the request, the data address, the data itself, the MAC and the result. In multiple block write case the MAC is included only to the last packet n, the n-1 packets will include value 0x00. In every packet the address is the start address of the full access (not address of the individual half a sector) and the block count is the total count of the half sectors (not the sequence number of the half a sector). If data fetch from addressed location inside e-MMC fails then returned result is 0x06 (Read failure). If some other error occurs during the read procedure then returned result is 0x01 (General failure).

It's not clear to me whether you still can read data after an authentication failure after doing the read request. However, it sounds strange that something like RPMB would allow that. That would mean that there would only be write protection on RPMB and no read protection at all. I.e., anyone can read out whatever is stored in the RPMB partition. I doubt that is the case.

bingzhux commented 5 years ago

@jenswi-linaro @jbech-linaro I just check again in my UFS spec, see this picture below. image

In the "Authenticated Data Read Request", the software has no need to fill up the MAC/Key fields when placing such a request, which means that the h/w doesn't check/verify the MAC from "Authenticated Data Read Request", and as per request, the h/w just blindly reads data, calculates the MAC with internal programmed key, copies the nonce, and places all these in the "Authenticated Data Read Response", and sends them back to s/w.

However, s/w is responsible for doing verification of received data, if s/w has no key for verification, then the data is untrusted.

Besides, we never see any document or specification saying that the RPMB can protect data confidentiality, right? I know that RPMB can only provide data integrity and replay protection.

Anyone who doesn't have the key can read your data in RPMB, so is it s/w's responsibility to encrypt the data (if applicable) before sending it to RPMB for confidentiality protection.

bingzhux commented 5 years ago

@dashemsec it seems that I understood your point here. If someone spoofs the eMMC bus to change the request code to 0x7, which means the key is not programmed yet, and lures you to send the plaintext key for reprogramming the key, then you will generate a new different random value, and use the new random number to derive the new RPMB key along with CID and HuK.

Then even if the attacker get the new RPMB key by bus spoofing, but this is a different key.

If the attacker can spoof the bus in Step 2.3 below, then change the random number, they can do nothing, but just make a DoS attack.

Read the key random data from the KEY DATA area of RPMB. Don’t verify it since we haven’t read the write count from partition data.

github-actions[bot] commented 4 years ago

This issue has been marked as a stale issue because it has been open (more than) 30 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this issue will automatically be closed in 5 days. Note, that you can always re-open a closed issue at any time.