xref: /optee_os/ta/pkcs11/src/attributes.c (revision e3f0cb566a9769b6b8d68e9a7585367cff35aea9)
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 
61fa247a2aSRuchika Gupta static enum pkcs11_rc _remove_attribute(struct obj_attrs **head,
62fa247a2aSRuchika Gupta 					uint32_t attribute, bool empty)
63fa247a2aSRuchika Gupta {
64fa247a2aSRuchika Gupta 	struct obj_attrs *h = *head;
65fa247a2aSRuchika Gupta 	char *cur = NULL;
66fa247a2aSRuchika Gupta 	char *end = NULL;
67fa247a2aSRuchika Gupta 	size_t next_off = 0;
68fa247a2aSRuchika Gupta 
69fa247a2aSRuchika Gupta 	/* Let's find the target attribute */
70fa247a2aSRuchika Gupta 	cur = (char *)h + sizeof(struct obj_attrs);
71fa247a2aSRuchika Gupta 	end = cur + h->attrs_size;
72fa247a2aSRuchika Gupta 	for (; cur < end; cur += next_off) {
73fa247a2aSRuchika Gupta 		struct pkcs11_attribute_head pkcs11_ref = { };
74fa247a2aSRuchika Gupta 
75fa247a2aSRuchika Gupta 		TEE_MemMove(&pkcs11_ref, cur, sizeof(pkcs11_ref));
76fa247a2aSRuchika Gupta 		next_off = sizeof(pkcs11_ref) + pkcs11_ref.size;
77fa247a2aSRuchika Gupta 
78fa247a2aSRuchika Gupta 		if (pkcs11_ref.id != attribute)
79fa247a2aSRuchika Gupta 			continue;
80fa247a2aSRuchika Gupta 
81fa247a2aSRuchika Gupta 		if (empty && pkcs11_ref.size)
82fa247a2aSRuchika Gupta 			return PKCS11_CKR_FUNCTION_FAILED;
83fa247a2aSRuchika Gupta 
84fa247a2aSRuchika Gupta 		TEE_MemMove(cur, cur + next_off, end - (cur + next_off));
85fa247a2aSRuchika Gupta 
86fa247a2aSRuchika Gupta 		h->attrs_count--;
87fa247a2aSRuchika Gupta 		h->attrs_size -= next_off;
88fa247a2aSRuchika Gupta 		end -= next_off;
89fa247a2aSRuchika Gupta 		next_off = 0;
90fa247a2aSRuchika Gupta 
91fa247a2aSRuchika Gupta 		return PKCS11_CKR_OK;
92fa247a2aSRuchika Gupta 	}
93fa247a2aSRuchika Gupta 
94fa247a2aSRuchika Gupta 	DMSG("Attribute %s (%#x) not found", id2str_attr(attribute), attribute);
95fa247a2aSRuchika Gupta 	return PKCS11_RV_NOT_FOUND;
96fa247a2aSRuchika Gupta }
97fa247a2aSRuchika Gupta 
98fa247a2aSRuchika Gupta enum pkcs11_rc remove_empty_attribute(struct obj_attrs **head,
99fa247a2aSRuchika Gupta 				      uint32_t attribute)
100fa247a2aSRuchika Gupta {
101fa247a2aSRuchika Gupta 	return _remove_attribute(head, attribute, true /* empty */);
102fa247a2aSRuchika Gupta }
103fa247a2aSRuchika Gupta 
10463f89caaSJens Wiklander void get_attribute_ptrs(struct obj_attrs *head, uint32_t attribute,
10563f89caaSJens Wiklander 			void **attr, uint32_t *attr_size, size_t *count)
10663f89caaSJens Wiklander {
10763f89caaSJens Wiklander 	char *cur = (char *)head + sizeof(struct obj_attrs);
10863f89caaSJens Wiklander 	char *end = cur + head->attrs_size;
10963f89caaSJens Wiklander 	size_t next_off = 0;
11063f89caaSJens Wiklander 	size_t max_found = *count;
11163f89caaSJens Wiklander 	size_t found = 0;
11263f89caaSJens Wiklander 	void **attr_ptr = attr;
11363f89caaSJens Wiklander 	uint32_t *attr_size_ptr = attr_size;
11463f89caaSJens Wiklander 
11563f89caaSJens Wiklander 	for (; cur < end; cur += next_off) {
11663f89caaSJens Wiklander 		/* Structure aligned copy of the pkcs11_ref in the object */
11763f89caaSJens Wiklander 		struct pkcs11_attribute_head pkcs11_ref = { };
11863f89caaSJens Wiklander 
11963f89caaSJens Wiklander 		TEE_MemMove(&pkcs11_ref, cur, sizeof(pkcs11_ref));
12063f89caaSJens Wiklander 		next_off = sizeof(pkcs11_ref) + pkcs11_ref.size;
12163f89caaSJens Wiklander 
12263f89caaSJens Wiklander 		if (pkcs11_ref.id != attribute)
12363f89caaSJens Wiklander 			continue;
12463f89caaSJens Wiklander 
12563f89caaSJens Wiklander 		found++;
12663f89caaSJens Wiklander 
12763f89caaSJens Wiklander 		if (!max_found)
12863f89caaSJens Wiklander 			continue;	/* only count matching attributes */
12963f89caaSJens Wiklander 
1300b912584SEtienne Carriere 		if (attr) {
1310b912584SEtienne Carriere 			if (pkcs11_ref.size)
13263f89caaSJens Wiklander 				*attr_ptr++ = cur + sizeof(pkcs11_ref);
1330b912584SEtienne Carriere 			else
1340b912584SEtienne Carriere 				*attr_ptr++ = NULL;
1350b912584SEtienne Carriere 		}
13663f89caaSJens Wiklander 
13763f89caaSJens Wiklander 		if (attr_size)
13863f89caaSJens Wiklander 			*attr_size_ptr++ = pkcs11_ref.size;
13963f89caaSJens Wiklander 
14063f89caaSJens Wiklander 		if (found == max_found)
14163f89caaSJens Wiklander 			break;
14263f89caaSJens Wiklander 	}
14363f89caaSJens Wiklander 
14463f89caaSJens Wiklander 	/* Sanity */
14563f89caaSJens Wiklander 	if (cur > end) {
14663f89caaSJens Wiklander 		DMSG("Exceeding serial object length");
14763f89caaSJens Wiklander 		TEE_Panic(0);
14863f89caaSJens Wiklander 	}
14963f89caaSJens Wiklander 
15063f89caaSJens Wiklander 	*count = found;
15163f89caaSJens Wiklander }
15263f89caaSJens Wiklander 
15363f89caaSJens Wiklander enum pkcs11_rc get_attribute_ptr(struct obj_attrs *head, uint32_t attribute,
15463f89caaSJens Wiklander 				 void **attr_ptr, uint32_t *attr_size)
15563f89caaSJens Wiklander {
15663f89caaSJens Wiklander 	size_t count = 1;
15763f89caaSJens Wiklander 
15863f89caaSJens Wiklander 	get_attribute_ptrs(head, attribute, attr_ptr, attr_size, &count);
15963f89caaSJens Wiklander 
16063f89caaSJens Wiklander 	if (!count)
16163f89caaSJens Wiklander 		return PKCS11_RV_NOT_FOUND;
16263f89caaSJens Wiklander 
16363f89caaSJens Wiklander 	if (count != 1)
16463f89caaSJens Wiklander 		return PKCS11_CKR_GENERAL_ERROR;
16563f89caaSJens Wiklander 
16663f89caaSJens Wiklander 	return PKCS11_CKR_OK;
16763f89caaSJens Wiklander }
16863f89caaSJens Wiklander 
16963f89caaSJens Wiklander enum pkcs11_rc get_attribute(struct obj_attrs *head, uint32_t attribute,
17063f89caaSJens Wiklander 			     void *attr, uint32_t *attr_size)
17163f89caaSJens Wiklander {
17263f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
17363f89caaSJens Wiklander 	void *attr_ptr = NULL;
17463f89caaSJens Wiklander 	uint32_t size = 0;
17563f89caaSJens Wiklander 
17663f89caaSJens Wiklander 	rc = get_attribute_ptr(head, attribute, &attr_ptr, &size);
17763f89caaSJens Wiklander 	if (rc)
17863f89caaSJens Wiklander 		return rc;
17963f89caaSJens Wiklander 
180d17c25d2SVesa Jääskeläinen 	if (attr_size && *attr_size < size) {
18163f89caaSJens Wiklander 		*attr_size = size;
18263f89caaSJens Wiklander 		/* This reuses buffer-to-small for any bad size matching */
18363f89caaSJens Wiklander 		return PKCS11_CKR_BUFFER_TOO_SMALL;
18463f89caaSJens Wiklander 	}
18563f89caaSJens Wiklander 
18663f89caaSJens Wiklander 	if (attr)
18763f89caaSJens Wiklander 		TEE_MemMove(attr, attr_ptr, size);
18863f89caaSJens Wiklander 
18963f89caaSJens Wiklander 	if (attr_size)
19063f89caaSJens Wiklander 		*attr_size = size;
19163f89caaSJens Wiklander 
19263f89caaSJens Wiklander 	return PKCS11_CKR_OK;
19363f89caaSJens Wiklander }
19463f89caaSJens Wiklander 
1952d25a9bcSRuchika Gupta enum pkcs11_rc set_attribute(struct obj_attrs **head, uint32_t attribute,
1962d25a9bcSRuchika Gupta 			     void *data, size_t size)
1972d25a9bcSRuchika Gupta {
1982d25a9bcSRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_OK;
1992d25a9bcSRuchika Gupta 
2002d25a9bcSRuchika Gupta 	rc = _remove_attribute(head, attribute, false);
2012d25a9bcSRuchika Gupta 	if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
2022d25a9bcSRuchika Gupta 		return rc;
2032d25a9bcSRuchika Gupta 
2042d25a9bcSRuchika Gupta 	return add_attribute(head, attribute, data, size);
2052d25a9bcSRuchika Gupta }
2062d25a9bcSRuchika Gupta 
2072d25a9bcSRuchika Gupta enum pkcs11_rc modify_attributes_list(struct obj_attrs **dst,
2082d25a9bcSRuchika Gupta 				      struct obj_attrs *head)
2092d25a9bcSRuchika Gupta {
2102d25a9bcSRuchika Gupta 	char *cur = (char *)head + sizeof(struct obj_attrs);
2112d25a9bcSRuchika Gupta 	char *end = cur + head->attrs_size;
2122d25a9bcSRuchika Gupta 	size_t len = 0;
2132d25a9bcSRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_OK;
2142d25a9bcSRuchika Gupta 
2152d25a9bcSRuchika Gupta 	for (; cur < end; cur += len) {
2162d25a9bcSRuchika Gupta 		struct pkcs11_attribute_head *cli_ref = (void *)cur;
2172d25a9bcSRuchika Gupta 		/* Structure aligned copy of the pkcs11_ref in the object */
2182d25a9bcSRuchika Gupta 		struct pkcs11_attribute_head cli_head = { };
2192d25a9bcSRuchika Gupta 
2202d25a9bcSRuchika Gupta 		TEE_MemMove(&cli_head, cur, sizeof(cli_head));
2212d25a9bcSRuchika Gupta 		len = sizeof(cli_head) + cli_head.size;
2222d25a9bcSRuchika Gupta 
2232d25a9bcSRuchika Gupta 		rc = set_attribute(dst, cli_head.id,
2242d25a9bcSRuchika Gupta 				   cli_head.size ? cli_ref->data : NULL,
2252d25a9bcSRuchika Gupta 				   cli_head.size);
2262d25a9bcSRuchika Gupta 		if (rc)
2272d25a9bcSRuchika Gupta 			return rc;
2282d25a9bcSRuchika Gupta 	}
2292d25a9bcSRuchika Gupta 
2302d25a9bcSRuchika Gupta 	return PKCS11_CKR_OK;
2312d25a9bcSRuchika Gupta }
2322d25a9bcSRuchika Gupta 
23363f89caaSJens Wiklander bool get_bool(struct obj_attrs *head, uint32_t attribute)
23463f89caaSJens Wiklander {
23563f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
23663f89caaSJens Wiklander 	uint8_t bbool = 0;
23763f89caaSJens Wiklander 	uint32_t size = sizeof(bbool);
23863f89caaSJens Wiklander 
23963f89caaSJens Wiklander 	rc = get_attribute(head, attribute, &bbool, &size);
24063f89caaSJens Wiklander 
24163f89caaSJens Wiklander 	if (rc == PKCS11_RV_NOT_FOUND)
24263f89caaSJens Wiklander 		return false;
24363f89caaSJens Wiklander 
24463f89caaSJens Wiklander 	assert(rc == PKCS11_CKR_OK);
24563f89caaSJens Wiklander 	return bbool;
24663f89caaSJens Wiklander }
24763f89caaSJens Wiklander 
248dc99b202SRuchika Gupta bool attributes_match_reference(struct obj_attrs *candidate,
249dc99b202SRuchika Gupta 				struct obj_attrs *ref)
250dc99b202SRuchika Gupta {
251dc99b202SRuchika Gupta 	size_t count = ref->attrs_count;
252dc99b202SRuchika Gupta 	unsigned char *ref_attr = ref->attrs;
253dc99b202SRuchika Gupta 	uint32_t rc = PKCS11_CKR_GENERAL_ERROR;
254dc99b202SRuchika Gupta 
255dc99b202SRuchika Gupta 	if (!ref->attrs_count) {
256fa1ac767SRobin van der Gracht 		DMSG("Empty reference match all");
257fa1ac767SRobin van der Gracht 		return true;
258dc99b202SRuchika Gupta 	}
259dc99b202SRuchika Gupta 
260dc99b202SRuchika Gupta 	for (count = 0; count < ref->attrs_count; count++) {
261dc99b202SRuchika Gupta 		struct pkcs11_attribute_head pkcs11_ref = { };
262dc99b202SRuchika Gupta 		void *value = NULL;
263dc99b202SRuchika Gupta 		uint32_t size = 0;
264dc99b202SRuchika Gupta 
265dc99b202SRuchika Gupta 		TEE_MemMove(&pkcs11_ref, ref_attr, sizeof(pkcs11_ref));
266dc99b202SRuchika Gupta 
267dc99b202SRuchika Gupta 		rc = get_attribute_ptr(candidate, pkcs11_ref.id, &value, &size);
268dc99b202SRuchika Gupta 
269dc99b202SRuchika Gupta 		if (rc || !value || size != pkcs11_ref.size ||
270dc99b202SRuchika Gupta 		    TEE_MemCompare(ref_attr + sizeof(pkcs11_ref), value, size))
271dc99b202SRuchika Gupta 			return false;
272dc99b202SRuchika Gupta 
273dc99b202SRuchika Gupta 		ref_attr += sizeof(pkcs11_ref) + pkcs11_ref.size;
274dc99b202SRuchika Gupta 	}
275dc99b202SRuchika Gupta 
276dc99b202SRuchika Gupta 	return true;
277dc99b202SRuchika Gupta }
278dc99b202SRuchika Gupta 
279*e3f0cb56SRuchika Gupta enum pkcs11_rc attributes_match_add_reference(struct obj_attrs **head,
280*e3f0cb56SRuchika Gupta 					      struct obj_attrs *ref)
281*e3f0cb56SRuchika Gupta {
282*e3f0cb56SRuchika Gupta 	size_t count = ref->attrs_count;
283*e3f0cb56SRuchika Gupta 	unsigned char *ref_attr = ref->attrs;
284*e3f0cb56SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_OK;
285*e3f0cb56SRuchika Gupta 
286*e3f0cb56SRuchika Gupta 	if (!ref->attrs_count)
287*e3f0cb56SRuchika Gupta 		return PKCS11_CKR_OK;
288*e3f0cb56SRuchika Gupta 
289*e3f0cb56SRuchika Gupta 	for (count = 0; count < ref->attrs_count; count++) {
290*e3f0cb56SRuchika Gupta 		struct pkcs11_attribute_head pkcs11_ref = { };
291*e3f0cb56SRuchika Gupta 		void *value = NULL;
292*e3f0cb56SRuchika Gupta 		uint32_t size = 0;
293*e3f0cb56SRuchika Gupta 
294*e3f0cb56SRuchika Gupta 		TEE_MemMove(&pkcs11_ref, ref_attr, sizeof(pkcs11_ref));
295*e3f0cb56SRuchika Gupta 
296*e3f0cb56SRuchika Gupta 		rc = get_attribute_ptr(*head, pkcs11_ref.id, &value, &size);
297*e3f0cb56SRuchika Gupta 		if (rc == PKCS11_RV_NOT_FOUND) {
298*e3f0cb56SRuchika Gupta 			rc = add_attribute(head, pkcs11_ref.id,
299*e3f0cb56SRuchika Gupta 					   ref_attr + sizeof(pkcs11_ref),
300*e3f0cb56SRuchika Gupta 					   pkcs11_ref.size);
301*e3f0cb56SRuchika Gupta 			if (rc)
302*e3f0cb56SRuchika Gupta 				return rc;
303*e3f0cb56SRuchika Gupta 		} else {
304*e3f0cb56SRuchika Gupta 			if (rc || !value || size != pkcs11_ref.size ||
305*e3f0cb56SRuchika Gupta 			    TEE_MemCompare(ref_attr + sizeof(pkcs11_ref), value,
306*e3f0cb56SRuchika Gupta 					   size))
307*e3f0cb56SRuchika Gupta 				return PKCS11_CKR_TEMPLATE_INCONSISTENT;
308*e3f0cb56SRuchika Gupta 		}
309*e3f0cb56SRuchika Gupta 
310*e3f0cb56SRuchika Gupta 		ref_attr += sizeof(pkcs11_ref) + pkcs11_ref.size;
311*e3f0cb56SRuchika Gupta 	}
312*e3f0cb56SRuchika Gupta 
313*e3f0cb56SRuchika Gupta 	return PKCS11_CKR_OK;
314*e3f0cb56SRuchika Gupta }
315*e3f0cb56SRuchika Gupta 
31663f89caaSJens Wiklander #if CFG_TEE_TA_LOG_LEVEL > 0
31763f89caaSJens Wiklander /*
31863f89caaSJens Wiklander  * Debug: dump CK attribute array to output trace
31963f89caaSJens Wiklander  */
32063f89caaSJens Wiklander #define ATTR_TRACE_FMT	"%s attr %s / %s\t(0x%04"PRIx32" %"PRIu32"-byte"
32163f89caaSJens Wiklander #define ATTR_FMT_0BYTE	ATTR_TRACE_FMT ")"
32263f89caaSJens Wiklander #define ATTR_FMT_1BYTE	ATTR_TRACE_FMT ": %02x)"
32363f89caaSJens Wiklander #define ATTR_FMT_2BYTE	ATTR_TRACE_FMT ": %02x %02x)"
32463f89caaSJens Wiklander #define ATTR_FMT_3BYTE	ATTR_TRACE_FMT ": %02x %02x %02x)"
32563f89caaSJens Wiklander #define ATTR_FMT_4BYTE	ATTR_TRACE_FMT ": %02x %02x %02x %02x)"
32663f89caaSJens Wiklander #define ATTR_FMT_ARRAY	ATTR_TRACE_FMT ": %02x %02x %02x %02x ...)"
32763f89caaSJens Wiklander 
32863f89caaSJens Wiklander static void __trace_attributes(char *prefix, void *src, void *end)
32963f89caaSJens Wiklander {
33063f89caaSJens Wiklander 	size_t next_off = 0;
33163f89caaSJens Wiklander 	char *prefix2 = NULL;
33263f89caaSJens Wiklander 	size_t prefix_len = strlen(prefix);
33363f89caaSJens Wiklander 	char *cur = src;
33463f89caaSJens Wiklander 
33563f89caaSJens Wiklander 	/* append 4 spaces to the prefix plus terminal '\0' */
33663f89caaSJens Wiklander 	prefix2 = TEE_Malloc(prefix_len + 1 + 4, TEE_MALLOC_FILL_ZERO);
33763f89caaSJens Wiklander 	if (!prefix2)
33863f89caaSJens Wiklander 		return;
33963f89caaSJens Wiklander 
34063f89caaSJens Wiklander 	TEE_MemMove(prefix2, prefix, prefix_len + 1);
34163f89caaSJens Wiklander 	TEE_MemFill(prefix2 + prefix_len, ' ', 4);
34263f89caaSJens Wiklander 	*(prefix2 + prefix_len + 4) = '\0';
34363f89caaSJens Wiklander 
34463f89caaSJens Wiklander 	for (; cur < (char *)end; cur += next_off) {
34563f89caaSJens Wiklander 		struct pkcs11_attribute_head pkcs11_ref = { };
34663f89caaSJens Wiklander 		uint8_t data[4] = { 0 };
34763f89caaSJens Wiklander 
34863f89caaSJens Wiklander 		TEE_MemMove(&pkcs11_ref, cur, sizeof(pkcs11_ref));
34963f89caaSJens Wiklander 		TEE_MemMove(&data[0], cur + sizeof(pkcs11_ref),
35063f89caaSJens Wiklander 			    MIN(pkcs11_ref.size, sizeof(data)));
35163f89caaSJens Wiklander 
35263f89caaSJens Wiklander 		next_off = sizeof(pkcs11_ref) + pkcs11_ref.size;
35363f89caaSJens Wiklander 
35463f89caaSJens Wiklander 		switch (pkcs11_ref.size) {
35563f89caaSJens Wiklander 		case 0:
35663f89caaSJens Wiklander 			IMSG_RAW(ATTR_FMT_0BYTE,
35763f89caaSJens Wiklander 				 prefix, id2str_attr(pkcs11_ref.id), "*",
35863f89caaSJens Wiklander 				 pkcs11_ref.id, pkcs11_ref.size);
35963f89caaSJens Wiklander 			break;
36063f89caaSJens Wiklander 		case 1:
36163f89caaSJens Wiklander 			IMSG_RAW(ATTR_FMT_1BYTE,
36263f89caaSJens Wiklander 				 prefix, id2str_attr(pkcs11_ref.id),
36363f89caaSJens Wiklander 				 id2str_attr_value(pkcs11_ref.id,
36463f89caaSJens Wiklander 						   pkcs11_ref.size,
36563f89caaSJens Wiklander 						   cur + sizeof(pkcs11_ref)),
36663f89caaSJens Wiklander 				 pkcs11_ref.id, pkcs11_ref.size, data[0]);
36763f89caaSJens Wiklander 			break;
36863f89caaSJens Wiklander 		case 2:
36963f89caaSJens Wiklander 			IMSG_RAW(ATTR_FMT_2BYTE,
37063f89caaSJens Wiklander 				 prefix, id2str_attr(pkcs11_ref.id),
37163f89caaSJens Wiklander 				 id2str_attr_value(pkcs11_ref.id,
37263f89caaSJens Wiklander 						   pkcs11_ref.size,
37363f89caaSJens Wiklander 						   cur + sizeof(pkcs11_ref)),
37463f89caaSJens Wiklander 				 pkcs11_ref.id, pkcs11_ref.size, data[0],
37563f89caaSJens Wiklander 				 data[1]);
37663f89caaSJens Wiklander 			break;
37763f89caaSJens Wiklander 		case 3:
37863f89caaSJens Wiklander 			IMSG_RAW(ATTR_FMT_3BYTE,
37963f89caaSJens Wiklander 				 prefix, id2str_attr(pkcs11_ref.id),
38063f89caaSJens Wiklander 				 id2str_attr_value(pkcs11_ref.id,
38163f89caaSJens Wiklander 						   pkcs11_ref.size,
38263f89caaSJens Wiklander 						   cur + sizeof(pkcs11_ref)),
38363f89caaSJens Wiklander 				 pkcs11_ref.id, pkcs11_ref.size,
38463f89caaSJens Wiklander 				 data[0], data[1], data[2]);
38563f89caaSJens Wiklander 			break;
38663f89caaSJens Wiklander 		case 4:
38763f89caaSJens Wiklander 			IMSG_RAW(ATTR_FMT_4BYTE,
38863f89caaSJens Wiklander 				 prefix, id2str_attr(pkcs11_ref.id),
38963f89caaSJens Wiklander 				 id2str_attr_value(pkcs11_ref.id,
39063f89caaSJens Wiklander 						   pkcs11_ref.size,
39163f89caaSJens Wiklander 						   cur + sizeof(pkcs11_ref)),
39263f89caaSJens Wiklander 				 pkcs11_ref.id, pkcs11_ref.size,
39363f89caaSJens Wiklander 				 data[0], data[1], data[2], data[3]);
39463f89caaSJens Wiklander 			break;
39563f89caaSJens Wiklander 		default:
39663f89caaSJens Wiklander 			IMSG_RAW(ATTR_FMT_ARRAY,
39763f89caaSJens Wiklander 				 prefix, id2str_attr(pkcs11_ref.id),
39863f89caaSJens Wiklander 				 id2str_attr_value(pkcs11_ref.id,
39963f89caaSJens Wiklander 						   pkcs11_ref.size,
40063f89caaSJens Wiklander 						   cur + sizeof(pkcs11_ref)),
40163f89caaSJens Wiklander 				 pkcs11_ref.id, pkcs11_ref.size,
40263f89caaSJens Wiklander 				 data[0], data[1], data[2], data[3]);
40363f89caaSJens Wiklander 			break;
40463f89caaSJens Wiklander 		}
40563f89caaSJens Wiklander 
40663f89caaSJens Wiklander 		switch (pkcs11_ref.id) {
40763f89caaSJens Wiklander 		case PKCS11_CKA_WRAP_TEMPLATE:
40863f89caaSJens Wiklander 		case PKCS11_CKA_UNWRAP_TEMPLATE:
40963f89caaSJens Wiklander 		case PKCS11_CKA_DERIVE_TEMPLATE:
410ef5f7584SEtienne Carriere 			if (pkcs11_ref.size)
411ef5f7584SEtienne Carriere 				trace_attributes(prefix2,
412ef5f7584SEtienne Carriere 						 cur + sizeof(pkcs11_ref));
41363f89caaSJens Wiklander 			break;
41463f89caaSJens Wiklander 		default:
41563f89caaSJens Wiklander 			break;
41663f89caaSJens Wiklander 		}
41763f89caaSJens Wiklander 	}
41863f89caaSJens Wiklander 
41963f89caaSJens Wiklander 	/* Sanity */
42063f89caaSJens Wiklander 	if (cur != end)
42163f89caaSJens Wiklander 		EMSG("Warning: unexpected alignment in object attributes");
42263f89caaSJens Wiklander 
42363f89caaSJens Wiklander 	TEE_Free(prefix2);
42463f89caaSJens Wiklander }
42563f89caaSJens Wiklander 
42663f89caaSJens Wiklander void trace_attributes(const char *prefix, void *ref)
42763f89caaSJens Wiklander {
428ef5f7584SEtienne Carriere 	struct obj_attrs head = { };
42963f89caaSJens Wiklander 	char *pre = NULL;
43063f89caaSJens Wiklander 
43163f89caaSJens Wiklander 	TEE_MemMove(&head, ref, sizeof(head));
43263f89caaSJens Wiklander 
433ef5f7584SEtienne Carriere 	if (!head.attrs_count)
434ef5f7584SEtienne Carriere 		return;
435ef5f7584SEtienne Carriere 
43663f89caaSJens Wiklander 	pre = TEE_Malloc(prefix ? strlen(prefix) + 2 : 2, TEE_MALLOC_FILL_ZERO);
43763f89caaSJens Wiklander 	if (!pre) {
43863f89caaSJens Wiklander 		EMSG("%s: out of memory", prefix);
43963f89caaSJens Wiklander 		return;
44063f89caaSJens Wiklander 	}
44163f89caaSJens Wiklander 
44263f89caaSJens Wiklander 	if (prefix)
44363f89caaSJens Wiklander 		TEE_MemMove(pre, prefix, strlen(prefix));
44463f89caaSJens Wiklander 
44563f89caaSJens Wiklander 	IMSG_RAW("%s,--- (serial object) Attributes list --------", pre);
44663f89caaSJens Wiklander 	IMSG_RAW("%s| %"PRIu32" item(s) - %"PRIu32" bytes",
44763f89caaSJens Wiklander 		 pre, head.attrs_count, head.attrs_size);
44863f89caaSJens Wiklander 
44963f89caaSJens Wiklander 	pre[prefix ? strlen(prefix) : 0] = '|';
45063f89caaSJens Wiklander 	__trace_attributes(pre, (char *)ref + sizeof(head),
45163f89caaSJens Wiklander 			   (char *)ref + sizeof(head) + head.attrs_size);
45263f89caaSJens Wiklander 
45363f89caaSJens Wiklander 	IMSG_RAW("%s`-----------------------", prefix ? prefix : "");
45463f89caaSJens Wiklander 
45563f89caaSJens Wiklander 	TEE_Free(pre);
45663f89caaSJens Wiklander }
45763f89caaSJens Wiklander #endif /*CFG_TEE_TA_LOG_LEVEL*/
458