1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2019, Softathome
4 */
5
6#ifdef USE_HOSTCC
7#include "mkimage.h"
8#include <time.h>
9#else
10#include <common.h>
11#include <malloc.h>
12#include <asm/global_data.h>
13DECLARE_GLOBAL_DATA_PTR;
14#endif /* !USE_HOSdTCC*/
15#include <image.h>
16#include <uboot_aes.h>
17#include <u-boot/aes.h>
18
19struct cipher_algo cipher_algos[] = {
20	{
21		.name = "aes128",
22		.key_len = AES128_KEY_LENGTH,
23		.iv_len  = AES_BLOCK_LENGTH,
24#if IMAGE_ENABLE_ENCRYPT
25		.calculate_type = EVP_aes_128_cbc,
26#endif
27		.encrypt = image_aes_encrypt,
28		.decrypt = image_aes_decrypt,
29		.add_cipher_data = image_aes_add_cipher_data
30	},
31	{
32		.name = "aes192",
33		.key_len = AES192_KEY_LENGTH,
34		.iv_len  = AES_BLOCK_LENGTH,
35#if IMAGE_ENABLE_ENCRYPT
36		.calculate_type = EVP_aes_192_cbc,
37#endif
38		.encrypt = image_aes_encrypt,
39		.decrypt = image_aes_decrypt,
40		.add_cipher_data = image_aes_add_cipher_data
41	},
42	{
43		.name = "aes256",
44		.key_len = AES256_KEY_LENGTH,
45		.iv_len  = AES_BLOCK_LENGTH,
46#if IMAGE_ENABLE_ENCRYPT
47		.calculate_type = EVP_aes_256_cbc,
48#endif
49		.encrypt = image_aes_encrypt,
50		.decrypt = image_aes_decrypt,
51		.add_cipher_data = image_aes_add_cipher_data
52	}
53};
54
55struct cipher_algo *image_get_cipher_algo(const char *full_name)
56{
57	int i;
58	const char *name;
59
60	for (i = 0; i < ARRAY_SIZE(cipher_algos); i++) {
61		name = cipher_algos[i].name;
62		if (!strncmp(name, full_name, strlen(name)))
63			return &cipher_algos[i];
64	}
65
66	return NULL;
67}
68
69static int fit_image_setup_decrypt(struct image_cipher_info *info,
70				   const void *fit, int image_noffset,
71				   int cipher_noffset)
72{
73	const void *fdt = gd_fdt_blob();
74	const char *node_name;
75	char node_path[128];
76	int noffset;
77	char *algo_name;
78	int ret;
79
80	node_name = fit_get_name(fit, image_noffset, NULL);
81	if (!node_name) {
82		printf("Can't get node name\n");
83		return -1;
84	}
85
86	if (fit_image_cipher_get_algo(fit, cipher_noffset, &algo_name)) {
87		printf("Can't get algo name for cipher '%s' in image '%s'\n",
88		       node_name, node_name);
89		return -1;
90	}
91
92	info->keyname = fdt_getprop(fit, cipher_noffset, FIT_KEY_HINT, NULL);
93	if (!info->keyname) {
94		printf("Can't get key name\n");
95		return -1;
96	}
97
98	info->iv = fdt_getprop(fit, cipher_noffset, "iv", NULL);
99	info->ivname = fdt_getprop(fit, cipher_noffset, "iv-name-hint", NULL);
100
101	if (!info->iv && !info->ivname) {
102		printf("Can't get IV or IV name\n");
103		return -1;
104	}
105
106	info->fit = fit;
107	info->node_noffset = image_noffset;
108	info->name = algo_name;
109	info->cipher = image_get_cipher_algo(algo_name);
110	if (!info->cipher) {
111		printf("Can't get cipher\n");
112		return -1;
113	}
114
115	ret = fit_image_get_data_size_unciphered(fit, image_noffset,
116						 &info->size_unciphered);
117	if (ret) {
118		printf("Can't get size of unciphered data\n");
119		return -1;
120	}
121
122	/*
123	 * Search the cipher node in the u-boot fdt
124	 * the path should be: /cipher/key-<algo>-<key>-<iv>
125	 */
126	if (info->ivname)
127		snprintf(node_path, sizeof(node_path), "/%s/key-%s-%s-%s",
128			 FIT_CIPHER_NODENAME, algo_name, info->keyname, info->ivname);
129	else
130		snprintf(node_path, sizeof(node_path), "/%s/key-%s-%s",
131			 FIT_CIPHER_NODENAME, algo_name, info->keyname);
132
133	noffset = fdt_path_offset(fdt, node_path);
134	if (noffset < 0) {
135		printf("Can't found cipher node offset\n");
136		return -1;
137	}
138
139	/* read key */
140	info->key = fdt_getprop(fdt, noffset, "key", NULL);
141	if (!info->key) {
142		printf("Can't get key in cipher node '%s'\n", node_path);
143		return -1;
144	}
145
146	/* read iv */
147	if (!info->iv) {
148		info->iv = fdt_getprop(fdt, noffset, "iv", NULL);
149		if (!info->iv) {
150			printf("Can't get IV in cipher node '%s'\n", node_path);
151			return -1;
152		}
153	}
154
155	return 0;
156}
157
158int fit_image_decrypt_data(const void *fit,
159			   int image_noffset, int cipher_noffset,
160			   const void *data_ciphered, size_t size_ciphered,
161			   void **data_unciphered, size_t *size_unciphered)
162{
163	struct image_cipher_info info;
164	int ret;
165
166	ret = fit_image_setup_decrypt(&info, fit, image_noffset,
167				      cipher_noffset);
168	if (ret < 0)
169		goto out;
170
171	ret = info.cipher->decrypt(&info, data_ciphered, size_ciphered,
172				   data_unciphered, size_unciphered);
173
174 out:
175	return ret;
176}
177