Date: Tue, 15 Sep 2015 06:21:34 +0000 (UTC) From: Baptiste Daroussin <bapt@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r287811 - stable/9/usr.sbin/pkg Message-ID: <201509150621.t8F6LY0t002159@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: bapt Date: Tue Sep 15 06:21:33 2015 New Revision: 287811 URL: https://svnweb.freebsd.org/changeset/base/287811 Log: MFC: r287579, r287810 (adapted to old openssl APIs) Implement pubkey support for the bootstrap Note that to not interfer with finger print it expects a signature on pkg itself which is named pkg.txz.pubkeysign To generate it: echo -n "$(sha256 -q pkg.txz)" | openssl dgst -sha256 -sign /thekey \ -binary -out ./pkg.txz.pubkeysig Note the "echo -n" which prevent signing the '\n' one would get otherwise PR: 202622 Modified: stable/9/usr.sbin/pkg/config.c stable/9/usr.sbin/pkg/config.h stable/9/usr.sbin/pkg/pkg.c Directory Properties: stable/9/usr.sbin/pkg/ (props changed) Modified: stable/9/usr.sbin/pkg/config.c ============================================================================== --- stable/9/usr.sbin/pkg/config.c Tue Sep 15 05:56:16 2015 (r287810) +++ stable/9/usr.sbin/pkg/config.c Tue Sep 15 06:21:33 2015 (r287811) @@ -131,6 +131,15 @@ static struct config_entry c[] = { false, true, }, + [PUBKEY] = { + PKG_CONFIG_STRING, + "PUBKEY", + NULL, + NULL, + NULL, + false, + false + } }; static const char * @@ -347,6 +356,8 @@ config_parse(const ucl_object_t *obj, pk sbuf_cpy(buf, "SIGNATURE_TYPE"); else if (strcasecmp(key, "fingerprints") == 0) sbuf_cpy(buf, "FINGERPRINTS"); + else if (strcasecmp(key, "pubkey") == 0) + sbuf_cpy(buf, "PUBKEY"); else if (strcasecmp(key, "enabled") == 0) { if ((cur->type != UCL_BOOLEAN) || !ucl_object_toboolean(cur)) Modified: stable/9/usr.sbin/pkg/config.h ============================================================================== --- stable/9/usr.sbin/pkg/config.h Tue Sep 15 05:56:16 2015 (r287810) +++ stable/9/usr.sbin/pkg/config.h Tue Sep 15 06:21:33 2015 (r287811) @@ -40,6 +40,7 @@ typedef enum { SIGNATURE_TYPE, FINGERPRINTS, REPOS_DIR, + PUBKEY, CONFIG_SIZE } pkg_config_key; Modified: stable/9/usr.sbin/pkg/pkg.c ============================================================================== --- stable/9/usr.sbin/pkg/pkg.c Tue Sep 15 05:56:16 2015 (r287810) +++ stable/9/usr.sbin/pkg/pkg.c Tue Sep 15 06:21:33 2015 (r287811) @@ -66,6 +66,11 @@ struct sig_cert { bool trusted; }; +struct pubkey { + unsigned char *sig; + int siglen; +}; + typedef enum { HASH_UNKNOWN, HASH_SHA256, @@ -481,7 +486,30 @@ cleanup: } static RSA * -load_rsa_public_key_buf(unsigned char *cert, int certlen) +load_rsa_public_key_file(const char *file) +{ + RSA *rsa = NULL; + BIO *bp; + char errbuf[1024]; + + bp = BIO_new_file(file, "r"); + if (!bp) + errx(EXIT_FAILURE, "Unable to read %s", file); + + if (!PEM_read_bio_RSA_PUBKEY(bp, &rsa, NULL, NULL)) { + warn("error reading public key: %s", + ERR_error_string(ERR_get_error(), errbuf)); + BIO_free(bp); + return (NULL); + } + + BIO_free(bp); + + return (rsa); +} + +static RSA * +load_rsa_public_key_buf(const unsigned char *cert, int certlen) { RSA *rsa = NULL; BIO *bp; @@ -500,8 +528,8 @@ load_rsa_public_key_buf(unsigned char *c static bool -rsa_verify_cert(int fd, unsigned char *key, int keylen, - unsigned char *sig, int siglen) +rsa_verify_cert(int fd, const char *sigfile, const unsigned char *key, + int keylen, unsigned char *sig, int siglen) { char sha256[SHA256_DIGEST_LENGTH *2 +1]; char hash[SHA256_DIGEST_LENGTH]; @@ -518,7 +546,11 @@ rsa_verify_cert(int fd, unsigned char *k sha256_buf_bin(sha256, strlen(sha256), hash); - rsa = load_rsa_public_key_buf(key, keylen); + if (sigfile != NULL) { + rsa = load_rsa_public_key_file(sigfile); + } else { + rsa = load_rsa_public_key_buf(key, keylen); + } if (rsa == NULL) return (false); ret = RSA_verify(NID_sha256, hash, sizeof(hash), sig, siglen, rsa); @@ -533,6 +565,35 @@ rsa_verify_cert(int fd, unsigned char *k return (true); } +static struct pubkey * +read_pubkey(int fd) +{ + struct pubkey *pk; + struct sbuf *sig; + char buf[4096]; + int r; + + if (lseek(fd, 0, 0) == -1) { + warn("lseek"); + return (NULL); + } + + sig = sbuf_new_auto(); + + while ((r = read(fd, buf, sizeof(buf))) >0) { + sbuf_bcat(sig, buf, r); + } + + sbuf_finish(sig); + pk = calloc(1, sizeof(struct pubkey)); + pk->siglen = sbuf_len(sig); + pk->sig = calloc(1, pk->siglen); + memcpy(pk->sig, sbuf_data(sig), pk->siglen); + sbuf_delete(sig); + + return (pk); +} + static struct sig_cert * parse_cert(int fd) { int my_fd; @@ -606,6 +667,45 @@ parse_cert(int fd) { } static bool +verify_pubsignature(int fd_pkg, int fd_sig) +{ + struct pubkey *pk; + const char *pubkey; + bool ret; + + pk = NULL; + pubkey = NULL; + ret = false; + if (config_string(PUBKEY, &pubkey) != 0) { + warnx("No CONFIG_PUBKEY defined"); + goto cleanup; + } + + if ((pk = read_pubkey(fd_sig)) == NULL) { + warnx("Error reading signature"); + goto cleanup; + } + + /* Verify the signature. */ + printf("Verifying signature with public key %s... ", pubkey); + if (rsa_verify_cert(fd_pkg, pubkey, NULL, 0, pk->sig, + pk->siglen) == false) { + fprintf(stderr, "Signature is not valid\n"); + goto cleanup; + } + + ret = true; + +cleanup: + if (pk) { + free(pk->sig); + free(pk); + } + + return (ret); +} + +static bool verify_signature(int fd_pkg, int fd_sig) { struct fingerprint_list *trusted, *revoked; @@ -683,7 +783,7 @@ verify_signature(int fd_pkg, int fd_sig) /* Verify the signature. */ printf("Verifying signature with trusted certificate %s... ", sc->name); - if (rsa_verify_cert(fd_pkg, sc->cert, sc->certlen, sc->sig, + if (rsa_verify_cert(fd_pkg, NULL, sc->cert, sc->certlen, sc->sig, sc->siglen) == false) { printf("failed\n"); fprintf(stderr, "Signature is not valid\n"); @@ -751,24 +851,42 @@ bootstrap_pkg(bool force) if (signature_type != NULL && strcasecmp(signature_type, "NONE") != 0) { - if (strcasecmp(signature_type, "FINGERPRINTS") != 0) { - warnx("Signature type %s is not supported for " - "bootstrapping.", signature_type); - goto cleanup; - } + if (strcasecmp(signature_type, "FINGERPRINTS") == 0) { + + snprintf(tmpsig, MAXPATHLEN, "%s/pkg.txz.sig.XXXXXX", + getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP); + snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz.sig", + packagesite); + + if ((fd_sig = fetch_to_fd(url, tmpsig)) == -1) { + fprintf(stderr, "Signature for pkg not " + "available.\n"); + goto fetchfail; + } - snprintf(tmpsig, MAXPATHLEN, "%s/pkg.txz.sig.XXXXXX", - getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP); - snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz.sig", - packagesite); + if (verify_signature(fd_pkg, fd_sig) == false) + goto cleanup; + } else if (strcasecmp(signature_type, "PUBKEY") == 0) { - if ((fd_sig = fetch_to_fd(url, tmpsig)) == -1) { - fprintf(stderr, "Signature for pkg not available.\n"); - goto fetchfail; - } + snprintf(tmpsig, MAXPATHLEN, + "%s/pkg.txz.pubkeysig.XXXXXX", + getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP); + snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz.pubkeysig", + packagesite); + + if ((fd_sig = fetch_to_fd(url, tmpsig)) == -1) { + fprintf(stderr, "Signature for pkg not " + "available.\n"); + goto fetchfail; + } - if (verify_signature(fd_pkg, fd_sig) == false) + if (verify_pubsignature(fd_pkg, fd_sig) == false) + goto cleanup; + } else { + warnx("Signature type %s is not supported for " + "bootstrapping.", signature_type); goto cleanup; + } } if ((ret = extract_pkg_static(fd_pkg, pkgstatic, MAXPATHLEN)) == 0) @@ -842,21 +960,37 @@ bootstrap_pkg_local(const char *pkgpath, } if (signature_type != NULL && strcasecmp(signature_type, "NONE") != 0) { - if (strcasecmp(signature_type, "FINGERPRINTS") != 0) { - warnx("Signature type %s is not supported for " - "bootstrapping.", signature_type); - goto cleanup; - } + if (strcasecmp(signature_type, "FINGERPRINTS") == 0) { - snprintf(path, sizeof(path), "%s.sig", pkgpath); + snprintf(path, sizeof(path), "%s.sig", pkgpath); - if ((fd_sig = open(path, O_RDONLY)) == -1) { - fprintf(stderr, "Signature for pkg not available.\n"); - goto cleanup; - } + if ((fd_sig = open(path, O_RDONLY)) == -1) { + fprintf(stderr, "Signature for pkg not " + "available.\n"); + goto cleanup; + } - if (verify_signature(fd_pkg, fd_sig) == false) + if (verify_signature(fd_pkg, fd_sig) == false) + goto cleanup; + + } else if (strcasecmp(signature_type, "PUBKEY") == 0) { + + snprintf(path, sizeof(path), "%s.pubkeysig", pkgpath); + + if ((fd_sig = open(path, O_RDONLY)) == -1) { + fprintf(stderr, "Signature for pkg not " + "available.\n"); + goto cleanup; + } + + if (verify_pubsignature(fd_pkg, fd_sig) == false) + goto cleanup; + + } else { + warnx("Signature type %s is not supported for " + "bootstrapping.", signature_type); goto cleanup; + } } if ((ret = extract_pkg_static(fd_pkg, pkgstatic, MAXPATHLEN)) == 0)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201509150621.t8F6LY0t002159>