diff mbox series

[V4,4/8] Add functions for asymmetric file decryption with CMS

Message ID 20240115192845.51530-5-Michael.Glembotzki@iris-sensing.com
State New
Delegated to: Stefano Babic
Headers show
Series Add support for asymmetric decryption | expand

Commit Message

Michael Glembotzki Jan. 15, 2024, 7:26 p.m. UTC
Decryption with OpenSSL CMS is limited to entire files, preventing the
ability to decrypt data in chunks, as is possible with symmetric
decryption.

Signed-off-by: Michael Glembotzki <Michael.Glembotzki@iris-sensing.com>
---
 corelib/Makefile               |   3 +
 corelib/swupdate_cms_decrypt.c | 115 +++++++++++++++++++++++++++++++++
 include/sslapi.h               |   9 +++
 3 files changed, 127 insertions(+)
 create mode 100644 corelib/swupdate_cms_decrypt.c
diff mbox series

Patch

diff --git a/corelib/Makefile b/corelib/Makefile
index c9ca4aa..06690d8 100644
--- a/corelib/Makefile
+++ b/corelib/Makefile
@@ -18,6 +18,9 @@  endif
 lib-$(CONFIG_SIGALG_RAWRSA)	+= swupdate_rsa_verify.o
 lib-$(CONFIG_SIGALG_RSAPSS)	+= swupdate_rsa_verify.o
 endif
+ifeq ($(CONFIG_ASYM_ENCRYPTED_SW_DESCRIPTION),y)
+lib-$(CONFIG_ENCRYPTED_IMAGES)	+= swupdate_cms_decrypt.o
+endif
 ifeq ($(CONFIG_SSL_IMPL_OPENSSL),y)
 lib-$(CONFIG_SIGALG_CMS)	+= swupdate_cms_verify.o
 endif
diff --git a/corelib/swupdate_cms_decrypt.c b/corelib/swupdate_cms_decrypt.c
new file mode 100644
index 0000000..45aa596
--- /dev/null
+++ b/corelib/swupdate_cms_decrypt.c
@@ -0,0 +1,115 @@ 
+/*
+ * (C) Copyright 2024
+ * Michael Glembotzki, iris-GmbH infrared & intelligent sensors, michael.glembotzki@iris-sensing.com
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Code mostly taken from openssl examples
+ */
+#include <sys/stat.h>
+#include "swupdate.h"
+#include "sslapi.h"
+#include "util.h"
+
+int swupdate_dgst_add_asym_keypair(struct swupdate_cfg *sw, const char *keypair_file)
+{
+	X509 *asym_decryption_cert = NULL;
+	EVP_PKEY *asym_decryption_key = NULL;
+	BIO *tbio = NULL;
+	struct swupdate_digest *dgst = sw->dgst;
+	int ret = 0;
+
+	if (!dgst) {
+		dgst = calloc(1, sizeof(*dgst));
+		if (!dgst) {
+			ret = 1;
+			goto err;
+		}
+	}
+
+	tbio = BIO_new_file(keypair_file, "r");
+
+	if (!tbio) {
+		ERROR("%s cannot be opened", keypair_file);
+		ret = 1;
+		goto err;
+	}
+
+	asym_decryption_cert = PEM_read_bio_X509(tbio, NULL, 0, NULL);
+	if (!asym_decryption_cert)
+		WARN("Decryption cert not found");
+
+	BIO_reset(tbio);
+
+	asym_decryption_key = PEM_read_bio_PrivateKey(tbio, NULL, 0, NULL);
+	BIO_free(tbio);
+	if (!asym_decryption_key) {
+		ERROR("Decryption key not found");
+		ret = 1;
+		goto err;
+	}
+
+	dgst->asym_decryption_cert = asym_decryption_cert;
+	dgst->asym_decryption_key = asym_decryption_key;
+
+	return ret;
+
+err:
+	if (dgst)
+		free(dgst);
+
+	return ret;
+}
+
+int swupdate_decrypt_file(struct swupdate_digest *dgst, const char *infile, const char *outfile)
+{
+	BIO *in = NULL, *out = NULL;
+	CMS_ContentInfo *cms = NULL;
+	int ret = 0;
+
+	if (!dgst || !infile || !outfile)
+		return 1;
+
+	/* Open CMS message to decrypt */
+	in = BIO_new_file(infile, "rb");
+	if (!in) {
+		ERROR("%s cannot be opened", infile);
+		ret = 1;
+		goto err;
+	}
+
+	/* Parse message */
+	cms = d2i_CMS_bio(in, NULL);
+	if (!cms) {
+		ERROR("%s cannot be parsed as DER-encoded CMS blob", infile);
+		ret = 1;
+		goto err;
+	}
+
+	out = BIO_new_file(outfile, "wb");
+	if (!out) {
+		ERROR("%s cannot be opened", outfile);
+		ret = 1;
+		goto err;
+	}
+
+	if (chmod(outfile, 0600)) {
+		ERROR("Setting file permissions");
+		ret = 1;
+		goto err;
+	}
+
+	/* Decrypt CMS message */
+	if (!CMS_decrypt(cms, dgst->asym_decryption_key, dgst->asym_decryption_cert, NULL, out, 0)) {
+		ERR_print_errors_fp(stderr);
+		ERROR("Decrypting %s failed", infile);
+		ret = 1;
+		goto err;
+	}
+
+err:
+	BIO_free(in);
+	BIO_free(out);
+	CMS_ContentInfo_free(cms);
+	return ret;
+}
diff --git a/include/sslapi.h b/include/sslapi.h
index 83efd9f..d27a23c 100644
--- a/include/sslapi.h
+++ b/include/sslapi.h
@@ -113,6 +113,10 @@  struct swupdate_digest {
 	int verbose;
 	char *gpgme_protocol;
 #endif
+#ifdef CONFIG_ASYM_ENCRYPTED_SW_DESCRIPTION
+	EVP_PKEY *asym_decryption_key;
+	X509 *asym_decryption_cert;
+#endif
 };
 
 #if OPENSSL_VERSION_NUMBER < 0x10100000L
@@ -222,6 +226,11 @@  UNUSED static inline struct swupdate_digest *swupdate_DECRYPT_init(
 #define swupdate_DECRYPT_cleanup(p)
 #endif
 
+#ifdef CONFIG_ASYM_ENCRYPTED_SW_DESCRIPTION
+int swupdate_dgst_add_asym_keypair(struct swupdate_cfg *sw, const char *keypair_file);
+int swupdate_decrypt_file(struct swupdate_digest *dgst, const char *infile, const char *outfile);
+#endif
+
 #ifndef SSL_PURPOSE_DEFAULT
 #define SSL_PURPOSE_EMAIL_PROT -1
 #define SSL_PURPOSE_CODE_SIGN  -1