git: 14cf1cdf9a09 - stable/13 - pkg: pull rsa bits out of pkg.c

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Sat, 11 Jan 2025 02:49:01 UTC
The branch stable/13 has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=14cf1cdf9a099d47b8c80596b462696ebda1c11d

commit 14cf1cdf9a099d47b8c80596b462696ebda1c11d
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2025-01-01 21:10:27 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2025-01-11 02:48:30 +0000

    pkg: pull rsa bits out of pkg.c
    
    We'll eventually add a pkgsign abstraction over these similar to how we do
    in pkg(8), but start by isolating these parts.
    
    Reviewed by:    bapt, emaste
    
    (cherry picked from commit 2629e90dd05fb69d767525f960101d7d055ffae0)
---
 usr.sbin/pkg/Makefile |   2 +-
 usr.sbin/pkg/pkg.c    | 130 +-----------------------------------------
 usr.sbin/pkg/pkg.h    |  50 ++++++++++++++++
 usr.sbin/pkg/rsa.c    | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 207 insertions(+), 130 deletions(-)

diff --git a/usr.sbin/pkg/Makefile b/usr.sbin/pkg/Makefile
index 3e0e047382ca..af0a4d57ee90 100644
--- a/usr.sbin/pkg/Makefile
+++ b/usr.sbin/pkg/Makefile
@@ -22,7 +22,7 @@ CONFSNAME_${PKGCONF}=	${PKGCONF:C/\.conf.+$/.conf/}
 CONFSDIR=	/etc/pkg
 CONFSMODE=	644
 PROG=	pkg
-SRCS=	pkg.c dns_utils.c config.c hash.c
+SRCS=	pkg.c rsa.c dns_utils.c config.c hash.c
 MAN=	pkg.7
 
 CFLAGS+=-I${SRCTOP}/contrib/libucl/include
diff --git a/usr.sbin/pkg/pkg.c b/usr.sbin/pkg/pkg.c
index 1915893af283..3e5e52751e0d 100644
--- a/usr.sbin/pkg/pkg.c
+++ b/usr.sbin/pkg/pkg.c
@@ -49,27 +49,12 @@
 #include <string.h>
 #include <ucl.h>
 
-#include <openssl/err.h>
-#include <openssl/ssl.h>
+#include "pkg.h"
 
 #include "dns_utils.h"
 #include "config.h"
 #include "hash.h"
 
-struct sig_cert {
-	char *name;
-	unsigned char *sig;
-	int siglen;
-	unsigned char *cert;
-	int certlen;
-	bool trusted;
-};
-
-struct pubkey {
-	unsigned char *sig;
-	int siglen;
-};
-
 typedef enum {
 	HASH_UNKNOWN,
 	HASH_SHA256,
@@ -399,119 +384,6 @@ load_fingerprints(const char *path, int *count)
 	return (fingerprints);
 }
 
-static EVP_PKEY *
-load_public_key_file(const char *file)
-{
-	EVP_PKEY *pkey;
-	BIO *bp;
-	char errbuf[1024];
-
-	bp = BIO_new_file(file, "r");
-	if (!bp)
-		errx(EXIT_FAILURE, "Unable to read %s", file);
-
-	if ((pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL)) == NULL)
-		warnx("ici: %s", ERR_error_string(ERR_get_error(), errbuf));
-
-	BIO_free(bp);
-
-	return (pkey);
-}
-
-static EVP_PKEY *
-load_public_key_buf(const unsigned char *cert, int certlen)
-{
-	EVP_PKEY *pkey;
-	BIO *bp;
-	char errbuf[1024];
-
-	bp = BIO_new_mem_buf(__DECONST(void *, cert), certlen);
-
-	if ((pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL)) == NULL)
-		warnx("%s", ERR_error_string(ERR_get_error(), errbuf));
-
-	BIO_free(bp);
-
-	return (pkey);
-}
-
-static bool
-rsa_verify_cert(int fd, const char *sigfile, const unsigned char *key,
-    int keylen, unsigned char *sig, int siglen)
-{
-	EVP_MD_CTX *mdctx;
-	EVP_PKEY *pkey;
-	char *sha256;
-	char errbuf[1024];
-	bool ret;
-
-	sha256 = NULL;
-	pkey = NULL;
-	mdctx = NULL;
-	ret = false;
-
-	SSL_load_error_strings();
-
-	/* Compute SHA256 of the package. */
-	if (lseek(fd, 0, 0) == -1) {
-		warn("lseek");
-		goto cleanup;
-	}
-	if ((sha256 = sha256_fd(fd)) == NULL) {
-		warnx("Error creating SHA256 hash for package");
-		goto cleanup;
-	}
-
-	if (sigfile != NULL) {
-		if ((pkey = load_public_key_file(sigfile)) == NULL) {
-			warnx("Error reading public key");
-			goto cleanup;
-		}
-	} else {
-		if ((pkey = load_public_key_buf(key, keylen)) == NULL) {
-			warnx("Error reading public key");
-			goto cleanup;
-		}
-	}
-
-	/* Verify signature of the SHA256(pkg) is valid. */
-	if ((mdctx = EVP_MD_CTX_create()) == NULL) {
-		warnx("%s", ERR_error_string(ERR_get_error(), errbuf));
-		goto error;
-	}
-
-	if (EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, pkey) != 1) {
-		warnx("%s", ERR_error_string(ERR_get_error(), errbuf));
-		goto error;
-	}
-	if (EVP_DigestVerifyUpdate(mdctx, sha256, strlen(sha256)) != 1) {
-		warnx("%s", ERR_error_string(ERR_get_error(), errbuf));
-		goto error;
-	}
-
-	if (EVP_DigestVerifyFinal(mdctx, sig, siglen) != 1) {
-		warnx("%s", ERR_error_string(ERR_get_error(), errbuf));
-		goto error;
-	}
-
-	ret = true;
-	printf("done\n");
-	goto cleanup;
-
-error:
-	printf("failed\n");
-
-cleanup:
-	free(sha256);
-	if (pkey)
-		EVP_PKEY_free(pkey);
-	if (mdctx)
-		EVP_MD_CTX_destroy(mdctx);
-	ERR_free_strings();
-
-	return (ret);
-}
-
 static struct pubkey *
 read_pubkey(int fd)
 {
diff --git a/usr.sbin/pkg/pkg.h b/usr.sbin/pkg/pkg.h
new file mode 100644
index 000000000000..01f69f5a825b
--- /dev/null
+++ b/usr.sbin/pkg/pkg.h
@@ -0,0 +1,50 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2012-2014 Baptiste Daroussin <bapt@FreeBSD.org>
+ * Copyright (c) 2013 Bryan Drewery <bdrewery@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _PKG_H
+#define	_PKG_H
+
+struct sig_cert {
+	char *name;
+	unsigned char *sig;
+	int siglen;
+	unsigned char *cert;
+	int certlen;
+	bool trusted;
+};
+
+struct pubkey {
+	unsigned char *sig;
+	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
new file mode 100644
index 000000000000..afc446a6ad06
--- /dev/null
+++ b/usr.sbin/pkg/rsa.c
@@ -0,0 +1,155 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2012-2014 Baptiste Daroussin <bapt@FreeBSD.org>
+ * Copyright (c) 2013 Bryan Drewery <bdrewery@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <err.h>
+#include <stdbool.h>
+
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+#include "pkg.h"
+
+#include "config.h"
+#include "hash.h"
+
+static EVP_PKEY *
+load_public_key_file(const char *file)
+{
+	EVP_PKEY *pkey;
+	BIO *bp;
+	char errbuf[1024];
+
+	bp = BIO_new_file(file, "r");
+	if (!bp)
+		errx(EXIT_FAILURE, "Unable to read %s", file);
+
+	if ((pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL)) == NULL)
+		warnx("ici: %s", ERR_error_string(ERR_get_error(), errbuf));
+
+	BIO_free(bp);
+
+	return (pkey);
+}
+
+static EVP_PKEY *
+load_public_key_buf(const unsigned char *cert, int certlen)
+{
+	EVP_PKEY *pkey;
+	BIO *bp;
+	char errbuf[1024];
+
+	bp = BIO_new_mem_buf(__DECONST(void *, cert), certlen);
+
+	if ((pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL)) == NULL)
+		warnx("%s", ERR_error_string(ERR_get_error(), errbuf));
+
+	BIO_free(bp);
+
+	return (pkey);
+}
+
+bool
+rsa_verify_cert(int fd, const char *sigfile, const unsigned char *key,
+    int keylen, unsigned char *sig, int siglen)
+{
+	EVP_MD_CTX *mdctx;
+	EVP_PKEY *pkey;
+	char *sha256;
+	char errbuf[1024];
+	bool ret;
+
+	sha256 = NULL;
+	pkey = NULL;
+	mdctx = NULL;
+	ret = false;
+
+	SSL_load_error_strings();
+
+	/* Compute SHA256 of the package. */
+	if (lseek(fd, 0, 0) == -1) {
+		warn("lseek");
+		goto cleanup;
+	}
+	if ((sha256 = sha256_fd(fd)) == NULL) {
+		warnx("Error creating SHA256 hash for package");
+		goto cleanup;
+	}
+
+	if (sigfile != NULL) {
+		if ((pkey = load_public_key_file(sigfile)) == NULL) {
+			warnx("Error reading public key");
+			goto cleanup;
+		}
+	} else {
+		if ((pkey = load_public_key_buf(key, keylen)) == NULL) {
+			warnx("Error reading public key");
+			goto cleanup;
+		}
+	}
+
+	/* Verify signature of the SHA256(pkg) is valid. */
+	if ((mdctx = EVP_MD_CTX_create()) == NULL) {
+		warnx("%s", ERR_error_string(ERR_get_error(), errbuf));
+		goto error;
+	}
+
+	if (EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, pkey) != 1) {
+		warnx("%s", ERR_error_string(ERR_get_error(), errbuf));
+		goto error;
+	}
+	if (EVP_DigestVerifyUpdate(mdctx, sha256, strlen(sha256)) != 1) {
+		warnx("%s", ERR_error_string(ERR_get_error(), errbuf));
+		goto error;
+	}
+
+	if (EVP_DigestVerifyFinal(mdctx, sig, siglen) != 1) {
+		warnx("%s", ERR_error_string(ERR_get_error(), errbuf));
+		goto error;
+	}
+
+	ret = true;
+	printf("done\n");
+	goto cleanup;
+
+error:
+	printf("failed\n");
+
+cleanup:
+	free(sha256);
+	if (pkey)
+		EVP_PKEY_free(pkey);
+	if (mdctx)
+		EVP_MD_CTX_destroy(mdctx);
+	ERR_free_strings();
+
+	return (ret);
+}