Skip to content

Commit

Permalink
storage: encrypt the FEK with a TA-specific key
Browse files Browse the repository at this point in the history
The File Encryption Key is now encrypted with a Trusted application
Storage Key (TSK) rather than directly with the Secure Storage Key.
The TSK is derived from the SSK and the TA UUID. This improves
isolation between TAs, and makes it impossible to read the data of a
TA from another TA after manually moving files in the REE filesystem
for instance.

Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
Reviewed-by: David Brown <david.brown@linaro.org>
  • Loading branch information
jforissier committed Aug 2, 2016
1 parent 61b59a7 commit fde4a75
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 58 deletions.
2 changes: 2 additions & 0 deletions core/include/tee/tee_fs_key_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@
#define TEE_FS_KEY_MANAGER_H

#include <tee_api_types.h>
#include <utee_defines.h>

#define TEE_FS_KM_CHIP_ID_LENGTH 32
#define TEE_FS_KM_HMAC_ALG TEE_ALG_HMAC_SHA256
#define TEE_FS_KM_AUTH_ENC_ALG TEE_ALG_AES_GCM
#define TEE_FS_KM_ENC_FEK_ALG TEE_ALG_AES_ECB_NOPAD
#define TEE_FS_KM_SSK_SIZE TEE_SHA256_HASH_SIZE
#define TEE_FS_KM_TSK_SIZE TEE_SHA256_HASH_SIZE
#define TEE_FS_KM_FEK_SIZE 16 /* bytes */
#define TEE_FS_KM_IV_LEN 12 /* bytes */
#define TEE_FS_KM_MAX_TAG_LEN 16 /* bytes */
Expand Down
109 changes: 61 additions & 48 deletions core/tee/tee_fs_key_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,23 @@
*/


/* Acronyms:
/*
* Acronyms:
*
* FEK - File Encryption Key
* SST - Secure Storage
* SSK - Secure Storage Key
* TSK - Trusted app Storage Key
* IV - Initial vector
* HUK - Hardware Unique Key
* RNG - Random Number Generator
*
* */
*/

#include <initcall.h>
#include <stdlib.h>
#include <string.h>
#include <kernel/tee_common_otp.h>
#include <kernel/tee_common_unpg.h>
#include <kernel/tee_ta_manager.h>
#include <tee/tee_cryp_utl.h>
#include <tee/tee_cryp_provider.h>
#include <tee/tee_fs_key_manager.h>
Expand All @@ -68,13 +69,55 @@ static struct tee_fs_ssk tee_fs_ssk;
static uint8_t string_for_ssk_gen[] = "ONLY_FOR_tee_fs_ssk";


static TEE_Result do_hmac(uint8_t *out_key, uint32_t out_key_size,
const uint8_t *in_key, uint32_t in_key_size,
const uint8_t *message, uint32_t message_size)
{
TEE_Result res = TEE_ERROR_GENERIC;
uint8_t *ctx = NULL;
size_t hash_ctx_size = 0;

if (!out_key || !in_key || !message)
return TEE_ERROR_BAD_PARAMETERS;

res = crypto_ops.mac.get_ctx_size(TEE_FS_KM_HMAC_ALG, &hash_ctx_size);
if (res != TEE_SUCCESS)
return res;

ctx = malloc(hash_ctx_size);
if (!ctx)
return TEE_ERROR_OUT_OF_MEMORY;

res = crypto_ops.mac.init(ctx, TEE_FS_KM_HMAC_ALG, in_key, in_key_size);
if (res != TEE_SUCCESS)
goto exit;

res = crypto_ops.mac.update(ctx, TEE_FS_KM_HMAC_ALG,
message, message_size);
if (res != TEE_SUCCESS)
goto exit;

res = crypto_ops.mac.final(ctx, TEE_FS_KM_HMAC_ALG, out_key,
out_key_size);
if (res != TEE_SUCCESS)
goto exit;

res = TEE_SUCCESS;

exit:
free(ctx);
return res;
}

static TEE_Result fek_crypt(TEE_OperationMode mode,
uint8_t *key, int size)
{
TEE_Result res;
uint8_t *ctx = NULL;
size_t ctx_size;
uint8_t tsk[TEE_FS_KM_TSK_SIZE];
uint8_t dst_key[TEE_FS_KM_FEK_SIZE];
struct tee_ta_session *sess;

if (!key)
return TEE_ERROR_BAD_PARAMETERS;
Expand All @@ -85,6 +128,15 @@ static TEE_Result fek_crypt(TEE_OperationMode mode,
if (tee_fs_ssk.is_init == 0)
return TEE_ERROR_GENERIC;

res = tee_ta_get_current_session(&sess);
if (res != TEE_SUCCESS)
return res;

res = do_hmac(tsk, sizeof(tsk), tee_fs_ssk.key, TEE_FS_KM_SSK_SIZE,
(uint8_t *)&sess->ctx->uuid, sizeof(TEE_UUID));
if (res != TEE_SUCCESS)
return res;

res = crypto_ops.cipher.get_ctx_size(TEE_FS_KM_ENC_FEK_ALG, &ctx_size);
if (res != TEE_SUCCESS)
return res;
Expand All @@ -93,9 +145,8 @@ static TEE_Result fek_crypt(TEE_OperationMode mode,
if (!ctx)
return TEE_ERROR_OUT_OF_MEMORY;

res = crypto_ops.cipher.init(ctx, TEE_FS_KM_ENC_FEK_ALG,
mode, tee_fs_ssk.key, TEE_FS_KM_SSK_SIZE,
NULL, 0, NULL, 0);
res = crypto_ops.cipher.init(ctx, TEE_FS_KM_ENC_FEK_ALG, mode, tsk,
sizeof(tsk), NULL, 0, NULL, 0);
if (res != TEE_SUCCESS)
goto exit;

Expand Down Expand Up @@ -124,45 +175,6 @@ static TEE_Result generate_iv(uint8_t *iv, uint8_t len)
return crypto_ops.prng.read(iv, len);
}

static TEE_Result generate_ssk(uint8_t *ssk, uint32_t ssk_size,
uint8_t *huk, uint32_t huk_size,
uint8_t *message, uint32_t message_size)
{
TEE_Result res = TEE_ERROR_GENERIC;
uint8_t *ctx = NULL;
size_t hash_ctx_size = 0;

if (!ssk || !huk || !message)
return TEE_ERROR_BAD_PARAMETERS;

res = crypto_ops.mac.get_ctx_size(TEE_FS_KM_HMAC_ALG, &hash_ctx_size);
if (res != TEE_SUCCESS)
return res;

ctx = malloc(hash_ctx_size);
if (!ctx)
return TEE_ERROR_OUT_OF_MEMORY;

res = crypto_ops.mac.init(ctx, TEE_FS_KM_HMAC_ALG, huk, huk_size);
if (res != TEE_SUCCESS)
goto exit;

res = crypto_ops.mac.update(ctx, TEE_FS_KM_HMAC_ALG,
message, message_size);
if (res != TEE_SUCCESS)
goto exit;

res = crypto_ops.mac.final(ctx, TEE_FS_KM_HMAC_ALG, ssk, ssk_size);
if (res != TEE_SUCCESS)
goto exit;

res = TEE_SUCCESS;

exit:
free(ctx);
return res;
}

static TEE_Result tee_fs_init_key_manager(void)
{
int res = TEE_SUCCESS;
Expand All @@ -182,7 +194,7 @@ static TEE_Result tee_fs_init_key_manager(void)
memcpy(message + sizeof(chip_id), string_for_ssk_gen,
sizeof(string_for_ssk_gen));

res = generate_ssk(tee_fs_ssk.key, sizeof(tee_fs_ssk.key),
res = do_hmac(tee_fs_ssk.key, sizeof(tee_fs_ssk.key),
huk.data, sizeof(huk.data),
message, sizeof(message));

Expand Down Expand Up @@ -318,7 +330,8 @@ TEE_Result tee_fs_encrypt_file(enum tee_fs_file_type file_type,
* Block File Format: |Header|Ciphertext|
* Header Format: |IV|Tag|
*
* FEK = AES_DECRYPT(SSK, Encrypted_FEK)
* TSK = HMAC(SSK, TA_UUID)
* FEK = AES_DECRYPT(TSK, Encrypted_FEK)
* Chipertext = AES_GCM_ENCRYPT(FEK, IV, Meta_Info, AAD)
*/

Expand Down
4 changes: 2 additions & 2 deletions core/tee/tee_rpmb_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1406,7 +1406,7 @@ static TEE_Result tee_rpmb_write_blk(uint16_t dev_id, uint16_t blk_idx,
* @addr Byte address of data.
* @data Pointer to the data.
* @len Size of data in bytes.
* @fek SSK-encrypted File Encryption Key or NULL.
* @fek Encrypted File Encryption Key or NULL.
*/
static TEE_Result tee_rpmb_read(uint16_t dev_id, uint32_t addr, uint8_t *data,
uint32_t len, uint8_t *fek)
Expand Down Expand Up @@ -1437,7 +1437,7 @@ static bool tee_rpmb_write_is_atomic(uint16_t dev_id __unused, uint32_t addr,
* @addr Byte address of data.
* @data Pointer to the data.
* @len Size of data in bytes.
* @fek SSK-encrypted File Encryption Key or NULL.
* @fek Encrypted File Encryption Key or NULL.
*/
static TEE_Result tee_rpmb_write(uint16_t dev_id, uint32_t addr,
const uint8_t *data, uint32_t len,
Expand Down
16 changes: 12 additions & 4 deletions documentation/secure_storage.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,13 @@ TEE file is 1024.

Key manager is an component in TEE file system, and is responsible for handling
data encryption and decryption and also management of the sensitive key
materials. There are two types of keys used by key manager. One is Secure
Storage Key (SSK) and another one is File Encryption Key (FEK).
materials. There are three types of keys used by the key manager: the Secure
Storage Key (SSK), the TA Storage KEY (TSK) and the File Encryption Key (FEK).

### Secure Storage Key (SSK)

SSK is a per-device key and is generated and stored in secure memory when OP-TEE
is booting. SSK is used for protecting FEK, in other words, is used for
encrypting/decrypting FEK.
is booting. SSK is used to derive the TA Storage Key (TSK).

SSK is derived by:
> SSK = HMAC<sub>SHA256</sub> (HUK, Chip ID || "static string")
Expand All @@ -129,6 +128,15 @@ per-device keys for different subsystems using the same algorithm as we
generate the SSK; An easy way to generate different per-device keys for
different subsystems is using different static strings to generate the keys.

### Trusted Application Storage Key (TKS)

The TSK is a per-Trusted Application key, which is generated from the SSK and
the TA's identifier (UUID). It is used to protect the FEK, in other words,
to encrypt/decrypt the FEK.

TSK is derived by:
> TSK = HMAC<sub>SHA256</sub> (SSK, TA_UUID)
### File Encryption Key (FEK)

When a new TEE file is created, key manager will generate a new FEK by
Expand Down
9 changes: 5 additions & 4 deletions documentation/secure_storage_rpmb.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,17 @@ off with `CFG_ENC_FS=n`. The algorithm is 128-bit AES in Cipher Block Chaining

- During OP-TEE initialization, a 128-bit AES Secure Storage Key (SSK) is
derived from a Hardware Unique Key (HUK). It is kept in secure memory and never
written to disk.
written to disk. A Trusted Application Storage Key is derived from the SSK and
the TA UUID.
- For each file, a 128-bit encrypted File Encryption Key (FEK) is randomly
generated when the file is created and stored in the FAT entry for the file.
Before use, this key is decrypted using the SSK.
generated when the file is created, encrypted with the TSK and stored in the FAT
entry for the file.
- Each 256-byte block of data is then encrypted in CBC mode. The initialization
vector is obtained by the ESSIV algorithm, that is, by encrypting the block
number with a hash of the FEK. This allows direct access to any block in the
file, as follows:
```
FEK = AES-Decrypt(encrypted FEK);
FEK = AES-Decrypt(TSK, encrypted FEK);
k = SHA256(FEK);
IV = AES-Encrypt(128 bits of k, block index padded to 16 bytes)
Encrypted block = AES-CBC-Encrypt(FEK, IV, block data);
Expand Down

0 comments on commit fde4a75

Please sign in to comment.