"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Omar Polo <op@omarpolo.com>
Subject:
provide functions to parse/serialize different hashes
To:
gameoftrees@openbsd.org
Date:
Thu, 23 Feb 2023 10:26:35 +0100

Download raw body.

Thread
Hello,

This adds an alternative set of functions to deal with sha256 hash
digest that behaves like the sha1 ones we already have.  On top of
these there's a generic got_parse_hash_digest() that uses the hash
algorithm specified as argument.  Finally, to prevent future breakage,
this adds got_parse_object_id() that fills the struct got_object_id.
The memset() is important: in the future I'd like to grow it with a
field, and the explicit zeroing will prevent breakages due to
un-initialized fields (we have many object ids lying on the stack.)

Finally, I'm also replacing almost all got_parse_sha1_digest() calls,
only a few in gotd and one in got-read-patch remains.  The various
enum got_hash_algorithm introduced in various places will be soon
bubbled up and disappear soon-ish.

ok?

diff /home/op/w/got
commit - 53bf0b541977b66862040d4b633fb6b5d3a3c6c8
path + /home/op/w/got
blob - 6a161bc20df5aaa7789395593ab2ffc6fbe4b1fb
file + include/got_object.h
--- include/got_object.h
+++ include/got_object.h
@@ -16,6 +16,11 @@ struct got_object_id {
 
 #define GOT_OBJECT_ID_HEX_MAXLEN SHA1_DIGEST_STRING_LENGTH
 
+enum got_hash_algorithm {
+	GOT_HASH_SHA1,
+	GOT_HASH_SHA256,
+};
+
 struct got_object_id {
 	u_int8_t sha1[SHA1_DIGEST_LENGTH];
 };
blob - 141cb2590fa14834c63381929a0a7438ae3e4556
file + lib/got_lib_hash.h
--- lib/got_lib_hash.h
+++ lib/got_lib_hash.h
@@ -15,7 +15,16 @@
  */
 
 #define GOT_SHA1_STRING_ZERO "0000000000000000000000000000000000000000"
+#define GOT_SHA256_STRING_ZERO "0000000000000000000000000000000000000000000000000000000000000000"
 
 int got_parse_xdigit(uint8_t *, const char *);
+
 int got_parse_sha1_digest(uint8_t *, const char *);
 char *got_sha1_digest_to_str(const uint8_t *, char *, size_t);
+
+int got_parse_sha256_digest(uint8_t *, const char *);
+char *got_sha256_digest_to_str(const uint8_t *, char *, size_t);
+
+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);
blob - fb4d3a30adf9281507aea3424f4c2711b1d3a28c
file + lib/hash.c
--- lib/hash.c
+++ lib/hash.c
@@ -15,13 +15,18 @@
  */
 
 #include <sys/types.h>
+#include <sys/queue.h>
+
 #include <sha1.h>
 #include <sha2.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <limits.h>
 
+#include "got_object.h"
+
 #include "got_lib_hash.h"
 
 int
@@ -83,3 +88,73 @@ got_sha1_digest_to_str(const uint8_t *digest, char *bu
 
 	return buf;
 }
+
+int
+got_parse_sha256_digest(uint8_t *digest, const char *line)
+{
+	uint8_t b = 0;
+	char hex[3] = {'\0', '\0', '\0'};
+	int i, j;
+
+	for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
+		if (line[0] == '\0' || line[1] == '\0')
+			return 0;
+		for (j = 0; j < 2; j++) {
+			hex[j] = *line;
+			line++;
+		}
+		if (!got_parse_xdigit(&b, hex))
+			return 0;
+		digest[i] = b;
+	}
+
+	return 1;
+}
+
+char *
+got_sha256_digest_to_str(const uint8_t *digest, char *buf, size_t size)
+{
+	char *p = buf;
+	char hex[3];
+	int i;
+
+	if (size < SHA256_DIGEST_STRING_LENGTH)
+		return NULL;
+
+	for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
+		snprintf(hex, sizeof(hex), "%.2x", digest[i]);
+		p[0] = hex[0];
+		p[1] = hex[1];
+		p += 2;
+	}
+	p[0] = '\0';
+
+	return buf;
+}
+
+int
+got_parse_hash_digest(uint8_t *digest, const char *line,
+    enum got_hash_algorithm algo)
+{
+	switch (algo) {
+	case GOT_HASH_SHA1:
+		return got_parse_sha1_digest(digest, line);
+	case GOT_HASH_SHA256:
+		return got_parse_sha256_digest(digest, line);
+	default:
+		return 0;
+	}
+}
+
+int
+got_parse_object_id(struct got_object_id *id, const char *line,
+    enum got_hash_algorithm algo)
+{
+	memset(id, 0, sizeof(*id));
+
+	/* XXX: temporary until we grow got_object_id */
+	if (algo != GOT_HASH_SHA1)
+		return 0;
+
+	return got_parse_hash_digest(id->sha1, line, algo);
+}
blob - f8b902a4c27338568c455eb639ecba5cbb38b8c2
file + lib/object.c
--- lib/object.c
+++ lib/object.c
@@ -151,7 +151,7 @@ got_object_open_by_id_str(struct got_object **obj, str
 {
 	struct got_object_id id;
 
-	if (!got_parse_sha1_digest(id.sha1, id_str))
+	if (!got_parse_object_id(&id, id_str, GOT_HASH_SHA1))
 		return got_error_path(id_str, GOT_ERR_BAD_OBJ_ID_STR);
 
 	return got_object_open(obj, repo, &id);
blob - 67c3bc37ea78571d6f3c25478ae3e612ee235f22
file + lib/object_parse.c
--- lib/object_parse.c
+++ lib/object_parse.c
@@ -387,7 +387,7 @@ got_object_commit_add_parent(struct got_commit_object 
 	if (err)
 		return err;
 
-	if (!got_parse_sha1_digest(qid->id.sha1, id_str)) {
+	if (!got_parse_object_id(&qid->id, id_str, GOT_HASH_SHA1)) {
 		err = got_error(GOT_ERR_BAD_OBJ_DATA);
 		got_object_qid_free(qid);
 		return err;
@@ -620,6 +620,7 @@ got_object_parse_commit(struct got_commit_object **com
     size_t len)
 {
 	const struct got_error *err = NULL;
+	enum got_hash_algorithm algo = GOT_HASH_SHA1;
 	char *s = buf;
 	size_t label_len;
 	ssize_t remain = (ssize_t)len;
@@ -639,7 +640,7 @@ got_object_parse_commit(struct got_commit_object **com
 			goto done;
 		}
 		s += label_len;
-		if (!got_parse_sha1_digest((*commit)->tree_id->sha1, s)) {
+		if (!got_parse_object_id((*commit)->tree_id, s, algo)) {
 			err = got_error(GOT_ERR_BAD_OBJ_DATA);
 			goto done;
 		}
@@ -974,6 +975,7 @@ got_object_parse_tag(struct got_tag_object **tag, uint
 got_object_parse_tag(struct got_tag_object **tag, uint8_t *buf, size_t len)
 {
 	const struct got_error *err = NULL;
+	enum got_hash_algorithm algo = GOT_HASH_SHA1;
 	size_t remain = len;
 	char *s = buf;
 	size_t label_len;
@@ -993,7 +995,7 @@ got_object_parse_tag(struct got_tag_object **tag, uint
 			goto done;
 		}
 		s += label_len;
-		if (!got_parse_sha1_digest((*tag)->id.sha1, s)) {
+		if (!got_parse_object_id(&(*tag)->id, s, algo)) {
 			err = got_error(GOT_ERR_BAD_OBJ_DATA);
 			goto done;
 		}
blob - 92514335bde2a392e0211cb8f5903c931aac55d2
file + lib/patch.c
--- lib/patch.c
+++ lib/patch.c
@@ -706,7 +706,7 @@ open_blob(char **path, FILE **fp, const char *blobid,
 			return err;
 		idptr = matched_id;
 	} else {
-		if (!got_parse_sha1_digest(id.sha1, blobid))
+		if (!got_parse_object_id(&id, blobid, GOT_HASH_SHA1))
 			return got_error(GOT_ERR_BAD_OBJ_ID_STR);
 		idptr = &id;
 	}
blob - b7e19bcfc7a34cea70cf48a5c32ab66ee4acb857
file + lib/reference.c
--- lib/reference.c
+++ lib/reference.c
@@ -155,6 +155,7 @@ parse_ref_line(struct got_reference **ref, const char 
 parse_ref_line(struct got_reference **ref, const char *name, const char *line,
     time_t mtime)
 {
+	enum got_hash_algorithm algo = GOT_HASH_SHA1;
 	struct got_object_id id;
 
 	if (strncmp(line, "ref: ", 5) == 0) {
@@ -162,7 +163,7 @@ parse_ref_line(struct got_reference **ref, const char 
 		return parse_symref(ref, name, line);
 	}
 
-	if (!got_parse_sha1_digest(id.sha1, line))
+	if (!got_parse_object_id(&id, line, algo))
 		return got_error(GOT_ERR_BAD_REF_DATA);
 
 	return alloc_ref(ref, name, &id, 0, mtime);
@@ -292,6 +293,7 @@ parse_packed_ref_line(struct got_reference **ref, cons
 parse_packed_ref_line(struct got_reference **ref, const char *abs_refname,
     const char *line, time_t mtime)
 {
+	enum got_hash_algorithm algo = GOT_HASH_SHA1;
 	struct got_object_id id;
 	const char *name;
 
@@ -300,7 +302,7 @@ parse_packed_ref_line(struct got_reference **ref, cons
 	if (line[0] == '#' || line[0] == '^')
 		return NULL;
 
-	if (!got_parse_sha1_digest(id.sha1, line))
+	if (!got_parse_object_id(&id, line, algo))
 		return got_error(GOT_ERR_BAD_REF_DATA);
 
 	if (abs_refname) {
blob - abff91e2c234cdd1c87f05d07d2a9d02a0cc98e4
file + lib/repository.c
--- lib/repository.c
+++ lib/repository.c
@@ -1738,6 +1738,7 @@ match_loose_object(struct got_object_id **unique_id, c
 	}
 	while ((dent = readdir(dir)) != NULL) {
 		int cmp;
+		enum got_hash_algorithm algo = GOT_HASH_SHA1;
 
 		free(id_str);
 		id_str = NULL;
@@ -1751,7 +1752,7 @@ match_loose_object(struct got_object_id **unique_id, c
 			goto done;
 		}
 
-		if (!got_parse_sha1_digest(id.sha1, id_str))
+		if (!got_parse_object_id(&id, id_str, algo))
 			continue;
 
 		/*
@@ -2291,6 +2292,7 @@ got_repo_get_loose_object_info(int *nobjects, off_t *o
 			char *id_str;
 			int fd;
 			struct stat sb;
+			enum got_hash_algorithm algo = GOT_HASH_SHA1;
 
 			if (strcmp(dent->d_name, ".") == 0 ||
 			    strcmp(dent->d_name, "..") == 0)
@@ -2301,7 +2303,7 @@ got_repo_get_loose_object_info(int *nobjects, off_t *o
 				goto done;
 			}
 
-			if (!got_parse_sha1_digest(id.sha1, id_str)) {
+			if (!got_parse_object_id(&id, id_str, algo)) {
 				free(id_str);
 				continue;
 			}
blob - d552b4a35a689baa8cf628c010eb5adfc9d57ce4
file + lib/repository_admin.c
--- lib/repository_admin.c
+++ lib/repository_admin.c
@@ -486,7 +486,7 @@ got_repo_find_pack(FILE **packfile, struct got_object_
 		goto done;
 	}
 	*dot = '\0';
-	if (!got_parse_sha1_digest(id.sha1, p)) {
+	if (!got_parse_object_id(&id, p, GOT_HASH_SHA1)) {
 		err = got_error_fmt(GOT_ERR_BAD_PATH,
 		    "'%s' is not a valid pack file name",
 		    packfile_name);
@@ -685,8 +685,8 @@ get_loose_object_ids(struct got_object_idset **loose_i
 				goto done;
 			}
 
-			memset(&id, 0, sizeof(id));
-			if (!got_parse_sha1_digest(id.sha1, id_str)) {
+			if (!got_parse_object_id(&id, id_str,
+			    GOT_HASH_SHA1)) {
 				free(id_str);
 				continue;
 			}
blob - ecd71cee9f0fb1d68f5a2341e98bfa386fb743c0
file + lib/serve.c
--- lib/serve.c
+++ lib/serve.c
@@ -36,6 +36,7 @@
 #include "got_path.h"
 #include "got_version.h"
 #include "got_reference.h"
+#include "got_object.h"
 
 #include "got_lib_pkt.h"
 #include "got_lib_dial.h"
blob - 9182db0e5c9f34de75291565e8162a16cda84db4
file + libexec/got-fetch-pack/got-fetch-pack.c
--- libexec/got-fetch-pack/got-fetch-pack.c
+++ libexec/got-fetch-pack/got-fetch-pack.c
@@ -300,7 +300,7 @@ fetch_ref(struct imsgbuf *ibuf, struct got_pathlist_he
 	const struct got_error *err;
 	char *theirs = NULL, *mine = NULL;
 
-	if (!got_parse_sha1_digest(want->sha1, id_str)) {
+	if (!got_parse_object_id(want, id_str, GOT_HASH_SHA1)) {
 		err = got_error(GOT_ERR_BAD_OBJ_ID_STR);
 		goto done;
 	}
@@ -619,7 +619,8 @@ fetch_pack(int fd, int packfd, uint8_t *pack_sha1,
 			    "unexpected message from server");
 			goto done;
 		}
-		if (!got_parse_sha1_digest(common_id.sha1, buf + 4)) {
+		if (!got_parse_object_id(&common_id, buf + 4,
+		    GOT_HASH_SHA1)) {
 			err = got_error_msg(GOT_ERR_BAD_PACKET,
 			    "bad object ID in ACK packet from server");
 			goto done;
blob - d1ffc719f8ca4925cb7bf8c3d4e5c8180824fb64
file + libexec/got-send-pack/got-send-pack.c
--- libexec/got-send-pack/got-send-pack.c
+++ libexec/got-send-pack/got-send-pack.c
@@ -414,7 +414,7 @@ send_pack(int fd, struct got_pathlist_head *refs,
 			err = got_error_from_errno("malloc");
 			goto done;
 		}
-		if (!got_parse_sha1_digest(id->sha1, id_str)) {
+		if (!got_parse_object_id(id, id_str, GOT_HASH_SHA1)) {
 			err = got_error(GOT_ERR_BAD_OBJ_ID_STR);
 			goto done;
 		}
blob - 511fd016b578a9308aede2f46618c2b7b6a353c2
file + regress/idset/idset_test.c
--- regress/idset/idset_test.c
+++ regress/idset/idset_test.c
@@ -70,15 +70,15 @@ idset_add_remove_iter(void)
 		goto done;
 	}
 
-	if (!got_parse_sha1_digest(id1.sha1, id_str1)) {
+	if (!got_parse_object_id(&id1, id_str1, GOT_HASH_SHA1)) {
 		err = got_error(GOT_ERR_BAD_OBJ_ID_STR);
 		goto done;
 	}
-	if (!got_parse_sha1_digest(id2.sha1, id_str2)) {
+	if (!got_parse_object_id(&id2, id_str2, GOT_HASH_SHA1)) {
 		err = got_error(GOT_ERR_BAD_OBJ_ID_STR);
 		goto done;
 	}
-	if (!got_parse_sha1_digest(id3.sha1, id_str3)) {
+	if (!got_parse_object_id(&id3, id_str3, GOT_HASH_SHA1)) {
 		err = got_error(GOT_ERR_BAD_OBJ_ID_STR);
 		goto done;
 	}