1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2014 Marek Vasut <marex@denx.de>
4 * Copyright (C) 2025 Ion Agorria <ion@agorria.com>
5 *
6 * Command for AES-[128/192/256] operations.
7 */
8
9 #include <command.h>
10 #include <uboot_aes.h>
11 #include <malloc.h>
12 #include <asm/byteorder.h>
13 #include <linux/compiler.h>
14 #include <mapmem.h>
15 #include <vsprintf.h>
16 #include <dm/uclass.h>
17 #include <dm/device.h>
18
aes_get_key_len(char * command)19 u32 aes_get_key_len(char *command)
20 {
21 u32 key_len = AES128_KEY_LENGTH;
22
23 if (!strcmp(command, "aes.192"))
24 key_len = AES192_KEY_LENGTH;
25 else if (!strcmp(command, "aes.256"))
26 key_len = AES256_KEY_LENGTH;
27
28 return key_len;
29 }
30
aes_get_driver(struct udevice ** dev)31 int aes_get_driver(struct udevice **dev)
32 {
33 int ret;
34
35 ret = uclass_get_device(UCLASS_AES, 0, dev);
36 if (ret) {
37 printf("Failed to get AES driver: %d\n", ret);
38 return ret;
39 }
40
41 return 0;
42 }
43
cmd_aes_cbc_simple(int argc,char * const argv[],u32 key_len)44 int cmd_aes_cbc_simple(int argc, char *const argv[], u32 key_len)
45 {
46 uint32_t key_addr, iv_addr, src_addr, dst_addr, len;
47 uint8_t *key_ptr, *iv_ptr, *src_ptr, *dst_ptr;
48 u8 key_exp[AES256_EXPAND_KEY_LENGTH];
49 u32 aes_blocks;
50 int enc;
51
52 if (argc != 7)
53 return CMD_RET_USAGE;
54
55 if (!strncmp(argv[1], "enc", 3))
56 enc = 1;
57 else if (!strncmp(argv[1], "dec", 3))
58 enc = 0;
59 else
60 return CMD_RET_USAGE;
61
62 key_addr = hextoul(argv[2], NULL);
63 iv_addr = hextoul(argv[3], NULL);
64 src_addr = hextoul(argv[4], NULL);
65 dst_addr = hextoul(argv[5], NULL);
66 len = hextoul(argv[6], NULL);
67
68 key_ptr = (uint8_t *)map_sysmem(key_addr, key_len);
69 iv_ptr = (uint8_t *)map_sysmem(iv_addr, 128 / 8);
70 src_ptr = (uint8_t *)map_sysmem(src_addr, len);
71 dst_ptr = (uint8_t *)map_sysmem(dst_addr, len);
72
73 /* First we expand the key. */
74 aes_expand_key(key_ptr, key_len, key_exp);
75
76 /* Calculate the number of AES blocks to encrypt. */
77 aes_blocks = DIV_ROUND_UP(len, AES_BLOCK_LENGTH);
78
79 if (enc)
80 aes_cbc_encrypt_blocks(key_len, key_exp, iv_ptr, src_ptr,
81 dst_ptr, aes_blocks);
82 else
83 aes_cbc_decrypt_blocks(key_len, key_exp, iv_ptr, src_ptr,
84 dst_ptr, aes_blocks);
85
86 unmap_sysmem(key_ptr);
87 unmap_sysmem(iv_ptr);
88 unmap_sysmem(src_ptr);
89 unmap_sysmem(dst_ptr);
90
91 return CMD_RET_SUCCESS;
92 }
93
cmd_aes_get_slots(void)94 int cmd_aes_get_slots(void)
95 {
96 struct udevice *dev;
97 u8 slots;
98 int ret;
99
100 ret = aes_get_driver(&dev);
101 if (ret)
102 return ret;
103
104 slots = dm_aes_get_available_key_slots(dev);
105 printf("Available slots: %d\n", slots);
106
107 return CMD_RET_SUCCESS;
108 }
109
cmd_aes_set_key(int argc,char * const argv[],u32 key_len)110 int cmd_aes_set_key(int argc, char *const argv[], u32 key_len)
111 {
112 struct udevice *dev;
113 u32 key_addr, slot;
114 u8 *key_ptr;
115 int ret;
116
117 if (argc != 4)
118 return CMD_RET_USAGE;
119
120 ret = aes_get_driver(&dev);
121 if (ret)
122 return ret;
123
124 key_addr = hextoul(argv[2], NULL);
125 slot = hextoul(argv[3], NULL);
126
127 key_ptr = (uint8_t *)map_sysmem(key_addr, key_len);
128
129 ret = dm_aes_set_key_for_key_slot(dev, key_len * 8, key_ptr, slot);
130 unmap_sysmem(key_ptr);
131 if (ret) {
132 printf("Unable to set key at slot: %d\n", ret);
133 return CMD_RET_FAILURE;
134 }
135
136 return CMD_RET_SUCCESS;
137 }
138
cmd_aes_select_slot(int argc,char * const argv[],u32 key_len)139 int cmd_aes_select_slot(int argc, char *const argv[], u32 key_len)
140 {
141 struct udevice *dev;
142 u32 slot;
143 int ret;
144
145 if (argc != 3)
146 return CMD_RET_USAGE;
147
148 ret = aes_get_driver(&dev);
149 if (ret)
150 return ret;
151
152 slot = hextoul(argv[2], NULL);
153
154 ret = dm_aes_select_key_slot(dev, key_len * 8, slot);
155 if (ret) {
156 printf("Unable to select key slot: %d\n", ret);
157 return CMD_RET_FAILURE;
158 }
159
160 return CMD_RET_SUCCESS;
161 }
162
cmd_aes_ecb(int argc,char * const argv[],u32 key_len)163 int cmd_aes_ecb(int argc, char *const argv[], u32 key_len)
164 {
165 struct udevice *dev;
166 u32 src_addr, dst_addr, len;
167 u8 *src_ptr, *dst_ptr;
168 u32 aes_blocks;
169 int enc, ret;
170
171 if (argc != 6)
172 return CMD_RET_USAGE;
173
174 ret = aes_get_driver(&dev);
175 if (ret)
176 return ret;
177
178 if (!strncmp(argv[1], "enc", 3))
179 enc = 1;
180 else if (!strncmp(argv[1], "dec", 3))
181 enc = 0;
182 else
183 return CMD_RET_USAGE;
184
185 src_addr = hextoul(argv[3], NULL);
186 dst_addr = hextoul(argv[4], NULL);
187 len = hextoul(argv[5], NULL);
188
189 src_ptr = (uint8_t *)map_sysmem(src_addr, len);
190 dst_ptr = (uint8_t *)map_sysmem(dst_addr, len);
191
192 /* Calculate the number of AES blocks to encrypt. */
193 aes_blocks = DIV_ROUND_UP(len, AES_BLOCK_LENGTH);
194
195 if (enc)
196 ret = dm_aes_ecb_encrypt(dev, src_ptr, dst_ptr, aes_blocks);
197 else
198 ret = dm_aes_ecb_decrypt(dev, src_ptr, dst_ptr, aes_blocks);
199
200 unmap_sysmem(src_ptr);
201 unmap_sysmem(dst_ptr);
202
203 if (ret) {
204 printf("Unable to do ecb operation: %d\n", ret);
205 return CMD_RET_FAILURE;
206 }
207
208 return CMD_RET_SUCCESS;
209 }
210
cmd_aes_cbc(int argc,char * const argv[],u32 key_len)211 int cmd_aes_cbc(int argc, char *const argv[], u32 key_len)
212 {
213 struct udevice *dev;
214 u32 iv_addr, src_addr, dst_addr, len;
215 u8 *iv_ptr, *src_ptr, *dst_ptr;
216 u32 aes_blocks;
217 int enc, ret;
218
219 if (argc != 7)
220 return CMD_RET_USAGE;
221
222 ret = aes_get_driver(&dev);
223 if (ret)
224 return ret;
225
226 if (!strncmp(argv[1], "enc", 3))
227 enc = 1;
228 else if (!strncmp(argv[1], "dec", 3))
229 enc = 0;
230 else
231 return CMD_RET_USAGE;
232
233 iv_addr = hextoul(argv[3], NULL);
234 src_addr = hextoul(argv[4], NULL);
235 dst_addr = hextoul(argv[5], NULL);
236 len = hextoul(argv[6], NULL);
237
238 iv_ptr = (uint8_t *)map_sysmem(iv_addr, AES_BLOCK_LENGTH);
239 src_ptr = (uint8_t *)map_sysmem(src_addr, len);
240 dst_ptr = (uint8_t *)map_sysmem(dst_addr, len);
241
242 /* Calculate the number of AES blocks to encrypt. */
243 aes_blocks = DIV_ROUND_UP(len, AES_BLOCK_LENGTH);
244
245 if (enc)
246 ret = dm_aes_cbc_encrypt(dev, iv_ptr, src_ptr, dst_ptr, aes_blocks);
247 else
248 ret = dm_aes_cbc_decrypt(dev, iv_ptr, src_ptr, dst_ptr, aes_blocks);
249
250 unmap_sysmem(iv_ptr);
251 unmap_sysmem(src_ptr);
252 unmap_sysmem(dst_ptr);
253
254 if (ret) {
255 printf("Unable to do cbc operation: %d\n", ret);
256 return CMD_RET_FAILURE;
257 }
258
259 return CMD_RET_SUCCESS;
260 }
261
262 /**
263 * do_aes() - Handle the "aes" command-line command
264 * @cmdtp: Command data struct pointer
265 * @flag: Command flag
266 * @argc: Command-line argument count
267 * @argv: Array of command-line arguments
268 *
269 * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
270 * on error.
271 */
do_aes(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])272 static int do_aes(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
273 {
274 u32 key_len;
275
276 if (argc < 2)
277 return CMD_RET_USAGE;
278
279 key_len = aes_get_key_len(argv[0]);
280
281 if (!strncmp(argv[1], "enc", 3) || !strncmp(argv[1], "dec", 3))
282 return cmd_aes_cbc_simple(argc, argv, key_len);
283 else if (CONFIG_IS_ENABLED(DM_AES) && !strncmp(argv[1], "get_slots", 9))
284 return cmd_aes_get_slots();
285 else if (CONFIG_IS_ENABLED(DM_AES) && !strncmp(argv[1], "set_key", 7))
286 return cmd_aes_set_key(argc, argv, key_len);
287 else if (CONFIG_IS_ENABLED(DM_AES) && !strncmp(argv[1], "select_slot", 11))
288 return cmd_aes_select_slot(argc, argv, key_len);
289 else if (CONFIG_IS_ENABLED(DM_AES) && !strncmp(argv[1], "ecb", 3))
290 return cmd_aes_ecb(argc, argv, key_len);
291 else if (CONFIG_IS_ENABLED(DM_AES) && !strncmp(argv[1], "cbc", 3))
292 return cmd_aes_cbc(argc, argv, key_len);
293 else
294 return CMD_RET_USAGE;
295 }
296
297 /***************************************************/
298 U_BOOT_LONGHELP(aes,
299 "[.128,.192,.256] enc key iv src dst len - CBC encrypt block of data $len bytes long\n"
300 " at address $src using a key at address\n"
301 " $key with initialization vector at address\n"
302 " $iv. Store the result at address $dst.\n"
303 " The $len size must be multiple of 16 bytes.\n"
304 " The $key and $iv must be 16 bytes long.\n"
305 "aes [.128,.192,.256] dec key iv src dst len - CBC decrypt block of data $len bytes long\n"
306 " at address $src using a key at address\n"
307 " $key with initialization vector at address\n"
308 " $iv. Store the result at address $dst.\n"
309 " The $len size must be multiple of 16 bytes.\n"
310 " The $key and $iv must be 16 bytes long."
311
312 #if CONFIG_IS_ENABLED(DM_AES)
313 "\n"
314 "aes get_slots - Gives number of available key slots\n"
315 "aes [.128,.192,.256] set_key key slot - Load key at address $key into the slot $slot\n"
316 "aes [.128,.192,.256] select_slot slot - Select current active key slot\n"
317 "aes [.128,.192,.256] ecb enc src dst len - ECB encrypt block of data $len bytes long\n"
318 " at address $src using a key at current\n"
319 " slot. Store the result at address $dst.\n"
320 " The $len size must be multiple of 16 bytes.\n"
321 "aes [.128,.192,.256] ecb dec src dst len - ECB decrypt block of data $len bytes long\n"
322 " at address $src using a key at current\n"
323 " slot. Store the result at address $dst.\n"
324 " The $len size must be multiple of 16 bytes.\n"
325 "aes [.128,.192,.256] cbc enc iv src dst len - CBC encrypt block of data $len bytes long\n"
326 " at address $src using a key at current\n"
327 " slot with initialization vector at address\n"
328 " $iv. Store the result at address $dst.\n"
329 " The $len size must be multiple of 16 bytes.\n"
330 " The $iv must be 16 bytes long.\n"
331 "aes [.128,.192,.256] cbc dec iv src dst len - CBC decrypt block of data $len bytes long\n"
332 " at address $src using a key at current\n"
333 " slot with initialization vector at address\n"
334 " $iv. Store the result at address $dst.\n"
335 " The $len size must be multiple of 16 bytes.\n"
336 " The $iv must be 16 bytes long."
337 #endif
338 );
339
340 U_BOOT_CMD(
341 aes, 7, 1, do_aes,
342 "AES 128/192/256 operations",
343 aes_help_text
344 );
345