Commit Diff


commit - 6583092f7f08b82a9004b2cb84625d3a74f6add6
commit + a1f06df2e1e5a293a55ebaf1b6707de629843295
blob - 4bb7ecf2163c2d7807d4697feab533b7c1e26e1a
blob + ad55ae60228e6f5628adae6d65087eb9de3ef68e
--- lib/got_lib_object_parse.h
+++ lib/got_lib_object_parse.h
@@ -37,14 +37,15 @@ struct got_parsed_tree_entry {
 	size_t namelen; /* strlen(name) */
 	mode_t mode; /* Mode parsed from tree buffer. */
 	uint8_t *id; /* Points to ID in parsed tree buffer. */
+	size_t idlen;
 };
 const struct got_error *got_object_parse_tree(struct got_parsed_tree_entry **,
-    size_t *, size_t *, uint8_t *, size_t);
+    size_t *, size_t *, uint8_t *, size_t, int);
 const struct got_error *got_object_read_tree(struct got_parsed_tree_entry **,
     size_t *, size_t *, uint8_t **, int, struct got_object_id *);
 
 const struct got_error *got_object_parse_tag(struct got_tag_object **,
-    uint8_t *, size_t);
+    uint8_t *, size_t, int);
 const struct got_error *got_object_read_tag(struct got_tag_object **, int,
     struct got_object_id *, size_t);
 const struct got_error *got_read_file_to_mem(uint8_t **, size_t *, FILE *);
blob - 1b4b7bc8fc2baddfd1f3353725f35bd6ac9af0cf
blob + 47d4a6408bd84242ec7ee5ee332f7379c9893a74
--- lib/got_lib_privsep.h
+++ lib/got_lib_privsep.h
@@ -256,7 +256,8 @@ struct got_imsg_commit_object {
 } __attribute__((__packed__));
 
 struct got_imsg_tree_entry {
-	char id[SHA1_DIGEST_LENGTH];
+	char id[SHA256_DIGEST_LENGTH];
+	int algo;
 	mode_t mode;
 	size_t namelen;
 	/* Followed by namelen bytes of entry's name, not NUL-terminated. */
blob - 0e0092a04fcb2d9a40bcfacc9cfbd86fc7d919cb
blob + 74cd39adeed51e4d24a86b74d1072ef84947a588
--- lib/object_parse.c
+++ lib/object_parse.c
@@ -297,18 +297,26 @@ 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 sha256[SHA256_DIGEST_LENGTH];
+	SHA2_CTX sha256_ctx;
 	uint8_t sha1[SHA1_DIGEST_LENGTH];
 	SHA1_CTX sha1_ctx;
 	size_t len, consumed;
 	FILE *f = NULL;
+	int r;
 
 	*outbuf = NULL;
 	*size = 0;
 	*hdrlen = 0;
 
-	SHA1Init(&sha1_ctx);
-	memset(&csum, 0, sizeof(csum));
-	csum.output_sha1 = &sha1_ctx;
+	memset(&csum, 0, sizeof(csum));
+	if (expected_id->algo == GOT_HASH_SHA256) {
+		SHA256Init(&sha256_ctx);
+		csum.output_sha256 = &sha256_ctx;
+	} else {
+		SHA1Init(&sha1_ctx);
+		csum.output_sha1 = &sha1_ctx;
+	}
 
 	if (lseek(infd, SEEK_SET, 0) == -1)
 		return got_error_from_errno("lseek");
@@ -349,8 +357,15 @@ got_object_read_raw(uint8_t **outbuf, off_t *size, siz
 		goto done;
 	}
 
-	SHA1Final(sha1, &sha1_ctx);
-	if (memcmp(expected_id->hash, sha1, SHA1_DIGEST_LENGTH) != 0) {
+	if (expected_id->algo == GOT_HASH_SHA256) {
+		SHA256Final(sha256, &sha256_ctx);
+		r = memcmp(expected_id->hash, sha256, sizeof(sha256));
+	} else {
+		SHA1Final(sha1, &sha1_ctx);
+		r = memcmp(expected_id->hash, sha1, sizeof(sha1));
+	}
+
+	if (r != 0) {
 		err = got_error_checksum(expected_id);
 		goto done;
 	}
@@ -658,6 +673,7 @@ got_object_parse_commit(struct got_commit_object **com
 			err = got_error(GOT_ERR_BAD_OBJ_DATA);
 			goto done;
 		}
+		(*commit)->tree_id->algo = algo;
 		remain -= digest_strlen;
 		s += digest_strlen;
 	} else {
@@ -833,7 +849,7 @@ got_object_tree_close(struct got_tree_object *tree)
 
 static const struct got_error *
 parse_tree_entry(struct got_parsed_tree_entry *pte, size_t *elen, char *buf,
-    size_t maxlen)
+    size_t maxlen, size_t idlen)
 {
 	char *p, *space;
 
@@ -857,14 +873,15 @@ parse_tree_entry(struct got_parsed_tree_entry *pte, si
 		p++;
 	}
 
-	if (*elen > maxlen || maxlen - *elen < SHA1_DIGEST_LENGTH)
+	if (*elen > maxlen || maxlen - *elen < idlen)
 		return got_error(GOT_ERR_BAD_OBJ_DATA);
 
 	pte->name = space + 1;
 	pte->namelen = strlen(pte->name);
 	buf += *elen;
 	pte->id = buf;
-	*elen += SHA1_DIGEST_LENGTH;
+	pte->idlen = idlen;
+	*elen += idlen;
 	return NULL;
 }
 
@@ -878,14 +895,18 @@ pte_cmp(const void *pa, const void *pb)
 
 const struct got_error *
 got_object_parse_tree(struct got_parsed_tree_entry **entries, size_t *nentries,
-    size_t *nentries_alloc, uint8_t *buf, size_t len)
+    size_t *nentries_alloc, uint8_t *buf, size_t len, int algo)
 {
 	const struct got_error *err = NULL;
 	size_t remain = len;
 	const size_t nalloc = 16;
 	struct got_parsed_tree_entry *pte;
+	size_t idlen = SHA256_DIGEST_LENGTH;
 	int i;
 
+	if (algo != GOT_HASH_SHA256)
+		idlen = SHA1_DIGEST_LENGTH;
+
 	*nentries = 0;
 	if (remain == 0)
 		return NULL; /* tree is empty */
@@ -905,7 +926,7 @@ got_object_parse_tree(struct got_parsed_tree_entry **e
 		}
 
 		pte = &(*entries)[*nentries];
-		err = parse_tree_entry(pte, &elen, buf, remain);
+		err = parse_tree_entry(pte, &elen, buf, remain, idlen);
 		if (err)
 			goto done;
 		buf += elen;
@@ -946,18 +967,28 @@ got_object_read_tree(struct got_parsed_tree_entry **en
 	struct got_object *obj = NULL;
 	size_t len;
 	struct got_inflate_checksum csum;
+	SHA2_CTX sha256_ctx;
 	SHA1_CTX sha1_ctx;
 	struct got_object_id id;
 
-	SHA1Init(&sha1_ctx);
 	memset(&csum, 0, sizeof(csum));
-	csum.output_sha1 = &sha1_ctx;
+	id.algo = expected_id->algo;
+	if (expected_id->algo == GOT_HASH_SHA256) {
+		SHA256Init(&sha256_ctx);
+		csum.output_sha256 = &sha256_ctx;
+	} else {
+		SHA1Init(&sha1_ctx);
+		csum.output_sha1 = &sha1_ctx;
+	}
 
 	err = got_inflate_to_mem_fd(p, &len, NULL, &csum, 0, fd);
 	if (err)
 		return err;
 
-	SHA1Final(id.hash, &sha1_ctx);
+	if (expected_id->algo == GOT_HASH_SHA256)
+		SHA256Final(id.hash, &sha256_ctx);
+	else
+		SHA1Final(id.hash, &sha1_ctx);
 	if (got_object_id_cmp(expected_id, &id) != 0) {
 		err = got_error_checksum(expected_id);
 		goto done;
@@ -975,7 +1006,7 @@ got_object_read_tree(struct got_parsed_tree_entry **en
 	/* Skip object header. */
 	len -= obj->hdrlen;
 	err = got_object_parse_tree(entries, nentries, nentries_alloc,
-	    *p + obj->hdrlen, len);
+	    *p + obj->hdrlen, len, expected_id->algo);
 done:
 	if (obj)
 		got_object_close(obj);
@@ -998,13 +1029,17 @@ got_object_tag_close(struct got_tag_object *tag)
 }
 
 const struct got_error *
-got_object_parse_tag(struct got_tag_object **tag, uint8_t *buf, size_t len)
+got_object_parse_tag(struct got_tag_object **tag, uint8_t *buf, size_t len,
+    int algo)
 {
 	const struct got_error *err = NULL;
 	size_t remain = len;
 	char *s = buf;
-	size_t label_len;
+	size_t label_len, digest_strlen = SHA256_DIGEST_STRING_LENGTH;
 
+	if (algo != GOT_HASH_SHA256)
+		digest_strlen = SHA1_DIGEST_STRING_LENGTH;
+
 	if (remain == 0)
 		return got_error(GOT_ERR_BAD_OBJ_DATA);
 
@@ -1015,17 +1050,18 @@ got_object_parse_tag(struct got_tag_object **tag, uint
 	label_len = strlen(GOT_TAG_LABEL_OBJECT);
 	if (strncmp(s, GOT_TAG_LABEL_OBJECT, label_len) == 0) {
 		remain -= label_len;
-		if (remain < SHA1_DIGEST_STRING_LENGTH) {
+		if (remain < digest_strlen) {
 			err = got_error(GOT_ERR_BAD_OBJ_DATA);
 			goto done;
 		}
 		s += label_len;
-		if (!got_parse_sha1_digest((*tag)->id.hash, s)) {
+		if (!got_parse_hash_digest((*tag)->id.hash, s, algo, NULL)) {
 			err = got_error(GOT_ERR_BAD_OBJ_DATA);
 			goto done;
 		}
-		remain -= SHA1_DIGEST_STRING_LENGTH;
-		s += SHA1_DIGEST_STRING_LENGTH;
+		(*tag)->id.algo = algo;
+		remain -= digest_strlen;
+		s += digest_strlen;
 	} else {
 		err = got_error(GOT_ERR_BAD_OBJ_DATA);
 		goto done;
@@ -1185,19 +1221,29 @@ got_object_read_tag(struct got_tag_object **tag, int f
 	size_t len;
 	uint8_t *p;
 	struct got_inflate_checksum csum;
+	SHA2_CTX sha256_ctx;
 	SHA1_CTX sha1_ctx;
 	struct got_object_id id;
 
-	SHA1Init(&sha1_ctx);
 	memset(&csum, 0, sizeof(csum));
-	csum.output_sha1 = &sha1_ctx;
+	id.algo = expected_id->algo;
+	if (expected_id->algo == GOT_HASH_SHA256) {
+		SHA256Init(&sha256_ctx);
+		csum.output_sha256 = &sha256_ctx;
+	} else {
+		SHA1Init(&sha1_ctx);
+		csum.output_sha1 = &sha1_ctx;
+	}
 
 	err = got_inflate_to_mem_fd(&p, &len, NULL, &csum,
 	    expected_size, fd);
 	if (err)
 		return err;
 
-	SHA1Final(id.hash, &sha1_ctx);
+	if (expected_id->algo == GOT_HASH_SHA256)
+		SHA256Final(id.hash, &sha256_ctx);
+	else
+		SHA1Final(id.hash, &sha1_ctx);
 	if (got_object_id_cmp(expected_id, &id) != 0) {
 		err = got_error_checksum(expected_id);
 		goto done;
@@ -1214,7 +1260,7 @@ got_object_read_tag(struct got_tag_object **tag, int f
 
 	/* Skip object header. */
 	len -= obj->hdrlen;
-	err = got_object_parse_tag(tag, p + obj->hdrlen, len);
+	err = got_object_parse_tag(tag, p + obj->hdrlen, len, expected_id->algo);
 done:
 	free(p);
 	if (obj)
blob - aaa7df19451129acb5dbcfbda0fa6a8a6a9a3ed6
blob + 88d46c62a322e8a2c03c181310e5a4c500fa2e1d
--- lib/privsep.c
+++ lib/privsep.c
@@ -1405,17 +1405,27 @@ send_tree_entries_batch(struct imsgbuf *ibuf,
 		return got_error_from_errno("imsg_add TREE_ENTRY");
 
 	for (i = idx0; i <= idxN; i++) {
+		static const char gap[12]; /* for sha1-inside-sha256 alignment */
 		struct got_parsed_tree_entry *pte = &entries[i];
+		int algo = GOT_HASH_SHA256;
 
-		/* Keep in sync with struct got_imsg_tree_entry definition! */
-		if (imsg_add(wbuf, pte->id, SHA1_DIGEST_LENGTH) == -1)
+		if (pte->idlen != SHA256_DIGEST_LENGTH)
+			algo = GOT_HASH_SHA1;
+
+		/* Keep in sync with struct got_imsg_tree_entry definition! */
+		if (imsg_add(wbuf, pte->id, pte->idlen) == -1)
 			return got_error_from_errno("imsg_add TREE_ENTRY");
+		if (pte->idlen != SHA256_DIGEST_LENGTH &&
+		    imsg_add(wbuf, gap, sizeof(gap)) == -1)
+			return got_error_from_errno("imsg_add TREE_ENTRY");
+		if (imsg_add(wbuf, &algo, sizeof(algo)) == -1)
+			return got_error_from_errno("imsg_add TREE_ENTRY");
 		if (imsg_add(wbuf, &pte->mode, sizeof(pte->mode)) == -1)
 			return got_error_from_errno("imsg_add TREE_ENTRY");
 		if (imsg_add(wbuf, &pte->namelen, sizeof(pte->namelen)) == -1)
 			return got_error_from_errno("imsg_add TREE_ENTRY");
 
-		/* Remaining bytes are the entry's name. */
+		/* Remaining bytes are the id and entry's name. */
 		if (imsg_add(wbuf, pte->name, pte->namelen) == -1)
 			return got_error_from_errno("imsg_add TREE_ENTRY");
 	}
@@ -1436,7 +1446,7 @@ send_tree_entries(struct imsgbuf *ibuf, struct got_par
 	i = 0;
 	for (j = 0; j < nentries; j++) {
 		struct got_parsed_tree_entry *pte = &entries[j];
-		size_t len = SHA1_DIGEST_LENGTH + sizeof(pte->mode) +
+		size_t len = SHA256_DIGEST_LENGTH + sizeof(pte->mode) +
 		    sizeof(pte->namelen) + pte->namelen;
 
 		if (j > 0 &&
@@ -1534,7 +1544,8 @@ recv_tree_entries(void *data, size_t datalen, struct g
 		te_name = buf + sizeof(ite);
 		memcpy(te->name, te_name, ite.namelen);
 		te->name[ite.namelen] = '\0';
-		memcpy(te->id.hash, ite.id, SHA1_DIGEST_LENGTH);
+		memcpy(te->id.hash, ite.id, sizeof(te->id.hash));
+		te->id.algo = ite.algo;
 		te->mode = ite.mode;
 		te->idx = *nentries;
 		(*nentries)++;
blob - d277332c05168baa15e867e91596533533345bb1
blob + 0861f8c76416b827bb112dd92d105552bd74a8fe
--- libexec/got-read-blob/got-read-blob.c
+++ libexec/got-read-blob/got-read-blob.c
@@ -77,12 +77,9 @@ main(int argc, char *argv[])
 		struct got_object_id id;
 		struct got_object_id expected_id;
 		struct got_inflate_checksum csum;
+		SHA2_CTX sha256_ctx;
 		SHA1_CTX sha1_ctx;
 
-		SHA1Init(&sha1_ctx);
-		memset(&csum, 0, sizeof(csum));
-		csum.output_sha1 = &sha1_ctx;
-
 		memset(&imsg, 0, sizeof(imsg));
 		imsg.fd = -1;
 		memset(&imsg_outfd, 0, sizeof(imsg_outfd));
@@ -145,6 +142,16 @@ main(int argc, char *argv[])
 			goto done;
 		}
 
+		memset(&csum, 0, sizeof(csum));
+		id.algo = expected_id.algo;
+		if (expected_id.algo == GOT_HASH_SHA256) {
+			SHA256Init(&sha256_ctx);
+			csum.output_sha256 = &sha256_ctx;
+		} else {
+			SHA1Init(&sha1_ctx);
+			csum.output_sha1 = &sha1_ctx;
+		}
+
 		err = got_object_read_header(&obj, imsg.fd);
 		if (err)
 			goto done;
@@ -170,7 +177,10 @@ main(int argc, char *argv[])
 			if (err)
 				goto done;
 		}
-		SHA1Final(id.hash, &sha1_ctx);
+		if (expected_id.algo == GOT_HASH_SHA256)
+			SHA256Final(id.hash, &sha256_ctx);
+		else
+			SHA1Final(id.hash, &sha1_ctx);
 		if (got_object_id_cmp(&expected_id, &id) != 0) {
 			err = got_error_checksum(&expected_id);
 			goto done;
blob - a7bc1b886b3ad07fbe8c6c1b889b4c23b1c07c28
blob + fa7e848b2a4b1ace5b5ac7c12b5d44e8474b980b
--- libexec/got-read-pack/got-read-pack.c
+++ libexec/got-read-pack/got-read-pack.c
@@ -212,7 +212,7 @@ open_tree(uint8_t **buf, struct got_parsed_tree_entry 
 	obj->size = len;
 
 	err = got_object_parse_tree(entries, nentries, nentries_alloc,
-	    *buf, len);
+	    *buf, len, id->algo);
 done:
 	got_object_close(obj);
 	if (err) {
@@ -411,7 +411,7 @@ tag_request(struct imsg *imsg, struct imsgbuf *ibuf, s
 		goto done;
 
 	obj->size = len;
-	err = got_object_parse_tag(&tag, buf, len);
+	err = got_object_parse_tag(&tag, buf, len, GOT_HASH_SHA1);
 	if (err)
 		goto done;
 
@@ -1437,7 +1437,7 @@ enumeration_request(struct imsg *imsg, struct imsgbuf 
 			if (err)
 				goto done;
 			obj->size = len;
-			err = got_object_parse_tag(&tag, buf, len);
+			err = got_object_parse_tag(&tag, buf, len, GOT_HASH_SHA1);
 			if (err) {
 				free(buf);
 				goto done;