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