Commit Diff


commit - 07a3a9fbc1d4396ffb64e0f0f59ec5bedfe0f545
commit + b16893ba284e90739fc814673523878e8874dc0f
blob - 319a93427d3f3e03ba19eef16c6c192b1160b7d8
blob + cdb5886454811ffbd3a3d913fded89b8bc22c738
--- gotd/repo_write.c
+++ gotd/repo_write.c
@@ -42,6 +42,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"
@@ -50,8 +51,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"
@@ -478,7 +477,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;
@@ -527,7 +526,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;
@@ -550,7 +549,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;
@@ -597,7 +596,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;
@@ -701,7 +700,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;
@@ -715,7 +714,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)
@@ -789,7 +788,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 - 4ba630b800dab6a323fdb7c5e2d6927c17956784
blob + fda3b7bb4c3102bedbed38b3065acde113eeb9a3
--- lib/deflate.c
+++ lib/deflate.c
@@ -28,6 +28,7 @@
 #include "got_path.h"
 
 #include "got_lib_deflate.h"
+#include "got_lib_hash.h"
 #include "got_lib_poll.h"
 
 #ifndef MIN
@@ -87,6 +88,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 - 9ce4aae5c7623e71a333b7d3ad82e754ffc46af3
blob + 1af66814fbade7825956cd89bee32c1d37572390
--- lib/fileindex.c
+++ lib/fileindex.c
@@ -32,6 +32,7 @@
 #include "got_object.h"
 #include "got_path.h"
 
+#include "got_lib_hash.h"
 #include "got_lib_fileindex.h"
 #include "got_lib_worktree.h"
 
@@ -352,12 +353,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);
@@ -365,12 +366,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);
@@ -378,12 +379,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);
@@ -391,7 +392,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 };
@@ -402,11 +403,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);
@@ -414,7 +415,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;
@@ -448,12 +449,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);
@@ -469,7 +470,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)
@@ -484,20 +485,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);
@@ -521,9 +522,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)
@@ -533,46 +534,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;
@@ -597,7 +598,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);
 
@@ -609,7 +610,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;
@@ -654,14 +655,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)
@@ -681,7 +682,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. */
@@ -701,14 +703,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)) {
@@ -729,9 +731,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);
@@ -754,7 +756,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 - c53fbbe58dae6a5d9e1e0e25106398709945c8db
blob + 5906f438cafc3808c3de15f60410dc0e4c3361cd
--- 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 - 9440011aed7234a7fffaed90fe2fb8b55fb0d2c9
blob + 7bbc9fd91dda8ec3420c22d048349828595e8b74
--- lib/inflate.c
+++ lib/inflate.c
@@ -29,6 +29,7 @@
 #include "got_object.h"
 #include "got_path.h"
 
+#include "got_lib_hash.h"
 #include "got_lib_inflate.h"
 #include "got_lib_poll.h"
 
@@ -92,6 +93,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
@@ -102,6 +106,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 - 3458a76c9475cc94b6aff79ea705d763984f159c
blob + c32445b4ccf86a89d33fd154fc5385b75914045d
--- 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 - c18378157f7335d09333043c3626ca7abbaa6092
blob + 6d050459574522d3b15ab4d56ebd14f4c5c2bf9c
--- lib/object_parse.c
+++ lib/object_parse.c
@@ -288,8 +288,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;
 
@@ -297,9 +297,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");
@@ -340,8 +340,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;
 	}
@@ -749,18 +749,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;
@@ -918,18 +918,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;
@@ -1158,19 +1158,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 - badb1b9dab4157a1df6f5314839f5c04d90ecbbc
blob + f0189ff480b44a73b0aa170458502a0c0deb3cd7
--- lib/pack.c
+++ lib/pack.c
@@ -70,14 +70,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;
@@ -112,7 +113,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);
@@ -143,7 +144,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;
@@ -172,7 +173,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;
 
@@ -200,7 +201,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;
 
@@ -225,7 +226,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);
 
@@ -250,8 +251,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);
 
@@ -293,7 +293,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);
@@ -321,10 +321,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 - 1d2bcd07b13eee0369a1fdd6bcd48e349cd744b2
blob + 9133b40383747d7fbabbf59b4dee0ff47cba156b
--- lib/pack_create.c
+++ lib/pack_create.c
@@ -47,6 +47,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"
@@ -1419,14 +1420,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];
@@ -1438,7 +1439,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;
@@ -1450,12 +1451,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);
 }
 
@@ -1550,8 +1551,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];
@@ -1589,7 +1590,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;
@@ -1599,7 +1600,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)
@@ -1693,7 +1694,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;
@@ -1703,7 +1704,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));
@@ -1784,7 +1785,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 - f596b8a839599caa2fb067402972de5dc629277b
blob + 5725bb0739ba291cf44b381849e3978306776011
--- lib/pack_index.c
+++ lib/pack_index.c
@@ -127,7 +127,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;
@@ -141,15 +141,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;
@@ -161,7 +161,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;
@@ -169,10 +169,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;
@@ -183,7 +183,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,
@@ -193,7 +193,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. */
@@ -235,7 +235,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);
@@ -248,17 +248,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;
@@ -279,7 +279,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,
@@ -300,8 +300,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)
@@ -334,7 +334,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,
@@ -373,11 +373,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)
@@ -398,7 +398,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;
@@ -443,15 +443,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);
@@ -636,7 +636,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;
@@ -673,8 +673,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
@@ -797,7 +797,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);
@@ -932,7 +932,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);
@@ -964,7 +964,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 - 002c66e8605f11fc36aee7b6b641538953bc6a13
blob + 63dce0af78fc0d4bad7b4c00ac61e3e82e915df7
--- libexec/got-fetch-pack/got-fetch-pack.c
+++ libexec/got-fetch-pack/got-fetch-pack.c
@@ -350,14 +350,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]));
@@ -761,7 +761,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;
@@ -775,7 +776,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,
@@ -784,10 +785,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,
@@ -819,7 +820,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 - a7606b8b2937a303d4d0f298209c1dabd9bb721b
blob + 38cdb5cd39d08a91da9319b72a9899f0f569cb01
--- libexec/got-index-pack/got-index-pack.c
+++ libexec/got-index-pack/got-index-pack.c
@@ -34,6 +34,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 - 278ffbba28800315d824bf942dd2a401bd045cb6
blob + 1b8716f656c76d4d70c14bbcc33c627b7d30b3ce
--- libexec/got-read-blob/got-read-blob.c
+++ libexec/got-read-blob/got-read-blob.c
@@ -34,6 +34,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"
@@ -88,11 +89,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;
@@ -181,7 +182,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;