diff --git a/Kconfig b/Kconfig
index 5a3dc9a..a6f0671 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 decrypt images device specific. The artifacts
+	  themselves are still encrypted symmetrically. An AES key can optionally
+	  be provided in the sw-description, or the default AES key will be used.
+	  Cryptographic Message Syntax (CMS) is used for decryption.
+
 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 03d43c9..2310156 100644
--- a/core/cpio_utils.c
+++ b/core/cpio_utils.c
@@ -26,6 +26,7 @@
 #include "util.h"
 #include "sslapi.h"
 #include "progress.h"
+#include "parsers.h"
 
 #define MODULE_NAME "cpio"
 
@@ -444,6 +445,7 @@ 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];
+	char keylen;
 
 	struct InputState input_state = {
 		.fdin = fdin,
@@ -513,7 +515,7 @@ static int __swupdate_copy(int fdin, unsigned char *inbuf, void *out, size_t nby
 	}
 
 	if (encrypted == SYMMETRIC) {
-		aes_key = get_aes_key();
+		/* Use default ivt, if no image ivt is provided */
 		if (imgivt) {
 			if (!strlen(imgivt) || !is_hex_str(imgivt) || ascii_to_bin(ivtbuf, sizeof(ivtbuf), imgivt)) {
 				ERROR("Invalid image ivt");
@@ -522,7 +524,19 @@ 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);
+
+#ifdef CONFIG_ASYM_ENCRYPTED_SW_DESCRIPTION
+		aes_key = get_tmp_aes_key();
+		keylen = get_tmp_aes_keylen();
+#endif
+
+		/* Use default aes-key, if no aes-key is provided within the sw-description */
+		if (!aes_key) {
+			aes_key = get_aes_key();
+			keylen = get_aes_keylen();
+		}
+
+		decrypt_state.dcrypt = swupdate_DECRYPT_init(aes_key, keylen, ivt);
 		if (!decrypt_state.dcrypt) {
 			ERROR("decrypt initialization failure, aborting");
 			ret = -EFAULT;
@@ -680,6 +694,43 @@ static int __swupdate_copy(int fdin, unsigned char *inbuf, void *out, size_t nby
 		*checksum = input_state.checksum;
 	}
 
+#ifdef CONFIG_ASYM_ENCRYPTED_SW_DESCRIPTION
+	if (encrypted == ASYMMETRIC) {
+		char sw_desc_file[MAX_IMAGE_FNAME];
+		char sw_desc_file_enc[MAX_IMAGE_FNAME];
+		const char *TMPDIR = get_tmpdir();
+		/*
+		 * Assume the asym encrypted sw-description file is written to fdout
+		 */
+		int fdout = out ? *(int *)out : -1;
+
+		if (fdout < 0) {
+			ERROR("out argument: invalid fd or pointer");
+			ret = -EFAULT;
+			goto copyfile_exit;
+		}
+		close(fdout);
+
+		snprintf(sw_desc_file, sizeof(sw_desc_file), "%s%s", TMPDIR, SW_DESCRIPTION_FILENAME);
+		snprintf(sw_desc_file_enc, sizeof(sw_desc_file_enc), "%s.enc", sw_desc_file);
+
+		if (rename(sw_desc_file, sw_desc_file_enc)) {
+			ERROR("Renaming %s to %s failed", sw_desc_file, sw_desc_file_enc);
+			ret = -EFAULT;
+			goto copyfile_exit;
+		}
+
+		/*
+		 * Decrypt the asym encrypted sw-description file
+		 */
+		if (swupdate_decrypt_file(get_swupdate_cfg()->dgst, sw_desc_file_enc, sw_desc_file)) {
+			ERROR("Decrypting %s failed", sw_desc_file);
+			ret = -EFAULT;
+			goto copyfile_exit;
+		}
+	}
+#endif
+
 	ret = 0;
 
 copyfile_exit:
diff --git a/core/installer.c b/core/installer.c
index 20b5b51..7707672 100644
--- a/core/installer.c
+++ b/core/installer.c
@@ -497,6 +497,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)
