xref: /openbmc/u-boot/drivers/crypto/aspeed_hace.c (revision 13765e7f)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * (C) Copyright ASPEED Technology Inc.
4  * Copyright 2021 IBM Corp.
5  */
6 #include <common.h>
7 #include <clk.h>
8 
9 #include <log.h>
10 #include <asm/io.h>
11 #include <malloc.h>
12 #include <hash.h>
13 
14 #include <dm/device.h>
15 #include <dm/fdtaddr.h>
16 
17 #include <linux/bitops.h>
18 #include <linux/delay.h>
19 #include <linux/kernel.h>
20 #include <linux/iopoll.h>
21 
22 #define ASPEED_HACE_STS			0x1C
23 #define  HACE_RSA_ISR			BIT(13)
24 #define  HACE_CRYPTO_ISR		BIT(12)
25 #define  HACE_HASH_ISR			BIT(9)
26 #define  HACE_RSA_BUSY			BIT(2)
27 #define  HACE_CRYPTO_BUSY		BIT(1)
28 #define  HACE_HASH_BUSY			BIT(0)
29 #define ASPEED_HACE_HASH_SRC		0x20
30 #define ASPEED_HACE_HASH_DIGEST_BUFF	0x24
31 #define ASPEED_HACE_HASH_KEY_BUFF	0x28
32 #define ASPEED_HACE_HASH_DATA_LEN	0x2C
33 #define  HACE_SG_LAST			BIT(31)
34 #define ASPEED_HACE_HASH_CMD		0x30
35 #define  HACE_SHA_BE_EN			BIT(3)
36 #define  HACE_MD5_LE_EN			BIT(2)
37 #define  HACE_ALGO_MD5			0
38 #define  HACE_ALGO_SHA1			BIT(5)
39 #define  HACE_ALGO_SHA224		BIT(6)
40 #define  HACE_ALGO_SHA256		(BIT(4) | BIT(6))
41 #define  HACE_ALGO_SHA512		(BIT(5) | BIT(6))
42 #define  HACE_ALGO_SHA384		(BIT(5) | BIT(6) | BIT(10))
43 #define  HASH_CMD_ACC_MODE		(0x2 << 7)
44 #define  HACE_SG_EN			BIT(18)
45 
46 #define ASPEED_SHA1_DIGEST_SIZE		20
47 #define ASPEED_SHA256_DIGEST_SIZE	32
48 #define ASPEED_SHA384_DIGEST_SIZE	64
49 #define ASPEED_SHA512_DIGEST_SIZE	64
50 
51 #define ASPEED_SHA_TYPE_SHA1		1
52 #define ASPEED_SHA_TYPE_SHA256		2
53 #define ASPEED_SHA_TYPE_SHA384		3
54 #define ASPEED_SHA_TYPE_SHA512		4
55 
56 struct aspeed_sg {
57 	u32 len;
58 	u32 addr;
59 };
60 
61 struct aspeed_hash_ctx {
62 	struct aspeed_sg sg[2]; /* Must be 8 byte aligned */
63 	u8 digest[64]; /* Must be 8 byte aligned */
64 	u32 method;
65 	u32 digest_size;
66 	u32 block_size;
67 	u64 digcnt[2]; /* total length */
68 	u32 bufcnt;
69 	u8 buffer[256];
70 };
71 
72 struct aspeed_hace {
73 	struct clk clk;
74 };
75 
76 static const u32 sha1_iv[8] = {
77 	0x01234567UL, 0x89abcdefUL, 0xfedcba98UL, 0x76543210UL,
78 	0xf0e1d2c3UL, 0, 0, 0
79 };
80 
81 static const u32 sha256_iv[8] = {
82 	0x67e6096aUL, 0x85ae67bbUL, 0x72f36e3cUL, 0x3af54fa5UL,
83 	0x7f520e51UL, 0x8c68059bUL, 0xabd9831fUL, 0x19cde05bUL
84 };
85 
86 static const u32 sha384_iv[16] = {
87 	0x5d9dbbcbUL, 0xd89e05c1UL, 0x2a299a62UL, 0x07d57c36UL,
88 	0x5a015991UL, 0x17dd7030UL, 0xd8ec2f15UL, 0x39590ef7UL,
89 	0x67263367UL, 0x310bc0ffUL, 0x874ab48eUL, 0x11155868UL,
90 	0x0d2e0cdbUL, 0xa78ff964UL, 0x1d48b547UL, 0xa44ffabeUL
91 };
92 
93 static const u32 sha512_iv[16] = {
94 	0x67e6096aUL, 0x08c9bcf3UL, 0x85ae67bbUL, 0x3ba7ca84UL,
95 	0x72f36e3cUL, 0x2bf894feUL, 0x3af54fa5UL, 0xf1361d5fUL,
96 	0x7f520e51UL, 0xd182e6adUL, 0x8c68059bUL, 0x1f6c3e2bUL,
97 	0xabd9831fUL, 0x6bbd41fbUL, 0x19cde05bUL, 0x79217e13UL
98 };
99 
100 static phys_addr_t base;
101 
102 static int aspeed_hace_wait_completion(u32 reg, u32 flag, int timeout_us)
103 {
104 	u32 val;
105 
106 	return readl_poll_timeout(reg, val, (val & flag) == flag, timeout_us);
107 }
108 
109 static void aspeed_ahash_fill_padding(struct aspeed_hash_ctx *ctx, unsigned int remainder)
110 {
111 	unsigned int index, padlen;
112 	u64 bits[2];
113 
114 	if (ctx->block_size == 64) {
115 		bits[0] = cpu_to_be64(ctx->digcnt[0] << 3);
116 		index = (ctx->bufcnt + remainder) & 0x3f;
117 		padlen = (index < 56) ? (56 - index) : ((64 + 56) - index);
118 		*(ctx->buffer + ctx->bufcnt) = 0x80;
119 		memset(ctx->buffer + ctx->bufcnt + 1, 0, padlen - 1);
120 		memcpy(ctx->buffer + ctx->bufcnt + padlen, bits, 8);
121 		ctx->bufcnt += padlen + 8;
122 	} else {
123 		bits[1] = cpu_to_be64(ctx->digcnt[0] << 3);
124 		bits[0] = cpu_to_be64(ctx->digcnt[1] << 3 | ctx->digcnt[0] >> 61);
125 		index = (ctx->bufcnt + remainder) & 0x7f;
126 		padlen = (index < 112) ? (112 - index) : ((128 + 112) - index);
127 		*(ctx->buffer + ctx->bufcnt) = 0x80;
128 		memset(ctx->buffer + ctx->bufcnt + 1, 0, padlen - 1);
129 		memcpy(ctx->buffer + ctx->bufcnt + padlen, bits, 16);
130 		ctx->bufcnt += padlen + 16;
131 	}
132 }
133 
134 static int hash_trigger(struct aspeed_hash_ctx *ctx, int hash_len)
135 {
136 	if (readl(base + ASPEED_HACE_STS) & HACE_HASH_BUSY) {
137 		debug("HACE error: engine busy\n");
138 		return -EBUSY;
139 	}
140 	/* Clear pending completion status */
141 	writel(HACE_HASH_ISR, base + ASPEED_HACE_STS);
142 
143 	writel((u32)ctx->sg, base + ASPEED_HACE_HASH_SRC);
144 	writel((u32)ctx->digest, base + ASPEED_HACE_HASH_DIGEST_BUFF);
145 	writel((u32)ctx->digest, base + ASPEED_HACE_HASH_KEY_BUFF);
146 	writel(hash_len, base + ASPEED_HACE_HASH_DATA_LEN);
147 	writel(ctx->method, base + ASPEED_HACE_HASH_CMD);
148 
149 	/* SHA512 hashing appears to have a througput of about 12MB/s */
150 	return aspeed_hace_wait_completion(base + ASPEED_HACE_STS,
151 					   HACE_HASH_ISR,
152 					   1000 + (hash_len >> 3));
153 }
154 
155 #if IS_ENABLED(CONFIG_SHA_PROG_HW_ACCEL)
156 int hw_sha_init(struct hash_algo *algo, void **ctxp)
157 {
158 	struct aspeed_hash_ctx *ctx;
159 	u32 method;
160 	u32 block_size;
161 
162 	ctx = memalign(8, sizeof(struct aspeed_hash_ctx));
163 	memset(ctx, '\0', sizeof(struct aspeed_hash_ctx));
164 
165 	method = HASH_CMD_ACC_MODE | HACE_SHA_BE_EN | HACE_SG_EN;
166 	if (!strcmp(algo->name, "sha1")) {
167 		method |= HACE_ALGO_SHA1;
168 		block_size = 64;
169 		memcpy(ctx->digest, sha1_iv, 32);
170 	} else if (!strcmp(algo->name, "sha256")) {
171 		method |= HACE_ALGO_SHA256;
172 		block_size = 64;
173 		memcpy(ctx->digest, sha256_iv, 32);
174 	} else if (!strcmp(algo->name, "sha384")) {
175 		method |= HACE_ALGO_SHA384;
176 		block_size = 128;
177 		memcpy(ctx->digest, sha384_iv, 64);
178 	} else if (!strcmp(algo->name, "sha512")) {
179 		method |= HACE_ALGO_SHA512;
180 		block_size = 128;
181 		memcpy(ctx->digest, sha512_iv, 64);
182 	} else {
183 		return -ENOTSUPP;
184 	}
185 
186 	if (!ctx) {
187 		debug("HACE error: Cannot allocate memory for context\n");
188 		return -ENOMEM;
189 	}
190 
191 	ctx->method = method;
192 	ctx->block_size = block_size;
193 	ctx->digest_size = algo->digest_size;
194 	ctx->bufcnt = 0;
195 	ctx->digcnt[0] = 0;
196 	ctx->digcnt[1] = 0;
197 	*ctxp = ctx;
198 
199 	return 0;
200 }
201 
202 int hw_sha_update(struct hash_algo *algo, void *hash_ctx, const void *buf,
203 		  unsigned int size, int is_last)
204 {
205 	struct aspeed_hash_ctx *ctx = hash_ctx;
206 	struct aspeed_sg *sg = ctx->sg;
207 	int rc;
208 	int remainder;
209 	int total_len;
210 	int i;
211 
212 	ctx->digcnt[0] += size;
213 	if (ctx->digcnt[0] < size)
214 		ctx->digcnt[1]++;
215 
216 	if (ctx->bufcnt + size < ctx->block_size) {
217 		memcpy(ctx->buffer + ctx->bufcnt, buf, size);
218 		ctx->bufcnt += size;
219 		return 0;
220 	}
221 	remainder = (size + ctx->bufcnt) % ctx->block_size;
222 	total_len = size + ctx->bufcnt - remainder;
223 	i = 0;
224 	if (ctx->bufcnt != 0) {
225 		sg[0].addr = (u32)ctx->buffer;
226 		sg[0].len = ctx->bufcnt;
227 		if (total_len == ctx->bufcnt)
228 			sg[0].len |= HACE_SG_LAST;
229 		i++;
230 	}
231 
232 	if (total_len != ctx->bufcnt) {
233 		sg[i].addr = (u32)buf;
234 		sg[i].len = (total_len - ctx->bufcnt) | HACE_SG_LAST;
235 	}
236 
237 	rc = hash_trigger(ctx, total_len);
238 	if (remainder != 0) {
239 		memcpy(ctx->buffer, buf + (total_len - ctx->bufcnt), remainder);
240 		ctx->bufcnt = remainder;
241 	}
242 
243 	return rc;
244 }
245 
246 int hw_sha_finish(struct hash_algo *algo, void *hash_ctx, void *dest_buf, int size)
247 {
248 	struct aspeed_hash_ctx *ctx = hash_ctx;
249 	struct aspeed_sg *sg = ctx->sg;
250 	int rc;
251 
252 	if (size < ctx->digest_size) {
253 		debug("HACE error: insufficient size on destination buffer\n");
254 		free(ctx);
255 		return -EINVAL;
256 	}
257 	aspeed_ahash_fill_padding(ctx, 0);
258 
259 	sg[0].addr = (u32)ctx->buffer;
260 	sg[0].len = ctx->bufcnt | HACE_SG_LAST;
261 
262 	rc = hash_trigger(ctx, ctx->bufcnt);
263 	memcpy(dest_buf, ctx->digest, ctx->digest_size);
264 
265 	free(ctx);
266 
267 	return rc;
268 }
269 #endif
270 
271 static int sha_digest(const void *src, unsigned int length, void *digest,
272 		      u32 sha_type)
273 {
274 	struct aspeed_hash_ctx *ctx;
275 	int ret;
276 
277 	if (!((u32)src & BIT(31))) {
278 		debug("HACE src out of bounds: can only copy from SDRAM\n");
279 		return -EINVAL;
280 	}
281 
282 	if (readl(base + ASPEED_HACE_STS) & HACE_HASH_BUSY) {
283 		debug("HACE error: engine busy\n");
284 		return -EBUSY;
285 	}
286 
287 	ctx = memalign(8, sizeof(struct aspeed_hash_ctx));
288 	memset(ctx, '\0', sizeof(struct aspeed_hash_ctx));
289 
290 	if (!ctx) {
291 		debug("HACE error: Cannot allocate memory for context\n");
292 		return -ENOMEM;
293 	}
294 	ctx->method = HASH_CMD_ACC_MODE | HACE_SHA_BE_EN | HACE_SG_EN;
295 
296 	switch (sha_type) {
297 	case ASPEED_SHA_TYPE_SHA1:
298 		ctx->block_size = 64;
299 		ctx->digest_size = 20;
300 		ctx->method |= HACE_ALGO_SHA1;
301 		memcpy(ctx->digest, sha1_iv, 32);
302 		break;
303 	case ASPEED_SHA_TYPE_SHA256:
304 		ctx->block_size = 64;
305 		ctx->digest_size = 32;
306 		ctx->method |= HACE_ALGO_SHA256;
307 		memcpy(ctx->digest, sha256_iv, 32);
308 		break;
309 	case ASPEED_SHA_TYPE_SHA384:
310 		ctx->block_size = 128;
311 		ctx->digest_size = 64;
312 		ctx->method |= HACE_ALGO_SHA384;
313 		memcpy(ctx->digest, sha384_iv, 64);
314 		break;
315 	case ASPEED_SHA_TYPE_SHA512:
316 		ctx->block_size = 128;
317 		ctx->digest_size = 64;
318 		ctx->method |= HACE_ALGO_SHA512;
319 		memcpy(ctx->digest, sha512_iv, 64);
320 		break;
321 	default:
322 		return -ENOTSUPP;
323 	}
324 
325 	ctx->digcnt[0] = length;
326 	ctx->digcnt[1] = 0;
327 
328 	aspeed_ahash_fill_padding(ctx, length);
329 
330 	if (length != 0) {
331 		ctx->sg[0].addr = (u32)src;
332 		ctx->sg[0].len = length;
333 		ctx->sg[1].addr = (u32)ctx->buffer;
334 		ctx->sg[1].len = ctx->bufcnt | HACE_SG_LAST;
335 	} else {
336 		ctx->sg[0].addr = (u32)ctx->buffer;
337 		ctx->sg[0].len = ctx->bufcnt | HACE_SG_LAST;
338 	}
339 
340 	ret = hash_trigger(ctx, length + ctx->bufcnt);
341 	memcpy(digest, ctx->digest, ctx->digest_size);
342 	free(ctx);
343 
344 	return ret;
345 }
346 
347 void hw_sha1(const unsigned char *pbuf, unsigned int buf_len,
348 	     unsigned char *pout, unsigned int chunk_size)
349 {
350 	int rc;
351 
352 	rc = sha_digest(pbuf, buf_len, pout, ASPEED_SHA_TYPE_SHA1);
353 	if (rc)
354 		debug("HACE failure: %d\n", rc);
355 }
356 
357 void hw_sha256(const unsigned char *pbuf, unsigned int buf_len,
358 	       unsigned char *pout, unsigned int chunk_size)
359 {
360 	int rc;
361 
362 	rc = sha_digest(pbuf, buf_len, pout, ASPEED_SHA_TYPE_SHA256);
363 	if (rc)
364 		debug("HACE failure: %d\n", rc);
365 }
366 
367 void hw_sha384(const unsigned char *pbuf, unsigned int buf_len,
368 	       unsigned char *pout, unsigned int chunk_size)
369 {
370 	int rc;
371 
372 	rc = sha_digest(pbuf, buf_len, pout, ASPEED_SHA_TYPE_SHA384);
373 	if (rc)
374 		debug("HACE failure: %d\n", rc);
375 }
376 
377 void hw_sha512(const unsigned char *pbuf, unsigned int buf_len,
378 	       unsigned char *pout, unsigned int chunk_size)
379 {
380 	int rc;
381 
382 	rc = sha_digest(pbuf, buf_len, pout, ASPEED_SHA_TYPE_SHA512);
383 	if (rc)
384 		debug("HACE failure: %d\n", rc);
385 }
386 
387 static int aspeed_hace_probe(struct udevice *dev)
388 {
389 	struct aspeed_hace *hace = dev_get_priv(dev);
390 	int ret;
391 
392 	ret = clk_get_by_index(dev, 0, &hace->clk);
393 	if (ret < 0) {
394 		debug("Can't get clock for %s: %d\n", dev->name, ret);
395 		return ret;
396 	}
397 
398 	ret = clk_enable(&hace->clk);
399 	if (ret) {
400 		debug("Failed to enable fsi clock (%d)\n", ret);
401 		return ret;
402 	}
403 
404 	/* As the crypto code does not pass us any driver state */
405 	base = devfdt_get_addr(dev);
406 
407 	return ret;
408 }
409 
410 static int aspeed_hace_remove(struct udevice *dev)
411 {
412 	struct aspeed_hace *hace = dev_get_priv(dev);
413 
414 	clk_disable(&hace->clk);
415 
416 	return 0;
417 }
418 
419 static const struct udevice_id aspeed_hace_ids[] = {
420 	{ .compatible = "aspeed,ast2600-hace" },
421 	{ }
422 };
423 
424 U_BOOT_DRIVER(aspeed_hace) = {
425 	.name		= "aspeed_hace",
426 	.id		= UCLASS_MISC,
427 	.of_match	= aspeed_hace_ids,
428 	.probe		= aspeed_hace_probe,
429 	.remove		= aspeed_hace_remove,
430 	.priv_auto_alloc_size = sizeof(struct aspeed_hace),
431 	.flags  = DM_FLAG_PRE_RELOC,
432 };
433