RRDP also uses SHA256 hashes to validate files (before withdraws and updates). Again move this from the implementation in mft.c to validate.c this way it can be reused.
OK? -- :wq Claudio Index: extern.h =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v retrieving revision 1.51 diff -u -p -r1.51 extern.h --- extern.h 5 Mar 2021 12:33:19 -0000 1.51 +++ extern.h 5 Mar 2021 14:00:29 -0000 @@ -354,6 +354,7 @@ int valid_ta(const char *, struct auth int valid_cert(const char *, struct auth_tree *, const struct cert *); int valid_roa(const char *, struct auth_tree *, struct roa *); +int valid_filehash(const char *, const char *, size_t); /* Working with CMS files. */ Index: mft.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/mft.c,v retrieving revision 1.28 diff -u -p -r1.28 mft.c --- mft.c 4 Mar 2021 14:24:17 -0000 1.28 +++ mft.c 5 Mar 2021 12:33:50 -0000 @@ -434,61 +434,32 @@ out: } /* - * Check the hash value of a file. + * Check all files and their hashes in a MFT structure. * Return zero on failure, non-zero on success. */ -static int -mft_validfilehash(const char *fn, const struct mftfile *m) +int +mft_check(const char *fn, struct mft *p) { - char filehash[SHA256_DIGEST_LENGTH]; - char buffer[8192]; + size_t i; + int rc = 1; char *cp, *path = NULL; - SHA256_CTX ctx; - ssize_t nr; - int fd; /* Check hash of file now, but first build path for it */ cp = strrchr(fn, '/'); assert(cp != NULL); assert(cp - fn < INT_MAX); - if (asprintf(&path, "%.*s/%s", (int)(cp - fn), fn, m->file) == -1) - err(1, NULL); - if ((fd = open(path, O_RDONLY)) == -1) { - warn("%s: referenced file %s", fn, m->file); + for (i = 0; i < p->filesz; i++) { + const struct mftfile *m = &p->files[i]; + if (asprintf(&path, "%.*s/%s", (int)(cp - fn), fn, + m->file) == -1) + err(1, NULL); + if (!valid_filehash(path, m->hash, sizeof(m->hash))) { + warnx("%s: bad message digest for %s", fn, m->file); + rc = 0; + } free(path); - return 0; } - free(path); - - SHA256_Init(&ctx); - while ((nr = read(fd, buffer, sizeof(buffer))) > 0) { - SHA256_Update(&ctx, buffer, nr); - } - close(fd); - - SHA256_Final(filehash, &ctx); - if (memcmp(m->hash, filehash, SHA256_DIGEST_LENGTH) != 0) { - warnx("%s: bad message digest for %s", fn, m->file); - return 0; - } - - return 1; -} - -/* - * Check all files and their hashes in a MFT structure. - * Return zero on failure, non-zero on success. - */ -int -mft_check(const char *fn, struct mft *p) -{ - size_t i; - int rc = 1; - - for (i = 0; i < p->filesz; i++) - if (!mft_validfilehash(fn, &p->files[i])) - rc = 0; return rc; } Index: validate.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/validate.c,v retrieving revision 1.11 diff -u -p -r1.11 validate.c --- validate.c 12 Sep 2020 15:46:48 -0000 1.11 +++ validate.c 5 Mar 2021 13:59:46 -0000 @@ -20,6 +20,7 @@ #include <arpa/inet.h> #include <assert.h> #include <err.h> +#include <fcntl.h> #include <inttypes.h> #include <stdarg.h> #include <stdlib.h> @@ -237,6 +238,37 @@ valid_roa(const char *fn, struct auth_tr tracewarn(a); return 0; } + + return 1; +} + +/* + * Validate a file by verifying the SHA256 hash of that file. + * Returns 1 if valid, 0 otherwise. + */ +int +valid_filehash(const char *fn, const char *hash, size_t hlen) +{ + SHA256_CTX ctx; + char filehash[SHA256_DIGEST_LENGTH]; + char buffer[8192]; + ssize_t nr; + int fd; + + if (hlen != sizeof(filehash)) + errx(1, "bad hash size"); + + if ((fd = open(fn, O_RDONLY)) == -1) + return 0; + + SHA256_Init(&ctx); + while ((nr = read(fd, buffer, sizeof(buffer))) > 0) + SHA256_Update(&ctx, buffer, nr); + close(fd); + + SHA256_Final(filehash, &ctx); + if (memcmp(hash, filehash, sizeof(filehash)) != 0) + return 0; return 1; }