u-boot/lib/aes/aes-encrypt.c
Paul HENRYS 79d7b11102 aes: Allow to store randomly generated IV in the FIT
When the initialisation vector is randomly generated, its value shall be
stored in the FIT together with the encrypted data. The changes allow to
store the IV in the FIT also in the case where the key is not stored in
the DTB but retrieved somewhere else at runtime.

Signed-off-by: Paul HENRYS <paul.henrys_ext@softathome.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
2024-12-19 09:10:34 -06:00

161 lines
3.5 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2019,Softathome
*/
#define OPENSSL_API_COMPAT 0x10101000L
#include "mkimage.h"
#include <stdio.h>
#include <string.h>
#include <image.h>
#include <time.h>
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/evp.h>
#include <openssl/engine.h>
#include <uboot_aes.h>
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
#define HAVE_ERR_REMOVE_THREAD_STATE
#endif
int image_aes_encrypt(struct image_cipher_info *info,
unsigned char *data, int size,
unsigned char **cipher, int *cipher_len)
{
EVP_CIPHER_CTX *ctx;
unsigned char *buf = NULL;
int buf_len, len, ret = 0;
/* create and initialise the context */
ctx = EVP_CIPHER_CTX_new();
if (!ctx) {
printf("Can't create context\n");
return -1;
}
/* allocate a buffer for the result */
buf = malloc(size + AES_BLOCK_LENGTH);
if (!buf) {
printf("Can't allocate memory to encrypt\n");
ret = -1;
goto out;
}
if (EVP_EncryptInit_ex(ctx, info->cipher->calculate_type(),
NULL, info->key, info->iv) != 1) {
printf("Can't init encryption\n");
ret = -1;
goto out;
}
if (EVP_EncryptUpdate(ctx, buf, &len, data, size) != 1) {
printf("Can't encrypt data\n");
ret = -1;
goto out;
}
buf_len = len;
if (EVP_EncryptFinal_ex(ctx, buf + len, &len) != 1) {
printf("Can't finalise the encryption\n");
ret = -1;
goto out;
}
buf_len += len;
*cipher = buf;
*cipher_len = buf_len;
out:
EVP_CIPHER_CTX_free(ctx);
return ret;
}
int image_aes_add_cipher_data(struct image_cipher_info *info, void *keydest,
void *fit, int node_noffset)
{
int parent, node;
char name[128];
int ret = 0;
if (!keydest && !info->ivname) {
/* At least, store the IV in the FIT image */
ret = fdt_setprop(fit, node_noffset, "iv",
info->iv, info->cipher->iv_len);
goto done;
}
/* Either create or overwrite the named cipher node */
parent = fdt_subnode_offset(keydest, 0, FIT_CIPHER_NODENAME);
if (parent == -FDT_ERR_NOTFOUND) {
parent = fdt_add_subnode(keydest, 0, FIT_CIPHER_NODENAME);
if (parent < 0) {
ret = parent;
if (ret != -FDT_ERR_NOSPACE) {
fprintf(stderr,
"Couldn't create cipher node: %s\n",
fdt_strerror(parent));
}
}
}
if (ret)
goto done;
/* Either create or overwrite the named key node */
if (info->ivname)
snprintf(name, sizeof(name), "key-%s-%s-%s",
info->name, info->keyname, info->ivname);
else
snprintf(name, sizeof(name), "key-%s-%s",
info->name, info->keyname);
node = fdt_subnode_offset(keydest, parent, name);
if (node == -FDT_ERR_NOTFOUND) {
node = fdt_add_subnode(keydest, parent, name);
if (node < 0) {
ret = node;
if (ret != -FDT_ERR_NOSPACE) {
fprintf(stderr,
"Could not create key subnode: %s\n",
fdt_strerror(node));
}
}
} else if (node < 0) {
fprintf(stderr, "Cannot select keys parent: %s\n",
fdt_strerror(node));
ret = node;
}
if (ret)
goto done;
if (info->ivname)
/* Store the IV in the u-boot device tree */
ret = fdt_setprop(keydest, node, "iv",
info->iv, info->cipher->iv_len);
else
/* Store the IV in the FIT image */
ret = fdt_setprop(fit, node_noffset, "iv",
info->iv, info->cipher->iv_len);
if (!ret)
ret = fdt_setprop(keydest, node, "key",
info->key, info->cipher->key_len);
if (!ret)
ret = fdt_setprop_u32(keydest, node, "key-len",
info->cipher->key_len);
done:
if (ret)
ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
return ret;
}