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 #10744cute-signatures
parent
7c9f001cda
commit
7ce4cc4b73
|
@ -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
|
||||
|
||||
|
|
82
src/adb.c
82
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;
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
15
src/apk_io.h
15
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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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,
|
||||
|
|
71
src/io.c
71
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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
66
src/trust.c
66
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)
|
||||
|
|
Loading…
Reference in New Issue