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