# 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;
+}
#include <errno.h>
#include <libgen.h>
+#include <limits.h>
#include <linux/limits.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <archive_entry.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
#include <pakfire/constants.h>
#include <pakfire/digest.h>
}
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))
}
// 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
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);