struct pakfire_scriptlet** scriptlets;
int scriptlets_loaded;
+ // Digests
+ struct pakfire_digests digests;
+ unsigned int digests_computed:1;
+
// Verify Status
int verify;
};
return filename;
}
+static int pakfire_archive_compute_digests(struct pakfire_archive* archive) {
+ int r;
+
+ // Skip if already done
+ if (archive->digests_computed)
+ return 0;
+
+ // Calculate digest
+ r = pakfire_digests_compute_from_file(archive->pakfire, &archive->digests,
+ PAKFIRE_ARCHIVE_CHECKSUM, archive->f);
+ if (r) {
+ ERROR(archive->pakfire, "Could not calculate digest of %s: %m\n", archive->path);
+ return r;
+ }
+
+ // Mark as computed
+ archive->digests_computed = 1;
+
+ return 0;
+}
+
/*
A helper function to close the archive and reset our data structures
*/
return buf.st_size;
}
-int pakfire_archive_digest(struct pakfire_archive* archive,
- enum pakfire_digest_types type, unsigned char* digest, size_t* length) {
- int r = 1;
-
- const EVP_MD* md = NULL;
-
- // Select hash function
- switch (type) {
- case PAKFIRE_DIGEST_SHA512:
- md = EVP_sha512();
- break;
-
- case PAKFIRE_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;
- }
+int pakfire_archive_check_digest(struct pakfire_archive* archive,
+ const enum pakfire_digest_types type, const unsigned char* digest, const size_t length) {
+ int r;
- 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;
- }
- }
+ // Compute the digest
+ r = pakfire_archive_compute_digests(archive);
+ if (r)
+ return r;
- // Finalise hash function
- r = EVP_DigestFinal_ex(ctx, digest, (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;
+ // Compare computed with expected digest
+ r = pakfire_digests_compare_one(archive->pakfire, &archive->digests,
+ type, digest, length);
+ if (r) {
+ ERROR(archive->pakfire, "Archive digest does not match");
}
- // Success
- r = 0;
-
-ERROR:
- // Cleanup
- if (ctx)
- EVP_MD_CTX_free(ctx);
-
- rewind(archive->f);
-
return r;
}
static int pakfire_archive_make_package_from_json(struct pakfire_archive* archive,
struct pakfire_repo* repo, struct pakfire_package** package) {
- unsigned char digest[EVP_MAX_MD_SIZE];
- size_t digest_length = 0;
+ struct pakfire_digests digests;
int r;
// Calculate digest
- // This must be done before we create the package object
- r = pakfire_archive_digest(archive, PAKFIRE_DIGEST_SHA512, digest, &digest_length);
+ r = pakfire_digests_compute_from_file(archive->pakfire, &digests,
+ PAKFIRE_ARCHIVE_CHECKSUM, archive->f);
if (r) {
ERROR(archive->pakfire, "Could not calculate digest of %s: %m\n", archive->path);
return r;
pakfire_package_set_path(pkg, archive->path);
// Set digest
- pakfire_package_set_digest(pkg, PAKFIRE_DIGEST_SHA512, digest);
+ switch (PAKFIRE_ARCHIVE_CHECKSUM) {
+ case PAKFIRE_DIGEST_SHA512:
+ pakfire_package_set_digest(pkg, PAKFIRE_ARCHIVE_CHECKSUM, digests.sha512);
+ break;
+
+ case PAKFIRE_DIGEST_SHA256:
+ pakfire_package_set_digest(pkg, PAKFIRE_ARCHIVE_CHECKSUM, digests.sha256);
+ break;
+
+ case PAKFIRE_DIGEST_UNDEFINED:
+ r = 1;
+ goto ERROR;
+ }
// Vendor
const char* vendor = pakfire_archive_metadata_get(archive, "vendor", NULL);
// Success!
*package = pkg;
return 0;
+
+ERROR:
+ return r;
}
static int pakfire_archive_make_legacy_package(struct pakfire_archive* archive,
struct pakfire_repo* repo, struct pakfire_package** package) {
- unsigned char digest[EVP_MAX_MD_SIZE];
- size_t digest_length = 0;
+ struct pakfire_digests digests;
int r;
// Calculate digest
- r = pakfire_archive_digest(archive, PAKFIRE_DIGEST_SHA512, digest, &digest_length);
+ r = pakfire_digests_compute_from_file(archive->pakfire, &digests,
+ PAKFIRE_ARCHIVE_CHECKSUM, archive->f);
if (r) {
ERROR(archive->pakfire, "Could not calculate digest of %s: %m\n", archive->path);
return r;
}
}
- // Set digests
- pakfire_package_set_digest(pkg, PAKFIRE_DIGEST_SHA512, digest);
+ // Set digest
+ switch (PAKFIRE_ARCHIVE_CHECKSUM) {
+ case PAKFIRE_DIGEST_SHA512:
+ pakfire_package_set_digest(pkg, PAKFIRE_ARCHIVE_CHECKSUM, digests.sha512);
+ break;
+
+ case PAKFIRE_DIGEST_SHA256:
+ pakfire_package_set_digest(pkg, PAKFIRE_ARCHIVE_CHECKSUM, digests.sha256);
+ break;
+
+ case PAKFIRE_DIGEST_UNDEFINED:
+ break;
+ }
*package = pkg;
#include <errno.h>
#include <stdlib.h>
-#include <openssl/crypto.h>
-#include <openssl/evp.h>
-
#include <solv/pool_fileconflicts.h>
#include <solv/transaction.h>
static int pakfire_transaction_verify(struct pakfire_transaction* transaction,
struct pakfire_package* pkg, struct pakfire_archive* archive) {
- int r;
-
const char* nevra = pakfire_package_get_nevra(pkg);
// Nothing to do if this step does not have an archive
return 0;
}
- enum pakfire_digest_types digest_type = 0;
+ enum pakfire_digest_types digest_type = PAKFIRE_DIGEST_UNDEFINED;
// Fetch digest from package
const unsigned char* expected_digest = pakfire_package_get_digest(pkg, &digest_type);
return 0;
}
- unsigned char computed_digest[EVP_MAX_MD_SIZE];
- size_t digest_length = 0;
+ const size_t length = pakfire_digest_length(digest_type);
- // Compute digest of the archive
- r = pakfire_archive_digest(archive, digest_type, computed_digest, &digest_length);
- if (r) {
- ERROR(transaction->pakfire, "Could not compute digest for %s: %m\n", nevra);
- return r;
- }
-
- // Compare digests
- r = CRYPTO_memcmp(computed_digest, expected_digest, digest_length);
- if (r) {
- ERROR(transaction->pakfire, "Digests of %s do not match\n", nevra);
- return 1;
- }
-
- return 0;
+ // Check against the digest of the archive
+ return pakfire_archive_check_digest(archive, digest_type, expected_digest, length);
}
static int pakfire_transaction_run_script(struct pakfire_transaction* transaction,