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
cute-signatures
Timo Teräs 2021-06-09 18:21:40 +03:00
parent 7c9f001cda
commit 7ce4cc4b73
25 changed files with 461 additions and 259 deletions

View File

@ -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

View File

@ -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;
if (adb_digest_adb(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 (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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

174
src/apk_crypto.h Normal file
View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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 *);

View File

@ -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;
}

View File

@ -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';

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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));

View File

@ -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);

View File

@ -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);

View File

@ -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);

112
src/crypto_openssl.c Normal file
View File

@ -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;
}

View File

@ -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,

View File

@ -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);
}

View File

@ -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;

View File

@ -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',

View File

@ -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;

View File

@ -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)