xref: /optee_os/ta/pkcs11/src/pkcs11_token.c (revision ce94efefb619f4d10aa95e81c2fe02a7dd03b753)
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>
7d38f9635SEtienne Carriere #include <confine_array_index.h>
8c84ccd0aSEtienne Carriere #include <pkcs11_ta.h>
9c84ccd0aSEtienne Carriere #include <string.h>
10c84ccd0aSEtienne Carriere #include <string_ext.h>
11c84ccd0aSEtienne Carriere #include <sys/queue.h>
12c84ccd0aSEtienne Carriere #include <tee_api_types.h>
13c84ccd0aSEtienne Carriere #include <tee_internal_api_extensions.h>
14c84ccd0aSEtienne Carriere #include <util.h>
15c84ccd0aSEtienne Carriere 
16c84ccd0aSEtienne Carriere #include "pkcs11_token.h"
17c84ccd0aSEtienne Carriere #include "pkcs11_helpers.h"
1822ac6984SEtienne Carriere #include "serializer.h"
19c84ccd0aSEtienne Carriere 
20c84ccd0aSEtienne Carriere /* Provide 3 slots/tokens, ID is token index */
21c84ccd0aSEtienne Carriere #ifndef CFG_PKCS11_TA_TOKEN_COUNT
22c84ccd0aSEtienne Carriere #define TOKEN_COUNT		3
23c84ccd0aSEtienne Carriere #else
24c84ccd0aSEtienne Carriere #define TOKEN_COUNT		CFG_PKCS11_TA_TOKEN_COUNT
25c84ccd0aSEtienne Carriere #endif
26c84ccd0aSEtienne Carriere 
27c84ccd0aSEtienne Carriere /* Static allocation of tokens runtime instances (reset to 0 at load) */
28c84ccd0aSEtienne Carriere struct ck_token ck_token[TOKEN_COUNT];
29c84ccd0aSEtienne Carriere 
30c84ccd0aSEtienne Carriere struct ck_token *get_token(unsigned int token_id)
31c84ccd0aSEtienne Carriere {
32d38f9635SEtienne Carriere 	if (token_id < TOKEN_COUNT)
33d38f9635SEtienne Carriere 		return &ck_token[confine_array_index(token_id, TOKEN_COUNT)];
34c84ccd0aSEtienne Carriere 
35d38f9635SEtienne Carriere 	return NULL;
36c84ccd0aSEtienne Carriere }
37c84ccd0aSEtienne Carriere 
38c84ccd0aSEtienne Carriere unsigned int get_token_id(struct ck_token *token)
39c84ccd0aSEtienne Carriere {
40c84ccd0aSEtienne Carriere 	ptrdiff_t id = token - ck_token;
41c84ccd0aSEtienne Carriere 
42c84ccd0aSEtienne Carriere 	assert(id >= 0 && id < TOKEN_COUNT);
43c84ccd0aSEtienne Carriere 	return id;
44c84ccd0aSEtienne Carriere }
45c84ccd0aSEtienne Carriere 
46c84ccd0aSEtienne Carriere static TEE_Result pkcs11_token_init(unsigned int id)
47c84ccd0aSEtienne Carriere {
48c84ccd0aSEtienne Carriere 	struct ck_token *token = init_persistent_db(id);
49c84ccd0aSEtienne Carriere 
50c84ccd0aSEtienne Carriere 	if (!token)
51c84ccd0aSEtienne Carriere 		return TEE_ERROR_SECURITY;
52c84ccd0aSEtienne Carriere 
53c84ccd0aSEtienne Carriere 	if (token->state == PKCS11_TOKEN_RESET) {
54c84ccd0aSEtienne Carriere 		/* As per PKCS#11 spec, token resets to read/write state */
55c84ccd0aSEtienne Carriere 		token->state = PKCS11_TOKEN_READ_WRITE;
56c84ccd0aSEtienne Carriere 		token->session_count = 0;
57c84ccd0aSEtienne Carriere 		token->rw_session_count = 0;
58c84ccd0aSEtienne Carriere 	}
59c84ccd0aSEtienne Carriere 
60c84ccd0aSEtienne Carriere 	return TEE_SUCCESS;
61c84ccd0aSEtienne Carriere }
62c84ccd0aSEtienne Carriere 
63c84ccd0aSEtienne Carriere TEE_Result pkcs11_init(void)
64c84ccd0aSEtienne Carriere {
65c84ccd0aSEtienne Carriere 	unsigned int id = 0;
66c84ccd0aSEtienne Carriere 	TEE_Result ret = TEE_ERROR_GENERIC;
67c84ccd0aSEtienne Carriere 
68c84ccd0aSEtienne Carriere 	for (id = 0; id < TOKEN_COUNT; id++) {
69c84ccd0aSEtienne Carriere 		ret = pkcs11_token_init(id);
70c84ccd0aSEtienne Carriere 		if (ret)
71c84ccd0aSEtienne Carriere 			return ret;
72c84ccd0aSEtienne Carriere 	}
73c84ccd0aSEtienne Carriere 
74c84ccd0aSEtienne Carriere 	return ret;
75c84ccd0aSEtienne Carriere }
76c84ccd0aSEtienne Carriere 
77c84ccd0aSEtienne Carriere void pkcs11_deinit(void)
78c84ccd0aSEtienne Carriere {
79c84ccd0aSEtienne Carriere 	unsigned int id = 0;
80c84ccd0aSEtienne Carriere 
81c84ccd0aSEtienne Carriere 	for (id = 0; id < TOKEN_COUNT; id++)
82c84ccd0aSEtienne Carriere 		close_persistent_db(get_token(id));
83c84ccd0aSEtienne Carriere }
8422ac6984SEtienne Carriere 
8522ac6984SEtienne Carriere uint32_t entry_ck_slot_list(uint32_t ptypes, TEE_Param *params)
8622ac6984SEtienne Carriere {
8722ac6984SEtienne Carriere 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
8822ac6984SEtienne Carriere 						TEE_PARAM_TYPE_NONE,
8922ac6984SEtienne Carriere 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
9022ac6984SEtienne Carriere 						TEE_PARAM_TYPE_NONE);
9122ac6984SEtienne Carriere 	TEE_Param *out = &params[2];
9222ac6984SEtienne Carriere 	uint32_t token_id = 0;
9322ac6984SEtienne Carriere 	const size_t out_size = sizeof(token_id) * TOKEN_COUNT;
9422ac6984SEtienne Carriere 	uint8_t *id = NULL;
9522ac6984SEtienne Carriere 
9622ac6984SEtienne Carriere 	if (ptypes != exp_pt ||
9722ac6984SEtienne Carriere 	    params[0].memref.size != TEE_PARAM0_SIZE_MIN)
9822ac6984SEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
9922ac6984SEtienne Carriere 
10022ac6984SEtienne Carriere 	if (out->memref.size < out_size) {
10122ac6984SEtienne Carriere 		out->memref.size = out_size;
10222ac6984SEtienne Carriere 
10322ac6984SEtienne Carriere 		if (out->memref.buffer)
10422ac6984SEtienne Carriere 			return PKCS11_CKR_BUFFER_TOO_SMALL;
10522ac6984SEtienne Carriere 		else
10622ac6984SEtienne Carriere 			return PKCS11_CKR_OK;
10722ac6984SEtienne Carriere 	}
10822ac6984SEtienne Carriere 
10922ac6984SEtienne Carriere 	for (token_id = 0, id = out->memref.buffer; token_id < TOKEN_COUNT;
11022ac6984SEtienne Carriere 	     token_id++, id += sizeof(token_id))
11122ac6984SEtienne Carriere 		TEE_MemMove(id, &token_id, sizeof(token_id));
11222ac6984SEtienne Carriere 
11322ac6984SEtienne Carriere 	out->memref.size = out_size;
11422ac6984SEtienne Carriere 
11522ac6984SEtienne Carriere 	return PKCS11_CKR_OK;
11622ac6984SEtienne Carriere }
117*ce94efefSEtienne Carriere 
118*ce94efefSEtienne Carriere uint32_t entry_ck_slot_info(uint32_t ptypes, TEE_Param *params)
119*ce94efefSEtienne Carriere {
120*ce94efefSEtienne Carriere 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
121*ce94efefSEtienne Carriere 						TEE_PARAM_TYPE_NONE,
122*ce94efefSEtienne Carriere 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
123*ce94efefSEtienne Carriere 						TEE_PARAM_TYPE_NONE);
124*ce94efefSEtienne Carriere 	TEE_Param *ctrl = &params[0];
125*ce94efefSEtienne Carriere 	TEE_Param *out = &params[2];
126*ce94efefSEtienne Carriere 	uint32_t rv = 0;
127*ce94efefSEtienne Carriere 	struct serialargs ctrlargs = { };
128*ce94efefSEtienne Carriere 	uint32_t token_id = 0;
129*ce94efefSEtienne Carriere 	struct ck_token *token = NULL;
130*ce94efefSEtienne Carriere 	struct pkcs11_slot_info info = {
131*ce94efefSEtienne Carriere 		.slot_description = PKCS11_SLOT_DESCRIPTION,
132*ce94efefSEtienne Carriere 		.manufacturer_id = PKCS11_SLOT_MANUFACTURER,
133*ce94efefSEtienne Carriere 		.flags = PKCS11_CKFS_TOKEN_PRESENT,
134*ce94efefSEtienne Carriere 		.hardware_version = PKCS11_SLOT_HW_VERSION,
135*ce94efefSEtienne Carriere 		.firmware_version = PKCS11_SLOT_FW_VERSION,
136*ce94efefSEtienne Carriere 	};
137*ce94efefSEtienne Carriere 	int n = 0;
138*ce94efefSEtienne Carriere 
139*ce94efefSEtienne Carriere 	COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_DESCRIPTION) <=
140*ce94efefSEtienne Carriere 			    sizeof(info.slot_description));
141*ce94efefSEtienne Carriere 	COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_MANUFACTURER) <=
142*ce94efefSEtienne Carriere 			    sizeof(info.manufacturer_id));
143*ce94efefSEtienne Carriere 
144*ce94efefSEtienne Carriere 	if (ptypes != exp_pt || out->memref.size != sizeof(info))
145*ce94efefSEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
146*ce94efefSEtienne Carriere 
147*ce94efefSEtienne Carriere 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
148*ce94efefSEtienne Carriere 
149*ce94efefSEtienne Carriere 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(token_id));
150*ce94efefSEtienne Carriere 	if (rv)
151*ce94efefSEtienne Carriere 		return rv;
152*ce94efefSEtienne Carriere 
153*ce94efefSEtienne Carriere 	if (serialargs_remaining_bytes(&ctrlargs))
154*ce94efefSEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
155*ce94efefSEtienne Carriere 
156*ce94efefSEtienne Carriere 	token = get_token(token_id);
157*ce94efefSEtienne Carriere 	if (!token)
158*ce94efefSEtienne Carriere 		return PKCS11_CKR_SLOT_ID_INVALID;
159*ce94efefSEtienne Carriere 
160*ce94efefSEtienne Carriere 	/* Pad string identifiers with blank characters */
161*ce94efefSEtienne Carriere 	n = strnlen((char *)info.slot_description,
162*ce94efefSEtienne Carriere 		    sizeof(info.slot_description));
163*ce94efefSEtienne Carriere 	TEE_MemFill(&info.slot_description[n], ' ',
164*ce94efefSEtienne Carriere 		    sizeof(info.slot_description) - n);
165*ce94efefSEtienne Carriere 
166*ce94efefSEtienne Carriere 	n = strnlen((char *)info.manufacturer_id,
167*ce94efefSEtienne Carriere 		    sizeof(info.manufacturer_id));
168*ce94efefSEtienne Carriere 	TEE_MemFill(&info.manufacturer_id[n], ' ',
169*ce94efefSEtienne Carriere 		    sizeof(info.manufacturer_id) - n);
170*ce94efefSEtienne Carriere 
171*ce94efefSEtienne Carriere 	out->memref.size = sizeof(info);
172*ce94efefSEtienne Carriere 	TEE_MemMove(out->memref.buffer, &info, out->memref.size);
173*ce94efefSEtienne Carriere 
174*ce94efefSEtienne Carriere 	return PKCS11_CKR_OK;
175*ce94efefSEtienne Carriere }
176