diff --git a/usr.sbin/pkg/Makefile b/usr.sbin/pkg/Makefile --- a/usr.sbin/pkg/Makefile +++ b/usr.sbin/pkg/Makefile @@ -21,7 +21,7 @@ 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.h b/usr.sbin/pkg/pkg.h new file mode 100644 --- /dev/null +++ b/usr.sbin/pkg/pkg.h @@ -0,0 +1,50 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2012-2014 Baptiste Daroussin + * Copyright (c) 2013 Bryan Drewery + * 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/pkg.c b/usr.sbin/pkg/pkg.c --- a/usr.sbin/pkg/pkg.c +++ b/usr.sbin/pkg/pkg.c @@ -48,27 +48,12 @@ #include #include -#include -#include +#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, @@ -400,119 +385,6 @@ 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/rsa.c b/usr.sbin/pkg/rsa.c new file mode 100644 --- /dev/null +++ b/usr.sbin/pkg/rsa.c @@ -0,0 +1,155 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2012-2014 Baptiste Daroussin + * Copyright (c) 2013 Bryan Drewery + * 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 +#include + +#include +#include + +#include +#include + +#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); +}