1 /* 2 * Copyright (c) 2014, STMicroelectronics International N.V. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 #include <tee_api.h> 28 29 #include <stdlib.h> 30 #include <string.h> 31 #include <stdio.h> 32 #include <tee_api_defines.h> 33 #include <tee_api_types.h> 34 #include <user_ta_header.h> 35 #include <tee_internal_api_extensions.h> 36 37 #include <utee_syscalls.h> 38 39 #include "string_ext.h" 40 #include "base64.h" 41 42 #define PROP_STR_MAX 80 43 44 #define PROP_ENUMERATOR_NOT_STARTED 0xffffffff 45 46 struct prop_enumerator { 47 uint32_t idx; 48 TEE_PropSetHandle prop_set; 49 }; 50 51 struct prop_value { 52 enum user_ta_prop_type type; 53 union { 54 bool bool_val; 55 uint32_t int_val; 56 TEE_UUID uuid_val; 57 TEE_Identity identity_val; 58 char str_val[PROP_STR_MAX]; 59 } u; 60 }; 61 62 typedef TEE_Result(*ta_propget_func_t) (struct prop_value *pv); 63 64 struct prop_set { 65 const char *str; 66 ta_propget_func_t get; 67 }; 68 69 static TEE_Result propget_gpd_ta_app_id(struct prop_value *pv) 70 { 71 pv->type = USER_TA_PROP_TYPE_UUID; 72 return utee_get_property(UTEE_PROP_TA_APP_ID, &pv->u.uuid_val, 73 sizeof(pv->u.uuid_val)); 74 } 75 76 static TEE_Result propget_gpd_client_identity(struct prop_value *pv) 77 { 78 pv->type = USER_TA_PROP_TYPE_IDENTITY; 79 return utee_get_property(UTEE_PROP_CLIENT_ID, &pv->u.identity_val, 80 sizeof(pv->u.identity_val)); 81 } 82 83 static TEE_Result propget_gpd_tee_api_version(struct prop_value *pv) 84 { 85 pv->type = USER_TA_PROP_TYPE_STRING; 86 return utee_get_property(UTEE_PROP_TEE_API_VERSION, &pv->u.str_val, 87 sizeof(pv->u.str_val)); 88 } 89 90 static TEE_Result propget_gpd_tee_description(struct prop_value *pv) 91 { 92 pv->type = USER_TA_PROP_TYPE_STRING; 93 return utee_get_property(UTEE_PROP_TEE_DESCR, &pv->u.str_val, 94 sizeof(pv->u.str_val)); 95 } 96 97 static TEE_Result propget_gpd_tee_device_id(struct prop_value *pv) 98 { 99 pv->type = USER_TA_PROP_TYPE_UUID; 100 return utee_get_property(UTEE_PROP_TEE_DEV_ID, &pv->u.uuid_val, 101 sizeof(pv->u.uuid_val)); 102 } 103 104 static TEE_Result propget_gpd_tee_sys_time_protection_level(struct prop_value 105 *pv) 106 { 107 pv->type = USER_TA_PROP_TYPE_U32; 108 return utee_get_property(UTEE_PROP_TEE_SYS_TIME_PROT_LEVEL, 109 &pv->u.int_val, sizeof(pv->u.int_val)); 110 } 111 112 static TEE_Result propget_gpd_tee_ta_time_protection_level(struct prop_value 113 *pv) 114 { 115 pv->type = USER_TA_PROP_TYPE_U32; 116 return utee_get_property(UTEE_PROP_TEE_TA_TIME_PROT_LEVEL, 117 &pv->u.int_val, sizeof(pv->u.int_val)); 118 } 119 120 static TEE_Result propget_gpd_tee_arith_max_big_int_size(struct prop_value *pv) 121 { 122 pv->type = USER_TA_PROP_TYPE_U32; 123 return utee_get_property(UTEE_PROP_TEE_ARITH_MAX_BIG_INT_SIZE, 124 &pv->u.int_val, sizeof(pv->u.int_val)); 125 } 126 127 static const struct prop_set propset_current_ta[] = { 128 {"gpd.ta.appID", propget_gpd_ta_app_id}, 129 }; 130 131 static const size_t propset_current_ta_len = 132 sizeof(propset_current_ta) / sizeof(propset_current_ta[0]); 133 134 static const struct prop_set propset_current_client[] = { 135 {"gpd.client.identity", propget_gpd_client_identity}, 136 }; 137 138 static const size_t propset_current_client_len = 139 sizeof(propset_current_client) / sizeof(propset_current_client[0]); 140 141 static const struct prop_set propset_implementation[] = { 142 {"gpd.tee.apiversion", propget_gpd_tee_api_version}, 143 {"gpd.tee.description", propget_gpd_tee_description}, 144 {"gpd.tee.deviceID", propget_gpd_tee_device_id}, 145 {"gpd.tee.systemTime.protectionLevel", 146 propget_gpd_tee_sys_time_protection_level}, 147 {"gpd.tee.TAPersistentTime.protectionLevel", 148 propget_gpd_tee_ta_time_protection_level}, 149 {"gpd.tee.arith.maxBigIntSize", propget_gpd_tee_arith_max_big_int_size}, 150 }; 151 152 static const size_t propset_implementation_len = 153 sizeof(propset_implementation) / sizeof(propset_implementation[0]); 154 155 static TEE_Result propset_get(TEE_PropSetHandle h, const struct prop_set **ps, 156 size_t *ps_len, 157 const struct user_ta_property **eps, 158 size_t *eps_len) 159 { 160 if (h == TEE_PROPSET_CURRENT_TA) { 161 *ps = propset_current_ta; 162 *ps_len = propset_current_ta_len; 163 *eps = ta_props; 164 *eps_len = ta_num_props; 165 } else if (h == TEE_PROPSET_CURRENT_CLIENT) { 166 *ps = propset_current_client; 167 *ps_len = propset_current_client_len; 168 *eps = NULL; 169 *eps_len = 0; 170 } else if (h == TEE_PROPSET_TEE_IMPLEMENTATION) { 171 *ps = propset_implementation; 172 *ps_len = propset_implementation_len; 173 *eps = NULL; 174 *eps_len = 0; 175 } else { 176 return TEE_ERROR_ITEM_NOT_FOUND; 177 } 178 179 return TEE_SUCCESS; 180 } 181 182 static TEE_Result propget_get_ext_prop(const struct user_ta_property *ep, 183 struct prop_value *pv) 184 { 185 size_t l; 186 187 pv->type = ep->type; 188 switch (ep->type) { 189 case USER_TA_PROP_TYPE_BOOL: 190 l = sizeof(bool); 191 break; 192 case USER_TA_PROP_TYPE_U32: 193 l = sizeof(uint32_t); 194 break; 195 case USER_TA_PROP_TYPE_UUID: 196 l = sizeof(TEE_UUID); 197 break; 198 case USER_TA_PROP_TYPE_IDENTITY: 199 l = sizeof(TEE_Identity); 200 break; 201 case USER_TA_PROP_TYPE_STRING: 202 case USER_TA_PROP_TYPE_BINARY_BLOCK: 203 /* Handle too large strings by truncating them */ 204 strlcpy(pv->u.str_val, ep->value, sizeof(pv->u.str_val)); 205 return TEE_SUCCESS; 206 default: 207 return TEE_ERROR_GENERIC; 208 } 209 memcpy(&pv->u, ep->value, l); 210 return TEE_SUCCESS; 211 } 212 213 static TEE_Result propget_get_property(TEE_PropSetHandle h, char *name, 214 struct prop_value *pv) 215 { 216 TEE_Result res; 217 const struct prop_set *ps; 218 size_t ps_len; 219 const struct user_ta_property *eps; 220 size_t eps_len; 221 222 if (h == TEE_PROPSET_CURRENT_TA || h == TEE_PROPSET_CURRENT_CLIENT || 223 h == TEE_PROPSET_TEE_IMPLEMENTATION) { 224 size_t n; 225 226 res = propset_get(h, &ps, &ps_len, &eps, &eps_len); 227 if (res != TEE_SUCCESS) 228 return res; 229 230 for (n = 0; n < ps_len; n++) { 231 if (strcmp(name, ps[n].str) == 0) 232 return ps[n].get(pv); 233 } 234 for (n = 0; n < eps_len; n++) { 235 if (strcmp(name, eps[n].name) == 0) 236 return propget_get_ext_prop(eps + n, pv); 237 } 238 return TEE_ERROR_ITEM_NOT_FOUND; 239 } else { 240 struct prop_enumerator *pe = (struct prop_enumerator *)h; 241 uint32_t idx = pe->idx; 242 243 if (idx == PROP_ENUMERATOR_NOT_STARTED) 244 return TEE_ERROR_ITEM_NOT_FOUND; 245 246 res = propset_get(pe->prop_set, &ps, &ps_len, &eps, &eps_len); 247 if (res != TEE_SUCCESS) 248 return res; 249 250 if (idx < ps_len) 251 return ps[idx].get(pv); 252 253 idx -= ps_len; 254 if (idx < eps_len) 255 return propget_get_ext_prop(eps + idx, pv); 256 257 return TEE_ERROR_BAD_PARAMETERS; 258 } 259 } 260 261 TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator, 262 char *name, char *valueBuffer, 263 size_t *valueBufferLen) 264 { 265 TEE_Result res; 266 struct prop_value pv; 267 size_t l; 268 size_t bufferlen; 269 270 if (valueBuffer == NULL || valueBufferLen == NULL) 271 return TEE_ERROR_BAD_PARAMETERS; 272 273 bufferlen = *valueBufferLen; 274 275 res = propget_get_property(propsetOrEnumerator, name, &pv); 276 if (res != TEE_SUCCESS) 277 return res; 278 279 switch (pv.type) { 280 case USER_TA_PROP_TYPE_BOOL: 281 l = strlcpy(valueBuffer, pv.u.bool_val ? "true" : "false", 282 bufferlen); 283 break; 284 285 case USER_TA_PROP_TYPE_U32: 286 l = snprintf(valueBuffer, bufferlen, "%u", 287 (unsigned int)pv.u.int_val); 288 break; 289 290 case USER_TA_PROP_TYPE_UUID: 291 l = snprintf(valueBuffer, bufferlen, 292 "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", 293 (unsigned int)pv.u.uuid_val.timeLow, 294 pv.u.uuid_val.timeMid, 295 pv.u.uuid_val.timeHiAndVersion, 296 pv.u.uuid_val.clockSeqAndNode[0], 297 pv.u.uuid_val.clockSeqAndNode[1], 298 pv.u.uuid_val.clockSeqAndNode[2], 299 pv.u.uuid_val.clockSeqAndNode[3], 300 pv.u.uuid_val.clockSeqAndNode[4], 301 pv.u.uuid_val.clockSeqAndNode[5], 302 pv.u.uuid_val.clockSeqAndNode[6], 303 pv.u.uuid_val.clockSeqAndNode[7]); 304 break; 305 306 case USER_TA_PROP_TYPE_IDENTITY: 307 l = snprintf(valueBuffer, bufferlen, 308 "%u:%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", 309 (unsigned int)pv.u.identity_val.login, 310 (unsigned int)pv.u.identity_val.uuid.timeLow, 311 pv.u.identity_val.uuid.timeMid, 312 pv.u.identity_val.uuid.timeHiAndVersion, 313 pv.u.identity_val.uuid.clockSeqAndNode[0], 314 pv.u.identity_val.uuid.clockSeqAndNode[1], 315 pv.u.identity_val.uuid.clockSeqAndNode[2], 316 pv.u.identity_val.uuid.clockSeqAndNode[3], 317 pv.u.identity_val.uuid.clockSeqAndNode[4], 318 pv.u.identity_val.uuid.clockSeqAndNode[5], 319 pv.u.identity_val.uuid.clockSeqAndNode[6], 320 pv.u.identity_val.uuid.clockSeqAndNode[7]); 321 break; 322 323 case USER_TA_PROP_TYPE_STRING: 324 case USER_TA_PROP_TYPE_BINARY_BLOCK: 325 l = strlcpy(valueBuffer, pv.u.str_val, bufferlen); 326 break; 327 328 default: 329 return TEE_ERROR_BAD_FORMAT; 330 } 331 332 /* The size "must account for the zero terminator" */ 333 *valueBufferLen = l + 1; 334 335 if (l >= bufferlen) 336 return TEE_ERROR_SHORT_BUFFER; 337 338 return TEE_SUCCESS; 339 } 340 341 TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator, 342 char *name, bool *value) 343 { 344 TEE_Result res; 345 struct prop_value pv; 346 347 if (value == NULL) 348 return TEE_ERROR_BAD_PARAMETERS; 349 350 res = propget_get_property(propsetOrEnumerator, name, &pv); 351 if (res != TEE_SUCCESS) 352 return res; 353 354 if (pv.type != USER_TA_PROP_TYPE_BOOL) 355 return TEE_ERROR_BAD_FORMAT; 356 357 *value = pv.u.bool_val; 358 return TEE_SUCCESS; 359 } 360 361 TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator, 362 char *name, uint32_t *value) 363 { 364 TEE_Result res; 365 struct prop_value pv; 366 367 if (value == NULL) 368 return TEE_ERROR_BAD_PARAMETERS; 369 370 res = propget_get_property(propsetOrEnumerator, name, &pv); 371 if (res != TEE_SUCCESS) 372 return res; 373 374 if (pv.type != USER_TA_PROP_TYPE_U32) 375 return TEE_ERROR_BAD_FORMAT; 376 377 *value = pv.u.int_val; 378 return TEE_SUCCESS; 379 } 380 381 TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator, 382 char *name, void *valueBuffer, 383 size_t *valueBufferLen) 384 { 385 TEE_Result res; 386 struct prop_value pv; 387 void *val; 388 int val_len; 389 390 if (valueBuffer == NULL || valueBufferLen == NULL) 391 return TEE_ERROR_BAD_PARAMETERS; 392 393 res = propget_get_property(propsetOrEnumerator, name, &pv); 394 if (res != TEE_SUCCESS) 395 return res; 396 397 if (pv.type != USER_TA_PROP_TYPE_BINARY_BLOCK) 398 return TEE_ERROR_BAD_FORMAT; 399 400 val = pv.u.str_val; 401 val_len = strlen(val); 402 if (!base64_dec(val, val_len, valueBuffer, valueBufferLen)) 403 return TEE_ERROR_SHORT_BUFFER; 404 return TEE_SUCCESS; 405 } 406 407 TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator, 408 char *name, TEE_UUID *value) 409 { 410 TEE_Result res; 411 struct prop_value pv; 412 413 if (value == NULL) 414 return TEE_ERROR_BAD_PARAMETERS; 415 416 res = propget_get_property(propsetOrEnumerator, name, &pv); 417 if (res != TEE_SUCCESS) 418 return res; 419 420 if (pv.type != USER_TA_PROP_TYPE_UUID) 421 return TEE_ERROR_BAD_FORMAT; 422 423 *value = pv.u.uuid_val; /* struct copy */ 424 return TEE_SUCCESS; 425 } 426 427 TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator, 428 char *name, TEE_Identity *value) 429 { 430 TEE_Result res; 431 struct prop_value pv; 432 433 if (value == NULL) 434 return TEE_ERROR_BAD_PARAMETERS; 435 436 res = propget_get_property(propsetOrEnumerator, name, &pv); 437 if (res != TEE_SUCCESS) 438 return res; 439 440 if (pv.type != USER_TA_PROP_TYPE_IDENTITY) 441 return TEE_ERROR_BAD_FORMAT; 442 443 *value = pv.u.identity_val; /* struct copy */ 444 return TEE_SUCCESS; 445 } 446 447 TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator) 448 { 449 struct prop_enumerator *pe; 450 451 if (enumerator == NULL) 452 return TEE_ERROR_BAD_PARAMETERS; 453 454 pe = TEE_Malloc(sizeof(struct prop_enumerator), 455 TEE_USER_MEM_HINT_NO_FILL_ZERO); 456 if (pe == NULL) 457 return TEE_ERROR_OUT_OF_MEMORY; 458 459 *enumerator = (TEE_PropSetHandle) pe; 460 TEE_ResetPropertyEnumerator(*enumerator); 461 return TEE_SUCCESS; 462 } 463 464 void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator) 465 { 466 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 467 468 pe->idx = PROP_ENUMERATOR_NOT_STARTED; 469 } 470 471 void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator) 472 { 473 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 474 475 TEE_Free(pe); 476 } 477 478 void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator, 479 TEE_PropSetHandle propSet) 480 { 481 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 482 483 if (pe == NULL) 484 return; 485 486 pe->idx = 0; 487 pe->prop_set = propSet; 488 } 489 490 TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator, 491 void *nameBuffer, size_t *nameBufferLen) 492 { 493 TEE_Result res; 494 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 495 const struct prop_set *ps; 496 size_t ps_len; 497 const struct user_ta_property *eps; 498 size_t eps_len; 499 size_t l; 500 const char *str; 501 size_t bufferlen; 502 503 if (pe == NULL || nameBuffer == NULL || nameBufferLen == NULL) 504 return TEE_ERROR_BAD_PARAMETERS; 505 506 bufferlen = *nameBufferLen; 507 res = propset_get(pe->prop_set, &ps, &ps_len, &eps, &eps_len); 508 if (res != TEE_SUCCESS) 509 return res; 510 511 if (pe->idx < ps_len) 512 str = ps[pe->idx].str; 513 else if ((pe->idx - ps_len) < eps_len) 514 str = ta_props[pe->idx - ps_len].name; 515 else 516 return TEE_ERROR_ITEM_NOT_FOUND; 517 518 l = strlcpy(nameBuffer, str, bufferlen); 519 520 /* The size "must account for the zero terminator" */ 521 *nameBufferLen = l + 1; 522 523 if (l >= bufferlen) 524 return TEE_ERROR_SHORT_BUFFER; 525 526 return TEE_SUCCESS; 527 } 528 529 TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator) 530 { 531 TEE_Result res; 532 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 533 uint32_t next_idx; 534 const struct prop_set *ps; 535 size_t ps_len; 536 const struct user_ta_property *eps; 537 size_t eps_len; 538 539 if (pe == NULL) 540 return TEE_ERROR_BAD_PARAMETERS; 541 542 if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) 543 return TEE_ERROR_ITEM_NOT_FOUND; 544 545 res = propset_get(pe->prop_set, &ps, &ps_len, &eps, &eps_len); 546 if (res != TEE_SUCCESS) 547 return res; 548 549 next_idx = pe->idx + 1; 550 pe->idx = next_idx; 551 if (next_idx >= (ps_len + eps_len)) 552 return TEE_ERROR_ITEM_NOT_FOUND; 553 554 return TEE_SUCCESS; 555 } 556