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, in_key, in_key_size); 56 if (res != TEE_SUCCESS) 57 goto exit; 58 59 res = crypto_mac_update(ctx, message, message_size); 60 if (res != TEE_SUCCESS) 61 goto exit; 62 63 res = crypto_mac_final(ctx, 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); 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, mode, tsk, sizeof(tsk), NULL, 0, NULL, 0); 115 if (res != TEE_SUCCESS) 116 goto exit; 117 118 res = crypto_cipher_update(ctx, mode, true, in_key, size, dst_key); 119 if (res != TEE_SUCCESS) 120 goto exit; 121 122 crypto_cipher_final(ctx); 123 124 memcpy(out_key, dst_key, sizeof(dst_key)); 125 126 exit: 127 crypto_cipher_free_ctx(ctx); 128 memzero_explicit(tsk, sizeof(tsk)); 129 memzero_explicit(dst_key, sizeof(dst_key)); 130 131 return res; 132 } 133 134 static TEE_Result generate_fek(uint8_t *key, uint8_t len) 135 { 136 return crypto_rng_read(key, len); 137 } 138 139 static TEE_Result tee_fs_init_key_manager(void) 140 { 141 TEE_Result res = TEE_SUCCESS; 142 143 COMPILE_TIME_ASSERT(TEE_FS_KM_SSK_SIZE <= HUK_SUBKEY_MAX_LEN); 144 145 res = huk_subkey_derive(HUK_SUBKEY_SSK, NULL, 0, 146 tee_fs_ssk.key, sizeof(tee_fs_ssk.key)); 147 if (res == TEE_SUCCESS) 148 tee_fs_ssk.is_init = 1; 149 else 150 memzero_explicit(&tee_fs_ssk, sizeof(tee_fs_ssk)); 151 152 return res; 153 } 154 155 TEE_Result tee_fs_generate_fek(const TEE_UUID *uuid, void *buf, size_t buf_size) 156 { 157 TEE_Result res; 158 159 if (buf_size != TEE_FS_KM_FEK_SIZE) 160 return TEE_ERROR_BAD_PARAMETERS; 161 162 res = generate_fek(buf, TEE_FS_KM_FEK_SIZE); 163 if (res != TEE_SUCCESS) 164 return res; 165 166 return tee_fs_fek_crypt(uuid, TEE_MODE_ENCRYPT, buf, 167 TEE_FS_KM_FEK_SIZE, buf); 168 } 169 170 static TEE_Result sha256(uint8_t *out, size_t out_size, const uint8_t *in, 171 size_t in_size) 172 { 173 return tee_hash_createdigest(TEE_ALG_SHA256, in, in_size, 174 out, out_size); 175 } 176 177 static TEE_Result aes_ecb(uint8_t out[TEE_AES_BLOCK_SIZE], 178 const uint8_t in[TEE_AES_BLOCK_SIZE], 179 const uint8_t *key, size_t key_size) 180 { 181 TEE_Result res; 182 void *ctx = NULL; 183 184 res = crypto_cipher_alloc_ctx(&ctx, TEE_ALG_AES_ECB_NOPAD); 185 if (res != TEE_SUCCESS) 186 return res; 187 188 res = crypto_cipher_init(ctx, TEE_MODE_ENCRYPT, key, 189 key_size, NULL, 0, NULL, 0); 190 if (res != TEE_SUCCESS) 191 goto out; 192 193 res = crypto_cipher_update(ctx, TEE_MODE_ENCRYPT, true, in, 194 TEE_AES_BLOCK_SIZE, out); 195 if (res != TEE_SUCCESS) 196 goto out; 197 198 crypto_cipher_final(ctx); 199 res = TEE_SUCCESS; 200 201 out: 202 crypto_cipher_free_ctx(ctx); 203 return res; 204 } 205 206 static TEE_Result essiv(uint8_t iv[TEE_AES_BLOCK_SIZE], 207 const uint8_t fek[TEE_FS_KM_FEK_SIZE], 208 uint16_t blk_idx) 209 { 210 TEE_Result res; 211 uint8_t sha[TEE_SHA256_HASH_SIZE]; 212 uint8_t pad_blkid[TEE_AES_BLOCK_SIZE] = { 0, }; 213 214 res = sha256(sha, sizeof(sha), fek, TEE_FS_KM_FEK_SIZE); 215 if (res != TEE_SUCCESS) 216 return res; 217 218 pad_blkid[0] = (blk_idx & 0xFF); 219 pad_blkid[1] = (blk_idx & 0xFF00) >> 8; 220 221 res = aes_ecb(iv, pad_blkid, sha, 16); 222 223 memzero_explicit(sha, sizeof(sha)); 224 return res; 225 } 226 227 /* 228 * Encryption/decryption of RPMB FS file data. This is AES CBC with ESSIV. 229 */ 230 TEE_Result tee_fs_crypt_block(const TEE_UUID *uuid, uint8_t *out, 231 const uint8_t *in, size_t size, 232 uint16_t blk_idx, const uint8_t *encrypted_fek, 233 TEE_OperationMode mode) 234 { 235 TEE_Result res; 236 uint8_t fek[TEE_FS_KM_FEK_SIZE]; 237 uint8_t iv[TEE_AES_BLOCK_SIZE]; 238 void *ctx; 239 240 DMSG("%scrypt block #%u", (mode == TEE_MODE_ENCRYPT) ? "En" : "De", 241 blk_idx); 242 243 /* Decrypt FEK */ 244 res = tee_fs_fek_crypt(uuid, TEE_MODE_DECRYPT, encrypted_fek, 245 TEE_FS_KM_FEK_SIZE, fek); 246 if (res != TEE_SUCCESS) 247 goto wipe; 248 249 /* Compute initialization vector for this block */ 250 res = essiv(iv, fek, blk_idx); 251 if (res != TEE_SUCCESS) 252 goto wipe; 253 254 /* Run AES CBC */ 255 res = crypto_cipher_alloc_ctx(&ctx, TEE_ALG_AES_CBC_NOPAD); 256 if (res != TEE_SUCCESS) 257 goto wipe; 258 259 res = crypto_cipher_init(ctx, mode, fek, sizeof(fek), NULL, 260 0, iv, TEE_AES_BLOCK_SIZE); 261 if (res != TEE_SUCCESS) 262 goto exit; 263 res = crypto_cipher_update(ctx, mode, true, in, size, out); 264 if (res != TEE_SUCCESS) 265 goto exit; 266 267 crypto_cipher_final(ctx); 268 269 exit: 270 crypto_cipher_free_ctx(ctx); 271 wipe: 272 memzero_explicit(fek, sizeof(fek)); 273 memzero_explicit(iv, sizeof(iv)); 274 return res; 275 } 276 277 service_init_late(tee_fs_init_key_manager); 278