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 
image_aes_encrypt(struct image_cipher_info * info,unsigned char * data,int size,unsigned char ** cipher,int * cipher_len)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 
image_aes_add_cipher_data(struct image_cipher_info * info,void * keydest,void * fit,int node_noffset)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 }
151