From: Michael Tremer Date: Sun, 7 Mar 2021 23:56:59 +0000 (+0000) Subject: archive: Compute BLAKE2 checksum when extracting files X-Git-Tag: 0.9.28~1285^2~611 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7ab0465c13a8f0cdda3a3ea9cdff6f715f82e67f;p=pakfire.git archive: Compute BLAKE2 checksum when extracting files Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/archive.c b/src/libpakfire/archive.c index b41d76918..eb05acb3e 100644 --- a/src/libpakfire/archive.c +++ b/src/libpakfire/archive.c @@ -617,35 +617,76 @@ PAKFIRE_EXPORT char* pakfire_archive_get(PakfireArchive archive, const char* nam return pakfire_parser_get(archive->parser, namespace, key); } -static int archive_copy_data(Pakfire pakfire, struct archive* in, struct archive* out) { - int r; - const void* buff; +static int archive_copy_data(Pakfire pakfire, struct archive* in, struct archive* out, + char** hexdigest) { + EVP_MD_CTX* mdctx = EVP_MD_CTX_new(); + + // Initialize digest + int r = EVP_DigestInit_ex(mdctx, EVP_blake2s256(), NULL); + if (r != 1) { + ERROR(pakfire, "Could not setup digest function: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + r = 1; + goto ERROR; + } + const void* buffer; size_t size; off_t offset; for (;;) { - r = archive_read_data_block(in, &buff, &size, &offset); + // Read a block of data + r = archive_read_data_block(in, &buffer, &size, &offset); if (r == ARCHIVE_EOF) break; if (r != ARCHIVE_OK) { ERROR(pakfire, "Could not read data from archive: %s\n", archive_error_string(in)); + goto ERROR; + } - return r; + // Update digest + r = EVP_DigestUpdate(mdctx, buffer, size); + if (r != 1) { + ERROR(pakfire, "EVP_DigestUpdate failed: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + r = 1; + goto ERROR; } - r = archive_write_data_block(out, buff, size, offset); + // Write the data + r = archive_write_data_block(out, buffer, size, offset); if (r != ARCHIVE_OK) { ERROR(pakfire, "Could not write data to disk: %s\n", archive_error_string(out)); - - return r; + goto ERROR; } } - return 0; + char digest[EVP_MAX_MD_SIZE]; + size_t digest_length; + + // Finalize the digest + r = EVP_DigestFinal_ex(mdctx, (unsigned char*)digest, (unsigned int*)&digest_length); + if (r != 1) { + ERROR(pakfire, "%s\n", ERR_error_string(ERR_get_error(), NULL)); + goto ERROR; + } + + // Convert to hex + *hexdigest = pakfire_hexlify(digest, digest_length); + + DEBUG(pakfire, "Computed digest of %zu bytes: %s\n", digest_length, *hexdigest); + + // Success + r = 0; + +ERROR: + if (mdctx) + EVP_MD_CTX_free(mdctx); + + return r; } static int archive_extract(Pakfire pakfire, struct archive* a, const char* prefix) { @@ -698,6 +739,8 @@ static int archive_extract(Pakfire pakfire, struct archive* a, const char* prefi free(h); } + char* hexdigest = NULL; + // Create file r = archive_write_header(ext, entry); if (r != ARCHIVE_OK) { @@ -708,7 +751,7 @@ static int archive_extract(Pakfire pakfire, struct archive* a, const char* prefi // Copy payload if (size > 0) { - r = archive_copy_data(pakfire, a, ext); + r = archive_copy_data(pakfire, a, ext, &hexdigest); if (r != ARCHIVE_OK) break; } @@ -735,6 +778,9 @@ static int archive_extract(Pakfire pakfire, struct archive* a, const char* prefi break; } + if (hexdigest) + free(hexdigest); + if (r != ARCHIVE_OK) break; } diff --git a/src/libpakfire/include/pakfire/util.h b/src/libpakfire/include/pakfire/util.h index c4ef1bf3f..2deb4faad 100644 --- a/src/libpakfire/include/pakfire/util.h +++ b/src/libpakfire/include/pakfire/util.h @@ -61,6 +61,8 @@ char* pakfire_generate_uuid(); int pakfire_string_endswith(const char* s, const char* suffix); char* pakfire_lstrip(const char* s); +char* pakfire_hexlify(const char* digest, const size_t length); + #endif #endif /* PAKFIRE_UTIL_H */ diff --git a/src/libpakfire/util.c b/src/libpakfire/util.c index 9f0b054ac..e4daba7f3 100644 --- a/src/libpakfire/util.c +++ b/src/libpakfire/util.c @@ -476,3 +476,23 @@ PAKFIRE_EXPORT char* pakfire_generate_uuid() { return ret; } + +char* pakfire_hexlify(const char* digest, const size_t length) { + const char* hexdigits = "0123456789abcdef"; + + char* s = malloc((length * 2) + 1); + if (!s) + return NULL; + + for (unsigned int i = 0, j = 0; i < length; i++) { + char b = digest[i]; + + s[j++] = hexdigits[(b >> 4) & 0xf]; + s[j++] = hexdigits[(b & 0x0f)]; + } + + // Terminate result + s[length * 2] = '\0'; + + return s; +}