diff mbox series

[V2,09/10] Add support for asymmetrical encrypted images

Message ID 20231204100620.27789-10-Michael.Glembotzki@iris-sensing.com
State Changes Requested
Headers show
Series [V2,01/10] util: BUG: set_aes_key does not fail on invalid aes key or ivt | expand

Commit Message

Michael Glembotzki Dec. 4, 2023, 10:05 a.m. UTC
Signed-off-by: Michael Glembotzki <Michael.Glembotzki@iris-sensing.com>
---
 Kconfig                 | 12 ++++++++++++
 core/cpio_utils.c       | 41 ++++++++++++++++++++++++++++++++++++++++-
 core/installer.c        |  7 +++++++
 core/stream_interface.c | 35 +++++++++++++++++++++++++++++++++--
 4 files changed, 92 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/Kconfig b/Kconfig
index 5a3dc9a..d3412b3 100644
--- a/Kconfig
+++ b/Kconfig
@@ -507,6 +507,18 @@  config ENCRYPTED_SW_DESCRIPTION
 	  if this is set. It is a compile time option, and mix of plain and
 	  encrypted sw-descriptions is not possible.
 
+config ASYM_ENCRYPTED_SW_DESCRIPTION
+	bool "Asymmetrical encrypted sw-description"
+	depends on ENCRYPTED_SW_DESCRIPTION && !PKCS11
+	depends on SSL_IMPL_OPENSSL
+	default n
+	help
+	  This option enables support for asymmetrical encrypted sw-description,
+	  making it possible to encrypt images device specific. The artifacts
+	  persist in being symmetrically encrypted by retrieving an AES key from
+	  the sw-description, which may be the same or distinct for each artifact.
+	  Cryptographic Message Syntax (CMS) with OpenSSL is used for encryption.
+
 config ENCRYPTED_IMAGES_HARDEN_LOGGING
 	bool "Harden logging for encrypted images"
 	default n
diff --git a/core/cpio_utils.c b/core/cpio_utils.c
index 4556033..cfd4bbe 100644
--- a/core/cpio_utils.c
+++ b/core/cpio_utils.c
@@ -445,6 +445,11 @@  static int __swupdate_copy(int fdin, unsigned char *inbuf, void *out, size_t nby
 	unsigned char *aes_key = NULL;
 	unsigned char *ivt = NULL;
 	unsigned char ivtbuf[AES_BLK_SIZE];
+#ifdef CONFIG_ASYM_ENCRYPTED_SW_DESCRIPTION
+	unsigned char aeskeybuf[AES_256_KEY_LEN];
+	char keylen_ascii;
+#endif
+	char keylen;
 
 	struct InputState input_state = {
 		.fdin = fdin,
@@ -514,7 +519,40 @@  static int __swupdate_copy(int fdin, unsigned char *inbuf, void *out, size_t nby
 	}
 
 	if (encrypted) {
+#ifdef CONFIG_ASYM_ENCRYPTED_SW_DESCRIPTION
+		if(!imgaeskey) {
+			return -EINVAL;
+		}
+
+		keylen_ascii = strlen(imgaeskey);
+		switch (keylen_ascii) {
+		case AES_128_KEY_LEN * 2:
+		case AES_192_KEY_LEN * 2:
+		case AES_256_KEY_LEN * 2:
+			// valid hex string size for AES 128/192/256
+			keylen = keylen_ascii / 2;
+			break;
+		default:
+			ERROR("Invalid image aes_key length");
+			return -EINVAL;
+		}
+
+		if (!imgivt || strlen(imgivt) != (AES_BLK_SIZE*2)) {
+			ERROR("Invalid image ivt length");
+			return -EINVAL;
+		}
+
+		if (is_hex_str(imgivt) || ascii_to_bin(ivtbuf, sizeof(ivtbuf), imgivt) ||
+			is_hex_str(imgaeskey) || ascii_to_bin(aeskeybuf, keylen, imgaeskey)) {
+			ERROR("Setting aes_key or ivt");
+			return -EINVAL;
+		}
+
+		aes_key = aeskeybuf;
+		ivt = ivtbuf;
+#else
 		aes_key = get_aes_key();
+		keylen = get_aes_keylen();
 		if (imgivt) {
 			if (strlen(imgivt) != (AES_BLK_SIZE * 2) ||
 					is_hex_str(imgivt) ||
@@ -525,7 +563,8 @@  static int __swupdate_copy(int fdin, unsigned char *inbuf, void *out, size_t nby
 			ivt = ivtbuf;
 		} else
 			ivt = get_aes_ivt();
-		decrypt_state.dcrypt = swupdate_DECRYPT_init(aes_key, get_aes_keylen(), ivt);
+#endif
+		decrypt_state.dcrypt = swupdate_DECRYPT_init(aes_key, keylen, ivt);
 		if (!decrypt_state.dcrypt) {
 			ERROR("decrypt initialization failure, aborting");
 			ret = -EFAULT;
diff --git a/core/installer.c b/core/installer.c
index db86075..ba85f98 100644
--- a/core/installer.c
+++ b/core/installer.c
@@ -498,6 +498,13 @@  void cleanup_files(struct swupdate_cfg *software) {
 		free(fn);
 	}
 #endif
+
+#ifdef CONFIG_ASYM_ENCRYPTED_SW_DESCRIPTION
+	if (asprintf(&fn, "%s%s.enc", TMPDIR, SW_DESCRIPTION_FILENAME) != ENOMEM_ASPRINTF) {
+		remove_sw_file(fn);
+		free(fn);
+	}
+#endif
 }
 
 int preupdatecmd(struct swupdate_cfg *swcfg)
diff --git a/core/stream_interface.c b/core/stream_interface.c
index bfafa30..ba88193 100644
--- a/core/stream_interface.c
+++ b/core/stream_interface.c
@@ -45,6 +45,7 @@ 
 #include "state.h"
 #include "bootloader.h"
 #include "hw-compatibility.h"
+#include "sslapi.h"
 
 #define BUFF_SIZE	 4096
 #define PERCENT_LB_INDEX	4
@@ -144,11 +145,14 @@  static int extract_files(int fd, struct swupdate_cfg *software)
 	int fdout;
 	struct img_type *img, *part;
 	char output_file[MAX_IMAGE_FNAME];
+#ifdef CONFIG_ASYM_ENCRYPTED_SW_DESCRIPTION
+	char enc_output_file[MAX_IMAGE_FNAME];
+#endif
 	const char* TMPDIR = get_tmpdir();
 	bool installed_directly = false;
 	bool encrypted_sw_desc = false;
 
-#ifdef CONFIG_ENCRYPTED_SW_DESCRIPTION
+#if defined(CONFIG_ENCRYPTED_SW_DESCRIPTION) && !defined(CONFIG_ASYM_ENCRYPTED_SW_DESCRIPTION)
 	encrypted_sw_desc = true;
 #endif
 
@@ -168,6 +172,16 @@  static int extract_files(int fd, struct swupdate_cfg *software)
 			if (extract_file_to_tmp(fd, SW_DESCRIPTION_FILENAME, &offset, encrypted_sw_desc) < 0 )
 				return -1;
 
+#ifdef CONFIG_ASYM_ENCRYPTED_SW_DESCRIPTION
+			snprintf(output_file, sizeof(output_file), "%s%s", TMPDIR, SW_DESCRIPTION_FILENAME);
+			snprintf(enc_output_file, sizeof(enc_output_file), "%s.enc", output_file);
+			if (rename(output_file, enc_output_file))
+				return -1;
+
+			if (swupdate_decrypt_file(software->dgst, enc_output_file, output_file))
+				return -1;
+#endif
+
 			status = STREAM_WAIT_SIGNATURE;
 			break;
 
@@ -381,10 +395,13 @@  static int save_stream(int fdin, struct swupdate_cfg *software)
 	unsigned int tmpsize;
 	unsigned long offset;
 	char output_file[MAX_IMAGE_FNAME];
+#ifdef CONFIG_ASYM_ENCRYPTED_SW_DESCRIPTION
+	char enc_output_file[MAX_IMAGE_FNAME];
+#endif
 	const char* TMPDIR = get_tmpdir();
 	bool encrypted_sw_desc = false;
 
-#ifdef CONFIG_ENCRYPTED_SW_DESCRIPTION
+#if defined(CONFIG_ENCRYPTED_SW_DESCRIPTION) && !defined(CONFIG_ASYM_ENCRYPTED_SW_DESCRIPTION)
 	encrypted_sw_desc = true;
 #endif
 	if (fdin < 0)
@@ -452,6 +469,20 @@  static int save_stream(int fdin, struct swupdate_cfg *software)
 		ret = -EINVAL;
 		goto no_copy_output;
 	}
+
+#ifdef CONFIG_ASYM_ENCRYPTED_SW_DESCRIPTION
+	snprintf(output_file, sizeof(output_file), "%s%s", TMPDIR, SW_DESCRIPTION_FILENAME);
+	snprintf(enc_output_file, sizeof(enc_output_file), "%s.enc", output_file);
+	if (rename(output_file, enc_output_file)) {
+		ret = -EINVAL;
+		goto no_copy_output;
+	}
+	if (swupdate_decrypt_file(software->dgst, enc_output_file, output_file)) {
+		ret = -EINVAL;
+		goto no_copy_output;
+	}
+#endif
+
 #ifdef CONFIG_SIGNED_IMAGES
 	snprintf(output_file, sizeof(output_file), "%s.sig", SW_DESCRIPTION_FILENAME);
 	if (extract_file_to_tmp(tmpfd, output_file, &offset, false) < 0 ) {