xref: /optee_os/ta/pkcs11/src/pkcs11_token.c (revision ce94efefb619f4d10aa95e81c2fe02a7dd03b753)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2017-2020, Linaro Limited
4  */
5 
6 #include <assert.h>
7 #include <confine_array_index.h>
8 #include <pkcs11_ta.h>
9 #include <string.h>
10 #include <string_ext.h>
11 #include <sys/queue.h>
12 #include <tee_api_types.h>
13 #include <tee_internal_api_extensions.h>
14 #include <util.h>
15 
16 #include "pkcs11_token.h"
17 #include "pkcs11_helpers.h"
18 #include "serializer.h"
19 
20 /* Provide 3 slots/tokens, ID is token index */
21 #ifndef CFG_PKCS11_TA_TOKEN_COUNT
22 #define TOKEN_COUNT		3
23 #else
24 #define TOKEN_COUNT		CFG_PKCS11_TA_TOKEN_COUNT
25 #endif
26 
27 /* Static allocation of tokens runtime instances (reset to 0 at load) */
28 struct ck_token ck_token[TOKEN_COUNT];
29 
30 struct ck_token *get_token(unsigned int token_id)
31 {
32 	if (token_id < TOKEN_COUNT)
33 		return &ck_token[confine_array_index(token_id, TOKEN_COUNT)];
34 
35 	return NULL;
36 }
37 
38 unsigned int get_token_id(struct ck_token *token)
39 {
40 	ptrdiff_t id = token - ck_token;
41 
42 	assert(id >= 0 && id < TOKEN_COUNT);
43 	return id;
44 }
45 
46 static TEE_Result pkcs11_token_init(unsigned int id)
47 {
48 	struct ck_token *token = init_persistent_db(id);
49 
50 	if (!token)
51 		return TEE_ERROR_SECURITY;
52 
53 	if (token->state == PKCS11_TOKEN_RESET) {
54 		/* As per PKCS#11 spec, token resets to read/write state */
55 		token->state = PKCS11_TOKEN_READ_WRITE;
56 		token->session_count = 0;
57 		token->rw_session_count = 0;
58 	}
59 
60 	return TEE_SUCCESS;
61 }
62 
63 TEE_Result pkcs11_init(void)
64 {
65 	unsigned int id = 0;
66 	TEE_Result ret = TEE_ERROR_GENERIC;
67 
68 	for (id = 0; id < TOKEN_COUNT; id++) {
69 		ret = pkcs11_token_init(id);
70 		if (ret)
71 			return ret;
72 	}
73 
74 	return ret;
75 }
76 
77 void pkcs11_deinit(void)
78 {
79 	unsigned int id = 0;
80 
81 	for (id = 0; id < TOKEN_COUNT; id++)
82 		close_persistent_db(get_token(id));
83 }
84 
85 uint32_t entry_ck_slot_list(uint32_t ptypes, TEE_Param *params)
86 {
87 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
88 						TEE_PARAM_TYPE_NONE,
89 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
90 						TEE_PARAM_TYPE_NONE);
91 	TEE_Param *out = &params[2];
92 	uint32_t token_id = 0;
93 	const size_t out_size = sizeof(token_id) * TOKEN_COUNT;
94 	uint8_t *id = NULL;
95 
96 	if (ptypes != exp_pt ||
97 	    params[0].memref.size != TEE_PARAM0_SIZE_MIN)
98 		return PKCS11_CKR_ARGUMENTS_BAD;
99 
100 	if (out->memref.size < out_size) {
101 		out->memref.size = out_size;
102 
103 		if (out->memref.buffer)
104 			return PKCS11_CKR_BUFFER_TOO_SMALL;
105 		else
106 			return PKCS11_CKR_OK;
107 	}
108 
109 	for (token_id = 0, id = out->memref.buffer; token_id < TOKEN_COUNT;
110 	     token_id++, id += sizeof(token_id))
111 		TEE_MemMove(id, &token_id, sizeof(token_id));
112 
113 	out->memref.size = out_size;
114 
115 	return PKCS11_CKR_OK;
116 }
117 
118 uint32_t entry_ck_slot_info(uint32_t ptypes, TEE_Param *params)
119 {
120 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
121 						TEE_PARAM_TYPE_NONE,
122 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
123 						TEE_PARAM_TYPE_NONE);
124 	TEE_Param *ctrl = &params[0];
125 	TEE_Param *out = &params[2];
126 	uint32_t rv = 0;
127 	struct serialargs ctrlargs = { };
128 	uint32_t token_id = 0;
129 	struct ck_token *token = NULL;
130 	struct pkcs11_slot_info info = {
131 		.slot_description = PKCS11_SLOT_DESCRIPTION,
132 		.manufacturer_id = PKCS11_SLOT_MANUFACTURER,
133 		.flags = PKCS11_CKFS_TOKEN_PRESENT,
134 		.hardware_version = PKCS11_SLOT_HW_VERSION,
135 		.firmware_version = PKCS11_SLOT_FW_VERSION,
136 	};
137 	int n = 0;
138 
139 	COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_DESCRIPTION) <=
140 			    sizeof(info.slot_description));
141 	COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_MANUFACTURER) <=
142 			    sizeof(info.manufacturer_id));
143 
144 	if (ptypes != exp_pt || out->memref.size != sizeof(info))
145 		return PKCS11_CKR_ARGUMENTS_BAD;
146 
147 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
148 
149 	rv = serialargs_get(&ctrlargs, &token_id, sizeof(token_id));
150 	if (rv)
151 		return rv;
152 
153 	if (serialargs_remaining_bytes(&ctrlargs))
154 		return PKCS11_CKR_ARGUMENTS_BAD;
155 
156 	token = get_token(token_id);
157 	if (!token)
158 		return PKCS11_CKR_SLOT_ID_INVALID;
159 
160 	/* Pad string identifiers with blank characters */
161 	n = strnlen((char *)info.slot_description,
162 		    sizeof(info.slot_description));
163 	TEE_MemFill(&info.slot_description[n], ' ',
164 		    sizeof(info.slot_description) - n);
165 
166 	n = strnlen((char *)info.manufacturer_id,
167 		    sizeof(info.manufacturer_id));
168 	TEE_MemFill(&info.manufacturer_id[n], ' ',
169 		    sizeof(info.manufacturer_id) - n);
170 
171 	out->memref.size = sizeof(info);
172 	TEE_MemMove(out->memref.buffer, &info, out->memref.size);
173 
174 	return PKCS11_CKR_OK;
175 }
176