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