xref: /optee_os/ta/pkcs11/src/pkcs11_token.c (revision e084583eada41a648a9ff9195899489402415cc2)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2017-2020, Linaro Limited
4  */
5 
6 #include <assert.h>
7 #include <confine_array_index.h>
8 #include <pkcs11_ta.h>
9 #include <string.h>
10 #include <string_ext.h>
11 #include <sys/queue.h>
12 #include <tee_api_types.h>
13 #include <tee_internal_api_extensions.h>
14 #include <util.h>
15 
16 #include "pkcs11_token.h"
17 #include "pkcs11_helpers.h"
18 #include "serializer.h"
19 
20 /* Provide 3 slots/tokens, ID is token index */
21 #ifndef CFG_PKCS11_TA_TOKEN_COUNT
22 #define TOKEN_COUNT		3
23 #else
24 #define TOKEN_COUNT		CFG_PKCS11_TA_TOKEN_COUNT
25 #endif
26 
27 /*
28  * Structure tracking client applications
29  *
30  * @link - chained list of registered client applications
31  * @sessions - list of the PKCS11 sessions opened by the client application
32  */
33 struct pkcs11_client {
34 	TAILQ_ENTRY(pkcs11_client) link;
35 	struct session_list session_list;
36 	struct handle_db session_handle_db;
37 };
38 
39 /* Static allocation of tokens runtime instances (reset to 0 at load) */
40 struct ck_token ck_token[TOKEN_COUNT];
41 
42 static struct client_list pkcs11_client_list =
43 	TAILQ_HEAD_INITIALIZER(pkcs11_client_list);
44 
45 struct ck_token *get_token(unsigned int token_id)
46 {
47 	if (token_id < TOKEN_COUNT)
48 		return &ck_token[confine_array_index(token_id, TOKEN_COUNT)];
49 
50 	return NULL;
51 }
52 
53 unsigned int get_token_id(struct ck_token *token)
54 {
55 	ptrdiff_t id = token - ck_token;
56 
57 	assert(id >= 0 && id < TOKEN_COUNT);
58 	return id;
59 }
60 
61 struct pkcs11_client *tee_session2client(void *tee_session)
62 {
63 	struct pkcs11_client *client = NULL;
64 
65 	TAILQ_FOREACH(client, &pkcs11_client_list, link)
66 		if (client == tee_session)
67 			break;
68 
69 	return client;
70 }
71 
72 struct pkcs11_client *register_client(void)
73 {
74 	struct pkcs11_client *client = NULL;
75 
76 	client = TEE_Malloc(sizeof(*client), TEE_MALLOC_FILL_ZERO);
77 	if (!client)
78 		return NULL;
79 
80 	TAILQ_INSERT_HEAD(&pkcs11_client_list, client, link);
81 	TAILQ_INIT(&client->session_list);
82 	handle_db_init(&client->session_handle_db);
83 
84 	return client;
85 }
86 
87 void unregister_client(struct pkcs11_client *client)
88 {
89 	if (!client) {
90 		EMSG("Invalid TEE session handle");
91 		return;
92 	}
93 
94 	TAILQ_REMOVE(&pkcs11_client_list, client, link);
95 	handle_db_destroy(&client->session_handle_db);
96 	TEE_Free(client);
97 }
98 
99 static TEE_Result pkcs11_token_init(unsigned int id)
100 {
101 	struct ck_token *token = init_persistent_db(id);
102 
103 	if (!token)
104 		return TEE_ERROR_SECURITY;
105 
106 	if (token->state == PKCS11_TOKEN_RESET) {
107 		/* As per PKCS#11 spec, token resets to read/write state */
108 		token->state = PKCS11_TOKEN_READ_WRITE;
109 		token->session_count = 0;
110 		token->rw_session_count = 0;
111 	}
112 
113 	return TEE_SUCCESS;
114 }
115 
116 TEE_Result pkcs11_init(void)
117 {
118 	unsigned int id = 0;
119 	TEE_Result ret = TEE_ERROR_GENERIC;
120 
121 	for (id = 0; id < TOKEN_COUNT; id++) {
122 		ret = pkcs11_token_init(id);
123 		if (ret)
124 			break;
125 	}
126 
127 	return ret;
128 }
129 
130 void pkcs11_deinit(void)
131 {
132 	unsigned int id = 0;
133 
134 	for (id = 0; id < TOKEN_COUNT; id++)
135 		close_persistent_db(get_token(id));
136 }
137 
138 uint32_t entry_ck_slot_list(uint32_t ptypes, TEE_Param *params)
139 {
140 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
141 						TEE_PARAM_TYPE_NONE,
142 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
143 						TEE_PARAM_TYPE_NONE);
144 	TEE_Param *out = &params[2];
145 	uint32_t token_id = 0;
146 	const size_t out_size = sizeof(token_id) * TOKEN_COUNT;
147 	uint8_t *id = NULL;
148 
149 	if (ptypes != exp_pt ||
150 	    params[0].memref.size != TEE_PARAM0_SIZE_MIN)
151 		return PKCS11_CKR_ARGUMENTS_BAD;
152 
153 	if (out->memref.size < out_size) {
154 		out->memref.size = out_size;
155 
156 		if (out->memref.buffer)
157 			return PKCS11_CKR_BUFFER_TOO_SMALL;
158 		else
159 			return PKCS11_CKR_OK;
160 	}
161 
162 	for (token_id = 0, id = out->memref.buffer; token_id < TOKEN_COUNT;
163 	     token_id++, id += sizeof(token_id))
164 		TEE_MemMove(id, &token_id, sizeof(token_id));
165 
166 	out->memref.size = out_size;
167 
168 	return PKCS11_CKR_OK;
169 }
170 
171 static void pad_str(uint8_t *str, size_t size)
172 {
173 	int n = strnlen((char *)str, size);
174 
175 	TEE_MemFill(str + n, ' ', size - n);
176 }
177 
178 uint32_t entry_ck_slot_info(uint32_t ptypes, TEE_Param *params)
179 {
180 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
181 						TEE_PARAM_TYPE_NONE,
182 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
183 						TEE_PARAM_TYPE_NONE);
184 	TEE_Param *ctrl = &params[0];
185 	TEE_Param *out = &params[2];
186 	uint32_t rv = 0;
187 	struct serialargs ctrlargs = { };
188 	uint32_t token_id = 0;
189 	struct ck_token *token = NULL;
190 	struct pkcs11_slot_info info = {
191 		.slot_description = PKCS11_SLOT_DESCRIPTION,
192 		.manufacturer_id = PKCS11_SLOT_MANUFACTURER,
193 		.flags = PKCS11_CKFS_TOKEN_PRESENT,
194 		.hardware_version = PKCS11_SLOT_HW_VERSION,
195 		.firmware_version = PKCS11_SLOT_FW_VERSION,
196 	};
197 
198 	COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_DESCRIPTION) <=
199 			    sizeof(info.slot_description));
200 	COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_MANUFACTURER) <=
201 			    sizeof(info.manufacturer_id));
202 
203 	if (ptypes != exp_pt || out->memref.size != sizeof(info))
204 		return PKCS11_CKR_ARGUMENTS_BAD;
205 
206 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
207 
208 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(token_id));
209 	if (rv)
210 		return rv;
211 
212 	if (serialargs_remaining_bytes(&ctrlargs))
213 		return PKCS11_CKR_ARGUMENTS_BAD;
214 
215 	token = get_token(token_id);
216 	if (!token)
217 		return PKCS11_CKR_SLOT_ID_INVALID;
218 
219 	pad_str(info.slot_description, sizeof(info.slot_description));
220 	pad_str(info.manufacturer_id, sizeof(info.manufacturer_id));
221 
222 	out->memref.size = sizeof(info);
223 	TEE_MemMove(out->memref.buffer, &info, out->memref.size);
224 
225 	return PKCS11_CKR_OK;
226 }
227 
228 uint32_t entry_ck_token_info(uint32_t ptypes, TEE_Param *params)
229 {
230 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
231 						TEE_PARAM_TYPE_NONE,
232 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
233 						TEE_PARAM_TYPE_NONE);
234 	TEE_Param *ctrl = &params[0];
235 	TEE_Param *out = &params[2];
236 	uint32_t rv = 0;
237 	struct serialargs ctrlargs = { };
238 	uint32_t token_id = 0;
239 	struct ck_token *token = NULL;
240 	struct pkcs11_token_info info = {
241 		.manufacturer_id = PKCS11_TOKEN_MANUFACTURER,
242 		.model = PKCS11_TOKEN_MODEL,
243 		.serial_number = PKCS11_TOKEN_SERIAL_NUMBER,
244 		.max_session_count = UINT32_MAX,
245 		.max_rw_session_count = UINT32_MAX,
246 		.max_pin_len = PKCS11_TOKEN_PIN_SIZE_MAX,
247 		.min_pin_len = PKCS11_TOKEN_PIN_SIZE_MIN,
248 		.total_public_memory = UINT32_MAX,
249 		.free_public_memory = UINT32_MAX,
250 		.total_private_memory = UINT32_MAX,
251 		.free_private_memory = UINT32_MAX,
252 		.hardware_version = PKCS11_TOKEN_HW_VERSION,
253 		.firmware_version = PKCS11_TOKEN_FW_VERSION,
254 	};
255 
256 	if (ptypes != exp_pt || out->memref.size != sizeof(info))
257 		return PKCS11_CKR_ARGUMENTS_BAD;
258 
259 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
260 
261 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(token_id));
262 	if (rv)
263 		return rv;
264 
265 	if (serialargs_remaining_bytes(&ctrlargs))
266 		return PKCS11_CKR_ARGUMENTS_BAD;
267 
268 	token = get_token(token_id);
269 	if (!token)
270 		return PKCS11_CKR_SLOT_ID_INVALID;
271 
272 	pad_str(info.manufacturer_id, sizeof(info.manufacturer_id));
273 	pad_str(info.model, sizeof(info.model));
274 	pad_str(info.serial_number, sizeof(info.serial_number));
275 
276 	TEE_MemMove(info.label, token->db_main->label, sizeof(info.label));
277 
278 	info.flags = token->db_main->flags;
279 	info.session_count = token->session_count;
280 	info.rw_session_count = token->rw_session_count;
281 
282 	TEE_MemMove(out->memref.buffer, &info, sizeof(info));
283 
284 	return PKCS11_CKR_OK;
285 }
286 
287 static void dmsg_print_supported_mechanism(unsigned int token_id __maybe_unused,
288 					   uint32_t *array __maybe_unused,
289 					   size_t count __maybe_unused)
290 {
291 	size_t __maybe_unused n = 0;
292 
293 	if (TRACE_LEVEL < TRACE_DEBUG)
294 		return;
295 
296 	for (n = 0; n < count; n++)
297 		DMSG("PKCS11 token %"PRIu32": mechanism 0x%04"PRIx32": %s",
298 		     token_id, array[n], id2str_mechanism(array[n]));
299 }
300 
301 uint32_t entry_ck_token_mecha_ids(uint32_t ptypes, TEE_Param *params)
302 {
303 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
304 						TEE_PARAM_TYPE_NONE,
305 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
306 						TEE_PARAM_TYPE_NONE);
307 	TEE_Param *ctrl = &params[0];
308 	TEE_Param *out = &params[2];
309 	uint32_t rv = 0;
310 	struct serialargs ctrlargs = { };
311 	uint32_t token_id = 0;
312 	struct ck_token __maybe_unused *token = NULL;
313 	size_t count = 0;
314 	uint32_t *array = NULL;
315 
316 	if (ptypes != exp_pt)
317 		return PKCS11_CKR_ARGUMENTS_BAD;
318 
319 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
320 
321 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(token_id));
322 	if (rv)
323 		return rv;
324 
325 	if (serialargs_remaining_bytes(&ctrlargs))
326 		return PKCS11_CKR_ARGUMENTS_BAD;
327 
328 	token = get_token(token_id);
329 	if (!token)
330 		return PKCS11_CKR_SLOT_ID_INVALID;
331 
332 	count = out->memref.size / sizeof(*array);
333 	array = tee_malloc_mechanism_list(&count);
334 
335 	if (out->memref.size < count * sizeof(*array)) {
336 		assert(!array);
337 		out->memref.size = count * sizeof(*array);
338 		return PKCS11_CKR_BUFFER_TOO_SMALL;
339 	}
340 
341 	if (!array)
342 		return PKCS11_CKR_DEVICE_MEMORY;
343 
344 	dmsg_print_supported_mechanism(token_id, array, count);
345 
346 	out->memref.size = count * sizeof(*array);
347 	TEE_MemMove(out->memref.buffer, array, out->memref.size);
348 
349 	TEE_Free(array);
350 
351 	return rv;
352 }
353 
354 static void supported_mechanism_key_size(uint32_t proc_id,
355 					 uint32_t *max_key_size,
356 					 uint32_t *min_key_size)
357 {
358 	switch (proc_id) {
359 	/* Will be filled once TA supports mechanisms */
360 	default:
361 		*min_key_size = 0;
362 		*max_key_size = 0;
363 		break;
364 	}
365 }
366 
367 uint32_t entry_ck_token_mecha_info(uint32_t ptypes, TEE_Param *params)
368 {
369 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
370 						TEE_PARAM_TYPE_NONE,
371 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
372 						TEE_PARAM_TYPE_NONE);
373 	TEE_Param *ctrl = &params[0];
374 	TEE_Param *out = &params[2];
375 	uint32_t rv = 0;
376 	struct serialargs ctrlargs = { };
377 	uint32_t token_id = 0;
378 	uint32_t type = 0;
379 	struct ck_token *token = NULL;
380 	struct pkcs11_mechanism_info info = { };
381 
382 	if (ptypes != exp_pt || out->memref.size != sizeof(info))
383 		return PKCS11_CKR_ARGUMENTS_BAD;
384 
385 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
386 
387 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t));
388 	if (rv)
389 		return rv;
390 
391 	rv = serialargs_get(&ctrlargs, &type, sizeof(uint32_t));
392 	if (rv)
393 		return rv;
394 
395 	if (serialargs_remaining_bytes(&ctrlargs))
396 		return PKCS11_CKR_ARGUMENTS_BAD;
397 
398 	token = get_token(token_id);
399 	if (!token)
400 		return PKCS11_CKR_SLOT_ID_INVALID;
401 
402 	if (!mechanism_is_valid(type))
403 		return PKCS11_CKR_MECHANISM_INVALID;
404 
405 	info.flags = mechanism_supported_flags(type);
406 
407 	supported_mechanism_key_size(type, &info.min_key_size,
408 				     &info.max_key_size);
409 
410 	TEE_MemMove(out->memref.buffer, &info, sizeof(info));
411 
412 	DMSG("PKCS11 token %"PRIu32": mechanism 0x%"PRIx32" info",
413 	     token_id, type);
414 
415 	return PKCS11_CKR_OK;
416 }
417