xref: /optee_os/core/drivers/crypto/caam/hash/caam_hash_mac.c (revision 2d53e979f05af4125409507e4281f06f6fba238b)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright 2018-2021 NXP
4  *
5  * Implementation of Hashing functions.
6  */
7 #include <caam_hal_ctrl.h>
8 #include <caam_hash.h>
9 #include <caam_jr.h>
10 #include <caam_utils_dmaobj.h>
11 #include <caam_utils_mem.h>
12 #include <caam_utils_status.h>
13 #include <drvcrypt.h>
14 #include <drvcrypt_mac.h>
15 #include <kernel/panic.h>
16 #include <mm/core_memprot.h>
17 #include <tee/cache.h>
18 #include <utee_defines.h>
19 
20 #include "local.h"
21 
22 #ifdef CFG_PHYS_64BIT
23 #define KEY_REDUCE_DESC_ENTRIES	 10
24 #define KEY_COMPUTE_DESC_ENTRIES 10
25 #else
26 #define KEY_REDUCE_DESC_ENTRIES	 8
27 #define KEY_COMPUTE_DESC_ENTRIES 8
28 #endif
29 
30 static const struct crypto_mac_ops hmac_ops;
31 
32 /*
33  * Format the MAC context to keep the reference to the operation driver.
34  */
35 struct crypto_mac {
36 	struct crypto_mac_ctx mac_ctx; /* Crypto MAC API context */
37 	struct hashctx *ctx;	       /* HMAC context */
38 };
39 
40 /*
41  * Keep the HW hash limit because after the initialization
42  * of the module, we don't have the CAAM Controller base address
43  * to call the function returning the HW capacity.
44  */
45 static uint8_t caam_hash_limit;
46 
47 /*
48  * Returns the reference to the driver context
49  *
50  * @ctx  API Context
51  */
to_mac_ctx(struct crypto_mac_ctx * ctx)52 static struct crypto_mac *to_mac_ctx(struct crypto_mac_ctx *ctx)
53 {
54 	assert(ctx && ctx->ops == &hmac_ops);
55 
56 	return container_of(ctx, struct crypto_mac, mac_ctx);
57 }
58 
59 /*
60  * Reduce key to be a hash algorithm block size maximum
61  *
62  * @alg     Reference to the algorithm definition
63  * @inkey   Key to be reduced
64  * @outkey  [out] key resulting
65  */
do_reduce_key(struct caamdmaobj * reduce_key,const struct hashalg * alg,const uint8_t * inkey,size_t len)66 static enum caam_status do_reduce_key(struct caamdmaobj *reduce_key,
67 				      const struct hashalg *alg,
68 				      const uint8_t *inkey, size_t len)
69 {
70 	enum caam_status retstatus = CAAM_FAILURE;
71 	struct caamdmaobj key = { };
72 	struct caam_jobctx jobctx = { };
73 	uint32_t *desc = NULL;
74 
75 	if (caam_dmaobj_input_sgtbuf(&key, inkey, len))
76 		return CAAM_OUT_MEMORY;
77 
78 	/* Allocate the job descriptor */
79 	desc = caam_calloc_desc(KEY_REDUCE_DESC_ENTRIES);
80 	if (!desc) {
81 		retstatus = CAAM_OUT_MEMORY;
82 		goto out;
83 	}
84 
85 	caam_desc_init(desc);
86 	caam_desc_add_word(desc, DESC_HEADER(0));
87 	caam_desc_add_word(desc, HASH_INITFINAL(alg->type));
88 
89 	/* Load the input key */
90 	caam_desc_fifo_load(desc, &key, CLASS_2, MSG, LAST_C2);
91 	/* Store key reduced */
92 	caam_desc_store(desc, reduce_key, CLASS_2, REG_CTX);
93 
94 	caam_dmaobj_cache_push(&key);
95 	caam_dmaobj_cache_push(reduce_key);
96 
97 	HASH_DUMPDESC(desc);
98 
99 	jobctx.desc = desc;
100 	retstatus = caam_jr_enqueue(&jobctx, NULL);
101 
102 	if (retstatus != CAAM_NO_ERROR) {
103 		HASH_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status);
104 		retstatus = CAAM_FAILURE;
105 	}
106 
107 out:
108 	caam_dmaobj_free(&key);
109 	caam_free_desc(&desc);
110 
111 	return retstatus;
112 }
113 
114 /*
115  * Initialization of the HMAC operation.
116  * Split the input key using the CAAM HW HMAC operation
117  * Call common initialization operation between hash and HMAC
118  *
119  * @ctx   Operation software context
120  * @key   Input key to compute
121  * @len   Key length
122  */
do_hmac_init(struct crypto_mac_ctx * ctx,const uint8_t * inkey,size_t len)123 static TEE_Result do_hmac_init(struct crypto_mac_ctx *ctx, const uint8_t *inkey,
124 			       size_t len)
125 {
126 	TEE_Result ret = TEE_ERROR_GENERIC;
127 	enum caam_status retstatus = CAAM_FAILURE;
128 	struct crypto_mac *mac = to_mac_ctx(ctx);
129 	struct hashctx *hmac_ctx = mac->ctx;
130 	const struct hashalg *alg = hmac_ctx->alg;
131 	struct caamdmaobj reduce_key = { };
132 	struct caam_jobctx jobctx = { };
133 	uint32_t *desc = NULL;
134 
135 	/* First initialize the context */
136 	ret = caam_hash_hmac_init(hmac_ctx);
137 	if (ret != TEE_SUCCESS)
138 		return ret;
139 
140 	HASH_TRACE("split key length %zu", len);
141 
142 	/* Allocate the job descriptor */
143 	desc = caam_calloc_desc(KEY_COMPUTE_DESC_ENTRIES);
144 	if (!desc) {
145 		ret = TEE_ERROR_OUT_OF_MEMORY;
146 		goto out;
147 	}
148 
149 	hmac_ctx->key.length = alg->size_key;
150 
151 	if (len > alg->size_block) {
152 		HASH_TRACE("Input key must be reduced");
153 
154 		ret = caam_dmaobj_output_sgtbuf(&reduce_key, NULL, 0,
155 						alg->size_digest);
156 		if (ret) {
157 			HASH_TRACE("Reduced Key allocation error");
158 			goto out;
159 		}
160 
161 		retstatus = do_reduce_key(&reduce_key, alg, inkey, len);
162 		if (retstatus != CAAM_NO_ERROR)
163 			goto out;
164 	} else {
165 		/* Key size is correct use directly the input key */
166 		ret = caam_dmaobj_input_sgtbuf(&reduce_key, inkey, len);
167 		if (ret)
168 			goto out;
169 	}
170 
171 	caam_desc_init(desc);
172 	caam_desc_add_word(desc, DESC_HEADER(0));
173 	/* Load either input key or the reduced input key into key register */
174 	caam_desc_load_key(desc, &reduce_key, CLASS_2, REG);
175 	/* Split the key */
176 	caam_desc_add_word(desc, HMAC_INIT_DECRYPT(alg->type));
177 	caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_2, MSG, LAST_C2, 0));
178 	/* Store the split key */
179 	caam_desc_add_word(desc, FIFO_ST(CLASS_NO,
180 					 C2_MDHA_SPLIT_KEY_AES_ECB_JKEK,
181 					 hmac_ctx->key.length));
182 	caam_desc_add_ptr(desc, hmac_ctx->key.paddr);
183 	HASH_DUMPDESC(desc);
184 
185 	caam_dmaobj_cache_push(&reduce_key);
186 	cache_operation(TEE_CACHEFLUSH, hmac_ctx->key.data,
187 			hmac_ctx->key.length);
188 
189 	jobctx.desc = desc;
190 	retstatus = caam_jr_enqueue(&jobctx, NULL);
191 
192 	if (retstatus == CAAM_NO_ERROR) {
193 		HASH_DUMPBUF("Split Key", hmac_ctx->key.data,
194 			     hmac_ctx->key.length);
195 
196 		ret = TEE_SUCCESS;
197 	} else {
198 		HASH_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status);
199 		ret = job_status_to_tee_result(jobctx.status);
200 	}
201 
202 out:
203 	caam_dmaobj_free(&reduce_key);
204 	caam_free_desc(&desc);
205 
206 	return ret;
207 }
208 
209 /*
210  * Update the HMAC operation
211  * Call common update operation between hash and HMAC
212  *
213  * @ctx   Operation Software context
214  * @data  Data to hash
215  * @len   Data length
216  */
do_hmac_update(struct crypto_mac_ctx * ctx,const uint8_t * data,size_t len)217 static TEE_Result do_hmac_update(struct crypto_mac_ctx *ctx,
218 				 const uint8_t *data, size_t len)
219 {
220 	struct crypto_mac *mac = to_mac_ctx(ctx);
221 
222 	return caam_hash_hmac_update(mac->ctx, data, len);
223 }
224 
225 /*
226  * Finalize the HMAC operation
227  * Call common final operation between hash and HMAC
228  *
229  * @ctx     Operation Software context
230  * @digest  [out] Hash digest buffer
231  * @len     Digest buffer length
232  */
do_hmac_final(struct crypto_mac_ctx * ctx,uint8_t * digest,size_t len)233 static TEE_Result do_hmac_final(struct crypto_mac_ctx *ctx, uint8_t *digest,
234 				size_t len)
235 {
236 	struct crypto_mac *mac = to_mac_ctx(ctx);
237 
238 	return caam_hash_hmac_final(mac->ctx, digest, len);
239 }
240 
241 /*
242  * Free the software context
243  * Call common free operation between hash and HMAC
244  *
245  * @ctx    Caller context variable
246  */
do_hmac_free(struct crypto_mac_ctx * ctx)247 static void do_hmac_free(struct crypto_mac_ctx *ctx)
248 {
249 	struct crypto_mac *mac = to_mac_ctx(ctx);
250 
251 	caam_hash_hmac_free(mac->ctx);
252 
253 	free(mac);
254 }
255 
256 /*
257  * Copy sofware HMAC context
258  * Call common copy operation between hash and HMAC
259  *
260  * @dst_ctx  [out] Reference the context destination
261  * @src_ctx  Reference the context source
262  */
do_hmac_copy_state(struct crypto_mac_ctx * dst_ctx,struct crypto_mac_ctx * src_ctx)263 static void do_hmac_copy_state(struct crypto_mac_ctx *dst_ctx,
264 			       struct crypto_mac_ctx *src_ctx)
265 {
266 	struct crypto_mac *mac_src = to_mac_ctx(src_ctx);
267 	struct crypto_mac *mac_dst = to_mac_ctx(dst_ctx);
268 
269 	return caam_hash_hmac_copy_state(mac_dst->ctx, mac_src->ctx);
270 }
271 
272 /*
273  * Registration of the HMAC driver
274  */
275 static const struct crypto_mac_ops hmac_ops = {
276 	.init = do_hmac_init,
277 	.update = do_hmac_update,
278 	.final = do_hmac_final,
279 	.free_ctx = do_hmac_free,
280 	.copy_state = do_hmac_copy_state,
281 };
282 
283 /*
284  * Allocate the internal hashing data context
285  *
286  * @ctx    [out] Caller context reference
287  * @algo   Algorithm ID
288  */
caam_hmac_allocate(struct crypto_mac_ctx ** ctx,uint32_t algo)289 static TEE_Result caam_hmac_allocate(struct crypto_mac_ctx **ctx, uint32_t algo)
290 {
291 	struct crypto_mac *mac = NULL;
292 	struct hashctx *hmac_ctx = NULL;
293 	const struct hashalg *alg = NULL;
294 	TEE_Result ret = TEE_ERROR_GENERIC;
295 
296 	HASH_TRACE("Allocate Context (%p) algo %" PRId32, ctx, algo);
297 
298 	*ctx = NULL;
299 
300 	alg = caam_hash_get_alg(algo);
301 	if (!alg)
302 		return TEE_ERROR_NOT_IMPLEMENTED;
303 
304 	mac = calloc(1, sizeof(*mac));
305 	if (!mac)
306 		return TEE_ERROR_OUT_OF_MEMORY;
307 
308 	hmac_ctx = caam_calloc(sizeof(*hmac_ctx));
309 	if (!hmac_ctx) {
310 		ret = TEE_ERROR_OUT_OF_MEMORY;
311 		goto err;
312 	}
313 
314 	hmac_ctx->alg = alg;
315 	mac->mac_ctx.ops = &hmac_ops;
316 	mac->ctx = hmac_ctx;
317 
318 	*ctx = &mac->mac_ctx;
319 
320 	ret = caam_hash_hmac_allocate(hmac_ctx);
321 	if (ret != TEE_SUCCESS)
322 		goto err;
323 
324 	HASH_TRACE("Allocated Context (%p)", hmac_ctx);
325 
326 	return TEE_SUCCESS;
327 
328 err:
329 	free(mac);
330 
331 	if (hmac_ctx)
332 		caam_free(hmac_ctx);
333 
334 	return ret;
335 }
336 
caam_hmac_init(struct caam_jrcfg * caam_jrcfg)337 enum caam_status caam_hmac_init(struct caam_jrcfg *caam_jrcfg)
338 {
339 	vaddr_t jr_base = caam_jrcfg->base + caam_jrcfg->offset;
340 
341 	caam_hash_limit = caam_hal_ctrl_hash_limit(jr_base);
342 
343 	if (caam_hash_limit != UINT8_MAX &&
344 	    caam_hal_ctrl_splitkey_support(jr_base)) {
345 		if (drvcrypt_register_hmac(&caam_hmac_allocate))
346 			return CAAM_FAILURE;
347 	}
348 
349 	return CAAM_NO_ERROR;
350 }
351