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 <compiler.h> 19 #include <crypto/crypto.h> 20 #include <initcall.h> 21 #include <kernel/panic.h> 22 #include <kernel/tee_common_otp.h> 23 #include <kernel/tee_ta_manager.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <tee/tee_cryp_utl.h> 27 #include <tee/tee_fs_key_manager.h> 28 #include <trace.h> 29 #include <util.h> 30 31 struct tee_fs_ssk { 32 bool is_init; 33 uint8_t key[TEE_FS_KM_SSK_SIZE]; 34 }; 35 36 static struct tee_fs_ssk tee_fs_ssk; 37 static uint8_t string_for_ssk_gen[] = "ONLY_FOR_tee_fs_ssk"; 38 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 uint8_t *ctx = NULL; 79 size_t ctx_size; 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_get_ctx_size(TEE_FS_KM_ENC_FEK_ALG, &ctx_size); 111 if (res != TEE_SUCCESS) 112 return res; 113 114 ctx = malloc(ctx_size); 115 if (!ctx) 116 return TEE_ERROR_OUT_OF_MEMORY; 117 118 res = crypto_cipher_init(ctx, TEE_FS_KM_ENC_FEK_ALG, mode, tsk, 119 sizeof(tsk), NULL, 0, NULL, 0); 120 if (res != TEE_SUCCESS) 121 goto exit; 122 123 res = crypto_cipher_update(ctx, TEE_FS_KM_ENC_FEK_ALG, 124 mode, true, in_key, size, dst_key); 125 if (res != TEE_SUCCESS) 126 goto exit; 127 128 crypto_cipher_final(ctx, TEE_FS_KM_ENC_FEK_ALG); 129 130 memcpy(out_key, dst_key, sizeof(dst_key)); 131 132 exit: 133 free(ctx); 134 135 return res; 136 } 137 138 static TEE_Result generate_fek(uint8_t *key, uint8_t len) 139 { 140 return crypto_rng_read(key, len); 141 } 142 143 static TEE_Result tee_fs_init_key_manager(void) 144 { 145 int res = TEE_SUCCESS; 146 struct tee_hw_unique_key huk; 147 uint8_t chip_id[TEE_FS_KM_CHIP_ID_LENGTH]; 148 uint8_t message[sizeof(chip_id) + sizeof(string_for_ssk_gen)]; 149 150 /* Secure Storage Key Generation: 151 * 152 * SSK = HMAC(HUK, message) 153 * message := concatenate(chip_id, static string) 154 * */ 155 tee_otp_get_hw_unique_key(&huk); 156 tee_otp_get_die_id(chip_id, sizeof(chip_id)); 157 158 memcpy(message, chip_id, sizeof(chip_id)); 159 memcpy(message + sizeof(chip_id), string_for_ssk_gen, 160 sizeof(string_for_ssk_gen)); 161 162 res = do_hmac(tee_fs_ssk.key, sizeof(tee_fs_ssk.key), 163 huk.data, sizeof(huk.data), 164 message, sizeof(message)); 165 166 if (res == TEE_SUCCESS) 167 tee_fs_ssk.is_init = 1; 168 169 return res; 170 } 171 172 TEE_Result tee_fs_generate_fek(const TEE_UUID *uuid, void *buf, size_t buf_size) 173 { 174 TEE_Result res; 175 176 if (buf_size != TEE_FS_KM_FEK_SIZE) 177 return TEE_ERROR_BAD_PARAMETERS; 178 179 res = generate_fek(buf, TEE_FS_KM_FEK_SIZE); 180 if (res != TEE_SUCCESS) 181 return res; 182 183 return tee_fs_fek_crypt(uuid, TEE_MODE_ENCRYPT, buf, 184 TEE_FS_KM_FEK_SIZE, buf); 185 } 186 187 static TEE_Result sha256(uint8_t *out, size_t out_size, const uint8_t *in, 188 size_t in_size) 189 { 190 return tee_hash_createdigest(TEE_ALG_SHA256, in, in_size, 191 out, out_size); 192 } 193 194 static TEE_Result aes_ecb(uint8_t out[TEE_AES_BLOCK_SIZE], 195 const uint8_t in[TEE_AES_BLOCK_SIZE], 196 const uint8_t *key, size_t key_size) 197 { 198 TEE_Result res; 199 uint8_t *ctx = NULL; 200 size_t ctx_size; 201 uint32_t algo = TEE_ALG_AES_ECB_NOPAD; 202 203 res = crypto_cipher_get_ctx_size(algo, &ctx_size); 204 if (res != TEE_SUCCESS) 205 return res; 206 207 ctx = malloc(ctx_size); 208 if (!ctx) 209 return TEE_ERROR_OUT_OF_MEMORY; 210 211 res = crypto_cipher_init(ctx, algo, TEE_MODE_ENCRYPT, key, 212 key_size, NULL, 0, NULL, 0); 213 if (res != TEE_SUCCESS) 214 goto out; 215 216 res = crypto_cipher_update(ctx, algo, TEE_MODE_ENCRYPT, true, in, 217 TEE_AES_BLOCK_SIZE, out); 218 if (res != TEE_SUCCESS) 219 goto out; 220 221 crypto_cipher_final(ctx, algo); 222 res = TEE_SUCCESS; 223 224 out: 225 free(ctx); 226 return res; 227 } 228 229 static TEE_Result essiv(uint8_t iv[TEE_AES_BLOCK_SIZE], 230 const uint8_t fek[TEE_FS_KM_FEK_SIZE], 231 uint16_t blk_idx) 232 { 233 TEE_Result res; 234 uint8_t sha[TEE_SHA256_HASH_SIZE]; 235 uint8_t pad_blkid[TEE_AES_BLOCK_SIZE] = { 0, }; 236 237 res = sha256(sha, sizeof(sha), fek, TEE_FS_KM_FEK_SIZE); 238 if (res != TEE_SUCCESS) 239 return res; 240 241 pad_blkid[0] = (blk_idx & 0xFF); 242 pad_blkid[1] = (blk_idx & 0xFF00) >> 8; 243 244 return aes_ecb(iv, pad_blkid, sha, 16); 245 } 246 247 /* 248 * Encryption/decryption of RPMB FS file data. This is AES CBC with ESSIV. 249 */ 250 TEE_Result tee_fs_crypt_block(const TEE_UUID *uuid, uint8_t *out, 251 const uint8_t *in, size_t size, 252 uint16_t blk_idx, const uint8_t *encrypted_fek, 253 TEE_OperationMode mode) 254 { 255 TEE_Result res; 256 uint8_t fek[TEE_FS_KM_FEK_SIZE]; 257 uint8_t iv[TEE_AES_BLOCK_SIZE]; 258 uint8_t *ctx; 259 size_t ctx_size; 260 uint32_t algo = TEE_ALG_AES_CBC_NOPAD; 261 262 DMSG("%scrypt block #%u", (mode == TEE_MODE_ENCRYPT) ? "En" : "De", 263 blk_idx); 264 265 /* Decrypt FEK */ 266 res = tee_fs_fek_crypt(uuid, TEE_MODE_DECRYPT, encrypted_fek, 267 TEE_FS_KM_FEK_SIZE, fek); 268 if (res != TEE_SUCCESS) 269 return res; 270 271 /* Compute initialization vector for this block */ 272 res = essiv(iv, fek, blk_idx); 273 274 /* Run AES CBC */ 275 res = crypto_cipher_get_ctx_size(algo, &ctx_size); 276 if (res != TEE_SUCCESS) 277 return res; 278 ctx = malloc(ctx_size); 279 if (!ctx) 280 return TEE_ERROR_OUT_OF_MEMORY; 281 282 res = crypto_cipher_init(ctx, algo, mode, fek, sizeof(fek), NULL, 283 0, iv, TEE_AES_BLOCK_SIZE); 284 if (res != TEE_SUCCESS) 285 goto exit; 286 res = crypto_cipher_update(ctx, algo, mode, true, in, size, out); 287 if (res != TEE_SUCCESS) 288 goto exit; 289 290 crypto_cipher_final(ctx, algo); 291 292 exit: 293 free(ctx); 294 return res; 295 } 296 297 service_init_late(tee_fs_init_key_manager); 298