1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2021, Vaisala Oyj
4 */
5
6 #include <assert.h>
7 #include <config.h>
8 #include <pkcs11_ta.h>
9 #include <string.h>
10 #include <tee_api_defines.h>
11 #include <tee_internal_api.h>
12 #include <tee_internal_api_extensions.h>
13 #include <utee_defines.h>
14 #include <util.h>
15
16 #include "attributes.h"
17 #include "object.h"
18 #include "pkcs11_attributes.h"
19 #include "pkcs11_helpers.h"
20 #include "pkcs11_token.h"
21 #include "processing.h"
22 #include "serializer.h"
23
processing_is_tee_digest(enum pkcs11_mechanism_id mecha_id)24 bool processing_is_tee_digest(enum pkcs11_mechanism_id mecha_id)
25 {
26 switch (mecha_id) {
27 case PKCS11_CKM_MD5:
28 case PKCS11_CKM_SHA_1:
29 case PKCS11_CKM_SHA224:
30 case PKCS11_CKM_SHA256:
31 case PKCS11_CKM_SHA384:
32 case PKCS11_CKM_SHA512:
33 return true;
34 default:
35 return false;
36 }
37 }
38
39 static enum pkcs11_rc
pkcs2tee_algorithm(uint32_t * tee_id,struct pkcs11_attribute_head * proc_params)40 pkcs2tee_algorithm(uint32_t *tee_id, struct pkcs11_attribute_head *proc_params)
41 {
42 static const struct {
43 enum pkcs11_mechanism_id mech_id;
44 uint32_t tee_id;
45 } pkcs2tee_algo[] = {
46 { PKCS11_CKM_MD5, TEE_ALG_MD5 },
47 { PKCS11_CKM_SHA_1, TEE_ALG_SHA1 },
48 { PKCS11_CKM_SHA224, TEE_ALG_SHA224 },
49 { PKCS11_CKM_SHA256, TEE_ALG_SHA256 },
50 { PKCS11_CKM_SHA384, TEE_ALG_SHA384 },
51 { PKCS11_CKM_SHA512, TEE_ALG_SHA512 },
52 };
53 size_t n = 0;
54
55 for (n = 0; n < ARRAY_SIZE(pkcs2tee_algo); n++) {
56 if (proc_params->id == pkcs2tee_algo[n].mech_id) {
57 *tee_id = pkcs2tee_algo[n].tee_id;
58 return PKCS11_CKR_OK;
59 }
60 }
61
62 return PKCS11_RV_NOT_IMPLEMENTED;
63 }
64
65 static enum pkcs11_rc
allocate_tee_operation(struct pkcs11_session * session,struct pkcs11_attribute_head * params)66 allocate_tee_operation(struct pkcs11_session *session,
67 struct pkcs11_attribute_head *params)
68 {
69 uint32_t algo = 0;
70 TEE_Result res = TEE_ERROR_GENERIC;
71
72 assert(session->processing->tee_op_handle == TEE_HANDLE_NULL);
73
74 if (pkcs2tee_algorithm(&algo, params))
75 return PKCS11_CKR_FUNCTION_FAILED;
76
77 res = TEE_AllocateOperation(&session->processing->tee_op_handle,
78 algo, TEE_MODE_DIGEST, 0);
79 if (res)
80 EMSG("TEE_AllocateOp. failed %#"PRIx32, algo);
81
82 if (res == TEE_ERROR_NOT_SUPPORTED)
83 return PKCS11_CKR_MECHANISM_INVALID;
84
85 return tee2pkcs_error(res);
86 }
87
init_digest_operation(struct pkcs11_session * session,struct pkcs11_attribute_head * proc_params)88 enum pkcs11_rc init_digest_operation(struct pkcs11_session *session,
89 struct pkcs11_attribute_head *proc_params)
90 {
91 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
92
93 assert(processing_is_tee_digest(proc_params->id));
94
95 rc = allocate_tee_operation(session, proc_params);
96 if (!rc)
97 session->processing->mecha_type = proc_params->id;
98
99 return rc;
100 }
101
102 /*
103 * step_digest_operation - processing digest operation step
104 *
105 * @session - current session
106 * @step - step ID in the processing (oneshot, update, final)
107 * @obj - PKCS#11 object for key based operations
108 * @ptype - invocation parameter types
109 * @params - invocation parameter references
110 */
step_digest_operation(struct pkcs11_session * session,enum processing_step step,struct pkcs11_object * obj,uint32_t ptypes,TEE_Param * params)111 enum pkcs11_rc step_digest_operation(struct pkcs11_session *session,
112 enum processing_step step,
113 struct pkcs11_object *obj,
114 uint32_t ptypes, TEE_Param *params)
115 {
116 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
117 TEE_Result res = TEE_ERROR_GENERIC;
118 void *in_buf = NULL;
119 size_t in_size = 0;
120 void *out_buf = NULL;
121 uint32_t out_size = 0;
122 void *secret_value = NULL;
123 uint32_t secret_value_size = 0;
124 enum pkcs11_key_type key_type = PKCS11_CKK_UNDEFINED_ID;
125 struct active_processing *proc = session->processing;
126
127 if (TEE_PARAM_TYPE_GET(ptypes, 1) == TEE_PARAM_TYPE_MEMREF_INPUT) {
128 in_buf = params[1].memref.buffer;
129 in_size = params[1].memref.size;
130 if (in_size && !in_buf)
131 return PKCS11_CKR_ARGUMENTS_BAD;
132 }
133 if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_OUTPUT) {
134 out_buf = params[2].memref.buffer;
135 out_size = params[2].memref.size;
136 if (out_size && !out_buf)
137 return PKCS11_CKR_ARGUMENTS_BAD;
138 }
139 if (TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE)
140 return PKCS11_CKR_ARGUMENTS_BAD;
141
142 switch (step) {
143 case PKCS11_FUNC_STEP_ONESHOT:
144 case PKCS11_FUNC_STEP_UPDATE:
145 case PKCS11_FUNC_STEP_UPDATE_KEY:
146 case PKCS11_FUNC_STEP_FINAL:
147 break;
148 default:
149 TEE_Panic(step);
150 break;
151 }
152
153 assert(proc->tee_op_handle != TEE_HANDLE_NULL);
154
155 assert(processing_is_tee_digest(proc->mecha_type));
156
157 /*
158 * Feed active operation with data
159 */
160
161 switch (step) {
162 case PKCS11_FUNC_STEP_UPDATE_KEY:
163 assert(obj);
164
165 if (!IS_ENABLED(CFG_PKCS11_TA_ALLOW_DIGEST_KEY))
166 return PKCS11_CKR_KEY_INDIGESTIBLE;
167
168 if (get_class(obj->attributes) != PKCS11_CKO_SECRET_KEY)
169 return PKCS11_CKR_KEY_INDIGESTIBLE;
170
171 key_type = get_key_type(obj->attributes);
172
173 if (key_type != PKCS11_CKK_GENERIC_SECRET &&
174 key_type != PKCS11_CKK_AES)
175 return PKCS11_CKR_KEY_INDIGESTIBLE;
176
177 rc = get_attribute_ptr(obj->attributes, PKCS11_CKA_VALUE,
178 &secret_value, &secret_value_size);
179 assert(!rc && secret_value && secret_value_size);
180
181 TEE_DigestUpdate(proc->tee_op_handle, secret_value,
182 secret_value_size);
183 return PKCS11_CKR_OK;
184
185 case PKCS11_FUNC_STEP_UPDATE:
186 if (!in_buf || !in_size)
187 return PKCS11_CKR_OK;
188
189 TEE_DigestUpdate(proc->tee_op_handle, in_buf, in_size);
190 return PKCS11_CKR_OK;
191
192 case PKCS11_FUNC_STEP_ONESHOT:
193 if (!out_buf)
194 return PKCS11_CKR_ARGUMENTS_BAD;
195
196 goto do_final;
197
198 case PKCS11_FUNC_STEP_FINAL:
199 if (in_buf || !out_buf)
200 return PKCS11_CKR_ARGUMENTS_BAD;
201
202 goto do_final;
203
204 default:
205 TEE_Panic(step);
206 break;
207 }
208
209 do_final:
210 res = TEE_DigestDoFinal(proc->tee_op_handle,
211 in_buf, in_size, out_buf,
212 &out_size);
213 rc = tee2pkcs_error(res);
214
215 if (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL)
216 params[2].memref.size = out_size;
217
218 return rc;
219 }
220