/ libpkg / pkg_checksum.c
pkg_checksum.c
  1  /* Copyright (c) 2014, Vsevolod Stakhov <vsevolod@FreeBSD.org>
  2   * Copyright (c) 2014, Google Inc.
  3   * All rights reserved.
  4   *
  5   * Redistribution and use in source and binary forms, with or without
  6   * modification, are permitted provided that the following conditions are met:
  7   *       * Redistributions of source code must retain the above copyright
  8   *         notice, this list of conditions and the following disclaimer.
  9   *       * Redistributions in binary form must reproduce the above copyright
 10   *         notice, this list of conditions and the following disclaimer in the
 11   *         documentation and/or other materials provided with the distribution.
 12   *
 13   * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
 14   * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 15   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 16   * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
 17   * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 18   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 19   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 20   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 21   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 22   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 23   */
 24  
 25  #include <assert.h>
 26  
 27  #include <sys/stat.h>
 28  
 29  #include <fcntl.h>
 30  #include <errno.h>
 31  #include "pkg.h"
 32  #include "private/pkg.h"
 33  #include "private/event.h"
 34  #include "sha256.h"
 35  #include "blake2.h"
 36  
 37  /* Separate checksum parts */
 38  #define PKG_CKSUM_SEPARATOR '$'
 39  
 40  /* Hash is in format <version>:<typeid>:<hexhash> */
 41  #define PKG_CHECKSUM_SHA256_LEN (SHA256_BLOCK_SIZE * 2 + 1)
 42  #define PKG_CHECKSUM_BLAKE2_LEN (BLAKE2B_OUTBYTES * 8 / 5 + sizeof("100") * 2 + 2)
 43  #define PKG_CHECKSUM_BLAKE2S_LEN (BLAKE2S_OUTBYTES * 8 / 5 + sizeof("100") * 2 + 2)
 44  #define PKG_CHECKSUM_CUR_VERSION 2
 45  
 46  struct kv {
 47  	const char *key;
 48  	const char *value;
 49  	struct kv *next;
 50  };
 51  
 52  static struct kv *
 53  kv_new(const char *k, const char *v)
 54  {
 55  	struct kv *kv = xcalloc(1, sizeof(*kv));
 56  	kv->key = k;
 57  	kv->value = v;
 58  	return (kv);
 59  }
 60  
 61  typedef void (*pkg_checksum_hash_func)(struct kv *entries,
 62  				unsigned char **out, size_t *outlen);
 63  typedef void (*pkg_checksum_hash_bulk_func)(const unsigned char *in, size_t inlen,
 64  				unsigned char **out, size_t *outlen);
 65  typedef void (*pkg_checksum_encode_func)(unsigned char *in, size_t inlen,
 66  				char *out, size_t outlen);
 67  
 68  typedef void (*pkg_checksum_hash_file_func)(int fd, unsigned char **out,
 69      size_t *outlen);
 70  
 71  static void pkg_checksum_hash_sha256(struct kv *entries,
 72  				unsigned char **out, size_t *outlen);
 73  static void pkg_checksum_hash_sha256_bulk(const unsigned char *in, size_t inlen,
 74  				unsigned char **out, size_t *outlen);
 75  static void pkg_checksum_hash_sha256_file(int fd, unsigned char **out,
 76      size_t *outlen);
 77  static void pkg_checksum_hash_blake2(struct kv *entries,
 78  				unsigned char **out, size_t *outlen);
 79  static void pkg_checksum_hash_blake2_bulk(const unsigned char *in, size_t inlen,
 80  				unsigned char **out, size_t *outlen);
 81  static void pkg_checksum_hash_blake2_file(int fd, unsigned char **out,
 82      size_t *outlen);
 83  static void pkg_checksum_hash_blake2s(struct kv *entries,
 84  				unsigned char **out, size_t *outlen);
 85  static void pkg_checksum_hash_blake2s_bulk(const unsigned char *in, size_t inlen,
 86  				unsigned char **out, size_t *outlen);
 87  static void pkg_checksum_hash_blake2s_file(int fd, unsigned char **out,
 88      size_t *outlen);
 89  static void pkg_checksum_encode_base32(unsigned char *in, size_t inlen,
 90  				char *out, size_t outlen);
 91  static void pkg_checksum_encode_hex(unsigned char *in, size_t inlen,
 92  				char *out, size_t outlen);
 93  
 94  static const struct _pkg_cksum_type {
 95  	const char *name;
 96  	size_t hlen;
 97  	pkg_checksum_hash_func hfunc;
 98  	pkg_checksum_hash_bulk_func hbulkfunc;
 99  	pkg_checksum_hash_file_func hfilefunc;
100  	pkg_checksum_encode_func encfunc;
101  } checksum_types[] = {
102  	[PKG_HASH_TYPE_SHA256_BASE32] = {
103  		"sha256_base32",
104  		PKG_CHECKSUM_SHA256_LEN,
105  		pkg_checksum_hash_sha256,
106  		pkg_checksum_hash_sha256_bulk,
107  		pkg_checksum_hash_sha256_file,
108  		pkg_checksum_encode_base32
109  	},
110  	[PKG_HASH_TYPE_SHA256_HEX] = {
111  		"sha256_hex",
112  		PKG_CHECKSUM_SHA256_LEN,
113  		pkg_checksum_hash_sha256,
114  		pkg_checksum_hash_sha256_bulk,
115  		pkg_checksum_hash_sha256_file,
116  		pkg_checksum_encode_hex
117  	},
118  	[PKG_HASH_TYPE_BLAKE2_BASE32] = {
119  		"blake2_base32",
120  		PKG_CHECKSUM_BLAKE2_LEN,
121  		pkg_checksum_hash_blake2,
122  		pkg_checksum_hash_blake2_bulk,
123  		pkg_checksum_hash_blake2_file,
124  		pkg_checksum_encode_base32
125  	},
126  	[PKG_HASH_TYPE_SHA256_RAW] = {
127  		"sha256_raw",
128  		SHA256_BLOCK_SIZE,
129  		pkg_checksum_hash_sha256,
130  		pkg_checksum_hash_sha256_bulk,
131  		pkg_checksum_hash_sha256_file,
132  		NULL
133  	},
134  	[PKG_HASH_TYPE_BLAKE2_RAW] = {
135  		"blake2_raw",
136  		BLAKE2B_OUTBYTES,
137  		pkg_checksum_hash_blake2,
138  		pkg_checksum_hash_blake2_bulk,
139  		pkg_checksum_hash_blake2_file,
140  		NULL
141  	},
142  	[PKG_HASH_TYPE_BLAKE2S_BASE32] = {
143  		"blake2s_base32",
144  		PKG_CHECKSUM_BLAKE2S_LEN,
145  		pkg_checksum_hash_blake2s,
146  		pkg_checksum_hash_blake2s_bulk,
147  		pkg_checksum_hash_blake2s_file,
148  		pkg_checksum_encode_base32
149  	},
150  	[PKG_HASH_TYPE_BLAKE2S_RAW] = {
151  		"blake2s_raw",
152  		BLAKE2S_OUTBYTES,
153  		pkg_checksum_hash_blake2s,
154  		pkg_checksum_hash_blake2s_bulk,
155  		pkg_checksum_hash_blake2s_file,
156  		NULL
157  	},
158  	[PKG_HASH_TYPE_UNKNOWN] = {
159  		NULL,
160  		-1,
161  		NULL,
162  		NULL,
163  		NULL,
164  		NULL
165  	}
166  };
167  
168  static int
169  pkg_checksum_entry_cmp(struct kv *e1,
170  	struct kv *e2)
171  {
172  	int r;
173  
174  	/* Compare field names first. */
175  	r = strcmp(e1->key, e2->key);
176  	if (r != 0)
177  		return r;
178  
179  	/* If field names are the same, compare values. */
180  	return (strcmp(e1->value, e2->value));
181  }
182  
183  /*
184   * At the moment we use the following fields to calculate the unique checksum
185   * of the following fields:
186   * - name
187   * - origin
188   * - version
189   * - arch
190   * - vital flag
191   * - options
192   * - required_shlibs
193   * - provided_shlibs
194   * - users
195   * - groups
196   * - dependencies
197   */
198  
199  int
200  pkg_checksum_generate(struct pkg *pkg, char *dest, size_t destlen,
201         pkg_checksum_type_t type, bool inc_scripts, bool inc_version, bool inc_files __unused)
202  {
203  	unsigned char *bdigest;
204  	char *olduid;
205  	size_t blen;
206  	struct kv *entries = NULL;
207  	charv_t tofree = vec_init();
208  	struct pkg_option *option = NULL;
209  	struct pkg_dep *dep = NULL;
210  	struct pkg_file *f = NULL;
211  	bool is_group = false;
212  
213  	if (pkg == NULL || type >= PKG_HASH_TYPE_UNKNOWN ||
214  					destlen < checksum_types[type].hlen)
215  		return (EPKG_FATAL);
216  	if (pkg_type(pkg) == PKG_GROUP_REMOTE || pkg_type(pkg) == PKG_GROUP_INSTALLED)
217  		is_group = true;
218  
219  	LL_APPEND(entries, kv_new("name", pkg->name));
220  	if (!is_group)
221  		LL_APPEND(entries, kv_new("origin", pkg->origin));
222  	if (inc_version && !is_group)
223  		LL_APPEND(entries, kv_new("version", pkg->version));
224  	if (!is_group)
225  		LL_APPEND(entries, kv_new("arch", pkg->altabi));
226  
227  	LL_APPEND(entries, kv_new("vital", pkg->vital ? "1" : "0"));
228  
229  	while (pkg_options(pkg, &option) == EPKG_OK) {
230  		LL_APPEND(entries, kv_new(option->key, option->value));
231  	}
232  
233  	vec_foreach(pkg->shlibs_required, i) {
234  		LL_APPEND(entries, kv_new("required_shlib", pkg->shlibs_required.d[i]));
235  	}
236  
237  	vec_foreach(pkg->shlibs_provided, i) {
238  		LL_APPEND(entries, kv_new("provided_shlib", pkg->shlibs_provided.d[i]));
239  	}
240  
241  	vec_foreach(pkg->users, i) {
242  		LL_APPEND(entries, kv_new("user", pkg->users.d[i]));
243  	}
244  
245  	vec_foreach(pkg->groups, i) {
246  		LL_APPEND(entries, kv_new("group", pkg->groups.d[i]));
247  	}
248  
249  	while (pkg_deps(pkg, &dep) == EPKG_OK) {
250  		if (is_group) {
251  			LL_APPEND(entries, kv_new("depend", dep->name));
252  		} else {
253  			xasprintf(&olduid, "%s~%s", dep->name, dep->origin);
254  			LL_APPEND(entries, kv_new("depend", olduid));
255  			vec_push(&tofree, olduid);
256  		}
257  	}
258  
259  	vec_foreach(pkg->provides, i) {
260  		LL_APPEND(entries, kv_new("provide", pkg->provides.d[i]));
261  	}
262  
263  	vec_foreach(pkg->requires, i) {
264  		LL_APPEND(entries, kv_new("require", pkg->requires.d[i]));
265  	}
266  
267  	if (inc_scripts) {
268  		for (int i = 0; i < PKG_NUM_SCRIPTS; i++) {
269  			if (pkg->scripts[i] != NULL) {
270  				fflush(pkg->scripts[i]->fp);
271  				LL_APPEND(entries, kv_new("script", pkg->scripts[i]->buf));
272  			}
273  		}
274  		for (int i = 0; i < PKG_NUM_LUA_SCRIPTS; i++) {
275  			vec_foreach(pkg->lua_scripts[i], j)
276  				LL_APPEND(entries, kv_new("lua_script", pkg->lua_scripts[i].d[j]));
277  		}
278  	}
279  
280  	while (pkg_files(pkg, &f) == EPKG_OK) {
281  		LL_APPEND(entries, kv_new(f->path, f->sum != NULL ? f->sum : "" ));
282  	}
283  
284  	/* Sort before hashing */
285  	LL_SORT(entries, pkg_checksum_entry_cmp);
286  
287  	checksum_types[type].hfunc(entries, &bdigest, &blen);
288  	if (blen == 0 || bdigest == NULL) {
289  		LL_FREE(entries, free);
290  		vec_free_and_free(&tofree, free);
291  		return (EPKG_FATAL);
292  	}
293  
294  	if (checksum_types[type].encfunc) {
295  		size_t i = snprintf(dest, destlen, "%d%c%d%c", PKG_CHECKSUM_CUR_VERSION,
296  				PKG_CKSUM_SEPARATOR, type, PKG_CKSUM_SEPARATOR);
297  		assert(i < destlen);
298  		checksum_types[type].encfunc(bdigest, blen, dest + i, destlen - i);
299  	}
300  	else {
301  		/* For raw formats we just output digest */
302  		assert(destlen >= blen);
303  		memcpy(dest, bdigest, blen);
304  	}
305  
306  	free(bdigest);
307  	LL_FREE(entries, free);
308  	vec_free_and_free(&tofree, free);
309  
310  	return (EPKG_OK);
311  }
312  
313  bool
314  pkg_checksum_is_valid(const char *cksum, size_t clen)
315  {
316  	const char *sep;
317  	unsigned int value;
318  
319  	if (clen < 4)
320  		return (false);
321  
322  	sep = strchr(cksum, PKG_CKSUM_SEPARATOR);
323  	if (sep == NULL || *sep == '\0')
324  		return (false);
325  
326  	/* Test version */
327  	value = strtoul(cksum, NULL, 10);
328  	if (value != PKG_CHECKSUM_CUR_VERSION)
329  		return (false);
330  
331  	cksum = sep + 1;
332  	sep = strchr(cksum, PKG_CKSUM_SEPARATOR);
333  	if (sep == NULL || *sep == '\0')
334  		return (false);
335  
336  	/* Test type */
337  	value = strtoul(cksum, NULL, 10);
338  	if (value >= PKG_HASH_TYPE_UNKNOWN)
339  		return (false);
340  
341  	return (true);
342  }
343  
344  /* <hashtype>$<hash> */
345  pkg_checksum_type_t
346  pkg_checksum_file_get_type(const char *cksum, size_t clen __unused)
347  {
348  	unsigned int value;
349  
350  	if (cksum == NULL || strchr(cksum, PKG_CKSUM_SEPARATOR) == NULL)
351  		return (PKG_HASH_TYPE_UNKNOWN);
352  
353  	value = strtoul(cksum, NULL, 10);
354  	if (value < PKG_HASH_TYPE_UNKNOWN)
355  		return (value);
356  
357  	return (PKG_HASH_TYPE_UNKNOWN);
358  }
359  
360  /* <version>$<hashtype>$<hash> */
361  pkg_checksum_type_t
362  pkg_checksum_get_type(const char *cksum, size_t clen __unused)
363  {
364  	const char *sep;
365  	unsigned int value;
366  
367  	sep = strchr(cksum, PKG_CKSUM_SEPARATOR);
368  	if (sep != NULL && *sep != '\0') {
369  		value = strtoul(sep + 1, NULL, 10);
370  		if (value < PKG_HASH_TYPE_UNKNOWN)
371  			return (value);
372  	}
373  
374  	return (PKG_HASH_TYPE_UNKNOWN);
375  }
376  
377  static void
378  pkg_checksum_hash_sha256(struct kv *entries,
379  		unsigned char **out, size_t *outlen)
380  {
381  	SHA256_CTX sign_ctx;
382  	struct kv *e;
383  
384  	sha256_init(&sign_ctx);
385  
386  	LL_FOREACH(entries, e) {
387  		sha256_update(&sign_ctx, e->key, strlen(e->key));
388  		sha256_update(&sign_ctx, e->value, strlen(e->value));
389  	}
390  	*out = xmalloc(SHA256_BLOCK_SIZE);
391  	sha256_final(&sign_ctx, *out);
392  	*outlen = SHA256_BLOCK_SIZE;
393  }
394  
395  static void
396  pkg_checksum_hash_sha256_bulk(const unsigned char *in, size_t inlen,
397  				unsigned char **out, size_t *outlen)
398  {
399  	SHA256_CTX sign_ctx;
400  
401  	*out = xmalloc(SHA256_BLOCK_SIZE);
402  	sha256_init(&sign_ctx);
403  	sha256_update(&sign_ctx, in, inlen);
404  	sha256_final(&sign_ctx, *out);
405  	*outlen = SHA256_BLOCK_SIZE;
406  }
407  
408  static void
409  pkg_checksum_hash_sha256_file(int fd, unsigned char **out, size_t *outlen)
410  {
411  	char buffer[8192];
412  	ssize_t r;
413  
414  	SHA256_CTX sign_ctx;
415  	*out = xmalloc(SHA256_BLOCK_SIZE);
416  	sha256_init(&sign_ctx);
417  	while ((r = read(fd, buffer, sizeof(buffer))) > 0)
418  		sha256_update(&sign_ctx, buffer, r);
419  	if (r < 0) {
420  		pkg_emit_errno(__func__, "read failed");
421  		free(*out);
422  		*out = NULL;
423  		return;
424  	}
425  	sha256_final(&sign_ctx, *out);
426  	*outlen = SHA256_BLOCK_SIZE;
427  }
428  
429  static void
430  pkg_checksum_hash_blake2(struct kv *entries,
431  		unsigned char **out, size_t *outlen)
432  {
433  	blake2b_state st;
434  	struct kv *e;
435  
436  	blake2b_init (&st, BLAKE2B_OUTBYTES);
437  
438  	LL_FOREACH(entries, e) {
439  		blake2b_update (&st, e->key, strlen(e->key));
440  		blake2b_update (&st, e->value, strlen(e->value));
441  	}
442  	*out = xmalloc(BLAKE2B_OUTBYTES);
443  	blake2b_final (&st, *out, BLAKE2B_OUTBYTES);
444  	*outlen = BLAKE2B_OUTBYTES;
445  }
446  
447  static void
448  pkg_checksum_hash_blake2_bulk(const unsigned char *in, size_t inlen,
449  				unsigned char **out, size_t *outlen)
450  {
451  	*out = xmalloc(BLAKE2B_OUTBYTES);
452  	blake2b(*out, BLAKE2B_OUTBYTES,  in, inlen, NULL, 0);
453  	*outlen = BLAKE2B_OUTBYTES;
454  }
455  
456  static void
457  pkg_checksum_hash_blake2_file(int fd, unsigned char **out, size_t *outlen)
458  {
459  	char buffer[8192];
460  	ssize_t r;
461  
462  	blake2b_state st;
463  	blake2b_init(&st, BLAKE2B_OUTBYTES);
464  
465  	while ((r = read(fd, buffer, sizeof(buffer))) > 0)
466  		blake2b_update(&st, buffer, r);
467  	if (r < 0) {
468  		pkg_emit_errno(__func__, "read failed");
469  		free(*out);
470  		*out = NULL;
471  		return;
472  	}
473  	*out = xmalloc(BLAKE2B_OUTBYTES);
474  	blake2b_final(&st, *out, BLAKE2B_OUTBYTES);
475  	*outlen = BLAKE2B_OUTBYTES;
476  }
477  
478  static void
479  pkg_checksum_hash_blake2s(struct kv *entries,
480  		unsigned char **out, size_t *outlen)
481  {
482  	blake2s_state st;
483  	struct kv *e;
484  
485  	blake2s_init (&st, BLAKE2S_OUTBYTES);
486  
487  	LL_FOREACH(entries, e) {
488  		blake2s_update (&st, e->key, strlen(e->key));
489  		blake2s_update (&st, e->value, strlen(e->value));
490  	}
491  	*out = xmalloc(BLAKE2S_OUTBYTES);
492  	blake2s_final (&st, *out, BLAKE2S_OUTBYTES);
493  	*outlen = BLAKE2S_OUTBYTES;
494  }
495  
496  static void
497  pkg_checksum_hash_blake2s_bulk(const unsigned char *in, size_t inlen,
498  				unsigned char **out, size_t *outlen)
499  {
500  	*out = xmalloc(BLAKE2S_OUTBYTES);
501  	blake2s(*out, BLAKE2S_OUTBYTES,  in, inlen, NULL, 0);
502  	*outlen = BLAKE2S_OUTBYTES;
503  }
504  
505  static void
506  pkg_checksum_hash_blake2s_file(int fd, unsigned char **out, size_t *outlen)
507  {
508  	char buffer[8192];
509  	ssize_t r;
510  
511  	blake2s_state st;
512  	blake2s_init(&st, BLAKE2S_OUTBYTES);
513  
514  	while ((r = read(fd, buffer, sizeof(buffer))) > 0)
515  		blake2s_update(&st, buffer, r);
516  	if (r < 0) {
517  		pkg_emit_errno(__func__, "read failed");
518  		free(*out);
519  		*out = NULL;
520  		return;
521  	}
522  	*out = xmalloc(BLAKE2S_OUTBYTES);
523  	blake2s_final(&st, *out, BLAKE2S_OUTBYTES);
524  	*outlen = BLAKE2S_OUTBYTES;
525  }
526  
527  /*
528   * We use here z-base32 encoding described here:
529   * http://philzimmermann.com/docs/human-oriented-base-32-encoding.txt
530   */
531  static const char b32[]="ybndrfg8ejkmcpqxot1uwisza345h769";
532  
533  
534  static void
535  pkg_checksum_encode_base32(unsigned char *in, size_t inlen,
536  				char *out, size_t outlen)
537  {
538  	size_t i;
539  	int remain = -1, r, x;
540  
541  	if (outlen < inlen * 8 / 5) {
542  		pkg_emit_error("cannot encode base32 as outlen is not sufficient");
543  		return;
544  	}
545  
546  	for (i = 0, r = 0; i < inlen; i++) {
547  		switch (i % 5) {
548  		case 0:
549  			/* 8 bits of input and 3 to remain */
550  			x = in[i];
551  			remain = in[i] >> 5;
552  			out[r++] = b32[x & 0x1F];
553  			break;
554  		case 1:
555  			/* 11 bits of input, 1 to remain */
556  			x = remain | in[i] << 3;
557  			out[r++] = b32[x & 0x1F];
558  			out[r++] = b32[x >> 5 & 0x1F];
559  			remain = x >> 10;
560  			break;
561  		case 2:
562  			/* 9 bits of input, 4 to remain */
563  			x = remain | in[i] << 1;
564  			out[r++] = b32[x & 0x1F];
565  			remain = x >> 5;
566  			break;
567  		case 3:
568  			/* 12 bits of input, 2 to remain */
569  			x = remain | in[i] << 4;
570  			out[r++] = b32[x & 0x1F];
571  			out[r++] = b32[x >> 5 & 0x1F];
572  			remain = x >> 10 & 0x3;
573  			break;
574  		case 4:
575  			/* 10 bits of output, nothing to remain */
576  			x = remain | in[i] << 2;
577  			out[r++] = b32[x & 0x1F];
578  			out[r++] = b32[x >> 5 & 0x1F];
579  			remain = -1;
580  			break;
581  		default:
582  			/* Not to be happen */
583  			break;
584  		}
585  
586  	}
587  	if (remain >= 0)
588  		out[r++] = b32[remain];
589  
590  	out[r] = 0;
591  }
592  
593  static void
594  pkg_checksum_encode_hex(unsigned char *in, size_t inlen,
595  				char *out, size_t outlen)
596  {
597  	size_t i;
598  
599  	if (outlen < inlen * 2) {
600  		pkg_emit_error("cannot encode hex as outlen is not sufficient");
601  		return;
602  	}
603  
604  	for (i = 0; i < inlen; i++)
605  		sprintf(out + (i * 2), "%02x", in[i]);
606  
607  	out[inlen * 2] = '\0';
608  }
609  
610  pkg_checksum_type_t
611  pkg_checksum_type_from_string(const char *name)
612  {
613  	int i;
614  	for (i = 0; i < PKG_HASH_TYPE_UNKNOWN; i ++) {
615  		if (STRIEQ(name, checksum_types[i].name))
616  			return (i);
617  	}
618  
619  	return (PKG_HASH_TYPE_UNKNOWN);
620  }
621  
622  const char*
623  pkg_checksum_type_to_string(pkg_checksum_type_t type)
624  {
625  	return (checksum_types[type].name);
626  }
627  
628  size_t
629  pkg_checksum_type_size(pkg_checksum_type_t type)
630  {
631  	return (checksum_types[type].hlen);
632  }
633  
634  int
635  pkg_checksum_calculate(struct pkg *pkg, struct pkgdb *db, bool inc_scripts,
636      bool inc_version, bool inc_files)
637  {
638  	char *new_digest;
639  	struct pkg_repo *repo;
640  	int rc = EPKG_OK;
641  	pkg_checksum_type_t type;
642  
643  	if (sizeof(void *) == 8)
644  		type = PKG_HASH_TYPE_BLAKE2_BASE32;
645  	else
646  		type = PKG_HASH_TYPE_BLAKE2S_BASE32;
647  
648  	if (pkg->reponame != NULL) {
649  		repo = pkg_repo_find(pkg->reponame);
650  
651  		if (repo != NULL)
652  			type = repo->meta->digest_format;
653  	}
654  
655  	new_digest = xmalloc(pkg_checksum_type_size(type));
656  	if (pkg_checksum_generate(pkg, new_digest, pkg_checksum_type_size(type),
657  	    type, inc_scripts, inc_version, inc_files)
658  			!= EPKG_OK) {
659  		free(new_digest);
660  		return (EPKG_FATAL);
661  	}
662  
663  	free(pkg->digest);
664  	pkg->digest = new_digest;
665  
666  	if (db != NULL)
667  		pkgdb_set_pkg_digest(db, pkg);
668  
669  	return (rc);
670  }
671  
672  
673  unsigned char *
674  pkg_checksum_data(const unsigned char *in, size_t inlen,
675  	pkg_checksum_type_t type)
676  {
677  	const struct _pkg_cksum_type *cksum;
678  	unsigned char *out, *res = NULL;
679  	size_t outlen;
680  
681  	if (type >= PKG_HASH_TYPE_UNKNOWN || in == NULL)
682  		return (NULL);
683  
684  	/* Zero terminated string */
685  	if (inlen == 0) {
686  		inlen = strlen(in);
687  	}
688  
689  	cksum = &checksum_types[type];
690  
691  	cksum->hbulkfunc(in, inlen, &out, &outlen);
692  	if (out != NULL) {
693  		if (cksum->encfunc != NULL) {
694  			res = xmalloc(cksum->hlen);
695  			cksum->encfunc(out, outlen, res, cksum->hlen);
696  			free(out);
697  		}
698  		else {
699  			res = out;
700  		}
701  	}
702  
703  	return (res);
704  }
705  
706  unsigned char *
707  pkg_checksum_fileat(int rootfd, const char *path, pkg_checksum_type_t type)
708  {
709  	int fd;
710  	unsigned char *ret;
711  
712  	if ((fd = openat(rootfd, path, O_RDONLY)) == -1) {
713  		pkg_emit_errno("open", path);
714  		return (NULL);
715  	}
716  
717  	ret = pkg_checksum_fd(fd, type);
718  
719  	close(fd);
720  
721  	return (ret);
722  }
723  
724  unsigned char *
725  pkg_checksum_file(const char *path, pkg_checksum_type_t type)
726  {
727  	return pkg_checksum_fileat(AT_FDCWD, path, type);
728  }
729  
730  unsigned char *
731  pkg_checksum_fd(int fd, pkg_checksum_type_t type)
732  {
733  	const struct _pkg_cksum_type *cksum;
734  	unsigned char *out, *res = NULL;
735  	size_t outlen;
736  
737  	if (type >= PKG_HASH_TYPE_UNKNOWN || fd < 0)
738  		return (NULL);
739  
740  	cksum = &checksum_types[type];
741  	cksum->hfilefunc(fd, &out, &outlen);
742  	if (out != NULL) {
743  		if (cksum->encfunc != NULL) {
744  			res = xmalloc(cksum->hlen);
745  			cksum->encfunc(out, outlen, res, cksum->hlen);
746  			free(out);
747  		} else {
748  			res = out;
749  		}
750  	}
751  
752  	return (res);
753  }
754  
755  static unsigned char *
756  pkg_checksum_symlink_readlink(const char *linkbuf, int linklen,
757      pkg_checksum_type_t type)
758  {
759  	const char *lnk;
760  
761  	lnk = linkbuf;
762  
763  	/*
764  	 * It is known that \0 is added to the checksum in case the symlink
765  	 * targets an absolute path but the behaviour is kept for compat
766  	 */
767  	return (pkg_checksum_data(RELATIVE_PATH(lnk), linklen, type));
768  }
769  
770  unsigned char *
771  pkg_checksum_symlink(const char *path, pkg_checksum_type_t type)
772  {
773  	return pkg_checksum_symlinkat(AT_FDCWD, path, type);
774  }
775  
776  unsigned char *
777  pkg_checksum_symlinkat(int fd, const char *path, pkg_checksum_type_t type)
778  {
779  	char linkbuf[MAXPATHLEN];
780  	int linklen;
781  
782  	if ((linklen = readlinkat(fd, path, linkbuf, sizeof(linkbuf) - 1)) == -1) {
783  		pkg_emit_errno("pkg_checksum_symlinkat", "readlink failed");
784  		return (NULL);
785  	}
786  	linkbuf[linklen] = '\0';
787  
788  	return (pkg_checksum_symlink_readlink(linkbuf, linklen, type));
789  }
790  
791  int
792  pkg_checksum_validate_file(const char *path, const char *sum)
793  {
794  	return pkg_checksum_validate_fileat(AT_FDCWD, path, sum);
795  }
796  
797  int
798  pkg_checksum_validate_fileat(int rootfd, const char *path, const char *sum)
799  {
800  	struct stat st;
801  	char *newsum;
802  	pkg_checksum_type_t type;
803  
804  	type = pkg_checksum_file_get_type(sum, strlen(sum));
805  	if (type == PKG_HASH_TYPE_UNKNOWN) {
806  		type = PKG_HASH_TYPE_SHA256_HEX;
807  	} else {
808  		sum = strchr(sum, PKG_CKSUM_SEPARATOR);
809  		if (sum != NULL)
810  			sum++;
811  	}
812  
813  	if (fstatat(rootfd, path, &st, AT_SYMLINK_NOFOLLOW) == -1) {
814  		return (errno);
815  	}
816  
817  	if (S_ISLNK(st.st_mode))
818  		newsum = pkg_checksum_symlinkat(rootfd, path, type);
819  	else
820  		newsum = pkg_checksum_fileat(rootfd, path, type);
821  
822  	if (newsum == NULL)
823  		return (-1);
824  
825  	if (!STREQ(sum, newsum)) {
826  		free(newsum);
827  		return (-1);
828  	}
829  
830  	free(newsum);
831  
832  	return (0);
833  }
834  
835  char *
836  pkg_checksum_generate_file(const char *path, pkg_checksum_type_t type)
837  {
838  	return pkg_checksum_generate_fileat(AT_FDCWD, path, type);
839  }
840  
841  char *
842  pkg_checksum_generate_fileat(int rootfd, const char *path,
843      pkg_checksum_type_t type)
844  {
845  	struct stat st;
846  	unsigned char *sum;
847  	char *cksum;
848  
849  	if (fstatat(rootfd, path, &st, AT_SYMLINK_NOFOLLOW) == -1) {
850  		pkg_emit_errno("pkg_checksum_generate_file", "lstat");
851  		return (NULL);
852  	}
853  
854  	if (S_ISLNK(st.st_mode))
855  		sum = pkg_checksum_symlinkat(rootfd, path, type);
856  	else
857  		sum = pkg_checksum_fileat(rootfd, path, type);
858  
859  	if (sum == NULL)
860  		return (NULL);
861  
862  	xasprintf(&cksum, "%d%c%s", type, PKG_CKSUM_SEPARATOR, sum);
863  	free(sum);
864  
865  	return (cksum);
866  }