1 /*
2  * Copyright (c) 2019, Remi Pommarel <repk@triplefau.lt>
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <arch_helpers.h>
8 #include <assert.h>
9 #include <crypto/sha_dma.h>
10 #include <lib/mmio.h>
11 
12 #include "aml_private.h"
13 
14 #define ASD_MODE_SHA224 0x7
15 #define ASD_MODE_SHA256 0x6
16 
17 /* SHA DMA descriptor */
18 struct asd_desc {
19 	uint32_t cfg;
20 	uint32_t src;
21 	uint32_t dst;
22 };
23 #define ASD_DESC_GET(x, msk, off) (((x) >> (off)) & (msk))
24 #define ASD_DESC_SET(x, v, msk, off)					\
25 	((x) = ((x) & ~((msk) << (off))) | (((v) & (msk)) << (off)))
26 
27 #define ASD_DESC_LEN_OFF 0
28 #define ASD_DESC_LEN_MASK 0x1ffff
29 #define ASD_DESC_LEN(d)							\
30 	(ASD_DESC_GET((d)->cfg, ASD_DESC_LEN_MASK, ASD_DESC_LEN_OFF))
31 #define ASD_DESC_LEN_SET(d, v)						\
32 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_LEN_MASK, ASD_DESC_LEN_OFF))
33 
34 #define ASD_DESC_IRQ_OFF 17
35 #define ASD_DESC_IRQ_MASK 0x1
36 #define ASD_DESC_IRQ(d)							\
37 	(ASD_DESC_GET((d)->cfg, ASD_DESC_IRQ_MASK, ASD_DESC_IRQ_OFF))
38 #define ASD_DESC_IRQ_SET(d, v)						\
39 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_IRQ_MASK, ASD_DESC_IRQ_OFF))
40 
41 #define ASD_DESC_EOD_OFF 18
42 #define ASD_DESC_EOD_MASK 0x1
43 #define ASD_DESC_EOD(d)							\
44 	(ASD_DESC_GET((d)->cfg, ASD_DESC_EOD_MASK, ASD_DESC_EOD_OFF))
45 #define ASD_DESC_EOD_SET(d, v)						\
46 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_EOD_MASK, ASD_DESC_EOD_OFF))
47 
48 #define ASD_DESC_LOOP_OFF 19
49 #define ASD_DESC_LOOP_MASK 0x1
50 #define ASD_DESC_LOOP(d)						\
51 	(ASD_DESC_GET((d)->cfg, ASD_DESC_LOOP_MASK, ASD_DESC_LOOP_OFF))
52 #define ASD_DESC_LOOP_SET(d, v)						\
53 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_LOOP_MASK, ASD_DESC_LOOP_OFF))
54 
55 #define ASD_DESC_MODE_OFF 20
56 #define ASD_DESC_MODE_MASK 0xf
57 #define ASD_DESC_MODE(d)						\
58 	(ASD_DESC_GET((d)->cfg, ASD_DESC_MODE_MASK, ASD_DESC_MODE_OFF))
59 #define ASD_DESC_MODE_SET(d, v)						\
60 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_MODE_MASK, ASD_DESC_MODE_OFF))
61 
62 #define ASD_DESC_BEGIN_OFF 24
63 #define ASD_DESC_BEGIN_MASK 0x1
64 #define ASD_DESC_BEGIN(d)						\
65 	(ASD_DESC_GET((d)->cfg, ASD_DESC_BEGIN_MASK, ASD_DESC_BEGIN_OFF))
66 #define ASD_DESC_BEGIN_SET(d, v)					\
67 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_BEGIN_MASK, ASD_DESC_BEGIN_OFF))
68 
69 #define ASD_DESC_END_OFF 25
70 #define ASD_DESC_END_MASK 0x1
71 #define ASD_DESC_END(d)							\
72 	(ASD_DESC_GET((d)->cfg, ASD_DESC_END_MASK, ASD_DESC_END_OFF))
73 #define ASD_DESC_END_SET(d, v)						\
74 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_END_MASK, ASD_DESC_END_OFF))
75 
76 #define ASD_DESC_OP_OFF 26
77 #define ASD_DESC_OP_MASK 0x2
78 #define ASD_DESC_OP(d)							\
79 	(ASD_DESC_GET((d)->cfg, ASD_DESC_OP_MASK, ASD_DESC_OP_OFF))
80 #define ASD_DESC_OP_SET(d, v)						\
81 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_OP_MASK, ASD_DESC_OP_OFF))
82 
83 #define ASD_DESC_ENCONLY_OFF 28
84 #define ASD_DESC_ENCONLY_MASK 0x1
85 #define ASD_DESC_ENCONLY(d)						\
86 	(ASD_DESC_GET((d)->cfg, ASD_DESC_ENCONLY_MASK, ASD_DESC_ENCONLY_OFF))
87 #define ASD_DESC_ENCONLY_SET(d, v)					\
88 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_ENCONLY_MASK, ASD_DESC_ENCONLY_OFF))
89 
90 #define ASD_DESC_BLOCK_OFF 29
91 #define ASD_DESC_BLOCK_MASK 0x1
92 #define ASD_DESC_BLOCK(d)						\
93 	(ASD_DESC_GET((d)->cfg, ASD_DESC_BLOCK_MASK, ASD_DESC_BLOCK_OFF))
94 #define ASD_DESC_BLOCK_SET(d, v)					\
95 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_BLOCK_MASK, ASD_DESC_BLOCK_OFF))
96 
97 #define ASD_DESC_ERR_OFF 30
98 #define ASD_DESC_ERR_MASK 0x1
99 #define ASD_DESC_ERR(d)						\
100 	(ASD_DESC_GET((d)->cfg, ASD_DESC_ERR_MASK, ASD_DESC_ERR_OFF))
101 #define ASD_DESC_ERR_SET(d, v)					\
102 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_ERR_MASK, ASD_DESC_ERR_OFF))
103 
104 #define ASD_DESC_OWNER_OFF 31u
105 #define ASD_DESC_OWNER_MASK 0x1u
106 #define ASD_DESC_OWNER(d)					\
107 	(ASD_DESC_GET((d)->cfg, ASD_DESC_OWNER_MASK, ASD_DESC_OWNER_OFF))
108 #define ASD_DESC_OWNER_SET(d, v)				\
109 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_OWNER_MASK, ASD_DESC_OWNER_OFF))
110 
asd_compute_sha(struct asd_ctx * ctx,void * data,size_t len,int finalize)111 static void asd_compute_sha(struct asd_ctx *ctx, void *data, size_t len,
112 		int finalize)
113 {
114 	/* Make it cache line size aligned ? */
115 	struct asd_desc desc = {
116 		.src = (uint32_t)(uintptr_t)data,
117 		.dst = (uint32_t)(uintptr_t)ctx->digest,
118 	};
119 
120 	/* Check data address is 32bit compatible */
121 	assert((uintptr_t)data == (uintptr_t)desc.src);
122 	assert((uintptr_t)ctx->digest == (uintptr_t)desc.dst);
123 	assert((uintptr_t)&desc == (uintptr_t)&desc);
124 
125 	ASD_DESC_LEN_SET(&desc, len);
126 	ASD_DESC_OWNER_SET(&desc, 1u);
127 	ASD_DESC_ENCONLY_SET(&desc, 1);
128 	ASD_DESC_EOD_SET(&desc, 1);
129 	if (ctx->started == 0) {
130 		ASD_DESC_BEGIN_SET(&desc, 1);
131 		ctx->started = 1;
132 	}
133 	if (finalize) {
134 		ASD_DESC_END_SET(&desc, 1);
135 		ctx->started = 0;
136 	}
137 	if (ctx->mode == ASM_SHA224)
138 		ASD_DESC_MODE_SET(&desc, ASD_MODE_SHA224);
139 	else
140 		ASD_DESC_MODE_SET(&desc, ASD_MODE_SHA256);
141 
142 	flush_dcache_range((uintptr_t)&desc, sizeof(desc));
143 	flush_dcache_range((uintptr_t)data, len);
144 
145 	mmio_write_32(AML_SHA_DMA_STATUS, 0xf);
146 	mmio_write_32(AML_SHA_DMA_DESC, ((uintptr_t)&desc) | 2);
147 	while (mmio_read_32(AML_SHA_DMA_STATUS) == 0)
148 		continue;
149 	flush_dcache_range((uintptr_t)ctx->digest, SHA256_HASHSZ);
150 }
151 
asd_sha_update(struct asd_ctx * ctx,void * data,size_t len)152 void asd_sha_update(struct asd_ctx *ctx, void *data, size_t len)
153 {
154 	size_t nr;
155 
156 	if (ctx->blocksz) {
157 		nr = MIN(len, SHA256_BLOCKSZ - ctx->blocksz);
158 		memcpy(ctx->block + ctx->blocksz, data, nr);
159 		ctx->blocksz += nr;
160 		len -= nr;
161 		data += nr;
162 	}
163 
164 	if (ctx->blocksz == SHA256_BLOCKSZ) {
165 		asd_compute_sha(ctx, ctx->block, SHA256_BLOCKSZ, 0);
166 		ctx->blocksz = 0;
167 	}
168 
169 	asd_compute_sha(ctx, data, len & ~(SHA256_BLOCKSZ - 1), 0);
170 	data += len & ~(SHA256_BLOCKSZ - 1);
171 
172 	if (len & (SHA256_BLOCKSZ - 1)) {
173 		nr = len & (SHA256_BLOCKSZ - 1);
174 		memcpy(ctx->block + ctx->blocksz, data, nr);
175 		ctx->blocksz += nr;
176 	}
177 }
178 
asd_sha_finalize(struct asd_ctx * ctx)179 void asd_sha_finalize(struct asd_ctx *ctx)
180 {
181 	asd_compute_sha(ctx, ctx->block, ctx->blocksz, 1);
182 }
183