1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (C) 2019-2020, Linaro Limited 4 */ 5 6 #include <assert.h> 7 #include <pta_system.h> 8 #include <string.h> 9 #include <string_ext.h> 10 #include <tee_internal_api.h> 11 #include <tee_internal_api_extensions.h> 12 #include <trusted_keys.h> 13 #include <util.h> 14 15 #define IV_SIZE 16 16 #define TAG_SIZE 16 17 #define MAX_BUF_SIZE 512 18 19 /* 20 * Acronym: 21 * 22 * TK - Trusted Key 23 */ 24 25 struct tk_blob_hdr { 26 uint8_t reserved; 27 uint8_t iv[IV_SIZE]; 28 uint8_t tag[TAG_SIZE]; 29 uint8_t enc_key[]; 30 }; 31 32 static TEE_Result get_random(uint32_t types, TEE_Param params[TEE_NUM_PARAMS]) 33 { 34 uint8_t *rng_buf = NULL; 35 36 DMSG("Invoked TA_CMD_GET_RANDOM"); 37 38 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, 39 TEE_PARAM_TYPE_NONE, 40 TEE_PARAM_TYPE_NONE, 41 TEE_PARAM_TYPE_NONE)) 42 return TEE_ERROR_BAD_PARAMETERS; 43 44 if (!params[0].memref.buffer || !params[0].memref.size) 45 return TEE_ERROR_BAD_PARAMETERS; 46 47 rng_buf = TEE_Malloc(params[0].memref.size, TEE_MALLOC_FILL_ZERO); 48 if (!rng_buf) 49 return TEE_ERROR_OUT_OF_MEMORY; 50 51 TEE_GenerateRandom(rng_buf, params[0].memref.size); 52 memcpy(params[0].memref.buffer, rng_buf, params[0].memref.size); 53 memzero_explicit(rng_buf, params[0].memref.size); 54 55 TEE_Free(rng_buf); 56 57 return TEE_SUCCESS; 58 } 59 60 static TEE_Result derive_unique_key(uint8_t *key, uint16_t key_size, 61 uint8_t *extra, uint16_t extra_size) 62 { 63 TEE_TASessionHandle sess = TEE_HANDLE_NULL; 64 TEE_Param params[TEE_NUM_PARAMS] = { }; 65 TEE_Result res = TEE_ERROR_GENERIC; 66 uint32_t ret_orig = 0; 67 uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 68 TEE_PARAM_TYPE_MEMREF_OUTPUT, 69 TEE_PARAM_TYPE_NONE, 70 TEE_PARAM_TYPE_NONE); 71 72 res = TEE_OpenTASession(&(const TEE_UUID)PTA_SYSTEM_UUID, 73 TEE_TIMEOUT_INFINITE, 0, NULL, &sess, 74 &ret_orig); 75 if (res) 76 return res; 77 78 if (extra && extra_size) { 79 params[0].memref.buffer = extra; 80 params[0].memref.size = extra_size; 81 } 82 83 params[1].memref.buffer = key; 84 params[1].memref.size = key_size; 85 86 res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, 87 PTA_SYSTEM_DERIVE_TA_UNIQUE_KEY, 88 param_types, params, &ret_orig); 89 90 TEE_CloseTASession(sess); 91 92 return res; 93 } 94 95 static TEE_Result huk_ae_encrypt(TEE_OperationHandle crypto_op, uint8_t *in, 96 size_t in_sz, uint8_t *out, size_t *out_sz) 97 { 98 TEE_Result res = TEE_ERROR_GENERIC; 99 struct tk_blob_hdr *hdr = (struct tk_blob_hdr *)out; 100 uint8_t iv[IV_SIZE] = { 0 }; 101 size_t enc_key_len = in_sz; 102 size_t tag_len = TAG_SIZE; 103 104 hdr->reserved = 0; 105 TEE_GenerateRandom(iv, IV_SIZE); 106 memcpy(hdr->iv, iv, IV_SIZE); 107 108 res = TEE_AEInit(crypto_op, hdr->iv, IV_SIZE, TAG_SIZE * 8, 0, 0); 109 if (res) 110 return res; 111 112 res = TEE_AEEncryptFinal(crypto_op, in, in_sz, hdr->enc_key, 113 &enc_key_len, hdr->tag, &tag_len); 114 if (res || tag_len != TAG_SIZE) 115 return TEE_ERROR_SECURITY; 116 117 if (ADD_OVERFLOW(enc_key_len, sizeof(*hdr), out_sz)) 118 return TEE_ERROR_SECURITY; 119 120 return res; 121 } 122 123 static TEE_Result huk_ae_decrypt(TEE_OperationHandle crypto_op, uint8_t *in, 124 size_t in_sz, uint8_t *out, size_t *out_sz) 125 { 126 TEE_Result res = TEE_ERROR_GENERIC; 127 struct tk_blob_hdr *hdr = (struct tk_blob_hdr *)in; 128 uint8_t tag[TAG_SIZE] = { 0 }; 129 size_t enc_key_len = 0; 130 131 if (SUB_OVERFLOW(in_sz, sizeof(*hdr), &enc_key_len)) 132 return TEE_ERROR_SECURITY; 133 134 res = TEE_AEInit(crypto_op, hdr->iv, IV_SIZE, TAG_SIZE * 8, 0, 0); 135 if (res) 136 return res; 137 138 memcpy(tag, hdr->tag, TAG_SIZE); 139 res = TEE_AEDecryptFinal(crypto_op, hdr->enc_key, enc_key_len, out, 140 out_sz, tag, TAG_SIZE); 141 if (res) 142 res = TEE_ERROR_SECURITY; 143 144 return res; 145 } 146 147 static TEE_Result huk_crypt(TEE_OperationMode mode, uint8_t *in, size_t in_sz, 148 uint8_t *out, size_t *out_sz) 149 { 150 TEE_Result res = TEE_ERROR_GENERIC; 151 TEE_OperationHandle crypto_op = TEE_HANDLE_NULL; 152 TEE_ObjectHandle hkey = TEE_HANDLE_NULL; 153 uint8_t huk_key[TA_DERIVED_KEY_MAX_SIZE] = { }; 154 TEE_Attribute attr = { }; 155 156 res = TEE_AllocateOperation(&crypto_op, TEE_ALG_AES_GCM, mode, 157 sizeof(huk_key) * 8); 158 if (res) 159 return res; 160 161 res = derive_unique_key(huk_key, sizeof(huk_key), NULL, 0); 162 if (res) { 163 EMSG("derive_unique_key failed: returned %#"PRIx32, res); 164 goto out_op; 165 } 166 167 res = TEE_AllocateTransientObject(TEE_TYPE_AES, sizeof(huk_key) * 8, 168 &hkey); 169 if (res) 170 goto out_op; 171 172 attr.attributeID = TEE_ATTR_SECRET_VALUE; 173 attr.content.ref.buffer = huk_key; 174 attr.content.ref.length = sizeof(huk_key); 175 176 res = TEE_PopulateTransientObject(hkey, &attr, 1); 177 if (res) 178 goto out_key; 179 180 res = TEE_SetOperationKey(crypto_op, hkey); 181 if (res) 182 goto out_key; 183 184 if (mode == TEE_MODE_ENCRYPT) { 185 res = huk_ae_encrypt(crypto_op, in, in_sz, out, out_sz); 186 if (res) 187 EMSG("huk_AE_encrypt failed: returned %#"PRIx32, res); 188 } else if (mode == TEE_MODE_DECRYPT) { 189 res = huk_ae_decrypt(crypto_op, in, in_sz, out, out_sz); 190 if (res) 191 EMSG("huk_AE_decrypt failed: returned %#"PRIx32, res); 192 } else { 193 TEE_Panic(0); 194 } 195 196 out_key: 197 TEE_FreeTransientObject(hkey); 198 out_op: 199 TEE_FreeOperation(crypto_op); 200 memzero_explicit(huk_key, sizeof(huk_key)); 201 return res; 202 } 203 204 static TEE_Result seal_trusted_key(uint32_t types, 205 TEE_Param params[TEE_NUM_PARAMS]) 206 { 207 TEE_Result res = TEE_SUCCESS; 208 uint8_t *in = NULL; 209 size_t in_sz = 0; 210 uint8_t *out = NULL; 211 size_t out_sz = 0; 212 213 DMSG("Invoked TA_CMD_SEAL"); 214 215 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 216 TEE_PARAM_TYPE_MEMREF_OUTPUT, 217 TEE_PARAM_TYPE_NONE, 218 TEE_PARAM_TYPE_NONE)) 219 return TEE_ERROR_BAD_PARAMETERS; 220 221 in = params[0].memref.buffer; 222 in_sz = params[0].memref.size; 223 out = params[1].memref.buffer; 224 out_sz = params[1].memref.size; 225 226 if (!in || !in_sz || in_sz > MAX_BUF_SIZE) 227 return TEE_ERROR_BAD_PARAMETERS; 228 if ((!out && out_sz) || 229 (out && !IS_ALIGNED_WITH_TYPE(out, struct tk_blob_hdr)) || 230 out_sz > MAX_BUF_SIZE) 231 return TEE_ERROR_BAD_PARAMETERS; 232 233 if ((in_sz + sizeof(struct tk_blob_hdr)) > out_sz) { 234 params[1].memref.size = in_sz + sizeof(struct tk_blob_hdr); 235 return TEE_ERROR_SHORT_BUFFER; 236 } 237 238 res = huk_crypt(TEE_MODE_ENCRYPT, in, in_sz, out, &out_sz); 239 if (res == TEE_SUCCESS) { 240 assert(out_sz == in_sz + sizeof(struct tk_blob_hdr)); 241 params[1].memref.size = out_sz; 242 } 243 244 return res; 245 } 246 247 static TEE_Result unseal_trusted_key(uint32_t types, 248 TEE_Param params[TEE_NUM_PARAMS]) 249 { 250 TEE_Result res = TEE_SUCCESS; 251 uint8_t *in = NULL; 252 size_t in_sz = 0; 253 uint8_t *out = NULL; 254 size_t out_sz = 0; 255 256 DMSG("Invoked TA_CMD_UNSEAL"); 257 258 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 259 TEE_PARAM_TYPE_MEMREF_OUTPUT, 260 TEE_PARAM_TYPE_NONE, 261 TEE_PARAM_TYPE_NONE)) 262 return TEE_ERROR_BAD_PARAMETERS; 263 264 in = params[0].memref.buffer; 265 in_sz = params[0].memref.size; 266 out = params[1].memref.buffer; 267 out_sz = params[1].memref.size; 268 269 if (!in || !IS_ALIGNED_WITH_TYPE(in, struct tk_blob_hdr) || 270 in_sz <= sizeof(struct tk_blob_hdr) || in_sz > MAX_BUF_SIZE) 271 return TEE_ERROR_BAD_PARAMETERS; 272 if ((!out && out_sz) || out_sz > MAX_BUF_SIZE) 273 return TEE_ERROR_BAD_PARAMETERS; 274 275 if (in_sz > (out_sz + sizeof(struct tk_blob_hdr))) { 276 params[1].memref.size = in_sz - sizeof(struct tk_blob_hdr); 277 return TEE_ERROR_SHORT_BUFFER; 278 } 279 280 res = huk_crypt(TEE_MODE_DECRYPT, in, in_sz, out, &out_sz); 281 if (res == TEE_SUCCESS) { 282 assert(out_sz == in_sz - sizeof(struct tk_blob_hdr)); 283 params[1].memref.size = out_sz; 284 } 285 286 return res; 287 } 288 289 TEE_Result TA_CreateEntryPoint(void) 290 { 291 return TEE_SUCCESS; 292 } 293 294 void TA_DestroyEntryPoint(void) 295 { 296 } 297 298 TEE_Result TA_OpenSessionEntryPoint(uint32_t pt __unused, 299 TEE_Param params[TEE_NUM_PARAMS] __unused, 300 void **session __unused) 301 { 302 TEE_Result res = TEE_ERROR_GENERIC; 303 TEE_PropSetHandle h = TEE_HANDLE_NULL; 304 TEE_Identity id = { }; 305 306 res = TEE_AllocatePropertyEnumerator(&h); 307 if (res) 308 goto out; 309 310 TEE_StartPropertyEnumerator(h, TEE_PROPSET_CURRENT_CLIENT); 311 312 res = TEE_GetPropertyAsIdentity(h, NULL, &id); 313 if (res) 314 goto out; 315 316 if (id.login != TEE_LOGIN_REE_KERNEL) 317 res = TEE_ERROR_ACCESS_DENIED; 318 319 out: 320 if (h) 321 TEE_FreePropertyEnumerator(h); 322 return res; 323 } 324 325 void TA_CloseSessionEntryPoint(void *sess __unused) 326 { 327 } 328 329 TEE_Result TA_InvokeCommandEntryPoint(void *sess __unused, uint32_t cmd, 330 uint32_t pt, 331 TEE_Param params[TEE_NUM_PARAMS]) 332 { 333 switch (cmd) { 334 case TA_CMD_GET_RANDOM: 335 return get_random(pt, params); 336 case TA_CMD_SEAL: 337 return seal_trusted_key(pt, params); 338 case TA_CMD_UNSEAL: 339 return unseal_trusted_key(pt, params); 340 default: 341 EMSG("Command ID %#"PRIx32" is not supported", cmd); 342 return TEE_ERROR_NOT_SUPPORTED; 343 } 344 } 345