1c84ccd0aSEtienne Carriere // SPDX-License-Identifier: BSD-2-Clause
2c84ccd0aSEtienne Carriere /*
3c84ccd0aSEtienne Carriere * Copyright (c) 2017-2020, Linaro Limited
4c84ccd0aSEtienne Carriere */
5c84ccd0aSEtienne Carriere
6c84ccd0aSEtienne Carriere #include <assert.h>
71a27b197SVesa Jääskeläinen #include <config.h>
8d38f9635SEtienne Carriere #include <confine_array_index.h>
9c84ccd0aSEtienne Carriere #include <pkcs11_ta.h>
10d628ebd9SEtienne Carriere #include <printk.h>
1122587dc4SVesa Jääskeläinen #include <pta_system.h>
12c84ccd0aSEtienne Carriere #include <string.h>
13c84ccd0aSEtienne Carriere #include <string_ext.h>
14c84ccd0aSEtienne Carriere #include <sys/queue.h>
15c84ccd0aSEtienne Carriere #include <tee_api_types.h>
16c84ccd0aSEtienne Carriere #include <tee_internal_api_extensions.h>
17c84ccd0aSEtienne Carriere #include <util.h>
18c84ccd0aSEtienne Carriere
19512cbf1dSJens Wiklander #include "attributes.h"
2049443fc0SEtienne Carriere #include "handle.h"
21c84ccd0aSEtienne Carriere #include "pkcs11_helpers.h"
22ee49d9f2SEtienne Carriere #include "pkcs11_token.h"
2355e6965cSEtienne Carriere #include "processing.h"
2422ac6984SEtienne Carriere #include "serializer.h"
2549443fc0SEtienne Carriere #include "token_capabilities.h"
26c84ccd0aSEtienne Carriere
27edce8377SEtienne Carriere /* Number of tokens implemented by the TA. Token ID is the token index */
28c84ccd0aSEtienne Carriere #define TOKEN_COUNT CFG_PKCS11_TA_TOKEN_COUNT
29c84ccd0aSEtienne Carriere
3022587dc4SVesa Jääskeläinen /* RNG chunk size used to split RNG generation to smaller sizes */
3122587dc4SVesa Jääskeläinen #define RNG_CHUNK_SIZE 512U
3222587dc4SVesa Jääskeläinen
33e084583eSEtienne Carriere /*
34e084583eSEtienne Carriere * Structure tracking client applications
35e084583eSEtienne Carriere *
36e084583eSEtienne Carriere * @link - chained list of registered client applications
37e084583eSEtienne Carriere * @sessions - list of the PKCS11 sessions opened by the client application
38bc555ee0SVesa Jääskeläinen * @object_handle_db - Database for object handles in name space of client
39e084583eSEtienne Carriere */
40e084583eSEtienne Carriere struct pkcs11_client {
41e084583eSEtienne Carriere TAILQ_ENTRY(pkcs11_client) link;
42e084583eSEtienne Carriere struct session_list session_list;
43e084583eSEtienne Carriere struct handle_db session_handle_db;
44bc555ee0SVesa Jääskeläinen struct handle_db object_handle_db;
45e084583eSEtienne Carriere };
46e084583eSEtienne Carriere
47c84ccd0aSEtienne Carriere /* Static allocation of tokens runtime instances (reset to 0 at load) */
48c84ccd0aSEtienne Carriere struct ck_token ck_token[TOKEN_COUNT];
49c84ccd0aSEtienne Carriere
50e084583eSEtienne Carriere static struct client_list pkcs11_client_list =
51e084583eSEtienne Carriere TAILQ_HEAD_INITIALIZER(pkcs11_client_list);
52e084583eSEtienne Carriere
536e4f8f17SEtienne Carriere static void close_ck_session(struct pkcs11_session *session);
546e4f8f17SEtienne Carriere
get_token(unsigned int token_id)55c84ccd0aSEtienne Carriere struct ck_token *get_token(unsigned int token_id)
56c84ccd0aSEtienne Carriere {
57d38f9635SEtienne Carriere if (token_id < TOKEN_COUNT)
58d38f9635SEtienne Carriere return &ck_token[confine_array_index(token_id, TOKEN_COUNT)];
59c84ccd0aSEtienne Carriere
60d38f9635SEtienne Carriere return NULL;
61c84ccd0aSEtienne Carriere }
62c84ccd0aSEtienne Carriere
get_token_id(struct ck_token * token)63c84ccd0aSEtienne Carriere unsigned int get_token_id(struct ck_token *token)
64c84ccd0aSEtienne Carriere {
65c84ccd0aSEtienne Carriere ptrdiff_t id = token - ck_token;
66c84ccd0aSEtienne Carriere
67c84ccd0aSEtienne Carriere assert(id >= 0 && id < TOKEN_COUNT);
68c84ccd0aSEtienne Carriere return id;
69c84ccd0aSEtienne Carriere }
70c84ccd0aSEtienne Carriere
get_object_handle_db(struct pkcs11_session * session)71bc555ee0SVesa Jääskeläinen struct handle_db *get_object_handle_db(struct pkcs11_session *session)
72bc555ee0SVesa Jääskeläinen {
73bc555ee0SVesa Jääskeläinen return &session->client->object_handle_db;
74bc555ee0SVesa Jääskeläinen }
75bc555ee0SVesa Jääskeläinen
get_session_list(struct pkcs11_session * session)76bc555ee0SVesa Jääskeläinen struct session_list *get_session_list(struct pkcs11_session *session)
77bc555ee0SVesa Jääskeläinen {
78bc555ee0SVesa Jääskeläinen return &session->client->session_list;
79bc555ee0SVesa Jääskeläinen }
80bc555ee0SVesa Jääskeläinen
tee_session2client(void * tee_session)81e084583eSEtienne Carriere struct pkcs11_client *tee_session2client(void *tee_session)
82e084583eSEtienne Carriere {
83e084583eSEtienne Carriere struct pkcs11_client *client = NULL;
84e084583eSEtienne Carriere
85e084583eSEtienne Carriere TAILQ_FOREACH(client, &pkcs11_client_list, link)
86e084583eSEtienne Carriere if (client == tee_session)
87e084583eSEtienne Carriere break;
88e084583eSEtienne Carriere
89e084583eSEtienne Carriere return client;
90e084583eSEtienne Carriere }
91e084583eSEtienne Carriere
pkcs11_handle2session(uint32_t handle,struct pkcs11_client * client)926e4f8f17SEtienne Carriere struct pkcs11_session *pkcs11_handle2session(uint32_t handle,
936e4f8f17SEtienne Carriere struct pkcs11_client *client)
946e4f8f17SEtienne Carriere {
956e4f8f17SEtienne Carriere return handle_lookup(&client->session_handle_db, handle);
966e4f8f17SEtienne Carriere }
976e4f8f17SEtienne Carriere
token_invalidate_object_handles(struct pkcs11_object * obj)98bb5d1825SEtienne Carriere void token_invalidate_object_handles(struct pkcs11_object *obj)
99bb5d1825SEtienne Carriere {
100bb5d1825SEtienne Carriere struct pkcs11_client *client = NULL;
101bb5d1825SEtienne Carriere uint32_t handle = 0;
102bb5d1825SEtienne Carriere
103bb5d1825SEtienne Carriere TAILQ_FOREACH(client, &pkcs11_client_list, link) {
104bb5d1825SEtienne Carriere handle = handle_lookup_handle(&client->object_handle_db, obj);
105bb5d1825SEtienne Carriere if (handle)
106bb5d1825SEtienne Carriere handle_invalidate(&client->object_handle_db, handle);
107bb5d1825SEtienne Carriere }
108bb5d1825SEtienne Carriere }
109bb5d1825SEtienne Carriere
register_client(void)110e084583eSEtienne Carriere struct pkcs11_client *register_client(void)
111e084583eSEtienne Carriere {
112e084583eSEtienne Carriere struct pkcs11_client *client = NULL;
113e084583eSEtienne Carriere
114e084583eSEtienne Carriere client = TEE_Malloc(sizeof(*client), TEE_MALLOC_FILL_ZERO);
115e084583eSEtienne Carriere if (!client)
116e084583eSEtienne Carriere return NULL;
117e084583eSEtienne Carriere
118e084583eSEtienne Carriere TAILQ_INSERT_HEAD(&pkcs11_client_list, client, link);
119e084583eSEtienne Carriere TAILQ_INIT(&client->session_list);
120e084583eSEtienne Carriere handle_db_init(&client->session_handle_db);
121bc555ee0SVesa Jääskeläinen handle_db_init(&client->object_handle_db);
122e084583eSEtienne Carriere
123e084583eSEtienne Carriere return client;
124e084583eSEtienne Carriere }
125e084583eSEtienne Carriere
unregister_client(struct pkcs11_client * client)126e084583eSEtienne Carriere void unregister_client(struct pkcs11_client *client)
127e084583eSEtienne Carriere {
1286e4f8f17SEtienne Carriere struct pkcs11_session *session = NULL;
1296e4f8f17SEtienne Carriere struct pkcs11_session *next = NULL;
1306e4f8f17SEtienne Carriere
131e084583eSEtienne Carriere if (!client) {
132e084583eSEtienne Carriere EMSG("Invalid TEE session handle");
133e084583eSEtienne Carriere return;
134e084583eSEtienne Carriere }
135e084583eSEtienne Carriere
1366e4f8f17SEtienne Carriere TAILQ_FOREACH_SAFE(session, &client->session_list, link, next)
1376e4f8f17SEtienne Carriere close_ck_session(session);
1386e4f8f17SEtienne Carriere
139e084583eSEtienne Carriere TAILQ_REMOVE(&pkcs11_client_list, client, link);
140bc555ee0SVesa Jääskeläinen handle_db_destroy(&client->object_handle_db);
141e084583eSEtienne Carriere handle_db_destroy(&client->session_handle_db);
142e084583eSEtienne Carriere TEE_Free(client);
143e084583eSEtienne Carriere }
144e084583eSEtienne Carriere
pkcs11_token_init(unsigned int id)145c84ccd0aSEtienne Carriere static TEE_Result pkcs11_token_init(unsigned int id)
146c84ccd0aSEtienne Carriere {
147c84ccd0aSEtienne Carriere struct ck_token *token = init_persistent_db(id);
148c84ccd0aSEtienne Carriere
149c84ccd0aSEtienne Carriere if (!token)
150c84ccd0aSEtienne Carriere return TEE_ERROR_SECURITY;
151c84ccd0aSEtienne Carriere
152c84ccd0aSEtienne Carriere if (token->state == PKCS11_TOKEN_RESET) {
153c84ccd0aSEtienne Carriere /* As per PKCS#11 spec, token resets to read/write state */
154c84ccd0aSEtienne Carriere token->state = PKCS11_TOKEN_READ_WRITE;
155c84ccd0aSEtienne Carriere token->session_count = 0;
156c84ccd0aSEtienne Carriere token->rw_session_count = 0;
157c84ccd0aSEtienne Carriere }
158c84ccd0aSEtienne Carriere
159c84ccd0aSEtienne Carriere return TEE_SUCCESS;
160c84ccd0aSEtienne Carriere }
161c84ccd0aSEtienne Carriere
pkcs11_init(void)162c84ccd0aSEtienne Carriere TEE_Result pkcs11_init(void)
163c84ccd0aSEtienne Carriere {
164c84ccd0aSEtienne Carriere unsigned int id = 0;
165c84ccd0aSEtienne Carriere TEE_Result ret = TEE_ERROR_GENERIC;
166c84ccd0aSEtienne Carriere
167c84ccd0aSEtienne Carriere for (id = 0; id < TOKEN_COUNT; id++) {
168c84ccd0aSEtienne Carriere ret = pkcs11_token_init(id);
169c84ccd0aSEtienne Carriere if (ret)
170e084583eSEtienne Carriere break;
171c84ccd0aSEtienne Carriere }
172c84ccd0aSEtienne Carriere
173c84ccd0aSEtienne Carriere return ret;
174c84ccd0aSEtienne Carriere }
175c84ccd0aSEtienne Carriere
pkcs11_deinit(void)176c84ccd0aSEtienne Carriere void pkcs11_deinit(void)
177c84ccd0aSEtienne Carriere {
178c84ccd0aSEtienne Carriere unsigned int id = 0;
179c84ccd0aSEtienne Carriere
180c84ccd0aSEtienne Carriere for (id = 0; id < TOKEN_COUNT; id++)
181c84ccd0aSEtienne Carriere close_persistent_db(get_token(id));
182c84ccd0aSEtienne Carriere }
18322ac6984SEtienne Carriere
184512cbf1dSJens Wiklander /*
185512cbf1dSJens Wiklander * Currently no support for dual operations.
186512cbf1dSJens Wiklander */
set_processing_state(struct pkcs11_session * session,enum processing_func function,struct pkcs11_object * obj1,struct pkcs11_object * obj2)187512cbf1dSJens Wiklander enum pkcs11_rc set_processing_state(struct pkcs11_session *session,
188512cbf1dSJens Wiklander enum processing_func function,
189512cbf1dSJens Wiklander struct pkcs11_object *obj1,
190512cbf1dSJens Wiklander struct pkcs11_object *obj2)
191512cbf1dSJens Wiklander {
192512cbf1dSJens Wiklander enum pkcs11_proc_state state = PKCS11_SESSION_READY;
193512cbf1dSJens Wiklander struct active_processing *proc = NULL;
194512cbf1dSJens Wiklander
195512cbf1dSJens Wiklander if (session->processing)
196512cbf1dSJens Wiklander return PKCS11_CKR_OPERATION_ACTIVE;
197512cbf1dSJens Wiklander
198512cbf1dSJens Wiklander switch (function) {
199512cbf1dSJens Wiklander case PKCS11_FUNCTION_ENCRYPT:
200512cbf1dSJens Wiklander state = PKCS11_SESSION_ENCRYPTING;
201512cbf1dSJens Wiklander break;
202512cbf1dSJens Wiklander case PKCS11_FUNCTION_DECRYPT:
203512cbf1dSJens Wiklander state = PKCS11_SESSION_DECRYPTING;
204512cbf1dSJens Wiklander break;
205512cbf1dSJens Wiklander case PKCS11_FUNCTION_SIGN:
206512cbf1dSJens Wiklander state = PKCS11_SESSION_SIGNING;
207512cbf1dSJens Wiklander break;
208512cbf1dSJens Wiklander case PKCS11_FUNCTION_VERIFY:
209512cbf1dSJens Wiklander state = PKCS11_SESSION_VERIFYING;
210512cbf1dSJens Wiklander break;
211512cbf1dSJens Wiklander case PKCS11_FUNCTION_DIGEST:
212512cbf1dSJens Wiklander state = PKCS11_SESSION_DIGESTING;
213512cbf1dSJens Wiklander break;
214512cbf1dSJens Wiklander case PKCS11_FUNCTION_DERIVE:
2155f80f270SRuchika Gupta case PKCS11_FUNCTION_WRAP:
2165f80f270SRuchika Gupta case PKCS11_FUNCTION_UNWRAP:
2175f80f270SRuchika Gupta state = PKCS11_SESSION_BUSY;
218512cbf1dSJens Wiklander break;
219512cbf1dSJens Wiklander default:
220512cbf1dSJens Wiklander TEE_Panic(function);
221512cbf1dSJens Wiklander return -1;
222512cbf1dSJens Wiklander }
223512cbf1dSJens Wiklander
224512cbf1dSJens Wiklander proc = TEE_Malloc(sizeof(*proc), TEE_MALLOC_FILL_ZERO);
225512cbf1dSJens Wiklander if (!proc)
226512cbf1dSJens Wiklander return PKCS11_CKR_DEVICE_MEMORY;
227512cbf1dSJens Wiklander
228512cbf1dSJens Wiklander /* Boolean are default to false and pointers to NULL */
229512cbf1dSJens Wiklander proc->state = state;
2302364aa69SRuchika Gupta proc->step = PKCS11_FUNC_STEP_INIT;
231512cbf1dSJens Wiklander proc->tee_op_handle = TEE_HANDLE_NULL;
232fb279d8bSVesa Jääskeläinen proc->tee_hash_algo = 0;
233*571857c0SEtienne Carriere proc->tee_op_handle2 = TEE_HANDLE_NULL;
234512cbf1dSJens Wiklander
235512cbf1dSJens Wiklander if (obj1 && get_bool(obj1->attributes, PKCS11_CKA_ALWAYS_AUTHENTICATE))
236512cbf1dSJens Wiklander proc->always_authen = true;
237512cbf1dSJens Wiklander
238512cbf1dSJens Wiklander if (obj2 && get_bool(obj2->attributes, PKCS11_CKA_ALWAYS_AUTHENTICATE))
239512cbf1dSJens Wiklander proc->always_authen = true;
240512cbf1dSJens Wiklander
241512cbf1dSJens Wiklander session->processing = proc;
242512cbf1dSJens Wiklander
243512cbf1dSJens Wiklander return PKCS11_CKR_OK;
244512cbf1dSJens Wiklander }
245512cbf1dSJens Wiklander
entry_ck_slot_list(uint32_t ptypes,TEE_Param * params)2464daf39b3SJens Wiklander enum pkcs11_rc entry_ck_slot_list(uint32_t ptypes, TEE_Param *params)
24722ac6984SEtienne Carriere {
24822ac6984SEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
24922ac6984SEtienne Carriere TEE_PARAM_TYPE_NONE,
25022ac6984SEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT,
25122ac6984SEtienne Carriere TEE_PARAM_TYPE_NONE);
25239b43b78SJens Wiklander TEE_Param *out = params + 2;
25322ac6984SEtienne Carriere uint32_t token_id = 0;
25422ac6984SEtienne Carriere const size_t out_size = sizeof(token_id) * TOKEN_COUNT;
25522ac6984SEtienne Carriere uint8_t *id = NULL;
25622ac6984SEtienne Carriere
25722ac6984SEtienne Carriere if (ptypes != exp_pt ||
25822ac6984SEtienne Carriere params[0].memref.size != TEE_PARAM0_SIZE_MIN)
25922ac6984SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD;
26022ac6984SEtienne Carriere
26122ac6984SEtienne Carriere if (out->memref.size < out_size) {
26222ac6984SEtienne Carriere out->memref.size = out_size;
26322ac6984SEtienne Carriere
26422ac6984SEtienne Carriere if (out->memref.buffer)
26522ac6984SEtienne Carriere return PKCS11_CKR_BUFFER_TOO_SMALL;
26622ac6984SEtienne Carriere else
26722ac6984SEtienne Carriere return PKCS11_CKR_OK;
26822ac6984SEtienne Carriere }
26922ac6984SEtienne Carriere
27022ac6984SEtienne Carriere for (token_id = 0, id = out->memref.buffer; token_id < TOKEN_COUNT;
27122ac6984SEtienne Carriere token_id++, id += sizeof(token_id))
27222ac6984SEtienne Carriere TEE_MemMove(id, &token_id, sizeof(token_id));
27322ac6984SEtienne Carriere
27422ac6984SEtienne Carriere out->memref.size = out_size;
27522ac6984SEtienne Carriere
27622ac6984SEtienne Carriere return PKCS11_CKR_OK;
27722ac6984SEtienne Carriere }
278ce94efefSEtienne Carriere
pad_str(uint8_t * str,size_t size)279b3ac5035SEtienne Carriere static void pad_str(uint8_t *str, size_t size)
280b3ac5035SEtienne Carriere {
281b3ac5035SEtienne Carriere int n = strnlen((char *)str, size);
282b3ac5035SEtienne Carriere
283b3ac5035SEtienne Carriere TEE_MemFill(str + n, ' ', size - n);
284b3ac5035SEtienne Carriere }
285b3ac5035SEtienne Carriere
set_token_description(struct pkcs11_slot_info * info)286d628ebd9SEtienne Carriere static void set_token_description(struct pkcs11_slot_info *info)
287d628ebd9SEtienne Carriere {
288d628ebd9SEtienne Carriere char desc[sizeof(info->slot_description) + 1] = { 0 };
289d628ebd9SEtienne Carriere TEE_UUID dev_id = { };
290d628ebd9SEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC;
291d628ebd9SEtienne Carriere int n = 0;
292d628ebd9SEtienne Carriere
293d628ebd9SEtienne Carriere res = TEE_GetPropertyAsUUID(TEE_PROPSET_TEE_IMPLEMENTATION,
294d628ebd9SEtienne Carriere "gpd.tee.deviceID", &dev_id);
295d628ebd9SEtienne Carriere if (res == TEE_SUCCESS) {
296d628ebd9SEtienne Carriere n = snprintk(desc, sizeof(desc), PKCS11_SLOT_DESCRIPTION
297d628ebd9SEtienne Carriere " - TEE UUID %pUl", (void *)&dev_id);
298d628ebd9SEtienne Carriere } else {
299d628ebd9SEtienne Carriere n = snprintf(desc, sizeof(desc), PKCS11_SLOT_DESCRIPTION
300d628ebd9SEtienne Carriere " - No TEE UUID");
301d628ebd9SEtienne Carriere }
302d628ebd9SEtienne Carriere if (n < 0 || n >= (int)sizeof(desc))
303d628ebd9SEtienne Carriere TEE_Panic(0);
304d628ebd9SEtienne Carriere
305d628ebd9SEtienne Carriere TEE_MemMove(info->slot_description, desc, n);
306d628ebd9SEtienne Carriere pad_str(info->slot_description, sizeof(info->slot_description));
307d628ebd9SEtienne Carriere }
308d628ebd9SEtienne Carriere
entry_ck_slot_info(uint32_t ptypes,TEE_Param * params)3094daf39b3SJens Wiklander enum pkcs11_rc entry_ck_slot_info(uint32_t ptypes, TEE_Param *params)
310ce94efefSEtienne Carriere {
311ce94efefSEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
312ce94efefSEtienne Carriere TEE_PARAM_TYPE_NONE,
313ce94efefSEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT,
314ce94efefSEtienne Carriere TEE_PARAM_TYPE_NONE);
31539b43b78SJens Wiklander TEE_Param *ctrl = params;
31639b43b78SJens Wiklander TEE_Param *out = params + 2;
3174daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
318ce94efefSEtienne Carriere struct serialargs ctrlargs = { };
319ce94efefSEtienne Carriere uint32_t token_id = 0;
320ce94efefSEtienne Carriere struct pkcs11_slot_info info = {
321ce94efefSEtienne Carriere .slot_description = PKCS11_SLOT_DESCRIPTION,
322ce94efefSEtienne Carriere .manufacturer_id = PKCS11_SLOT_MANUFACTURER,
323ce94efefSEtienne Carriere .flags = PKCS11_CKFS_TOKEN_PRESENT,
324ce94efefSEtienne Carriere .hardware_version = PKCS11_SLOT_HW_VERSION,
325ce94efefSEtienne Carriere .firmware_version = PKCS11_SLOT_FW_VERSION,
326ce94efefSEtienne Carriere };
327ce94efefSEtienne Carriere
328ce94efefSEtienne Carriere COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_DESCRIPTION) <=
329ce94efefSEtienne Carriere sizeof(info.slot_description));
330ce94efefSEtienne Carriere COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_MANUFACTURER) <=
331ce94efefSEtienne Carriere sizeof(info.manufacturer_id));
332ce94efefSEtienne Carriere
333ce94efefSEtienne Carriere if (ptypes != exp_pt || out->memref.size != sizeof(info))
334ce94efefSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD;
335ce94efefSEtienne Carriere
336ce94efefSEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
337ce94efefSEtienne Carriere
3384daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &token_id, sizeof(token_id));
3394daf39b3SJens Wiklander if (rc)
3404daf39b3SJens Wiklander return rc;
341ce94efefSEtienne Carriere
342ce94efefSEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs))
343ce94efefSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD;
344ce94efefSEtienne Carriere
34529b0949aSEtienne Carriere if (!get_token(token_id))
346ce94efefSEtienne Carriere return PKCS11_CKR_SLOT_ID_INVALID;
347ce94efefSEtienne Carriere
348d628ebd9SEtienne Carriere set_token_description(&info);
349d628ebd9SEtienne Carriere
350b3ac5035SEtienne Carriere pad_str(info.manufacturer_id, sizeof(info.manufacturer_id));
351ce94efefSEtienne Carriere
352ce94efefSEtienne Carriere out->memref.size = sizeof(info);
353ce94efefSEtienne Carriere TEE_MemMove(out->memref.buffer, &info, out->memref.size);
354ce94efefSEtienne Carriere
355ce94efefSEtienne Carriere return PKCS11_CKR_OK;
356ce94efefSEtienne Carriere }
357030e7392SEtienne Carriere
entry_ck_token_info(uint32_t ptypes,TEE_Param * params)3584daf39b3SJens Wiklander enum pkcs11_rc entry_ck_token_info(uint32_t ptypes, TEE_Param *params)
359030e7392SEtienne Carriere {
360030e7392SEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
361030e7392SEtienne Carriere TEE_PARAM_TYPE_NONE,
362030e7392SEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT,
363030e7392SEtienne Carriere TEE_PARAM_TYPE_NONE);
36439b43b78SJens Wiklander TEE_Param *ctrl = params;
36539b43b78SJens Wiklander TEE_Param *out = params + 2;
3664daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
367030e7392SEtienne Carriere struct serialargs ctrlargs = { };
368030e7392SEtienne Carriere uint32_t token_id = 0;
369030e7392SEtienne Carriere struct ck_token *token = NULL;
370030e7392SEtienne Carriere struct pkcs11_token_info info = {
371030e7392SEtienne Carriere .manufacturer_id = PKCS11_TOKEN_MANUFACTURER,
372030e7392SEtienne Carriere .model = PKCS11_TOKEN_MODEL,
373030e7392SEtienne Carriere .max_session_count = UINT32_MAX,
374030e7392SEtienne Carriere .max_rw_session_count = UINT32_MAX,
375030e7392SEtienne Carriere .max_pin_len = PKCS11_TOKEN_PIN_SIZE_MAX,
376030e7392SEtienne Carriere .min_pin_len = PKCS11_TOKEN_PIN_SIZE_MIN,
377030e7392SEtienne Carriere .total_public_memory = UINT32_MAX,
378030e7392SEtienne Carriere .free_public_memory = UINT32_MAX,
379030e7392SEtienne Carriere .total_private_memory = UINT32_MAX,
380030e7392SEtienne Carriere .free_private_memory = UINT32_MAX,
381030e7392SEtienne Carriere .hardware_version = PKCS11_TOKEN_HW_VERSION,
382030e7392SEtienne Carriere .firmware_version = PKCS11_TOKEN_FW_VERSION,
383030e7392SEtienne Carriere };
38402b4d42aSEtienne Carriere char sn[sizeof(info.serial_number) + 1] = { 0 };
38502b4d42aSEtienne Carriere int n = 0;
386030e7392SEtienne Carriere
387030e7392SEtienne Carriere if (ptypes != exp_pt || out->memref.size != sizeof(info))
388030e7392SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD;
389030e7392SEtienne Carriere
390030e7392SEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
391030e7392SEtienne Carriere
3924daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &token_id, sizeof(token_id));
3934daf39b3SJens Wiklander if (rc)
3944daf39b3SJens Wiklander return rc;
395030e7392SEtienne Carriere
396030e7392SEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs))
397030e7392SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD;
398030e7392SEtienne Carriere
399030e7392SEtienne Carriere token = get_token(token_id);
400030e7392SEtienne Carriere if (!token)
401030e7392SEtienne Carriere return PKCS11_CKR_SLOT_ID_INVALID;
402030e7392SEtienne Carriere
403030e7392SEtienne Carriere pad_str(info.manufacturer_id, sizeof(info.manufacturer_id));
404030e7392SEtienne Carriere pad_str(info.model, sizeof(info.model));
40502b4d42aSEtienne Carriere
40602b4d42aSEtienne Carriere n = snprintf(sn, sizeof(sn), "%0*"PRIu32,
40702b4d42aSEtienne Carriere (int)sizeof(info.serial_number), token_id);
40802b4d42aSEtienne Carriere if (n != (int)sizeof(info.serial_number))
40902b4d42aSEtienne Carriere TEE_Panic(0);
41002b4d42aSEtienne Carriere
41102b4d42aSEtienne Carriere TEE_MemMove(info.serial_number, sn, sizeof(info.serial_number));
412030e7392SEtienne Carriere pad_str(info.serial_number, sizeof(info.serial_number));
413030e7392SEtienne Carriere
414030e7392SEtienne Carriere TEE_MemMove(info.label, token->db_main->label, sizeof(info.label));
415030e7392SEtienne Carriere
416030e7392SEtienne Carriere info.flags = token->db_main->flags;
417030e7392SEtienne Carriere info.session_count = token->session_count;
418030e7392SEtienne Carriere info.rw_session_count = token->rw_session_count;
419030e7392SEtienne Carriere
420030e7392SEtienne Carriere TEE_MemMove(out->memref.buffer, &info, sizeof(info));
421030e7392SEtienne Carriere
422030e7392SEtienne Carriere return PKCS11_CKR_OK;
423030e7392SEtienne Carriere }
4246f74919dSEtienne Carriere
dmsg_print_supported_mechanism(unsigned int token_id __maybe_unused,uint32_t * array __maybe_unused,size_t count __maybe_unused)4256f74919dSEtienne Carriere static void dmsg_print_supported_mechanism(unsigned int token_id __maybe_unused,
4266f74919dSEtienne Carriere uint32_t *array __maybe_unused,
4276f74919dSEtienne Carriere size_t count __maybe_unused)
4286f74919dSEtienne Carriere {
4296f74919dSEtienne Carriere size_t __maybe_unused n = 0;
4306f74919dSEtienne Carriere
4316f74919dSEtienne Carriere if (TRACE_LEVEL < TRACE_DEBUG)
4326f74919dSEtienne Carriere return;
4336f74919dSEtienne Carriere
4346f74919dSEtienne Carriere for (n = 0; n < count; n++)
4356f74919dSEtienne Carriere DMSG("PKCS11 token %"PRIu32": mechanism 0x%04"PRIx32": %s",
4366f74919dSEtienne Carriere token_id, array[n], id2str_mechanism(array[n]));
4376f74919dSEtienne Carriere }
4386f74919dSEtienne Carriere
entry_ck_token_mecha_ids(uint32_t ptypes,TEE_Param * params)4394daf39b3SJens Wiklander enum pkcs11_rc entry_ck_token_mecha_ids(uint32_t ptypes, TEE_Param *params)
4406f74919dSEtienne Carriere {
4416f74919dSEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
4426f74919dSEtienne Carriere TEE_PARAM_TYPE_NONE,
4436f74919dSEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT,
4446f74919dSEtienne Carriere TEE_PARAM_TYPE_NONE);
44539b43b78SJens Wiklander TEE_Param *ctrl = params;
44639b43b78SJens Wiklander TEE_Param *out = params + 2;
4474daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
4486f74919dSEtienne Carriere struct serialargs ctrlargs = { };
4496f74919dSEtienne Carriere uint32_t token_id = 0;
4506f74919dSEtienne Carriere struct ck_token __maybe_unused *token = NULL;
4516f74919dSEtienne Carriere size_t count = 0;
4526f74919dSEtienne Carriere uint32_t *array = NULL;
4536f74919dSEtienne Carriere
4546f74919dSEtienne Carriere if (ptypes != exp_pt)
4556f74919dSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD;
4566f74919dSEtienne Carriere
4576f74919dSEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
4586f74919dSEtienne Carriere
4594daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &token_id, sizeof(token_id));
4604daf39b3SJens Wiklander if (rc)
4614daf39b3SJens Wiklander return rc;
4626f74919dSEtienne Carriere
4636f74919dSEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs))
4646f74919dSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD;
4656f74919dSEtienne Carriere
4666f74919dSEtienne Carriere token = get_token(token_id);
4676f74919dSEtienne Carriere if (!token)
4686f74919dSEtienne Carriere return PKCS11_CKR_SLOT_ID_INVALID;
4696f74919dSEtienne Carriere
4706f74919dSEtienne Carriere count = out->memref.size / sizeof(*array);
4716f74919dSEtienne Carriere array = tee_malloc_mechanism_list(&count);
4726f74919dSEtienne Carriere
4736f74919dSEtienne Carriere if (out->memref.size < count * sizeof(*array)) {
4746f74919dSEtienne Carriere assert(!array);
4756f74919dSEtienne Carriere out->memref.size = count * sizeof(*array);
4766459f267SEtienne Carriere if (out->memref.buffer)
4776f74919dSEtienne Carriere return PKCS11_CKR_BUFFER_TOO_SMALL;
4786459f267SEtienne Carriere else
4796459f267SEtienne Carriere return PKCS11_CKR_OK;
4806f74919dSEtienne Carriere }
4816f74919dSEtienne Carriere
4826f74919dSEtienne Carriere if (!array)
4836f74919dSEtienne Carriere return PKCS11_CKR_DEVICE_MEMORY;
4846f74919dSEtienne Carriere
4856f74919dSEtienne Carriere dmsg_print_supported_mechanism(token_id, array, count);
4866f74919dSEtienne Carriere
4876f74919dSEtienne Carriere out->memref.size = count * sizeof(*array);
4886f74919dSEtienne Carriere TEE_MemMove(out->memref.buffer, array, out->memref.size);
4896f74919dSEtienne Carriere
4906f74919dSEtienne Carriere TEE_Free(array);
4916f74919dSEtienne Carriere
4924daf39b3SJens Wiklander return rc;
4936f74919dSEtienne Carriere }
4941d3ebedbSEtienne Carriere
entry_ck_token_mecha_info(uint32_t ptypes,TEE_Param * params)4954daf39b3SJens Wiklander enum pkcs11_rc entry_ck_token_mecha_info(uint32_t ptypes, TEE_Param *params)
4961d3ebedbSEtienne Carriere {
4971d3ebedbSEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
4981d3ebedbSEtienne Carriere TEE_PARAM_TYPE_NONE,
4991d3ebedbSEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT,
5001d3ebedbSEtienne Carriere TEE_PARAM_TYPE_NONE);
50139b43b78SJens Wiklander TEE_Param *ctrl = params;
50239b43b78SJens Wiklander TEE_Param *out = params + 2;
5034daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
5041d3ebedbSEtienne Carriere struct serialargs ctrlargs = { };
5051d3ebedbSEtienne Carriere uint32_t token_id = 0;
5061d3ebedbSEtienne Carriere uint32_t type = 0;
5071d3ebedbSEtienne Carriere struct ck_token *token = NULL;
5081d3ebedbSEtienne Carriere struct pkcs11_mechanism_info info = { };
5091d3ebedbSEtienne Carriere
5101d3ebedbSEtienne Carriere if (ptypes != exp_pt || out->memref.size != sizeof(info))
5111d3ebedbSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD;
5121d3ebedbSEtienne Carriere
5131d3ebedbSEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
5141d3ebedbSEtienne Carriere
5154daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t));
5164daf39b3SJens Wiklander if (rc)
5174daf39b3SJens Wiklander return rc;
5181d3ebedbSEtienne Carriere
5194daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &type, sizeof(uint32_t));
5204daf39b3SJens Wiklander if (rc)
5214daf39b3SJens Wiklander return rc;
5221d3ebedbSEtienne Carriere
5231d3ebedbSEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs))
5241d3ebedbSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD;
5251d3ebedbSEtienne Carriere
5261d3ebedbSEtienne Carriere token = get_token(token_id);
5271d3ebedbSEtienne Carriere if (!token)
5281d3ebedbSEtienne Carriere return PKCS11_CKR_SLOT_ID_INVALID;
5291d3ebedbSEtienne Carriere
5301d3ebedbSEtienne Carriere if (!mechanism_is_valid(type))
5311d3ebedbSEtienne Carriere return PKCS11_CKR_MECHANISM_INVALID;
5321d3ebedbSEtienne Carriere
5331d3ebedbSEtienne Carriere info.flags = mechanism_supported_flags(type);
5341d3ebedbSEtienne Carriere
5352d0cd829SRuchika Gupta pkcs11_mechanism_supported_key_sizes(type, &info.min_key_size,
5361d3ebedbSEtienne Carriere &info.max_key_size);
5371d3ebedbSEtienne Carriere
5381d3ebedbSEtienne Carriere TEE_MemMove(out->memref.buffer, &info, sizeof(info));
5391d3ebedbSEtienne Carriere
5401d3ebedbSEtienne Carriere DMSG("PKCS11 token %"PRIu32": mechanism 0x%"PRIx32" info",
5411d3ebedbSEtienne Carriere token_id, type);
5421d3ebedbSEtienne Carriere
5431d3ebedbSEtienne Carriere return PKCS11_CKR_OK;
5441d3ebedbSEtienne Carriere }
5456e4f8f17SEtienne Carriere
5466e4f8f17SEtienne Carriere /* Select the ReadOnly or ReadWrite state for session login state */
set_session_state(struct pkcs11_client * client,struct pkcs11_session * session,bool readonly)5476e4f8f17SEtienne Carriere static void set_session_state(struct pkcs11_client *client,
5486e4f8f17SEtienne Carriere struct pkcs11_session *session, bool readonly)
5496e4f8f17SEtienne Carriere {
5506e4f8f17SEtienne Carriere struct pkcs11_session *sess = NULL;
5516e4f8f17SEtienne Carriere enum pkcs11_session_state state = PKCS11_CKS_RO_PUBLIC_SESSION;
5526e4f8f17SEtienne Carriere
5536e4f8f17SEtienne Carriere /* Default to public session if no session already registered */
5546e4f8f17SEtienne Carriere if (readonly)
5556e4f8f17SEtienne Carriere state = PKCS11_CKS_RO_PUBLIC_SESSION;
5566e4f8f17SEtienne Carriere else
5576e4f8f17SEtienne Carriere state = PKCS11_CKS_RW_PUBLIC_SESSION;
5586e4f8f17SEtienne Carriere
5596e4f8f17SEtienne Carriere /*
5606e4f8f17SEtienne Carriere * No need to check all client sessions, the first found in
5616e4f8f17SEtienne Carriere * target token gives client login configuration.
5626e4f8f17SEtienne Carriere */
5636e4f8f17SEtienne Carriere TAILQ_FOREACH(sess, &client->session_list, link) {
5646e4f8f17SEtienne Carriere assert(sess != session);
5656e4f8f17SEtienne Carriere
5666e4f8f17SEtienne Carriere if (sess->token == session->token) {
5676e4f8f17SEtienne Carriere switch (sess->state) {
5686e4f8f17SEtienne Carriere case PKCS11_CKS_RW_PUBLIC_SESSION:
5696e4f8f17SEtienne Carriere case PKCS11_CKS_RO_PUBLIC_SESSION:
5706e4f8f17SEtienne Carriere if (readonly)
5716e4f8f17SEtienne Carriere state = PKCS11_CKS_RO_PUBLIC_SESSION;
5726e4f8f17SEtienne Carriere else
5736e4f8f17SEtienne Carriere state = PKCS11_CKS_RW_PUBLIC_SESSION;
5746e4f8f17SEtienne Carriere break;
5756e4f8f17SEtienne Carriere case PKCS11_CKS_RO_USER_FUNCTIONS:
5766e4f8f17SEtienne Carriere case PKCS11_CKS_RW_USER_FUNCTIONS:
5776e4f8f17SEtienne Carriere if (readonly)
5786e4f8f17SEtienne Carriere state = PKCS11_CKS_RO_USER_FUNCTIONS;
5796e4f8f17SEtienne Carriere else
5806e4f8f17SEtienne Carriere state = PKCS11_CKS_RW_USER_FUNCTIONS;
5816e4f8f17SEtienne Carriere break;
5826e4f8f17SEtienne Carriere case PKCS11_CKS_RW_SO_FUNCTIONS:
5836e4f8f17SEtienne Carriere if (readonly)
5846e4f8f17SEtienne Carriere TEE_Panic(0);
5856e4f8f17SEtienne Carriere else
5866e4f8f17SEtienne Carriere state = PKCS11_CKS_RW_SO_FUNCTIONS;
5876e4f8f17SEtienne Carriere break;
5886e4f8f17SEtienne Carriere default:
5896e4f8f17SEtienne Carriere TEE_Panic(0);
5906e4f8f17SEtienne Carriere }
5916e4f8f17SEtienne Carriere break;
5926e4f8f17SEtienne Carriere }
5936e4f8f17SEtienne Carriere }
5946e4f8f17SEtienne Carriere
5956e4f8f17SEtienne Carriere session->state = state;
5966e4f8f17SEtienne Carriere }
5976e4f8f17SEtienne Carriere
entry_ck_open_session(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)5984daf39b3SJens Wiklander enum pkcs11_rc entry_ck_open_session(struct pkcs11_client *client,
5996e4f8f17SEtienne Carriere uint32_t ptypes, TEE_Param *params)
6006e4f8f17SEtienne Carriere {
6016e4f8f17SEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
6026e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE,
6036e4f8f17SEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT,
6046e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE);
60539b43b78SJens Wiklander TEE_Param *ctrl = params;
60639b43b78SJens Wiklander TEE_Param *out = params + 2;
6074daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
6086e4f8f17SEtienne Carriere struct serialargs ctrlargs = { };
6096e4f8f17SEtienne Carriere uint32_t token_id = 0;
6106e4f8f17SEtienne Carriere uint32_t flags = 0;
6116e4f8f17SEtienne Carriere struct ck_token *token = NULL;
6126e4f8f17SEtienne Carriere struct pkcs11_session *session = NULL;
6136e4f8f17SEtienne Carriere bool readonly = false;
6146e4f8f17SEtienne Carriere
6156e4f8f17SEtienne Carriere if (!client || ptypes != exp_pt ||
6166e4f8f17SEtienne Carriere out->memref.size != sizeof(session->handle))
6176e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD;
6186e4f8f17SEtienne Carriere
6196e4f8f17SEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
6206e4f8f17SEtienne Carriere
6214daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &token_id, sizeof(token_id));
6224daf39b3SJens Wiklander if (rc)
6234daf39b3SJens Wiklander return rc;
6246e4f8f17SEtienne Carriere
6254daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &flags, sizeof(flags));
6264daf39b3SJens Wiklander if (rc)
6274daf39b3SJens Wiklander return rc;
6286e4f8f17SEtienne Carriere
6296e4f8f17SEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs))
6306e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD;
6316e4f8f17SEtienne Carriere
6326e4f8f17SEtienne Carriere token = get_token(token_id);
6336e4f8f17SEtienne Carriere if (!token)
6346e4f8f17SEtienne Carriere return PKCS11_CKR_SLOT_ID_INVALID;
6356e4f8f17SEtienne Carriere
6366e4f8f17SEtienne Carriere /* Sanitize session flags */
63708774c86SVesa Jääskeläinen if (!(flags & PKCS11_CKFSS_SERIAL_SESSION))
63808774c86SVesa Jääskeläinen return PKCS11_CKR_SESSION_PARALLEL_NOT_SUPPORTED;
63908774c86SVesa Jääskeläinen
64008774c86SVesa Jääskeläinen if (flags & ~(PKCS11_CKFSS_RW_SESSION | PKCS11_CKFSS_SERIAL_SESSION))
6416e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD;
6426e4f8f17SEtienne Carriere
6436e4f8f17SEtienne Carriere readonly = !(flags & PKCS11_CKFSS_RW_SESSION);
6446e4f8f17SEtienne Carriere
6456e4f8f17SEtienne Carriere if (!readonly && token->state == PKCS11_TOKEN_READ_ONLY)
6466e4f8f17SEtienne Carriere return PKCS11_CKR_TOKEN_WRITE_PROTECTED;
6476e4f8f17SEtienne Carriere
6486e4f8f17SEtienne Carriere if (readonly) {
6496e4f8f17SEtienne Carriere /* Specifically reject read-only session under SO login */
6506e4f8f17SEtienne Carriere TAILQ_FOREACH(session, &client->session_list, link)
6516e4f8f17SEtienne Carriere if (pkcs11_session_is_so(session))
6526e4f8f17SEtienne Carriere return PKCS11_CKR_SESSION_READ_WRITE_SO_EXISTS;
6536e4f8f17SEtienne Carriere }
6546e4f8f17SEtienne Carriere
6556e4f8f17SEtienne Carriere session = TEE_Malloc(sizeof(*session), TEE_MALLOC_FILL_ZERO);
6566e4f8f17SEtienne Carriere if (!session)
6576e4f8f17SEtienne Carriere return PKCS11_CKR_DEVICE_MEMORY;
6586e4f8f17SEtienne Carriere
6596e4f8f17SEtienne Carriere session->handle = handle_get(&client->session_handle_db, session);
6606e4f8f17SEtienne Carriere if (!session->handle) {
6616e4f8f17SEtienne Carriere TEE_Free(session);
6626e4f8f17SEtienne Carriere return PKCS11_CKR_DEVICE_MEMORY;
6636e4f8f17SEtienne Carriere }
6646e4f8f17SEtienne Carriere
6656e4f8f17SEtienne Carriere session->token = token;
6666e4f8f17SEtienne Carriere session->client = client;
6676e4f8f17SEtienne Carriere
668b56b3d07SJens Wiklander LIST_INIT(&session->object_list);
669b56b3d07SJens Wiklander
6706e4f8f17SEtienne Carriere set_session_state(client, session, readonly);
6716e4f8f17SEtienne Carriere
6726e4f8f17SEtienne Carriere TAILQ_INSERT_HEAD(&client->session_list, session, link);
6736e4f8f17SEtienne Carriere
6746e4f8f17SEtienne Carriere session->token->session_count++;
6756e4f8f17SEtienne Carriere if (!readonly)
6766e4f8f17SEtienne Carriere session->token->rw_session_count++;
6776e4f8f17SEtienne Carriere
6786e4f8f17SEtienne Carriere TEE_MemMove(out->memref.buffer, &session->handle,
6796e4f8f17SEtienne Carriere sizeof(session->handle));
6806e4f8f17SEtienne Carriere
6816e4f8f17SEtienne Carriere DMSG("Open PKCS11 session %"PRIu32, session->handle);
6826e4f8f17SEtienne Carriere
6836e4f8f17SEtienne Carriere return PKCS11_CKR_OK;
6846e4f8f17SEtienne Carriere }
6856e4f8f17SEtienne Carriere
close_ck_session(struct pkcs11_session * session)6866e4f8f17SEtienne Carriere static void close_ck_session(struct pkcs11_session *session)
6876e4f8f17SEtienne Carriere {
68855e6965cSEtienne Carriere release_active_processing(session);
689bc555ee0SVesa Jääskeläinen release_session_find_obj_context(session);
69055e6965cSEtienne Carriere
691bc555ee0SVesa Jääskeläinen /* Release all session objects */
692b56b3d07SJens Wiklander while (!LIST_EMPTY(&session->object_list))
693b56b3d07SJens Wiklander destroy_object(session,
694b56b3d07SJens Wiklander LIST_FIRST(&session->object_list), true);
695b56b3d07SJens Wiklander
6966e4f8f17SEtienne Carriere TAILQ_REMOVE(&session->client->session_list, session, link);
6976e4f8f17SEtienne Carriere handle_put(&session->client->session_handle_db, session->handle);
6986e4f8f17SEtienne Carriere
6996e4f8f17SEtienne Carriere session->token->session_count--;
7006e4f8f17SEtienne Carriere if (pkcs11_session_is_read_write(session))
7016e4f8f17SEtienne Carriere session->token->rw_session_count--;
7026e4f8f17SEtienne Carriere
7036e4f8f17SEtienne Carriere DMSG("Close PKCS11 session %"PRIu32, session->handle);
7049325ea3dSJerome Forissier
7059325ea3dSJerome Forissier TEE_Free(session);
7066e4f8f17SEtienne Carriere }
7076e4f8f17SEtienne Carriere
entry_ck_close_session(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)7084daf39b3SJens Wiklander enum pkcs11_rc entry_ck_close_session(struct pkcs11_client *client,
7096e4f8f17SEtienne Carriere uint32_t ptypes, TEE_Param *params)
7106e4f8f17SEtienne Carriere {
7116e4f8f17SEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
7126e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE,
7136e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE,
7146e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE);
71539b43b78SJens Wiklander TEE_Param *ctrl = params;
7164daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
7176e4f8f17SEtienne Carriere struct serialargs ctrlargs = { };
7186e4f8f17SEtienne Carriere struct pkcs11_session *session = NULL;
7196e4f8f17SEtienne Carriere
7206e4f8f17SEtienne Carriere if (!client || ptypes != exp_pt)
7216e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD;
7226e4f8f17SEtienne Carriere
7236e4f8f17SEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
7246e4f8f17SEtienne Carriere
7254daf39b3SJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
7264daf39b3SJens Wiklander if (rc)
7274daf39b3SJens Wiklander return rc;
7286e4f8f17SEtienne Carriere
7296e4f8f17SEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs))
7306e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD;
7316e4f8f17SEtienne Carriere
7326e4f8f17SEtienne Carriere close_ck_session(session);
7336e4f8f17SEtienne Carriere
7346e4f8f17SEtienne Carriere return PKCS11_CKR_OK;
7356e4f8f17SEtienne Carriere }
7366e4f8f17SEtienne Carriere
entry_ck_close_all_sessions(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)7374daf39b3SJens Wiklander enum pkcs11_rc entry_ck_close_all_sessions(struct pkcs11_client *client,
7386e4f8f17SEtienne Carriere uint32_t ptypes, TEE_Param *params)
7396e4f8f17SEtienne Carriere {
7406e4f8f17SEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
7416e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE,
7426e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE,
7436e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE);
74439b43b78SJens Wiklander TEE_Param *ctrl = params;
7454daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
7466e4f8f17SEtienne Carriere struct serialargs ctrlargs = { };
7476e4f8f17SEtienne Carriere uint32_t token_id = 0;
7486e4f8f17SEtienne Carriere struct ck_token *token = NULL;
7496e4f8f17SEtienne Carriere struct pkcs11_session *session = NULL;
7506e4f8f17SEtienne Carriere struct pkcs11_session *next = NULL;
7516e4f8f17SEtienne Carriere
7526e4f8f17SEtienne Carriere if (!client || ptypes != exp_pt)
7536e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD;
7546e4f8f17SEtienne Carriere
7556e4f8f17SEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
7566e4f8f17SEtienne Carriere
7574daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t));
7584daf39b3SJens Wiklander if (rc)
7594daf39b3SJens Wiklander return rc;
7606e4f8f17SEtienne Carriere
7616e4f8f17SEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs))
7626e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD;
7636e4f8f17SEtienne Carriere
7646e4f8f17SEtienne Carriere token = get_token(token_id);
7656e4f8f17SEtienne Carriere if (!token)
7666e4f8f17SEtienne Carriere return PKCS11_CKR_SLOT_ID_INVALID;
7676e4f8f17SEtienne Carriere
7686e4f8f17SEtienne Carriere DMSG("Close all sessions for PKCS11 token %"PRIu32, token_id);
7696e4f8f17SEtienne Carriere
7706e4f8f17SEtienne Carriere TAILQ_FOREACH_SAFE(session, &client->session_list, link, next)
7716e4f8f17SEtienne Carriere if (session->token == token)
7726e4f8f17SEtienne Carriere close_ck_session(session);
7736e4f8f17SEtienne Carriere
7746e4f8f17SEtienne Carriere return PKCS11_CKR_OK;
7756e4f8f17SEtienne Carriere }
7766e4f8f17SEtienne Carriere
entry_ck_session_info(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)7774daf39b3SJens Wiklander enum pkcs11_rc entry_ck_session_info(struct pkcs11_client *client,
7786e4f8f17SEtienne Carriere uint32_t ptypes, TEE_Param *params)
7796e4f8f17SEtienne Carriere {
7806e4f8f17SEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
7816e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE,
7826e4f8f17SEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT,
7836e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE);
78439b43b78SJens Wiklander TEE_Param *ctrl = params;
78539b43b78SJens Wiklander TEE_Param *out = params + 2;
7864daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
7876e4f8f17SEtienne Carriere struct serialargs ctrlargs = { };
7886e4f8f17SEtienne Carriere struct pkcs11_session *session = NULL;
7896e4f8f17SEtienne Carriere struct pkcs11_session_info info = {
7906e4f8f17SEtienne Carriere .flags = PKCS11_CKFSS_SERIAL_SESSION,
7916e4f8f17SEtienne Carriere };
7926e4f8f17SEtienne Carriere
7936e4f8f17SEtienne Carriere if (!client || ptypes != exp_pt || out->memref.size != sizeof(info))
7946e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD;
7956e4f8f17SEtienne Carriere
7966e4f8f17SEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
7976e4f8f17SEtienne Carriere
7984daf39b3SJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
7994daf39b3SJens Wiklander if (rc)
8004daf39b3SJens Wiklander return rc;
8016e4f8f17SEtienne Carriere
8026e4f8f17SEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs))
8036e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD;
8046e4f8f17SEtienne Carriere
8056e4f8f17SEtienne Carriere info.slot_id = get_token_id(session->token);
8066e4f8f17SEtienne Carriere info.state = session->state;
8076e4f8f17SEtienne Carriere if (pkcs11_session_is_read_write(session))
8086e4f8f17SEtienne Carriere info.flags |= PKCS11_CKFSS_RW_SESSION;
8096e4f8f17SEtienne Carriere
8106e4f8f17SEtienne Carriere TEE_MemMove(out->memref.buffer, &info, sizeof(info));
8116e4f8f17SEtienne Carriere
8126e4f8f17SEtienne Carriere DMSG("Get find on PKCS11 session %"PRIu32, session->handle);
8136e4f8f17SEtienne Carriere
8146e4f8f17SEtienne Carriere return PKCS11_CKR_OK;
8156e4f8f17SEtienne Carriere }
816f485be04SJens Wiklander
entry_ck_token_initialize(uint32_t ptypes,TEE_Param * params)8174daf39b3SJens Wiklander enum pkcs11_rc entry_ck_token_initialize(uint32_t ptypes, TEE_Param *params)
818f485be04SJens Wiklander {
819f485be04SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
820f485be04SJens Wiklander TEE_PARAM_TYPE_NONE,
821f485be04SJens Wiklander TEE_PARAM_TYPE_NONE,
822f485be04SJens Wiklander TEE_PARAM_TYPE_NONE);
823f485be04SJens Wiklander char label[PKCS11_TOKEN_LABEL_SIZE] = { 0 };
824f485be04SJens Wiklander struct pkcs11_client *client = NULL;
825f485be04SJens Wiklander struct pkcs11_session *sess = NULL;
826f485be04SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
827f485be04SJens Wiklander struct serialargs ctrlargs = { };
828f485be04SJens Wiklander struct ck_token *token = NULL;
829f485be04SJens Wiklander TEE_Param *ctrl = params;
830f485be04SJens Wiklander uint32_t token_id = 0;
831f485be04SJens Wiklander uint32_t pin_size = 0;
832f485be04SJens Wiklander void *pin = NULL;
8337f12c782SRobin van der Gracht struct pkcs11_object *obj = NULL;
834f485be04SJens Wiklander
835f485be04SJens Wiklander if (ptypes != exp_pt)
836f485be04SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD;
837f485be04SJens Wiklander
838f485be04SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
839f485be04SJens Wiklander
840f485be04SJens Wiklander rc = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t));
841f485be04SJens Wiklander if (rc)
842f485be04SJens Wiklander return rc;
843f485be04SJens Wiklander
844f485be04SJens Wiklander rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t));
845f485be04SJens Wiklander if (rc)
846f485be04SJens Wiklander return rc;
847f485be04SJens Wiklander
848f485be04SJens Wiklander rc = serialargs_get(&ctrlargs, &label, PKCS11_TOKEN_LABEL_SIZE);
849f485be04SJens Wiklander if (rc)
850f485be04SJens Wiklander return rc;
851f485be04SJens Wiklander
852f485be04SJens Wiklander rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size);
853f485be04SJens Wiklander if (rc)
854f485be04SJens Wiklander return rc;
855f485be04SJens Wiklander
856f485be04SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs))
857f485be04SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD;
858f485be04SJens Wiklander
859f485be04SJens Wiklander token = get_token(token_id);
860f485be04SJens Wiklander if (!token)
861f485be04SJens Wiklander return PKCS11_CKR_SLOT_ID_INVALID;
862f485be04SJens Wiklander
863f485be04SJens Wiklander if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED) {
864f485be04SJens Wiklander IMSG("Token %"PRIu32": SO PIN locked", token_id);
865f485be04SJens Wiklander return PKCS11_CKR_PIN_LOCKED;
866f485be04SJens Wiklander }
867f485be04SJens Wiklander
868f485be04SJens Wiklander /* Check there's no open session on this token */
869f485be04SJens Wiklander TAILQ_FOREACH(client, &pkcs11_client_list, link)
870f485be04SJens Wiklander TAILQ_FOREACH(sess, &client->session_list, link)
871f485be04SJens Wiklander if (sess->token == token)
872f485be04SJens Wiklander return PKCS11_CKR_SESSION_EXISTS;
873f485be04SJens Wiklander
874f1105cc5SVesa Jääskeläinen /* Verify authentication if token is already initialized */
875f1105cc5SVesa Jääskeläinen if (token->db_main->flags & PKCS11_CKFT_TOKEN_INITIALIZED) {
876f1105cc5SVesa Jääskeläinen unsigned int pin_count = 0;
877f1105cc5SVesa Jääskeläinen
878f1105cc5SVesa Jääskeläinen if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) &&
879f1105cc5SVesa Jääskeläinen (token->db_main->flags &
880f1105cc5SVesa Jääskeläinen PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH)) {
8811a27b197SVesa Jääskeläinen /* Check TEE Identity based authentication if enabled */
882f44a7a58SEtienne Carriere rc = verify_identity_auth(token, PKCS11_CKU_SO);
8831a27b197SVesa Jääskeläinen if (rc)
8841a27b197SVesa Jääskeläinen return rc;
885f485be04SJens Wiklander
886f485be04SJens Wiklander goto inited;
887f485be04SJens Wiklander }
888f485be04SJens Wiklander
889f1105cc5SVesa Jääskeläinen /* Check PIN based authentication */
890f485be04SJens Wiklander rc = verify_pin(PKCS11_CKU_SO, pin, pin_size,
891f485be04SJens Wiklander token->db_main->so_pin_salt,
892f485be04SJens Wiklander token->db_main->so_pin_hash);
893f1105cc5SVesa Jääskeläinen if (!rc)
894f1105cc5SVesa Jääskeläinen goto inited;
895f485be04SJens Wiklander
896f485be04SJens Wiklander if (rc != PKCS11_CKR_PIN_INCORRECT)
897f485be04SJens Wiklander return rc;
898f485be04SJens Wiklander
899f485be04SJens Wiklander token->db_main->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW;
900f485be04SJens Wiklander token->db_main->so_pin_count++;
901f485be04SJens Wiklander
902f485be04SJens Wiklander pin_count = token->db_main->so_pin_count;
903f485be04SJens Wiklander if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1)
904f485be04SJens Wiklander token->db_main->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY;
905f485be04SJens Wiklander if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX)
906f485be04SJens Wiklander token->db_main->flags |= PKCS11_CKFT_SO_PIN_LOCKED;
907f485be04SJens Wiklander
908f485be04SJens Wiklander update_persistent_db(token);
909f485be04SJens Wiklander
910f485be04SJens Wiklander return PKCS11_CKR_PIN_INCORRECT;
911f485be04SJens Wiklander }
912f485be04SJens Wiklander
913f1105cc5SVesa Jääskeläinen /* Initialize SO's authentication */
914f1105cc5SVesa Jääskeläinen if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && !pin) {
915f1105cc5SVesa Jääskeläinen rc = setup_so_identity_auth_from_client(token);
916f1105cc5SVesa Jääskeläinen if (rc)
917f1105cc5SVesa Jääskeläinen return rc;
918f1105cc5SVesa Jääskeläinen } else {
919f1105cc5SVesa Jääskeläinen /*
920f1105cc5SVesa Jääskeläinen * The spec doesn't permit returning
921f1105cc5SVesa Jääskeläinen * PKCS11_CKR_PIN_LEN_RANGE for this function, take another
922f1105cc5SVesa Jääskeläinen * error code.
923f1105cc5SVesa Jääskeläinen */
924f1105cc5SVesa Jääskeläinen if (pin_size < PKCS11_TOKEN_PIN_SIZE_MIN ||
925f1105cc5SVesa Jääskeläinen pin_size > PKCS11_TOKEN_PIN_SIZE_MAX)
926f1105cc5SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD;
927f1105cc5SVesa Jääskeläinen
928f1105cc5SVesa Jääskeläinen rc = hash_pin(PKCS11_CKU_SO, pin, pin_size,
929f1105cc5SVesa Jääskeläinen &token->db_main->so_pin_salt,
930f1105cc5SVesa Jääskeläinen token->db_main->so_pin_hash);
931f1105cc5SVesa Jääskeläinen if (rc)
932f1105cc5SVesa Jääskeläinen return rc;
933f1105cc5SVesa Jääskeläinen }
934f1105cc5SVesa Jääskeläinen
93512253e9eSVesa Jääskeläinen inited:
93612253e9eSVesa Jääskeläinen /* Make sure SO PIN counters are zeroed */
937f485be04SJens Wiklander token->db_main->flags &= ~(PKCS11_CKFT_SO_PIN_COUNT_LOW |
93812253e9eSVesa Jääskeläinen PKCS11_CKFT_SO_PIN_FINAL_TRY |
93912253e9eSVesa Jääskeläinen PKCS11_CKFT_SO_PIN_LOCKED |
94012253e9eSVesa Jääskeläinen PKCS11_CKFT_SO_PIN_TO_BE_CHANGED);
941f485be04SJens Wiklander token->db_main->so_pin_count = 0;
942f485be04SJens Wiklander
943f485be04SJens Wiklander TEE_MemMove(token->db_main->label, label, PKCS11_TOKEN_LABEL_SIZE);
944f485be04SJens Wiklander token->db_main->flags |= PKCS11_CKFT_TOKEN_INITIALIZED;
945f485be04SJens Wiklander /* Reset user PIN */
946f485be04SJens Wiklander token->db_main->user_pin_salt = 0;
947f485be04SJens Wiklander token->db_main->flags &= ~(PKCS11_CKFT_USER_PIN_INITIALIZED |
948f485be04SJens Wiklander PKCS11_CKFT_USER_PIN_COUNT_LOW |
949f485be04SJens Wiklander PKCS11_CKFT_USER_PIN_FINAL_TRY |
950f485be04SJens Wiklander PKCS11_CKFT_USER_PIN_LOCKED |
951f485be04SJens Wiklander PKCS11_CKFT_USER_PIN_TO_BE_CHANGED);
952f485be04SJens Wiklander
953f485be04SJens Wiklander update_persistent_db(token);
954f485be04SJens Wiklander
9557f12c782SRobin van der Gracht /* Remove all persistent objects */
9567f12c782SRobin van der Gracht while (!LIST_EMPTY(&token->object_list)) {
9577f12c782SRobin van der Gracht obj = LIST_FIRST(&token->object_list);
9587f12c782SRobin van der Gracht
9597f12c782SRobin van der Gracht /* Try twice otherwise panic! */
9607f12c782SRobin van der Gracht if (unregister_persistent_object(token, obj->uuid) &&
9617f12c782SRobin van der Gracht unregister_persistent_object(token, obj->uuid))
9627f12c782SRobin van der Gracht TEE_Panic(0);
9637f12c782SRobin van der Gracht
9647f12c782SRobin van der Gracht cleanup_persistent_object(obj, token);
9657f12c782SRobin van der Gracht }
9667f12c782SRobin van der Gracht
967f485be04SJens Wiklander IMSG("PKCS11 token %"PRIu32": initialized", token_id);
968f485be04SJens Wiklander
969f485be04SJens Wiklander return PKCS11_CKR_OK;
970f485be04SJens Wiklander }
971e8dbd92cSJens Wiklander
set_pin(struct pkcs11_session * session,uint8_t * new_pin,size_t new_pin_size,enum pkcs11_user_type user_type)972e8dbd92cSJens Wiklander static enum pkcs11_rc set_pin(struct pkcs11_session *session,
973e8dbd92cSJens Wiklander uint8_t *new_pin, size_t new_pin_size,
974e8dbd92cSJens Wiklander enum pkcs11_user_type user_type)
975e8dbd92cSJens Wiklander {
9761e497011SVesa Jääskeläinen struct ck_token *token = session->token;
977e8dbd92cSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
978e8dbd92cSJens Wiklander uint32_t flags_clear = 0;
979e8dbd92cSJens Wiklander uint32_t flags_set = 0;
980e8dbd92cSJens Wiklander
9811e497011SVesa Jääskeläinen if (token->db_main->flags & PKCS11_CKFT_WRITE_PROTECTED)
982e8dbd92cSJens Wiklander return PKCS11_CKR_TOKEN_WRITE_PROTECTED;
983e8dbd92cSJens Wiklander
984e8dbd92cSJens Wiklander if (!pkcs11_session_is_read_write(session))
985e8dbd92cSJens Wiklander return PKCS11_CKR_SESSION_READ_ONLY;
986e8dbd92cSJens Wiklander
9871a27b197SVesa Jääskeläinen if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) &&
988920e0127SVesa Jääskeläinen (token->db_main->flags &
989920e0127SVesa Jääskeläinen PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH)) {
990920e0127SVesa Jääskeläinen rc = setup_identity_auth_from_pin(token, user_type,
991920e0127SVesa Jääskeläinen new_pin, new_pin_size);
992920e0127SVesa Jääskeläinen if (rc == PKCS11_CKR_OK) {
993920e0127SVesa Jääskeläinen goto update_db;
994920e0127SVesa Jääskeläinen } else if (rc == PKCS11_CKR_PIN_INVALID &&
995920e0127SVesa Jääskeläinen !(token->db_main->flags &
996920e0127SVesa Jääskeläinen PKCS11_CKFT_USER_PIN_INITIALIZED)) {
997920e0127SVesa Jääskeläinen /*
998920e0127SVesa Jääskeläinen * PIN was not compatible with TEE Identity
999920e0127SVesa Jääskeläinen * Authentication syntax so let's assume it might be a
1000920e0127SVesa Jääskeläinen * new SO PIN to switch the authentication mode.
1001920e0127SVesa Jääskeläinen */
1002920e0127SVesa Jääskeläinen
1003920e0127SVesa Jääskeläinen /* Update mode flag if all PIN checks pass */
1004920e0127SVesa Jääskeläinen flags_clear |=
1005920e0127SVesa Jääskeläinen PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH;
1006920e0127SVesa Jääskeläinen } else {
10071a27b197SVesa Jääskeläinen return rc;
1008920e0127SVesa Jääskeläinen }
1009920e0127SVesa Jääskeläinen } else if ((user_type == PKCS11_CKU_SO) && !new_pin &&
1010920e0127SVesa Jääskeläinen IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) &&
1011920e0127SVesa Jääskeläinen !(token->db_main->flags &
1012920e0127SVesa Jääskeläinen PKCS11_CKFT_USER_PIN_INITIALIZED)) {
1013920e0127SVesa Jääskeläinen /*
1014920e0127SVesa Jääskeläinen * Allow changing of token authentication mode before user pin
1015920e0127SVesa Jääskeläinen * has been initialized.
1016920e0127SVesa Jääskeläinen */
1017920e0127SVesa Jääskeläinen
1018920e0127SVesa Jääskeläinen /*
1019920e0127SVesa Jääskeläinen * Set protected authentication path temporary until
1020920e0127SVesa Jääskeläinen * finalized.
1021920e0127SVesa Jääskeläinen */
1022920e0127SVesa Jääskeläinen token->db_main->flags |=
1023920e0127SVesa Jääskeläinen PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH;
1024920e0127SVesa Jääskeläinen
1025920e0127SVesa Jääskeläinen /*
1026920e0127SVesa Jääskeläinen * Setup authentication from currently active TEE Client
1027920e0127SVesa Jääskeläinen * Identity.
1028920e0127SVesa Jääskeläinen */
1029920e0127SVesa Jääskeläinen rc = setup_identity_auth_from_pin(token, PKCS11_CKU_SO,
1030920e0127SVesa Jääskeläinen NULL, 0);
1031920e0127SVesa Jääskeläinen if (rc) {
1032920e0127SVesa Jääskeläinen /*
1033920e0127SVesa Jääskeläinen * Failed to setup protected authentication path so
1034920e0127SVesa Jääskeläinen * clear the temporary flag.
1035920e0127SVesa Jääskeläinen */
1036920e0127SVesa Jääskeläinen token->db_main->flags &=
1037920e0127SVesa Jääskeläinen ~PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH;
1038920e0127SVesa Jääskeläinen return rc;
1039920e0127SVesa Jääskeläinen }
10401a27b197SVesa Jääskeläinen
10411a27b197SVesa Jääskeläinen goto update_db;
10421a27b197SVesa Jääskeläinen }
10431a27b197SVesa Jääskeläinen
1044e8dbd92cSJens Wiklander if (new_pin_size < PKCS11_TOKEN_PIN_SIZE_MIN ||
1045e8dbd92cSJens Wiklander new_pin_size > PKCS11_TOKEN_PIN_SIZE_MAX)
1046e8dbd92cSJens Wiklander return PKCS11_CKR_PIN_LEN_RANGE;
1047e8dbd92cSJens Wiklander
1048e8dbd92cSJens Wiklander switch (user_type) {
1049e8dbd92cSJens Wiklander case PKCS11_CKU_SO:
1050e8dbd92cSJens Wiklander rc = hash_pin(user_type, new_pin, new_pin_size,
10511e497011SVesa Jääskeläinen &token->db_main->so_pin_salt,
10521e497011SVesa Jääskeläinen token->db_main->so_pin_hash);
1053e8dbd92cSJens Wiklander if (rc)
1054e8dbd92cSJens Wiklander return rc;
10551e497011SVesa Jääskeläinen token->db_main->so_pin_count = 0;
1056920e0127SVesa Jääskeläinen flags_clear |= PKCS11_CKFT_SO_PIN_COUNT_LOW |
1057e8dbd92cSJens Wiklander PKCS11_CKFT_SO_PIN_FINAL_TRY |
1058e8dbd92cSJens Wiklander PKCS11_CKFT_SO_PIN_LOCKED |
1059e8dbd92cSJens Wiklander PKCS11_CKFT_SO_PIN_TO_BE_CHANGED;
1060e8dbd92cSJens Wiklander break;
1061e8dbd92cSJens Wiklander case PKCS11_CKU_USER:
1062e8dbd92cSJens Wiklander rc = hash_pin(user_type, new_pin, new_pin_size,
10631e497011SVesa Jääskeläinen &token->db_main->user_pin_salt,
10641e497011SVesa Jääskeläinen token->db_main->user_pin_hash);
1065e8dbd92cSJens Wiklander if (rc)
1066e8dbd92cSJens Wiklander return rc;
10671e497011SVesa Jääskeläinen token->db_main->user_pin_count = 0;
1068920e0127SVesa Jääskeläinen flags_clear |= PKCS11_CKFT_USER_PIN_COUNT_LOW |
1069e8dbd92cSJens Wiklander PKCS11_CKFT_USER_PIN_FINAL_TRY |
1070e8dbd92cSJens Wiklander PKCS11_CKFT_USER_PIN_LOCKED |
1071e8dbd92cSJens Wiklander PKCS11_CKFT_USER_PIN_TO_BE_CHANGED;
1072920e0127SVesa Jääskeläinen flags_set |= PKCS11_CKFT_USER_PIN_INITIALIZED;
1073e8dbd92cSJens Wiklander break;
1074e8dbd92cSJens Wiklander default:
1075e8dbd92cSJens Wiklander return PKCS11_CKR_FUNCTION_FAILED;
1076e8dbd92cSJens Wiklander }
1077e8dbd92cSJens Wiklander
10781a27b197SVesa Jääskeläinen update_db:
10791e497011SVesa Jääskeläinen token->db_main->flags &= ~flags_clear;
10801e497011SVesa Jääskeläinen token->db_main->flags |= flags_set;
1081e8dbd92cSJens Wiklander
10821e497011SVesa Jääskeläinen update_persistent_db(token);
1083e8dbd92cSJens Wiklander
1084e8dbd92cSJens Wiklander return PKCS11_CKR_OK;
1085e8dbd92cSJens Wiklander }
1086e8dbd92cSJens Wiklander
entry_ck_init_pin(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)10874daf39b3SJens Wiklander enum pkcs11_rc entry_ck_init_pin(struct pkcs11_client *client,
1088e8dbd92cSJens Wiklander uint32_t ptypes, TEE_Param *params)
1089e8dbd92cSJens Wiklander {
1090e8dbd92cSJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
1091e8dbd92cSJens Wiklander TEE_PARAM_TYPE_NONE,
1092e8dbd92cSJens Wiklander TEE_PARAM_TYPE_NONE,
1093e8dbd92cSJens Wiklander TEE_PARAM_TYPE_NONE);
1094e8dbd92cSJens Wiklander struct pkcs11_session *session = NULL;
1095e8dbd92cSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
1096e8dbd92cSJens Wiklander struct serialargs ctrlargs = { };
1097e8dbd92cSJens Wiklander TEE_Param *ctrl = params;
1098e8dbd92cSJens Wiklander uint32_t pin_size = 0;
1099e8dbd92cSJens Wiklander void *pin = NULL;
1100e8dbd92cSJens Wiklander
1101e8dbd92cSJens Wiklander if (!client || ptypes != exp_pt)
1102e8dbd92cSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD;
1103e8dbd92cSJens Wiklander
1104e8dbd92cSJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
1105e8dbd92cSJens Wiklander
1106f40f331fSEtienne Carriere rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
1107e8dbd92cSJens Wiklander if (rc)
1108e8dbd92cSJens Wiklander return rc;
1109e8dbd92cSJens Wiklander
1110e8dbd92cSJens Wiklander rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t));
1111e8dbd92cSJens Wiklander if (rc)
1112e8dbd92cSJens Wiklander return rc;
1113e8dbd92cSJens Wiklander
1114e8dbd92cSJens Wiklander rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size);
1115e8dbd92cSJens Wiklander if (rc)
1116e8dbd92cSJens Wiklander return rc;
1117e8dbd92cSJens Wiklander
1118e8dbd92cSJens Wiklander if (serialargs_remaining_bytes(&ctrlargs))
1119e8dbd92cSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD;
1120e8dbd92cSJens Wiklander
1121e8dbd92cSJens Wiklander if (!pkcs11_session_is_so(session))
1122e8dbd92cSJens Wiklander return PKCS11_CKR_USER_NOT_LOGGED_IN;
1123e8dbd92cSJens Wiklander
1124e8dbd92cSJens Wiklander assert(session->token->db_main->flags & PKCS11_CKFT_TOKEN_INITIALIZED);
1125e8dbd92cSJens Wiklander
1126f40f331fSEtienne Carriere IMSG("PKCS11 session %"PRIu32": init PIN", session->handle);
1127e8dbd92cSJens Wiklander
1128e8dbd92cSJens Wiklander return set_pin(session, pin, pin_size, PKCS11_CKU_USER);
1129e8dbd92cSJens Wiklander }
11301dbb91e7SJens Wiklander
check_so_pin(struct pkcs11_session * session,uint8_t * pin,size_t pin_size)11314daf39b3SJens Wiklander static enum pkcs11_rc check_so_pin(struct pkcs11_session *session,
11321dbb91e7SJens Wiklander uint8_t *pin, size_t pin_size)
11331dbb91e7SJens Wiklander {
11341dbb91e7SJens Wiklander struct ck_token *token = session->token;
1135d75c42ffSLoic Poulain struct token_persistent_main *db = token->db_main;
11361dbb91e7SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
11371dbb91e7SJens Wiklander
1138d75c42ffSLoic Poulain assert(db->flags & PKCS11_CKFT_TOKEN_INITIALIZED);
11391dbb91e7SJens Wiklander
11401a27b197SVesa Jääskeläinen if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) &&
1141d75c42ffSLoic Poulain db->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH)
11421a27b197SVesa Jääskeläinen return verify_identity_auth(token, PKCS11_CKU_SO);
11431a27b197SVesa Jääskeläinen
1144d75c42ffSLoic Poulain if (db->flags & PKCS11_CKFT_SO_PIN_LOCKED)
11451dbb91e7SJens Wiklander return PKCS11_CKR_PIN_LOCKED;
11461dbb91e7SJens Wiklander
1147d75c42ffSLoic Poulain /*
1148d75c42ffSLoic Poulain * Preset the counter and flags conservatively in the database so that
1149d75c42ffSLoic Poulain * the tentative is saved whatever happens next.
1150d75c42ffSLoic Poulain */
1151d75c42ffSLoic Poulain db->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW;
1152d75c42ffSLoic Poulain db->so_pin_count++;
11531dbb91e7SJens Wiklander
1154d75c42ffSLoic Poulain if (db->so_pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1)
1155d75c42ffSLoic Poulain db->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY;
1156d75c42ffSLoic Poulain else if (db->so_pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX)
1157d75c42ffSLoic Poulain db->flags |= PKCS11_CKFT_SO_PIN_LOCKED;
11581dbb91e7SJens Wiklander
11591dbb91e7SJens Wiklander update_persistent_db(token);
11601dbb91e7SJens Wiklander
1161d75c42ffSLoic Poulain rc = verify_pin(PKCS11_CKU_SO, pin, pin_size,
1162d75c42ffSLoic Poulain db->so_pin_salt,
1163d75c42ffSLoic Poulain db->so_pin_hash);
1164d75c42ffSLoic Poulain if (rc == PKCS11_CKR_PIN_INCORRECT) {
1165d75c42ffSLoic Poulain if (db->flags & PKCS11_CKFT_SO_PIN_LOCKED)
11661dbb91e7SJens Wiklander return PKCS11_CKR_PIN_LOCKED;
11671dbb91e7SJens Wiklander
11681dbb91e7SJens Wiklander return PKCS11_CKR_PIN_INCORRECT;
11691dbb91e7SJens Wiklander }
11701dbb91e7SJens Wiklander
1171d75c42ffSLoic Poulain if (rc)
1172d75c42ffSLoic Poulain db->so_pin_count--;
1173d75c42ffSLoic Poulain else
1174d75c42ffSLoic Poulain db->so_pin_count = 0;
11751dbb91e7SJens Wiklander
1176d75c42ffSLoic Poulain db->flags &= ~PKCS11_CKFT_SO_PIN_LOCKED;
1177d75c42ffSLoic Poulain if (db->so_pin_count < PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1) {
1178d75c42ffSLoic Poulain db->flags &= ~PKCS11_CKFT_SO_PIN_FINAL_TRY;
1179d75c42ffSLoic Poulain if (!db->so_pin_count)
1180d75c42ffSLoic Poulain db->flags &= ~PKCS11_CKFT_SO_PIN_COUNT_LOW;
11811dbb91e7SJens Wiklander }
11821dbb91e7SJens Wiklander
11831dbb91e7SJens Wiklander update_persistent_db(token);
11841dbb91e7SJens Wiklander
1185d75c42ffSLoic Poulain return rc;
11861dbb91e7SJens Wiklander }
11871dbb91e7SJens Wiklander
check_user_pin(struct pkcs11_session * session,uint8_t * pin,size_t pin_size)11884daf39b3SJens Wiklander static enum pkcs11_rc check_user_pin(struct pkcs11_session *session,
11891dbb91e7SJens Wiklander uint8_t *pin, size_t pin_size)
11901dbb91e7SJens Wiklander {
11911dbb91e7SJens Wiklander struct ck_token *token = session->token;
1192d75c42ffSLoic Poulain struct token_persistent_main *db = token->db_main;
11931dbb91e7SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
11941dbb91e7SJens Wiklander
11952eba68d2SEtienne Carriere if (!(db->flags & PKCS11_CKFT_USER_PIN_INITIALIZED))
11962eba68d2SEtienne Carriere return PKCS11_CKR_USER_PIN_NOT_INITIALIZED;
11972eba68d2SEtienne Carriere
11981a27b197SVesa Jääskeläinen if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) &&
1199d75c42ffSLoic Poulain db->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH)
12001a27b197SVesa Jääskeläinen return verify_identity_auth(token, PKCS11_CKU_USER);
12011a27b197SVesa Jääskeläinen
12022eba68d2SEtienne Carriere assert(db->user_pin_salt);
12031dbb91e7SJens Wiklander
1204d75c42ffSLoic Poulain if (db->flags & PKCS11_CKFT_USER_PIN_LOCKED)
12051dbb91e7SJens Wiklander return PKCS11_CKR_PIN_LOCKED;
12061dbb91e7SJens Wiklander
1207d75c42ffSLoic Poulain /*
1208d75c42ffSLoic Poulain * Preset the counter and flags conservatively in the database so that
1209d75c42ffSLoic Poulain * the tentative is saved whatever happens next.
1210d75c42ffSLoic Poulain */
1211d75c42ffSLoic Poulain db->flags |= PKCS11_CKFT_USER_PIN_COUNT_LOW;
1212d75c42ffSLoic Poulain db->user_pin_count++;
12131dbb91e7SJens Wiklander
1214d75c42ffSLoic Poulain if (db->user_pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1)
1215d75c42ffSLoic Poulain db->flags |= PKCS11_CKFT_USER_PIN_FINAL_TRY;
1216d75c42ffSLoic Poulain else if (db->user_pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX)
1217d75c42ffSLoic Poulain db->flags |= PKCS11_CKFT_USER_PIN_LOCKED;
12181dbb91e7SJens Wiklander
12191dbb91e7SJens Wiklander update_persistent_db(token);
12201dbb91e7SJens Wiklander
1221d75c42ffSLoic Poulain rc = verify_pin(PKCS11_CKU_USER, pin, pin_size,
1222d75c42ffSLoic Poulain db->user_pin_salt,
1223d75c42ffSLoic Poulain db->user_pin_hash);
1224d75c42ffSLoic Poulain if (rc == PKCS11_CKR_PIN_INCORRECT) {
1225d75c42ffSLoic Poulain if (db->flags & PKCS11_CKFT_USER_PIN_LOCKED)
12261dbb91e7SJens Wiklander return PKCS11_CKR_PIN_LOCKED;
12271dbb91e7SJens Wiklander
12281dbb91e7SJens Wiklander return PKCS11_CKR_PIN_INCORRECT;
12291dbb91e7SJens Wiklander }
12301dbb91e7SJens Wiklander
1231d75c42ffSLoic Poulain if (rc)
1232d75c42ffSLoic Poulain db->user_pin_count--;
1233d75c42ffSLoic Poulain else
1234d75c42ffSLoic Poulain db->user_pin_count = 0;
12351dbb91e7SJens Wiklander
1236d75c42ffSLoic Poulain db->flags &= ~PKCS11_CKFT_USER_PIN_LOCKED;
1237d75c42ffSLoic Poulain if (db->user_pin_count < PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1) {
1238d75c42ffSLoic Poulain db->flags &= ~PKCS11_CKFT_USER_PIN_FINAL_TRY;
1239d75c42ffSLoic Poulain if (!db->user_pin_count)
1240d75c42ffSLoic Poulain db->flags &= ~PKCS11_CKFT_USER_PIN_COUNT_LOW;
12411dbb91e7SJens Wiklander }
12421dbb91e7SJens Wiklander
12431dbb91e7SJens Wiklander update_persistent_db(token);
12441dbb91e7SJens Wiklander
1245d75c42ffSLoic Poulain return rc;
12461dbb91e7SJens Wiklander }
12471dbb91e7SJens Wiklander
entry_ck_set_pin(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)12484daf39b3SJens Wiklander enum pkcs11_rc entry_ck_set_pin(struct pkcs11_client *client,
12491dbb91e7SJens Wiklander uint32_t ptypes, TEE_Param *params)
12501dbb91e7SJens Wiklander {
12511dbb91e7SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
12521dbb91e7SJens Wiklander TEE_PARAM_TYPE_NONE,
12531dbb91e7SJens Wiklander TEE_PARAM_TYPE_NONE,
12541dbb91e7SJens Wiklander TEE_PARAM_TYPE_NONE);
12551dbb91e7SJens Wiklander struct pkcs11_session *session = NULL;
12561dbb91e7SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
12571dbb91e7SJens Wiklander struct serialargs ctrlargs = { };
12581dbb91e7SJens Wiklander uint32_t old_pin_size = 0;
12591dbb91e7SJens Wiklander TEE_Param *ctrl = params;
12601dbb91e7SJens Wiklander uint32_t pin_size = 0;
12611dbb91e7SJens Wiklander void *old_pin = NULL;
12621dbb91e7SJens Wiklander void *pin = NULL;
12631dbb91e7SJens Wiklander
12641dbb91e7SJens Wiklander if (!client || ptypes != exp_pt)
12651dbb91e7SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD;
12661dbb91e7SJens Wiklander
12671dbb91e7SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
12681dbb91e7SJens Wiklander
1269f40f331fSEtienne Carriere rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
12701dbb91e7SJens Wiklander if (rc)
12711dbb91e7SJens Wiklander return rc;
12721dbb91e7SJens Wiklander
12731dbb91e7SJens Wiklander rc = serialargs_get(&ctrlargs, &old_pin_size, sizeof(uint32_t));
12741dbb91e7SJens Wiklander if (rc)
12751dbb91e7SJens Wiklander return rc;
12761dbb91e7SJens Wiklander
12771dbb91e7SJens Wiklander rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t));
12781dbb91e7SJens Wiklander if (rc)
12791dbb91e7SJens Wiklander return rc;
12801dbb91e7SJens Wiklander
12811dbb91e7SJens Wiklander rc = serialargs_get_ptr(&ctrlargs, &old_pin, old_pin_size);
12821dbb91e7SJens Wiklander if (rc)
12831dbb91e7SJens Wiklander return rc;
12841dbb91e7SJens Wiklander
12851dbb91e7SJens Wiklander rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size);
12861dbb91e7SJens Wiklander if (rc)
12871dbb91e7SJens Wiklander return rc;
12881dbb91e7SJens Wiklander
12891dbb91e7SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs))
12901dbb91e7SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD;
12911dbb91e7SJens Wiklander
12921dbb91e7SJens Wiklander if (!pkcs11_session_is_read_write(session))
12931dbb91e7SJens Wiklander return PKCS11_CKR_SESSION_READ_ONLY;
12941dbb91e7SJens Wiklander
12951dbb91e7SJens Wiklander if (pkcs11_session_is_so(session)) {
12961dbb91e7SJens Wiklander if (!(session->token->db_main->flags &
12971dbb91e7SJens Wiklander PKCS11_CKFT_TOKEN_INITIALIZED))
12981dbb91e7SJens Wiklander return PKCS11_CKR_GENERAL_ERROR;
12991dbb91e7SJens Wiklander
13001dbb91e7SJens Wiklander rc = check_so_pin(session, old_pin, old_pin_size);
13011dbb91e7SJens Wiklander if (rc)
13021dbb91e7SJens Wiklander return rc;
13031dbb91e7SJens Wiklander
1304f40f331fSEtienne Carriere IMSG("PKCS11 session %"PRIu32": set PIN", session->handle);
13051dbb91e7SJens Wiklander
13061dbb91e7SJens Wiklander return set_pin(session, pin, pin_size, PKCS11_CKU_SO);
13071dbb91e7SJens Wiklander }
13081dbb91e7SJens Wiklander
13091dbb91e7SJens Wiklander if (!(session->token->db_main->flags &
13101dbb91e7SJens Wiklander PKCS11_CKFT_USER_PIN_INITIALIZED))
13111dbb91e7SJens Wiklander return PKCS11_CKR_GENERAL_ERROR;
13121dbb91e7SJens Wiklander
13131dbb91e7SJens Wiklander rc = check_user_pin(session, old_pin, old_pin_size);
13141dbb91e7SJens Wiklander if (rc)
13151dbb91e7SJens Wiklander return rc;
13161dbb91e7SJens Wiklander
1317f40f331fSEtienne Carriere IMSG("PKCS11 session %"PRIu32": set PIN", session->handle);
13181dbb91e7SJens Wiklander
13191dbb91e7SJens Wiklander return set_pin(session, pin, pin_size, PKCS11_CKU_USER);
13201dbb91e7SJens Wiklander }
1321f7cc36c0SJens Wiklander
session_login_user(struct pkcs11_session * session)1322f7cc36c0SJens Wiklander static void session_login_user(struct pkcs11_session *session)
1323f7cc36c0SJens Wiklander {
1324f7cc36c0SJens Wiklander struct pkcs11_client *client = session->client;
1325f7cc36c0SJens Wiklander struct pkcs11_session *sess = NULL;
1326f7cc36c0SJens Wiklander
1327f7cc36c0SJens Wiklander TAILQ_FOREACH(sess, &client->session_list, link) {
1328f7cc36c0SJens Wiklander if (sess->token != session->token)
1329f7cc36c0SJens Wiklander continue;
1330f7cc36c0SJens Wiklander
1331f7cc36c0SJens Wiklander if (pkcs11_session_is_read_write(sess))
1332f7cc36c0SJens Wiklander sess->state = PKCS11_CKS_RW_USER_FUNCTIONS;
1333f7cc36c0SJens Wiklander else
1334f7cc36c0SJens Wiklander sess->state = PKCS11_CKS_RO_USER_FUNCTIONS;
1335f7cc36c0SJens Wiklander }
1336f7cc36c0SJens Wiklander }
1337f7cc36c0SJens Wiklander
session_login_so(struct pkcs11_session * session)1338f7cc36c0SJens Wiklander static void session_login_so(struct pkcs11_session *session)
1339f7cc36c0SJens Wiklander {
1340f7cc36c0SJens Wiklander struct pkcs11_client *client = session->client;
1341f7cc36c0SJens Wiklander struct pkcs11_session *sess = NULL;
1342f7cc36c0SJens Wiklander
1343f7cc36c0SJens Wiklander TAILQ_FOREACH(sess, &client->session_list, link) {
1344f7cc36c0SJens Wiklander if (sess->token != session->token)
1345f7cc36c0SJens Wiklander continue;
1346f7cc36c0SJens Wiklander
1347f7cc36c0SJens Wiklander if (pkcs11_session_is_read_write(sess))
1348f7cc36c0SJens Wiklander sess->state = PKCS11_CKS_RW_SO_FUNCTIONS;
1349f7cc36c0SJens Wiklander else
1350f7cc36c0SJens Wiklander TEE_Panic(0);
1351f7cc36c0SJens Wiklander }
1352f7cc36c0SJens Wiklander }
1353f7cc36c0SJens Wiklander
session_logout(struct pkcs11_session * session)1354f7cc36c0SJens Wiklander static void session_logout(struct pkcs11_session *session)
1355f7cc36c0SJens Wiklander {
1356f7cc36c0SJens Wiklander struct pkcs11_client *client = session->client;
1357f7cc36c0SJens Wiklander struct pkcs11_session *sess = NULL;
1358f7cc36c0SJens Wiklander
1359f7cc36c0SJens Wiklander TAILQ_FOREACH(sess, &client->session_list, link) {
136089735787SRuchika Gupta struct pkcs11_object *obj = NULL;
13613bf0e097SRuchika Gupta struct pkcs11_object *tobj = NULL;
136289735787SRuchika Gupta uint32_t handle = 0;
136389735787SRuchika Gupta
1364f7cc36c0SJens Wiklander if (sess->token != session->token)
1365f7cc36c0SJens Wiklander continue;
1366f7cc36c0SJens Wiklander
136789735787SRuchika Gupta release_active_processing(session);
136889735787SRuchika Gupta
136989735787SRuchika Gupta /* Destroy private session objects */
13703bf0e097SRuchika Gupta LIST_FOREACH_SAFE(obj, &sess->object_list, link, tobj) {
137189735787SRuchika Gupta if (object_is_private(obj->attributes))
137289735787SRuchika Gupta destroy_object(sess, obj, true);
137389735787SRuchika Gupta }
137489735787SRuchika Gupta
137589735787SRuchika Gupta /*
137689735787SRuchika Gupta * Remove handle of token private objects from
137789735787SRuchika Gupta * sessions object_handle_db
137889735787SRuchika Gupta */
137989735787SRuchika Gupta LIST_FOREACH(obj, &session->token->object_list, link) {
138089735787SRuchika Gupta handle = pkcs11_object2handle(obj, session);
138189735787SRuchika Gupta
138289735787SRuchika Gupta if (handle && object_is_private(obj->attributes))
1383bc555ee0SVesa Jääskeläinen handle_put(get_object_handle_db(sess), handle);
138489735787SRuchika Gupta }
138589735787SRuchika Gupta
138689735787SRuchika Gupta release_session_find_obj_context(session);
138789735787SRuchika Gupta
1388f7cc36c0SJens Wiklander if (pkcs11_session_is_read_write(sess))
1389f7cc36c0SJens Wiklander sess->state = PKCS11_CKS_RW_PUBLIC_SESSION;
1390f7cc36c0SJens Wiklander else
1391f7cc36c0SJens Wiklander sess->state = PKCS11_CKS_RO_PUBLIC_SESSION;
1392f7cc36c0SJens Wiklander }
1393f7cc36c0SJens Wiklander }
1394f7cc36c0SJens Wiklander
entry_ck_login(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)13954daf39b3SJens Wiklander enum pkcs11_rc entry_ck_login(struct pkcs11_client *client,
1396f7cc36c0SJens Wiklander uint32_t ptypes, TEE_Param *params)
1397f7cc36c0SJens Wiklander {
1398f7cc36c0SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
1399f7cc36c0SJens Wiklander TEE_PARAM_TYPE_NONE,
1400f7cc36c0SJens Wiklander TEE_PARAM_TYPE_NONE,
1401f7cc36c0SJens Wiklander TEE_PARAM_TYPE_NONE);
1402f7cc36c0SJens Wiklander struct pkcs11_session *session = NULL;
1403f7cc36c0SJens Wiklander struct pkcs11_session *sess = NULL;
1404f7cc36c0SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
1405f7cc36c0SJens Wiklander struct serialargs ctrlargs = { };
1406f7cc36c0SJens Wiklander TEE_Param *ctrl = params;
1407f7cc36c0SJens Wiklander uint32_t user_type = 0;
1408f7cc36c0SJens Wiklander uint32_t pin_size = 0;
1409f7cc36c0SJens Wiklander void *pin = NULL;
1410f7cc36c0SJens Wiklander
1411f7cc36c0SJens Wiklander if (!client || ptypes != exp_pt)
1412f7cc36c0SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD;
1413f7cc36c0SJens Wiklander
1414f7cc36c0SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
1415f7cc36c0SJens Wiklander
1416f40f331fSEtienne Carriere rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
1417f7cc36c0SJens Wiklander if (rc)
1418f7cc36c0SJens Wiklander return rc;
1419f7cc36c0SJens Wiklander
1420f7cc36c0SJens Wiklander rc = serialargs_get(&ctrlargs, &user_type, sizeof(uint32_t));
1421f7cc36c0SJens Wiklander if (rc)
1422f7cc36c0SJens Wiklander return rc;
1423f7cc36c0SJens Wiklander
1424f7cc36c0SJens Wiklander rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t));
1425f7cc36c0SJens Wiklander if (rc)
1426f7cc36c0SJens Wiklander return rc;
1427f7cc36c0SJens Wiklander
1428f7cc36c0SJens Wiklander rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size);
1429f7cc36c0SJens Wiklander if (rc)
1430f7cc36c0SJens Wiklander return rc;
1431f7cc36c0SJens Wiklander
1432f7cc36c0SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs))
1433f7cc36c0SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD;
1434f7cc36c0SJens Wiklander
1435f7cc36c0SJens Wiklander switch (user_type) {
1436f7cc36c0SJens Wiklander case PKCS11_CKU_SO:
1437f7cc36c0SJens Wiklander if (pkcs11_session_is_so(session))
1438f7cc36c0SJens Wiklander return PKCS11_CKR_USER_ALREADY_LOGGED_IN;
1439f7cc36c0SJens Wiklander
1440f7cc36c0SJens Wiklander if (pkcs11_session_is_user(session))
1441f7cc36c0SJens Wiklander return PKCS11_CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
1442f7cc36c0SJens Wiklander
1443f7cc36c0SJens Wiklander TAILQ_FOREACH(sess, &client->session_list, link)
1444f7cc36c0SJens Wiklander if (sess->token == session->token &&
1445f7cc36c0SJens Wiklander !pkcs11_session_is_read_write(sess))
1446f7cc36c0SJens Wiklander return PKCS11_CKR_SESSION_READ_ONLY_EXISTS;
1447f7cc36c0SJens Wiklander
1448f7cc36c0SJens Wiklander /*
1449f7cc36c0SJens Wiklander * This is the point where we could check if another client
1450f7cc36c0SJens Wiklander * has another user or SO logged in.
1451f7cc36c0SJens Wiklander *
1452f7cc36c0SJens Wiklander * The spec says:
1453f7cc36c0SJens Wiklander * CKR_USER_TOO_MANY_TYPES: An attempt was made to have
1454f7cc36c0SJens Wiklander * more distinct users simultaneously logged into the token
1455f7cc36c0SJens Wiklander * than the token and/or library permits. For example, if
1456f7cc36c0SJens Wiklander * some application has an open SO session, and another
1457f7cc36c0SJens Wiklander * application attempts to log the normal user into a
1458f7cc36c0SJens Wiklander * session, the attempt may return this error. It is not
1459f7cc36c0SJens Wiklander * required to, however. Only if the simultaneous distinct
1460f7cc36c0SJens Wiklander * users cannot be supported does C_Login have to return
1461f7cc36c0SJens Wiklander * this value. Note that this error code generalizes to
1462f7cc36c0SJens Wiklander * true multi-user tokens.
1463f7cc36c0SJens Wiklander *
1464f7cc36c0SJens Wiklander * So it's permitted to have another user or SO logged in
1465f7cc36c0SJens Wiklander * from another client.
1466f7cc36c0SJens Wiklander */
1467f7cc36c0SJens Wiklander
1468f7cc36c0SJens Wiklander rc = check_so_pin(session, pin, pin_size);
1469f7cc36c0SJens Wiklander if (!rc)
1470f7cc36c0SJens Wiklander session_login_so(session);
1471f7cc36c0SJens Wiklander
1472f7cc36c0SJens Wiklander break;
1473f7cc36c0SJens Wiklander
1474f7cc36c0SJens Wiklander case PKCS11_CKU_USER:
1475f7cc36c0SJens Wiklander if (pkcs11_session_is_so(session))
1476f7cc36c0SJens Wiklander return PKCS11_CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
1477f7cc36c0SJens Wiklander
1478f7cc36c0SJens Wiklander if (pkcs11_session_is_user(session))
1479f7cc36c0SJens Wiklander return PKCS11_CKR_USER_ALREADY_LOGGED_IN;
1480f7cc36c0SJens Wiklander
1481f7cc36c0SJens Wiklander /*
1482f7cc36c0SJens Wiklander * This is the point where we could check if another client
1483f7cc36c0SJens Wiklander * has another user or SO logged in.
1484f7cc36c0SJens Wiklander * See comment on CKR_USER_TOO_MANY_TYPES above.
1485f7cc36c0SJens Wiklander */
1486f7cc36c0SJens Wiklander
1487f7cc36c0SJens Wiklander rc = check_user_pin(session, pin, pin_size);
1488f7cc36c0SJens Wiklander if (!rc)
1489f7cc36c0SJens Wiklander session_login_user(session);
1490f7cc36c0SJens Wiklander
1491f7cc36c0SJens Wiklander break;
1492f7cc36c0SJens Wiklander
1493f7cc36c0SJens Wiklander case PKCS11_CKU_CONTEXT_SPECIFIC:
1494f7cc36c0SJens Wiklander return PKCS11_CKR_OPERATION_NOT_INITIALIZED;
1495f7cc36c0SJens Wiklander
1496f7cc36c0SJens Wiklander default:
1497f7cc36c0SJens Wiklander return PKCS11_CKR_USER_TYPE_INVALID;
1498f7cc36c0SJens Wiklander }
1499f7cc36c0SJens Wiklander
1500f7cc36c0SJens Wiklander if (!rc)
1501f40f331fSEtienne Carriere IMSG("PKCS11 session %"PRIu32": login", session->handle);
1502f7cc36c0SJens Wiklander
1503f7cc36c0SJens Wiklander return rc;
1504f7cc36c0SJens Wiklander }
1505f7cc36c0SJens Wiklander
entry_ck_logout(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)15064daf39b3SJens Wiklander enum pkcs11_rc entry_ck_logout(struct pkcs11_client *client,
1507f7cc36c0SJens Wiklander uint32_t ptypes, TEE_Param *params)
1508f7cc36c0SJens Wiklander {
1509f7cc36c0SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
1510f7cc36c0SJens Wiklander TEE_PARAM_TYPE_NONE,
1511f7cc36c0SJens Wiklander TEE_PARAM_TYPE_NONE,
1512f7cc36c0SJens Wiklander TEE_PARAM_TYPE_NONE);
1513f7cc36c0SJens Wiklander struct pkcs11_session *session = NULL;
1514f7cc36c0SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
1515f7cc36c0SJens Wiklander struct serialargs ctrlargs = { };
1516f7cc36c0SJens Wiklander TEE_Param *ctrl = params;
1517f7cc36c0SJens Wiklander
1518f7cc36c0SJens Wiklander if (!client || ptypes != exp_pt)
1519f7cc36c0SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD;
1520f7cc36c0SJens Wiklander
1521f7cc36c0SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
1522f7cc36c0SJens Wiklander
1523f40f331fSEtienne Carriere rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
1524f7cc36c0SJens Wiklander if (rc)
1525f7cc36c0SJens Wiklander return rc;
1526f7cc36c0SJens Wiklander
1527f7cc36c0SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs))
1528f7cc36c0SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD;
1529f7cc36c0SJens Wiklander
1530f7cc36c0SJens Wiklander if (pkcs11_session_is_public(session))
1531f7cc36c0SJens Wiklander return PKCS11_CKR_USER_NOT_LOGGED_IN;
1532f7cc36c0SJens Wiklander
1533f7cc36c0SJens Wiklander session_logout(session);
1534f7cc36c0SJens Wiklander
1535f40f331fSEtienne Carriere IMSG("PKCS11 session %"PRIu32": logout", session->handle);
1536f7cc36c0SJens Wiklander
1537f7cc36c0SJens Wiklander return PKCS11_CKR_OK;
1538f7cc36c0SJens Wiklander }
153922587dc4SVesa Jääskeläinen
seed_rng_pool(void * seed,size_t length)154022587dc4SVesa Jääskeläinen static TEE_Result seed_rng_pool(void *seed, size_t length)
154122587dc4SVesa Jääskeläinen {
154222587dc4SVesa Jääskeläinen static const TEE_UUID system_uuid = PTA_SYSTEM_UUID;
154322587dc4SVesa Jääskeläinen uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
154422587dc4SVesa Jääskeläinen TEE_PARAM_TYPE_NONE,
154522587dc4SVesa Jääskeläinen TEE_PARAM_TYPE_NONE,
154622587dc4SVesa Jääskeläinen TEE_PARAM_TYPE_NONE);
154722587dc4SVesa Jääskeläinen TEE_Param params[TEE_NUM_PARAMS] = { };
154822587dc4SVesa Jääskeläinen TEE_TASessionHandle sess = TEE_HANDLE_NULL;
154922587dc4SVesa Jääskeläinen TEE_Result res = TEE_ERROR_GENERIC;
155022587dc4SVesa Jääskeläinen uint32_t ret_orig = 0;
155122587dc4SVesa Jääskeläinen
155222587dc4SVesa Jääskeläinen params[0].memref.buffer = seed;
155322587dc4SVesa Jääskeläinen params[0].memref.size = (uint32_t)length;
155422587dc4SVesa Jääskeläinen
155522587dc4SVesa Jääskeläinen res = TEE_OpenTASession(&system_uuid, TEE_TIMEOUT_INFINITE, 0, NULL,
155622587dc4SVesa Jääskeläinen &sess, &ret_orig);
155722587dc4SVesa Jääskeläinen if (res != TEE_SUCCESS) {
155822587dc4SVesa Jääskeläinen EMSG("Can't open session to system PTA");
155922587dc4SVesa Jääskeläinen return res;
156022587dc4SVesa Jääskeläinen }
156122587dc4SVesa Jääskeläinen
156222587dc4SVesa Jääskeläinen res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE,
156322587dc4SVesa Jääskeläinen PTA_SYSTEM_ADD_RNG_ENTROPY,
156422587dc4SVesa Jääskeläinen param_types, params, &ret_orig);
156522587dc4SVesa Jääskeläinen if (res != TEE_SUCCESS)
156622587dc4SVesa Jääskeläinen EMSG("Can't invoke system PTA");
156722587dc4SVesa Jääskeläinen
156822587dc4SVesa Jääskeläinen TEE_CloseTASession(sess);
156922587dc4SVesa Jääskeläinen return res;
157022587dc4SVesa Jääskeläinen }
157122587dc4SVesa Jääskeläinen
entry_ck_seed_random(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)157222587dc4SVesa Jääskeläinen enum pkcs11_rc entry_ck_seed_random(struct pkcs11_client *client,
157322587dc4SVesa Jääskeläinen uint32_t ptypes, TEE_Param *params)
157422587dc4SVesa Jääskeläinen {
157522587dc4SVesa Jääskeläinen const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
157622587dc4SVesa Jääskeläinen TEE_PARAM_TYPE_MEMREF_INPUT,
157722587dc4SVesa Jääskeläinen TEE_PARAM_TYPE_NONE,
157822587dc4SVesa Jääskeläinen TEE_PARAM_TYPE_NONE);
157922587dc4SVesa Jääskeläinen TEE_Param *ctrl = params;
158022587dc4SVesa Jääskeläinen TEE_Param *in = params + 1;
158122587dc4SVesa Jääskeläinen enum pkcs11_rc rc = PKCS11_CKR_OK;
158222587dc4SVesa Jääskeläinen struct serialargs ctrlargs = { };
158322587dc4SVesa Jääskeläinen struct pkcs11_session *session = NULL;
158422587dc4SVesa Jääskeläinen TEE_Result res = TEE_SUCCESS;
158522587dc4SVesa Jääskeläinen
158622587dc4SVesa Jääskeläinen if (!client || ptypes != exp_pt)
158722587dc4SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD;
158822587dc4SVesa Jääskeläinen
158922587dc4SVesa Jääskeläinen serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
159022587dc4SVesa Jääskeläinen
159122587dc4SVesa Jääskeläinen rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
159222587dc4SVesa Jääskeläinen if (rc)
159322587dc4SVesa Jääskeläinen return rc;
159422587dc4SVesa Jääskeläinen
159522587dc4SVesa Jääskeläinen if (serialargs_remaining_bytes(&ctrlargs))
159622587dc4SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD;
159722587dc4SVesa Jääskeläinen
159822587dc4SVesa Jääskeläinen if (in->memref.size && !in->memref.buffer)
159922587dc4SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD;
160022587dc4SVesa Jääskeläinen
160122587dc4SVesa Jääskeläinen if (!in->memref.size)
160222587dc4SVesa Jääskeläinen return PKCS11_CKR_OK;
160322587dc4SVesa Jääskeläinen
160422587dc4SVesa Jääskeläinen res = seed_rng_pool(in->memref.buffer, in->memref.size);
160522587dc4SVesa Jääskeläinen if (res != TEE_SUCCESS)
160622587dc4SVesa Jääskeläinen return PKCS11_CKR_FUNCTION_FAILED;
160722587dc4SVesa Jääskeläinen
160822587dc4SVesa Jääskeläinen DMSG("PKCS11 session %"PRIu32": seed random", session->handle);
160922587dc4SVesa Jääskeläinen
161022587dc4SVesa Jääskeläinen return PKCS11_CKR_OK;
161122587dc4SVesa Jääskeläinen }
161222587dc4SVesa Jääskeläinen
entry_ck_generate_random(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)161322587dc4SVesa Jääskeläinen enum pkcs11_rc entry_ck_generate_random(struct pkcs11_client *client,
161422587dc4SVesa Jääskeläinen uint32_t ptypes, TEE_Param *params)
161522587dc4SVesa Jääskeläinen {
161622587dc4SVesa Jääskeläinen const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
161722587dc4SVesa Jääskeläinen TEE_PARAM_TYPE_NONE,
161822587dc4SVesa Jääskeläinen TEE_PARAM_TYPE_MEMREF_OUTPUT,
161922587dc4SVesa Jääskeläinen TEE_PARAM_TYPE_NONE);
162022587dc4SVesa Jääskeläinen TEE_Param *ctrl = params;
162122587dc4SVesa Jääskeläinen TEE_Param *out = params + 2;
162222587dc4SVesa Jääskeläinen enum pkcs11_rc rc = PKCS11_CKR_OK;
162322587dc4SVesa Jääskeläinen struct serialargs ctrlargs = { };
162422587dc4SVesa Jääskeläinen struct pkcs11_session *session = NULL;
162522587dc4SVesa Jääskeläinen void *buffer = NULL;
162622587dc4SVesa Jääskeläinen size_t buffer_size = 0;
162722587dc4SVesa Jääskeläinen uint8_t *data = NULL;
162822587dc4SVesa Jääskeläinen size_t left = 0;
162922587dc4SVesa Jääskeläinen
163022587dc4SVesa Jääskeläinen if (!client || ptypes != exp_pt)
163122587dc4SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD;
163222587dc4SVesa Jääskeläinen
163322587dc4SVesa Jääskeläinen serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
163422587dc4SVesa Jääskeläinen
163522587dc4SVesa Jääskeläinen rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
163622587dc4SVesa Jääskeläinen if (rc)
163722587dc4SVesa Jääskeläinen return rc;
163822587dc4SVesa Jääskeläinen
163922587dc4SVesa Jääskeläinen if (serialargs_remaining_bytes(&ctrlargs))
164022587dc4SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD;
164122587dc4SVesa Jääskeläinen
164222587dc4SVesa Jääskeläinen if (out->memref.size && !out->memref.buffer)
164322587dc4SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD;
164422587dc4SVesa Jääskeläinen
164522587dc4SVesa Jääskeläinen if (!out->memref.size)
164622587dc4SVesa Jääskeläinen return PKCS11_CKR_OK;
164722587dc4SVesa Jääskeläinen
164822587dc4SVesa Jääskeläinen buffer_size = MIN(out->memref.size, RNG_CHUNK_SIZE);
164922587dc4SVesa Jääskeläinen buffer = TEE_Malloc(buffer_size, TEE_MALLOC_FILL_ZERO);
165022587dc4SVesa Jääskeläinen if (!buffer)
165122587dc4SVesa Jääskeläinen return PKCS11_CKR_DEVICE_MEMORY;
165222587dc4SVesa Jääskeläinen
165322587dc4SVesa Jääskeläinen data = out->memref.buffer;
165422587dc4SVesa Jääskeläinen left = out->memref.size;
165522587dc4SVesa Jääskeläinen
165622587dc4SVesa Jääskeläinen while (left) {
165722587dc4SVesa Jääskeläinen size_t count = MIN(left, buffer_size);
165822587dc4SVesa Jääskeläinen
165922587dc4SVesa Jääskeläinen TEE_GenerateRandom(buffer, count);
166022587dc4SVesa Jääskeläinen TEE_MemMove(data, buffer, count);
166122587dc4SVesa Jääskeläinen
166222587dc4SVesa Jääskeläinen data += count;
166322587dc4SVesa Jääskeläinen left -= count;
166422587dc4SVesa Jääskeläinen }
166522587dc4SVesa Jääskeläinen
166622587dc4SVesa Jääskeläinen DMSG("PKCS11 session %"PRIu32": generate random", session->handle);
166722587dc4SVesa Jääskeläinen
166822587dc4SVesa Jääskeläinen TEE_Free(buffer);
166922587dc4SVesa Jääskeläinen
167022587dc4SVesa Jääskeläinen return PKCS11_CKR_OK;
167122587dc4SVesa Jääskeläinen }
1672