163f89caaSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause 263f89caaSJens Wiklander /* 363f89caaSJens Wiklander * Copyright (c) 2017-2020, Linaro Limited 463f89caaSJens Wiklander */ 563f89caaSJens Wiklander 663f89caaSJens Wiklander #include <assert.h> 763f89caaSJens Wiklander #include <compiler.h> 863f89caaSJens Wiklander #include <pkcs11_ta.h> 963f89caaSJens Wiklander #include <stddef.h> 1063f89caaSJens Wiklander #include <stdlib.h> 1163f89caaSJens Wiklander #include <string.h> 1263f89caaSJens Wiklander #include <string_ext.h> 1363f89caaSJens Wiklander #include <tee_internal_api.h> 1463f89caaSJens Wiklander #include <tee_internal_api_extensions.h> 1563f89caaSJens Wiklander #include <trace.h> 1663f89caaSJens Wiklander #include <util.h> 1763f89caaSJens Wiklander 1863f89caaSJens Wiklander #include "attributes.h" 1963f89caaSJens Wiklander #include "pkcs11_helpers.h" 2063f89caaSJens Wiklander #include "serializer.h" 2163f89caaSJens Wiklander 2263f89caaSJens Wiklander enum pkcs11_rc init_attributes_head(struct obj_attrs **head) 2363f89caaSJens Wiklander { 2463f89caaSJens Wiklander *head = TEE_Malloc(sizeof(**head), TEE_MALLOC_FILL_ZERO); 2563f89caaSJens Wiklander if (!*head) 2663f89caaSJens Wiklander return PKCS11_CKR_DEVICE_MEMORY; 2763f89caaSJens Wiklander 2863f89caaSJens Wiklander return PKCS11_CKR_OK; 2963f89caaSJens Wiklander } 3063f89caaSJens Wiklander 3163f89caaSJens Wiklander enum pkcs11_rc add_attribute(struct obj_attrs **head, uint32_t attribute, 3263f89caaSJens Wiklander void *data, size_t size) 3363f89caaSJens Wiklander { 3463f89caaSJens Wiklander size_t buf_len = sizeof(struct obj_attrs) + (*head)->attrs_size; 3563f89caaSJens Wiklander char **bstart = (void *)head; 3663f89caaSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 3763f89caaSJens Wiklander uint32_t data32 = 0; 3863f89caaSJens Wiklander 3963f89caaSJens Wiklander data32 = attribute; 4063f89caaSJens Wiklander rc = serialize(bstart, &buf_len, &data32, sizeof(uint32_t)); 4163f89caaSJens Wiklander if (rc) 4263f89caaSJens Wiklander return rc; 4363f89caaSJens Wiklander 4463f89caaSJens Wiklander data32 = size; 4563f89caaSJens Wiklander rc = serialize(bstart, &buf_len, &data32, sizeof(uint32_t)); 4663f89caaSJens Wiklander if (rc) 4763f89caaSJens Wiklander return rc; 4863f89caaSJens Wiklander 4963f89caaSJens Wiklander rc = serialize(bstart, &buf_len, data, size); 5063f89caaSJens Wiklander if (rc) 5163f89caaSJens Wiklander return rc; 5263f89caaSJens Wiklander 5363f89caaSJens Wiklander /* Alloced buffer is always well aligned */ 5463f89caaSJens Wiklander head = (void *)bstart; 5563f89caaSJens Wiklander (*head)->attrs_size += 2 * sizeof(uint32_t) + size; 5663f89caaSJens Wiklander (*head)->attrs_count++; 5763f89caaSJens Wiklander 5863f89caaSJens Wiklander return rc; 5963f89caaSJens Wiklander } 6063f89caaSJens Wiklander 6163f89caaSJens Wiklander void get_attribute_ptrs(struct obj_attrs *head, uint32_t attribute, 6263f89caaSJens Wiklander void **attr, uint32_t *attr_size, size_t *count) 6363f89caaSJens Wiklander { 6463f89caaSJens Wiklander char *cur = (char *)head + sizeof(struct obj_attrs); 6563f89caaSJens Wiklander char *end = cur + head->attrs_size; 6663f89caaSJens Wiklander size_t next_off = 0; 6763f89caaSJens Wiklander size_t max_found = *count; 6863f89caaSJens Wiklander size_t found = 0; 6963f89caaSJens Wiklander void **attr_ptr = attr; 7063f89caaSJens Wiklander uint32_t *attr_size_ptr = attr_size; 7163f89caaSJens Wiklander 7263f89caaSJens Wiklander for (; cur < end; cur += next_off) { 7363f89caaSJens Wiklander /* Structure aligned copy of the pkcs11_ref in the object */ 7463f89caaSJens Wiklander struct pkcs11_attribute_head pkcs11_ref = { }; 7563f89caaSJens Wiklander 7663f89caaSJens Wiklander TEE_MemMove(&pkcs11_ref, cur, sizeof(pkcs11_ref)); 7763f89caaSJens Wiklander next_off = sizeof(pkcs11_ref) + pkcs11_ref.size; 7863f89caaSJens Wiklander 7963f89caaSJens Wiklander if (pkcs11_ref.id != attribute) 8063f89caaSJens Wiklander continue; 8163f89caaSJens Wiklander 8263f89caaSJens Wiklander found++; 8363f89caaSJens Wiklander 8463f89caaSJens Wiklander if (!max_found) 8563f89caaSJens Wiklander continue; /* only count matching attributes */ 8663f89caaSJens Wiklander 8763f89caaSJens Wiklander if (attr) 8863f89caaSJens Wiklander *attr_ptr++ = cur + sizeof(pkcs11_ref); 8963f89caaSJens Wiklander 9063f89caaSJens Wiklander if (attr_size) 9163f89caaSJens Wiklander *attr_size_ptr++ = pkcs11_ref.size; 9263f89caaSJens Wiklander 9363f89caaSJens Wiklander if (found == max_found) 9463f89caaSJens Wiklander break; 9563f89caaSJens Wiklander } 9663f89caaSJens Wiklander 9763f89caaSJens Wiklander /* Sanity */ 9863f89caaSJens Wiklander if (cur > end) { 9963f89caaSJens Wiklander DMSG("Exceeding serial object length"); 10063f89caaSJens Wiklander TEE_Panic(0); 10163f89caaSJens Wiklander } 10263f89caaSJens Wiklander 10363f89caaSJens Wiklander *count = found; 10463f89caaSJens Wiklander } 10563f89caaSJens Wiklander 10663f89caaSJens Wiklander enum pkcs11_rc get_attribute_ptr(struct obj_attrs *head, uint32_t attribute, 10763f89caaSJens Wiklander void **attr_ptr, uint32_t *attr_size) 10863f89caaSJens Wiklander { 10963f89caaSJens Wiklander size_t count = 1; 11063f89caaSJens Wiklander 11163f89caaSJens Wiklander get_attribute_ptrs(head, attribute, attr_ptr, attr_size, &count); 11263f89caaSJens Wiklander 11363f89caaSJens Wiklander if (!count) 11463f89caaSJens Wiklander return PKCS11_RV_NOT_FOUND; 11563f89caaSJens Wiklander 11663f89caaSJens Wiklander if (count != 1) 11763f89caaSJens Wiklander return PKCS11_CKR_GENERAL_ERROR; 11863f89caaSJens Wiklander 11963f89caaSJens Wiklander return PKCS11_CKR_OK; 12063f89caaSJens Wiklander } 12163f89caaSJens Wiklander 12263f89caaSJens Wiklander enum pkcs11_rc get_attribute(struct obj_attrs *head, uint32_t attribute, 12363f89caaSJens Wiklander void *attr, uint32_t *attr_size) 12463f89caaSJens Wiklander { 12563f89caaSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 12663f89caaSJens Wiklander void *attr_ptr = NULL; 12763f89caaSJens Wiklander uint32_t size = 0; 12863f89caaSJens Wiklander 12963f89caaSJens Wiklander rc = get_attribute_ptr(head, attribute, &attr_ptr, &size); 13063f89caaSJens Wiklander if (rc) 13163f89caaSJens Wiklander return rc; 13263f89caaSJens Wiklander 13363f89caaSJens Wiklander if (attr_size && *attr_size != size) { 13463f89caaSJens Wiklander *attr_size = size; 13563f89caaSJens Wiklander /* This reuses buffer-to-small for any bad size matching */ 13663f89caaSJens Wiklander return PKCS11_CKR_BUFFER_TOO_SMALL; 13763f89caaSJens Wiklander } 13863f89caaSJens Wiklander 13963f89caaSJens Wiklander if (attr) 14063f89caaSJens Wiklander TEE_MemMove(attr, attr_ptr, size); 14163f89caaSJens Wiklander 14263f89caaSJens Wiklander if (attr_size) 14363f89caaSJens Wiklander *attr_size = size; 14463f89caaSJens Wiklander 14563f89caaSJens Wiklander return PKCS11_CKR_OK; 14663f89caaSJens Wiklander } 14763f89caaSJens Wiklander 14863f89caaSJens Wiklander bool get_bool(struct obj_attrs *head, uint32_t attribute) 14963f89caaSJens Wiklander { 15063f89caaSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 15163f89caaSJens Wiklander uint8_t bbool = 0; 15263f89caaSJens Wiklander uint32_t size = sizeof(bbool); 15363f89caaSJens Wiklander 15463f89caaSJens Wiklander rc = get_attribute(head, attribute, &bbool, &size); 15563f89caaSJens Wiklander 15663f89caaSJens Wiklander if (rc == PKCS11_RV_NOT_FOUND) 15763f89caaSJens Wiklander return false; 15863f89caaSJens Wiklander 15963f89caaSJens Wiklander assert(rc == PKCS11_CKR_OK); 16063f89caaSJens Wiklander return bbool; 16163f89caaSJens Wiklander } 16263f89caaSJens Wiklander 16363f89caaSJens Wiklander #if CFG_TEE_TA_LOG_LEVEL > 0 16463f89caaSJens Wiklander /* 16563f89caaSJens Wiklander * Debug: dump CK attribute array to output trace 16663f89caaSJens Wiklander */ 16763f89caaSJens Wiklander #define ATTR_TRACE_FMT "%s attr %s / %s\t(0x%04"PRIx32" %"PRIu32"-byte" 16863f89caaSJens Wiklander #define ATTR_FMT_0BYTE ATTR_TRACE_FMT ")" 16963f89caaSJens Wiklander #define ATTR_FMT_1BYTE ATTR_TRACE_FMT ": %02x)" 17063f89caaSJens Wiklander #define ATTR_FMT_2BYTE ATTR_TRACE_FMT ": %02x %02x)" 17163f89caaSJens Wiklander #define ATTR_FMT_3BYTE ATTR_TRACE_FMT ": %02x %02x %02x)" 17263f89caaSJens Wiklander #define ATTR_FMT_4BYTE ATTR_TRACE_FMT ": %02x %02x %02x %02x)" 17363f89caaSJens Wiklander #define ATTR_FMT_ARRAY ATTR_TRACE_FMT ": %02x %02x %02x %02x ...)" 17463f89caaSJens Wiklander 17563f89caaSJens Wiklander static void __trace_attributes(char *prefix, void *src, void *end) 17663f89caaSJens Wiklander { 17763f89caaSJens Wiklander size_t next_off = 0; 17863f89caaSJens Wiklander char *prefix2 = NULL; 17963f89caaSJens Wiklander size_t prefix_len = strlen(prefix); 18063f89caaSJens Wiklander char *cur = src; 18163f89caaSJens Wiklander 18263f89caaSJens Wiklander /* append 4 spaces to the prefix plus terminal '\0' */ 18363f89caaSJens Wiklander prefix2 = TEE_Malloc(prefix_len + 1 + 4, TEE_MALLOC_FILL_ZERO); 18463f89caaSJens Wiklander if (!prefix2) 18563f89caaSJens Wiklander return; 18663f89caaSJens Wiklander 18763f89caaSJens Wiklander TEE_MemMove(prefix2, prefix, prefix_len + 1); 18863f89caaSJens Wiklander TEE_MemFill(prefix2 + prefix_len, ' ', 4); 18963f89caaSJens Wiklander *(prefix2 + prefix_len + 4) = '\0'; 19063f89caaSJens Wiklander 19163f89caaSJens Wiklander for (; cur < (char *)end; cur += next_off) { 19263f89caaSJens Wiklander struct pkcs11_attribute_head pkcs11_ref = { }; 19363f89caaSJens Wiklander uint8_t data[4] = { 0 }; 19463f89caaSJens Wiklander 19563f89caaSJens Wiklander TEE_MemMove(&pkcs11_ref, cur, sizeof(pkcs11_ref)); 19663f89caaSJens Wiklander TEE_MemMove(&data[0], cur + sizeof(pkcs11_ref), 19763f89caaSJens Wiklander MIN(pkcs11_ref.size, sizeof(data))); 19863f89caaSJens Wiklander 19963f89caaSJens Wiklander next_off = sizeof(pkcs11_ref) + pkcs11_ref.size; 20063f89caaSJens Wiklander 20163f89caaSJens Wiklander switch (pkcs11_ref.size) { 20263f89caaSJens Wiklander case 0: 20363f89caaSJens Wiklander IMSG_RAW(ATTR_FMT_0BYTE, 20463f89caaSJens Wiklander prefix, id2str_attr(pkcs11_ref.id), "*", 20563f89caaSJens Wiklander pkcs11_ref.id, pkcs11_ref.size); 20663f89caaSJens Wiklander break; 20763f89caaSJens Wiklander case 1: 20863f89caaSJens Wiklander IMSG_RAW(ATTR_FMT_1BYTE, 20963f89caaSJens Wiklander prefix, id2str_attr(pkcs11_ref.id), 21063f89caaSJens Wiklander id2str_attr_value(pkcs11_ref.id, 21163f89caaSJens Wiklander pkcs11_ref.size, 21263f89caaSJens Wiklander cur + sizeof(pkcs11_ref)), 21363f89caaSJens Wiklander pkcs11_ref.id, pkcs11_ref.size, data[0]); 21463f89caaSJens Wiklander break; 21563f89caaSJens Wiklander case 2: 21663f89caaSJens Wiklander IMSG_RAW(ATTR_FMT_2BYTE, 21763f89caaSJens Wiklander prefix, id2str_attr(pkcs11_ref.id), 21863f89caaSJens Wiklander id2str_attr_value(pkcs11_ref.id, 21963f89caaSJens Wiklander pkcs11_ref.size, 22063f89caaSJens Wiklander cur + sizeof(pkcs11_ref)), 22163f89caaSJens Wiklander pkcs11_ref.id, pkcs11_ref.size, data[0], 22263f89caaSJens Wiklander data[1]); 22363f89caaSJens Wiklander break; 22463f89caaSJens Wiklander case 3: 22563f89caaSJens Wiklander IMSG_RAW(ATTR_FMT_3BYTE, 22663f89caaSJens Wiklander prefix, id2str_attr(pkcs11_ref.id), 22763f89caaSJens Wiklander id2str_attr_value(pkcs11_ref.id, 22863f89caaSJens Wiklander pkcs11_ref.size, 22963f89caaSJens Wiklander cur + sizeof(pkcs11_ref)), 23063f89caaSJens Wiklander pkcs11_ref.id, pkcs11_ref.size, 23163f89caaSJens Wiklander data[0], data[1], data[2]); 23263f89caaSJens Wiklander break; 23363f89caaSJens Wiklander case 4: 23463f89caaSJens Wiklander IMSG_RAW(ATTR_FMT_4BYTE, 23563f89caaSJens Wiklander prefix, id2str_attr(pkcs11_ref.id), 23663f89caaSJens Wiklander id2str_attr_value(pkcs11_ref.id, 23763f89caaSJens Wiklander pkcs11_ref.size, 23863f89caaSJens Wiklander cur + sizeof(pkcs11_ref)), 23963f89caaSJens Wiklander pkcs11_ref.id, pkcs11_ref.size, 24063f89caaSJens Wiklander data[0], data[1], data[2], data[3]); 24163f89caaSJens Wiklander break; 24263f89caaSJens Wiklander default: 24363f89caaSJens Wiklander IMSG_RAW(ATTR_FMT_ARRAY, 24463f89caaSJens Wiklander prefix, id2str_attr(pkcs11_ref.id), 24563f89caaSJens Wiklander id2str_attr_value(pkcs11_ref.id, 24663f89caaSJens Wiklander pkcs11_ref.size, 24763f89caaSJens Wiklander cur + sizeof(pkcs11_ref)), 24863f89caaSJens Wiklander pkcs11_ref.id, pkcs11_ref.size, 24963f89caaSJens Wiklander data[0], data[1], data[2], data[3]); 25063f89caaSJens Wiklander break; 25163f89caaSJens Wiklander } 25263f89caaSJens Wiklander 25363f89caaSJens Wiklander switch (pkcs11_ref.id) { 25463f89caaSJens Wiklander case PKCS11_CKA_WRAP_TEMPLATE: 25563f89caaSJens Wiklander case PKCS11_CKA_UNWRAP_TEMPLATE: 25663f89caaSJens Wiklander case PKCS11_CKA_DERIVE_TEMPLATE: 257*ef5f7584SEtienne Carriere if (pkcs11_ref.size) 258*ef5f7584SEtienne Carriere trace_attributes(prefix2, 259*ef5f7584SEtienne Carriere cur + sizeof(pkcs11_ref)); 26063f89caaSJens Wiklander break; 26163f89caaSJens Wiklander default: 26263f89caaSJens Wiklander break; 26363f89caaSJens Wiklander } 26463f89caaSJens Wiklander } 26563f89caaSJens Wiklander 26663f89caaSJens Wiklander /* Sanity */ 26763f89caaSJens Wiklander if (cur != end) 26863f89caaSJens Wiklander EMSG("Warning: unexpected alignment in object attributes"); 26963f89caaSJens Wiklander 27063f89caaSJens Wiklander TEE_Free(prefix2); 27163f89caaSJens Wiklander } 27263f89caaSJens Wiklander 27363f89caaSJens Wiklander void trace_attributes(const char *prefix, void *ref) 27463f89caaSJens Wiklander { 275*ef5f7584SEtienne Carriere struct obj_attrs head = { }; 27663f89caaSJens Wiklander char *pre = NULL; 27763f89caaSJens Wiklander 27863f89caaSJens Wiklander TEE_MemMove(&head, ref, sizeof(head)); 27963f89caaSJens Wiklander 280*ef5f7584SEtienne Carriere if (!head.attrs_count) 281*ef5f7584SEtienne Carriere return; 282*ef5f7584SEtienne Carriere 28363f89caaSJens Wiklander pre = TEE_Malloc(prefix ? strlen(prefix) + 2 : 2, TEE_MALLOC_FILL_ZERO); 28463f89caaSJens Wiklander if (!pre) { 28563f89caaSJens Wiklander EMSG("%s: out of memory", prefix); 28663f89caaSJens Wiklander return; 28763f89caaSJens Wiklander } 28863f89caaSJens Wiklander 28963f89caaSJens Wiklander if (prefix) 29063f89caaSJens Wiklander TEE_MemMove(pre, prefix, strlen(prefix)); 29163f89caaSJens Wiklander 29263f89caaSJens Wiklander IMSG_RAW("%s,--- (serial object) Attributes list --------", pre); 29363f89caaSJens Wiklander IMSG_RAW("%s| %"PRIu32" item(s) - %"PRIu32" bytes", 29463f89caaSJens Wiklander pre, head.attrs_count, head.attrs_size); 29563f89caaSJens Wiklander 29663f89caaSJens Wiklander pre[prefix ? strlen(prefix) : 0] = '|'; 29763f89caaSJens Wiklander __trace_attributes(pre, (char *)ref + sizeof(head), 29863f89caaSJens Wiklander (char *)ref + sizeof(head) + head.attrs_size); 29963f89caaSJens Wiklander 30063f89caaSJens Wiklander IMSG_RAW("%s`-----------------------", prefix ? prefix : ""); 30163f89caaSJens Wiklander 30263f89caaSJens Wiklander TEE_Free(pre); 30363f89caaSJens Wiklander } 30463f89caaSJens Wiklander #endif /*CFG_TEE_TA_LOG_LEVEL*/ 305