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