xref: /optee_os/ta/pkcs11/src/attributes.c (revision 63f89caa9022ecf51d1b82dc78af35ba9e38466d)
1*63f89caaSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2*63f89caaSJens Wiklander /*
3*63f89caaSJens Wiklander  * Copyright (c) 2017-2020, Linaro Limited
4*63f89caaSJens Wiklander  */
5*63f89caaSJens Wiklander 
6*63f89caaSJens Wiklander #include <assert.h>
7*63f89caaSJens Wiklander #include <compiler.h>
8*63f89caaSJens Wiklander #include <pkcs11_ta.h>
9*63f89caaSJens Wiklander #include <stddef.h>
10*63f89caaSJens Wiklander #include <stdlib.h>
11*63f89caaSJens Wiklander #include <string.h>
12*63f89caaSJens Wiklander #include <string_ext.h>
13*63f89caaSJens Wiklander #include <tee_internal_api.h>
14*63f89caaSJens Wiklander #include <tee_internal_api_extensions.h>
15*63f89caaSJens Wiklander #include <trace.h>
16*63f89caaSJens Wiklander #include <util.h>
17*63f89caaSJens Wiklander 
18*63f89caaSJens Wiklander #include "attributes.h"
19*63f89caaSJens Wiklander #include "pkcs11_helpers.h"
20*63f89caaSJens Wiklander #include "serializer.h"
21*63f89caaSJens Wiklander 
22*63f89caaSJens Wiklander enum pkcs11_rc init_attributes_head(struct obj_attrs **head)
23*63f89caaSJens Wiklander {
24*63f89caaSJens Wiklander 	*head = TEE_Malloc(sizeof(**head), TEE_MALLOC_FILL_ZERO);
25*63f89caaSJens Wiklander 	if (!*head)
26*63f89caaSJens Wiklander 		return PKCS11_CKR_DEVICE_MEMORY;
27*63f89caaSJens Wiklander 
28*63f89caaSJens Wiklander 	return PKCS11_CKR_OK;
29*63f89caaSJens Wiklander }
30*63f89caaSJens Wiklander 
31*63f89caaSJens Wiklander enum pkcs11_rc add_attribute(struct obj_attrs **head, uint32_t attribute,
32*63f89caaSJens Wiklander 			     void *data, size_t size)
33*63f89caaSJens Wiklander {
34*63f89caaSJens Wiklander 	size_t buf_len = sizeof(struct obj_attrs) + (*head)->attrs_size;
35*63f89caaSJens Wiklander 	char **bstart = (void *)head;
36*63f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
37*63f89caaSJens Wiklander 	uint32_t data32 = 0;
38*63f89caaSJens Wiklander 
39*63f89caaSJens Wiklander 	data32 = attribute;
40*63f89caaSJens Wiklander 	rc = serialize(bstart, &buf_len, &data32, sizeof(uint32_t));
41*63f89caaSJens Wiklander 	if (rc)
42*63f89caaSJens Wiklander 		return rc;
43*63f89caaSJens Wiklander 
44*63f89caaSJens Wiklander 	data32 = size;
45*63f89caaSJens Wiklander 	rc = serialize(bstart, &buf_len, &data32, sizeof(uint32_t));
46*63f89caaSJens Wiklander 	if (rc)
47*63f89caaSJens Wiklander 		return rc;
48*63f89caaSJens Wiklander 
49*63f89caaSJens Wiklander 	rc = serialize(bstart, &buf_len, data, size);
50*63f89caaSJens Wiklander 	if (rc)
51*63f89caaSJens Wiklander 		return rc;
52*63f89caaSJens Wiklander 
53*63f89caaSJens Wiklander 	/* Alloced buffer is always well aligned */
54*63f89caaSJens Wiklander 	head = (void *)bstart;
55*63f89caaSJens Wiklander 	(*head)->attrs_size += 2 * sizeof(uint32_t) + size;
56*63f89caaSJens Wiklander 	(*head)->attrs_count++;
57*63f89caaSJens Wiklander 
58*63f89caaSJens Wiklander 	return rc;
59*63f89caaSJens Wiklander }
60*63f89caaSJens Wiklander 
61*63f89caaSJens Wiklander void get_attribute_ptrs(struct obj_attrs *head, uint32_t attribute,
62*63f89caaSJens Wiklander 			void **attr, uint32_t *attr_size, size_t *count)
63*63f89caaSJens Wiklander {
64*63f89caaSJens Wiklander 	char *cur = (char *)head + sizeof(struct obj_attrs);
65*63f89caaSJens Wiklander 	char *end = cur + head->attrs_size;
66*63f89caaSJens Wiklander 	size_t next_off = 0;
67*63f89caaSJens Wiklander 	size_t max_found = *count;
68*63f89caaSJens Wiklander 	size_t found = 0;
69*63f89caaSJens Wiklander 	void **attr_ptr = attr;
70*63f89caaSJens Wiklander 	uint32_t *attr_size_ptr = attr_size;
71*63f89caaSJens Wiklander 
72*63f89caaSJens Wiklander 	for (; cur < end; cur += next_off) {
73*63f89caaSJens Wiklander 		/* Structure aligned copy of the pkcs11_ref in the object */
74*63f89caaSJens Wiklander 		struct pkcs11_attribute_head pkcs11_ref = { };
75*63f89caaSJens Wiklander 
76*63f89caaSJens Wiklander 		TEE_MemMove(&pkcs11_ref, cur, sizeof(pkcs11_ref));
77*63f89caaSJens Wiklander 		next_off = sizeof(pkcs11_ref) + pkcs11_ref.size;
78*63f89caaSJens Wiklander 
79*63f89caaSJens Wiklander 		if (pkcs11_ref.id != attribute)
80*63f89caaSJens Wiklander 			continue;
81*63f89caaSJens Wiklander 
82*63f89caaSJens Wiklander 		found++;
83*63f89caaSJens Wiklander 
84*63f89caaSJens Wiklander 		if (!max_found)
85*63f89caaSJens Wiklander 			continue;	/* only count matching attributes */
86*63f89caaSJens Wiklander 
87*63f89caaSJens Wiklander 		if (attr)
88*63f89caaSJens Wiklander 			*attr_ptr++ = cur + sizeof(pkcs11_ref);
89*63f89caaSJens Wiklander 
90*63f89caaSJens Wiklander 		if (attr_size)
91*63f89caaSJens Wiklander 			*attr_size_ptr++ = pkcs11_ref.size;
92*63f89caaSJens Wiklander 
93*63f89caaSJens Wiklander 		if (found == max_found)
94*63f89caaSJens Wiklander 			break;
95*63f89caaSJens Wiklander 	}
96*63f89caaSJens Wiklander 
97*63f89caaSJens Wiklander 	/* Sanity */
98*63f89caaSJens Wiklander 	if (cur > end) {
99*63f89caaSJens Wiklander 		DMSG("Exceeding serial object length");
100*63f89caaSJens Wiklander 		TEE_Panic(0);
101*63f89caaSJens Wiklander 	}
102*63f89caaSJens Wiklander 
103*63f89caaSJens Wiklander 	*count = found;
104*63f89caaSJens Wiklander }
105*63f89caaSJens Wiklander 
106*63f89caaSJens Wiklander enum pkcs11_rc get_attribute_ptr(struct obj_attrs *head, uint32_t attribute,
107*63f89caaSJens Wiklander 				 void **attr_ptr, uint32_t *attr_size)
108*63f89caaSJens Wiklander {
109*63f89caaSJens Wiklander 	size_t count = 1;
110*63f89caaSJens Wiklander 
111*63f89caaSJens Wiklander 	get_attribute_ptrs(head, attribute, attr_ptr, attr_size, &count);
112*63f89caaSJens Wiklander 
113*63f89caaSJens Wiklander 	if (!count)
114*63f89caaSJens Wiklander 		return PKCS11_RV_NOT_FOUND;
115*63f89caaSJens Wiklander 
116*63f89caaSJens Wiklander 	if (count != 1)
117*63f89caaSJens Wiklander 		return PKCS11_CKR_GENERAL_ERROR;
118*63f89caaSJens Wiklander 
119*63f89caaSJens Wiklander 	return PKCS11_CKR_OK;
120*63f89caaSJens Wiklander }
121*63f89caaSJens Wiklander 
122*63f89caaSJens Wiklander enum pkcs11_rc get_attribute(struct obj_attrs *head, uint32_t attribute,
123*63f89caaSJens Wiklander 			     void *attr, uint32_t *attr_size)
124*63f89caaSJens Wiklander {
125*63f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
126*63f89caaSJens Wiklander 	void *attr_ptr = NULL;
127*63f89caaSJens Wiklander 	uint32_t size = 0;
128*63f89caaSJens Wiklander 
129*63f89caaSJens Wiklander 	rc = get_attribute_ptr(head, attribute, &attr_ptr, &size);
130*63f89caaSJens Wiklander 	if (rc)
131*63f89caaSJens Wiklander 		return rc;
132*63f89caaSJens Wiklander 
133*63f89caaSJens Wiklander 	if (attr_size && *attr_size != size) {
134*63f89caaSJens Wiklander 		*attr_size = size;
135*63f89caaSJens Wiklander 		/* This reuses buffer-to-small for any bad size matching */
136*63f89caaSJens Wiklander 		return PKCS11_CKR_BUFFER_TOO_SMALL;
137*63f89caaSJens Wiklander 	}
138*63f89caaSJens Wiklander 
139*63f89caaSJens Wiklander 	if (attr)
140*63f89caaSJens Wiklander 		TEE_MemMove(attr, attr_ptr, size);
141*63f89caaSJens Wiklander 
142*63f89caaSJens Wiklander 	if (attr_size)
143*63f89caaSJens Wiklander 		*attr_size = size;
144*63f89caaSJens Wiklander 
145*63f89caaSJens Wiklander 	return PKCS11_CKR_OK;
146*63f89caaSJens Wiklander }
147*63f89caaSJens Wiklander 
148*63f89caaSJens Wiklander bool get_bool(struct obj_attrs *head, uint32_t attribute)
149*63f89caaSJens Wiklander {
150*63f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
151*63f89caaSJens Wiklander 	uint8_t bbool = 0;
152*63f89caaSJens Wiklander 	uint32_t size = sizeof(bbool);
153*63f89caaSJens Wiklander 
154*63f89caaSJens Wiklander 	rc = get_attribute(head, attribute, &bbool, &size);
155*63f89caaSJens Wiklander 
156*63f89caaSJens Wiklander 	if (rc == PKCS11_RV_NOT_FOUND)
157*63f89caaSJens Wiklander 		return false;
158*63f89caaSJens Wiklander 
159*63f89caaSJens Wiklander 	assert(rc == PKCS11_CKR_OK);
160*63f89caaSJens Wiklander 	return bbool;
161*63f89caaSJens Wiklander }
162*63f89caaSJens Wiklander 
163*63f89caaSJens Wiklander #if CFG_TEE_TA_LOG_LEVEL > 0
164*63f89caaSJens Wiklander /*
165*63f89caaSJens Wiklander  * Debug: dump CK attribute array to output trace
166*63f89caaSJens Wiklander  */
167*63f89caaSJens Wiklander #define ATTR_TRACE_FMT	"%s attr %s / %s\t(0x%04"PRIx32" %"PRIu32"-byte"
168*63f89caaSJens Wiklander #define ATTR_FMT_0BYTE	ATTR_TRACE_FMT ")"
169*63f89caaSJens Wiklander #define ATTR_FMT_1BYTE	ATTR_TRACE_FMT ": %02x)"
170*63f89caaSJens Wiklander #define ATTR_FMT_2BYTE	ATTR_TRACE_FMT ": %02x %02x)"
171*63f89caaSJens Wiklander #define ATTR_FMT_3BYTE	ATTR_TRACE_FMT ": %02x %02x %02x)"
172*63f89caaSJens Wiklander #define ATTR_FMT_4BYTE	ATTR_TRACE_FMT ": %02x %02x %02x %02x)"
173*63f89caaSJens Wiklander #define ATTR_FMT_ARRAY	ATTR_TRACE_FMT ": %02x %02x %02x %02x ...)"
174*63f89caaSJens Wiklander 
175*63f89caaSJens Wiklander static void __trace_attributes(char *prefix, void *src, void *end)
176*63f89caaSJens Wiklander {
177*63f89caaSJens Wiklander 	size_t next_off = 0;
178*63f89caaSJens Wiklander 	char *prefix2 = NULL;
179*63f89caaSJens Wiklander 	size_t prefix_len = strlen(prefix);
180*63f89caaSJens Wiklander 	char *cur = src;
181*63f89caaSJens Wiklander 
182*63f89caaSJens Wiklander 	/* append 4 spaces to the prefix plus terminal '\0' */
183*63f89caaSJens Wiklander 	prefix2 = TEE_Malloc(prefix_len + 1 + 4, TEE_MALLOC_FILL_ZERO);
184*63f89caaSJens Wiklander 	if (!prefix2)
185*63f89caaSJens Wiklander 		return;
186*63f89caaSJens Wiklander 
187*63f89caaSJens Wiklander 	TEE_MemMove(prefix2, prefix, prefix_len + 1);
188*63f89caaSJens Wiklander 	TEE_MemFill(prefix2 + prefix_len, ' ', 4);
189*63f89caaSJens Wiklander 	*(prefix2 + prefix_len + 4) = '\0';
190*63f89caaSJens Wiklander 
191*63f89caaSJens Wiklander 	for (; cur < (char *)end; cur += next_off) {
192*63f89caaSJens Wiklander 		struct pkcs11_attribute_head pkcs11_ref = { };
193*63f89caaSJens Wiklander 		uint8_t data[4] = { 0 };
194*63f89caaSJens Wiklander 
195*63f89caaSJens Wiklander 		TEE_MemMove(&pkcs11_ref, cur, sizeof(pkcs11_ref));
196*63f89caaSJens Wiklander 		TEE_MemMove(&data[0], cur + sizeof(pkcs11_ref),
197*63f89caaSJens Wiklander 			    MIN(pkcs11_ref.size, sizeof(data)));
198*63f89caaSJens Wiklander 
199*63f89caaSJens Wiklander 		next_off = sizeof(pkcs11_ref) + pkcs11_ref.size;
200*63f89caaSJens Wiklander 
201*63f89caaSJens Wiklander 		switch (pkcs11_ref.size) {
202*63f89caaSJens Wiklander 		case 0:
203*63f89caaSJens Wiklander 			IMSG_RAW(ATTR_FMT_0BYTE,
204*63f89caaSJens Wiklander 				 prefix, id2str_attr(pkcs11_ref.id), "*",
205*63f89caaSJens Wiklander 				 pkcs11_ref.id, pkcs11_ref.size);
206*63f89caaSJens Wiklander 			break;
207*63f89caaSJens Wiklander 		case 1:
208*63f89caaSJens Wiklander 			IMSG_RAW(ATTR_FMT_1BYTE,
209*63f89caaSJens Wiklander 				 prefix, id2str_attr(pkcs11_ref.id),
210*63f89caaSJens Wiklander 				 id2str_attr_value(pkcs11_ref.id,
211*63f89caaSJens Wiklander 						   pkcs11_ref.size,
212*63f89caaSJens Wiklander 						   cur + sizeof(pkcs11_ref)),
213*63f89caaSJens Wiklander 				 pkcs11_ref.id, pkcs11_ref.size, data[0]);
214*63f89caaSJens Wiklander 			break;
215*63f89caaSJens Wiklander 		case 2:
216*63f89caaSJens Wiklander 			IMSG_RAW(ATTR_FMT_2BYTE,
217*63f89caaSJens Wiklander 				 prefix, id2str_attr(pkcs11_ref.id),
218*63f89caaSJens Wiklander 				 id2str_attr_value(pkcs11_ref.id,
219*63f89caaSJens Wiklander 						   pkcs11_ref.size,
220*63f89caaSJens Wiklander 						   cur + sizeof(pkcs11_ref)),
221*63f89caaSJens Wiklander 				 pkcs11_ref.id, pkcs11_ref.size, data[0],
222*63f89caaSJens Wiklander 				 data[1]);
223*63f89caaSJens Wiklander 			break;
224*63f89caaSJens Wiklander 		case 3:
225*63f89caaSJens Wiklander 			IMSG_RAW(ATTR_FMT_3BYTE,
226*63f89caaSJens Wiklander 				 prefix, id2str_attr(pkcs11_ref.id),
227*63f89caaSJens Wiklander 				 id2str_attr_value(pkcs11_ref.id,
228*63f89caaSJens Wiklander 						   pkcs11_ref.size,
229*63f89caaSJens Wiklander 						   cur + sizeof(pkcs11_ref)),
230*63f89caaSJens Wiklander 				 pkcs11_ref.id, pkcs11_ref.size,
231*63f89caaSJens Wiklander 				 data[0], data[1], data[2]);
232*63f89caaSJens Wiklander 			break;
233*63f89caaSJens Wiklander 		case 4:
234*63f89caaSJens Wiklander 			IMSG_RAW(ATTR_FMT_4BYTE,
235*63f89caaSJens Wiklander 				 prefix, id2str_attr(pkcs11_ref.id),
236*63f89caaSJens Wiklander 				 id2str_attr_value(pkcs11_ref.id,
237*63f89caaSJens Wiklander 						   pkcs11_ref.size,
238*63f89caaSJens Wiklander 						   cur + sizeof(pkcs11_ref)),
239*63f89caaSJens Wiklander 				 pkcs11_ref.id, pkcs11_ref.size,
240*63f89caaSJens Wiklander 				 data[0], data[1], data[2], data[3]);
241*63f89caaSJens Wiklander 			break;
242*63f89caaSJens Wiklander 		default:
243*63f89caaSJens Wiklander 			IMSG_RAW(ATTR_FMT_ARRAY,
244*63f89caaSJens Wiklander 				 prefix, id2str_attr(pkcs11_ref.id),
245*63f89caaSJens Wiklander 				 id2str_attr_value(pkcs11_ref.id,
246*63f89caaSJens Wiklander 						   pkcs11_ref.size,
247*63f89caaSJens Wiklander 						   cur + sizeof(pkcs11_ref)),
248*63f89caaSJens Wiklander 				 pkcs11_ref.id, pkcs11_ref.size,
249*63f89caaSJens Wiklander 				 data[0], data[1], data[2], data[3]);
250*63f89caaSJens Wiklander 			break;
251*63f89caaSJens Wiklander 		}
252*63f89caaSJens Wiklander 
253*63f89caaSJens Wiklander 		switch (pkcs11_ref.id) {
254*63f89caaSJens Wiklander 		case PKCS11_CKA_WRAP_TEMPLATE:
255*63f89caaSJens Wiklander 		case PKCS11_CKA_UNWRAP_TEMPLATE:
256*63f89caaSJens Wiklander 		case PKCS11_CKA_DERIVE_TEMPLATE:
257*63f89caaSJens Wiklander 			trace_attributes(prefix2, cur + sizeof(pkcs11_ref));
258*63f89caaSJens Wiklander 			break;
259*63f89caaSJens Wiklander 		default:
260*63f89caaSJens Wiklander 			break;
261*63f89caaSJens Wiklander 		}
262*63f89caaSJens Wiklander 	}
263*63f89caaSJens Wiklander 
264*63f89caaSJens Wiklander 	/* Sanity */
265*63f89caaSJens Wiklander 	if (cur != end)
266*63f89caaSJens Wiklander 		EMSG("Warning: unexpected alignment in object attributes");
267*63f89caaSJens Wiklander 
268*63f89caaSJens Wiklander 	TEE_Free(prefix2);
269*63f89caaSJens Wiklander }
270*63f89caaSJens Wiklander 
271*63f89caaSJens Wiklander void trace_attributes(const char *prefix, void *ref)
272*63f89caaSJens Wiklander {
273*63f89caaSJens Wiklander 	struct obj_attrs head;
274*63f89caaSJens Wiklander 	char *pre = NULL;
275*63f89caaSJens Wiklander 
276*63f89caaSJens Wiklander 	TEE_MemMove(&head, ref, sizeof(head));
277*63f89caaSJens Wiklander 
278*63f89caaSJens Wiklander 	pre = TEE_Malloc(prefix ? strlen(prefix) + 2 : 2, TEE_MALLOC_FILL_ZERO);
279*63f89caaSJens Wiklander 	if (!pre) {
280*63f89caaSJens Wiklander 		EMSG("%s: out of memory", prefix);
281*63f89caaSJens Wiklander 		return;
282*63f89caaSJens Wiklander 	}
283*63f89caaSJens Wiklander 
284*63f89caaSJens Wiklander 	if (prefix)
285*63f89caaSJens Wiklander 		TEE_MemMove(pre, prefix, strlen(prefix));
286*63f89caaSJens Wiklander 
287*63f89caaSJens Wiklander 	IMSG_RAW("%s,--- (serial object) Attributes list --------", pre);
288*63f89caaSJens Wiklander 	IMSG_RAW("%s| %"PRIu32" item(s) - %"PRIu32" bytes",
289*63f89caaSJens Wiklander 		 pre, head.attrs_count, head.attrs_size);
290*63f89caaSJens Wiklander 
291*63f89caaSJens Wiklander 	pre[prefix ? strlen(prefix) : 0] = '|';
292*63f89caaSJens Wiklander 	__trace_attributes(pre, (char *)ref + sizeof(head),
293*63f89caaSJens Wiklander 			   (char *)ref + sizeof(head) + head.attrs_size);
294*63f89caaSJens Wiklander 
295*63f89caaSJens Wiklander 	IMSG_RAW("%s`-----------------------", prefix ? prefix : "");
296*63f89caaSJens Wiklander 
297*63f89caaSJens Wiklander 	TEE_Free(pre);
298*63f89caaSJens Wiklander }
299*63f89caaSJens Wiklander #endif /*CFG_TEE_TA_LOG_LEVEL*/
300