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