summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2021-06-09 18:21:40 +0300
committerTimo Teräs <timo.teras@iki.fi>2021-06-11 13:35:32 +0300
commit7ce4cc4b739127c0b4b36ffcabc007e5781b13c9 (patch)
tree1f751b9dc62c59a1fa1e05d34550961f39719137 /src
parent7c9f001cda932c74164e8aaa6740dcb6d24aa62f (diff)
downloadapk-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/Makefile2
-rw-r--r--src/adb.c84
-rw-r--r--src/adb.h8
-rw-r--r--src/apk.c2
-rw-r--r--src/apk_blob.h7
-rw-r--r--src/apk_crypto.h174
-rw-r--r--src/apk_io.h15
-rw-r--r--src/apk_openssl.h23
-rw-r--r--src/apk_trust.h14
-rw-r--r--src/app_add.c18
-rw-r--r--src/app_audit.c4
-rw-r--r--src/app_fetch.c2
-rw-r--r--src/app_index.c4
-rw-r--r--src/app_manifest.c7
-rw-r--r--src/app_mkndx.c4
-rw-r--r--src/app_mkpkg.c4
-rw-r--r--src/app_verify.c4
-rw-r--r--src/context.c2
-rw-r--r--src/crypto_openssl.c112
-rw-r--r--src/database.c69
-rw-r--r--src/io.c71
-rw-r--r--src/io_archive.c16
-rw-r--r--src/meson.build2
-rw-r--r--src/package.c8
-rw-r--r--src/trust.c66
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
diff --git a/src/adb.c b/src/adb.c
index 03f50f3..5fc762c 100644
--- a/src/adb.c
+++ b/src/adb.c
@@ -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;
}
diff --git a/src/adb.h b/src/adb.h
index 5f0d7bd..509605c 100644
--- a/src/adb.h
+++ b/src/adb.h
@@ -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);
diff --git a/src/apk.c b/src/apk.c
index 0c2482f..2da1788 100644
--- a/src/apk.c
+++ b/src/apk.c
@@ -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,
diff --git a/src/io.c b/src/io.c
index 93ca9d6..5cc993a 100644
--- a/src/io.c
+++ b/src/io.c
@@ -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)