xref: /openbmc/u-boot/drivers/crypto/fsl/fsl_hash.c (revision 5d97dff0)
1b9eebfadSRuchika Gupta /*
2b9eebfadSRuchika Gupta  * Copyright 2014 Freescale Semiconductor, Inc.
3b9eebfadSRuchika Gupta  *
4b9eebfadSRuchika Gupta  * SPDX-License-Identifier:	GPL-2.0+
5b9eebfadSRuchika Gupta  *
6b9eebfadSRuchika Gupta  */
7b9eebfadSRuchika Gupta 
8b9eebfadSRuchika Gupta #include <common.h>
9b9eebfadSRuchika Gupta #include <malloc.h>
10b9eebfadSRuchika Gupta #include "jobdesc.h"
11b9eebfadSRuchika Gupta #include "desc.h"
12b9eebfadSRuchika Gupta #include "jr.h"
1394e3c8c4Sgaurav rana #include "fsl_hash.h"
1494e3c8c4Sgaurav rana #include <hw_sha.h>
15*5d97dff0SMasahiro Yamada #include <linux/errno.h>
16b9eebfadSRuchika Gupta 
17b9eebfadSRuchika Gupta #define CRYPTO_MAX_ALG_NAME	80
18b9eebfadSRuchika Gupta #define SHA1_DIGEST_SIZE        20
19b9eebfadSRuchika Gupta #define SHA256_DIGEST_SIZE      32
20b9eebfadSRuchika Gupta 
21b9eebfadSRuchika Gupta struct caam_hash_template {
22b9eebfadSRuchika Gupta 	char name[CRYPTO_MAX_ALG_NAME];
23b9eebfadSRuchika Gupta 	unsigned int digestsize;
24b9eebfadSRuchika Gupta 	u32 alg_type;
25b9eebfadSRuchika Gupta };
26b9eebfadSRuchika Gupta 
27b9eebfadSRuchika Gupta enum caam_hash_algos {
28b9eebfadSRuchika Gupta 	SHA1 = 0,
29b9eebfadSRuchika Gupta 	SHA256
30b9eebfadSRuchika Gupta };
31b9eebfadSRuchika Gupta 
32b9eebfadSRuchika Gupta static struct caam_hash_template driver_hash[] = {
33b9eebfadSRuchika Gupta 	{
34b9eebfadSRuchika Gupta 		.name = "sha1",
35b9eebfadSRuchika Gupta 		.digestsize = SHA1_DIGEST_SIZE,
36b9eebfadSRuchika Gupta 		.alg_type = OP_ALG_ALGSEL_SHA1,
37b9eebfadSRuchika Gupta 	},
38b9eebfadSRuchika Gupta 	{
39b9eebfadSRuchika Gupta 		.name = "sha256",
40b9eebfadSRuchika Gupta 		.digestsize = SHA256_DIGEST_SIZE,
41b9eebfadSRuchika Gupta 		.alg_type = OP_ALG_ALGSEL_SHA256,
42b9eebfadSRuchika Gupta 	},
43b9eebfadSRuchika Gupta };
44b9eebfadSRuchika Gupta 
4594e3c8c4Sgaurav rana static enum caam_hash_algos get_hash_type(struct hash_algo *algo)
4694e3c8c4Sgaurav rana {
4794e3c8c4Sgaurav rana 	if (!strcmp(algo->name, driver_hash[SHA1].name))
4894e3c8c4Sgaurav rana 		return SHA1;
4994e3c8c4Sgaurav rana 	else
5094e3c8c4Sgaurav rana 		return SHA256;
5194e3c8c4Sgaurav rana }
5294e3c8c4Sgaurav rana 
5394e3c8c4Sgaurav rana /* Create the context for progressive hashing using h/w acceleration.
5494e3c8c4Sgaurav rana  *
5594e3c8c4Sgaurav rana  * @ctxp: Pointer to the pointer of the context for hashing
5694e3c8c4Sgaurav rana  * @caam_algo: Enum for SHA1 or SHA256
5794e3c8c4Sgaurav rana  * @return 0 if ok, -ENOMEM on error
5894e3c8c4Sgaurav rana  */
5994e3c8c4Sgaurav rana static int caam_hash_init(void **ctxp, enum caam_hash_algos caam_algo)
6094e3c8c4Sgaurav rana {
6194e3c8c4Sgaurav rana 	*ctxp = calloc(1, sizeof(struct sha_ctx));
6294e3c8c4Sgaurav rana 	if (*ctxp == NULL) {
6394e3c8c4Sgaurav rana 		debug("Cannot allocate memory for context\n");
6494e3c8c4Sgaurav rana 		return -ENOMEM;
6594e3c8c4Sgaurav rana 	}
6694e3c8c4Sgaurav rana 	return 0;
6794e3c8c4Sgaurav rana }
6894e3c8c4Sgaurav rana 
6994e3c8c4Sgaurav rana /*
7094e3c8c4Sgaurav rana  * Update sg table for progressive hashing using h/w acceleration
7194e3c8c4Sgaurav rana  *
7294e3c8c4Sgaurav rana  * The context is freed by this function if an error occurs.
7394e3c8c4Sgaurav rana  * We support at most 32 Scatter/Gather Entries.
7494e3c8c4Sgaurav rana  *
7594e3c8c4Sgaurav rana  * @hash_ctx: Pointer to the context for hashing
7694e3c8c4Sgaurav rana  * @buf: Pointer to the buffer being hashed
7794e3c8c4Sgaurav rana  * @size: Size of the buffer being hashed
7894e3c8c4Sgaurav rana  * @is_last: 1 if this is the last update; 0 otherwise
7994e3c8c4Sgaurav rana  * @caam_algo: Enum for SHA1 or SHA256
8094e3c8c4Sgaurav rana  * @return 0 if ok, -EINVAL on error
8194e3c8c4Sgaurav rana  */
8294e3c8c4Sgaurav rana static int caam_hash_update(void *hash_ctx, const void *buf,
8394e3c8c4Sgaurav rana 			    unsigned int size, int is_last,
8494e3c8c4Sgaurav rana 			    enum caam_hash_algos caam_algo)
8594e3c8c4Sgaurav rana {
8694e3c8c4Sgaurav rana 	uint32_t final = 0;
87f59e69cbSAneesh Bansal 	phys_addr_t addr = virt_to_phys((void *)buf);
8894e3c8c4Sgaurav rana 	struct sha_ctx *ctx = hash_ctx;
8994e3c8c4Sgaurav rana 
9094e3c8c4Sgaurav rana 	if (ctx->sg_num >= MAX_SG_32) {
9194e3c8c4Sgaurav rana 		free(ctx);
9294e3c8c4Sgaurav rana 		return -EINVAL;
9394e3c8c4Sgaurav rana 	}
9494e3c8c4Sgaurav rana 
9594e3c8c4Sgaurav rana #ifdef CONFIG_PHYS_64BIT
96f59e69cbSAneesh Bansal 	sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, (uint32_t)(addr >> 32));
9794e3c8c4Sgaurav rana #else
98f59e69cbSAneesh Bansal 	sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, 0x0);
9994e3c8c4Sgaurav rana #endif
100f59e69cbSAneesh Bansal 	sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_lo, (uint32_t)addr);
10194e3c8c4Sgaurav rana 
10294e3c8c4Sgaurav rana 	sec_out32(&ctx->sg_tbl[ctx->sg_num].len_flag,
10394e3c8c4Sgaurav rana 		  (size & SG_ENTRY_LENGTH_MASK));
10494e3c8c4Sgaurav rana 
10594e3c8c4Sgaurav rana 	ctx->sg_num++;
10694e3c8c4Sgaurav rana 
10794e3c8c4Sgaurav rana 	if (is_last) {
10894e3c8c4Sgaurav rana 		final = sec_in32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag) |
10994e3c8c4Sgaurav rana 			SG_ENTRY_FINAL_BIT;
11094e3c8c4Sgaurav rana 		sec_out32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag, final);
11194e3c8c4Sgaurav rana 	}
11294e3c8c4Sgaurav rana 
11394e3c8c4Sgaurav rana 	return 0;
11494e3c8c4Sgaurav rana }
11594e3c8c4Sgaurav rana 
11694e3c8c4Sgaurav rana /*
11794e3c8c4Sgaurav rana  * Perform progressive hashing on the given buffer and copy hash at
11894e3c8c4Sgaurav rana  * destination buffer
11994e3c8c4Sgaurav rana  *
12094e3c8c4Sgaurav rana  * The context is freed after completion of hash operation.
12194e3c8c4Sgaurav rana  *
12294e3c8c4Sgaurav rana  * @hash_ctx: Pointer to the context for hashing
12394e3c8c4Sgaurav rana  * @dest_buf: Pointer to the destination buffer where hash is to be copied
12494e3c8c4Sgaurav rana  * @size: Size of the buffer being hashed
12594e3c8c4Sgaurav rana  * @caam_algo: Enum for SHA1 or SHA256
12694e3c8c4Sgaurav rana  * @return 0 if ok, -EINVAL on error
12794e3c8c4Sgaurav rana  */
12894e3c8c4Sgaurav rana static int caam_hash_finish(void *hash_ctx, void *dest_buf,
12994e3c8c4Sgaurav rana 			    int size, enum caam_hash_algos caam_algo)
13094e3c8c4Sgaurav rana {
13194e3c8c4Sgaurav rana 	uint32_t len = 0;
13294e3c8c4Sgaurav rana 	struct sha_ctx *ctx = hash_ctx;
13394e3c8c4Sgaurav rana 	int i = 0, ret = 0;
13494e3c8c4Sgaurav rana 
13594e3c8c4Sgaurav rana 	if (size < driver_hash[caam_algo].digestsize) {
13694e3c8c4Sgaurav rana 		free(ctx);
13794e3c8c4Sgaurav rana 		return -EINVAL;
13894e3c8c4Sgaurav rana 	}
13994e3c8c4Sgaurav rana 
14094e3c8c4Sgaurav rana 	for (i = 0; i < ctx->sg_num; i++)
14194e3c8c4Sgaurav rana 		len += (sec_in32(&ctx->sg_tbl[i].len_flag) &
14294e3c8c4Sgaurav rana 			SG_ENTRY_LENGTH_MASK);
14394e3c8c4Sgaurav rana 
14494e3c8c4Sgaurav rana 	inline_cnstr_jobdesc_hash(ctx->sha_desc, (uint8_t *)ctx->sg_tbl, len,
14594e3c8c4Sgaurav rana 				  ctx->hash,
14694e3c8c4Sgaurav rana 				  driver_hash[caam_algo].alg_type,
14794e3c8c4Sgaurav rana 				  driver_hash[caam_algo].digestsize,
14894e3c8c4Sgaurav rana 				  1);
14994e3c8c4Sgaurav rana 
15094e3c8c4Sgaurav rana 	ret = run_descriptor_jr(ctx->sha_desc);
15194e3c8c4Sgaurav rana 
15294e3c8c4Sgaurav rana 	if (ret)
15394e3c8c4Sgaurav rana 		debug("Error %x\n", ret);
15494e3c8c4Sgaurav rana 	else
15594e3c8c4Sgaurav rana 		memcpy(dest_buf, ctx->hash, sizeof(ctx->hash));
15694e3c8c4Sgaurav rana 
15794e3c8c4Sgaurav rana 	free(ctx);
15894e3c8c4Sgaurav rana 	return ret;
15994e3c8c4Sgaurav rana }
16094e3c8c4Sgaurav rana 
161b9eebfadSRuchika Gupta int caam_hash(const unsigned char *pbuf, unsigned int buf_len,
162b9eebfadSRuchika Gupta 	      unsigned char *pout, enum caam_hash_algos algo)
163b9eebfadSRuchika Gupta {
164b9eebfadSRuchika Gupta 	int ret = 0;
165b9eebfadSRuchika Gupta 	uint32_t *desc;
166b9eebfadSRuchika Gupta 
167b9eebfadSRuchika Gupta 	desc = malloc(sizeof(int) * MAX_CAAM_DESCSIZE);
168b9eebfadSRuchika Gupta 	if (!desc) {
169b9eebfadSRuchika Gupta 		debug("Not enough memory for descriptor allocation\n");
17094e3c8c4Sgaurav rana 		return -ENOMEM;
171b9eebfadSRuchika Gupta 	}
172b9eebfadSRuchika Gupta 
173b9eebfadSRuchika Gupta 	inline_cnstr_jobdesc_hash(desc, pbuf, buf_len, pout,
174b9eebfadSRuchika Gupta 				  driver_hash[algo].alg_type,
175b9eebfadSRuchika Gupta 				  driver_hash[algo].digestsize,
176b9eebfadSRuchika Gupta 				  0);
177b9eebfadSRuchika Gupta 
178b9eebfadSRuchika Gupta 	ret = run_descriptor_jr(desc);
179b9eebfadSRuchika Gupta 
180b9eebfadSRuchika Gupta 	free(desc);
181b9eebfadSRuchika Gupta 	return ret;
182b9eebfadSRuchika Gupta }
183b9eebfadSRuchika Gupta 
184b9eebfadSRuchika Gupta void hw_sha256(const unsigned char *pbuf, unsigned int buf_len,
185b9eebfadSRuchika Gupta 			unsigned char *pout, unsigned int chunk_size)
186b9eebfadSRuchika Gupta {
187b9eebfadSRuchika Gupta 	if (caam_hash(pbuf, buf_len, pout, SHA256))
188b9eebfadSRuchika Gupta 		printf("CAAM was not setup properly or it is faulty\n");
189b9eebfadSRuchika Gupta }
190b9eebfadSRuchika Gupta 
191b9eebfadSRuchika Gupta void hw_sha1(const unsigned char *pbuf, unsigned int buf_len,
192b9eebfadSRuchika Gupta 			unsigned char *pout, unsigned int chunk_size)
193b9eebfadSRuchika Gupta {
194b9eebfadSRuchika Gupta 	if (caam_hash(pbuf, buf_len, pout, SHA1))
195b9eebfadSRuchika Gupta 		printf("CAAM was not setup properly or it is faulty\n");
196b9eebfadSRuchika Gupta }
19794e3c8c4Sgaurav rana 
19894e3c8c4Sgaurav rana int hw_sha_init(struct hash_algo *algo, void **ctxp)
19994e3c8c4Sgaurav rana {
20094e3c8c4Sgaurav rana 	return caam_hash_init(ctxp, get_hash_type(algo));
20194e3c8c4Sgaurav rana }
20294e3c8c4Sgaurav rana 
20394e3c8c4Sgaurav rana int hw_sha_update(struct hash_algo *algo, void *ctx, const void *buf,
20494e3c8c4Sgaurav rana 			    unsigned int size, int is_last)
20594e3c8c4Sgaurav rana {
20694e3c8c4Sgaurav rana 	return caam_hash_update(ctx, buf, size, is_last, get_hash_type(algo));
20794e3c8c4Sgaurav rana }
20894e3c8c4Sgaurav rana 
20994e3c8c4Sgaurav rana int hw_sha_finish(struct hash_algo *algo, void *ctx, void *dest_buf,
21094e3c8c4Sgaurav rana 		     int size)
21194e3c8c4Sgaurav rana {
21294e3c8c4Sgaurav rana 	return caam_hash_finish(ctx, dest_buf, size, get_hash_type(algo));
21394e3c8c4Sgaurav rana }
214