summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@pep.foundation>2022-09-06 12:43:08 +0200
committerPanu Matilainen <pmatilai@redhat.com>2022-09-20 15:07:44 +0300
commit3404dd64d4c67ee830cfcc13ef71b671354ce889 (patch)
treee8f8e002d86bf9d453f9c04e88ae3979ae9615b8
parent12e0c8b2979280350c9b55c56eb5662bae04408c (diff)
downloadrpm-3404dd64d4c67ee830cfcc13ef71b671354ce889.tar.gz
Add pgpPubkeyFingerprint for Sequoia.
Also add a unit test to exercise pgpPubkeyFingerprint. Backported from commit 2bc745f2fde028e09f663c7967353e8b6aacdbf1
-rw-r--r--rpmio/rpmpgp_sequoia.c3
-rw-r--r--tests/Makefile.am3
-rw-r--r--tests/rpmpgp.at11
-rw-r--r--tests/rpmpgppubkeyfingerprint.c117
4 files changed, 133 insertions, 1 deletions
diff --git a/rpmio/rpmpgp_sequoia.c b/rpmio/rpmpgp_sequoia.c
index 24a381acc..e01acd0e9 100644
--- a/rpmio/rpmpgp_sequoia.c
+++ b/rpmio/rpmpgp_sequoia.c
@@ -39,6 +39,9 @@ W(rpmRC, pgpVerifySignature,
W(int, pgpPubkeyKeyID,
(const uint8_t * pkt, size_t pktlen, pgpKeyID_t keyid),
(pkt, pktlen, keyid))
+W(int, pgpPubkeyFingerprint,
+ (const uint8_t * pkt, size_t pktlen, uint8_t **fp, size_t *fplen),
+ (pkt, pktlen, fp, fplen))
W(char *, pgpArmorWrap,
(int atype, const unsigned char * s, size_t ns),
(atype, s, ns))
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 821f001f1..ca96f952e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -14,6 +14,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
rpmpgpcheck_LDADD = ../rpmio/librpmio.la
rpmpgpprtpkts_LDADD = ../rpmio/librpmio.la
+rpmpgppubkeyfingerprint_LDADD = ../rpmio/librpmio.la
## testsuite components
TESTSUITE_AT = rpmtests.at
@@ -147,7 +148,7 @@ EXTRA_DIST += data/misc/libhello.so
.PHONY: populate_testing
-check_PROGRAMS = rpmpgpcheck rpmpgpprtpkts
+check_PROGRAMS = rpmpgpcheck rpmpgpprtpkts rpmpgppubkeyfingerprint
# testsuite voodoo
AUTOTEST = $(AUTOM4TE) --language=autotest
diff --git a/tests/rpmpgp.at b/tests/rpmpgp.at
index 0ba35fe3f..c2d475a98 100644
--- a/tests/rpmpgp.at
+++ b/tests/rpmpgp.at
@@ -10,6 +10,17 @@ AT_CHECK([[
]],0,)
AT_CLEANUP
+# Test pgpPubkeyFingerprint
+AT_SETUP([[Running tests for computing OpenPGP fingerprints]])
+AT_KEYWORDS([[rpmkeys digest OpenPGP]])
+# Note: the internal OpenPGP parser produces a warning when fed
+# bad data. Don't force Sequoia to generate the same warning.
+AT_CHECK([[
+../../rpmpgppubkeyfingerprint 2>&1 | { grep -v 'warning: Unsupported version of key: '; true; }
+]],0,[Exit code: 0
+])
+AT_CLEANUP
+
# Test pgpPrtPkts printing
AT_SETUP([[Running tests for pgpPrtPkts]])
AT_KEYWORDS([[rpmkeys digest OpenPGP]])
diff --git a/tests/rpmpgppubkeyfingerprint.c b/tests/rpmpgppubkeyfingerprint.c
new file mode 100644
index 000000000..11db45bfb
--- /dev/null
+++ b/tests/rpmpgppubkeyfingerprint.c
@@ -0,0 +1,117 @@
+#include <stddef.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include <rpm/rpmpgp.h>
+
+struct test {
+ char *filename;
+ // If NULL, then filename does not contain a valid fingerprint.
+ char *fingerprint;
+};
+
+static int test(struct test *test)
+{
+ // This program is run from BUILDDIR/tests/rpmtests.dir/XXX. The
+ // data is in BUILDDIR/tests/testing.
+ const char *dir = "../../testing/data/";
+
+ const char *filename = test->filename;
+ const char *fpr = test->fingerprint;
+
+ char *path = malloc(strlen(dir) + 1 + strlen(filename) + 1);
+ if (!path) {
+ fprintf(stderr, "out of memory\n");
+ return 1;
+ }
+ sprintf(path, "%s/%s", dir, filename);
+
+
+ FILE *f = fopen(path, "r");
+ if (!f) {
+ char buffer[PATH_MAX];
+ char *cwd = getcwd(buffer, sizeof(buffer));
+
+ fprintf(stderr, "Failed to open %s (cwd: %s)\n",
+ path, cwd ? : "<unknown>");
+ free(path);
+ return 1;
+ }
+ free(path);
+
+ const int len = 100 * 1024;
+ uint8_t *data = malloc(len);
+ if (!data) {
+ fprintf(stderr, "out of memory\n");
+ return 1;
+ }
+
+ ssize_t bytes = fread((char *)data, 1, len, f);
+ int err = ferror(f);
+ if (err) {
+ fprintf(stderr, "%s: Read error: %s\n",
+ filename, strerror(err));
+ free(data);
+ return 1;
+ }
+
+ uint8_t *fp = NULL;
+ size_t fplen = 0;
+ int rc = pgpPubkeyFingerprint(data, bytes, &fp, &fplen);
+ if (rc) {
+ if (! fpr) {
+ // This test expects the parser to fail.
+ return 0;
+ }
+ fprintf(stderr, "pgpPubkeyFingerprint failed on %s\n", filename);
+ return 1;
+ }
+
+ // We expect success now.
+ char *got = rpmhex(fp, fplen);
+ if (! got) {
+ fprintf(stderr, "%s: rpmhex failed\n", filename);
+ return 1;
+ }
+
+ if (!fpr || strcmp(got, fpr) != 0) {
+ fprintf(stderr, "%s:\n got '%s'\nexpected '%s'\n",
+ filename, got, fpr ? fpr : "<none>");
+ free(got);
+ return 1;
+ }
+ free(got);
+
+ return 0;
+}
+
+int main(void)
+{
+ int rt;
+ int ec = 0;
+
+ struct test tests[] = {
+ // Make sure this fails.
+ { "RPMS/hello-1.0-1.i386.rpm", NULL },
+ // ASCII-armor
+ { "keys/rpm.org-rsa-2048-test.pub",
+ NULL },
+ { "keys/CVE-2021-3521-badbind.asc",
+ NULL },
+ // Binary.
+ { "keys/rpm.org-rsa-2048-test.pgp",
+ "771b18d3d7baa28734333c424344591e1964c5fc" },
+ };
+
+ int i;
+ for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
+ rt = test(&tests[i]);
+ if (rt != 0) {
+ fprintf(stderr, "%s failed\n", tests[i].filename);
+ ec = 1;
+ }
+ }
+
+ fprintf(stderr, "Exit code: %d\n", ec);
+ return ec;
+}