1 #include "bflb_sec_aes.h"
2 #include "hardware/sec_eng_reg.h"
3 
4 #define CONFIG_BFLB_AES_USE_BE
5 
6 #define BFLB_PUT_LE32(p) ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | (p[0]))
7 #define BFLB_PUT_BE32(p) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]))
8 
9 volatile uint8_t hw_key_sel = 1;
10 
bflb_aes_init(struct bflb_device_s * dev)11 void bflb_aes_init(struct bflb_device_s *dev)
12 {
13     uint32_t regval;
14     uint32_t reg_base;
15 
16     reg_base = dev->reg_base;
17 
18 #ifdef CONFIG_BFLB_AES_USE_BE
19     putreg32(0x1f, reg_base + SEC_ENG_SE_AES_0_ENDIAN_OFFSET);
20 #else
21     putreg32(0x10, reg_base + SEC_ENG_SE_AES_0_ENDIAN_OFFSET);
22 #endif
23 
24     regval = getreg32(reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
25     regval |= SEC_ENG_SE_AES_0_EN;
26     putreg32(regval, reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
27 }
28 
bflb_aes_deinit(struct bflb_device_s * dev)29 void bflb_aes_deinit(struct bflb_device_s *dev)
30 {
31     uint32_t regval;
32     uint32_t reg_base;
33 
34     reg_base = dev->reg_base;
35 
36     regval = getreg32(reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
37     regval &= ~SEC_ENG_SE_AES_0_EN;
38     putreg32(regval, reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
39 }
40 
bflb_aes_set_hwkey(uint8_t keysel)41 void bflb_aes_set_hwkey(uint8_t keysel)
42 {
43     hw_key_sel = keysel;
44 }
45 
bflb_aes_set_mode(struct bflb_device_s * dev,uint8_t mode)46 void bflb_aes_set_mode(struct bflb_device_s *dev, uint8_t mode)
47 {
48     uint32_t regval;
49     uint32_t reg_base;
50 
51     reg_base = dev->reg_base;
52 
53     regval = getreg32(reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
54     regval &= ~SEC_ENG_SE_AES_0_BLOCK_MODE_MASK;
55     regval |= (mode << SEC_ENG_SE_AES_0_BLOCK_MODE_SHIFT);
56 
57     if (mode == AES_MODE_CTR) {
58         regval |= SEC_ENG_SE_AES_0_DEC_KEY_SEL;
59     } else {
60         regval &= ~SEC_ENG_SE_AES_0_DEC_KEY_SEL; /* clear key to set new key */
61     }
62 
63     putreg32(regval, reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
64 }
65 
bflb_aes_setkey(struct bflb_device_s * dev,const uint8_t * key,uint16_t keybits)66 void bflb_aes_setkey(struct bflb_device_s *dev, const uint8_t *key, uint16_t keybits)
67 {
68     uint32_t regval;
69     uint32_t reg_base;
70     uint8_t mode;
71     uint8_t *temp_key = (uint8_t *)key;
72 
73     reg_base = dev->reg_base;
74 
75     regval = getreg32(reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
76     mode = (regval & SEC_ENG_SE_AES_0_BLOCK_MODE_MASK) >> SEC_ENG_SE_AES_0_BLOCK_MODE_SHIFT;
77 
78     regval &= ~SEC_ENG_SE_AES_0_MODE_MASK;
79     regval &= ~SEC_ENG_SE_AES_0_HW_KEY_EN;
80     if (key == NULL) {
81         regval |= SEC_ENG_SE_AES_0_HW_KEY_EN;
82     }
83 
84     if (keybits == 128) {
85         regval |= (0 << SEC_ENG_SE_AES_0_MODE_SHIFT);
86     } else if (keybits == 192) {
87         regval |= (2 << SEC_ENG_SE_AES_0_MODE_SHIFT);
88     } else if (keybits == 256) {
89         regval |= (1 << SEC_ENG_SE_AES_0_MODE_SHIFT);
90     } else {
91         regval |= (3 << SEC_ENG_SE_AES_0_MODE_SHIFT);
92     }
93     putreg32(regval, reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
94 
95     if (key == NULL) {
96         regval = getreg32(reg_base + SEC_ENG_SE_AES_0_KEY_SEL_OFFSET);
97         regval &= ~SEC_ENG_SE_AES_0_KEY_SEL_MASK;
98         regval |= (hw_key_sel << SEC_ENG_SE_AES_0_KEY_SEL_SHIFT);
99         putreg32(regval, reg_base + SEC_ENG_SE_AES_0_KEY_SEL_OFFSET);
100 
101         regval = getreg32(reg_base + SEC_ENG_SE_AES_1_KEY_SEL_OFFSET);
102         regval &= ~SEC_ENG_SE_AES_1_KEY_SEL_MASK;
103         regval |= (hw_key_sel << SEC_ENG_SE_AES_1_KEY_SEL_SHIFT);
104         putreg32(regval, reg_base + SEC_ENG_SE_AES_1_KEY_SEL_OFFSET);
105     } else {
106         putreg32(BFLB_PUT_LE32(temp_key), reg_base + SEC_ENG_SE_AES_0_KEY_0_OFFSET);
107         temp_key += 4;
108         putreg32(BFLB_PUT_LE32(temp_key), reg_base + SEC_ENG_SE_AES_0_KEY_1_OFFSET);
109         temp_key += 4;
110         putreg32(BFLB_PUT_LE32(temp_key), reg_base + SEC_ENG_SE_AES_0_KEY_2_OFFSET);
111         temp_key += 4;
112         putreg32(BFLB_PUT_LE32(temp_key), reg_base + SEC_ENG_SE_AES_0_KEY_3_OFFSET);
113         temp_key += 4;
114 
115         if (keybits == 192) {
116             putreg32(BFLB_PUT_LE32(temp_key), reg_base + SEC_ENG_SE_AES_0_KEY_4_OFFSET);
117             temp_key += 4;
118             putreg32(BFLB_PUT_LE32(temp_key), reg_base + SEC_ENG_SE_AES_0_KEY_5_OFFSET);
119             temp_key += 4;
120         } else if ((keybits == 256) || (mode == AES_MODE_XTS)) {
121             putreg32(BFLB_PUT_LE32(temp_key), reg_base + SEC_ENG_SE_AES_0_KEY_4_OFFSET);
122             temp_key += 4;
123             putreg32(BFLB_PUT_LE32(temp_key), reg_base + SEC_ENG_SE_AES_0_KEY_5_OFFSET);
124             temp_key += 4;
125             putreg32(BFLB_PUT_LE32(temp_key), reg_base + SEC_ENG_SE_AES_0_KEY_6_OFFSET);
126             temp_key += 4;
127             putreg32(BFLB_PUT_LE32(temp_key), reg_base + SEC_ENG_SE_AES_0_KEY_7_OFFSET);
128             temp_key += 4;
129         }
130     }
131 }
132 
bflb_aes_encrypt(struct bflb_device_s * dev,const uint8_t * input,const uint8_t * iv,uint8_t * output,uint32_t len)133 int bflb_aes_encrypt(struct bflb_device_s *dev,
134                      const uint8_t *input,
135                      const uint8_t *iv,
136                      uint8_t *output,
137                      uint32_t len)
138 {
139     uint32_t regval;
140     uint32_t reg_base;
141     uint64_t start_time;
142     uint8_t mode;
143     uint8_t *temp_iv = (uint8_t *)iv;
144 
145     reg_base = dev->reg_base;
146 
147     if (len % 16) {
148         return -EINVAL;
149     }
150 
151     regval = getreg32(reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
152     regval &= ~SEC_ENG_SE_AES_0_TRIG_1T;
153     if (temp_iv) {
154         regval &= ~SEC_ENG_SE_AES_0_IV_SEL; /* Clear aes iv sel to select new iv */
155     } else {
156         regval |= SEC_ENG_SE_AES_0_IV_SEL; /* Clear aes iv sel to select last iv */
157     }
158     regval &= ~SEC_ENG_SE_AES_0_DEC_EN; /* Set AES encryption */
159     regval &= ~SEC_ENG_SE_AES_0_MSG_LEN_MASK;
160     regval |= SEC_ENG_SE_AES_0_INT_CLR_1T;
161     regval |= ((len / 16) << SEC_ENG_SE_AES_0_MSG_LEN_SHIFT);
162     putreg32(regval, reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
163 
164     mode = (regval & SEC_ENG_SE_AES_0_BLOCK_MODE_MASK) >> SEC_ENG_SE_AES_0_BLOCK_MODE_SHIFT;
165 
166     if (temp_iv) {
167         if (mode == AES_MODE_XTS) {
168             putreg32(BFLB_PUT_BE32(temp_iv), reg_base + SEC_ENG_SE_AES_0_IV_3_OFFSET);
169             temp_iv += 4;
170             putreg32(BFLB_PUT_BE32(temp_iv), reg_base + SEC_ENG_SE_AES_0_IV_2_OFFSET);
171             temp_iv += 4;
172             putreg32(BFLB_PUT_BE32(temp_iv), reg_base + SEC_ENG_SE_AES_0_IV_1_OFFSET);
173             temp_iv += 4;
174             putreg32(BFLB_PUT_BE32(temp_iv), reg_base + SEC_ENG_SE_AES_0_IV_0_OFFSET);
175             temp_iv += 4;
176         } else {
177             putreg32(BFLB_PUT_LE32(temp_iv), reg_base + SEC_ENG_SE_AES_0_IV_0_OFFSET);
178             temp_iv += 4;
179             putreg32(BFLB_PUT_LE32(temp_iv), reg_base + SEC_ENG_SE_AES_0_IV_1_OFFSET);
180             temp_iv += 4;
181             putreg32(BFLB_PUT_LE32(temp_iv), reg_base + SEC_ENG_SE_AES_0_IV_2_OFFSET);
182             temp_iv += 4;
183             putreg32(BFLB_PUT_LE32(temp_iv), reg_base + SEC_ENG_SE_AES_0_IV_3_OFFSET);
184             temp_iv += 4;
185         }
186     }
187 
188     /* Set input and output address */
189     putreg32((uint32_t)input, reg_base + SEC_ENG_SE_AES_0_MSA_OFFSET);
190     putreg32((uint32_t)output, reg_base + SEC_ENG_SE_AES_0_MDA_OFFSET);
191 
192     regval = getreg32(reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
193     regval |= SEC_ENG_SE_AES_0_TRIG_1T;
194     putreg32(regval, reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
195 
196     start_time = bflb_mtimer_get_time_ms();
197     while (getreg32(reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET) & SEC_ENG_SE_AES_0_BUSY) {
198         if ((bflb_mtimer_get_time_ms() - start_time) > 100) {
199             return -ETIMEDOUT;
200         }
201     }
202     return 0;
203 }
204 
bflb_aes_decrypt(struct bflb_device_s * dev,const uint8_t * input,const uint8_t * iv,uint8_t * output,uint32_t len)205 int bflb_aes_decrypt(struct bflb_device_s *dev,
206                      const uint8_t *input,
207                      const uint8_t *iv,
208                      uint8_t *output,
209                      uint32_t len)
210 {
211     uint32_t regval;
212     uint32_t reg_base;
213     uint64_t start_time;
214     uint8_t mode;
215     uint8_t *temp_iv = (uint8_t *)iv;
216 
217     reg_base = dev->reg_base;
218 
219     if (len % 16) {
220         return -EINVAL;
221     }
222 
223     regval = getreg32(reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
224     regval &= ~SEC_ENG_SE_AES_0_TRIG_1T;
225     if (temp_iv) {
226         regval &= ~SEC_ENG_SE_AES_0_IV_SEL; /* Clear aes iv sel to select new iv */
227     } else {
228         regval |= SEC_ENG_SE_AES_0_IV_SEL; /* Clear aes iv sel to select last iv */
229     }
230     regval |= SEC_ENG_SE_AES_0_DEC_EN; /* Set AES decryption */
231     regval |= SEC_ENG_SE_AES_0_INT_CLR_1T;
232     regval &= ~SEC_ENG_SE_AES_0_MSG_LEN_MASK;
233     regval |= ((len / 16) << SEC_ENG_SE_AES_0_MSG_LEN_SHIFT);
234     putreg32(regval, reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
235 
236     mode = (regval & SEC_ENG_SE_AES_0_BLOCK_MODE_MASK) >> SEC_ENG_SE_AES_0_BLOCK_MODE_SHIFT;
237 
238     if (temp_iv) {
239         if (mode == AES_MODE_XTS) {
240             putreg32(BFLB_PUT_BE32(temp_iv), reg_base + SEC_ENG_SE_AES_0_IV_3_OFFSET);
241             temp_iv += 4;
242             putreg32(BFLB_PUT_BE32(temp_iv), reg_base + SEC_ENG_SE_AES_0_IV_2_OFFSET);
243             temp_iv += 4;
244             putreg32(BFLB_PUT_BE32(temp_iv), reg_base + SEC_ENG_SE_AES_0_IV_1_OFFSET);
245             temp_iv += 4;
246             putreg32(BFLB_PUT_BE32(temp_iv), reg_base + SEC_ENG_SE_AES_0_IV_0_OFFSET);
247             temp_iv += 4;
248         } else {
249             putreg32(BFLB_PUT_LE32(temp_iv), reg_base + SEC_ENG_SE_AES_0_IV_0_OFFSET);
250             temp_iv += 4;
251             putreg32(BFLB_PUT_LE32(temp_iv), reg_base + SEC_ENG_SE_AES_0_IV_1_OFFSET);
252             temp_iv += 4;
253             putreg32(BFLB_PUT_LE32(temp_iv), reg_base + SEC_ENG_SE_AES_0_IV_2_OFFSET);
254             temp_iv += 4;
255             putreg32(BFLB_PUT_LE32(temp_iv), reg_base + SEC_ENG_SE_AES_0_IV_3_OFFSET);
256             temp_iv += 4;
257         }
258     }
259 
260     /* Set input and output address */
261     putreg32((uint32_t)input, reg_base + SEC_ENG_SE_AES_0_MSA_OFFSET);
262     putreg32((uint32_t)output, reg_base + SEC_ENG_SE_AES_0_MDA_OFFSET);
263 
264     regval = getreg32(reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
265     regval |= SEC_ENG_SE_AES_0_TRIG_1T;
266     putreg32(regval, reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
267 
268     start_time = bflb_mtimer_get_time_ms();
269     while (getreg32(reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET) & SEC_ENG_SE_AES_0_BUSY) {
270         if ((bflb_mtimer_get_time_ms() - start_time) > 100) {
271             return -ETIMEDOUT;
272         }
273     }
274     return 0;
275 }
276 
bflb_aes_link_init(struct bflb_device_s * dev)277 void bflb_aes_link_init(struct bflb_device_s *dev)
278 {
279     uint32_t regval;
280     uint32_t reg_base;
281 
282     reg_base = dev->reg_base;
283 
284 #ifdef CONFIG_BFLB_AES_USE_BE
285     putreg32(0x1f, reg_base + SEC_ENG_SE_AES_0_ENDIAN_OFFSET);
286 #else
287     putreg32(0x10, reg_base + SEC_ENG_SE_AES_0_ENDIAN_OFFSET);
288 #endif
289 
290     regval = getreg32(reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
291     regval |= SEC_ENG_SE_AES_0_LINK_MODE;
292     regval |= SEC_ENG_SE_AES_0_EN;
293     putreg32(regval, reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
294 }
295 
bflb_aes_link_deinit(struct bflb_device_s * dev)296 void bflb_aes_link_deinit(struct bflb_device_s *dev)
297 {
298     uint32_t regval;
299     uint32_t reg_base;
300 
301     reg_base = dev->reg_base;
302 
303     regval = getreg32(reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
304     regval &= ~SEC_ENG_SE_AES_0_LINK_MODE;
305     regval &= ~SEC_ENG_SE_AES_0_EN;
306     putreg32(regval, reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
307 }
308 
bflb_aes_link_update(struct bflb_device_s * dev,uint32_t link_addr,const uint8_t * input,uint8_t * output,uint32_t len)309 int bflb_aes_link_update(struct bflb_device_s *dev,
310                          uint32_t link_addr,
311                          const uint8_t *input,
312                          uint8_t *output,
313                          uint32_t len)
314 {
315     uint32_t regval;
316     uint32_t reg_base;
317     uint64_t start_time;
318 
319     reg_base = dev->reg_base;
320 
321     if ((len % 16) || ((link_addr & 0x03))) {
322         return -EINVAL;
323     }
324 
325     regval = getreg32(reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
326     regval &= ~SEC_ENG_SE_AES_0_TRIG_1T;
327     putreg32(regval, reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
328 
329     /* Set link address */
330     putreg32(link_addr, reg_base + SEC_ENG_SE_AES_0_LINK_OFFSET);
331 
332     /* Change source buffer address and destination buffer address */
333     *(uint32_t *)(uintptr_t)(link_addr + 4) = (uint32_t)(uintptr_t)input;
334     *(uint32_t *)(uintptr_t)(link_addr + 8) = (uint32_t)(uintptr_t)output;
335 
336     /* Set data length */
337     *((uint16_t *)(uintptr_t)link_addr + 1) = len / 16;
338 
339     regval = getreg32(reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
340     regval |= SEC_ENG_SE_AES_0_TRIG_1T;
341     putreg32(regval, reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET);
342 
343     __asm volatile("nop");
344     __asm volatile("nop");
345 
346     start_time = bflb_mtimer_get_time_ms();
347     while (getreg32(reg_base + SEC_ENG_SE_AES_0_CTRL_OFFSET) & SEC_ENG_SE_AES_0_BUSY) {
348         if ((bflb_mtimer_get_time_ms() - start_time) > 100) {
349             return -ETIMEDOUT;
350         }
351     }
352 
353     return 0;
354 }
355 
bflb_group0_request_aes_access(struct bflb_device_s * dev)356 void bflb_group0_request_aes_access(struct bflb_device_s *dev)
357 {
358     uint32_t regval;
359     uint32_t reg_base;
360 
361     reg_base = dev->reg_base;
362 
363     regval = getreg32(reg_base + SEC_ENG_SE_CTRL_PROT_RD_OFFSET);
364     if (((regval >> 2) & 0x03) == 0x03) {
365         putreg32(0x02, reg_base + SEC_ENG_SE_AES_0_CTRL_PROT_OFFSET);
366 
367         regval = getreg32(reg_base + SEC_ENG_SE_CTRL_PROT_RD_OFFSET);
368         if (((regval >> 2) & 0x03) == 0x01) {
369         }
370     }
371 }
372 
bflb_group0_release_aes_access(struct bflb_device_s * dev)373 void bflb_group0_release_aes_access(struct bflb_device_s *dev)
374 {
375     uint32_t reg_base;
376 
377     reg_base = dev->reg_base;
378 
379     putreg32(0x06, reg_base + SEC_ENG_SE_AES_0_CTRL_PROT_OFFSET);
380 }
381 
bflb_aes_set_hwkey_source(struct bflb_device_s * dev,uint8_t source)382 void bflb_aes_set_hwkey_source(struct bflb_device_s *dev, uint8_t source)
383 {
384     uint32_t regval;
385     uint32_t reg_base;
386 
387     reg_base = dev->reg_base;
388 
389     regval = getreg32(reg_base + SEC_ENG_SE_AES_0_SBOOT_OFFSET);
390     regval |= (source << 0);
391     putreg32(0x02, reg_base + SEC_ENG_SE_AES_0_SBOOT_OFFSET);
392 }
393