1 // SPDX-License-Identifier: BSD-2-Clause 2 /* Copyright (c) 2018, Linaro Limited */ 3 4 #include <ta_avb.h> 5 #include <tee_internal_api.h> 6 #include <tee_internal_api_extensions.h> 7 8 #include <string.h> 9 #include <util.h> 10 11 #define DEFAULT_LOCK_STATE 0 12 13 static const uint32_t storageid = TEE_STORAGE_PRIVATE_RPMB; 14 static const char rb_obj_name[] = "rb_state"; 15 static const char *named_value_prefix = "named_value_"; 16 17 static TEE_Result get_slot_offset(size_t slot, size_t *offset) 18 { 19 if (slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS) 20 return TEE_ERROR_BAD_PARAMETERS; 21 22 *offset = sizeof(uint32_t) /* lock_state */ + slot * sizeof(uint64_t); 23 return TEE_SUCCESS; 24 } 25 26 static TEE_Result create_rb_state(uint32_t lock_state, TEE_ObjectHandle *h) 27 { 28 const uint32_t flags = TEE_DATA_FLAG_ACCESS_READ | 29 TEE_DATA_FLAG_ACCESS_WRITE | 30 TEE_DATA_FLAG_OVERWRITE; 31 32 return TEE_CreatePersistentObject(storageid, rb_obj_name, 33 sizeof(rb_obj_name), flags, NULL, 34 &lock_state, sizeof(lock_state), h); 35 } 36 37 static TEE_Result open_rb_state(uint32_t default_lock_state, 38 TEE_ObjectHandle *h) 39 { 40 uint32_t flags = TEE_DATA_FLAG_ACCESS_READ | 41 TEE_DATA_FLAG_ACCESS_WRITE; 42 TEE_Result res; 43 44 res = TEE_OpenPersistentObject(storageid, rb_obj_name, 45 sizeof(rb_obj_name), flags, h); 46 if (!res) 47 return TEE_SUCCESS; 48 49 return create_rb_state(default_lock_state, h); 50 } 51 52 static TEE_Result get_named_object_name(char *name_orig, 53 uint32_t name_orig_size, 54 char *name, uint32_t *name_size) 55 { 56 size_t pref_len = strlen(named_value_prefix); 57 58 if (name_orig_size + pref_len > 59 TEE_OBJECT_ID_MAX_LEN) 60 return TEE_ERROR_BAD_PARAMETERS; 61 62 /* Start with prefix */ 63 TEE_MemMove(name, named_value_prefix, pref_len); 64 65 /* Concatenate provided object name */ 66 TEE_MemMove(name + pref_len, name_orig, name_orig_size); 67 68 *name_size = name_orig_size + pref_len; 69 70 return TEE_SUCCESS; 71 } 72 73 static TEE_Result read_rb_idx(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) 74 { 75 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 76 TEE_PARAM_TYPE_VALUE_OUTPUT, 77 TEE_PARAM_TYPE_NONE, 78 TEE_PARAM_TYPE_NONE); 79 size_t slot_offset; 80 uint64_t idx; 81 uint32_t count; 82 TEE_Result res; 83 TEE_ObjectHandle h; 84 85 if (pt != exp_pt) 86 return TEE_ERROR_BAD_PARAMETERS; 87 88 res = get_slot_offset(params[0].value.a, &slot_offset); 89 if (res) 90 return res; 91 92 res = open_rb_state(DEFAULT_LOCK_STATE, &h); 93 if (res) 94 return res; 95 96 res = TEE_SeekObjectData(h, slot_offset, TEE_DATA_SEEK_SET); 97 if (res) 98 goto out; 99 100 res = TEE_ReadObjectData(h, &idx, sizeof(idx), &count); 101 if (res) 102 goto out; 103 if (count != sizeof(idx)) { 104 idx = 0; /* Not yet written slots are reported as 0 */ 105 106 if (count) { 107 /* 108 * Somehow the file didn't even hold a complete 109 * slot index entry. Write it as 0. 110 */ 111 res = TEE_SeekObjectData(h, slot_offset, 112 TEE_DATA_SEEK_SET); 113 if (res) 114 goto out; 115 res = TEE_WriteObjectData(h, &idx, sizeof(idx)); 116 if (res) 117 goto out; 118 } 119 } 120 121 params[1].value.a = idx >> 32; 122 params[1].value.b = idx; 123 out: 124 TEE_CloseObject(h); 125 return res; 126 } 127 128 static TEE_Result write_rb_idx(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) 129 { 130 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 131 TEE_PARAM_TYPE_VALUE_INPUT, 132 TEE_PARAM_TYPE_NONE, 133 TEE_PARAM_TYPE_NONE); 134 size_t slot_offset; 135 uint64_t widx; 136 uint64_t idx; 137 uint32_t count; 138 TEE_Result res; 139 TEE_ObjectHandle h; 140 141 if (pt != exp_pt) 142 return TEE_ERROR_BAD_PARAMETERS; 143 144 res = get_slot_offset(params[0].value.a, &slot_offset); 145 if (res) 146 return res; 147 widx = ((uint64_t)params[1].value.a << 32) | params[1].value.b; 148 149 res = open_rb_state(DEFAULT_LOCK_STATE, &h); 150 if (res) 151 return res; 152 153 res = TEE_SeekObjectData(h, slot_offset, TEE_DATA_SEEK_SET); 154 if (res) 155 goto out; 156 157 res = TEE_ReadObjectData(h, &idx, sizeof(idx), &count); 158 if (res) 159 goto out; 160 if (count != sizeof(idx)) 161 idx = 0; /* Not yet written slots are reported as 0 */ 162 163 if (widx < idx) { 164 res = TEE_ERROR_SECURITY; 165 goto out; 166 } 167 168 res = TEE_SeekObjectData(h, slot_offset, TEE_DATA_SEEK_SET); 169 if (res) 170 goto out; 171 172 res = TEE_WriteObjectData(h, &widx, sizeof(widx)); 173 out: 174 TEE_CloseObject(h); 175 return res; 176 } 177 178 static TEE_Result read_lock_state(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) 179 { 180 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, 181 TEE_PARAM_TYPE_NONE, 182 TEE_PARAM_TYPE_NONE, 183 TEE_PARAM_TYPE_NONE); 184 uint32_t lock_state; 185 uint32_t count; 186 TEE_Result res; 187 TEE_ObjectHandle h; 188 189 if (pt != exp_pt) 190 return TEE_ERROR_BAD_PARAMETERS; 191 192 res = open_rb_state(DEFAULT_LOCK_STATE, &h); 193 if (res) 194 return res; 195 196 res = TEE_ReadObjectData(h, &lock_state, sizeof(lock_state), &count); 197 if (res) 198 goto out; 199 if (count != sizeof(lock_state)) { 200 /* 201 * Client need write the lock state to recover, this can 202 * normally not happen. 203 */ 204 res = TEE_ERROR_CORRUPT_OBJECT; 205 goto out; 206 } 207 208 params[0].value.a = lock_state; 209 out: 210 TEE_CloseObject(h); 211 return res; 212 } 213 214 static TEE_Result write_lock_state(uint32_t pt, 215 TEE_Param params[TEE_NUM_PARAMS]) 216 { 217 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 218 TEE_PARAM_TYPE_NONE, 219 TEE_PARAM_TYPE_NONE, 220 TEE_PARAM_TYPE_NONE); 221 uint32_t wlock_state; 222 uint32_t lock_state; 223 uint32_t count; 224 TEE_Result res; 225 TEE_ObjectHandle h; 226 227 if (pt != exp_pt) 228 return TEE_ERROR_BAD_PARAMETERS; 229 230 wlock_state = params[0].value.a; 231 232 res = open_rb_state(wlock_state, &h); 233 if (res) 234 return res; 235 236 res = TEE_ReadObjectData(h, &lock_state, sizeof(lock_state), &count); 237 if (res) 238 goto out; 239 if (count == sizeof(lock_state) && lock_state == wlock_state) 240 goto out; 241 242 res = create_rb_state(wlock_state, &h); 243 out: 244 TEE_CloseObject(h); 245 return res; 246 } 247 248 static TEE_Result write_persist_value(uint32_t pt, 249 TEE_Param params[TEE_NUM_PARAMS]) 250 { 251 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 252 TEE_PARAM_TYPE_MEMREF_INPUT, 253 TEE_PARAM_TYPE_NONE, 254 TEE_PARAM_TYPE_NONE); 255 const uint32_t flags = TEE_DATA_FLAG_ACCESS_READ | 256 TEE_DATA_FLAG_ACCESS_WRITE | 257 TEE_DATA_FLAG_OVERWRITE; 258 char name_full[TEE_OBJECT_ID_MAX_LEN] = { }; 259 TEE_ObjectHandle h = TEE_HANDLE_NULL; 260 TEE_Result res = TEE_SUCCESS; 261 uint32_t name_full_sz = 0; 262 uint32_t name_buf_sz = 0; 263 uint32_t value_sz = 0; 264 char *name_buf = NULL; 265 char *value = NULL; 266 267 if (pt != exp_pt) 268 return TEE_ERROR_BAD_PARAMETERS; 269 270 name_buf = params[0].memref.buffer; 271 name_buf_sz = params[0].memref.size; 272 value_sz = params[1].memref.size; 273 value = TEE_Malloc(value_sz, 0); 274 if (!value) 275 return TEE_ERROR_OUT_OF_MEMORY; 276 277 TEE_MemMove(value, params[1].memref.buffer, value_sz); 278 279 res = get_named_object_name(name_buf, name_buf_sz, 280 name_full, &name_full_sz); 281 if (res) 282 goto out; 283 284 res = TEE_CreatePersistentObject(storageid, name_full, 285 name_full_sz, 286 flags, NULL, value, 287 value_sz, &h); 288 if (res) 289 EMSG("Can't create named object value, res = 0x%x", res); 290 291 TEE_CloseObject(h); 292 out: 293 TEE_Free(value); 294 295 return res; 296 } 297 298 static TEE_Result read_persist_value(uint32_t pt, 299 TEE_Param params[TEE_NUM_PARAMS]) 300 { 301 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 302 TEE_PARAM_TYPE_MEMREF_INOUT, 303 TEE_PARAM_TYPE_NONE, 304 TEE_PARAM_TYPE_NONE); 305 uint32_t flags = TEE_DATA_FLAG_ACCESS_READ | 306 TEE_DATA_FLAG_ACCESS_WRITE; 307 TEE_Result res = TEE_SUCCESS; 308 TEE_ObjectHandle h = TEE_HANDLE_NULL; 309 char name_full[TEE_OBJECT_ID_MAX_LEN]; 310 uint32_t name_full_sz = 0; 311 uint32_t name_buf_sz = 0; 312 char *name_buf = NULL; 313 uint32_t value_sz = 0; 314 char *value = NULL; 315 uint32_t count = 0; 316 317 if (pt != exp_pt) 318 return TEE_ERROR_BAD_PARAMETERS; 319 320 name_buf = params[0].memref.buffer; 321 name_buf_sz = params[0].memref.size; 322 value_sz = params[1].memref.size; 323 value = TEE_Malloc(value_sz, 0); 324 if (!value) 325 return TEE_ERROR_OUT_OF_MEMORY; 326 327 res = get_named_object_name(name_buf, name_buf_sz, 328 name_full, &name_full_sz); 329 if (res) 330 goto out_free; 331 332 res = TEE_OpenPersistentObject(storageid, name_full, 333 name_full_sz, flags, &h); 334 if (res) { 335 EMSG("Can't open named object value, res = 0x%x", res); 336 goto out_free; 337 } 338 339 res = TEE_ReadObjectData(h, value, value_sz, &count); 340 if (res) { 341 EMSG("Can't read named object value, res = 0x%x", res); 342 goto out; 343 } 344 345 TEE_MemMove(params[1].memref.buffer, value, 346 value_sz); 347 348 params[1].memref.size = count; 349 out: 350 TEE_CloseObject(h); 351 out_free: 352 TEE_Free(value); 353 354 return res; 355 } 356 357 TEE_Result TA_CreateEntryPoint(void) 358 { 359 return TEE_SUCCESS; 360 } 361 362 void TA_DestroyEntryPoint(void) 363 { 364 } 365 366 TEE_Result TA_OpenSessionEntryPoint(uint32_t pt __unused, 367 TEE_Param params[4] __unused, 368 void **session __unused) 369 { 370 return TEE_SUCCESS; 371 } 372 373 void TA_CloseSessionEntryPoint(void *sess __unused) 374 { 375 } 376 377 TEE_Result TA_InvokeCommandEntryPoint(void *sess __unused, uint32_t cmd, 378 uint32_t pt, 379 TEE_Param params[TEE_NUM_PARAMS]) 380 { 381 switch (cmd) { 382 case TA_AVB_CMD_READ_ROLLBACK_INDEX: 383 return read_rb_idx(pt, params); 384 case TA_AVB_CMD_WRITE_ROLLBACK_INDEX: 385 return write_rb_idx(pt, params); 386 case TA_AVB_CMD_READ_LOCK_STATE: 387 return read_lock_state(pt, params); 388 case TA_AVB_CMD_WRITE_LOCK_STATE: 389 return write_lock_state(pt, params); 390 case TA_AVB_CMD_READ_PERSIST_VALUE: 391 return read_persist_value(pt, params); 392 case TA_AVB_CMD_WRITE_PERSIST_VALUE: 393 return write_persist_value(pt, params); 394 default: 395 EMSG("Command ID 0x%x is not supported", cmd); 396 return TEE_ERROR_NOT_SUPPORTED; 397 } 398 } 399