portable: enable gotctl (via --enable-gotd)
[got-portable.git] / lib / hash.c
blob641d2b5b84fd5163c607e96980ad52cb3109c1ae
1 /*
2 * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include "got_compat.h"
19 #include <sys/types.h>
20 #include <sys/queue.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <limits.h>
28 #include "got_object.h"
29 #include "got_error.h"
31 #include "got_lib_hash.h"
33 struct got_object_id *
34 got_object_id_dup(struct got_object_id *id1)
36 struct got_object_id *id2;
38 id2 = malloc(sizeof(*id2));
39 if (id2 == NULL)
40 return NULL;
41 memcpy(id2, id1, sizeof(*id2));
42 return id2;
45 int
46 got_object_id_cmp(const struct got_object_id *id1,
47 const struct got_object_id *id2)
49 return memcmp(id1->sha1, id2->sha1, SHA1_DIGEST_LENGTH);
52 const struct got_error *
53 got_object_id_str(char **outbuf, struct got_object_id *id)
55 static const size_t len = GOT_OBJECT_ID_HEX_MAXLEN;
57 *outbuf = malloc(len);
58 if (*outbuf == NULL)
59 return got_error_from_errno("malloc");
61 if (got_object_id_hex(id, *outbuf, len) == NULL) {
62 free(*outbuf);
63 *outbuf = NULL;
64 return got_error(GOT_ERR_BAD_OBJ_ID_STR);
67 return NULL;
70 int
71 got_parse_xdigit(uint8_t *val, const char *hex)
73 char *ep;
74 long lval;
76 errno = 0;
77 lval = strtol(hex, &ep, 16);
78 if (hex[0] == '\0' || *ep != '\0')
79 return 0;
80 if (errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN))
81 return 0;
83 *val = (uint8_t)lval;
84 return 1;
87 static int
88 parse_digest(uint8_t *digest, int len, const char *line)
90 uint8_t b = 0;
91 char hex[3] = {'\0', '\0', '\0'};
92 int i, j;
94 for (i = 0; i < len; i++) {
95 if (line[0] == '\0' || line[1] == '\0')
96 return 0;
97 for (j = 0; j < 2; j++) {
98 hex[j] = *line;
99 line++;
101 if (!got_parse_xdigit(&b, hex))
102 return 0;
103 digest[i] = b;
106 return 1;
109 static char *
110 digest_to_str(const uint8_t *digest, int len, char *buf)
112 const char hex[] = "0123456789abcdef";
113 char *p = buf;
114 int i;
116 for (i = 0; i < len; i++) {
117 *p++ = hex[digest[i] >> 4];
118 *p++ = hex[digest[i] & 0xf];
120 *p = '\0';
122 return buf;
125 char *
126 got_sha1_digest_to_str(const uint8_t *digest, char *buf, size_t size)
128 if (size < SHA1_DIGEST_STRING_LENGTH)
129 return NULL;
130 return digest_to_str(digest, SHA1_DIGEST_LENGTH, buf);
133 char *
134 got_sha256_digest_to_str(const uint8_t *digest, char *buf, size_t size)
136 if (size < SHA256_DIGEST_STRING_LENGTH)
137 return NULL;
138 return digest_to_str(digest, SHA256_DIGEST_LENGTH, buf);
142 got_parse_hash_digest(uint8_t *digest, const char *line,
143 enum got_hash_algorithm algo)
145 switch (algo) {
146 case GOT_HASH_SHA1:
147 return parse_digest(digest, SHA1_DIGEST_LENGTH, line);
148 case GOT_HASH_SHA256:
149 return parse_digest(digest, SHA256_DIGEST_LENGTH, line);
150 default:
151 return 0;
155 char *
156 got_object_id_hex(struct got_object_id *id, char *buf, size_t len)
158 return got_sha1_digest_to_str(id->sha1, buf, len);
162 got_parse_object_id(struct got_object_id *id, const char *line,
163 enum got_hash_algorithm algo)
165 memset(id, 0, sizeof(*id));
167 /* XXX: temporary until we grow got_object_id */
168 if (algo != GOT_HASH_SHA1)
169 return 0;
171 return got_parse_hash_digest(id->sha1, line, algo);
174 void
175 got_hash_init(struct got_hash *hash, enum got_hash_algorithm algo)
177 memset(hash, 0, sizeof(*hash));
178 hash->algo = algo;
180 if (algo == GOT_HASH_SHA1)
181 SHA1Init(&hash->sha1_ctx);
182 else if (algo == GOT_HASH_SHA256)
183 SHA256Init(&hash->sha256_ctx);
186 void
187 got_hash_update(struct got_hash *hash, const void *data, size_t len)
189 if (hash->algo == GOT_HASH_SHA1)
190 SHA1Update(&hash->sha1_ctx, data, len);
191 else if (hash->algo == GOT_HASH_SHA256)
192 SHA256Update(&hash->sha256_ctx, data, len);
195 void
196 got_hash_final(struct got_hash *hash, uint8_t *out)
198 if (hash->algo == GOT_HASH_SHA1)
199 SHA1Final(out, &hash->sha1_ctx);
200 else if (hash->algo == GOT_HASH_SHA256)
201 SHA256Final(out, &hash->sha256_ctx);
204 void
205 got_hash_final_object_id(struct got_hash *hash, struct got_object_id *id)
207 memset(id, 0, sizeof(*id));
208 got_hash_final(hash, id->sha1);
212 got_hash_cmp(enum got_hash_algorithm algo, uint8_t *b1, uint8_t *b2)
214 if (algo == GOT_HASH_SHA1)
215 return memcmp(b1, b2, SHA1_DIGEST_LENGTH);
216 else if (algo == GOT_HASH_SHA256)
217 return memcmp(b1, b2, SHA256_DIGEST_LENGTH);
218 return -1;