The branch main has been updated by kevans:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=5862580ded35e23581291a2e1052f04428369ead

commit 5862580ded35e23581291a2e1052f04428369ead
Author:     Kyle Evans <kev...@freebsd.org>
AuthorDate: 2025-01-01 21:10:27 +0000
Commit:     Kyle Evans <kev...@freebsd.org>
CommitDate: 2025-01-01 21:11:23 +0000

    pkg: abstract rsa out behind a pkgsign API
    
    This mirrors a change we made in pkg(8), and will be used to next add
    another signer that does ECC.
    
    Reviewed by:    bapt, emaste
    Differential Revision:  https://reviews.freebsd.org/D48106
---
 usr.sbin/pkg/pkg.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 usr.sbin/pkg/pkg.h | 22 ++++++++++++--
 usr.sbin/pkg/rsa.c | 11 +++++--
 3 files changed, 110 insertions(+), 9 deletions(-)

diff --git a/usr.sbin/pkg/pkg.c b/usr.sbin/pkg/pkg.c
index 24a4f6516307..4d476f7653f7 100644
--- a/usr.sbin/pkg/pkg.c
+++ b/usr.sbin/pkg/pkg.c
@@ -34,6 +34,7 @@
 
 #include <archive.h>
 #include <archive_entry.h>
+#include <assert.h>
 #include <dirent.h>
 #include <err.h>
 #include <errno.h>
@@ -54,6 +55,16 @@
 #include "config.h"
 #include "hash.h"
 
+static const struct pkgsign_impl {
+       const char                      *pi_name;
+       const struct pkgsign_ops        *pi_ops;
+} pkgsign_builtins[] = {
+       {
+               .pi_name = "rsa",
+               .pi_ops = &pkgsign_rsa,
+       },
+};
+
 typedef enum {
        HASH_UNKNOWN,
        HASH_SHA256,
@@ -76,6 +87,61 @@ STAILQ_HEAD(fingerprint_list, fingerprint);
 
 static int debug;
 
+static int
+pkgsign_new(const char *name, struct pkgsign_ctx **ctx)
+{
+       const struct pkgsign_impl *impl;
+       const struct pkgsign_ops *ops;
+       struct pkgsign_ctx *nctx;
+       size_t ctx_size;
+       int ret;
+
+       assert(*ctx == NULL);
+       ops = NULL;
+       for (size_t i = 0; i < nitems(pkgsign_builtins); i++) {
+               impl = &pkgsign_builtins[i];
+
+               if (strcmp(name, impl->pi_name) == 0) {
+                       ops = impl->pi_ops;
+                       break;
+               }
+       }
+
+       if (ops == NULL)
+               return (ENOENT);
+
+       ctx_size = ops->pkgsign_ctx_size;
+       if (ctx_size == 0)
+               ctx_size = sizeof(*nctx);
+       assert(ctx_size >= sizeof(*nctx));
+
+       nctx = calloc(1, ctx_size);
+       if (nctx == NULL)
+               err(EXIT_FAILURE, "calloc");
+       nctx->impl = impl;
+
+       ret = 0;
+       if (ops->pkgsign_new != NULL)
+               ret = (*ops->pkgsign_new)(name, nctx);
+
+       if (ret != 0) {
+               free(nctx);
+               return (ret);
+       }
+
+       *ctx = nctx;
+       return (0);
+}
+
+static bool
+pkgsign_verify_cert(const struct pkgsign_ctx *ctx, int fd, const char *sigfile,
+    const unsigned char *key, int keylen, unsigned char *sig, int siglen)
+{
+
+       return ((*ctx->impl->pi_ops->pkgsign_verify_cert)(ctx, fd, sigfile,
+           key, keylen, sig, siglen));
+}
+
 static int
 extract_pkg_static(int fd, char *p, int sz)
 {
@@ -494,10 +560,12 @@ verify_pubsignature(int fd_pkg, int fd_sig)
 {
        struct pubkey *pk;
        const char *pubkey;
+       struct pkgsign_ctx *sctx;
        bool ret;
 
        pk = NULL;
        pubkey = NULL;
+       sctx = NULL;
        ret = false;
        if (config_string(PUBKEY, &pubkey) != 0) {
                warnx("No CONFIG_PUBKEY defined");
@@ -509,9 +577,14 @@ verify_pubsignature(int fd_pkg, int fd_sig)
                goto cleanup;
        }
 
+       if (pkgsign_new("rsa", &sctx) != 0) {
+               warnx("Failed to fetch 'rsa' signer");
+               goto cleanup;
+       }
+
        /* Verify the signature. */
        printf("Verifying signature with public key %s... ", pubkey);
-       if (rsa_verify_cert(fd_pkg, pubkey, NULL, 0, pk->sig,
+       if (pkgsign_verify_cert(sctx, fd_pkg, pubkey, NULL, 0, pk->sig,
            pk->siglen) == false) {
                fprintf(stderr, "Signature is not valid\n");
                goto cleanup;
@@ -534,6 +607,7 @@ verify_signature(int fd_pkg, int fd_sig)
        struct fingerprint_list *trusted, *revoked;
        struct fingerprint *fingerprint;
        struct sig_cert *sc;
+       struct pkgsign_ctx *sctx;
        bool ret;
        int trusted_count, revoked_count;
        const char *fingerprints;
@@ -542,6 +616,7 @@ verify_signature(int fd_pkg, int fd_sig)
 
        hash = NULL;
        sc = NULL;
+       sctx = NULL;
        trusted = revoked = NULL;
        ret = false;
 
@@ -605,10 +680,15 @@ verify_signature(int fd_pkg, int fd_sig)
                goto cleanup;
        }
 
+       if (pkgsign_new("rsa", &sctx) != 0) {
+               fprintf(stderr, "Failed to fetch 'rsa' signer\n");
+               goto cleanup;
+       }
+
        /* Verify the signature. */
        printf("Verifying signature with trusted certificate %s... ", sc->name);
-       if (rsa_verify_cert(fd_pkg, NULL, sc->cert, sc->certlen, sc->sig,
-           sc->siglen) == false) {
+       if (pkgsign_verify_cert(sctx, fd_pkg, NULL, sc->cert, sc->certlen,
+           sc->sig, sc->siglen) == false) {
                fprintf(stderr, "Signature is not valid\n");
                goto cleanup;
        }
diff --git a/usr.sbin/pkg/pkg.h b/usr.sbin/pkg/pkg.h
index 01f69f5a825b..d42f5a95d327 100644
--- a/usr.sbin/pkg/pkg.h
+++ b/usr.sbin/pkg/pkg.h
@@ -30,6 +30,25 @@
 #ifndef _PKG_H
 #define        _PKG_H
 
+#include <stdbool.h>
+
+struct pkgsign_ctx {
+       const struct pkgsign_impl       *impl;
+};
+
+/* Tentatively won't be needing to free any state, all allocated in the ctx. */
+typedef int pkgsign_new_cb(const char *, struct pkgsign_ctx *);
+typedef bool pkgsign_verify_cert_cb(const struct pkgsign_ctx *, int,
+    const char *, const unsigned char *, int, unsigned char *, int);
+
+struct pkgsign_ops {
+       size_t                   pkgsign_ctx_size;
+       pkgsign_new_cb          *pkgsign_new;
+       pkgsign_verify_cert_cb  *pkgsign_verify_cert;
+};
+
+extern const struct pkgsign_ops pkgsign_rsa;
+
 struct sig_cert {
        char *name;
        unsigned char *sig;
@@ -44,7 +63,4 @@ struct pubkey {
        int siglen;
 };
 
-bool rsa_verify_cert(int, const char *, const unsigned char *, int,
-    unsigned char *, int);
-
 #endif /* _PKG_H */
diff --git a/usr.sbin/pkg/rsa.c b/usr.sbin/pkg/rsa.c
index afc446a6ad06..b6345cdcecb8 100644
--- a/usr.sbin/pkg/rsa.c
+++ b/usr.sbin/pkg/rsa.c
@@ -77,9 +77,10 @@ load_public_key_buf(const unsigned char *cert, int certlen)
        return (pkey);
 }
 
-bool
-rsa_verify_cert(int fd, const char *sigfile, const unsigned char *key,
-    int keylen, unsigned char *sig, int siglen)
+static bool
+rsa_verify_cert(const struct pkgsign_ctx *ctx __unused, int fd,
+    const char *sigfile, const unsigned char *key, int keylen,
+    unsigned char *sig, int siglen)
 {
        EVP_MD_CTX *mdctx;
        EVP_PKEY *pkey;
@@ -153,3 +154,7 @@ cleanup:
 
        return (ret);
 }
+
+const struct pkgsign_ops pkgsign_rsa = {
+       .pkgsign_verify_cert = rsa_verify_cert,
+};

Reply via email to