Commit Diff


commit - 87a3ab84d3eb87b790e3d34aeec2c344a8d7375b
commit + ae25a666dd4099105786ef32f1e6ebaf92abe64d
blob - 9534a8dc0cbb055298ed2df9da2f4cc08ae9ad9f
blob + 1bdc33841ab4da7acfd56bcad536f26eee4ff1d7
--- gotd/repo_write.c
+++ gotd/repo_write.c
@@ -44,6 +44,7 @@
 
 #include "got_lib_delta.h"
 #include "got_lib_delta_cache.h"
+#include "got_lib_hash.h"
 #include "got_lib_object.h"
 #include "got_lib_object_cache.h"
 #include "got_lib_ratelimit.h"
@@ -52,8 +53,6 @@
 #include "got_lib_repository.h"
 #include "got_lib_poll.h"
 
-#include "got_lib_hash.h" /* XXX temp include for debugging */
-
 #include "log.h"
 #include "gotd.h"
 #include "repo_write.h"
@@ -480,7 +479,7 @@ read_more_pack_stream(int infd, BUF *buf, size_t minsi
 
 static const struct got_error *
 copy_object_type_and_size(uint8_t *type, uint64_t *size, int infd, int outfd,
-    off_t *outsize, BUF *buf, size_t *buf_pos, SHA1_CTX *ctx)
+    off_t *outsize, BUF *buf, size_t *buf_pos, struct got_hash *ctx)
 {
 	const struct got_error *err = NULL;
 	uint8_t t = 0;
@@ -529,7 +528,7 @@ copy_object_type_and_size(uint8_t *type, uint64_t *siz
 
 static const struct got_error *
 copy_ref_delta(int infd, int outfd, off_t *outsize, BUF *buf, size_t *buf_pos,
-    SHA1_CTX *ctx)
+    struct got_hash *ctx)
 {
 	const struct got_error *err = NULL;
 	size_t remain = buf_len(buf) - *buf_pos;
@@ -552,7 +551,7 @@ copy_ref_delta(int infd, int outfd, off_t *outsize, BU
 
 static const struct got_error *
 copy_offset_delta(int infd, int outfd, off_t *outsize, BUF *buf, size_t *buf_pos,
-    SHA1_CTX *ctx)
+    struct got_hash *ctx)
 {
 	const struct got_error *err = NULL;
 	uint64_t o = 0;
@@ -599,7 +598,7 @@ copy_offset_delta(int infd, int outfd, off_t *outsize,
 
 static const struct got_error *
 copy_zstream(int infd, int outfd, off_t *outsize, BUF *buf, size_t *buf_pos,
-    SHA1_CTX *ctx)
+    struct got_hash *ctx)
 {
 	const struct got_error *err = NULL;
 	z_stream z;
@@ -703,7 +702,7 @@ recv_packdata(off_t *outsize, uint32_t *nobj, uint8_t 
 	struct got_packfile_hdr hdr;
 	size_t have;
 	uint32_t nhave = 0;
-	SHA1_CTX ctx;
+	struct got_hash ctx;
 	uint8_t expected_sha1[SHA1_DIGEST_LENGTH];
 	char hex[SHA1_DIGEST_STRING_LENGTH];
 	BUF *buf = NULL;
@@ -717,7 +716,7 @@ recv_packdata(off_t *outsize, uint32_t *nobj, uint8_t 
 	if (client->nref_updates == client->nref_del)
 		return NULL;
 
-	SHA1Init(&ctx);
+	got_hash_init(&ctx, GOT_HASH_SHA1);
 
 	err = got_poll_read_full(infd, &have, &hdr, sizeof(hdr), sizeof(hdr));
 	if (err)
@@ -791,7 +790,7 @@ recv_packdata(off_t *outsize, uint32_t *nobj, uint8_t 
 
 	log_debug("received %u objects", *nobj);
 
-	SHA1Final(expected_sha1, &ctx);
+	got_hash_final(&ctx, expected_sha1);
 
 	remain = buf_len(buf) - buf_pos;
 	if (remain < SHA1_DIGEST_LENGTH) {
blob - 2e454602c2119dabd994881cce3b363f4ac0b9ac
blob + 68040e9a601ee88f5422f037dee26c3ce0213fc0
--- lib/deflate.c
+++ lib/deflate.c
@@ -30,6 +30,7 @@
 #include "got_path.h"
 
 #include "got_lib_deflate.h"
+#include "got_lib_hash.h"
 #include "got_lib_poll.h"
 
 #ifndef MIN
@@ -89,6 +90,9 @@ csum_output(struct got_deflate_checksum *csum, const u
 
 	if (csum->output_sha1)
 		SHA1Update(csum->output_sha1, buf, len);
+
+	if (csum->output_ctx)
+		got_hash_update(csum->output_ctx, buf, len);
 }
 
 const struct got_error *
blob - 8d63257a31ec340aa4c23346b7148d5331d4c107
blob + f391c9b29f69de0b5abb466e2cd2bd6e65ae9dde
--- lib/fileindex.c
+++ lib/fileindex.c
@@ -35,6 +35,7 @@
 #include "got_object.h"
 #include "got_path.h"
 
+#include "got_lib_hash.h"
 #include "got_lib_fileindex.h"
 #include "got_lib_worktree.h"
 
@@ -355,12 +356,12 @@ got_fileindex_free(struct got_fileindex *fileindex)
 }
 
 static const struct got_error *
-write_fileindex_val64(SHA1_CTX *ctx, uint64_t val, FILE *outfile)
+write_fileindex_val64(struct got_hash *ctx, uint64_t val, FILE *outfile)
 {
 	size_t n;
 
 	val = htobe64(val);
-	SHA1Update(ctx, (uint8_t *)&val, sizeof(val));
+	got_hash_update(ctx, &val, sizeof(val));
 	n = fwrite(&val, 1, sizeof(val), outfile);
 	if (n != sizeof(val))
 		return got_ferror(outfile, GOT_ERR_IO);
@@ -368,12 +369,12 @@ write_fileindex_val64(SHA1_CTX *ctx, uint64_t val, FIL
 }
 
 static const struct got_error *
-write_fileindex_val32(SHA1_CTX *ctx, uint32_t val, FILE *outfile)
+write_fileindex_val32(struct got_hash *ctx, uint32_t val, FILE *outfile)
 {
 	size_t n;
 
 	val = htobe32(val);
-	SHA1Update(ctx, (uint8_t *)&val, sizeof(val));
+	got_hash_update(ctx, &val, sizeof(val));
 	n = fwrite(&val, 1, sizeof(val), outfile);
 	if (n != sizeof(val))
 		return got_ferror(outfile, GOT_ERR_IO);
@@ -381,12 +382,12 @@ write_fileindex_val32(SHA1_CTX *ctx, uint32_t val, FIL
 }
 
 static const struct got_error *
-write_fileindex_val16(SHA1_CTX *ctx, uint16_t val, FILE *outfile)
+write_fileindex_val16(struct got_hash *ctx, uint16_t val, FILE *outfile)
 {
 	size_t n;
 
 	val = htobe16(val);
-	SHA1Update(ctx, (uint8_t *)&val, sizeof(val));
+	got_hash_update(ctx, &val, sizeof(val));
 	n = fwrite(&val, 1, sizeof(val), outfile);
 	if (n != sizeof(val))
 		return got_ferror(outfile, GOT_ERR_IO);
@@ -394,7 +395,7 @@ write_fileindex_val16(SHA1_CTX *ctx, uint16_t val, FIL
 }
 
 static const struct got_error *
-write_fileindex_path(SHA1_CTX *ctx, const char *path, FILE *outfile)
+write_fileindex_path(struct got_hash *ctx, const char *path, FILE *outfile)
 {
 	size_t n, len, pad = 0;
 	static const uint8_t zero[8] = { 0 };
@@ -405,11 +406,11 @@ write_fileindex_path(SHA1_CTX *ctx, const char *path, 
 	if (pad == 0)
 		pad = 8; /* NUL-terminate */
 
-	SHA1Update(ctx, path, len);
+	got_hash_update(ctx, path, len);
 	n = fwrite(path, 1, len, outfile);
 	if (n != len)
 		return got_ferror(outfile, GOT_ERR_IO);
-	SHA1Update(ctx, zero, pad);
+	got_hash_update(ctx, zero, pad);
 	n = fwrite(zero, 1, pad, outfile);
 	if (n != pad)
 		return got_ferror(outfile, GOT_ERR_IO);
@@ -417,7 +418,7 @@ write_fileindex_path(SHA1_CTX *ctx, const char *path, 
 }
 
 static const struct got_error *
-write_fileindex_entry(SHA1_CTX *ctx, struct got_fileindex_entry *ie,
+write_fileindex_entry(struct got_hash *ctx, struct got_fileindex_entry *ie,
     FILE *outfile)
 {
 	const struct got_error *err;
@@ -451,12 +452,12 @@ write_fileindex_entry(SHA1_CTX *ctx, struct got_filein
 	if (err)
 		return err;
 
-	SHA1Update(ctx, ie->blob_sha1, SHA1_DIGEST_LENGTH);
+	got_hash_update(ctx, ie->blob_sha1, SHA1_DIGEST_LENGTH);
 	n = fwrite(ie->blob_sha1, 1, SHA1_DIGEST_LENGTH, outfile);
 	if (n != SHA1_DIGEST_LENGTH)
 		return got_ferror(outfile, GOT_ERR_IO);
 
-	SHA1Update(ctx, ie->commit_sha1, SHA1_DIGEST_LENGTH);
+	got_hash_update(ctx, ie->commit_sha1, SHA1_DIGEST_LENGTH);
 	n = fwrite(ie->commit_sha1, 1, SHA1_DIGEST_LENGTH, outfile);
 	if (n != SHA1_DIGEST_LENGTH)
 		return got_ferror(outfile, GOT_ERR_IO);
@@ -472,7 +473,7 @@ write_fileindex_entry(SHA1_CTX *ctx, struct got_filein
 	stage = got_fileindex_entry_stage_get(ie);
 	if (stage == GOT_FILEIDX_STAGE_MODIFY ||
 	    stage == GOT_FILEIDX_STAGE_ADD) {
-		SHA1Update(ctx, ie->staged_blob_sha1, SHA1_DIGEST_LENGTH);
+		got_hash_update(ctx, ie->staged_blob_sha1, SHA1_DIGEST_LENGTH);
 		n = fwrite(ie->staged_blob_sha1, 1, SHA1_DIGEST_LENGTH,
 		    outfile);
 		if (n != SHA1_DIGEST_LENGTH)
@@ -487,20 +488,20 @@ got_fileindex_write(struct got_fileindex *fileindex, F
 {
 	const struct got_error *err = NULL;
 	struct got_fileindex_hdr hdr;
-	SHA1_CTX ctx;
-	uint8_t sha1[SHA1_DIGEST_LENGTH];
+	struct got_hash ctx;
+	uint8_t hash[GOT_HASH_DIGEST_MAXLEN];
 	size_t n;
 	struct got_fileindex_entry *ie, *tmp;
 
-	SHA1Init(&ctx);
+	got_hash_init(&ctx, GOT_HASH_SHA1);
 
 	hdr.signature = htobe32(GOT_FILE_INDEX_SIGNATURE);
 	hdr.version = htobe32(GOT_FILE_INDEX_VERSION);
 	hdr.nentries = htobe32(fileindex->nentries);
 
-	SHA1Update(&ctx, (uint8_t *)&hdr.signature, sizeof(hdr.signature));
-	SHA1Update(&ctx, (uint8_t *)&hdr.version, sizeof(hdr.version));
-	SHA1Update(&ctx, (uint8_t *)&hdr.nentries, sizeof(hdr.nentries));
+	got_hash_update(&ctx, &hdr.signature, sizeof(hdr.signature));
+	got_hash_update(&ctx, &hdr.version, sizeof(hdr.version));
+	got_hash_update(&ctx, &hdr.nentries, sizeof(hdr.nentries));
 	n = fwrite(&hdr.signature, 1, sizeof(hdr.signature), outfile);
 	if (n != sizeof(hdr.signature))
 		return got_ferror(outfile, GOT_ERR_IO);
@@ -524,9 +525,9 @@ got_fileindex_write(struct got_fileindex *fileindex, F
 			return err;
 	}
 
-	SHA1Final(sha1, &ctx);
-	n = fwrite(sha1, 1, sizeof(sha1), outfile);
-	if (n != sizeof(sha1))
+	got_hash_final(&ctx, hash);
+	n = fwrite(hash, 1, SHA1_DIGEST_LENGTH, outfile);
+	if (n != SHA1_DIGEST_LENGTH)
 		return got_ferror(outfile, GOT_ERR_IO);
 
 	if (fflush(outfile) != 0)
@@ -536,46 +537,46 @@ got_fileindex_write(struct got_fileindex *fileindex, F
 }
 
 static const struct got_error *
-read_fileindex_val64(uint64_t *val, SHA1_CTX *ctx, FILE *infile)
+read_fileindex_val64(uint64_t *val, struct got_hash *ctx, FILE *infile)
 {
 	size_t n;
 
 	n = fread(val, 1, sizeof(*val), infile);
 	if (n != sizeof(*val))
 		return got_ferror(infile, GOT_ERR_FILEIDX_BAD);
-	SHA1Update(ctx, (uint8_t *)val, sizeof(*val));
+	got_hash_update(ctx, val, sizeof(*val));
 	*val = be64toh(*val);
 	return NULL;
 }
 
 static const struct got_error *
-read_fileindex_val32(uint32_t *val, SHA1_CTX *ctx, FILE *infile)
+read_fileindex_val32(uint32_t *val, struct got_hash *ctx, FILE *infile)
 {
 	size_t n;
 
 	n = fread(val, 1, sizeof(*val), infile);
 	if (n != sizeof(*val))
 		return got_ferror(infile, GOT_ERR_FILEIDX_BAD);
-	SHA1Update(ctx, (uint8_t *)val, sizeof(*val));
+	got_hash_update(ctx, val, sizeof(*val));
 	*val = be32toh(*val);
 	return NULL;
 }
 
 static const struct got_error *
-read_fileindex_val16(uint16_t *val, SHA1_CTX *ctx, FILE *infile)
+read_fileindex_val16(uint16_t *val, struct got_hash *ctx, FILE *infile)
 {
 	size_t n;
 
 	n = fread(val, 1, sizeof(*val), infile);
 	if (n != sizeof(*val))
 		return got_ferror(infile, GOT_ERR_FILEIDX_BAD);
-	SHA1Update(ctx, (uint8_t *)val, sizeof(*val));
+	got_hash_update(ctx, val, sizeof(*val));
 	*val = be16toh(*val);
 	return NULL;
 }
 
 static const struct got_error *
-read_fileindex_path(char **path, SHA1_CTX *ctx, FILE *infile)
+read_fileindex_path(char **path, struct got_hash *ctx, FILE *infile)
 {
 	const struct got_error *err = NULL;
 	const size_t chunk_size = 8;
@@ -600,7 +601,7 @@ read_fileindex_path(char **path, SHA1_CTX *ctx, FILE *
 			err = got_ferror(infile, GOT_ERR_FILEIDX_BAD);
 			break;
 		}
-		SHA1Update(ctx, *path + len, chunk_size);
+		got_hash_update(ctx, *path + len, chunk_size);
 		len += chunk_size;
 	} while (memchr(*path + len - chunk_size, '\0', chunk_size) == NULL);
 
@@ -612,7 +613,7 @@ read_fileindex_path(char **path, SHA1_CTX *ctx, FILE *
 }
 
 static const struct got_error *
-read_fileindex_entry(struct got_fileindex_entry **iep, SHA1_CTX *ctx,
+read_fileindex_entry(struct got_fileindex_entry **iep, struct got_hash *ctx,
     FILE *infile, uint32_t version)
 {
 	const struct got_error *err;
@@ -657,14 +658,14 @@ read_fileindex_entry(struct got_fileindex_entry **iep,
 		err = got_ferror(infile, GOT_ERR_FILEIDX_BAD);
 		goto done;
 	}
-	SHA1Update(ctx, ie->blob_sha1, SHA1_DIGEST_LENGTH);
+	got_hash_update(ctx, ie->blob_sha1, SHA1_DIGEST_LENGTH);
 
 	n = fread(ie->commit_sha1, 1, SHA1_DIGEST_LENGTH, infile);
 	if (n != SHA1_DIGEST_LENGTH) {
 		err = got_ferror(infile, GOT_ERR_FILEIDX_BAD);
 		goto done;
 	}
-	SHA1Update(ctx, ie->commit_sha1, SHA1_DIGEST_LENGTH);
+	got_hash_update(ctx, ie->commit_sha1, SHA1_DIGEST_LENGTH);
 
 	err = read_fileindex_val32(&ie->flags, ctx, infile);
 	if (err)
@@ -684,7 +685,8 @@ read_fileindex_entry(struct got_fileindex_entry **iep,
 				err = got_ferror(infile, GOT_ERR_FILEIDX_BAD);
 				goto done;
 			}
-			SHA1Update(ctx, ie->staged_blob_sha1, SHA1_DIGEST_LENGTH);
+			got_hash_update(ctx, ie->staged_blob_sha1,
+			    SHA1_DIGEST_LENGTH);
 		}
 	} else {
 		/* GOT_FILE_INDEX_VERSION 1 does not support staging. */
@@ -704,14 +706,14 @@ got_fileindex_read(struct got_fileindex *fileindex, FI
 {
 	const struct got_error *err = NULL;
 	struct got_fileindex_hdr hdr;
-	SHA1_CTX ctx;
+	struct got_hash ctx;
 	struct got_fileindex_entry *ie;
 	uint8_t sha1_expected[SHA1_DIGEST_LENGTH];
 	uint8_t sha1[SHA1_DIGEST_LENGTH];
 	size_t n;
 	int i;
 
-	SHA1Init(&ctx);
+	got_hash_init(&ctx, GOT_HASH_SHA1);
 
 	n = fread(&hdr.signature, 1, sizeof(hdr.signature), infile);
 	if (n != sizeof(hdr.signature)) {
@@ -732,9 +734,9 @@ got_fileindex_read(struct got_fileindex *fileindex, FI
 		return got_ferror(infile, GOT_ERR_FILEIDX_BAD);
 	}
 
-	SHA1Update(&ctx, (uint8_t *)&hdr.signature, sizeof(hdr.signature));
-	SHA1Update(&ctx, (uint8_t *)&hdr.version, sizeof(hdr.version));
-	SHA1Update(&ctx, (uint8_t *)&hdr.nentries, sizeof(hdr.nentries));
+	got_hash_update(&ctx, &hdr.signature, sizeof(hdr.signature));
+	got_hash_update(&ctx, &hdr.version, sizeof(hdr.version));
+	got_hash_update(&ctx, &hdr.nentries, sizeof(hdr.nentries));
 
 	hdr.signature = be32toh(hdr.signature);
 	hdr.version = be32toh(hdr.version);
@@ -757,7 +759,7 @@ got_fileindex_read(struct got_fileindex *fileindex, FI
 	n = fread(sha1_expected, 1, sizeof(sha1_expected), infile);
 	if (n != sizeof(sha1_expected))
 		return got_ferror(infile, GOT_ERR_FILEIDX_BAD);
-	SHA1Final(sha1, &ctx);
+	got_hash_final(&ctx, sha1);
 	if (memcmp(sha1, sha1_expected, SHA1_DIGEST_LENGTH) != 0)
 		return got_error(GOT_ERR_FILEIDX_CSUM);
 
blob - 2575eb63d3f9bfe0cd35903ae30824124fa07ca8
blob + b2bda4a5026dccd005650cb802799dd42a235574
--- lib/got_lib_deflate.h
+++ lib/got_lib_deflate.h
@@ -20,6 +20,9 @@ struct got_deflate_checksum {
 
 	/* If not NULL, mix output bytes into this SHA1 context. */
 	SHA1_CTX *output_sha1;
+
+	/* If not NULL, mix output bytes into this hash context. */
+	struct got_hash *output_ctx;
 };
 
 struct got_deflate_buf {
blob - 6cf096112b33a6a0627c71d31836cc10bedb3469
blob + 1405a67ac335af59f8e1c2f04ac566ecd07436e7
--- lib/got_lib_hash.h
+++ lib/got_lib_hash.h
@@ -17,6 +17,8 @@
 #define GOT_SHA1_STRING_ZERO "0000000000000000000000000000000000000000"
 #define GOT_SHA256_STRING_ZERO "0000000000000000000000000000000000000000000000000000000000000000"
 
+#define GOT_HASH_DIGEST_MAXLEN SHA256_DIGEST_LENGTH
+
 int got_parse_xdigit(uint8_t *, const char *);
 
 char *got_sha1_digest_to_str(const uint8_t *, char *, size_t);
@@ -25,3 +27,26 @@ char *got_sha256_digest_to_str(const uint8_t *, char *
 int got_parse_hash_digest(uint8_t *, const char *, enum got_hash_algorithm);
 int got_parse_object_id(struct got_object_id *, const char *,
     enum got_hash_algorithm);
+
+struct got_hash {
+	SHA1_CTX		 sha1_ctx;
+	SHA2_CTX		 sha256_ctx;
+	enum got_hash_algorithm	 algo;
+};
+
+/*
+ * These functions allow to compute and check hashes.
+ * The hash function used is specified during got_hash_init.
+ * Data can be added with got_hash_update and, once done, the checksum
+ * saved in a buffer long at least GOT_HASH_DIGEST_MAXLEN bytes with
+ * got_hash_final or in an got_object_id with got_hash_final_object_id.
+ */
+void	got_hash_init(struct got_hash *, enum got_hash_algorithm);
+void	got_hash_update(struct got_hash *, const void *, size_t);
+void	got_hash_final(struct got_hash *, uint8_t *);
+void	got_hash_final_object_id(struct got_hash *, struct got_object_id *);
+
+/*
+ * Compare two hash digest; similar to memcmp().
+ */
+int	got_hash_cmp(enum got_hash_algorithm, uint8_t *, uint8_t *);
blob - 4ddc5aac63e46a5562147f8b561c4dea76cad65c
blob + 1f5de8404ec67a5500a3ef801466a208558ba9d3
--- lib/got_lib_inflate.h
+++ lib/got_lib_inflate.h
@@ -21,11 +21,17 @@ struct got_inflate_checksum {
 	/* If not NULL, mix input bytes into this SHA1 context. */
 	SHA1_CTX *input_sha1;
 
+	/* if not NULL, mix input bytes into this hash context. */
+	struct got_hash *input_ctx;
+
 	/* If not NULL, mix output bytes into this CRC checksum. */
 	uint32_t *output_crc;
 
 	/* If not NULL, mix output bytes into this SHA1 context. */
 	SHA1_CTX *output_sha1;
+
+	/* If not NULL, mix output bytes into this hash context. */
+	struct got_hash *output_ctx;
 };
 
 struct got_inflate_buf {
blob - bec94759fda7eb63db8c6a38520291cd5c1a8ad1
blob + 8fcb52f1333aada44e211d3b89366979118e617d
--- lib/got_lib_pack_index.h
+++ lib/got_lib_pack_index.h
@@ -18,7 +18,7 @@ typedef const struct got_error *(got_pack_index_progre
     uint32_t nobj_total, uint32_t nobj_indexed, uint32_t nobj_loose,
     uint32_t nobj_resolved);
 
-const struct got_error *got_pack_hwrite(int, void *, int, SHA1_CTX *);
+const struct got_error *got_pack_hwrite(int, void *, int, struct got_hash *);
 
 const struct got_error *
 got_pack_index(struct got_pack *pack, int idxfd,
blob - 51a9a0ca1ab1e8d6bc5e9f6722d0595f2a3b5fe7
blob + b13fad65324a1d95a5dba98ac096ee6accce9093
--- lib/hash.c
+++ lib/hash.c
@@ -128,3 +128,50 @@ got_parse_object_id(struct got_object_id *id, const ch
 
 	return got_parse_hash_digest(id->sha1, line, algo);
 }
+
+void
+got_hash_init(struct got_hash *hash, enum got_hash_algorithm algo)
+{
+	memset(hash, 0, sizeof(*hash));
+	hash->algo = algo;
+
+	if (algo == GOT_HASH_SHA1)
+		SHA1Init(&hash->sha1_ctx);
+	else if (algo == GOT_HASH_SHA256)
+		SHA256Init(&hash->sha256_ctx);
+}
+
+void
+got_hash_update(struct got_hash *hash, const void *data, size_t len)
+{
+	if (hash->algo == GOT_HASH_SHA1)
+		SHA1Update(&hash->sha1_ctx, data, len);
+	else if (hash->algo == GOT_HASH_SHA256)
+		SHA256Update(&hash->sha256_ctx, data, len);
+}
+
+void
+got_hash_final(struct got_hash *hash, uint8_t *out)
+{
+	if (hash->algo == GOT_HASH_SHA1)
+		SHA1Final(out, &hash->sha1_ctx);
+	else if (hash->algo == GOT_HASH_SHA256)
+		SHA256Final(out, &hash->sha256_ctx);
+}
+
+void
+got_hash_final_object_id(struct got_hash *hash, struct got_object_id *id)
+{
+	memset(id, 0, sizeof(*id));
+	got_hash_final(hash, id->sha1);
+}
+
+int
+got_hash_cmp(enum got_hash_algorithm algo, uint8_t *b1, uint8_t *b2)
+{
+	if (algo == GOT_HASH_SHA1)
+		return memcmp(b1, b2, SHA1_DIGEST_LENGTH);
+	else if (algo == GOT_HASH_SHA256)
+		return memcmp(b1, b2, SHA256_DIGEST_LENGTH);
+	return -1;
+}
blob - a7430b2862ad5a27a62c256b504986391d92854d
blob + adf582371c406cc4a2a79408bde3913ff792159f
--- lib/inflate.c
+++ lib/inflate.c
@@ -31,6 +31,7 @@
 #include "got_object.h"
 #include "got_path.h"
 
+#include "got_lib_hash.h"
 #include "got_lib_inflate.h"
 #include "got_lib_poll.h"
 
@@ -94,6 +95,9 @@ csum_input(struct got_inflate_checksum *csum, const ui
 
 	if (csum->input_sha1)
 		SHA1Update(csum->input_sha1, buf, len);
+
+	if (csum->input_ctx)
+		got_hash_update(csum->input_ctx, buf, len);
 }
 
 static void
@@ -104,6 +108,9 @@ csum_output(struct got_inflate_checksum *csum, const u
 
 	if (csum->output_sha1)
 		SHA1Update(csum->output_sha1, buf, len);
+
+	if (csum->output_ctx)
+		got_hash_update(csum->output_ctx, buf, len);
 }
 
 const struct got_error *
blob - d703aefd6b522073c9b2c3c3eb7f2cff2a4e3590
blob + 4ab8eb812ff2dae65b617a1f7699919ca73d32e9
--- lib/object_create.c
+++ lib/object_create.c
@@ -126,14 +126,14 @@ got_object_blob_file_create(struct got_object_id **id,
 	char *header = NULL;
 	int fd = -1;
 	struct stat sb;
-	SHA1_CTX sha1_ctx;
+	struct got_hash ctx;
 	size_t headerlen = 0, n;
 
 	*id = NULL;
 	*blobfile = NULL;
 	*blobsize = 0;
 
-	SHA1Init(&sha1_ctx);
+	got_hash_init(&ctx, GOT_HASH_SHA1);
 
 	fd = open(ondisk_path, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
 	if (fd == -1) {
@@ -155,7 +155,7 @@ got_object_blob_file_create(struct got_object_id **id,
 		goto done;
 	}
 	headerlen = strlen(header) + 1;
-	SHA1Update(&sha1_ctx, header, headerlen);
+	got_hash_update(&ctx, header, headerlen);
 
 	*blobfile = got_opentemp();
 	if (*blobfile == NULL) {
@@ -188,7 +188,7 @@ got_object_blob_file_create(struct got_object_id **id,
 		}
 		if (inlen == 0)
 			break; /* EOF */
-		SHA1Update(&sha1_ctx, buf, inlen);
+		got_hash_update(&ctx, buf, inlen);
 		n = fwrite(buf, 1, inlen, *blobfile);
 		if (n != inlen) {
 			err = got_ferror(*blobfile, GOT_ERR_IO);
@@ -204,7 +204,7 @@ got_object_blob_file_create(struct got_object_id **id,
 		err = got_error_from_errno("calloc");
 		goto done;
 	}
-	SHA1Final((*id)->sha1, &sha1_ctx);
+	got_hash_final_object_id(&ctx, *id);
 
 	if (fflush(*blobfile) != 0) {
 		err = got_error_from_errno("fflush");
@@ -307,7 +307,7 @@ got_object_tree_create(struct got_object_id **id,
 {
 	const struct got_error *err = NULL;
 	char modebuf[sizeof("100644 ")];
-	SHA1_CTX sha1_ctx;
+	struct got_hash ctx;
 	char *header = NULL;
 	size_t headerlen, len = 0, n;
 	FILE *treefile = NULL;
@@ -319,7 +319,7 @@ got_object_tree_create(struct got_object_id **id,
 
 	*id = NULL;
 
-	SHA1Init(&sha1_ctx);
+	got_hash_init(&ctx, GOT_HASH_SHA1);
 
 	sorted_entries = calloc(nentries, sizeof(struct got_tree_entry *));
 	if (sorted_entries == NULL)
@@ -345,7 +345,7 @@ got_object_tree_create(struct got_object_id **id,
 		goto done;
 	}
 	headerlen = strlen(header) + 1;
-	SHA1Update(&sha1_ctx, header, headerlen);
+	got_hash_update(&ctx, header, headerlen);
 
 	treefile = got_opentemp();
 	if (treefile == NULL) {
@@ -371,7 +371,7 @@ got_object_tree_create(struct got_object_id **id,
 			err = got_ferror(treefile, GOT_ERR_IO);
 			goto done;
 		}
-		SHA1Update(&sha1_ctx, modebuf, len);
+		got_hash_update(&ctx, modebuf, len);
 		treesize += n;
 
 		len = strlen(te->name) + 1; /* must include NUL */
@@ -380,7 +380,7 @@ got_object_tree_create(struct got_object_id **id,
 			err = got_ferror(treefile, GOT_ERR_IO);
 			goto done;
 		}
-		SHA1Update(&sha1_ctx, te->name, len);
+		got_hash_update(&ctx, te->name, len);
 		treesize += n;
 
 		len = SHA1_DIGEST_LENGTH;
@@ -389,7 +389,7 @@ got_object_tree_create(struct got_object_id **id,
 			err = got_ferror(treefile, GOT_ERR_IO);
 			goto done;
 		}
-		SHA1Update(&sha1_ctx, te->id.sha1, len);
+		got_hash_update(&ctx, te->id.sha1, len);
 		treesize += n;
 	}
 
@@ -398,7 +398,7 @@ got_object_tree_create(struct got_object_id **id,
 		err = got_error_from_errno("calloc");
 		goto done;
 	}
-	SHA1Final((*id)->sha1, &sha1_ctx);
+	got_hash_final_object_id(&ctx, *id);
 
 	if (fflush(treefile) != 0) {
 		err = got_error_from_errno("fflush");
@@ -427,7 +427,7 @@ got_object_commit_create(struct got_object_id **id,
     const char *logmsg, struct got_repository *repo)
 {
 	const struct got_error *err = NULL;
-	SHA1_CTX sha1_ctx;
+	struct got_hash ctx;
 	char *header = NULL, *tree_str = NULL;
 	char *author_str = NULL, *committer_str = NULL;
 	char *id_str = NULL;
@@ -439,7 +439,7 @@ got_object_commit_create(struct got_object_id **id,
 
 	*id = NULL;
 
-	SHA1Init(&sha1_ctx);
+	got_hash_init(&ctx, GOT_HASH_SHA1);
 
 	msg0 = strdup(logmsg);
 	if (msg0 == NULL)
@@ -478,7 +478,7 @@ got_object_commit_create(struct got_object_id **id,
 		goto done;
 	}
 	headerlen = strlen(header) + 1;
-	SHA1Update(&sha1_ctx, header, headerlen);
+	got_hash_update(&ctx, header, headerlen);
 
 	commitfile = got_opentemp();
 	if (commitfile == NULL) {
@@ -502,7 +502,7 @@ got_object_commit_create(struct got_object_id **id,
 		goto done;
 	}
 	len = strlen(tree_str);
-	SHA1Update(&sha1_ctx, tree_str, len);
+	got_hash_update(&ctx, tree_str, len);
 	n = fwrite(tree_str, 1, len, commitfile);
 	if (n != len) {
 		err = got_ferror(commitfile, GOT_ERR_IO);
@@ -525,7 +525,7 @@ got_object_commit_create(struct got_object_id **id,
 				goto done;
 			}
 			len = strlen(parent_str);
-			SHA1Update(&sha1_ctx, parent_str, len);
+			got_hash_update(&ctx, parent_str, len);
 			n = fwrite(parent_str, 1, len, commitfile);
 			if (n != len) {
 				err = got_ferror(commitfile, GOT_ERR_IO);
@@ -540,7 +540,7 @@ got_object_commit_create(struct got_object_id **id,
 	}
 
 	len = strlen(author_str);
-	SHA1Update(&sha1_ctx, author_str, len);
+	got_hash_update(&ctx, author_str, len);
 	n = fwrite(author_str, 1, len, commitfile);
 	if (n != len) {
 		err = got_ferror(commitfile, GOT_ERR_IO);
@@ -549,7 +549,7 @@ got_object_commit_create(struct got_object_id **id,
 	commitsize += n;
 
 	len = strlen(committer_str);
-	SHA1Update(&sha1_ctx, committer_str, len);
+	got_hash_update(&ctx, committer_str, len);
 	n = fwrite(committer_str, 1, len, commitfile);
 	if (n != len) {
 		err = got_ferror(commitfile, GOT_ERR_IO);
@@ -557,7 +557,7 @@ got_object_commit_create(struct got_object_id **id,
 	}
 	commitsize += n;
 
-	SHA1Update(&sha1_ctx, "\n", 1);
+	got_hash_update(&ctx, "\n", 1);
 	n = fwrite("\n", 1, 1, commitfile);
 	if (n != 1) {
 		err = got_ferror(commitfile, GOT_ERR_IO);
@@ -566,7 +566,7 @@ got_object_commit_create(struct got_object_id **id,
 	commitsize += n;
 
 	len = strlen(msg);
-	SHA1Update(&sha1_ctx, msg, len);
+	got_hash_update(&ctx, msg, len);
 	n = fwrite(msg, 1, len, commitfile);
 	if (n != len) {
 		err = got_ferror(commitfile, GOT_ERR_IO);
@@ -574,7 +574,7 @@ got_object_commit_create(struct got_object_id **id,
 	}
 	commitsize += n;
 
-	SHA1Update(&sha1_ctx, "\n", 1);
+	got_hash_update(&ctx, "\n", 1);
 	n = fwrite("\n", 1, 1, commitfile);
 	if (n != 1) {
 		err = got_ferror(commitfile, GOT_ERR_IO);
@@ -587,7 +587,7 @@ got_object_commit_create(struct got_object_id **id,
 		err = got_error_from_errno("calloc");
 		goto done;
 	}
-	SHA1Final((*id)->sha1, &sha1_ctx);
+	got_hash_final_object_id(&ctx, *id);
 
 	if (fflush(commitfile) != 0) {
 		err = got_error_from_errno("fflush");
@@ -619,7 +619,7 @@ got_object_tag_create(struct got_object_id **id,
     struct got_repository *repo, int verbosity)
 {
 	const struct got_error *err = NULL;
-	SHA1_CTX sha1_ctx;
+	struct got_hash ctx;
 	char *header = NULL;
 	char *tag_str = NULL, *tagger_str = NULL;
 	char *id_str = NULL, *obj_str = NULL, *type_str = NULL;
@@ -633,7 +633,7 @@ got_object_tag_create(struct got_object_id **id,
 
 	*id = NULL;
 
-	SHA1Init(&sha1_ctx);
+	got_hash_init(&ctx, GOT_HASH_SHA1);
 
 	err = got_object_id_str(&id_str, object_id);
 	if (err)
@@ -764,7 +764,7 @@ got_object_tag_create(struct got_object_id **id,
 	}
 
 	headerlen = strlen(header) + 1;
-	SHA1Update(&sha1_ctx, header, headerlen);
+	got_hash_update(&ctx, header, headerlen);
 
 	tagfile = got_opentemp();
 	if (tagfile == NULL) {
@@ -779,7 +779,7 @@ got_object_tag_create(struct got_object_id **id,
 	}
 	tagsize += headerlen;
 	len = strlen(obj_str);
-	SHA1Update(&sha1_ctx, obj_str, len);
+	got_hash_update(&ctx, obj_str, len);
 	n = fwrite(obj_str, 1, len, tagfile);
 	if (n != len) {
 		err = got_ferror(tagfile, GOT_ERR_IO);
@@ -787,7 +787,7 @@ got_object_tag_create(struct got_object_id **id,
 	}
 	tagsize += n;
 	len = strlen(type_str);
-	SHA1Update(&sha1_ctx, type_str, len);
+	got_hash_update(&ctx, type_str, len);
 	n = fwrite(type_str, 1, len, tagfile);
 	if (n != len) {
 		err = got_ferror(tagfile, GOT_ERR_IO);
@@ -796,7 +796,7 @@ got_object_tag_create(struct got_object_id **id,
 	tagsize += n;
 
 	len = strlen(tag_str);
-	SHA1Update(&sha1_ctx, tag_str, len);
+	got_hash_update(&ctx, tag_str, len);
 	n = fwrite(tag_str, 1, len, tagfile);
 	if (n != len) {
 		err = got_ferror(tagfile, GOT_ERR_IO);
@@ -805,7 +805,7 @@ got_object_tag_create(struct got_object_id **id,
 	tagsize += n;
 
 	len = strlen(tagger_str);
-	SHA1Update(&sha1_ctx, tagger_str, len);
+	got_hash_update(&ctx, tagger_str, len);
 	n = fwrite(tagger_str, 1, len, tagfile);
 	if (n != len) {
 		err = got_ferror(tagfile, GOT_ERR_IO);
@@ -813,7 +813,7 @@ got_object_tag_create(struct got_object_id **id,
 	}
 	tagsize += n;
 
-	SHA1Update(&sha1_ctx, "\n", 1);
+	got_hash_update(&ctx, "\n", 1);
 	n = fwrite("\n", 1, 1, tagfile);
 	if (n != 1) {
 		err = got_ferror(tagfile, GOT_ERR_IO);
@@ -822,7 +822,7 @@ got_object_tag_create(struct got_object_id **id,
 	tagsize += n;
 
 	len = strlen(msg);
-	SHA1Update(&sha1_ctx, msg, len);
+	got_hash_update(&ctx, msg, len);
 	n = fwrite(msg, 1, len, tagfile);
 	if (n != len) {
 		err = got_ferror(tagfile, GOT_ERR_IO);
@@ -830,7 +830,7 @@ got_object_tag_create(struct got_object_id **id,
 	}
 	tagsize += n;
 
-	SHA1Update(&sha1_ctx, "\n", 1);
+	got_hash_update(&ctx, "\n", 1);
 	n = fwrite("\n", 1, 1, tagfile);
 	if (n != 1) {
 		err = got_ferror(tagfile, GOT_ERR_IO);
@@ -840,7 +840,7 @@ got_object_tag_create(struct got_object_id **id,
 
 	if (signer_id && buf_len(buf) > 0) {
 		len = buf_len(buf);
-		SHA1Update(&sha1_ctx, buf_get(buf), len);
+		got_hash_update(&ctx, buf_get(buf), len);
 		n = fwrite(buf_get(buf), 1, len, tagfile);
 		if (n != len) {
 			err = got_ferror(tagfile, GOT_ERR_IO);
@@ -854,7 +854,7 @@ got_object_tag_create(struct got_object_id **id,
 		err = got_error_from_errno("calloc");
 		goto done;
 	}
-	SHA1Final((*id)->sha1, &sha1_ctx);
+	got_hash_final_object_id(&ctx, *id);
 
 	if (fflush(tagfile) != 0) {
 		err = got_error_from_errno("fflush");
blob - 5efb32c22767820707ae2c11266b810d15999dfa
blob + 29c7c842065b16ecb3aa7fe09de578199bb18ed0
--- lib/object_parse.c
+++ lib/object_parse.c
@@ -290,8 +290,8 @@ got_object_read_raw(uint8_t **outbuf, off_t *size, siz
 	const struct got_error *err = NULL;
 	struct got_object *obj;
 	struct got_inflate_checksum csum;
-	uint8_t sha1[SHA1_DIGEST_LENGTH];
-	SHA1_CTX sha1_ctx;
+	struct got_object_id id;
+	struct got_hash ctx;
 	size_t len, consumed;
 	FILE *f = NULL;
 
@@ -299,9 +299,9 @@ got_object_read_raw(uint8_t **outbuf, off_t *size, siz
 	*size = 0;
 	*hdrlen = 0;
 
-	SHA1Init(&sha1_ctx);
+	got_hash_init(&ctx, GOT_HASH_SHA1);
 	memset(&csum, 0, sizeof(csum));
-	csum.output_sha1 = &sha1_ctx;
+	csum.output_ctx = &ctx;
 
 	if (lseek(infd, SEEK_SET, 0) == -1)
 		return got_error_from_errno("lseek");
@@ -342,8 +342,8 @@ got_object_read_raw(uint8_t **outbuf, off_t *size, siz
 		goto done;
 	}
 
-	SHA1Final(sha1, &sha1_ctx);
-	if (memcmp(expected_id->sha1, sha1, SHA1_DIGEST_LENGTH) != 0) {
+	got_hash_final_object_id(&ctx, &id);
+	if (got_object_id_cmp(expected_id, &id) != 0) {
 		err = got_error_checksum(expected_id);
 		goto done;
 	}
@@ -751,18 +751,18 @@ got_object_read_commit(struct got_commit_object **comm
 	size_t len;
 	uint8_t *p;
 	struct got_inflate_checksum csum;
-	SHA1_CTX sha1_ctx;
+	struct got_hash ctx;
 	struct got_object_id id;
 
-	SHA1Init(&sha1_ctx);
+	got_hash_init(&ctx, GOT_HASH_SHA1);
 	memset(&csum, 0, sizeof(csum));
-	csum.output_sha1 = &sha1_ctx;
+	csum.output_ctx = &ctx;
 
 	err = got_inflate_to_mem_fd(&p, &len, NULL, &csum, expected_size, fd);
 	if (err)
 		return err;
 
-	SHA1Final(id.sha1, &sha1_ctx);
+	got_hash_final_object_id(&ctx, &id);
 	if (got_object_id_cmp(expected_id, &id) != 0) {
 		err = got_error_checksum(expected_id);
 		goto done;
@@ -920,18 +920,18 @@ got_object_read_tree(struct got_parsed_tree_entry **en
 	struct got_object *obj = NULL;
 	size_t len;
 	struct got_inflate_checksum csum;
-	SHA1_CTX sha1_ctx;
+	struct got_hash ctx;
 	struct got_object_id id;
 
-	SHA1Init(&sha1_ctx);
+	got_hash_init(&ctx, GOT_HASH_SHA1);
 	memset(&csum, 0, sizeof(csum));
-	csum.output_sha1 = &sha1_ctx;
+	csum.output_ctx = &ctx;
 
 	err = got_inflate_to_mem_fd(p, &len, NULL, &csum, 0, fd);
 	if (err)
 		return err;
 
-	SHA1Final(id.sha1, &sha1_ctx);
+	got_hash_final_object_id(&ctx, &id);
 	if (got_object_id_cmp(expected_id, &id) != 0) {
 		err = got_error_checksum(expected_id);
 		goto done;
@@ -1160,19 +1160,19 @@ got_object_read_tag(struct got_tag_object **tag, int f
 	size_t len;
 	uint8_t *p;
 	struct got_inflate_checksum csum;
-	SHA1_CTX sha1_ctx;
+	struct got_hash ctx;
 	struct got_object_id id;
 
-	SHA1Init(&sha1_ctx);
+	got_hash_init(&ctx, GOT_HASH_SHA1);
 	memset(&csum, 0, sizeof(csum));
-	csum.output_sha1 = &sha1_ctx;
+	csum.output_ctx = &ctx;
 
 	err = got_inflate_to_mem_fd(&p, &len, NULL, &csum,
 	    expected_size, fd);
 	if (err)
 		return err;
 
-	SHA1Final(id.sha1, &sha1_ctx);
+	got_hash_final_object_id(&ctx, &id);
 	if (got_object_id_cmp(expected_id, &id) != 0) {
 		err = got_error_checksum(expected_id);
 		goto done;
blob - 41355efc540436f1b9cbb6f193ac0916c8dffb06
blob + af03219f49ee499a7c4d1a39e802bc0773762f06
--- lib/pack.c
+++ lib/pack.c
@@ -74,14 +74,15 @@ const struct got_error *
 got_packidx_init_hdr(struct got_packidx *p, int verify, off_t packfile_size)
 {
 	const struct got_error *err = NULL;
+	enum got_hash_algorithm algo = GOT_HASH_SHA1;
 	struct got_packidx_v2_hdr *h;
-	SHA1_CTX ctx;
-	uint8_t sha1[SHA1_DIGEST_LENGTH];
+	struct got_hash ctx;
+	uint8_t hash[GOT_HASH_DIGEST_MAXLEN];
 	size_t nobj, len_fanout, len_ids, offset, remain;
 	ssize_t n;
 	int i;
 
-	SHA1Init(&ctx);
+	got_hash_init(&ctx, algo);
 
 	h = &p->hdr;
 	offset = 0;
@@ -116,7 +117,7 @@ got_packidx_init_hdr(struct got_packidx *p, int verify
 	remain -= sizeof(*h->magic);
 
 	if (verify)
-		SHA1Update(&ctx, (uint8_t *)h->magic, sizeof(*h->magic));
+		got_hash_update(&ctx, h->magic, sizeof(*h->magic));
 
 	if (remain < sizeof(*h->version)) {
 		err = got_error(GOT_ERR_BAD_PACKIDX);
@@ -147,7 +148,7 @@ got_packidx_init_hdr(struct got_packidx *p, int verify
 	remain -= sizeof(*h->version);
 
 	if (verify)
-		SHA1Update(&ctx, (uint8_t *)h->version, sizeof(*h->version));
+		got_hash_update(&ctx, h->version, sizeof(*h->version));
 
 	len_fanout =
 	    sizeof(*h->fanout_table) * GOT_PACKIDX_V2_FANOUT_TABLE_ITEMS;
@@ -176,7 +177,7 @@ got_packidx_init_hdr(struct got_packidx *p, int verify
 	if (err)
 		goto done;
 	if (verify)
-		SHA1Update(&ctx, (uint8_t *)h->fanout_table, len_fanout);
+		got_hash_update(&ctx, h->fanout_table, len_fanout);
 	offset += len_fanout;
 	remain -= len_fanout;
 
@@ -204,7 +205,7 @@ got_packidx_init_hdr(struct got_packidx *p, int verify
 		}
 	}
 	if (verify)
-		SHA1Update(&ctx, (uint8_t *)h->sorted_ids, len_ids);
+		got_hash_update(&ctx, h->sorted_ids, len_ids);
 	offset += len_ids;
 	remain -= len_ids;
 
@@ -229,7 +230,7 @@ got_packidx_init_hdr(struct got_packidx *p, int verify
 		}
 	}
 	if (verify)
-		SHA1Update(&ctx, (uint8_t *)h->crc32, nobj * sizeof(*h->crc32));
+		got_hash_update(&ctx, h->crc32, nobj * sizeof(*h->crc32));
 	remain -= nobj * sizeof(*h->crc32);
 	offset += nobj * sizeof(*h->crc32);
 
@@ -254,8 +255,7 @@ got_packidx_init_hdr(struct got_packidx *p, int verify
 		}
 	}
 	if (verify)
-		SHA1Update(&ctx, (uint8_t *)h->offsets,
-		    nobj * sizeof(*h->offsets));
+		got_hash_update(&ctx, h->offsets, nobj * sizeof(*h->offsets));
 	remain -= nobj * sizeof(*h->offsets);
 	offset += nobj * sizeof(*h->offsets);
 
@@ -297,7 +297,7 @@ got_packidx_init_hdr(struct got_packidx *p, int verify
 		}
 	}
 	if (verify)
-		SHA1Update(&ctx, (uint8_t*)h->large_offsets,
+		got_hash_update(&ctx, h->large_offsets,
 		    p->nlargeobj * sizeof(*h->large_offsets));
 	remain -= p->nlargeobj * sizeof(*h->large_offsets);
 	offset += p->nlargeobj * sizeof(*h->large_offsets);
@@ -325,10 +325,11 @@ checksum:
 		}
 	}
 	if (verify) {
-		SHA1Update(&ctx, h->trailer->packfile_sha1, SHA1_DIGEST_LENGTH);
-		SHA1Final(sha1, &ctx);
-		if (memcmp(h->trailer->packidx_sha1, sha1,
-		    SHA1_DIGEST_LENGTH) != 0)
+		got_hash_update(&ctx, h->trailer->packfile_sha1,
+		    SHA1_DIGEST_LENGTH);
+		got_hash_final(&ctx, hash);
+		if (got_hash_cmp(ctx.algo, hash, h->trailer->packidx_sha1)
+		    != 0)
 			err = got_error(GOT_ERR_PACKIDX_CSUM);
 	}
 done:
blob - da928cb0a1c732e0c7d6f0df0401177528771e3f
blob + 7b9d8ec82cf5ba8c697ed65bfab03a59ac4cabe8
--- lib/pack_create.c
+++ lib/pack_create.c
@@ -48,6 +48,7 @@
 
 #include "got_lib_deltify.h"
 #include "got_lib_delta.h"
+#include "got_lib_hash.h"
 #include "got_lib_object.h"
 #include "got_lib_object_idset.h"
 #include "got_lib_object_cache.h"
@@ -1420,14 +1421,14 @@ done:
 }
 
 static const struct got_error *
-hwrite(int fd, const void *buf, off_t len, SHA1_CTX *ctx)
+hwrite(int fd, const void *buf, off_t len, struct got_hash *ctx)
 {
-	SHA1Update(ctx, buf, len);
+	got_hash_update(ctx, buf, len);
 	return got_poll_write_full(fd, buf, len);
 }
 
 static const struct got_error *
-hcopy(FILE *fsrc, int fd_dst, off_t len, SHA1_CTX *ctx)
+hcopy(FILE *fsrc, int fd_dst, off_t len, struct got_hash *ctx)
 {
 	const struct got_error *err;
 	unsigned char buf[65536];
@@ -1439,7 +1440,7 @@ hcopy(FILE *fsrc, int fd_dst, off_t len, SHA1_CTX *ctx
 		n = fread(buf, 1, copylen, fsrc);
 		if (n != copylen)
 			return got_ferror(fsrc, GOT_ERR_IO);
-		SHA1Update(ctx, buf, copylen);
+		got_hash_update(ctx, buf, copylen);
 		err = got_poll_write_full(fd_dst, buf, copylen);
 		if (err)
 			return err;
@@ -1451,12 +1452,12 @@ hcopy(FILE *fsrc, int fd_dst, off_t len, SHA1_CTX *ctx
 
 static const struct got_error *
 hcopy_mmap(uint8_t *src, off_t src_offset, size_t src_size,
-    int fd, off_t len, SHA1_CTX *ctx)
+    int fd, off_t len, struct got_hash *ctx)
 {
 	if (src_offset + len > src_size)
 		return got_error(GOT_ERR_RANGE);
 
-	SHA1Update(ctx, src + src_offset, len);
+	got_hash_update(ctx, src + src_offset, len);
 	return got_poll_write_full(fd, src + src_offset, len);
 }
 
@@ -1551,8 +1552,8 @@ packoff(char *hdr, off_t off)
 }
 
 static const struct got_error *
-deltahdr(off_t *packfile_size, SHA1_CTX *ctx, int packfd, int force_refdelta,
-    struct got_pack_meta *m)
+deltahdr(off_t *packfile_size, struct got_hash *ctx, int packfd,
+    int force_refdelta, struct got_pack_meta *m)
 {
 	const struct got_error *err;
 	char buf[32];
@@ -1590,7 +1591,7 @@ deltahdr(off_t *packfile_size, SHA1_CTX *ctx, int pack
 static const struct got_error *
 write_packed_object(off_t *packfile_size, int packfd,
     FILE *delta_cache, uint8_t *delta_cache_map, size_t delta_cache_size,
-    struct got_pack_meta *m, int *outfd, SHA1_CTX *ctx,
+    struct got_pack_meta *m, int *outfd, struct got_hash *ctx,
     struct got_repository *repo, int force_refdelta)
 {
 	const struct got_error *err = NULL;
@@ -1600,7 +1601,7 @@ write_packed_object(off_t *packfile_size, int packfd,
 	struct got_raw_object *raw = NULL;
 	off_t outlen, delta_offset;
 
-	csum.output_sha1 = ctx;
+	csum.output_ctx = ctx;
 	csum.output_crc = NULL;
 
 	if (m->reused_delta_offset)
@@ -1694,7 +1695,7 @@ genpack(uint8_t *pack_sha1, int packfd, struct got_pac
 {
 	const struct got_error *err = NULL;
 	int i;
-	SHA1_CTX ctx;
+	struct got_hash ctx;
 	struct got_pack_meta *m;
 	char buf[32];
 	off_t packfile_size = 0;
@@ -1704,7 +1705,7 @@ genpack(uint8_t *pack_sha1, int packfd, struct got_pac
 	size_t delta_cache_size = 0;
 	FILE *packfile = NULL;
 
-	SHA1Init(&ctx);
+	got_hash_init(&ctx, GOT_HASH_SHA1);
 
 #ifndef GOT_PACK_NO_MMAP
 	delta_cache_fd = dup(fileno(delta_cache));
@@ -1785,7 +1786,7 @@ genpack(uint8_t *pack_sha1, int packfd, struct got_pac
 			goto done;
 	}
 
-	SHA1Final(pack_sha1, &ctx);
+	got_hash_final(&ctx, pack_sha1);
 	err = got_poll_write_full(packfd, pack_sha1, SHA1_DIGEST_LENGTH);
 	if (err)
 		goto done;
blob - d7107177f8056953e03aac01278c49f2aee6f81f
blob + 25889d5c1fc15e6c52fd8f251cc2c9c692d0cbcf
--- lib/pack_index.c
+++ lib/pack_index.c
@@ -130,7 +130,7 @@ get_obj_type_label(const char **label, int obj_type)
 }
 
 static const struct got_error *
-read_checksum(uint32_t *crc, SHA1_CTX *sha1_ctx, int fd, size_t len)
+read_checksum(uint32_t *crc, struct got_hash *ctx, int fd, size_t len)
 {
 	uint8_t buf[8192];
 	size_t n;
@@ -144,15 +144,15 @@ read_checksum(uint32_t *crc, SHA1_CTX *sha1_ctx, int f
 			break;
 		if (crc)
 			*crc = crc32(*crc, buf, r);
-		if (sha1_ctx)
-			SHA1Update(sha1_ctx, buf, r);
+		if (ctx)
+			got_hash_update(ctx, buf, r);
 	}
 
 	return NULL;
 }
 
 static const struct got_error *
-read_file_sha1(SHA1_CTX *ctx, FILE *f, size_t len)
+read_file_digest(struct got_hash *ctx, FILE *f, size_t len)
 {
 	uint8_t buf[8192];
 	size_t n, r;
@@ -164,7 +164,7 @@ read_file_sha1(SHA1_CTX *ctx, FILE *f, size_t len)
 				return NULL;
 			return got_ferror(f, GOT_ERR_IO);
 		}
-		SHA1Update(ctx, buf, r);
+		got_hash_update(ctx, buf, r);
 	}
 
 	return NULL;
@@ -172,10 +172,10 @@ read_file_sha1(SHA1_CTX *ctx, FILE *f, size_t len)
 
 static const struct got_error *
 read_packed_object(struct got_pack *pack, struct got_indexed_object *obj,
-    FILE *tmpfile, SHA1_CTX *pack_sha1_ctx)
+    FILE *tmpfile, struct got_hash *pack_sha1_ctx)
 {
 	const struct got_error *err = NULL;
-	SHA1_CTX ctx;
+	struct got_hash ctx;
 	uint8_t *data = NULL;
 	size_t datalen = 0;
 	ssize_t n;
@@ -186,7 +186,7 @@ read_packed_object(struct got_pack *pack, struct got_i
 	struct got_inflate_checksum csum;
 
 	memset(&csum, 0, sizeof(csum));
-	csum.input_sha1 = pack_sha1_ctx;
+	csum.input_ctx = pack_sha1_ctx;
 	csum.input_crc = &obj->crc;
 
 	err = got_pack_parse_object_type_and_size(&obj->type, &obj->size,
@@ -196,7 +196,7 @@ read_packed_object(struct got_pack *pack, struct got_i
 
 	if (pack->map) {
 		obj->crc = crc32(obj->crc, pack->map + mapoff, obj->tslen);
-		SHA1Update(pack_sha1_ctx, pack->map + mapoff, obj->tslen);
+		got_hash_update(pack_sha1_ctx, pack->map + mapoff, obj->tslen);
 		mapoff += obj->tslen;
 	} else {
 		/* XXX Seek back and get the CRC of on-disk type+size bytes. */
@@ -238,7 +238,7 @@ read_packed_object(struct got_pack *pack, struct got_i
 		}
 		if (err)
 			break;
-		SHA1Init(&ctx);
+		got_hash_init(&ctx, GOT_HASH_SHA1);
 		err = get_obj_type_label(&obj_label, obj->type);
 		if (err) {
 			free(data);
@@ -251,17 +251,17 @@ read_packed_object(struct got_pack *pack, struct got_i
 			break;
 		}
 		headerlen = strlen(header) + 1;
-		SHA1Update(&ctx, header, headerlen);
+		got_hash_update(&ctx, header, headerlen);
 		if (obj->size > GOT_DELTA_RESULT_SIZE_CACHED_MAX) {
-			err = read_file_sha1(&ctx, tmpfile, datalen);
+			err = read_file_digest(&ctx, tmpfile, datalen);
 			if (err) {
 				free(header);
 				free(data);
 				break;
 			}
 		} else
-			SHA1Update(&ctx, data, datalen);
-		SHA1Final(obj->id.sha1, &ctx);
+			got_hash_update(&ctx, data, datalen);
+		got_hash_final_object_id(&ctx, &obj->id);
 		free(header);
 		free(data);
 		break;
@@ -282,7 +282,7 @@ read_packed_object(struct got_pack *pack, struct got_i
 			    SHA1_DIGEST_LENGTH);
 			obj->crc = crc32(obj->crc, pack->map + mapoff,
 			    SHA1_DIGEST_LENGTH);
-			SHA1Update(pack_sha1_ctx, pack->map + mapoff,
+			got_hash_update(pack_sha1_ctx, pack->map + mapoff,
 			    SHA1_DIGEST_LENGTH);
 			mapoff += SHA1_DIGEST_LENGTH;
 			err = got_inflate_to_mem_mmap(NULL, &datalen,
@@ -303,8 +303,8 @@ read_packed_object(struct got_pack *pack, struct got_i
 			}
 			obj->crc = crc32(obj->crc, obj->delta.ref.ref_id.sha1,
 			    SHA1_DIGEST_LENGTH);
-			SHA1Update(pack_sha1_ctx, obj->delta.ref.ref_id.sha1,
-			    SHA1_DIGEST_LENGTH);
+			got_hash_update(pack_sha1_ctx,
+			    obj->delta.ref.ref_id.sha1, SHA1_DIGEST_LENGTH);
 			err = got_inflate_to_mem_fd(NULL, &datalen, &obj->len,
 			    &csum, obj->size, pack->fd);
 			if (err)
@@ -337,7 +337,7 @@ read_packed_object(struct got_pack *pack, struct got_i
 
 			obj->crc = crc32(obj->crc, pack->map + mapoff,
 			    obj->delta.ofs.base_offsetlen);
-			SHA1Update(pack_sha1_ctx, pack->map + mapoff,
+			got_hash_update(pack_sha1_ctx, pack->map + mapoff,
 			    obj->delta.ofs.base_offsetlen);
 			mapoff += obj->delta.ofs.base_offsetlen;
 			err = got_inflate_to_mem_mmap(NULL, &datalen,
@@ -376,11 +376,11 @@ read_packed_object(struct got_pack *pack, struct got_i
 }
 
 const struct got_error *
-got_pack_hwrite(int fd, void *buf, int len, SHA1_CTX *ctx)
+got_pack_hwrite(int fd, void *buf, int len, struct got_hash *ctx)
 {
 	ssize_t w;
 
-	SHA1Update(ctx, buf, len);
+	got_hash_update(ctx, buf, len);
 
 	w = write(fd, buf, len);
 	if (w == -1)
@@ -401,7 +401,7 @@ resolve_deltified_object(struct got_pack *pack, struct
 	struct got_delta *delta;
 	uint8_t *buf = NULL;
 	size_t len = 0;
-	SHA1_CTX ctx;
+	struct got_hash ctx;
 	char *header = NULL;
 	size_t headerlen;
 	uint64_t max_size;
@@ -446,15 +446,15 @@ resolve_deltified_object(struct got_pack *pack, struct
 		goto done;
 	}
 	headerlen = strlen(header) + 1;
-	SHA1Init(&ctx);
-	SHA1Update(&ctx, header, headerlen);
+	got_hash_init(&ctx, GOT_HASH_SHA1);
+	got_hash_update(&ctx, header, headerlen);
 	if (max_size > GOT_DELTA_RESULT_SIZE_CACHED_MAX) {
-		err = read_file_sha1(&ctx, tmpfile, len);
+		err = read_file_digest(&ctx, tmpfile, len);
 		if (err)
 			goto done;
 	} else
-		SHA1Update(&ctx, buf, len);
-	SHA1Final(obj->id.sha1, &ctx);
+		got_hash_update(&ctx, buf, len);
+	got_hash_final_object_id(&ctx, &obj->id);
 done:
 	free(buf);
 	free(header);
@@ -639,7 +639,7 @@ got_pack_index(struct got_pack *pack, int idxfd, FILE 
 	char pack_sha1[SHA1_DIGEST_LENGTH];
 	uint32_t nobj, nvalid, nloose, nresolved = 0, i;
 	struct got_indexed_object *objects = NULL, *obj;
-	SHA1_CTX ctx;
+	struct got_hash ctx;
 	uint8_t packidx_hash[SHA1_DIGEST_LENGTH];
 	ssize_t r, w;
 	int pass, have_ref_deltas = 0, first_delta_idx = -1;
@@ -676,8 +676,8 @@ got_pack_index(struct got_pack *pack, int idxfd, FILE 
 		    "bad packfile with zero objects");
 
 	/* We compute the SHA1 of pack file contents and verify later on. */
-	SHA1Init(&ctx);
-	SHA1Update(&ctx, (void *)&hdr, sizeof(hdr));
+	got_hash_init(&ctx, GOT_HASH_SHA1);
+	got_hash_update(&ctx, &hdr, sizeof(hdr));
 
 	/*
 	 * Create an in-memory pack index which will grow as objects
@@ -800,7 +800,7 @@ got_pack_index(struct got_pack *pack, int idxfd, FILE 
 	 * Having done a full pass over the pack file and can now
 	 * verify its checksum.
 	 */
-	SHA1Final(pack_sha1, &ctx);
+	got_hash_final(&ctx, pack_sha1);
 
 	if (memcmp(pack_sha1_expected, pack_sha1, SHA1_DIGEST_LENGTH) != 0) {
 		err = got_error(GOT_ERR_PACKFILE_CSUM);
@@ -935,7 +935,7 @@ got_pack_index(struct got_pack *pack, int idxfd, FILE 
 	free(objects);
 	objects = NULL;
 
-	SHA1Init(&ctx);
+	got_hash_init(&ctx, GOT_HASH_SHA1);
 	putbe32(buf, GOT_PACKIDX_V2_MAGIC);
 	putbe32(buf + 4, GOT_PACKIDX_VERSION);
 	err = got_pack_hwrite(idxfd, buf, 8, &ctx);
@@ -967,7 +967,7 @@ got_pack_index(struct got_pack *pack, int idxfd, FILE 
 	if (err)
 		goto done;
 
-	SHA1Final(packidx_hash, &ctx);
+	got_hash_final(&ctx, packidx_hash);
 	w = write(idxfd, packidx_hash, sizeof(packidx_hash));
 	if (w == -1) {
 		err = got_error_from_errno("write");
blob - 7d0e1dac2141bac1193dc36c27fc80b7cda09259
blob + cb8defa207bb0da2d9fc2ed1c5efbf17d671c6c1
--- libexec/got-fetch-pack/got-fetch-pack.c
+++ libexec/got-fetch-pack/got-fetch-pack.c
@@ -351,14 +351,14 @@ fetch_pack(int fd, int packfd, uint8_t *pack_sha1,
 	struct got_pathlist_entry *pe;
 	int sent_my_capabilites = 0, have_sidebands = 0;
 	int found_branch = 0;
-	SHA1_CTX sha1_ctx;
+	struct got_hash ctx;
 	uint8_t sha1_buf[SHA1_DIGEST_LENGTH];
 	size_t sha1_buf_len = 0;
 	ssize_t w;
 	struct got_ratelimit rl;
 
 	TAILQ_INIT(&symrefs);
-	SHA1Init(&sha1_ctx);
+	got_hash_init(&ctx, GOT_HASH_SHA1);
 	got_ratelimit_init(&rl, 0, 500);
 
 	have = malloc(refsz * sizeof(have[0]));
@@ -762,7 +762,8 @@ fetch_pack(int fd, int packfd, uint8_t *pack_sha1,
 				    sha1_buf_len + r > SHA1_DIGEST_LENGTH) {
 					size_t nshift = MIN(sha1_buf_len + r -
 					    SHA1_DIGEST_LENGTH, sha1_buf_len);
-					SHA1Update(&sha1_ctx, sha1_buf, nshift);
+					got_hash_update(&ctx, sha1_buf,
+					    nshift);
 					memmove(sha1_buf, sha1_buf + nshift,
 					    sha1_buf_len - nshift);
 					sha1_buf_len -= nshift;
@@ -776,7 +777,7 @@ fetch_pack(int fd, int packfd, uint8_t *pack_sha1,
 				 * Mix in previously buffered bytes which
 				 * are not part of the checksum after all.
 				 */
-				SHA1Update(&sha1_ctx, sha1_buf, r);
+				got_hash_update(&ctx, sha1_buf, r);
 
 				/* Update potential checksum buffer. */
 				memmove(sha1_buf, sha1_buf + r,
@@ -785,10 +786,10 @@ fetch_pack(int fd, int packfd, uint8_t *pack_sha1,
 			}
 		} else {
 			/* Mix in any previously buffered bytes. */
-			SHA1Update(&sha1_ctx, sha1_buf, sha1_buf_len);
+			got_hash_update(&ctx, sha1_buf, sha1_buf_len);
 
 			/* Mix in bytes read minus potential checksum bytes. */
-			SHA1Update(&sha1_ctx, buf, r - SHA1_DIGEST_LENGTH);
+			got_hash_update(&ctx, buf, r - SHA1_DIGEST_LENGTH);
 
 			/* Buffer potential checksum bytes. */
 			memcpy(sha1_buf, buf + r - SHA1_DIGEST_LENGTH,
@@ -820,7 +821,7 @@ fetch_pack(int fd, int packfd, uint8_t *pack_sha1,
 	if (err)
 		goto done;
 
-	SHA1Final(pack_sha1, &sha1_ctx);
+	got_hash_final(&ctx, pack_sha1);
 	if (sha1_buf_len != SHA1_DIGEST_LENGTH ||
 	    memcmp(pack_sha1, sha1_buf, sha1_buf_len) != 0) {
 		err = got_error_msg(GOT_ERR_BAD_PACKFILE,
blob - 6211bae909a86681a6c240bb9f1d8e44a471a89d
blob + 8b366057440af8a415007747940c3f85474583a3
--- libexec/got-index-pack/got-index-pack.c
+++ libexec/got-index-pack/got-index-pack.c
@@ -36,6 +36,7 @@
 
 #include "got_lib_delta.h"
 #include "got_lib_delta_cache.h"
+#include "got_lib_hash.h"
 #include "got_lib_object.h"
 #include "got_lib_privsep.h"
 #include "got_lib_ratelimit.h"
blob - ed8291ef577fe09d4957c03653a00c031b0cb0dd
blob + e4c92bbc9d32142b0790c085ca4e39a36991795e
--- libexec/got-read-blob/got-read-blob.c
+++ libexec/got-read-blob/got-read-blob.c
@@ -35,6 +35,7 @@
 #include "got_object.h"
 
 #include "got_lib_delta.h"
+#include "got_lib_hash.h"
 #include "got_lib_inflate.h"
 #include "got_lib_object.h"
 #include "got_lib_object_parse.h"
@@ -77,11 +78,11 @@ main(int argc, char *argv[])
 		struct got_object_id id;
 		struct got_object_id expected_id;
 		struct got_inflate_checksum csum;
-		SHA1_CTX sha1_ctx;
+		struct got_hash ctx;
 
-		SHA1Init(&sha1_ctx);
+		got_hash_init(&ctx, GOT_HASH_SHA1);
 		memset(&csum, 0, sizeof(csum));
-		csum.output_sha1 = &sha1_ctx;
+		csum.output_ctx = &ctx;
 
 		memset(&imsg, 0, sizeof(imsg));
 		imsg.fd = -1;
@@ -170,7 +171,7 @@ main(int argc, char *argv[])
 			if (err)
 				goto done;
 		}
-		SHA1Final(id.sha1, &sha1_ctx);
+		got_hash_final_object_id(&ctx, &id);
 		if (got_object_id_cmp(&expected_id, &id) != 0) {
 			err = got_error_checksum(&expected_id);
 			goto done;