Prepare v2024.10
[platform/kernel/u-boot.git] / lib / aes / aes-encrypt.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2019,Softathome
4  */
5
6 #define OPENSSL_API_COMPAT 0x10101000L
7
8 #include "mkimage.h"
9 #include <stdio.h>
10 #include <string.h>
11 #include <image.h>
12 #include <time.h>
13 #include <openssl/bn.h>
14 #include <openssl/rsa.h>
15 #include <openssl/pem.h>
16 #include <openssl/err.h>
17 #include <openssl/ssl.h>
18 #include <openssl/evp.h>
19 #include <openssl/engine.h>
20 #include <uboot_aes.h>
21
22 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
23 #define HAVE_ERR_REMOVE_THREAD_STATE
24 #endif
25
26 int image_aes_encrypt(struct image_cipher_info *info,
27                       unsigned char *data, int size,
28                       unsigned char **cipher, int *cipher_len)
29 {
30         EVP_CIPHER_CTX *ctx;
31         unsigned char *buf = NULL;
32         int buf_len, len, ret = 0;
33
34         /* create and initialise the context */
35         ctx = EVP_CIPHER_CTX_new();
36         if (!ctx) {
37                 printf("Can't create context\n");
38                 return -1;
39         }
40
41         /* allocate a buffer for the result */
42         buf = malloc(size + AES_BLOCK_LENGTH);
43         if (!buf) {
44                 printf("Can't allocate memory to encrypt\n");
45                 ret = -1;
46                 goto out;
47         }
48
49         if (EVP_EncryptInit_ex(ctx, info->cipher->calculate_type(),
50                                NULL, info->key, info->iv) != 1) {
51                 printf("Can't init encryption\n");
52                 ret = -1;
53                 goto out;
54         }
55
56         if (EVP_EncryptUpdate(ctx, buf, &len, data, size) != 1) {
57                 printf("Can't encrypt data\n");
58                 ret = -1;
59                 goto out;
60         }
61
62         buf_len = len;
63
64         if (EVP_EncryptFinal_ex(ctx, buf + len, &len) != 1) {
65                 printf("Can't finalise the encryption\n");
66                 ret = -1;
67                 goto out;
68         }
69
70         buf_len += len;
71
72         *cipher = buf;
73         *cipher_len = buf_len;
74
75  out:
76         EVP_CIPHER_CTX_free(ctx);
77         return ret;
78 }
79
80 int image_aes_add_cipher_data(struct image_cipher_info *info, void *keydest,
81                               void *fit, int node_noffset)
82 {
83         int parent, node;
84         char name[128];
85         int ret = 0;
86
87         /* Either create or overwrite the named cipher node */
88         parent = fdt_subnode_offset(keydest, 0, FIT_CIPHER_NODENAME);
89         if (parent == -FDT_ERR_NOTFOUND) {
90                 parent = fdt_add_subnode(keydest, 0, FIT_CIPHER_NODENAME);
91                 if (parent < 0) {
92                         ret = parent;
93                         if (ret != -FDT_ERR_NOSPACE) {
94                                 fprintf(stderr,
95                                         "Couldn't create cipher node: %s\n",
96                                         fdt_strerror(parent));
97                         }
98                 }
99         }
100         if (ret)
101                 goto done;
102
103         /* Either create or overwrite the named key node */
104         if (info->ivname)
105                 snprintf(name, sizeof(name), "key-%s-%s-%s",
106                          info->name, info->keyname, info->ivname);
107         else
108                 snprintf(name, sizeof(name), "key-%s-%s",
109                          info->name, info->keyname);
110
111         node = fdt_subnode_offset(keydest, parent, name);
112         if (node == -FDT_ERR_NOTFOUND) {
113                 node = fdt_add_subnode(keydest, parent, name);
114                 if (node < 0) {
115                         ret = node;
116                         if (ret != -FDT_ERR_NOSPACE) {
117                                 fprintf(stderr,
118                                         "Could not create key subnode: %s\n",
119                                         fdt_strerror(node));
120                         }
121                 }
122         } else if (node < 0) {
123                 fprintf(stderr, "Cannot select keys parent: %s\n",
124                         fdt_strerror(node));
125                 ret = node;
126         }
127
128         if (ret)
129                 goto done;
130
131         if (info->ivname)
132                 /* Store the IV in the u-boot device tree */
133                 ret = fdt_setprop(keydest, node, "iv",
134                                   info->iv, info->cipher->iv_len);
135         else
136                 /* Store the IV in the FIT image */
137                 ret = fdt_setprop(fit, node_noffset, "iv",
138                                   info->iv, info->cipher->iv_len);
139
140         if (!ret)
141                 ret = fdt_setprop(keydest, node, "key",
142                                   info->key, info->cipher->key_len);
143
144         if (!ret)
145                 ret = fdt_setprop_u32(keydest, node, "key-len",
146                                       info->cipher->key_len);
147
148 done:
149         if (ret)
150                 ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
151
152         return ret;
153 }