From fde4a756bfc837d36bae74853194f0f6646e7b36 Mon Sep 17 00:00:00 2001 From: Jerome Forissier Date: Tue, 2 Aug 2016 10:33:57 +0200 Subject: [PATCH] storage: encrypt the FEK with a TA-specific key 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 Reviewed-by: David Brown --- core/include/tee/tee_fs_key_manager.h | 2 + core/tee/tee_fs_key_manager.c | 109 ++++++++++++++------------ core/tee/tee_rpmb_fs.c | 4 +- documentation/secure_storage.md | 16 +++- documentation/secure_storage_rpmb.md | 9 ++- 5 files changed, 82 insertions(+), 58 deletions(-) diff --git a/core/include/tee/tee_fs_key_manager.h b/core/include/tee/tee_fs_key_manager.h index ac4ff50214a..cbb5e11bec4 100644 --- a/core/include/tee/tee_fs_key_manager.h +++ b/core/include/tee/tee_fs_key_manager.h @@ -29,12 +29,14 @@ #define TEE_FS_KEY_MANAGER_H #include +#include #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 */ diff --git a/core/tee/tee_fs_key_manager.c b/core/tee/tee_fs_key_manager.c index 19cc5c11263..8fa2282871f 100644 --- a/core/tee/tee_fs_key_manager.c +++ b/core/tee/tee_fs_key_manager.c @@ -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 #include #include #include #include +#include #include #include #include @@ -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; @@ -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; @@ -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; @@ -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; @@ -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)); @@ -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) */ diff --git a/core/tee/tee_rpmb_fs.c b/core/tee/tee_rpmb_fs.c index 20ab8f616e1..2c8b55d8fe0 100644 --- a/core/tee/tee_rpmb_fs.c +++ b/core/tee/tee_rpmb_fs.c @@ -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) @@ -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, diff --git a/documentation/secure_storage.md b/documentation/secure_storage.md index e6d6cc6c442..e4824c0a99c 100644 --- a/documentation/secure_storage.md +++ b/documentation/secure_storage.md @@ -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 = HMACSHA256 (HUK, Chip ID || "static string") @@ -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 = HMACSHA256 (SSK, TA_UUID) + ### File Encryption Key (FEK) When a new TEE file is created, key manager will generate a new FEK by diff --git a/documentation/secure_storage_rpmb.md b/documentation/secure_storage_rpmb.md index 0437265a597..0d21928ecac 100644 --- a/documentation/secure_storage_rpmb.md +++ b/documentation/secure_storage_rpmb.md @@ -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);