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