Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Complete pkg_checksum API and reduce duplicated code
Baptiste Daroussin committed 10 years ago
commit 8f013472a15ed5daf483f524fbf5444b7718744e
parent 38c8776
15 files changed +270 -217
modified libpkg/pkg.c
@@ -1618,7 +1618,7 @@ pkg_test_filesum(struct pkg *pkg)
{
	struct pkg_file *f = NULL;
	struct stat	 st;
-
	char sha256[SHA256_DIGEST_LENGTH * 2 + 1];
+
	char *sha256;
	int rc = EPKG_OK;

	assert(pkg != NULL);
@@ -1629,19 +1629,19 @@ pkg_test_filesum(struct pkg *pkg)
				pkg_emit_errno("pkg_create_from_dir", "lstat failed");
				return (EPKG_FATAL);
			}
-
			if (S_ISLNK(st.st_mode)) {
-
				if (pkg_symlink_cksum(f->path, NULL, sha256) != EPKG_OK)
-
					return (EPKG_FATAL);
-
			}
-
			else {
-
				if (sha256_file(f->path, sha256) != EPKG_OK)
-
					return (EPKG_FATAL);
-

-
			}
+
			if (S_ISLNK(st.st_mode))
+
				sha256 = pkg_checksum_symlink(f->path, NULL,
+
				    PKG_HASH_TYPE_SHA256_HEX);
+
			else
+
				sha256 = pkg_checksum_file(f->path,
+
				    PKG_HASH_TYPE_SHA256_HEX);
+
			if (sha256 == NULL)
+
				return (EPKG_FATAL);
			if (strcmp(sha256, f->sum) != 0) {
				pkg_emit_file_mismatch(pkg, f, f->sum);
				rc = EPKG_FATAL;
			}
+
			free(sha256);
		}
	}

@@ -1656,7 +1656,7 @@ pkg_recompute(struct pkgdb *db, struct pkg *pkg)
	int64_t flatsize = 0;
	struct stat st;
	bool regular = false;
-
	char sha256[SHA256_DIGEST_LENGTH * 2 + 1];
+
	char *sha256;
	int rc = EPKG_OK;

	hl = kh_init_hardlinks();
@@ -1665,16 +1665,15 @@ pkg_recompute(struct pkgdb *db, struct pkg *pkg)
			regular = true;
			if (S_ISLNK(st.st_mode)) {
				regular = false;
-
				if (pkg_symlink_cksum(f->path, NULL, sha256)
-
				    != EPKG_OK) {
-
					rc = EPKG_FATAL;
-
					break;
-
				}
+
				sha256 = pkg_checksum_symlink(f->path, NULL,
+
				    PKG_HASH_TYPE_SHA256_HEX);
			} else {
-
				if (sha256_file(f->path, sha256) != EPKG_OK) {
-
					rc = EPKG_FATAL;
-
					break;
-
				}
+
				sha256 = pkg_checksum_file(f->path,
+
				    PKG_HASH_TYPE_SHA256_HEX);
+
			}
+
			if (sha256 == NULL) {
+
				rc = EPKG_FATAL;
+
				break;
			}

			if (st.st_nlink > 1)
@@ -1685,6 +1684,7 @@ pkg_recompute(struct pkgdb *db, struct pkg *pkg)
		}
		if (strcmp(sha256, f->sum) != 0)
			pkgdb_file_set_cksum(db, f, sha256);
+
		free(sha256);
	}
	kh_destroy_hardlinks(hl);

modified libpkg/pkg_add.c
@@ -89,7 +89,7 @@ attempt_to_merge(bool renamed, struct pkg_config_file *rcf,

	char *localconf = NULL;
	size_t sz;
-
	char localsum[SHA256_DIGEST_LENGTH];
+
	char *localsum;

	if (!renamed) {
		pkg_debug(3, "Not renamed");
@@ -123,12 +123,15 @@ attempt_to_merge(bool renamed, struct pkg_config_file *rcf,

	if (sz == strlen(lcf->content)) {
		pkg_debug(2, "Ancient vanilla and deployed conf are the same size testing checksum");
-
		sha256_buf(localconf, sz, localsum);
-
		if (strcmp(localsum, lf->sum) == 0) {
+
		localsum = pkg_checksum_data(localconf, sz,
+
		    PKG_HASH_TYPE_SHA256_HEX);
+
		if (localsum && strcmp(localsum, lf->sum) == 0) {
			pkg_debug(2, "Checksum are the same %d", strlen(localconf));
			free(localconf);
+
			free(localsum);
			return;
		}
+
		free(localsum);
		pkg_debug(2, "Checksum are different %d", strlen(localconf));
	}

modified libpkg/pkg_checksum.c
@@ -24,6 +24,7 @@

#include <assert.h>

+
#include <fcntl.h>
#include "pkg.h"
#include "private/pkg.h"
#include "private/event.h"
@@ -45,14 +46,21 @@ typedef void (*pkg_checksum_hash_bulk_func)(const unsigned char *in, size_t inle
typedef void (*pkg_checksum_encode_func)(unsigned char *in, size_t inlen,
				char *out, size_t outlen);

+
typedef void (*pkg_checksum_hash_file_func)(int fd, unsigned char **out,
+
    size_t *outlen);
+

static void pkg_checksum_hash_sha256(struct pkg_checksum_entry *entries,
				unsigned char **out, size_t *outlen);
static void pkg_checksum_hash_sha256_bulk(const unsigned char *in, size_t inlen,
				unsigned char **out, size_t *outlen);
+
static void pkg_checksum_hash_sha256_file(int fd, unsigned char **out,
+
    size_t *outlen);
static void pkg_checksum_hash_blake2(struct pkg_checksum_entry *entries,
				unsigned char **out, size_t *outlen);
static void pkg_checksum_hash_blake2_bulk(const unsigned char *in, size_t inlen,
				unsigned char **out, size_t *outlen);
+
static void pkg_checksum_hash_blake2_file(int fd, unsigned char **out,
+
    size_t *outlen);
static void pkg_checksum_encode_base32(unsigned char *in, size_t inlen,
				char *out, size_t outlen);
static void pkg_checksum_encode_hex(unsigned char *in, size_t inlen,
@@ -63,6 +71,7 @@ static const struct _pkg_cksum_type {
	size_t hlen;
	pkg_checksum_hash_func hfunc;
	pkg_checksum_hash_bulk_func hbulkfunc;
+
	pkg_checksum_hash_file_func hfilefunc;
	pkg_checksum_encode_func encfunc;
} checksum_types[] = {
	[PKG_HASH_TYPE_SHA256_BASE32] = {
@@ -70,6 +79,7 @@ static const struct _pkg_cksum_type {
		PKG_CHECKSUM_SHA256_LEN,
		pkg_checksum_hash_sha256,
		pkg_checksum_hash_sha256_bulk,
+
		pkg_checksum_hash_sha256_file,
		pkg_checksum_encode_base32
	},
	[PKG_HASH_TYPE_SHA256_HEX] = {
@@ -77,6 +87,7 @@ static const struct _pkg_cksum_type {
		PKG_CHECKSUM_SHA256_LEN,
		pkg_checksum_hash_sha256,
		pkg_checksum_hash_sha256_bulk,
+
		pkg_checksum_hash_sha256_file,
		pkg_checksum_encode_hex
	},
	[PKG_HASH_TYPE_BLAKE2_BASE32] = {
@@ -84,6 +95,7 @@ static const struct _pkg_cksum_type {
		PKG_CHECKSUM_BLAKE2_LEN,
		pkg_checksum_hash_blake2,
		pkg_checksum_hash_blake2_bulk,
+
		pkg_checksum_hash_blake2_file,
		pkg_checksum_encode_hex
	},
	[PKG_HASH_TYPE_SHA256_RAW] = {
@@ -91,6 +103,7 @@ static const struct _pkg_cksum_type {
		SHA256_DIGEST_LENGTH,
		pkg_checksum_hash_sha256,
		pkg_checksum_hash_sha256_bulk,
+
		pkg_checksum_hash_sha256_file,
		NULL
	},
	[PKG_HASH_TYPE_BLAKE2_RAW] = {
@@ -98,12 +111,14 @@ static const struct _pkg_cksum_type {
		BLAKE2B_OUTBYTES,
		pkg_checksum_hash_blake2,
		pkg_checksum_hash_blake2_bulk,
+
		pkg_checksum_hash_blake2_file,
		NULL
	},
	[PKG_HASH_TYPE_UNKNOWN] = {
		NULL,
		-1,
		NULL,
+
		NULL,
		NULL
	}
};
@@ -341,6 +356,21 @@ pkg_checksum_hash_sha256_bulk(const unsigned char *in, size_t inlen,
}

static void
+
pkg_checksum_hash_sha256_file(int fd, unsigned char **out, size_t *outlen)
+
{
+
	char buffer[8192];
+
	size_t r;
+

+
	SHA256_CTX sign_ctx;
+
	*out = malloc(SHA256_DIGEST_LENGTH);
+
	SHA256_Init(&sign_ctx);
+
	while ((r = read(fd, buffer, sizeof(buffer))) > 0)
+
		SHA256_Update(&sign_ctx, buffer, r);
+
	SHA256_Final(*out, &sign_ctx);
+
	*outlen = SHA256_DIGEST_LENGTH;
+
}
+

+
static void
pkg_checksum_hash_blake2(struct pkg_checksum_entry *entries,
		unsigned char **out, size_t *outlen)
{
@@ -373,6 +403,22 @@ pkg_checksum_hash_blake2_bulk(const unsigned char *in, size_t inlen,
	*outlen = BLAKE2B_OUTBYTES;
}

+
static void
+
pkg_checksum_hash_blake2_file(int fd, unsigned char **out, size_t *outlen)
+
{
+
	char buffer[8192];
+
	size_t r;
+

+
	blake2b_state st;
+
	blake2b_init(&st, BLAKE2B_OUTBYTES);
+

+
	while ((r = read(fd, buffer, sizeof(buffer))) > 0)
+
		blake2b_update(&st, buffer, r);
+

+
	blake2b_final(&st, *out, BLAKE2B_OUTBYTES);
+
	*outlen = BLAKE2B_OUTBYTES;
+
}
+

/*
 * We use here z-base32 encoding described here:
 * http://philzimmermann.com/docs/human-oriented-base-32-encoding.txt
@@ -548,3 +594,113 @@ pkg_checksum_data(const unsigned char *in, size_t inlen,

	return (res);
}
+

+
unsigned char *
+
pkg_checksum_fileat(int rootfd, const char *path, pkg_checksum_type_t type)
+
{
+
	int fd;
+
	unsigned char *ret;
+

+
	if ((fd = openat(rootfd, path, O_RDONLY)) == -1) {
+
		pkg_emit_errno("open", path);
+
		return (NULL);
+
	}
+

+
	ret = pkg_checksum_fd(fd, type);
+

+
	close(fd);
+

+
	return (ret);
+
}
+

+
unsigned char *
+
pkg_checksum_file(const char *path, pkg_checksum_type_t type)
+
{
+
	int fd;
+
	unsigned char *ret;
+

+
	if ((fd = open(path, O_RDONLY)) == -1) {
+
		pkg_emit_errno("open", path);
+
		return (NULL);
+
	}
+

+
	ret = pkg_checksum_fd(fd, type);
+

+
	close(fd);
+

+
	return (ret);
+
}
+

+
unsigned char *
+
pkg_checksum_fd(int fd, pkg_checksum_type_t type)
+
{
+
	const struct _pkg_cksum_type *cksum;
+
	unsigned char *out, *res = NULL;
+
	size_t outlen;
+

+
	if (type >= PKG_HASH_TYPE_UNKNOWN || fd < 0)
+
		return (NULL);
+

+
	cksum = &checksum_types[type];
+
	cksum->hfilefunc(fd, &out, &outlen);
+
	if (out != NULL) {
+
		if (cksum->encfunc != NULL) {
+
			res = malloc(cksum->hlen);
+
			cksum->encfunc(out, outlen, res, cksum->hlen);
+
			free(out);
+
		} else {
+
			res = out;
+
		}
+
	}
+

+
	return (res);
+
}
+

+
static unsigned char *
+
pkg_checksum_symlink_readlink(const char *linkbuf, int linklen, const char *root, pkg_checksum_type_t type)
+
{
+
	const char *lnk;
+

+
	lnk = linkbuf;
+
	if (root != NULL) {
+
		/* Skip root from checksum, as it is meaningless */
+
		if (strncmp(root, linkbuf, strlen(root)) == 0)
+
			lnk += strlen(root);
+
	}
+

+
	/* Skip heading slashes */
+
	while(*lnk == '/')
+
		lnk++;
+

+
	return (pkg_checksum_data(lnk, linklen, type));
+
}
+

+
unsigned char *
+
pkg_checksum_symlink(const char *path, const char *root, pkg_checksum_type_t type)
+
{
+
	char linkbuf[MAXPATHLEN];
+
	int linklen;
+

+
	if ((linklen = readlink(path, linkbuf, sizeof(linkbuf) - 1)) == -1) {
+
		pkg_emit_errno("pkg_checksum_symlink", "readlink failed");
+
		return (NULL);
+
	}
+
	linkbuf[linklen] = '\0';
+

+
	return (pkg_checksum_symlink_readlink(linkbuf, linklen, root, type));
+
}
+

+
unsigned char *
+
pkg_checksum_symlinkat(int fd, const char *path, const char *root, pkg_checksum_type_t type)
+
{
+
	char linkbuf[MAXPATHLEN];
+
	int linklen;
+

+
	if ((linklen = readlinkat(fd, path, linkbuf, sizeof(linkbuf) - 1)) == -1) {
+
		pkg_emit_errno("pkg_checksum_symlinkat", "readlink failed");
+
		return (NULL);
+
	}
+
	linkbuf[linklen] = '\0';
+

+
	return (pkg_checksum_symlink_readlink(linkbuf, linklen, root, type));
+
}
modified libpkg/pkg_create.c
@@ -55,7 +55,7 @@ pkg_create_from_dir(struct pkg *pkg, const char *root,
	struct pkg_dir	*dir = NULL;
	int		 ret;
	struct stat	 st;
-
	char		 sha256[SHA256_DIGEST_LENGTH * 2 + 1];
+
	char		*sha256;
	int64_t		 flatsize = 0;
	int64_t		 nfiles;
	const char	*relocation;
@@ -100,17 +100,22 @@ pkg_create_from_dir(struct pkg *pkg, const char *root,
		if (S_ISLNK(st.st_mode)) {

			if (file->sum[0] == '\0') {
-
				if (pkg_symlink_cksum(fpath, root, sha256) == EPKG_OK)
-
					strlcpy(file->sum, sha256, sizeof(file->sum));
-
				else
+
				sha256 = pkg_checksum_symlink(fpath, root,
+
				    PKG_HASH_TYPE_SHA256_HEX);
+
				if (sha256 == NULL)
					return (EPKG_FATAL);
+
				strlcpy(file->sum, sha256, sizeof(file->sum));
+
				free(sha256);
			}
		}
		else {
			if (file->sum[0] == '\0') {
-
				if (sha256_file(fpath, sha256) != EPKG_OK)
+
				sha256 = pkg_checksum_file(fpath,
+
				    PKG_HASH_TYPE_SHA256_HEX);
+
				if (sha256 == NULL)
					return (EPKG_FATAL);
				strlcpy(file->sum, sha256, sizeof(file->sum));
+
				free(sha256);
			}
		}

modified libpkg/pkg_delete.c
@@ -260,7 +260,7 @@ pkg_delete_file(struct pkg *pkg, struct pkg_file *file, unsigned force)
	const char *prefix_rel;
	struct stat st;
	size_t len;
-
	char sha256[SHA256_DIGEST_LENGTH * 2 + 1];
+
	char *sha256;
#if defined(HAVE_CHFLAGS) && !defined(HAVE_CHFLAGSAT)
	int fd;
#endif
@@ -286,12 +286,15 @@ pkg_delete_file(struct pkg *pkg, struct pkg_file *file, unsigned force)
			return;
		}
		if (S_ISLNK(st.st_mode)) {
-
			if (pkg_symlink_cksumat(pkg->rootfd, path, NULL,
-
			    sha256) != EPKG_OK)
+
			sha256 = pkg_checksum_symlinkat(pkg->rootfd, path, NULL,
+
			    PKG_HASH_TYPE_SHA256_HEX);
+
			if (!sha256)
				return;
		}
		else {
-
			if (sha256_fileat(pkg->rootfd, path, sha256) != EPKG_OK)
+
			sha256 = pkg_checksum_fileat(pkg->rootfd, path,
+
			    PKG_HASH_TYPE_SHA256_HEX);
+
			if (!sha256)
				return;
		}
		if (strcmp(sha256, file->sum)) {
@@ -299,8 +302,10 @@ pkg_delete_file(struct pkg *pkg, struct pkg_file *file, unsigned force)
				"checksum, not removing", pkg->rootpath,
				pkg->rootpath[strlen(pkg->rootpath) - 1] == '/' ? "" : "/",
				path);
+
			free(sha256);
			return;
		}
+
		free(sha256);
	}

#ifdef HAVE_CHFLAGS
modified libpkg/pkg_old.c
@@ -111,14 +111,17 @@ int
pkg_from_old(struct pkg *p)
{
	struct pkg_file *f = NULL;
-
	char sha256[SHA256_DIGEST_LENGTH * 2 + 1];
+
	char *sha256;

	p->type = PKG_INSTALLED;
	while (pkg_files(p, &f) == EPKG_OK) {
		if (f->sum[0] == '\0')
			continue;
-
		if (sha256_file(f->path, sha256) == EPKG_OK)
+
		sha256 = pkg_checksum_file(f->path, PKG_HASH_TYPE_SHA256_HEX);
+
		if (sha256) {
			strlcpy(f->sum, sha256, sizeof(f->sum));
+
			free(sha256);
+
		}
	}

	return (EPKG_OK);
modified libpkg/pkg_ports.c
@@ -317,7 +317,6 @@ meta_file(struct plist *p, char *line, struct file_attr *a, bool is_config)
	struct stat st;
	char *buf;
	bool regular = false;
-
	char sha256[SHA256_DIGEST_LENGTH * 2 + 1];
	int ret = EPKG_OK;

	len = strlen(line);
@@ -359,19 +358,18 @@ meta_file(struct plist *p, char *line, struct file_attr *a, bool is_config)
		else
			regular = true;
	} else if (S_ISLNK(st.st_mode)) {
-
		if (pkg_symlink_cksum(testpath, p->stage, sha256) == EPKG_OK) {
-
			buf = sha256;
-
			regular = false;
-
		} else {
+
		buf = pkg_checksum_symlink(testpath, p->stage,
+
		    PKG_HASH_TYPE_SHA256_HEX);
+
		if (buf == NULL) {
			free_file_attr(a);
			return (EPKG_FATAL);
		}
+
		regular = false;
	}

	if (regular) {
		p->flatsize += st.st_size;
-
		sha256_file(testpath, sha256);
-
		buf = sha256;
+
		buf = pkg_checksum_file(testpath, PKG_HASH_TYPE_SHA256_HEX);
		if (is_config) {
			size_t sz;
			char *content;
@@ -384,6 +382,7 @@ meta_file(struct plist *p, char *line, struct file_attr *a, bool is_config)
			pkg_emit_error("Plist error, @config %s: not a regular "
			    "file", line);
			free_file_attr(a);
+
			free(buf);
			return (EPKG_FATAL);
		}
	}
@@ -393,6 +392,7 @@ meta_file(struct plist *p, char *line, struct file_attr *a, bool is_config)
		pkg_emit_error("Plist error, directory listed as a file: %s",
		    line);
		free_file_attr(a);
+
		free(buf);
		return (EPKG_FATAL);
	}

@@ -418,6 +418,7 @@ meta_file(struct plist *p, char *line, struct file_attr *a, bool is_config)
			    p->gname, p->perm, 0, true);
	}

+
	free(buf);
	free_file_attr(a);

	return (ret);
modified libpkg/pkg_repo.c
@@ -133,7 +133,7 @@ static bool
pkg_repo_check_fingerprint(struct pkg_repo *repo, struct sig_cert *sc, bool fatal)
{
	struct fingerprint *f = NULL;
-
	char hash[SHA256_DIGEST_LENGTH * 2 + 1];
+
	char *hash;
	int nbgood = 0;
	struct sig_cert *s = NULL, *stmp = NULL;
	struct pkg_repo_meta_key *mk = NULL;
@@ -175,17 +175,20 @@ pkg_repo_check_fingerprint(struct pkg_repo *repo, struct sig_cert *sc, bool fata
		}

		s->trusted = false;
-
		sha256_buf(s->cert, s->certlen, hash);
+
		hash = pkg_checksum_data(s->cert, s->certlen,
+
		    PKG_HASH_TYPE_SHA256_HEX);
		HASH_FIND_STR(repo->revoked_fp, hash, f);
		if (f != NULL) {
			if (fatal)
				pkg_emit_error("At least one of the "
					" certificates has been revoked");

+
			free(hash);
			return (false);
		}

		HASH_FIND_STR(repo->trusted_fp, hash, f);
+
		free(hash);
		if (f != NULL) {
			nbgood++;
			s->trusted = true;
modified libpkg/pkg_repo_create.c
@@ -291,7 +291,7 @@ pkg_create_repo_worker(struct pkg_fts_item *start, size_t nelts,
	struct pkg_fts_item *cur;
	struct pkg *pkg = NULL;
	struct pkg_manifest_key *keys = NULL;
-
	char checksum[SHA256_DIGEST_LENGTH * 3 + 1], *mdigest = NULL;
+
	char *mdigest = NULL;
	char digestbuf[1024];
	struct iovec iov[2];
	struct msghdr msg;
@@ -356,9 +356,9 @@ pkg_create_repo_worker(struct pkg_fts_item *start, size_t nelts,
			off_t mpos, fpos = 0;
			size_t mlen;

-
			sha256_file(cur->fts_accpath, checksum);
+
			pkg->sum = pkg_checksum_file(cur->fts_accpath,
+
			    PKG_HASH_TYPE_SHA256_HEX);
			pkg->pkgsize = cur->fts_size;
-
			pkg->sum = strdup(checksum);
			pkg->repopath = strdup(cur->pkg_path);

			/*
@@ -852,7 +852,7 @@ static int
pkg_repo_sign(char *path, char **argv, int argc, struct sbuf **sig, struct sbuf **cert)
{
	FILE *fp;
-
	char sha256[SHA256_DIGEST_LENGTH * 2 + 1];
+
	char *sha256;
	struct sbuf *cmd = NULL;
	struct sbuf *buf = NULL;
	char *line = NULL;
@@ -860,7 +860,8 @@ pkg_repo_sign(char *path, char **argv, int argc, struct sbuf **sig, struct sbuf
	ssize_t linelen;
	int i, ret = EPKG_OK;

-
	if (sha256_file(path, sha256) != EPKG_OK)
+
	sha256 = pkg_checksum_file(path, PKG_HASH_TYPE_SHA256_HEX);
+
	if (!sha256)
		return (EPKG_FATAL);

	cmd = sbuf_new_auto();
@@ -875,10 +876,12 @@ pkg_repo_sign(char *path, char **argv, int argc, struct sbuf **sig, struct sbuf

	if ((fp = popen(sbuf_data(cmd), "r+")) == NULL) {
		ret = EPKG_FATAL;
+
		free(sha256);
		goto done;
	}

	fprintf(fp, "%s\n", sha256);
+
	free(sha256);

	if (*sig == NULL)
		*sig = sbuf_new_auto();
modified libpkg/private/pkg.h
@@ -631,6 +631,14 @@ int pkg_checksum_generate(struct pkg *pkg, char *dest, size_t destlen,
 */
unsigned char * pkg_checksum_data(const unsigned char *in, size_t inlen,
	pkg_checksum_type_t type);
+
unsigned char *pkg_checksum_fd(int fd, pkg_checksum_type_t type);
+
unsigned char *pkg_checksum_file(const char *path, pkg_checksum_type_t type);
+
unsigned char *pkg_checksum_fileat(int fd, const char *path,
+
    pkg_checksum_type_t type);
+
unsigned char *pkg_checksum_symlink(const char *path, const char *root,
+
    pkg_checksum_type_t type);
+
unsigned char *pkg_checksum_symlinkat(int fd, const char *path,
+
    const char *root, pkg_checksum_type_t type);

bool pkg_checksum_is_valid(const char *cksum, size_t clen);
pkg_checksum_type_t pkg_checksum_get_type(const char *cksum, size_t clen);
modified libpkg/private/utils.h
@@ -38,7 +38,6 @@

#include <openssl/pem.h>
#include <openssl/rsa.h>
-
#include <openssl/sha.h>

#define STARTS_WITH(string, needle) (strncasecmp(string, needle, strlen(needle)) == 0)

@@ -83,12 +82,6 @@ int format_exec_cmd(char **, const char *, const char *, const char *, char *,
    int argc, char **argv);
int is_dir(const char *);

-
void sha256_buf(const char *, size_t len, char[SHA256_DIGEST_LENGTH * 2 +1]);
-
void sha256_buf_bin(const char *, size_t len, char[SHA256_DIGEST_LENGTH]);
-
int sha256_file(const char *, char[SHA256_DIGEST_LENGTH * 2 +1]);
-
int sha256_fileat(int fd, const char *, char[SHA256_DIGEST_LENGTH * 2 +1]);
-
int sha256_fd(int fd, char[SHA256_DIGEST_LENGTH * 2 +1]);
-

int rsa_new(struct rsa_key **, pem_password_cb *, char *path);
void rsa_free(struct rsa_key *);
int rsa_sign(char *path, struct rsa_key *rsa, unsigned char **sigret, unsigned int *siglen);
modified libpkg/repo/binary/fetch.c
@@ -132,7 +132,7 @@ pkg_repo_binary_try_fetch(struct pkg_repo *repo, struct pkg *pkg,
	char url[MAXPATHLEN];
	char *dir = NULL;
	int fetched = 0;
-
	char cksum[SHA256_DIGEST_LENGTH * 2 +1];
+
	char *cksum;
	struct stat st;
	char *path = NULL;
	const char *packagesite = NULL;
@@ -226,8 +226,8 @@ checksum:
		    pkg->name, pkg->version);
		return (pkg_repo_binary_try_fetch(repo, pkg, true, mirror, destdir));
	}
-
	retcode = sha256_file(dest, cksum);
-
	if (retcode == EPKG_OK) {
+
	cksum = pkg_checksum_file(dest, PKG_HASH_TYPE_SHA256_HEX);;
+
	if (cksum != NULL) {
		if (strcmp(cksum, pkg->sum)) {
			if (already_tried || fetched == 1) {
				pkg_emit_error("%s-%s failed checksum "
@@ -238,9 +238,11 @@ checksum:
				    "checksum mismatch, fetching from remote",
				    pkg->name, pkg->version);
				unlink(dest);
+
				free(cksum);
				return (pkg_repo_binary_try_fetch(repo, pkg, true, mirror, destdir));
			}
		}
+
		free(cksum);
	}

cleanup:
modified libpkg/repo/binary/init.c
@@ -59,7 +59,7 @@ sqlite_file_exists(sqlite3_context *ctx, int argc, sqlite3_value **argv)
	char	 fpath[MAXPATHLEN];
	sqlite3	*db = sqlite3_context_db_handle(ctx);
	char	*path = bsd_dirname(sqlite3_db_filename(db, "main"));
-
	char	 cksum[SHA256_DIGEST_LENGTH * 2 +1];
+
	char	*cksum;

	if (argc != 2) {
		sqlite3_result_error(ctx, "file_exists needs two argument", -1);
@@ -69,10 +69,11 @@ sqlite_file_exists(sqlite3_context *ctx, int argc, sqlite3_value **argv)
	snprintf(fpath, sizeof(fpath), "%s/%s", path, sqlite3_value_text(argv[0]));

	if (access(fpath, R_OK) == 0) {
-
		sha256_file(fpath, cksum);
-
		if (strcmp(cksum, sqlite3_value_text(argv[1])) == 0)
+
		cksum = pkg_checksum_file(fpath, PKG_HASH_TYPE_SHA256_HEX);
+
		if (cksum && strcmp(cksum, sqlite3_value_text(argv[1])) == 0) {
			sqlite3_result_int(ctx, 1);
-
		else
+
			free(cksum);
+
		} else
			sqlite3_result_int(ctx, 0);
	} else {
		sqlite3_result_int(ctx, 0);
modified libpkg/rsa.c
@@ -115,22 +115,28 @@ static int
rsa_verify_cert_cb(int fd, void *ud)
{
	struct rsa_verify_cbdata *cbdata = ud;
-
	char sha256[SHA256_DIGEST_LENGTH *2 +1];
-
	char hash[SHA256_DIGEST_LENGTH];
+
	char *sha256;
+
	char *hash;
	char errbuf[1024];
	RSA *rsa = NULL;
	int ret;

-
	if (sha256_fd(fd, sha256) != EPKG_OK)
+
	sha256 = pkg_checksum_fd(fd, PKG_HASH_TYPE_SHA256_HEX);
+
	if (sha256 == NULL)
		return (EPKG_FATAL);

-
	sha256_buf_bin(sha256, strlen(sha256), hash);
+
	hash = pkg_checksum_data(sha256, strlen(sha256),
+
	    PKG_HASH_TYPE_SHA256_RAW);
+
	free(sha256);

	rsa = _load_rsa_public_key_buf(cbdata->key, cbdata->keylen);
-
	if (rsa == NULL)
+
	if (rsa == NULL) {
+
		free(hash);
		return (EPKG_FATAL);
+
	}
	ret = RSA_verify(NID_sha256, hash, sizeof(hash), cbdata->sig,
			cbdata->siglen, rsa);
+
	free(hash);
	if (ret == 0) {
		pkg_emit_error("rsa verify failed: %s",
				ERR_error_string(ERR_get_error(), errbuf));
@@ -180,23 +186,27 @@ static int
rsa_verify_cb(int fd, void *ud)
{
	struct rsa_verify_cbdata *cbdata = ud;
-
	char sha256[SHA256_DIGEST_LENGTH *2 +1];
+
	char *sha256;
	char errbuf[1024];
	RSA *rsa = NULL;
	int ret;

-
	if (sha256_fd(fd, sha256) != EPKG_OK)
+
	sha256 = pkg_checksum_fd(fd, PKG_HASH_TYPE_SHA256_HEX);
+
	if (sha256 == NULL)
		return (EPKG_FATAL);

	rsa = _load_rsa_public_key_buf(cbdata->key, cbdata->keylen);
-
	if (rsa == NULL)
+
	if (rsa == NULL) {
+
		free(sha256);
		return(EPKG_FATAL);
+
	}

	ret = RSA_verify(NID_sha1, sha256, sizeof(sha256), cbdata->sig,
-
			cbdata->siglen, rsa);
+
	    cbdata->siglen, rsa);
+
	free(sha256);
	if (ret == 0) {
		pkg_emit_error("%s: %s", cbdata->key,
-
				ERR_error_string(ERR_get_error(), errbuf));
+
		    ERR_error_string(ERR_get_error(), errbuf));
		RSA_free(rsa);
		return (EPKG_FATAL);
	}
@@ -254,7 +264,7 @@ rsa_sign(char *path, struct rsa_key *rsa, unsigned char **sigret, unsigned int *
{
	char errbuf[1024];
	int max_len = 0, ret;
-
	char sha256[SHA256_DIGEST_LENGTH * 2 +1];
+
	char *sha256;

	if (access(rsa->path, R_OK) == -1) {
		pkg_emit_errno("access", rsa->path);
@@ -269,9 +279,12 @@ rsa_sign(char *path, struct rsa_key *rsa, unsigned char **sigret, unsigned int *
	max_len = RSA_size(rsa->key);
	*sigret = calloc(1, max_len + 1);

-
	sha256_file(path, sha256);
+
	sha256 = pkg_checksum_file(path, PKG_HASH_TYPE_SHA256_HEX);
+
	if (sha256 == NULL)
+
		return (EPKG_FATAL);

	ret = RSA_sign(NID_sha1, sha256, sizeof(sha256), *sigret, siglen, rsa->key);
+
	free(sha256);
	if (ret == 0) {
		/* XXX pass back RSA errors correctly */
		pkg_emit_error("%s: %s", rsa->path,
modified libpkg/utils.c
@@ -363,96 +363,6 @@ is_dir(const char *path)
	return (stat(path, &st) == 0 && S_ISDIR(st.st_mode));
}

-
static void
-
sha256_hash(unsigned char hash[SHA256_DIGEST_LENGTH],
-
    char out[SHA256_DIGEST_LENGTH * 2 + 1])
-
{
-
	int i;
-
	for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
-
		sprintf(out + (i * 2), "%02x", hash[i]);
-

-
	out[SHA256_DIGEST_LENGTH * 2] = '\0';
-
}
-

-
int
-
sha256_fileat(int rootfd, const char *path,
-
    char out[SHA256_DIGEST_LENGTH * 2 + 1])
-
{
-
	int fd, ret;
-

-
	if ((fd = openat(rootfd, path, O_RDONLY)) == -1) {
-
		pkg_emit_errno("openat", path);
-
		return (EPKG_FATAL);
-
	}
-

-
	ret = sha256_fd(fd, out);
-

-
	close(fd);
-

-
	return (ret);
-
}
-

-
int
-
sha256_file(const char *path, char out[SHA256_DIGEST_LENGTH * 2 + 1])
-
{
-
	int fd;
-
	int ret;
-

-
	if ((fd = open(path, O_RDONLY)) == -1) {
-
		pkg_emit_errno("open", path);
-
		return (EPKG_FATAL);
-
	}
-

-
	ret = sha256_fd(fd, out);
-

-
	close(fd);
-

-
	return (ret);
-
}
-

-
void
-
sha256_buf(const char *buf, size_t len, char out[SHA256_DIGEST_LENGTH * 2 + 1])
-
{
-
	unsigned char hash[SHA256_DIGEST_LENGTH];
-
	sha256_buf_bin(buf, len, hash);
-
	out[0] = '\0';
-
	sha256_hash(hash, out);
-
}
-

-
void
-
sha256_buf_bin(const char *buf, size_t len, char hash[SHA256_DIGEST_LENGTH])
-
{
-
	SHA256_CTX sha256;
-

-
	SHA256_Init(&sha256);
-
	SHA256_Update(&sha256, buf, len);
-
	SHA256_Final(hash, &sha256);
-
}
-

-
int
-
sha256_fd(int fd, char out[SHA256_DIGEST_LENGTH * 2 + 1])
-
{
-
	char buffer[BUFSIZ];
-
	unsigned char hash[SHA256_DIGEST_LENGTH];
-
	size_t r = 0;
-
	int ret = EPKG_OK;
-
	SHA256_CTX sha256;
-

-
	out[0] = '\0';
-

-
	SHA256_Init(&sha256);
-

-
	while ((r = read(fd, buffer, BUFSIZ)) > 0)
-
		SHA256_Update(&sha256, buffer, r);
-

-
	SHA256_Final(hash, &sha256);
-
	sha256_hash(hash, out);
-

-
	(void)lseek(fd, 0, SEEK_SET);
-

-
	return (ret);
-
}
-

bool
string_end_with(const char *path, const char *str)
{
@@ -737,59 +647,6 @@ ucl_object_emit_sbuf(const ucl_object_t *obj, enum ucl_emitter emit_type,
	return (ret);
}

-
static int
-
pkg_symlink_cksum_readlink(const char *linkbuf, int linklen, const char *root,
-
    char *cksum)
-
{
-
	const char *lnk;
-

-
	lnk = linkbuf;
-
	if (root != NULL) {
-
		/* Skip root from checksum, as it is meaningless */
-
		if (strncmp(root, linkbuf, strlen(root)) == 0) {
-
			lnk += strlen(root);
-
		}
-
	}
-
	/* Skip heading slashes */
-
	while(*lnk == '/')
-
		lnk ++;
-

-
	sha256_buf(lnk, linklen, cksum);
-

-
	return (EPKG_OK);
-
}
-

-
int
-
pkg_symlink_cksum(const char *path, const char *root, char *cksum)
-
{
-
	char linkbuf[MAXPATHLEN];
-
	int linklen;
-

-
	if ((linklen = readlink(path, linkbuf, sizeof(linkbuf) - 1)) == -1) {
-
		pkg_emit_errno("pkg_symlink_cksum", "readlink failed");
-
		return (EPKG_FATAL);
-
	}
-
	linkbuf[linklen] = '\0';
-

-
	return (pkg_symlink_cksum_readlink(linkbuf, linklen, root, cksum));
-
}
-

-
int
-
pkg_symlink_cksumat(int fd, const char *path, const char *root, char *cksum)
-
{
-
	char linkbuf[MAXPATHLEN];
-
	int linklen;
-

-
	if ((linklen = readlinkat(fd, path, linkbuf, sizeof(linkbuf) - 1)) ==
-
	    -1) {
-
		pkg_emit_errno("pkg_symlink_cksum", "readlink failed");
-
		return (EPKG_FATAL);
-
	}
-
	linkbuf[linklen] = '\0';
-

-
	return (pkg_symlink_cksum_readlink(linkbuf, linklen, root, cksum));
-
}
-

/* A bit like strsep(), except it accounts for "double" and 'single'
   quotes.  Unlike strsep(), returns the next arg string, trimmed of
   whitespace or enclosing quotes, and updates **args to point at the