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 assert(processing_is_tee_digest(proc_params->id));
92
93 return allocate_tee_operation(session, proc_params);
94 }
95
96 /*
97 * step_digest_operation - processing digest operation step
98 *
99 * @session - current session
100 * @step - step ID in the processing (oneshot, update, final)
101 * @obj - PKCS#11 object for key based operations
102 * @ptype - invocation parameter types
103 * @params - invocation parameter references
104 */
step_digest_operation(struct pkcs11_session * session,enum processing_step step,struct pkcs11_object * obj,uint32_t ptypes,TEE_Param * params)105 enum pkcs11_rc step_digest_operation(struct pkcs11_session *session,
106 enum processing_step step,
107 struct pkcs11_object *obj,
108 uint32_t ptypes, TEE_Param *params)
109 {
110 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
111 TEE_Result res = TEE_ERROR_GENERIC;
112 void *in_buf = NULL;
113 size_t in_size = 0;
114 void *out_buf = NULL;
115 uint32_t out_size = 0;
116 void *secret_value = NULL;
117 uint32_t secret_value_size = 0;
118 enum pkcs11_key_type key_type = PKCS11_CKK_UNDEFINED_ID;
119 struct active_processing *proc = session->processing;
120
121 if (TEE_PARAM_TYPE_GET(ptypes, 1) == TEE_PARAM_TYPE_MEMREF_INPUT) {
122 in_buf = params[1].memref.buffer;
123 in_size = params[1].memref.size;
124 if (in_size && !in_buf)
125 return PKCS11_CKR_ARGUMENTS_BAD;
126 }
127 if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_OUTPUT) {
128 out_buf = params[2].memref.buffer;
129 out_size = params[2].memref.size;
130 if (out_size && !out_buf)
131 return PKCS11_CKR_ARGUMENTS_BAD;
132 }
133 if (TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE)
134 return PKCS11_CKR_ARGUMENTS_BAD;
135
136 switch (step) {
137 case PKCS11_FUNC_STEP_ONESHOT:
138 case PKCS11_FUNC_STEP_UPDATE:
139 case PKCS11_FUNC_STEP_UPDATE_KEY:
140 case PKCS11_FUNC_STEP_FINAL:
141 break;
142 default:
143 TEE_Panic(step);
144 break;
145 }
146
147 assert(proc->tee_op_handle != TEE_HANDLE_NULL);
148
149 assert(processing_is_tee_digest(proc->mecha_type));
150
151 /*
152 * Feed active operation with data
153 */
154
155 switch (step) {
156 case PKCS11_FUNC_STEP_UPDATE_KEY:
157 assert(obj);
158
159 if (!IS_ENABLED(CFG_PKCS11_TA_ALLOW_DIGEST_KEY))
160 return PKCS11_CKR_KEY_INDIGESTIBLE;
161
162 if (get_class(obj->attributes) != PKCS11_CKO_SECRET_KEY)
163 return PKCS11_CKR_KEY_INDIGESTIBLE;
164
165 key_type = get_key_type(obj->attributes);
166
167 if (key_type != PKCS11_CKK_GENERIC_SECRET &&
168 key_type != PKCS11_CKK_AES)
169 return PKCS11_CKR_KEY_INDIGESTIBLE;
170
171 rc = get_attribute_ptr(obj->attributes, PKCS11_CKA_VALUE,
172 &secret_value, &secret_value_size);
173 assert(!rc && secret_value && secret_value_size);
174
175 TEE_DigestUpdate(proc->tee_op_handle, secret_value,
176 secret_value_size);
177 return PKCS11_CKR_OK;
178
179 case PKCS11_FUNC_STEP_UPDATE:
180 if (!in_buf || !in_size)
181 return PKCS11_CKR_OK;
182
183 TEE_DigestUpdate(proc->tee_op_handle, in_buf, in_size);
184 return PKCS11_CKR_OK;
185
186 case PKCS11_FUNC_STEP_ONESHOT:
187 if (!out_buf)
188 return PKCS11_CKR_ARGUMENTS_BAD;
189
190 goto do_final;
191
192 case PKCS11_FUNC_STEP_FINAL:
193 if (in_buf || !out_buf)
194 return PKCS11_CKR_ARGUMENTS_BAD;
195
196 goto do_final;
197
198 default:
199 TEE_Panic(step);
200 break;
201 }
202
203 do_final:
204 res = TEE_DigestDoFinal(proc->tee_op_handle,
205 in_buf, in_size, out_buf,
206 &out_size);
207 rc = tee2pkcs_error(res);
208
209 if (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL)
210 params[2].memref.size = out_size;
211
212 return rc;
213 }
214