xref: /optee_os/ta/pkcs11/src/entry.c (revision e43ab7a8557a87604fc4fccc0ac03b0bcac81b83)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2018-2020, Linaro Limited
4  */
5 
6 #include <assert.h>
7 #include <compiler.h>
8 #include <pkcs11_ta.h>
9 #include <tee_internal_api.h>
10 #include <tee_internal_api_extensions.h>
11 #include <util.h>
12 
13 #include "pkcs11_helpers.h"
14 #include "pkcs11_token.h"
15 
16 TEE_Result TA_CreateEntryPoint(void)
17 {
18 	return pkcs11_init();
19 }
20 
21 void TA_DestroyEntryPoint(void)
22 {
23 	pkcs11_deinit();
24 }
25 
26 TEE_Result TA_OpenSessionEntryPoint(uint32_t __unused param_types,
27 				    TEE_Param __unused params[4],
28 				    void **session)
29 {
30 	*session = NULL;
31 
32 	return TEE_SUCCESS;
33 }
34 
35 void TA_CloseSessionEntryPoint(void *session __unused)
36 {
37 }
38 
39 /*
40  * Entry point for invocation command PKCS11_CMD_PING
41  *
42  * Return a PKCS11_CKR_* value which is also loaded into the output param#0
43  */
44 static uint32_t entry_ping(uint32_t ptypes, TEE_Param *params)
45 {
46 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
47 						TEE_PARAM_TYPE_NONE,
48 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
49 						TEE_PARAM_TYPE_NONE);
50 	TEE_Param *out = &params[2];
51 	const uint32_t ver[] = {
52 		PKCS11_TA_VERSION_MAJOR,
53 		PKCS11_TA_VERSION_MINOR,
54 		PKCS11_TA_VERSION_PATCH,
55 	};
56 
57 	if (ptypes != exp_pt ||
58 	    params[0].memref.size != TEE_PARAM0_SIZE_MIN ||
59 	    out->memref.size != sizeof(ver))
60 		return PKCS11_CKR_ARGUMENTS_BAD;
61 
62 	TEE_MemMove(out->memref.buffer, ver, sizeof(ver));
63 
64 	return PKCS11_CKR_OK;
65 }
66 
67 static bool __maybe_unused param_is_none(uint32_t ptypes, unsigned int index)
68 {
69 	return TEE_PARAM_TYPE_GET(ptypes, index) ==
70 	       TEE_PARAM_TYPE_NONE;
71 }
72 
73 static bool __maybe_unused param_is_memref(uint32_t ptypes, unsigned int index)
74 {
75 	switch (TEE_PARAM_TYPE_GET(ptypes, index)) {
76 	case TEE_PARAM_TYPE_MEMREF_INPUT:
77 	case TEE_PARAM_TYPE_MEMREF_OUTPUT:
78 	case TEE_PARAM_TYPE_MEMREF_INOUT:
79 		return true;
80 	default:
81 		return false;
82 	}
83 }
84 
85 static bool __maybe_unused param_is_input(uint32_t ptypes, unsigned int index)
86 {
87 	return TEE_PARAM_TYPE_GET(ptypes, index) ==
88 	       TEE_PARAM_TYPE_MEMREF_INPUT;
89 }
90 
91 static bool __maybe_unused param_is_output(uint32_t ptypes, unsigned int index)
92 {
93 	return TEE_PARAM_TYPE_GET(ptypes, index) ==
94 	       TEE_PARAM_TYPE_MEMREF_OUTPUT;
95 }
96 
97 /*
98  * Entry point for PKCS11 TA commands
99  *
100  * Param#0 (ctrl) is an output or an in/out buffer. Input data are serialized
101  * arguments for the invoked command while the output data is used to send
102  * back to the client a PKCS11 finer status ID than the GPD TEE result codes
103  * Client shall check the status ID from the parameter #0 output buffer together
104  * with the GPD TEE result code.
105  */
106 TEE_Result TA_InvokeCommandEntryPoint(void *tee_session __unused, uint32_t cmd,
107 				      uint32_t ptypes,
108 				      TEE_Param params[TEE_NUM_PARAMS])
109 {
110 	uint32_t rc = 0;
111 
112 	/* All command handlers will check only against 4 parameters */
113 	COMPILE_TIME_ASSERT(TEE_NUM_PARAMS == 4);
114 
115 	/*
116 	 * Param#0 must be either an output or an inout memref as used to
117 	 * store the output return value for the invoked command.
118 	 */
119 	switch (TEE_PARAM_TYPE_GET(ptypes, 0)) {
120 	case TEE_PARAM_TYPE_MEMREF_OUTPUT:
121 	case TEE_PARAM_TYPE_MEMREF_INOUT:
122 		if (params[0].memref.size < sizeof(rc))
123 			return TEE_ERROR_BAD_PARAMETERS;
124 		break;
125 	default:
126 		return TEE_ERROR_BAD_PARAMETERS;
127 	}
128 
129 	DMSG("%s p#0 %"PRIu32"@%p, p#1 %s %"PRIu32"@%p, p#2 %s %"PRIu32"@%p",
130 	     id2str_ta_cmd(cmd),
131 	     params[0].memref.size, params[0].memref.buffer,
132 	     param_is_input(ptypes, 1) ? "in" :
133 	     param_is_output(ptypes, 1) ? "out" : "---",
134 	     param_is_memref(ptypes, 1) ? params[1].memref.size : 0,
135 	     param_is_memref(ptypes, 1) ? params[1].memref.buffer : NULL,
136 	     param_is_input(ptypes, 2) ? "in" :
137 	     param_is_output(ptypes, 2) ? "out" : "---",
138 	     param_is_memref(ptypes, 2) ? params[2].memref.size : 0,
139 	     param_is_memref(ptypes, 2) ? params[2].memref.buffer : NULL);
140 
141 	switch (cmd) {
142 	case PKCS11_CMD_PING:
143 		rc = entry_ping(ptypes, params);
144 		break;
145 
146 	case PKCS11_CMD_SLOT_LIST:
147 		rc = entry_ck_slot_list(ptypes, params);
148 		break;
149 	case PKCS11_CMD_SLOT_INFO:
150 		rc = entry_ck_slot_info(ptypes, params);
151 		break;
152 	case PKCS11_CMD_TOKEN_INFO:
153 		rc = entry_ck_token_info(ptypes, params);
154 		break;
155 
156 	default:
157 		EMSG("Command 0x%"PRIx32" is not supported", cmd);
158 		return TEE_ERROR_NOT_SUPPORTED;
159 	}
160 
161 	DMSG("%s rc 0x%08"PRIx32"/%s", id2str_ta_cmd(cmd), rc, id2str_rc(rc));
162 
163 	TEE_MemMove(params[0].memref.buffer, &rc, sizeof(rc));
164 	params[0].memref.size = sizeof(rc);
165 
166 	if (rc == PKCS11_CKR_BUFFER_TOO_SMALL)
167 		return TEE_ERROR_SHORT_BUFFER;
168 	else
169 		return TEE_SUCCESS;
170 }
171