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