]> git.ipfire.org Git - pakfire.git/commitdiff
digests: Add a compute and comparison function
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 24 Aug 2022 10:46:41 +0000 (10:46 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 24 Aug 2022 10:46:41 +0000 (10:46 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/digest.c
src/libpakfire/file.c
src/libpakfire/include/pakfire/digest.h

index e69e9afa95bede13165ed03f07eb13ad0d518d15..02cee06e93c284f0f8390fce21d49ef0578252ac 100644 (file)
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
 #                                                                             #
 #############################################################################*/
+
+#include <stdio.h>
+
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
+#include <pakfire/digest.h>
+#include <pakfire/logging.h>
+#include <pakfire/pakfire.h>
+#include <pakfire/private.h>
+
+static EVP_MD_CTX* __pakfire_digest_setup(struct pakfire* pakfire, const EVP_MD* md) {
+       EVP_MD_CTX* ctx = NULL;
+       int r;
+
+       // Setup a new context
+       ctx = EVP_MD_CTX_new();
+       if (!ctx) {
+               ERROR(pakfire, "Could not initialize OpenSSL context: %s\n",
+                       ERR_error_string(ERR_get_error(), NULL));
+               r = 1;
+               goto ERROR;
+       }
+
+       // Setup digest
+       r = EVP_DigestInit_ex(ctx, md, NULL);
+       if (r != 1) {
+               ERROR(pakfire, "Could not setup digest: %s\n",
+                       ERR_error_string(ERR_get_error(), NULL));
+               r = 1;
+               goto ERROR;
+       }
+
+       return ctx;
+
+ERROR:
+       if (ctx)
+               EVP_MD_CTX_free(ctx);
+
+       return NULL;
+}
+
+int pakfire_digests_compute_from_file(struct pakfire* pakfire,
+               struct pakfire_digests* digests, const int types, FILE* f) {
+       EVP_MD_CTX* sha512_ctx = NULL;
+       EVP_MD_CTX* sha256_ctx = NULL;
+       char buffer[PAKFIRE_BUFFER_SIZE];
+       int r = 1;
+
+       // Initialize context for SHA-512
+       if (types & PAKFIRE_DIGEST_SHA512) {
+               sha512_ctx = __pakfire_digest_setup(pakfire, EVP_sha512());
+               if (!sha512_ctx)
+                       goto ERROR;
+       }
+
+       // Initialize context for SHA-256
+       if (types & PAKFIRE_DIGEST_SHA256) {
+               sha512_ctx = __pakfire_digest_setup(pakfire, EVP_sha256());
+               if (!sha512_ctx)
+                       goto ERROR;
+       }
+
+       // Read the file into the hash functions
+       while (!feof(f)) {
+               size_t bytes_read = fread(buffer, 1, sizeof(buffer), f);
+
+               // Raise any reading errors
+               if (ferror(f)) {
+                       r = 1;
+                       goto ERROR;
+               }
+
+               // SHA-512
+               r = EVP_DigestUpdate(sha512_ctx, buffer, bytes_read);
+               if (r != 1) {
+                       ERROR(pakfire, "EVP_Digest_Update() failed: %s\n",
+                               ERR_error_string(ERR_get_error(), NULL));
+                       r = 1;
+                       goto ERROR;
+               }
+
+               // SHA-256
+               r = EVP_DigestUpdate(sha256_ctx, buffer, bytes_read);
+               if (r != 1) {
+                       ERROR(pakfire, "EVP_Digest_Update() failed: %s\n",
+                               ERR_error_string(ERR_get_error(), NULL));
+                       r = 1;
+                       goto ERROR;
+               }
+       }
+
+       // Finalize SHA-512
+       r = EVP_DigestFinal_ex(sha512_ctx, digests->sha512, NULL);
+       if (r != 1) {
+               ERROR(pakfire, "EVP_DigestFinal_ex() failed: %s\n",
+                       ERR_error_string(ERR_get_error(), NULL));
+               r = 1;
+               goto ERROR;
+       }
+
+       // Finalize SHA-256
+       r = EVP_DigestFinal_ex(sha256_ctx, digests->sha256, NULL);
+       if (r != 1) {
+               ERROR(pakfire, "EVP_DigestFinal_ex() failed: %s\n",
+                       ERR_error_string(ERR_get_error(), NULL));
+               r = 1;
+               goto ERROR;
+       }
+
+ERROR:
+       if (sha512_ctx)
+               EVP_MD_CTX_free(sha512_ctx);
+       if (sha256_ctx)
+               EVP_MD_CTX_free(sha256_ctx);
+
+       return r;
+}
+
+int pakfire_digests_compare(struct pakfire* pakfire, const struct pakfire_digests* digests1,
+               const struct pakfire_digests* digests2, const int types) {
+       int r;
+
+       // Check if we are at least comparing one type
+       if (!types) {
+               errno = EINVAL;
+               return 1;
+       }
+
+       // Check SHA-512
+       if (types & PAKFIRE_DIGEST_SHA512) {
+               r = CRYPTO_memcmp(digests1->sha512, digests2->sha512, sizeof(digests1->sha512));
+               if (r) {
+                       DEBUG(pakfire, "SHA-512 digest does not match\n");
+                       return 1;
+               }
+       }
+
+       // Check SHA-256
+       if (types & PAKFIRE_DIGEST_SHA256) {
+               r = CRYPTO_memcmp(digests1->sha256, digests2->sha256, sizeof(digests1->sha256));
+               if (r) {
+                       DEBUG(pakfire, "SHA-256 digest does not match\n");
+                       return 1;
+               }
+       }
+
+       // All digests match
+       return 0;
+}
index 54e393e26c0a2eb7e4b86a88cb962880031136c7..eafa22c243783150e1965f72c2dd33f91a9c7119 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <errno.h>
 #include <libgen.h>
+#include <limits.h>
 #include <linux/limits.h>
 #include <stdlib.h>
 #include <string.h>
@@ -28,8 +29,6 @@
 #include <time.h>
 
 #include <archive_entry.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
 
 #include <pakfire/constants.h>
 #include <pakfire/digest.h>
@@ -733,14 +732,11 @@ static int pakfire_file_verify_timestamps(struct pakfire_file* file, const struc
 }
 
 static int pakfire_file_verify_payload(struct pakfire_file* file, const struct stat* st) {
-       char buffer[PAKFIRE_BUFFER_SIZE];
        FILE* f = NULL;
        int r;
 
-       EVP_MD_CTX* sha512_ctx = NULL;
-       EVP_MD_CTX* sha256_ctx = NULL;
-
        struct pakfire_digests computed_digests;
+       int digest_types = PAKFIRE_DIGEST_UNDEFINED;
 
        // Nothing to do for anything that isn't a regular file
        if (!S_ISREG(st->st_mode))
@@ -753,46 +749,15 @@ static int pakfire_file_verify_payload(struct pakfire_file* file, const struct s
        }
 
        // Check if this file has any digests at all
-       if (!pakfire_file_has_digest(file->digests.sha512) &&
-                       !pakfire_file_has_digest(file->digests.sha256)) {
-               ERROR(file->pakfire, "%s: No digests available\n", file->path);
-               return 0;
-       }
-
-       // Initialize context for SHA-512
-       sha512_ctx = EVP_MD_CTX_new();
-       if (!sha512_ctx) {
-               ERROR(file->pakfire, "Could not initialize OpenSSL context: %s\n",
-                       ERR_error_string(ERR_get_error(), NULL));
-               r = 1;
-               goto ERROR;
-       }
-
-       // Setup SHA-512 digest
-       r = EVP_DigestInit_ex(sha512_ctx, EVP_sha512(), NULL);
-       if (r != 1) {
-               ERROR(file->pakfire, "Could not setup SHA-512 digest: %s\n",
-                       ERR_error_string(ERR_get_error(), NULL));
-               r = 1;
-               goto ERROR;
-       }
+       if (pakfire_file_has_digest(file->digests.sha512))
+               digest_types |= PAKFIRE_DIGEST_SHA512;
 
-       // Initialize context for SHA-256
-       sha256_ctx = EVP_MD_CTX_new();
-       if (!sha256_ctx) {
-               ERROR(file->pakfire, "Could not initialize OpenSSL context: %s\n",
-                       ERR_error_string(ERR_get_error(), NULL));
-               r = 1;
-               goto ERROR;
-       }
+       if (pakfire_file_has_digest(file->digests.sha256))
+               digest_types |= PAKFIRE_DIGEST_SHA256;
 
-       // Setup SHA-256 digest
-       r = EVP_DigestInit_ex(sha256_ctx, EVP_sha256(), NULL);
-       if (r != 1) {
-               ERROR(file->pakfire, "Could not setup SHA-256 digest: %s\n",
-                       ERR_error_string(ERR_get_error(), NULL));
-               r = 1;
-               goto ERROR;
+       if (!digest_types) {
+               ERROR(file->pakfire, "%s: No digests available\n", file->path);
+               return 0;
        }
 
        // Open the file
@@ -802,79 +767,20 @@ static int pakfire_file_verify_payload(struct pakfire_file* file, const struct s
                goto ERROR;
        }
 
-       // Read the file into the hash functions
-       while (!feof(f)) {
-               size_t bytes_read = fread(buffer, 1, sizeof(buffer), f);
-
-               // Raise any reading errors
-               if (ferror(f)) {
-                       r = 1;
-                       goto ERROR;
-               }
-
-               // SHA-512
-               r = EVP_DigestUpdate(sha512_ctx, buffer, bytes_read);
-               if (r != 1) {
-                       ERROR(file->pakfire, "EVP_Digest_Update() failed: %s\n",
-                               ERR_error_string(ERR_get_error(), NULL));
-                       r = 1;
-                       goto ERROR;
-               }
-
-               // SHA-256
-               r = EVP_DigestUpdate(sha256_ctx, buffer, bytes_read);
-               if (r != 1) {
-                       ERROR(file->pakfire, "EVP_Digest_Update() failed: %s\n",
-                               ERR_error_string(ERR_get_error(), NULL));
-                       r = 1;
-                       goto ERROR;
-               }
-       }
-
-       // Finalize SHA-512
-       r = EVP_DigestFinal_ex(sha512_ctx, computed_digests.sha512, NULL);
-       if (r != 1) {
-               ERROR(file->pakfire, "EVP_DigestFinal_ex() failed: %s\n",
-                       ERR_error_string(ERR_get_error(), NULL));
-               r = 1;
-               goto ERROR;
-       }
-
-       // Finalize SHA-256
-       r = EVP_DigestFinal_ex(sha256_ctx, computed_digests.sha256, NULL);
-       if (r != 1) {
-               ERROR(file->pakfire, "EVP_DigestFinal_ex() failed: %s\n",
-                       ERR_error_string(ERR_get_error(), NULL));
-               r = 1;
+       // Compute digests
+       r = pakfire_digests_compute_from_file(file->pakfire, &computed_digests, digest_types, f);
+       if (r)
                goto ERROR;
-       }
 
-       // Check SHA-512
-       r = CRYPTO_memcmp(computed_digests.sha512,
-               file->digests.sha512, sizeof(file->digests.sha512));
+       // Compare digests
+       r = pakfire_digests_compare(file->pakfire, &file->digests, &computed_digests, digest_types);
        if (r) {
                file->verify_status |= PAKFIRE_FILE_PAYLOAD_CHANGED;
 
-               DEBUG(file->pakfire, "%s: SHA-512 digest does not match\n", file->path);
+               DEBUG(file->pakfire, "%s: Digest(s) do not match\n", file->path);
        }
 
-       // Check SHA-256
-       r = CRYPTO_memcmp(computed_digests.sha256,
-               file->digests.sha256, sizeof(file->digests.sha256));
-       if (r) {
-               file->verify_status |= PAKFIRE_FILE_PAYLOAD_CHANGED;
-
-               DEBUG(file->pakfire, "%s: SHA-256 digest does not match\n", file->path);
-       }
-
-       // Success
-       r = 0;
-
 ERROR:
-       if (sha512_ctx)
-               EVP_MD_CTX_free(sha512_ctx);
-       if (sha256_ctx)
-               EVP_MD_CTX_free(sha256_ctx);
        if (f)
                fclose(f);
 
index 5ed91ea7f4a4bffe81d65773d73fa07b929d9685..df6a3b44652eba0b1a036682d5e765012ca86cba 100644 (file)
@@ -30,8 +30,12 @@ enum pakfire_digest_types {
 
 #ifdef PAKFIRE_PRIVATE
 
+#include <stdio.h>
+
 #include <openssl/sha.h>
 
+#include <pakfire/pakfire.h>
+
 // Digests
 struct pakfire_digests {
        // SHA-512
@@ -41,6 +45,12 @@ struct pakfire_digests {
        unsigned char sha256[SHA256_DIGEST_LENGTH];
 };
 
+int pakfire_digests_compute_from_file(struct pakfire* pakfire,
+       struct pakfire_digests* digests, int flags, FILE* f);
+
+int pakfire_digests_compare(struct pakfire* pakfire, const struct pakfire_digests* digests1,
+       const struct pakfire_digests* digests2, const int types);
+
 #endif
 
 #endif /* PAKFIRE_DIGEST_H */