treewide: Drop bootm_headers_t typedef
[platform/kernel/u-boot.git] / boot / image-cipher.c
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>
13 DECLARE_GLOBAL_DATA_PTR;
14 #endif /* !USE_HOSdTCC*/
15 #include <image.h>
16 #include <uboot_aes.h>
17 #include <u-boot/aes.h>
18
19 struct 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
55 struct 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
69 static 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
158 int 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 }