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