From b346d02daf524490255559f07bde5119334d5812 Mon Sep 17 00:00:00 2001
From: Amy Fong <Amy_Fong@mentor.com>
Date: Wed, 20 Sep 2023 12:01:58 -0400
Subject: [PATCH] gpg: add optional gpg signing verification
This change introduces a Kconfig parameter allowing gpg verification.
The environment variable GPG_HOMEDIR, if set, is used to specify the
home directory.
Signed-off-by: Amy Fong <Amy_Fong@mentor.com>
---
Kconfig | 2 +
Makefile.flags | 5 ++
corelib/Makefile | 1 +
corelib/swupdate_gpg_verify.c | 126 ++++++++++++++++++++++++++++++++++
4 files changed, 134 insertions(+)
create mode 100644 corelib/swupdate_gpg_verify.c
@@ -431,6 +431,8 @@ choice
bool "mbedTLS"
depends on HAVE_MBEDTLS
+ config SIGALG_GPG
+ bool "GPG signing"
endchoice
@@ -305,3 +305,8 @@ endif
# (we stole scripts/checkstack.pl from the kernel... thanks guys!)
# Reduced from 20k to 16k in 1.9.0.
FLTFLAGS += -s 16000
+
+ifeq ($(CONFIG_SIGALG_GPG),y)
+LDLIBS += gpgme
+endif
+
@@ -32,6 +32,7 @@ endif
lib-$(CONFIG_SIGALG_RAWRSA) += swupdate_rsa_verify_mbedtls.o
lib-$(CONFIG_SIGALG_RSAPSS) += swupdate_rsa_verify_mbedtls.o
endif
+lib-$(CONFIG_SIGALG_GPG) += swupdate_gpg_verify.o
lib-$(CONFIG_LIBCONFIG) += swupdate_settings.o \
parsing_library_libconfig.o
lib-$(CONFIG_JSON) += parsing_library_libjson.o server_utils.o
new file mode 100644
@@ -0,0 +1,126 @@
+/*
+ * Author: Amy Fong
+ * Copyright (C) 2023, Siemens AG
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include "swupdate.h"
+#include "sslapi.h"
+#include "util.h"
+
+#include <errno.h>
+#include <locale.h>
+#include <gpgme.h>
+
+static gpg_error_t
+status_cb(void *opaque, const char *keyword, const char *value)
+{
+ (void)opaque;
+ TRACE("status_cb: %s %s\n", keyword, value);
+ return 0;
+}
+
+int swupdate_verify_file(struct swupdate_digest *dgst, const char *sigfile,
+ const char *file, const char *signer_name)
+{
+ gpgme_ctx_t ctx;
+ gpgme_error_t err;
+ gpgme_data_t image_sig, image;
+ FILE *fp_sig = NULL;
+ FILE *fp = NULL;
+ gpgme_signature_t sig;
+ char *gpg_home_dir = NULL;
+ int status = 0;
+ gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
+ gpgme_verify_result_t result;
+
+ TRACE("Enter swupdate_verify_file: gpg verify");
+ /* Initialize the locale environment. */
+ setlocale(LC_ALL, "");
+ (void)gpgme_check_version(NULL);
+
+ err = gpgme_new(&ctx);
+ if (err) {
+ ERROR("Failed to create new gpg context: %s",
+ gpgme_strerror(err));
+ status = -EFAULT;
+ goto out;
+ }
+
+ gpgme_set_protocol(ctx, protocol);
+ gpgme_set_status_cb(ctx, status_cb, NULL);
+ gpgme_set_ctx_flag(ctx, "full-status", "1");
+
+ fp_sig = fopen(sigfile, "rb");
+ if (!fp_sig) {
+ ERROR("Failed to open %s", sigfile);
+ status = -EBADF;
+ goto out;
+ }
+ err = gpgme_data_new_from_stream(&image_sig, fp_sig);
+ if (err) {
+ ERROR("error allocating data object: %s", gpgme_strerror(err));
+ status = -ENOMEM;
+ goto out;
+ }
+
+ fp = fopen(file, "rb");
+ if (!fp) {
+ ERROR("Failed to open %s", file);
+ status = -EBADF;
+ goto out;
+ }
+ err = gpgme_data_new_from_stream(&image, fp);
+ if (err) {
+ ERROR("error allocating data object: %s", gpgme_strerror(err));
+ status = -ENOMEM;
+ goto out;
+ }
+
+ gpg_home_dir = getenv("GPG_HOMEDIR");
+ if (gpg_home_dir != NULL) {
+ err = gpgme_ctx_set_engine_info(ctx, protocol, NULL, gpg_home_dir);
+ if (err) {
+ ERROR("Something went wrong while setting the engine info: %s",
+ gpgme_strerror(err));
+ status = -EFAULT;
+ goto out;
+ }
+ }
+
+ err = gpgme_op_verify(ctx, image_sig, image, NULL);
+ result = gpgme_op_verify_result(ctx);
+ if (err) {
+ ERROR("verify failed: %s\n", gpgme_strerror(err));
+ status = -EBADMSG;
+ goto out;
+ }
+
+ if (result) {
+ for (sig = result->signatures; sig; sig = sig->next) {
+ if (sig->status == GPG_ERR_NO_ERROR) {
+ TRACE("Verified OK\n");
+ status = 0;
+ goto out;
+ }
+ }
+ }
+ TRACE(" Verification failed\n");
+ status = -EBADMSG;
+
+ out:
+ gpgme_data_release(image);
+ gpgme_data_release(image_sig);
+ gpgme_release(ctx);
+
+ if (fp)
+ fclose(fp);
+ if (fp_sig)
+ fclose(fp_sig);
+
+ return status;
+}
--
2.39.2