diff options
author | Timo Teräs <timo.teras@iki.fi> | 2021-06-09 18:21:40 +0300 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2021-06-11 13:35:32 +0300 |
commit | 7ce4cc4b739127c0b4b36ffcabc007e5781b13c9 (patch) | |
tree | 1f751b9dc62c59a1fa1e05d34550961f39719137 /src | |
parent | 7c9f001cda932c74164e8aaa6740dcb6d24aa62f (diff) | |
download | apk-tools-7ce4cc4b739127c0b4b36ffcabc007e5781b13c9.tar.gz apk-tools-7ce4cc4b739127c0b4b36ffcabc007e5781b13c9.tar.bz2 apk-tools-7ce4cc4b739127c0b4b36ffcabc007e5781b13c9.tar.xz apk-tools-7ce4cc4b739127c0b4b36ffcabc007e5781b13c9.zip |
add basic abstraction for cryptographic operations
- basic digesting and signing apis (subject still to fine tuning)
- update digest code, and adb signing for the thin wrapping layer
- old v1 package and database handling not updated
- default mkpkg file hash to sha256
ref #10744
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile | 2 | ||||
-rw-r--r-- | src/adb.c | 84 | ||||
-rw-r--r-- | src/adb.h | 8 | ||||
-rw-r--r-- | src/apk.c | 2 | ||||
-rw-r--r-- | src/apk_blob.h | 7 | ||||
-rw-r--r-- | src/apk_crypto.h | 174 | ||||
-rw-r--r-- | src/apk_io.h | 15 | ||||
-rw-r--r-- | src/apk_openssl.h | 23 | ||||
-rw-r--r-- | src/apk_trust.h | 14 | ||||
-rw-r--r-- | src/app_add.c | 18 | ||||
-rw-r--r-- | src/app_audit.c | 4 | ||||
-rw-r--r-- | src/app_fetch.c | 2 | ||||
-rw-r--r-- | src/app_index.c | 4 | ||||
-rw-r--r-- | src/app_manifest.c | 7 | ||||
-rw-r--r-- | src/app_mkndx.c | 4 | ||||
-rw-r--r-- | src/app_mkpkg.c | 4 | ||||
-rw-r--r-- | src/app_verify.c | 4 | ||||
-rw-r--r-- | src/context.c | 2 | ||||
-rw-r--r-- | src/crypto_openssl.c | 112 | ||||
-rw-r--r-- | src/database.c | 69 | ||||
-rw-r--r-- | src/io.c | 71 | ||||
-rw-r--r-- | src/io_archive.c | 16 | ||||
-rw-r--r-- | src/meson.build | 2 | ||||
-rw-r--r-- | src/package.c | 8 | ||||
-rw-r--r-- | src/trust.c | 66 |
25 files changed, 462 insertions, 260 deletions
diff --git a/src/Makefile b/src/Makefile index 6b1b237..4df1e63 100644 --- a/src/Makefile +++ b/src/Makefile @@ -19,7 +19,7 @@ ZLIB_LIBS := $(shell $(PKG_CONFIG) --libs zlib) libapk_soname := 3.12.0 libapk_so := $(obj)/libapk.so.$(libapk_soname) libapk.so.$(libapk_soname)-objs := \ - adb.o common.o context.o database.o package.o commit.o solver.o \ + adb.o common.o context.o database.o digest.o package.o commit.o solver.o \ trust.o version.o atom.o blob.o hash.o print.o \ io.o io_url.o io_gunzip.o io_archive.o @@ -866,21 +866,22 @@ int adb_c_block_data(struct apk_ostream *os, apk_blob_t hdr, uint32_t size, stru int adb_c_block_copy(struct apk_ostream *os, struct adb_block *b, struct apk_istream *is, struct adb_verify_ctx *vfy) { - EVP_MD_CTX *mdctx = NULL; int r; r = apk_ostream_write(os, b, sizeof *b); if (r < 0) return r; if (vfy) { - mdctx = EVP_MD_CTX_new(); - EVP_DigestInit_ex(mdctx, EVP_sha512(), 0); - } - r = apk_stream_copy(is, os, adb_block_size(b), 0, 0, mdctx); - if (vfy) { - EVP_DigestFinal_ex(mdctx, vfy->sha512, 0); - EVP_MD_CTX_free(mdctx); - vfy->calc |= (1 << ADB_HASH_SHA512); + struct apk_digest_ctx dctx; + const uint8_t alg = APK_DIGEST_SHA512; + + apk_digest_ctx_init(&dctx, alg); + r = apk_stream_copy(is, os, adb_block_size(b), 0, 0, &dctx); + apk_digest_ctx_final(&dctx, &vfy->sha512); + vfy->calc |= (1 << alg); + apk_digest_ctx_free(&dctx); + } else { + r = apk_stream_copy(is, os, adb_block_size(b), 0, 0, 0); } return r; } @@ -906,28 +907,38 @@ int adb_c_create(struct apk_ostream *os, struct adb *db, struct apk_trust *t) } /* Signatures */ -static int adb_verify_ctx_calc(struct adb_verify_ctx *vfy, unsigned int hash_alg, apk_blob_t data, apk_blob_t *pmd) +static int adb_digest_adb(struct adb_verify_ctx *vfy, unsigned int hash_alg, apk_blob_t data, apk_blob_t *pmd) { - const EVP_MD *evp; - apk_blob_t md; + struct apk_digest *d; + int r; switch (hash_alg) { - case ADB_HASH_SHA512: - evp = EVP_sha512(); - *pmd = md = APK_BLOB_BUF(vfy->sha512); + case APK_DIGEST_SHA512: + d = &vfy->sha512; break; default: return -ENOTSUP; } if (!(vfy->calc & (1 << hash_alg))) { - unsigned int sz = md.len; if (APK_BLOB_IS_NULL(data)) return -ENOMSG; - if (EVP_Digest(data.ptr, data.len, (unsigned char*) md.ptr, &sz, evp, NULL) != 1 || - sz != md.len) - return -EIO; + r = apk_digest_calc(d, hash_alg, data.ptr, data.len); + if (r != 0) return r; vfy->calc |= (1 << hash_alg); } + + *pmd = APK_DIGEST_BLOB(*d); + return 0; +} + +static int adb_digest_v0_signature(struct apk_digest_ctx *dctx, struct adb_header *hdr, struct adb_sign_v0 *sig0, apk_blob_t md) +{ + int r; + + if ((r = apk_digest_ctx_update(dctx, hdr, sizeof *hdr)) != 0 || + (r = apk_digest_ctx_update(dctx, sig0, sizeof *sig0)) != 0 || + (r = apk_digest_ctx_update(dctx, md.ptr, md.len)) != 0) + return r; return 0; } @@ -948,33 +959,27 @@ int adb_trust_write_signatures(struct apk_trust *trust, struct adb *db, struct a memset(vfy, 0, sizeof *vfy); } - r = adb_verify_ctx_calc(vfy, ADB_HASH_SHA512, db->adb, &md); + r = adb_digest_adb(vfy, APK_DIGEST_SHA512, db->adb, &md); if (r) return r; list_for_each_entry(tkey, &trust->private_key_list, key_node) { sig.v0 = (struct adb_sign_v0) { .hdr.sign_ver = 0, - .hdr.hash_alg = ADB_HASH_SHA512, + .hdr.hash_alg = APK_DIGEST_SHA512, }; memcpy(sig.v0.id, tkey->key.id, sizeof(sig.v0.id)); siglen = sizeof sig.buf - sizeof sig.v0; - EVP_MD_CTX_set_pkey_ctx(trust->mdctx, NULL); - if (EVP_DigestSignInit(trust->mdctx, NULL, EVP_sha512(), NULL, tkey->key.key) != 1 || - EVP_DigestUpdate(trust->mdctx, &db->hdr, sizeof db->hdr) != 1 || - EVP_DigestUpdate(trust->mdctx, &sig.v0, sizeof sig.v0) != 1 || - EVP_DigestUpdate(trust->mdctx, md.ptr, md.len) != 1 || - EVP_DigestSignFinal(trust->mdctx, sig.v0.sig, &siglen) != 1) { - ERR_print_errors_fp(stdout); - goto err_io; - } + + if ((r = apk_sign_start(&trust->dctx, &tkey->key)) != 0 || + (r = adb_digest_v0_signature(&trust->dctx, &db->hdr, &sig.v0, md)) != 0 || + (r = apk_sign(&trust->dctx, sig.v0.sig, &siglen)) != 0) + goto err; r = adb_c_block(os, ADB_BLOCK_SIG, APK_BLOB_PTR_LEN((char*) &sig, sizeof(sig.v0) + siglen)); if (r < 0) goto err; } return 0; -err_io: - r = -EIO; err: apk_ostream_cancel(os, r); return r; @@ -996,17 +1001,12 @@ int adb_trust_verify_signature(struct apk_trust *trust, struct adb *db, struct a list_for_each_entry(tkey, &trust->trusted_key_list, key_node) { if (memcmp(sig0->id, tkey->key.id, sizeof sig0->id) != 0) continue; - if (adb_verify_ctx_calc(vfy, sig->hash_alg, db->adb, &md) != 0) continue; - - EVP_MD_CTX_set_pkey_ctx(trust->mdctx, NULL); - if (EVP_DigestVerifyInit(trust->mdctx, NULL, EVP_sha512(), NULL, tkey->key.key) != 1 || - EVP_DigestUpdate(trust->mdctx, &db->hdr, sizeof db->hdr) != 1 || - EVP_DigestUpdate(trust->mdctx, sig0, sizeof *sig0) != 1 || - EVP_DigestUpdate(trust->mdctx, md.ptr, md.len) != 1 || - EVP_DigestVerifyFinal(trust->mdctx, sig0->sig, sigb.len - sizeof(*sig0)) != 1) { - ERR_clear_error(); + if (adb_digest_adb(vfy, sig->hash_alg, db->adb, &md) != 0) continue; + + if (apk_verify_start(&trust->dctx, &tkey->key) != 0 || + adb_digest_v0_signature(&trust->dctx, &db->hdr, sig0, md) != 0 || + apk_verify(&trust->dctx, sig0->sig, sigb.len - sizeof *sig0) != 0) continue; - } return 0; } @@ -84,12 +84,6 @@ struct adb_sign_v0 { uint8_t sig[0]; }; -/* Hash algorithms */ -#define ADB_HASH_NONE 0x00 -#define ADB_HASH_SHA1 0x01 -#define ADB_HASH_SHA256 0x02 -#define ADB_HASH_SHA512 0x03 - /* Block enumeration */ struct adb_block *adb_block_first(apk_blob_t b); struct adb_block *adb_block_next(struct adb_block *cur, apk_blob_t b); @@ -237,7 +231,7 @@ int adb_c_create(struct apk_ostream *os, struct adb *db, struct apk_trust *t); /* Trust */ struct adb_verify_ctx { uint32_t calc; - uint8_t sha512[64]; + struct apk_digest sha512; }; int adb_trust_write_signatures(struct apk_trust *trust, struct adb *db, struct adb_verify_ctx *vfy, struct apk_ostream *os); @@ -428,7 +428,7 @@ int main(int argc, char **argv) ctx.force |= applet->forced_force; } - apk_openssl_init(); + apk_crypto_init(); setup_automatic_flags(&ctx); fetchConnectionCacheInit(32, 4); diff --git a/src/apk_blob.h b/src/apk_blob.h index e222739..e2c7c4a 100644 --- a/src/apk_blob.h +++ b/src/apk_blob.h @@ -112,13 +112,6 @@ static inline char *apk_blob_chr(apk_blob_t b, unsigned char ch) return memchr(b.ptr, ch, b.len); } -static inline const int apk_checksum_compare(const struct apk_checksum *a, - const struct apk_checksum *b) -{ - return apk_blob_compare(APK_BLOB_PTR_LEN((char *) a->data, a->type), - APK_BLOB_PTR_LEN((char *) b->data, b->type)); -} - void apk_blob_push_blob(apk_blob_t *to, apk_blob_t literal); void apk_blob_push_uint(apk_blob_t *to, unsigned int value, int radix); void apk_blob_push_csum(apk_blob_t *to, struct apk_checksum *csum); diff --git a/src/apk_crypto.h b/src/apk_crypto.h new file mode 100644 index 0000000..35d27aa --- /dev/null +++ b/src/apk_crypto.h @@ -0,0 +1,174 @@ +/* apk_crypt.c - Alpine Package Keeper (APK) + * + * Copyright (C) 2021 Timo Teräs <timo.teras@iki.fi> + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#ifndef APK_CRYPTO_H +#define APK_CRYPTO_H + +#include <assert.h> +#include <errno.h> +#include <openssl/evp.h> +#include "apk_openssl.h" + +// Digest + +struct apk_digest_ctx { + EVP_MD_CTX *mdctx; + uint8_t alg; +}; + +#define APK_DIGEST_NONE 0x00 +#define APK_DIGEST_MD5 0x01 +#define APK_DIGEST_SHA1 0x02 +#define APK_DIGEST_SHA256 0x03 +#define APK_DIGEST_SHA512 0x04 + +#define APK_DIGEST_MAX_LENGTH 64 // longest is SHA512 + +const char *apk_digest_alg_str(uint8_t); +uint8_t apk_digest_alg_from_csum(int); + +struct apk_digest { + uint8_t alg, len; + uint8_t data[APK_DIGEST_MAX_LENGTH]; +}; + +#define APK_DIGEST_BLOB(d) APK_BLOB_PTR_LEN((void*)((d).data), (d).len) + +static inline const EVP_MD *apk_digest_alg_to_evp(uint8_t alg) { + switch (alg) { + case APK_DIGEST_NONE: return EVP_md_null(); + case APK_DIGEST_MD5: return EVP_md5(); + case APK_DIGEST_SHA1: return EVP_sha1(); + case APK_DIGEST_SHA256: return EVP_sha256(); + case APK_DIGEST_SHA512: return EVP_sha512(); + default: + assert(alg); + return EVP_md_null(); + } +} + +static inline int apk_digest_alg_len(uint8_t alg) { + switch (alg) { + case APK_DIGEST_MD5: return 16; + case APK_DIGEST_SHA1: return 20; + case APK_DIGEST_SHA256: return 32; + case APK_DIGEST_SHA512: return 64; + default: + assert(alg); + return 0; + } +} + +static inline void apk_digest_reset(struct apk_digest *d) { + d->len = 0; + d->alg = APK_DIGEST_NONE; +} + +static inline void apk_digest_set(struct apk_digest *d, uint8_t alg) { + d->alg = alg; + d->len = apk_digest_alg_len(alg); +} + +static inline int apk_digest_calc(struct apk_digest *d, uint8_t alg, const void *ptr, size_t sz) +{ + unsigned int md_sz = sizeof d->data; + if (EVP_Digest(ptr, sz, d->data, &md_sz, apk_digest_alg_to_evp(alg), 0) != 1) + return -EIO; + d->alg = alg; + d->len = md_sz; + return 0; +} + +static inline int apk_digest_ctx_init(struct apk_digest_ctx *dctx, uint8_t alg) { + dctx->mdctx = EVP_MD_CTX_new(); + if (!dctx->mdctx) return -ENOMEM; + dctx->alg = alg; + EVP_MD_CTX_set_flags(dctx->mdctx, EVP_MD_CTX_FLAG_FINALISE); + EVP_DigestInit_ex(dctx->mdctx, apk_digest_alg_to_evp(alg), 0); + return 0; +} + +static inline void apk_digest_ctx_free(struct apk_digest_ctx *dctx) { + EVP_MD_CTX_free(dctx->mdctx); + dctx->mdctx = 0; +} + +static inline int apk_digest_ctx_update(struct apk_digest_ctx *dctx, const void *ptr, size_t sz) { + return EVP_DigestUpdate(dctx->mdctx, ptr, sz) == 1 ? 0 : -EIO; +} + +static inline int apk_digest_ctx_final(struct apk_digest_ctx *dctx, struct apk_digest *d) { + unsigned int mdlen = sizeof d->data; + if (EVP_DigestFinal_ex(dctx->mdctx, d->data, &mdlen) != 1) { + apk_digest_reset(d); + return -EIO; + } + d->alg = dctx->alg; + d->len = mdlen; + return 0; +} + +#include "apk_blob.h" +static inline int apk_digest_cmp_csum(const struct apk_digest *d, const struct apk_checksum *csum) +{ + return apk_blob_compare(APK_DIGEST_BLOB(*d), APK_BLOB_CSUM(*csum)); +} +static inline void apk_checksum_from_digest(struct apk_checksum *csum, const struct apk_digest *d) +{ + csum->type = d->len; + memcpy(csum->data, d->data, d->len); +} + +// Asymmetric keys + +struct apk_pkey { + uint8_t id[16]; + EVP_PKEY *key; +}; + +int apk_pkey_init(struct apk_pkey *pkey, EVP_PKEY *key); +void apk_pkey_free(struct apk_pkey *pkey); +int apk_pkey_load(struct apk_pkey *pkey, int dirfd, const char *fn); + +// Signing + +int apk_sign_start(struct apk_digest_ctx *, struct apk_pkey *); +int apk_sign(struct apk_digest_ctx *, void *, size_t *); +int apk_verify_start(struct apk_digest_ctx *, struct apk_pkey *); +int apk_verify(struct apk_digest_ctx *, void *, size_t); + +// Initializiation + +#if OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL) + +static inline void apk_crypto_cleanup(void) +{ + EVP_cleanup(); +#ifndef OPENSSL_NO_ENGINE + ENGINE_cleanup(); +#endif + CRYPTO_cleanup_all_ex_data(); +} + +static inline void apk_crypto_init(void) +{ + atexit(apk_crypto_cleanup); + OpenSSL_add_all_algorithms(); +#ifndef OPENSSL_NO_ENGINE + ENGINE_load_builtin_engines(); + ENGINE_register_all_complete(); +#endif +} + +#else + +static inline void apk_crypto_init(void) {} + +#endif + +#endif diff --git a/src/apk_io.h b/src/apk_io.h index 030255e..a0025be 100644 --- a/src/apk_io.h +++ b/src/apk_io.h @@ -16,6 +16,7 @@ #include "apk_defines.h" #include "apk_blob.h" #include "apk_atom.h" +#include "apk_crypto.h" struct apk_id_hash { int empty; @@ -50,8 +51,8 @@ struct apk_file_info { mode_t mode; time_t mtime; dev_t device; - struct apk_checksum csum; - struct apk_checksum xattr_csum; + struct apk_digest digest; + struct apk_digest xattr_digest; struct apk_xattr_array *xattrs; }; @@ -93,7 +94,7 @@ static inline apk_blob_t apk_istream_get_all(struct apk_istream *is) { return ap ssize_t apk_istream_splice(struct apk_istream *is, int fd, size_t size, apk_progress_cb cb, void *cb_ctx); ssize_t apk_stream_copy(struct apk_istream *is, struct apk_ostream *os, size_t size, - apk_progress_cb cb, void *cb_ctx, EVP_MD_CTX *mdctx); + apk_progress_cb cb, void *cb_ctx, struct apk_digest_ctx *dctx); static inline struct apk_istream *apk_istream_from_url(const char *url, time_t since) { @@ -170,11 +171,13 @@ apk_blob_t apk_blob_from_file(int atfd, const char *file); int apk_blob_to_file(int atfd, const char *file, apk_blob_t b, unsigned int flags); #define APK_FI_NOFOLLOW 0x80000000 -#define APK_FI_XATTR_CSUM(x) (((x) & 0xff) << 8) -#define APK_FI_CSUM(x) (((x) & 0xff)) +#define APK_FI_XATTR_DIGEST(x) (((x) & 0xff) << 8) +#define APK_FI_XATTR_CSUM(x) APK_FI_XATTR_DIGEST(apk_digest_alg_from_csum(x)) +#define APK_FI_DIGEST(x) (((x) & 0xff)) +#define APK_FI_CSUM(x) APK_FI_DIGEST(apk_digest_alg_from_csum(x)) int apk_fileinfo_get(int atfd, const char *filename, unsigned int flags, struct apk_file_info *fi, struct apk_atom_pool *atoms); -void apk_fileinfo_hash_xattr(struct apk_file_info *fi); +void apk_fileinfo_hash_xattr(struct apk_file_info *fi, uint8_t alg); void apk_fileinfo_free(struct apk_file_info *fi); typedef int apk_dir_file_cb(void *ctx, int dirfd, const char *entry); diff --git a/src/apk_openssl.h b/src/apk_openssl.h index c0abdf2..3867101 100644 --- a/src/apk_openssl.h +++ b/src/apk_openssl.h @@ -29,29 +29,6 @@ static inline void EVP_MD_CTX_free(EVP_MD_CTX *mdctx) return EVP_MD_CTX_destroy(mdctx); } -static inline void apk_openssl_cleanup(void) -{ - EVP_cleanup(); -#ifndef OPENSSL_NO_ENGINE - ENGINE_cleanup(); -#endif - CRYPTO_cleanup_all_ex_data(); -} - -static inline void apk_openssl_init(void) -{ - atexit(apk_openssl_cleanup); - OpenSSL_add_all_algorithms(); -#ifndef OPENSSL_NO_ENGINE - ENGINE_load_builtin_engines(); - ENGINE_register_all_complete(); -#endif -} - -#else - -static inline void apk_openssl_init(void) {} - #endif #endif diff --git a/src/apk_trust.h b/src/apk_trust.h index 89c5d7a..0f612f9 100644 --- a/src/apk_trust.h +++ b/src/apk_trust.h @@ -9,17 +9,8 @@ #ifndef APK_TRUST #define APK_TRUST -#include <openssl/evp.h> #include "apk_blob.h" - -struct apk_pkey { - uint8_t id[16]; - EVP_PKEY *key; -}; - -int apk_pkey_init(struct apk_pkey *pkey, EVP_PKEY *key); -void apk_pkey_free(struct apk_pkey *pkey); -int apk_pkey_load(struct apk_pkey *pkey, int dirfd, const char *fn); +#include "apk_crypto.h" struct apk_trust_key { struct list_head key_node; @@ -29,10 +20,11 @@ struct apk_trust_key { }; struct apk_trust { - EVP_MD_CTX *mdctx; + struct apk_digest_ctx dctx; struct list_head trusted_key_list; struct list_head private_key_list; int allow_untrusted : 1; + int initialized : 1; }; int apk_trust_init(struct apk_trust *trust, int keysfd, struct apk_string_array *); diff --git a/src/app_add.c b/src/app_add.c index 655d2d1..559475e 100644 --- a/src/app_add.c +++ b/src/app_add.c @@ -82,8 +82,9 @@ static struct apk_package *create_virtual_package(struct apk_database *db, struc { char ver[32]; struct apk_package *virtpkg; + struct apk_digest_ctx dctx; + struct apk_digest d; struct tm tm; - EVP_MD_CTX *mdctx; time_t now = time(NULL); pid_t pid = getpid(); @@ -98,14 +99,13 @@ static struct apk_package *create_virtual_package(struct apk_database *db, struc virtpkg->description = strdup("virtual meta package"); virtpkg->arch = apk_atomize(&db->atoms, APK_BLOB_STR("noarch")); - mdctx = EVP_MD_CTX_new(); - EVP_DigestInit_ex(mdctx, apk_checksum_default(), NULL); - EVP_DigestUpdate(mdctx, &tm, sizeof tm); - EVP_DigestUpdate(mdctx, &pid, sizeof pid); - EVP_DigestUpdate(mdctx, virtpkg->name->name, strlen(virtpkg->name->name) + 1); - virtpkg->csum.type = EVP_MD_CTX_size(mdctx); - EVP_DigestFinal_ex(mdctx, virtpkg->csum.data, NULL); - EVP_MD_CTX_free(mdctx); + apk_digest_ctx_init(&dctx, APK_DIGEST_SHA1); + apk_digest_ctx_update(&dctx, &tm, sizeof tm); + apk_digest_ctx_update(&dctx, &pid, sizeof pid); + apk_digest_ctx_update(&dctx, virtpkg->name->name, strlen(virtpkg->name->name) + 1); + apk_digest_ctx_final(&dctx, &d); + apk_digest_ctx_free(&dctx); + apk_checksum_from_digest(&virtpkg->csum, &d); return virtpkg; } diff --git a/src/app_audit.c b/src/app_audit.c index 2d4925d..09d67e0 100644 --- a/src/app_audit.c +++ b/src/app_audit.c @@ -105,10 +105,10 @@ static int audit_file(struct audit_ctx *actx, return -EPERM; if (dbf->csum.type != APK_CHECKSUM_NONE && - apk_checksum_compare(&fi.csum, &dbf->csum) != 0) + apk_digest_cmp_csum(&fi.digest, &dbf->csum) != 0) rv = 'U'; else if (!S_ISLNK(fi.mode) && !dbf->diri->pkg->ipkg->broken_xattr && - apk_checksum_compare(&fi.xattr_csum, &dbf->acl->xattr_csum) != 0) + apk_digest_cmp_csum(&fi.xattr_digest, &dbf->acl->xattr_csum) != 0) rv = 'x'; else if (S_ISLNK(fi.mode) && dbf->csum.type == APK_CHECKSUM_NONE) rv = 'U'; diff --git a/src/app_fetch.c b/src/app_fetch.c index 9963503..d1c527d 100644 --- a/src/app_fetch.c +++ b/src/app_fetch.c @@ -140,7 +140,7 @@ static int fetch_package(apk_hash_item item, void *pctx) } if (!(ctx->flags & FETCH_STDOUT)) { - if (apk_fileinfo_get(ctx->outdir_fd, filename, APK_CHECKSUM_NONE, &fi, &db->atoms) == 0 && + if (apk_fileinfo_get(ctx->outdir_fd, filename, 0, &fi, &db->atoms) == 0 && fi.size == pkg->size) return 0; } diff --git a/src/app_index.c b/src/app_index.c index 5881e56..cc37fa4 100644 --- a/src/app_index.c +++ b/src/app_index.c @@ -80,7 +80,7 @@ static int index_read_file(struct apk_database *db, struct index_ctx *ictx) if (ictx->index == NULL) return 0; - if (apk_fileinfo_get(AT_FDCWD, ictx->index, APK_CHECKSUM_NONE, &fi, &db->atoms) < 0) + if (apk_fileinfo_get(AT_FDCWD, ictx->index, 0, &fi, &db->atoms) < 0) return 0; ictx->index_mtime = fi.mtime; @@ -138,7 +138,7 @@ static int index_main(void *ctx, struct apk_ctx *ac, struct apk_string_array *ar rewrite_arch = apk_atomize(&db->atoms, APK_BLOB_STR(ictx->rewrite_arch)); foreach_array_item(parg, args) { - if (apk_fileinfo_get(AT_FDCWD, *parg, APK_CHECKSUM_NONE, &fi, &db->atoms) < 0) { + if (apk_fileinfo_get(AT_FDCWD, *parg, 0, &fi, &db->atoms) < 0) { apk_warn(out, "File '%s' is unaccessible", *parg); continue; } diff --git a/src/app_manifest.c b/src/app_manifest.c index 6f32a92..86164f6 100644 --- a/src/app_manifest.c +++ b/src/app_manifest.c @@ -83,11 +83,12 @@ static int read_file_entry(void *ctx, const struct apk_file_info *ae, struct apk return 0; memset(csum_buf, '\0', sizeof(csum_buf)); - apk_blob_push_hexdump(&csum_blob, APK_BLOB_CSUM(ae->csum)); + apk_blob_push_hexdump(&csum_blob, APK_DIGEST_BLOB(ae->digest)); - apk_out(out, "%s%s%s:%s %s\n", + apk_out(out, "%s%s%s:%s %s", mctx->prefix1, mctx->prefix2, - csum_types[ae->csum.type], csum_buf, ae->name); + apk_digest_alg_str(ae->digest.alg), csum_buf, + ae->name); return 0; } diff --git a/src/app_mkndx.c b/src/app_mkndx.c index 8c29ce6..1281702 100644 --- a/src/app_mkndx.c +++ b/src/app_mkndx.c @@ -213,7 +213,7 @@ static int mkndx_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *a adb_wo_alloca(&ctx->pkgs, &schema_pkginfo_array, &ctx->db); if (ctx->index) { - apk_fileinfo_get(AT_FDCWD, ctx->index, APK_CHECKSUM_NONE, &fi, 0); + apk_fileinfo_get(AT_FDCWD, ctx->index, 0, &fi, 0); index_mtime = fi.mtime; r = adb_m_map(&odb, open(ctx->index, O_RDONLY), ADB_SCHEMA_INDEX, trust); @@ -225,7 +225,7 @@ static int mkndx_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *a } foreach_array_item(parg, args) { - r = apk_fileinfo_get(AT_FDCWD, *parg, APK_CHECKSUM_NONE, &fi, 0); + r = apk_fileinfo_get(AT_FDCWD, *parg, 0, &fi, 0); if (r < 0) { err_pkg: apk_err(out, "%s: %s", *parg, apk_error_str(r)); diff --git a/src/app_mkpkg.c b/src/app_mkpkg.c index 872b4da..82ba208 100644 --- a/src/app_mkpkg.c +++ b/src/app_mkpkg.c @@ -121,7 +121,7 @@ static int mkpkg_process_dirent(void *pctx, int dirfd, const char *entry) struct adb_obj fio, acl; int r; - r = apk_fileinfo_get(dirfd, entry, APK_FI_NOFOLLOW | APK_FI_CSUM(APK_CHECKSUM_SHA1), &fi, NULL); + r = apk_fileinfo_get(dirfd, entry, APK_FI_NOFOLLOW | APK_FI_DIGEST(APK_DIGEST_SHA256), &fi, NULL); if (r) return r; switch (fi.mode & S_IFMT) { @@ -134,7 +134,7 @@ static int mkpkg_process_dirent(void *pctx, int dirfd, const char *entry) adb_wo_alloca(&fio, &schema_file, &ctx->db); adb_wo_alloca(&acl, &schema_acl, &ctx->db); adb_wo_blob(&fio, ADBI_FI_NAME, APK_BLOB_STR(entry)); - adb_wo_blob(&fio, ADBI_FI_HASHES, APK_BLOB_PTR_LEN((char*) fi.csum.data, fi.csum.type)); + adb_wo_blob(&fio, ADBI_FI_HASHES, APK_DIGEST_BLOB(fi.digest)); adb_wo_int(&fio, ADBI_FI_MTIME, fi.mtime); adb_wo_int(&fio, ADBI_FI_SIZE, fi.size); ctx->installed_size += (fi.size + BLOCK_SIZE - 1) & ~(BLOCK_SIZE-1); diff --git a/src/app_verify.c b/src/app_verify.c index edec6c9..adfe0ec 100644 --- a/src/app_verify.c +++ b/src/app_verify.c @@ -49,10 +49,10 @@ static int verify_main(void *ctx, struct apk_ctx *ac, struct apk_string_array *a return rc; } -static struct apk_applet apk_verify = { +static struct apk_applet apk_verify_applet = { .name = "verify", .main = verify_main, }; -APK_DEFINE_APPLET(apk_verify); +APK_DEFINE_APPLET(apk_verify_applet); diff --git a/src/context.c b/src/context.c index 32a284e..ac586a8 100644 --- a/src/context.c +++ b/src/context.c @@ -74,7 +74,7 @@ int apk_ctx_prepare(struct apk_ctx *ac) struct apk_trust *apk_ctx_get_trust(struct apk_ctx *ac) { - if (!ac->trust.mdctx) { + if (!ac->trust.initialized) { int r = apk_trust_init(&ac->trust, openat(ac->root_fd, ac->keys_dir, O_RDONLY | O_CLOEXEC), ac->private_keys); diff --git a/src/crypto_openssl.c b/src/crypto_openssl.c new file mode 100644 index 0000000..97d80b8 --- /dev/null +++ b/src/crypto_openssl.c @@ -0,0 +1,112 @@ +#include <errno.h> +#include <stdio.h> +#include <fcntl.h> +#include <openssl/bio.h> +#include <openssl/pem.h> +#include <openssl/err.h> + +#include "apk_crypto.h" + +static const char *apk_digest_str[] = { + [APK_DIGEST_NONE] = "none", + [APK_DIGEST_MD5] = "md5", + [APK_DIGEST_SHA1] = "sha1", + [APK_DIGEST_SHA256] = "sha256", + [APK_DIGEST_SHA512] = "sha512", +}; + +const char *apk_digest_alg_str(uint8_t alg) +{ + const char *alg_str = "unknown"; + if (alg < ARRAY_SIZE(apk_digest_str)) + alg_str = apk_digest_str[alg]; + return alg_str; +} + +uint8_t apk_digest_alg_from_csum(int csum) +{ + switch (csum) { + case APK_CHECKSUM_NONE: return APK_DIGEST_NONE; + case APK_CHECKSUM_MD5: return APK_DIGEST_MD5; + case APK_CHECKSUM_SHA1: return APK_DIGEST_SHA1; + default: return APK_DIGEST_NONE; + } +} + +int apk_pkey_init(struct apk_pkey *pkey, EVP_PKEY *key) +{ + unsigned char dig[EVP_MAX_MD_SIZE], *pub = NULL; + unsigned int dlen = sizeof dig; + int len; + + if ((len = i2d_PublicKey(key, &pub)) < 0) return -EIO; + EVP_Digest(pub, len, dig, &dlen, EVP_sha512(), NULL); + memcpy(pkey->id, dig, sizeof pkey->id); + OPENSSL_free(pub); + + pkey->key = key; + return 0; +} + +void apk_pkey_free(struct apk_pkey *pkey) +{ + EVP_PKEY_free(pkey->key); +} + +int apk_pkey_load(struct apk_pkey *pkey, int dirfd, const char *fn) +{ + EVP_PKEY *key; + BIO *bio; + int fd; + + fd = openat(dirfd, fn, O_RDONLY|O_CLOEXEC); + if (fd < 0) return -errno; + + bio = BIO_new_fp(fdopen(fd, "r"), BIO_CLOSE); + if (!bio) return -ENOMEM; + + key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); + if (!key) { + BIO_reset(bio); + key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); + } + ERR_clear_error(); + + BIO_free(bio); + if (!key) return -EBADMSG; + + apk_pkey_init(pkey, key); + return 0; +} + +int apk_sign_start(struct apk_digest_ctx *dctx, struct apk_pkey *pkey) +{ + EVP_MD_CTX_set_pkey_ctx(dctx->mdctx, NULL); + if (EVP_DigestSignInit(dctx->mdctx, NULL, EVP_sha512(), NULL, pkey->key) != 1) + return -EIO; + return 0; +} + +int apk_sign(struct apk_digest_ctx *dctx, void *sig, size_t *len) +{ + if (EVP_DigestSignFinal(dctx->mdctx, sig, len) != 1) + return -EBADMSG; + return 0; +} + +int apk_verify_start(struct apk_digest_ctx *dctx, struct apk_pkey *pkey) +{ + EVP_MD_CTX_set_pkey_ctx(dctx->mdctx, NULL); + if (EVP_DigestVerifyInit(dctx->mdctx, NULL, EVP_sha512(), NULL, pkey->key) != 1) + return -EIO; + return 0; +} + +int apk_verify(struct apk_digest_ctx *dctx, void *sig, size_t len) +{ + if (EVP_DigestVerifyFinal(dctx->mdctx, sig, len) != 1) { + ERR_print_errors_fp(stderr); + return -EBADMSG; + } + return 0; +} diff --git a/src/database.c b/src/database.c index 40efd93..04733b8 100644 --- a/src/database.c +++ b/src/database.c @@ -212,18 +212,35 @@ struct apk_name *apk_db_get_name(struct apk_database *db, apk_blob_t name) return pn; } -static struct apk_db_acl *apk_db_acl_atomize(struct apk_database *db, mode_t mode, uid_t uid, gid_t gid, const struct apk_checksum *xattr_csum) +static struct apk_db_acl *__apk_db_acl_atomize(struct apk_database *db, mode_t mode, uid_t uid, gid_t gid, uint8_t csum_type, const uint8_t *csum_data) { struct apk_db_acl acl = { .mode = mode & 07777, .uid = uid, .gid = gid }; apk_blob_t *b; - if (xattr_csum && xattr_csum->type != APK_CHECKSUM_NONE) - acl.xattr_csum = *xattr_csum; + if (csum_data && csum_type != APK_CHECKSUM_NONE) { + acl.xattr_csum.type = csum_type; + memcpy(acl.xattr_csum.data, csum_data, csum_type); + } b = apk_atomize_dup(&db->atoms, APK_BLOB_STRUCT(acl)); return (struct apk_db_acl *) b->ptr; } +static struct apk_db_acl *apk_db_acl_atomize(struct apk_database *db, mode_t mode, uid_t uid, gid_t gid) +{ + return __apk_db_acl_atomize(db, mode, uid, gid, 0, 0); +} + +static struct apk_db_acl *apk_db_acl_atomize_csum(struct apk_database *db, mode_t mode, uid_t uid, gid_t gid, const struct apk_checksum *xattr_csum) +{ + return __apk_db_acl_atomize(db, mode, uid, gid, xattr_csum->type, xattr_csum->data); +} + +static struct apk_db_acl *apk_db_acl_atomize_digest(struct apk_database *db, mode_t mode, uid_t uid, gid_t gid, const struct apk_digest *dig) +{ + return __apk_db_acl_atomize(db, mode, uid, gid, dig->len, dig->data); +} + static void apk_db_dir_prepare(struct apk_database *db, struct apk_db_dir *dir, mode_t newmode) { struct stat st; @@ -840,7 +857,7 @@ int apk_db_index_read(struct apk_database *db, struct apk_istream *is, int repo) else xattr_csum.type = APK_CHECKSUM_NONE; - acl = apk_db_acl_atomize(db, mode, uid, gid, &xattr_csum); + acl = apk_db_acl_atomize_csum(db, mode, uid, gid, &xattr_csum); if (field == 'M') diri->acl = acl; else @@ -1517,8 +1534,8 @@ int apk_db_open(struct apk_database *db, struct apk_ctx *ac) apk_blob_t blob; int r, fd, write_arch = FALSE; - apk_default_acl_dir = apk_db_acl_atomize(db, 0755, 0, 0, NULL); - apk_default_acl_file = apk_db_acl_atomize(db, 0644, 0, 0, NULL); + apk_default_acl_dir = apk_db_acl_atomize(db, 0755, 0, 0); + apk_default_acl_file = apk_db_acl_atomize(db, 0644, 0, 0); db->ctx = ac; if (ac->open_flags == 0) { @@ -2337,22 +2354,20 @@ static struct apk_db_dir_instance *apk_db_install_directory_entry(struct install static const char *format_tmpname(struct apk_package *pkg, struct apk_db_file *f, char tmpname[static TMPNAME_MAX]) { - EVP_MD_CTX *mdctx; - unsigned char md[EVP_MAX_MD_SIZE]; + struct apk_digest_ctx dctx; + struct apk_digest d; apk_blob_t b = APK_BLOB_PTR_LEN(tmpname, TMPNAME_MAX); if (!f) return NULL; - mdctx = EVP_MD_CTX_new(); - if (!mdctx) return NULL; + if (apk_digest_ctx_init(&dctx, APK_DIGEST_SHA256) != 0) return NULL; - EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL); - EVP_DigestUpdate(mdctx, pkg->name->name, strlen(pkg->name->name) + 1); - EVP_DigestUpdate(mdctx, f->diri->dir->name, f->diri->dir->namelen); - EVP_DigestUpdate(mdctx, "/", 1); - EVP_DigestUpdate(mdctx, f->name, f->namelen); - EVP_DigestFinal_ex(mdctx, md, NULL); - EVP_MD_CTX_free(mdctx); + apk_digest_ctx_update(&dctx, pkg->name->name, strlen(pkg->name->name) + 1); + apk_digest_ctx_update(&dctx, f->diri->dir->name, f->diri->dir->namelen); + apk_digest_ctx_update(&dctx, "/", 1); + apk_digest_ctx_update(&dctx, f->name, f->namelen); + apk_digest_ctx_final(&dctx, &d); + apk_digest_ctx_free(&dctx); apk_blob_push_blob(&b, APK_BLOB_PTR_LEN(f->diri->dir->name, f->diri->dir->namelen)); if (f->diri->dir->namelen > 0) { @@ -2360,7 +2375,7 @@ static const char *format_tmpname(struct apk_package *pkg, struct apk_db_file *f } else { apk_blob_push_blob(&b, APK_BLOB_STR(".apk.")); } - apk_blob_push_hexdump(&b, APK_BLOB_PTR_LEN((char *)md, 24)); + apk_blob_push_hexdump(&b, APK_BLOB_PTR_LEN((char *)d.data, 24)); apk_blob_push_blob(&b, APK_BLOB_PTR_LEN("", 1)); return tmpname; @@ -2546,7 +2561,7 @@ static int apk_db_install_archive_entry(void *_ctx, apk_dbg2(out, "%s", ae->name); /* Extract the file with temporary name */ - file->acl = apk_db_acl_atomize(db, ae->mode, ae->uid, ae->gid, &ae->xattr_csum); + file->acl = apk_db_acl_atomize_digest(db, ae->mode, ae->uid, ae->gid, &ae->xattr_digest); r = apk_archive_entry_extract( db->root_fd, ae, format_tmpname(pkg, file, tmpname_file), @@ -2559,7 +2574,7 @@ static int apk_db_install_archive_entry(void *_ctx, if (link_target_file) memcpy(&file->csum, &link_target_file->csum, sizeof file->csum); else - memcpy(&file->csum, &ae->csum, sizeof file->csum); + apk_checksum_from_digest(&file->csum, &ae->digest); /* only warn once per package */ if (file->csum.type == APK_CHECKSUM_NONE && !ctx->missing_checksum) { apk_warn(out, @@ -2590,7 +2605,7 @@ static int apk_db_install_archive_entry(void *_ctx, diri = apk_db_install_directory_entry(ctx, name); apk_db_dir_prepare(db, diri->dir, ae->mode); } - apk_db_diri_set(diri, apk_db_acl_atomize(db, ae->mode, ae->uid, ae->gid, &ae->xattr_csum)); + apk_db_diri_set(diri, apk_db_acl_atomize_digest(db, ae->mode, ae->uid, ae->gid, &ae->xattr_digest)); } ctx->installed_size += ctx->current_file_size; @@ -2627,8 +2642,8 @@ static void apk_db_purge_pkg(struct apk_database *db, if ((diri->dir->protect_mode == APK_PROTECT_NONE) || (db->ctx->flags & APK_PURGE) || (file->csum.type != APK_CHECKSUM_NONE && - apk_fileinfo_get(db->root_fd, name, APK_FI_NOFOLLOW | file->csum.type, &fi, &db->atoms) == 0 && - apk_checksum_compare(&file->csum, &fi.csum) == 0)) + apk_fileinfo_get(db->root_fd, name, APK_FI_NOFOLLOW | APK_FI_CSUM(file->csum.type), &fi, &db->atoms) == 0 && + apk_digest_cmp_csum(&fi.digest, &file->csum) == 0)) unlinkat(db->root_fd, name, 0); apk_dbg2(out, "%s", name); __hlist_del(fc, &diri->owned_files.first); @@ -2680,7 +2695,7 @@ static void apk_db_migrate_files(struct apk_database *db, * in db, and the file is in a protected path */ cstype = APK_CHECKSUM_NONE; if (ofile != NULL && diri->dir->protect_mode != APK_PROTECT_NONE) - cstype = ofile->csum.type; + cstype = APK_FI_CSUM(ofile->csum.type); cstype |= APK_FI_NOFOLLOW; r = apk_fileinfo_get(db->root_fd, name, cstype, &fi, &db->atoms); @@ -2692,7 +2707,7 @@ static void apk_db_migrate_files(struct apk_database *db, (r == 0) && (ofile == NULL || ofile->csum.type == APK_CHECKSUM_NONE || - apk_checksum_compare(&ofile->csum, &fi.csum) != 0)) { + apk_digest_cmp_csum(&fi.digest, &ofile->csum) != 0)) { /* Protected directory, with file without * db entry, or local modifications. * @@ -2701,11 +2716,11 @@ static void apk_db_migrate_files(struct apk_database *db, if (ofile == NULL || ofile->csum.type != file->csum.type) apk_fileinfo_get(db->root_fd, name, - APK_FI_NOFOLLOW | file->csum.type, + APK_FI_NOFOLLOW |APK_FI_CSUM(file->csum.type), &fi, &db->atoms); if ((db->ctx->flags & APK_CLEAN_PROTECTED) || (file->csum.type != APK_CHECKSUM_NONE && - apk_checksum_compare(&file->csum, &fi.csum) == 0)) { + apk_digest_cmp_csum(&fi.digest, &file->csum) == 0)) { unlinkat(db->root_fd, tmpname, 0); } else { snprintf(name, sizeof name, @@ -24,8 +24,7 @@ #include "apk_defines.h" #include "apk_io.h" -#include "apk_hash.h" -#include "apk_openssl.h" +#include "apk_crypto.h" #if defined(__GLIBC__) || defined(__UCLIBC__) #define HAVE_FGETPWENT_R @@ -493,7 +492,7 @@ struct apk_istream *apk_istream_from_file(int atfd, const char *file) } ssize_t apk_stream_copy(struct apk_istream *is, struct apk_ostream *os, size_t size, - apk_progress_cb cb, void *cb_ctx, EVP_MD_CTX *mdctx) + apk_progress_cb cb, void *cb_ctx, struct apk_digest_ctx *dctx) { size_t done = 0; apk_blob_t d; @@ -508,7 +507,7 @@ ssize_t apk_stream_copy(struct apk_istream *is, struct apk_ostream *os, size_t s if (size != APK_IO_ALL) return -EBADMSG; break; } - if (mdctx) EVP_DigestUpdate(mdctx, d.ptr, d.len); + if (dctx) apk_digest_ctx_update(dctx, d.ptr, d.len); r = apk_ostream_write(os, d.ptr, d.len); if (r < 0) return r; @@ -663,50 +662,45 @@ static int cmp_xattr(const void *p1, const void *p2) return strcmp(d1->name, d2->name); } -static void hash_len_data(EVP_MD_CTX *ctx, uint32_t len, const void *ptr) +static void hash_len_data(struct apk_digest_ctx *ctx, uint32_t len, const void *ptr) { uint32_t belen = htobe32(len); - EVP_DigestUpdate(ctx, &belen, sizeof(belen)); - EVP_DigestUpdate(ctx, ptr, len); + apk_digest_ctx_update(ctx, &belen, sizeof(belen)); + apk_digest_ctx_update(ctx, ptr, len); } -void apk_fileinfo_hash_xattr_array(struct apk_xattr_array *xattrs, const EVP_MD *md, struct apk_checksum *csum) +static void apk_fileinfo_hash_xattr_array(struct apk_xattr_array *xattrs, uint8_t alg, struct apk_digest *d) { struct apk_xattr *xattr; - EVP_MD_CTX *mdctx; + struct apk_digest_ctx dctx; - if (!xattrs || xattrs->num == 0) goto err; - mdctx = EVP_MD_CTX_new(); - if (!mdctx) goto err; + apk_digest_reset(d); + if (!xattrs || xattrs->num == 0) return; + if (apk_digest_ctx_init(&dctx, alg)) return; qsort(xattrs->item, xattrs->num, sizeof(xattrs->item[0]), cmp_xattr); - - EVP_DigestInit_ex(mdctx, md, NULL); foreach_array_item(xattr, xattrs) { - hash_len_data(mdctx, strlen(xattr->name), xattr->name); - hash_len_data(mdctx, xattr->value.len, xattr->value.ptr); + hash_len_data(&dctx, strlen(xattr->name), xattr->name); + hash_len_data(&dctx, xattr->value.len, xattr->value.ptr); } - csum->type = EVP_MD_CTX_size(mdctx); - EVP_DigestFinal_ex(mdctx, csum->data, NULL); - EVP_MD_CTX_free(mdctx); - return; -err: - csum->type = APK_CHECKSUM_NONE; + apk_digest_ctx_final(&dctx, d); + apk_digest_ctx_free(&dctx); } -void apk_fileinfo_hash_xattr(struct apk_file_info *fi) +void apk_fileinfo_hash_xattr(struct apk_file_info *fi, uint8_t alg) { - apk_fileinfo_hash_xattr_array(fi->xattrs, apk_checksum_default(), &fi->xattr_csum); + apk_fileinfo_hash_xattr_array(fi->xattrs, alg, &fi->xattr_digest); } int apk_fileinfo_get(int atfd, const char *filename, unsigned int flags, struct apk_file_info *fi, struct apk_atom_pool *atoms) { struct stat64 st; - unsigned int checksum = flags & 0xff; - unsigned int xattr_checksum = (flags >> 8) & 0xff; + unsigned int hash_alg = flags & 0xff; + unsigned int xattr_hash_alg = (flags >> 8) & 0xff; int atflags = 0; + memset(fi, 0, sizeof *fi); if (flags & APK_FI_NOFOLLOW) atflags |= AT_SYMLINK_NOFOLLOW; @@ -722,7 +716,7 @@ int apk_fileinfo_get(int atfd, const char *filename, unsigned int flags, .device = st.st_dev, }; - if (xattr_checksum != APK_CHECKSUM_NONE) { + if (xattr_hash_alg != APK_DIGEST_NONE) { ssize_t len, vlen; int fd, i, r; char val[1024], buf[1024]; @@ -746,7 +740,7 @@ int apk_fileinfo_get(int atfd, const char *filename, unsigned int flags, .value = *apk_atomize_dup(atoms, APK_BLOB_PTR_LEN(val, vlen)), }; } - apk_fileinfo_hash_xattr_array(xattrs, apk_checksum_evp(xattr_checksum), &fi->xattr_csum); + apk_fileinfo_hash_xattr_array(xattrs, xattr_hash_alg, &fi->xattr_digest); apk_xattr_array_free(&xattrs); } else if (r < 0) r = errno; close(fd); @@ -755,7 +749,7 @@ int apk_fileinfo_get(int atfd, const char *filename, unsigned int flags, if (r && r != ENOTSUP) return -r; } - if (checksum == APK_CHECKSUM_NONE) return 0; + if (hash_alg == APK_DIGEST_NONE) return 0; if (S_ISDIR(st.st_mode)) return 0; /* Checksum file content */ @@ -766,25 +760,18 @@ int apk_fileinfo_get(int atfd, const char *filename, unsigned int flags, if (readlinkat(atfd, filename, target, st.st_size) < 0) return -errno; - EVP_Digest(target, st.st_size, fi->csum.data, NULL, - apk_checksum_evp(checksum), NULL); - fi->csum.type = checksum; + apk_digest_calc(&fi->digest, hash_alg, target, st.st_size); } else { struct apk_istream *is = apk_istream_from_file(atfd, filename); if (!IS_ERR_OR_NULL(is)) { - EVP_MD_CTX *mdctx; + struct apk_digest_ctx dctx; apk_blob_t blob; - mdctx = EVP_MD_CTX_new(); - if (mdctx) { - EVP_DigestInit_ex(mdctx, apk_checksum_evp(checksum), NULL); - if (is->flags & APK_ISTREAM_SINGLE_READ) - EVP_MD_CTX_set_flags(mdctx, EVP_MD_CTX_FLAG_ONESHOT); + if (apk_digest_ctx_init(&dctx, hash_alg) == 0) { while (!APK_BLOB_IS_NULL(blob = apk_istream_get_all(is))) - EVP_DigestUpdate(mdctx, (void*) blob.ptr, blob.len); - fi->csum.type = EVP_MD_CTX_size(mdctx); - EVP_DigestFinal_ex(mdctx, fi->csum.data, NULL); - EVP_MD_CTX_free(mdctx); + apk_digest_ctx_update(&dctx, blob.ptr, blob.len); + apk_digest_ctx_final(&dctx, &fi->digest); + apk_digest_ctx_free(&dctx); } apk_istream_close(is); } diff --git a/src/io_archive.c b/src/io_archive.c index ad4f621..5e1498a 100644 --- a/src/io_archive.c +++ b/src/io_archive.c @@ -112,15 +112,15 @@ static void handle_extended_header(struct apk_file_info *fi, apk_blob_t hdr) .value = value, }; } else if (apk_blob_pull_blob_match(&name, APK_BLOB_STR("APK-TOOLS.checksum."))) { - int type = APK_CHECKSUM_NONE; + int alg = APK_DIGEST_NONE; if (apk_blob_compare(name, APK_BLOB_STR("SHA1")) == 0) - type = APK_CHECKSUM_SHA1; + alg = APK_DIGEST_SHA1; else if (apk_blob_compare(name, APK_BLOB_STR("MD5")) == 0) - type = APK_CHECKSUM_MD5; - if (type > fi->csum.type) { - fi->csum.type = type; - apk_blob_pull_hexdump(&value, APK_BLOB_CSUM(fi->csum)); - if (APK_BLOB_IS_NULL(value)) fi->csum.type = APK_CHECKSUM_NONE; + alg = APK_DIGEST_MD5; + if (alg > fi->digest.alg) { + apk_digest_set(&fi->digest, alg); + apk_blob_pull_hexdump(&value, APK_DIGEST_BLOB(fi->digest)); + if (APK_BLOB_IS_NULL(value)) apk_digest_reset(&fi->digest); } } } @@ -175,7 +175,7 @@ int apk_tar_parse(struct apk_istream *is, apk_archive_entry_parser parser, if (paxlen) { handle_extended_header(&entry, APK_BLOB_PTR_LEN(pax.ptr, paxlen)); - apk_fileinfo_hash_xattr(&entry); + apk_fileinfo_hash_xattr(&entry, APK_DIGEST_SHA1); } toskip = (entry.size + 511) & -512; diff --git a/src/meson.build b/src/meson.build index 4a76d4c..27dc566 100644 --- a/src/meson.build +++ b/src/meson.build @@ -11,6 +11,7 @@ libapk_src = [ 'commit.c', 'common.c', 'context.c', + 'crypto_openssl.c', 'database.c', 'hash.c', 'io.c', @@ -30,6 +31,7 @@ libapk_headers = [ 'apk_atom.h', 'apk_archive.h', 'apk_blob.h', + 'apk_crypto.h', 'apk_database.h', 'apk_defines.h', 'apk_hash.h', diff --git a/src/package.c b/src/package.c index 5f0e88a..6cfa1a9 100644 --- a/src/package.c +++ b/src/package.c @@ -300,6 +300,12 @@ void apk_dep_from_pkg(struct apk_dependency *dep, struct apk_database *db, }; } +static const int apk_checksum_compare(const struct apk_checksum *a, const struct apk_checksum *b) +{ + return apk_blob_compare(APK_BLOB_PTR_LEN((char *) a->data, a->type), + APK_BLOB_PTR_LEN((char *) b->data, b->type)); +} + static int apk_dep_match_checksum(struct apk_dependency *dep, struct apk_package *pkg) { struct apk_checksum csum; @@ -912,7 +918,7 @@ int apk_pkg_read(struct apk_database *db, const char *file, struct apk_file_info fi; int r; - r = apk_fileinfo_get(AT_FDCWD, file, APK_CHECKSUM_NONE, &fi, &db->atoms); + r = apk_fileinfo_get(AT_FDCWD, file, 0, &fi, &db->atoms); if (r != 0) return r; diff --git a/src/trust.c b/src/trust.c index 6f63137..6f0f885 100644 --- a/src/trust.c +++ b/src/trust.c @@ -1,60 +1,7 @@ -#include <errno.h> -#include <stdio.h> -#include <openssl/bio.h> -#include <openssl/pem.h> -#include <openssl/err.h> - #include "apk_defines.h" #include "apk_trust.h" #include "apk_io.h" -/* Trust */ -int apk_pkey_init(struct apk_pkey *pkey, EVP_PKEY *key) -{ - unsigned char dig[EVP_MAX_MD_SIZE], *pub = NULL; - unsigned int dlen = sizeof dig; - int len; - - if ((len = i2d_PublicKey(key, &pub)) < 0) return -EIO; - EVP_Digest(pub, len, dig, &dlen, EVP_sha512(), NULL); - memcpy(pkey->id, dig, sizeof pkey->id); - OPENSSL_free(pub); - - pkey->key = key; - return 0; -} - -void apk_pkey_free(struct apk_pkey *pkey) -{ - EVP_PKEY_free(pkey->key); -} - -int apk_pkey_load(struct apk_pkey *pkey, int dirfd, const char *fn) -{ - EVP_PKEY *key; - BIO *bio; - int fd; - - fd = openat(dirfd, fn, O_RDONLY|O_CLOEXEC); - if (fd < 0) return -errno; - - bio = BIO_new_fp(fdopen(fd, "r"), BIO_CLOSE); - if (!bio) return -ENOMEM; - - key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); - if (!key) { - BIO_reset(bio); - key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); - } - ERR_clear_error(); - - BIO_free(bio); - if (!key) return -EBADMSG; - - apk_pkey_init(pkey, key); - return 0; -} - static struct apk_trust_key *apk_trust_load_key(int dirfd, const char *filename) { struct apk_trust_key *key; @@ -89,13 +36,11 @@ int apk_trust_init(struct apk_trust *trust, int dirfd, struct apk_string_array * { char **fn; - *trust = (struct apk_trust){ - .mdctx = EVP_MD_CTX_new(), - }; - if (!trust->mdctx) return -ENOMEM; - EVP_MD_CTX_set_flags(trust->mdctx, EVP_MD_CTX_FLAG_FINALISE); + *trust = (struct apk_trust){}; + apk_digest_ctx_init(&trust->dctx, APK_DIGEST_NONE); list_init(&trust->trusted_key_list); list_init(&trust->private_key_list); + trust->initialized = 1; apk_dir_foreach_file(dirfd, __apk_trust_load_pubkey, trust); foreach_array_item(fn, pkey_files) { @@ -121,10 +66,11 @@ static void __apk_trust_free_keys(struct list_head *h) void apk_trust_free(struct apk_trust *trust) { - if (!trust->mdctx) return; + if (!trust->initialized) return; + trust->initialized = 0; __apk_trust_free_keys(&trust->trusted_key_list); __apk_trust_free_keys(&trust->private_key_list); - EVP_MD_CTX_free(trust->mdctx); + apk_digest_ctx_free(&trust->dctx); } struct apk_pkey *apk_trust_key_by_name(struct apk_trust *trust, const char *filename) |