From: Michael Tremer Date: Mon, 20 Sep 2021 11:15:58 +0000 (+0000) Subject: package: Calculate digests X-Git-Tag: 0.9.28~966 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e61716e4229c206dd82fd2be18a548cd675b3513;p=pakfire.git package: Calculate digests Signed-off-by: Michael Tremer --- diff --git a/src/_pakfire/package.c b/src/_pakfire/package.c index b308dca0d..b6b4dc9c1 100644 --- a/src/_pakfire/package.c +++ b/src/_pakfire/package.c @@ -194,10 +194,16 @@ static void Package_set_uuid(PackageObject* self, PyObject* value) { } static PyObject* Package_get_hexdigest(PackageObject* self, enum pakfire_package_digests type) { - const char* hexdigest = pakfire_package_get_hexdigest(self->package, type); + enum pakfire_package_digests digest = PAKFIRE_PACKAGE_DIGEST_NONE; + + const char* hexdigest = pakfire_package_get_hexdigest(self->package, &digest); if (!hexdigest) Py_RETURN_NONE; + // Is this the requested type? + if (digest != type) + Py_RETURN_NONE; + return PyUnicode_FromString(hexdigest); } diff --git a/src/libpakfire/archive.c b/src/libpakfire/archive.c index 38873a436..c58d1c0fe 100644 --- a/src/libpakfire/archive.c +++ b/src/libpakfire/archive.c @@ -1870,12 +1870,99 @@ PAKFIRE_EXPORT ssize_t pakfire_archive_get_size(struct pakfire_archive* archive) return buf.st_size; } +static int pakfire_archive_calculate_digest(struct pakfire_archive* archive, + enum pakfire_package_digests digest, unsigned char* output, size_t* length) { + int r = 1; + + const EVP_MD* md = NULL; + + // Select hash function + switch (digest) { + case PAKFIRE_PACKAGE_DIGEST_SHA512: + md = EVP_sha512(); + break; + + case PAKFIRE_PACKAGE_DIGEST_SHA256: + md = EVP_sha256(); + break; + + default: + errno = ENOTSUP; + return 1; + } + + // Initialize context + EVP_MD_CTX* ctx = EVP_MD_CTX_new(); + if (!ctx) { + ERROR(archive->pakfire, "Could not initialize EVP context: %m\n"); + goto ERROR; + } + + r = EVP_DigestInit_ex(ctx, md, NULL); + if (r != 1) { + ERROR(archive->pakfire, "EVP_DigestInit_ex failed: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + r = 1; + goto ERROR; + } + + char buffer[64 * 1024]; + + // Feed archive into the hash functions + while (!feof(archive->f)) { + size_t bytes_read = fread(buffer, 1, sizeof(buffer), archive->f); + + if (ferror(archive->f)) { + ERROR(archive->pakfire, "Error reading from file: %m\n"); + goto ERROR; + } + + r = EVP_DigestUpdate(ctx, buffer, bytes_read); + if (r != 1) { + ERROR(archive->pakfire, "EVP_DigestUpdate failed: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + r = 1; + goto ERROR; + } + } + + // Finalise hash function + r = EVP_DigestFinal_ex(ctx, output, (unsigned int*)length); + if (r != 1) { + ERROR(archive->pakfire, "EVP_DigestFinal_ex failed: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + r = 1; + goto ERROR; + } + + // Success + r = 0; + +ERROR: + // Cleanup + if (ctx) + EVP_MD_CTX_free(ctx); + + rewind(archive->f); + + return r; +} + /* Copy all metadata from this archive to the package object */ PAKFIRE_EXPORT int pakfire_archive_make_package(struct pakfire_archive* archive, struct pakfire_repo* repo, struct pakfire_package** package) { struct pakfire_repo* dummy = NULL; + unsigned char digest[EVP_MAX_MD_SIZE]; + size_t digest_length = 0; + int r; + + // Calculate digest + r = pakfire_archive_calculate_digest(archive, PAKFIRE_PACKAGE_DIGEST_SHA512, + digest, &digest_length); + if (r) + return r; // Use dummy repo if no repository was passed if (!repo) { @@ -2063,6 +2150,9 @@ PAKFIRE_EXPORT int pakfire_archive_make_package(struct pakfire_archive* archive, pakfire_filelist_unref(filelist); } + // Set digests + pakfire_package_set_digest(pkg, PAKFIRE_PACKAGE_DIGEST_SHA512, digest); + *package = pkg; // Cleanup diff --git a/src/libpakfire/db.c b/src/libpakfire/db.c index 445254f80..0dc703d38 100644 --- a/src/libpakfire/db.c +++ b/src/libpakfire/db.c @@ -1096,22 +1096,27 @@ int pakfire_db_add_package(struct pakfire_db* db, goto ROLLBACK; } - // Bind digest_sha512 - const char* digest_sha512 = pakfire_package_get_hexdigest(pkg, PAKFIRE_PACKAGE_DIGEST_SHA512); + enum pakfire_package_digests digest = PAKFIRE_PACKAGE_DIGEST_NONE; - r = sqlite3_bind_text(stmt, 8, digest_sha512, -1, NULL); - if (r) { - ERROR(db->pakfire, "Could not bind digest_sha512: %s\n", sqlite3_errmsg(db->handle)); - goto ROLLBACK; - } + const char* hexdigest = pakfire_package_get_hexdigest(pkg, &digest); + switch (digest) { + case PAKFIRE_PACKAGE_DIGEST_SHA512: + r = sqlite3_bind_text(stmt, 8, hexdigest, -1, NULL); + if (r) { + ERROR(db->pakfire, "Could not bind digest_sha512: %s\n", sqlite3_errmsg(db->handle)); + goto ROLLBACK; + } + break; - // Bind digest_sha256 - const char* digest_sha256 = pakfire_package_get_hexdigest(pkg, PAKFIRE_PACKAGE_DIGEST_SHA256); + case PAKFIRE_PACKAGE_DIGEST_SHA256: + r = sqlite3_bind_text(stmt, 9, hexdigest, -1, NULL); + if (r) { + ERROR(db->pakfire, "Could not bind digest_sha256: %s\n", sqlite3_errmsg(db->handle)); + goto ROLLBACK; + } - r = sqlite3_bind_text(stmt, 9, digest_sha256, -1, NULL); - if (r) { - ERROR(db->pakfire, "Could not bind digest_sha256: %s\n", sqlite3_errmsg(db->handle)); - goto ROLLBACK; + case PAKFIRE_PACKAGE_DIGEST_NONE: + break; } // Bind license diff --git a/src/libpakfire/include/pakfire/package.h b/src/libpakfire/include/pakfire/package.h index 990f69243..aebc85ef5 100644 --- a/src/libpakfire/include/pakfire/package.h +++ b/src/libpakfire/include/pakfire/package.h @@ -31,8 +31,9 @@ struct pakfire_package; #include enum pakfire_package_digests { - PAKFIRE_PACKAGE_DIGEST_SHA256, - PAKFIRE_PACKAGE_DIGEST_SHA512, + PAKFIRE_PACKAGE_DIGEST_NONE = 0, + PAKFIRE_PACKAGE_DIGEST_SHA256 = 1 << 0, + PAKFIRE_PACKAGE_DIGEST_SHA512 = 1 << 1, }; struct pakfire_package* pakfire_package_create(struct pakfire* pakfire, struct pakfire_repo* repo, @@ -57,9 +58,9 @@ void pakfire_package_set_arch(struct pakfire_package* pkg, const char* arch); const char* pakfire_package_get_uuid(struct pakfire_package* pkg); void pakfire_package_set_uuid(struct pakfire_package* pkg, const char* uuid); const unsigned char* pakfire_package_get_digest(struct pakfire_package* pkg, - enum pakfire_package_digests type); + enum pakfire_package_digests* type); const char* pakfire_package_get_hexdigest(struct pakfire_package* pkg, - enum pakfire_package_digests type); + enum pakfire_package_digests* type); int pakfire_package_set_digest(struct pakfire_package* pkg, enum pakfire_package_digests type, const unsigned char* digest); int pakfire_package_set_hexdigest(struct pakfire_package* pkg, diff --git a/src/libpakfire/package.c b/src/libpakfire/package.c index 0fcd6353c..beeeaf1bd 100644 --- a/src/libpakfire/package.c +++ b/src/libpakfire/package.c @@ -375,57 +375,72 @@ PAKFIRE_EXPORT void pakfire_package_set_uuid(struct pakfire_package* pkg, const pakfire_package_set_string(pkg, SOLVABLE_PKGID, uuid); } -static Id pakfire_package_digest2id(enum pakfire_package_digests type) { - Id id = 0; +static enum pakfire_package_digests pakfire_package_id2digest(Id id) { + switch (id) { + case REPOKEY_TYPE_SHA512: + return PAKFIRE_PACKAGE_DIGEST_SHA512; - switch (type) { - case PAKFIRE_PACKAGE_DIGEST_SHA256: - id = REPOKEY_TYPE_SHA256; - break; - - case PAKFIRE_PACKAGE_DIGEST_SHA512: - id = REPOKEY_TYPE_SHA512; - break; + case REPOKEY_TYPE_SHA256: + return PAKFIRE_PACKAGE_DIGEST_SHA256; } - // Type is invalid - if (!id) - errno = EINVAL; - - return id; + return PAKFIRE_PACKAGE_DIGEST_NONE; } PAKFIRE_EXPORT const unsigned char* pakfire_package_get_digest( - struct pakfire_package* pkg, enum pakfire_package_digests type) { + struct pakfire_package* pkg, enum pakfire_package_digests* type) { Solvable* s = get_solvable(pkg); + Id id; - Id id = pakfire_package_digest2id(type); - if (!id) - return NULL; + const unsigned char* checksum = solvable_lookup_bin_checksum(s, SOLVABLE_CHECKSUM, &id); - return solvable_lookup_bin_checksum(s, SOLVABLE_CHECKSUM, &id); + // Convert ID to digest type + *type = pakfire_package_id2digest(id); + if (!*type) { + errno = ENOTSUP; + checksum = NULL; + } + + return checksum; } PAKFIRE_EXPORT const char* pakfire_package_get_hexdigest( - struct pakfire_package* pkg, enum pakfire_package_digests type) { + struct pakfire_package* pkg, enum pakfire_package_digests* type) { Solvable* s = get_solvable(pkg); + Id id; - Id id = pakfire_package_digest2id(type); - if (!id) - return NULL; + const char* checksum = solvable_lookup_checksum(s, SOLVABLE_CHECKSUM, &id); - return solvable_lookup_checksum(s, SOLVABLE_CHECKSUM, &id); + // Convert ID to digest type + *type = pakfire_package_id2digest(id); + if (!*type) { + errno = ENOTSUP; + checksum = NULL; + } + + return checksum; } PAKFIRE_EXPORT int pakfire_package_set_digest(struct pakfire_package* pkg, enum pakfire_package_digests type, const unsigned char* digest) { Solvable* s = get_solvable(pkg); Pool* pool = s->repo->pool; + Id id; int r = 1; - Id id = pakfire_package_digest2id(type); - if (!id) - return 1; + switch (type) { + case PAKFIRE_PACKAGE_DIGEST_SHA256: + id = REPOKEY_TYPE_SHA256; + break; + + case PAKFIRE_PACKAGE_DIGEST_SHA512: + id = REPOKEY_TYPE_SHA512; + break; + + default: + errno = ENOTSUP; + return 1; + } struct pakfire_repo* repo = pakfire_package_get_repo(pkg); @@ -446,11 +461,14 @@ ERROR: static size_t pakfire_package_digest_length(enum pakfire_package_digests digest) { switch (digest) { + case PAKFIRE_PACKAGE_DIGEST_SHA512: + return 64; + case PAKFIRE_PACKAGE_DIGEST_SHA256: return 32; - case PAKFIRE_PACKAGE_DIGEST_SHA512: - return 64; + case PAKFIRE_PACKAGE_DIGEST_NONE: + return 0; } return 0; @@ -554,13 +572,15 @@ PAKFIRE_EXPORT void pakfire_package_set_maintainer(struct pakfire_package* pkg, static int pakfire_package_make_cache_path(struct pakfire_package* pkg) { const char* filename = pakfire_package_get_filename(pkg); - const char* checksum = pakfire_package_get_hexdigest(pkg, PAKFIRE_PACKAGE_DIGEST_SHA256); - if (!checksum || strlen(checksum) < 3) + enum pakfire_package_digests digest = PAKFIRE_PACKAGE_DIGEST_NONE; + const char* hexdigest = pakfire_package_get_hexdigest(pkg, &digest); + + if (!hexdigest || strlen(hexdigest) < 3) return 1; return pakfire_make_cache_path(pkg->pakfire, pkg->path, - "%c%c/%s/%s", checksum[0], checksum[1], checksum + 2, filename); + "%c%c/%s/%s", hexdigest[0], hexdigest[1], hexdigest + 2, filename); } PAKFIRE_EXPORT const char* pakfire_package_get_path(struct pakfire_package* pkg) { @@ -998,15 +1018,22 @@ PAKFIRE_EXPORT char* pakfire_package_dump(struct pakfire_package* pkg, int flags if (build_id) pakfire_package_dump_add_line(&string, _("Build ID"), build_id); - // Digest SHA512 - const char* digest_sha512 = pakfire_package_get_hexdigest(pkg, PAKFIRE_PACKAGE_DIGEST_SHA512); - if (digest_sha512) - pakfire_package_dump_add_line(&string, _("SHA512 Digest"), digest_sha512); + enum pakfire_package_digests digest = PAKFIRE_PACKAGE_DIGEST_NONE; + + // Digest + const char* hexdigest = pakfire_package_get_hexdigest(pkg, &digest); + switch (digest) { + case PAKFIRE_PACKAGE_DIGEST_SHA512: + pakfire_package_dump_add_line(&string, _("SHA512 Digest"), hexdigest); + break; - // Digest SHA256 - const char* digest_sha256 = pakfire_package_get_hexdigest(pkg, PAKFIRE_PACKAGE_DIGEST_SHA256); - if (digest_sha256) - pakfire_package_dump_add_line(&string, _("SHA256 Digest"), digest_sha256); + case PAKFIRE_PACKAGE_DIGEST_SHA256: + pakfire_package_dump_add_line(&string, _("SHA256 Digest"), hexdigest); + break; + + case PAKFIRE_PACKAGE_DIGEST_NONE: + break; + } // Build time time_t build_time = pakfire_package_get_build_time(pkg);