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