a6982a6f76
Binaries may be encrypted in a FIT image with AES. This algo needs a key and an IV (Initialization Vector). The IV is provided in a file (pointer by iv-name-hint in the ITS file) when building the ITB file. This commits adds provide an alternative way to manage the IV. If the property iv-name-hint is not provided in the ITS file, the tool mkimage will generate an random IV and store it in the FIT image. Signed-off-by: Philippe Reynes <philippe.reynes@softathome.com>
151 lines
3.3 KiB
C
151 lines
3.3 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Copyright (c) 2019,Softathome
|
|
*/
|
|
#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;
|
|
|
|
/* 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;
|
|
}
|