1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2015, Linaro Limited 4 */ 5 6 7 /* 8 * Acronyms: 9 * 10 * FEK - File Encryption Key 11 * SSK - Secure Storage Key 12 * TSK - Trusted app Storage Key 13 * IV - Initial vector 14 * HUK - Hardware Unique Key 15 * RNG - Random Number Generator 16 */ 17 18 #include <assert.h> 19 #include <compiler.h> 20 #include <crypto/crypto.h> 21 #include <initcall.h> 22 #include <kernel/huk_subkey.h> 23 #include <kernel/panic.h> 24 #include <kernel/tee_common_otp.h> 25 #include <kernel/tee_ta_manager.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <tee/tee_cryp_utl.h> 29 #include <tee/tee_fs_key_manager.h> 30 #include <trace.h> 31 #include <util.h> 32 33 struct tee_fs_ssk { 34 bool is_init; 35 uint8_t key[TEE_FS_KM_SSK_SIZE]; 36 }; 37 38 static struct tee_fs_ssk tee_fs_ssk; 39 40 static TEE_Result do_hmac(void *out_key, size_t out_key_size, 41 const void *in_key, size_t in_key_size, 42 const void *message, size_t message_size) 43 { 44 TEE_Result res; 45 void *ctx = NULL; 46 47 if (!out_key || !in_key || !message) 48 return TEE_ERROR_BAD_PARAMETERS; 49 50 res = crypto_mac_alloc_ctx(&ctx, TEE_FS_KM_HMAC_ALG); 51 if (res != TEE_SUCCESS) 52 return res; 53 54 res = crypto_mac_init(ctx, TEE_FS_KM_HMAC_ALG, in_key, in_key_size); 55 if (res != TEE_SUCCESS) 56 goto exit; 57 58 res = crypto_mac_update(ctx, TEE_FS_KM_HMAC_ALG, message, message_size); 59 if (res != TEE_SUCCESS) 60 goto exit; 61 62 res = crypto_mac_final(ctx, TEE_FS_KM_HMAC_ALG, out_key, out_key_size); 63 if (res != TEE_SUCCESS) 64 goto exit; 65 66 res = TEE_SUCCESS; 67 68 exit: 69 crypto_mac_free_ctx(ctx, TEE_FS_KM_HMAC_ALG); 70 return res; 71 } 72 73 TEE_Result tee_fs_fek_crypt(const TEE_UUID *uuid, TEE_OperationMode mode, 74 const uint8_t *in_key, size_t size, 75 uint8_t *out_key) 76 { 77 TEE_Result res; 78 void *ctx = NULL; 79 uint8_t tsk[TEE_FS_KM_TSK_SIZE]; 80 uint8_t dst_key[size]; 81 82 if (!in_key || !out_key) 83 return TEE_ERROR_BAD_PARAMETERS; 84 85 if (size != TEE_FS_KM_FEK_SIZE) 86 return TEE_ERROR_BAD_PARAMETERS; 87 88 if (tee_fs_ssk.is_init == 0) 89 return TEE_ERROR_GENERIC; 90 91 if (uuid) { 92 res = do_hmac(tsk, sizeof(tsk), tee_fs_ssk.key, 93 TEE_FS_KM_SSK_SIZE, uuid, sizeof(*uuid)); 94 if (res != TEE_SUCCESS) 95 return res; 96 } else { 97 /* 98 * Pick something of a different size than TEE_UUID to 99 * guarantee that there's never a conflict. 100 */ 101 uint8_t dummy[1] = { 0 }; 102 103 res = do_hmac(tsk, sizeof(tsk), tee_fs_ssk.key, 104 TEE_FS_KM_SSK_SIZE, dummy, sizeof(dummy)); 105 if (res != TEE_SUCCESS) 106 return res; 107 } 108 109 res = crypto_cipher_alloc_ctx(&ctx, TEE_FS_KM_ENC_FEK_ALG); 110 if (res != TEE_SUCCESS) 111 return res; 112 113 res = crypto_cipher_init(ctx, TEE_FS_KM_ENC_FEK_ALG, mode, tsk, 114 sizeof(tsk), NULL, 0, NULL, 0); 115 if (res != TEE_SUCCESS) 116 goto exit; 117 118 res = crypto_cipher_update(ctx, TEE_FS_KM_ENC_FEK_ALG, 119 mode, true, in_key, size, dst_key); 120 if (res != TEE_SUCCESS) 121 goto exit; 122 123 crypto_cipher_final(ctx, TEE_FS_KM_ENC_FEK_ALG); 124 125 memcpy(out_key, dst_key, sizeof(dst_key)); 126 127 exit: 128 crypto_cipher_free_ctx(ctx, TEE_FS_KM_ENC_FEK_ALG); 129 130 return res; 131 } 132 133 static TEE_Result generate_fek(uint8_t *key, uint8_t len) 134 { 135 return crypto_rng_read(key, len); 136 } 137 138 static TEE_Result tee_fs_init_key_manager(void) 139 { 140 TEE_Result res = TEE_SUCCESS; 141 142 COMPILE_TIME_ASSERT(TEE_FS_KM_SSK_SIZE <= HUK_SUBKEY_MAX_LEN); 143 144 res = huk_subkey_derive(HUK_SUBKEY_SSK, NULL, 0, 145 tee_fs_ssk.key, sizeof(tee_fs_ssk.key)); 146 if (res == TEE_SUCCESS) 147 tee_fs_ssk.is_init = 1; 148 149 return res; 150 } 151 152 TEE_Result tee_fs_generate_fek(const TEE_UUID *uuid, void *buf, size_t buf_size) 153 { 154 TEE_Result res; 155 156 if (buf_size != TEE_FS_KM_FEK_SIZE) 157 return TEE_ERROR_BAD_PARAMETERS; 158 159 res = generate_fek(buf, TEE_FS_KM_FEK_SIZE); 160 if (res != TEE_SUCCESS) 161 return res; 162 163 return tee_fs_fek_crypt(uuid, TEE_MODE_ENCRYPT, buf, 164 TEE_FS_KM_FEK_SIZE, buf); 165 } 166 167 static TEE_Result sha256(uint8_t *out, size_t out_size, const uint8_t *in, 168 size_t in_size) 169 { 170 return tee_hash_createdigest(TEE_ALG_SHA256, in, in_size, 171 out, out_size); 172 } 173 174 static TEE_Result aes_ecb(uint8_t out[TEE_AES_BLOCK_SIZE], 175 const uint8_t in[TEE_AES_BLOCK_SIZE], 176 const uint8_t *key, size_t key_size) 177 { 178 TEE_Result res; 179 void *ctx = NULL; 180 const uint32_t algo = TEE_ALG_AES_ECB_NOPAD; 181 182 res = crypto_cipher_alloc_ctx(&ctx, algo); 183 if (res != TEE_SUCCESS) 184 return res; 185 186 res = crypto_cipher_init(ctx, algo, TEE_MODE_ENCRYPT, key, 187 key_size, NULL, 0, NULL, 0); 188 if (res != TEE_SUCCESS) 189 goto out; 190 191 res = crypto_cipher_update(ctx, algo, TEE_MODE_ENCRYPT, true, in, 192 TEE_AES_BLOCK_SIZE, out); 193 if (res != TEE_SUCCESS) 194 goto out; 195 196 crypto_cipher_final(ctx, algo); 197 res = TEE_SUCCESS; 198 199 out: 200 crypto_cipher_free_ctx(ctx, algo); 201 return res; 202 } 203 204 static TEE_Result essiv(uint8_t iv[TEE_AES_BLOCK_SIZE], 205 const uint8_t fek[TEE_FS_KM_FEK_SIZE], 206 uint16_t blk_idx) 207 { 208 TEE_Result res; 209 uint8_t sha[TEE_SHA256_HASH_SIZE]; 210 uint8_t pad_blkid[TEE_AES_BLOCK_SIZE] = { 0, }; 211 212 res = sha256(sha, sizeof(sha), fek, TEE_FS_KM_FEK_SIZE); 213 if (res != TEE_SUCCESS) 214 return res; 215 216 pad_blkid[0] = (blk_idx & 0xFF); 217 pad_blkid[1] = (blk_idx & 0xFF00) >> 8; 218 219 return aes_ecb(iv, pad_blkid, sha, 16); 220 } 221 222 /* 223 * Encryption/decryption of RPMB FS file data. This is AES CBC with ESSIV. 224 */ 225 TEE_Result tee_fs_crypt_block(const TEE_UUID *uuid, uint8_t *out, 226 const uint8_t *in, size_t size, 227 uint16_t blk_idx, const uint8_t *encrypted_fek, 228 TEE_OperationMode mode) 229 { 230 TEE_Result res; 231 uint8_t fek[TEE_FS_KM_FEK_SIZE]; 232 uint8_t iv[TEE_AES_BLOCK_SIZE]; 233 void *ctx; 234 const uint32_t algo = TEE_ALG_AES_CBC_NOPAD; 235 236 DMSG("%scrypt block #%u", (mode == TEE_MODE_ENCRYPT) ? "En" : "De", 237 blk_idx); 238 239 /* Decrypt FEK */ 240 res = tee_fs_fek_crypt(uuid, TEE_MODE_DECRYPT, encrypted_fek, 241 TEE_FS_KM_FEK_SIZE, fek); 242 if (res != TEE_SUCCESS) 243 return res; 244 245 /* Compute initialization vector for this block */ 246 res = essiv(iv, fek, blk_idx); 247 if (res != TEE_SUCCESS) 248 return res; 249 250 /* Run AES CBC */ 251 res = crypto_cipher_alloc_ctx(&ctx, algo); 252 if (res != TEE_SUCCESS) 253 return res; 254 255 res = crypto_cipher_init(ctx, algo, mode, fek, sizeof(fek), NULL, 256 0, iv, TEE_AES_BLOCK_SIZE); 257 if (res != TEE_SUCCESS) 258 goto exit; 259 res = crypto_cipher_update(ctx, algo, mode, true, in, size, out); 260 if (res != TEE_SUCCESS) 261 goto exit; 262 263 crypto_cipher_final(ctx, algo); 264 265 exit: 266 crypto_cipher_free_ctx(ctx, algo); 267 return res; 268 } 269 270 service_init_late(tee_fs_init_key_manager); 271