1 /*
2  * Copyright (c) 2023 ITE Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT ite_it8xxx2_sha
8 
9 #include <zephyr/kernel.h>
10 #include <zephyr/crypto/crypto.h>
11 #include <zephyr/sys/byteorder.h>
12 #include <chip_chipregs.h>
13 #include <errno.h>
14 
15 #include <zephyr/logging/log.h>
16 LOG_MODULE_REGISTER(sha_it8xxx2, CONFIG_CRYPTO_LOG_LEVEL);
17 
18 BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1,
19 	     "unsupported sha instance");
20 
21 #define IT8XXX2_SHA_REGS_BASE DT_REG_ADDR(DT_NODELABEL(sha0))
22 
23 /* 0x00: Hash Control Register */
24 #define IT8XXX2_REG_HASHCTRLR    (0)
25 /* 0x01: SHA256 Hash Base Address 1 Register */
26 #define IT8XXX2_REG_SHA_HBADDR   (1)
27 /* 0x02: SHA256 Hash Base Address 2 Register */
28 #define IT8XXX2_REG_SHA_HBADDR2  (2)
29 
30 #define IT8XXX2_SHA_START_SHA256 BIT(1)
31 
32 #define SHA_SHA256_HASH_LEN        32
33 #define SHA_SHA256_BLOCK_LEN       64
34 #define SHA_SHA256_K_LEN           256
35 #define SHA_SHA256_HASH_LEN_WORDS  (SHA_SHA256_HASH_LEN / sizeof(uint32_t))
36 #define SHA_SHA256_BLOCK_LEN_WORDS (SHA_SHA256_BLOCK_LEN / sizeof(uint32_t))
37 #define SHA_SHA256_K_LEN_WORDS     (SHA_SHA256_K_LEN / sizeof(uint32_t))
38 
39 /*
40  * This struct is used by the hardware and must be stored in RAM first 4k-byte
41  * and aligned on a 256-byte boundary.
42  */
43 struct chip_sha256_ctx {
44 	union {
45 		/* W[0] ~ W[15] */
46 		uint32_t w_sha[SHA_SHA256_BLOCK_LEN_WORDS];
47 		uint8_t w_input[SHA_SHA256_BLOCK_LEN];
48 	};
49 	/* reserved */
50 	uint32_t reserved1[8];
51 	/* H[0] ~ H[7] */
52 	uint32_t h[SHA_SHA256_HASH_LEN_WORDS];
53 	/* reserved */
54 	uint32_t reserved2[30];
55 	uint32_t w_input_index;
56 	uint32_t total_len;
57 	/* K[0] ~ K[63] */
58 	uint32_t k[SHA_SHA256_K_LEN_WORDS];
59 } __aligned(256);
60 
61 Z_GENERIC_SECTION(.__sha256_ram_block) struct chip_sha256_ctx chip_ctx;
62 
63 static const uint32_t sha256_h0[SHA_SHA256_HASH_LEN_WORDS] = {
64 	0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c,
65 	0x1f83d9ab, 0x5be0cd19
66 };
67 
68 /*
69  * References of K of SHA-256:
70  * https://en.wikipedia.org/wiki/SHA-2#Pseudocode
71  */
72 static const uint32_t sha256_k[SHA_SHA256_K_LEN_WORDS] = {
73 	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
74 	0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
75 	0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
76 	0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
77 	0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
78 	0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
79 	0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
80 	0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
81 	0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
82 	0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
83 	0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
84 };
85 
it8xxx2_sha256_init(bool init_k)86 static void it8xxx2_sha256_init(bool init_k)
87 {
88 	int i;
89 
90 	chip_ctx.total_len = 0;
91 	chip_ctx.w_input_index = 0;
92 
93 	/* Initialize hash values */
94 	for (i = 0; i < ARRAY_SIZE(sha256_h0); i++) {
95 		chip_ctx.h[i] = sha256_h0[i];
96 	}
97 	/* Initialize array of round constants */
98 	if (init_k) {
99 		for (i = 0; i < ARRAY_SIZE(sha256_k); i++) {
100 			chip_ctx.k[i] = sha256_k[i];
101 		}
102 	}
103 }
104 
it8xxx2_sha256_module_calculation(void)105 static void it8xxx2_sha256_module_calculation(void)
106 {
107 	uint32_t key;
108 	uint8_t hash_ctrl;
109 
110 	/*
111 	 * Since W field on it8xxx2 requires big-endian format, change byte
112 	 * order before computing hash.
113 	 */
114 	for (int i = 0; i < SHA_SHA256_BLOCK_LEN_WORDS; i++) {
115 		chip_ctx.w_sha[i] = sys_cpu_to_be32(chip_ctx.w_sha[i]);
116 	}
117 	/*
118 	 * Global interrupt is disabled because the CPU cannot access memory
119 	 * via the DLM (Data Local Memory) bus while HW module is computing
120 	 * hash.
121 	 */
122 	key = irq_lock();
123 	hash_ctrl = sys_read8(IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_HASHCTRLR);
124 	sys_write8(hash_ctrl | IT8XXX2_SHA_START_SHA256,
125 			IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_HASHCTRLR);
126 	hash_ctrl = sys_read8(IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_HASHCTRLR);
127 	irq_unlock(key);
128 
129 	chip_ctx.w_input_index = 0;
130 }
131 
it8xxx2_hash_handler(struct hash_ctx * ctx,struct hash_pkt * pkt,bool finish)132 static int it8xxx2_hash_handler(struct hash_ctx *ctx, struct hash_pkt *pkt,
133 				bool finish)
134 {
135 	uint32_t rem_len = pkt->in_len;
136 	uint32_t in_buf_idx = 0;
137 
138 	while (rem_len--) {
139 		chip_ctx.w_input[chip_ctx.w_input_index++] =
140 						pkt->in_buf[in_buf_idx++];
141 		if (chip_ctx.w_input_index >= SHA_SHA256_BLOCK_LEN) {
142 			it8xxx2_sha256_module_calculation();
143 		}
144 	}
145 	chip_ctx.total_len += pkt->in_len;
146 
147 	if (finish) {
148 		uint32_t *ob_ptr = (uint32_t *)pkt->out_buf;
149 
150 		/* Pre-processing (Padding) */
151 		memset(&chip_ctx.w_input[chip_ctx.w_input_index],
152 			0, SHA_SHA256_BLOCK_LEN - chip_ctx.w_input_index);
153 		chip_ctx.w_input[chip_ctx.w_input_index] = 0x80;
154 
155 		if (chip_ctx.w_input_index >= 56) {
156 			it8xxx2_sha256_module_calculation();
157 			memset(&chip_ctx.w_input[chip_ctx.w_input_index],
158 			0, SHA_SHA256_BLOCK_LEN - chip_ctx.w_input_index);
159 		}
160 		chip_ctx.w_sha[15] = sys_cpu_to_be32(chip_ctx.total_len * 8);
161 		it8xxx2_sha256_module_calculation();
162 
163 		for (int i = 0; i < SHA_SHA256_HASH_LEN_WORDS; i++) {
164 			ob_ptr[i] = sys_be32_to_cpu(chip_ctx.h[i]);
165 		}
166 
167 		it8xxx2_sha256_init(false);
168 	}
169 
170 	return 0;
171 }
172 
it8xxx2_hash_session_free(const struct device * dev,struct hash_ctx * ctx)173 static int it8xxx2_hash_session_free(const struct device *dev,
174 				struct hash_ctx *ctx)
175 {
176 	it8xxx2_sha256_init(false);
177 
178 	return 0;
179 }
180 
it8xxx2_query_hw_caps(const struct device * dev)181 static inline int it8xxx2_query_hw_caps(const struct device *dev)
182 {
183 	return (CAP_SEPARATE_IO_BUFS | CAP_SYNC_OPS);
184 }
185 
it8xxx2_hash_begin_session(const struct device * dev,struct hash_ctx * ctx,enum hash_algo algo)186 static int it8xxx2_hash_begin_session(const struct device *dev,
187 				struct hash_ctx *ctx, enum hash_algo algo)
188 {
189 	if (algo != CRYPTO_HASH_ALGO_SHA256) {
190 		LOG_ERR("Unsupported algo");
191 		return -EINVAL;
192 	}
193 
194 	if (ctx->flags & ~(it8xxx2_query_hw_caps(dev))) {
195 		LOG_ERR("Unsupported flag");
196 		return -EINVAL;
197 	}
198 
199 	it8xxx2_sha256_init(false);
200 	ctx->hash_hndlr = it8xxx2_hash_handler;
201 
202 	return 0;
203 }
204 
it8xxx2_sha_init(const struct device * dev)205 static int it8xxx2_sha_init(const struct device *dev)
206 {
207 	it8xxx2_sha256_init(true);
208 	/* Configure base address register for W and H */
209 	sys_write8(((uint32_t)&chip_ctx >> 6) & 0xfc,
210 			IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHA_HBADDR);
211 	/* Configure base address register for K */
212 	sys_write8(((uint32_t)&chip_ctx.k >> 6) & 0xfc,
213 			IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHA_HBADDR2);
214 
215 	return 0;
216 }
217 
218 static const struct crypto_driver_api it8xxx2_crypto_api = {
219 	.hash_begin_session = it8xxx2_hash_begin_session,
220 	.hash_free_session = it8xxx2_hash_session_free,
221 	.query_hw_caps = it8xxx2_query_hw_caps,
222 };
223 
224 DEVICE_DT_INST_DEFINE(0, &it8xxx2_sha_init, NULL, NULL, NULL, POST_KERNEL,
225 			CONFIG_CRYPTO_INIT_PRIORITY, &it8xxx2_crypto_api);
226