Compare commits

..

No commits in common. "e02ab1d0bea0210a1f7be14c061defea70927ea4" and "232067b3d1399d97b5058440bd8282031053fa7c" have entirely different histories.

21 changed files with 167 additions and 673 deletions

View File

@ -42,9 +42,7 @@ following options:
*-t, --virtual* _NAME_
Create virtual package _NAME_ with given dependencies. This new package
will get the _packages_ as dependencies instead of _world_. Finally the
_NAME_ is added to _world_. An optional version specifier for the virtual
package can be given via syntax _NAME_=_VERSION_. The version defaults
to synthesized version based on time.
_NAME_ is added to _world_.
One can use this to ensure that selected set of packages are installed,
and later the temporary modification be undone with *apk-del*(8) _NAME_

View File

@ -32,9 +32,6 @@ specified.
*Note*: this option is incompatible with *-o*, *-R*, and the global
*--progress* option.
*-w, --world*
Download packages needed to satisfy _world_. Implies *--recursive*.
*--simulate*
Simulate the requested operation without making any changes.

View File

@ -17,13 +17,11 @@ scdoc_dep = dependency('scdoc', version: '>=1.10', required: get_option('docs'))
shared_deps = [
dependency('zlib'),
dependency('openssl'),
dependency('libsodium'),
]
static_deps = [
dependency('openssl', static: true),
dependency('zlib', static: true),
dependency('libsodium', static: true),
]
add_project_arguments('-D_GNU_SOURCE', language: 'c')

View File

@ -21,20 +21,6 @@ foreach f : check_functions
endforeach
# Check for wrong (non-POSIX) qsort_r prototype
qsort_r_test = '''
#define _GNU_SOURCE
#include <stdlib.h>
_Static_assert(_Generic((qsort_r),
void (*)(void *, size_t, size_t, void *,
int (*)(void *, const void *, const void *)) : 1, default: 0),
"Bad prototype not matched");
'''
if cc.compiles(qsort_r_test, name: 'Test qsort_r non-POSIX prototype')
add_project_arguments('-DHAVE_BROKEN_QSORT_R', language: 'c')
endif
if libportability_src.length() > 0
libportability = static_library(
'portability',

View File

@ -1,4 +1,3 @@
#pragma once
#include_next <stdlib.h>
#ifdef NEED_QSORT_R
@ -6,28 +5,3 @@ void qsort_r(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *, void *),
void *arg);
#endif
#ifdef HAVE_BROKEN_QSORT_R
struct __portable_qsort_r_compat_arg {
int (*compar)(const void *, const void *, void *);
void *arg;
};
static inline int __portable_qsort_r_compar_compat(void *arg, const void *a, const void *b)
{
struct __portable_qsort_r_compat_arg *compat_arg = arg;
return compat_arg->compar(a, b, compat_arg->arg);
}
static inline void __portable_qsort_r(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *, void *),
void *arg)
{
struct __portable_qsort_r_compat_arg compat_arg = {
.compar = compar,
.arg = arg,
};
qsort_r(base, nmemb, size, &compat_arg, __portable_qsort_r_compar_compat);
}
#define qsort_r(...) __portable_qsort_r(__VA_ARGS__)
#endif

View File

@ -15,15 +15,12 @@ OPENSSL_LIBS := $(shell $(PKG_CONFIG) --libs openssl)
ZLIB_CFLAGS := $(shell $(PKG_CONFIG) --cflags zlib)
ZLIB_LIBS := $(shell $(PKG_CONFIG) --libs zlib)
SODIUM_FLAGS := $(shell $(PKG_CONFIG) --cflags libsodium)
SODIUM_LIBS := $(shell $(PKG_CONFIG) --libs libsodium)
# Dynamic library
libapk_soname := 2.99.0
libapk_so := $(obj)/libapk.so.$(libapk_soname)
libapk.so.$(libapk_soname)-objs := \
adb.o adb_comp.o adb_walk_adb.o adb_walk_genadb.o adb_walk_gentext.o adb_walk_text.o apk_adb.o \
atom.o blob.o commit.o common.o context.o crypto_core.o crypto_digest.o crypto_openssl.o database.o hash.o \
atom.o blob.o commit.o common.o context.o crypto_openssl.o database.o hash.o \
extract_v2.o extract_v3.o fs_fsys.o fs_uvol.o io.o io_gunzip.o io_url.o tar.o \
package.o pathbuilder.o print.o solver.o trust.o version.o
@ -93,9 +90,9 @@ LIBS_apk.static := -Wl,--as-needed -ldl -Wl,--no-as-needed
LDFLAGS_apk += -L$(obj)
LDFLAGS_apk-test += -L$(obj)
CFLAGS_ALL += $(OPENSSL_CFLAGS) $(ZLIB_CFLAGS) $(SODIUM_CFLAGS)
CFLAGS_ALL += $(OPENSSL_CFLAGS) $(ZLIB_CFLAGS)
LIBS := -Wl,--as-needed \
$(OPENSSL_LIBS) $(ZLIB_LIBS) $(SODIUM_LIBS) \
$(OPENSSL_LIBS) $(ZLIB_LIBS) \
-Wl,--no-as-needed
# Help generation

View File

@ -441,11 +441,7 @@ int main(int argc, char **argv)
ctx.force |= applet->forced_force;
}
if (apk_crypto_init() != 0) {
apk_err(out, "failure to initialize");
return 1;
}
apk_crypto_init();
setup_automatic_flags(&ctx);
fetchConnectionCacheInit(32, 4);

View File

@ -5,6 +5,6 @@ includedir=@INCLUDE_DIR@
Name: apk
Description: Alpine Package Manager
Version: @VERSION@
Requires: zlib openssl sodium
Libs: -L${libdir} -lapk -lsodium
Requires: zlib openssl
Libs: -L${libdir} -lapk
Cflags: -I${includedir}

View File

@ -10,39 +10,26 @@
#define APK_CRYPTO_H
#include <assert.h>
#include <openssl/evp.h>
#include <string.h>
#include "apk_blob.h"
#include <openssl/evp.h>
#include "apk_defines.h"
#include "apk_openssl.h"
// Digest
struct apk_digest_ctx {
uint8_t alg;
void *impl;
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_SHA256_160 0x05
#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_SHA256_160 0x05
#define APK_DIGEST_MAX_LENGTH 64 // longest is SHA512
#define APK_PKEY_ED25519 0x00
#define APK_PKEY_RSAPKCS1v15 0x01
#define APK_PKEY_TYPE_PUBLIC 0x00
#define APK_PKEY_TYPE_SECRET 0x01
// includes '\0'
#define APK_PKEY_CUTE_PUBLIC_SIZE 69
#define APK_PKEY_CUTE_SECRET_SIZE 113
#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);
@ -52,22 +39,16 @@ struct apk_digest {
uint8_t data[APK_DIGEST_MAX_LENGTH];
};
#define APK_DIGEST_BLOB(d) APK_BLOB_PTR_LEN((void *) ((d).data), (d).len)
#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)
{
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_NONE: return EVP_md_null();
case APK_DIGEST_MD5: return EVP_md5();
case APK_DIGEST_SHA1: return EVP_sha1();
case APK_DIGEST_SHA256_160:
case APK_DIGEST_SHA256:
return EVP_sha256();
case APK_DIGEST_SHA512:
return EVP_sha512();
case APK_DIGEST_SHA256: return EVP_sha256();
case APK_DIGEST_SHA512: return EVP_sha512();
default:
assert(alg);
return EVP_md_null();
@ -77,27 +58,21 @@ static inline const EVP_MD *apk_digest_alg_to_evp(uint8_t alg)
int apk_digest_alg_len(uint8_t alg);
uint8_t apk_digest_alg_by_len(int len);
static inline int apk_digest_cmp(struct apk_digest *a, struct apk_digest *b)
{
if (a->alg != b->alg)
return b->alg - a->alg;
static inline int apk_digest_cmp(struct apk_digest *a, struct apk_digest *b) {
if (a->alg != b->alg) return b->alg - a->alg;
return memcmp(a->data, b->data, a->len);
}
static inline void apk_digest_reset(struct apk_digest *d)
{
static inline void apk_digest_reset(struct apk_digest *d) {
d->alg = APK_DIGEST_NONE;
d->len = 0;
}
static inline void apk_digest_set(struct apk_digest *d, uint8_t alg)
{
static inline void apk_digest_set(struct apk_digest *d, uint8_t alg) {
d->alg = alg;
d->len = apk_digest_alg_len(alg);
}
int apk_digest_calc(struct apk_digest *d, uint8_t alg, const void *ptr, size_t sz);
/*
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;
@ -107,14 +82,45 @@ static inline int apk_digest_calc(struct apk_digest *d, uint8_t alg, const void
d->len = apk_digest_alg_len(alg);
return 0;
}
*/
int apk_digest_ctx_init(struct apk_digest_ctx *dctx, uint8_t alg);
void apk_digest_ctx_reset(struct apk_digest_ctx *dctx, uint8_t alg);
void apk_digest_ctx_free(struct apk_digest_ctx *dctx);
int apk_digest_ctx_update(struct apk_digest_ctx *dctx, const void *ptr, size_t sz);
int apk_digest_ctx_final(struct apk_digest_ctx *dctx, struct apk_digest *d);
static inline int apk_digest_ctx_init(struct apk_digest_ctx *dctx, uint8_t alg) {
dctx->alg = alg;
dctx->mdctx = EVP_MD_CTX_new();
if (!dctx->mdctx) return -ENOMEM;
#ifdef EVP_MD_CTX_FLAG_FINALISE
EVP_MD_CTX_set_flags(dctx->mdctx, EVP_MD_CTX_FLAG_FINALISE);
#endif
if (alg != APK_DIGEST_NONE) EVP_DigestInit_ex(dctx->mdctx, apk_digest_alg_to_evp(alg), 0);
return 0;
}
static inline void apk_digest_ctx_reset(struct apk_digest_ctx *dctx, uint8_t alg)
{
dctx->alg = alg;
EVP_DigestInit_ex(dctx->mdctx, apk_digest_alg_to_evp(alg), 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 : -APKE_CRYPTO_ERROR;
}
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 -APKE_CRYPTO_ERROR;
}
d->alg = dctx->alg;
d->len = apk_digest_alg_len(d->alg);
return 0;
}
#include "apk_blob.h"
uint8_t apk_digest_from_blob(struct apk_digest *d, apk_blob_t b);
static inline int apk_digest_cmp_csum(const struct apk_digest *d, const struct apk_checksum *csum)
{
@ -133,14 +139,13 @@ static inline void apk_checksum_from_digest(struct apk_checksum *csum, const str
// Asymmetric keys
struct apk_pkey {
uint8_t type;
uint8_t alg;
uint8_t id[16];
void *impl;
uint8_t id[16];
EVP_PKEY *key;
};
int apk_pkey_load(struct apk_pkey *pkey, int dirfd, const char *fn);
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
@ -151,6 +156,31 @@ int apk_verify(struct apk_digest_ctx *, void *, size_t);
// Initializiation
int apk_crypto_init(void);
#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

@ -18,7 +18,6 @@
#include "apk_atom.h"
#include "apk_crypto.h"
int apk_make_dirs(int root_fd, const char *dirname, mode_t dirmode, mode_t parentmode);
ssize_t apk_write_fully(int fd, const void *ptr, size_t size);
struct apk_id_hash {

View File

@ -81,26 +81,32 @@ static int non_repository_check(struct apk_database *db)
return 1;
}
static struct apk_package *create_virtual_package(struct apk_database *db, struct apk_dependency *dep)
static struct apk_package *create_virtual_package(struct apk_database *db, struct apk_name *name)
{
char ver[32];
struct apk_package *virtpkg;
struct apk_digest_ctx dctx;
struct apk_digest d;
struct tm tm;
time_t now = time(NULL);
pid_t pid = getpid();
gmtime_r(&now, &tm);
strftime(ver, sizeof ver, "%Y%m%d.%H%M%S", &tm);
virtpkg = apk_pkg_new();
if (virtpkg == NULL) return 0;
virtpkg->name = dep->name;
virtpkg->version = dep->version;
virtpkg->name = name;
virtpkg->version = apk_atomize_dup(&db->atoms, APK_BLOB_STR(ver));
virtpkg->description = strdup("virtual meta package");
virtpkg->arch = apk_atomize(&db->atoms, APK_BLOB_STR("noarch"));
virtpkg->repos |= BIT(APK_REPOSITORY_CACHED);
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_update(&dctx, dep->version->ptr, dep->version->len);
apk_digest_ctx_final(&dctx, &d);
apk_digest_ctx_free(&dctx);
apk_checksum_from_digest(&virtpkg->csum, &d);
@ -108,17 +114,6 @@ static struct apk_package *create_virtual_package(struct apk_database *db, struc
return virtpkg;
}
static apk_blob_t *generate_version(struct apk_database *db)
{
char ver[32];
struct tm tm;
time_t now = time(NULL);
gmtime_r(&now, &tm);
strftime(ver, sizeof ver, "%Y%m%d.%H%M%S", &tm);
return apk_atomize_dup(&db->atoms, APK_BLOB_STR(ver));
}
static int add_main(void *ctx, struct apk_ctx *ac, struct apk_string_array *args)
{
struct apk_out *out = &ac->out;
@ -138,32 +133,24 @@ static int add_main(void *ctx, struct apk_ctx *ac, struct apk_string_array *args
if (actx->virtpkg) {
apk_blob_t b = APK_BLOB_STR(actx->virtpkg);
apk_blob_pull_dep(&b, db, &virtdep);
if (APK_BLOB_IS_NULL(b) || virtdep.conflict ||
(virtdep.name->name[0] != '.' && non_repository_check(db)))
goto bad_spec;
switch (virtdep.result_mask) {
case APK_DEPMASK_ANY:
if (virtdep.version != &apk_atom_null) goto bad_spec;
virtdep.result_mask = APK_VERSION_EQUAL;
virtdep.version = generate_version(db);
break;
case APK_VERSION_EQUAL:
if (virtdep.version == &apk_atom_null) goto bad_spec;
break;
default:
bad_spec:
virtdep.result_mask != APK_DEPMASK_ANY ||
virtdep.version != &apk_atom_null) {
apk_err(out, "%s: bad package specifier", actx->virtpkg);
return -1;
}
if (virtdep.name->name[0] != '.' && non_repository_check(db))
return -1;
virtpkg = create_virtual_package(db, &virtdep);
virtpkg = create_virtual_package(db, virtdep.name);
if (!virtpkg) {
apk_err(out, "Failed to allocate virtual meta package");
return -1;
}
virtdep.result_mask = APK_VERSION_EQUAL;
virtdep.version = virtpkg->version;
if (!args->num) apk_warn(out, "creating empty virtual package");
}

View File

@ -20,11 +20,10 @@
#include "apk_print.h"
#include "apk_solver.h"
#define FETCH_RECURSIVE 0x01
#define FETCH_STDOUT 0x02
#define FETCH_LINK 0x04
#define FETCH_URL 0x08
#define FETCH_WORLD 0x10
#define FETCH_RECURSIVE 1
#define FETCH_STDOUT 2
#define FETCH_LINK 4
#define FETCH_URL 8
struct fetch_ctx {
unsigned int flags;
@ -76,7 +75,6 @@ static int cup(void)
OPT(OPT_FETCH_simulate, "simulate") \
OPT(OPT_FETCH_stdout, APK_OPT_SH("s") "stdout") \
OPT(OPT_FETCH_url, "url") \
OPT(OPT_FETCH_world, APK_OPT_SH("w") "world") \
APK_OPT_APPLET(option_desc, FETCH_OPTIONS);
@ -103,10 +101,6 @@ static int option_parse_applet(void *ctx, struct apk_ctx *ac, int opt, const cha
case OPT_FETCH_url:
fctx->flags |= FETCH_URL;
break;
case OPT_FETCH_world:
fctx->flags |= FETCH_WORLD | FETCH_RECURSIVE;
ac->open_flags &= ~APK_OPENF_NO_WORLD;
break;
default:
return -ENOTSUP;
}
@ -224,12 +218,6 @@ static void mark_error(struct fetch_ctx *ctx, const char *match, struct apk_name
ctx->errors++;
}
static void mark_dep_flags(struct fetch_ctx *ctx, struct apk_dependency *dep)
{
dep->name->auto_select_virtual = 1;
apk_deps_add(&ctx->world, dep);
}
static void mark_name_flags(struct apk_database *db, const char *match, struct apk_name *name, void *pctx)
{
struct fetch_ctx *ctx = (struct fetch_ctx *) pctx;
@ -240,7 +228,8 @@ static void mark_name_flags(struct apk_database *db, const char *match, struct a
};
if (name) {
mark_dep_flags(ctx, &dep);
name->auto_select_virtual = 1;
apk_deps_add(&ctx->world, &dep);
} else {
ctx->errors++;
mark_error(ctx, match, name);
@ -321,7 +310,6 @@ static int fetch_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *a
struct apk_out *out = &ac->out;
struct apk_database *db = ac->db;
struct fetch_ctx *ctx = (struct fetch_ctx *) pctx;
struct apk_dependency *dep;
ctx->db = db;
ctx->prog = db->ctx->progress;
@ -341,8 +329,6 @@ static int fetch_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *a
if (ctx->flags & FETCH_RECURSIVE) {
apk_dependency_array_init(&ctx->world);
foreach_array_item(dep, db->world)
mark_dep_flags(ctx, dep);
apk_name_foreach_matching(db, args, apk_foreach_genid(), mark_name_flags, ctx);
if (ctx->errors == 0)
mark_names_recursive(db, args, ctx);
@ -363,7 +349,7 @@ static int fetch_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *a
static struct apk_applet apk_fetch = {
.name = "fetch",
.open_flags = APK_OPENF_READ | APK_OPENF_NO_STATE,
.open_flags = APK_OPENF_READ | APK_OPENF_NO_STATE,
.context_size = sizeof(struct fetch_ctx),
.optgroups = { &optgroup_global, &optgroup_applet },
.main = fetch_main,

View File

@ -74,7 +74,8 @@ int apk_ctx_prepare(struct apk_ctx *ac)
const int lflags = O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC;
int fd = openat(ac->root_fd, log_path, lflags, 0644);
if (fd < 0 && (ac->open_flags & APK_OPENF_CREATE)) {
apk_make_dirs(ac->root_fd, "var/log", 0755, 0755);
mkdirat(ac->root_fd, "var", 0755);
mkdirat(ac->root_fd, "var/log", 0755);
fd = openat(ac->root_fd, log_path, lflags, 0644);
}
if (fd < 0) {

View File

@ -1,38 +0,0 @@
#include <sodium.h>
#include <openssl/evp.h>
#include "apk_crypto.h"
#include "apk_defines.h"
#if OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
static void apk_crypto_cleanup(void)
{
EVP_cleanup();
#ifndef OPENSSL_NO_ENGINE
ENGINE_cleanup();
#endif
CRYPTO_cleanup_all_ex_data();
}
#endif
int apk_crypto_init(void)
{
if (sodium_init() < 0) {
return -APKE_CRYPTO_ERROR;
}
#if OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
atexit(apk_crypto_cleanup);
OpenSSL_add_all_algorithms();
#ifndef OPENSSL_NO_ENGINE
ENGINE_load_builtin_engines();
ENGINE_register_all_complete();
#endif
#endif
return 0;
}

View File

@ -1,209 +0,0 @@
#include <sodium.h>
#include "apk_crypto.h"
/*
static inline int apk_digest_ctx_init(struct apk_digest_ctx *dctx, uint8_t alg) {
dctx->alg = alg;
dctx->mdctx = EVP_MD_CTX_new();
if (!dctx->mdctx) return -ENOMEM;
#ifdef EVP_MD_CTX_FLAG_FINALISE
EVP_MD_CTX_set_flags(dctx->mdctx, EVP_MD_CTX_FLAG_FINALISE);
#endif
if (alg != APK_DIGEST_NONE) EVP_DigestInit_ex(dctx->mdctx, apk_digest_alg_to_evp(alg), 0);
return 0;
}
*/
union digest_state {
crypto_hash_sha256_state sha256;
crypto_hash_sha512_state sha512;
EVP_MD_CTX *mdctx;
};
static const char *apk_digest_str[] = {
[APK_DIGEST_NONE] = "none",
[APK_DIGEST_MD5] = "md5",
[APK_DIGEST_SHA1] = "sha1",
[APK_DIGEST_SHA256_160] = "sha256-160",
[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;
}
int apk_digest_calc(struct apk_digest *d, uint8_t alg, const void *ptr, size_t sz)
{
switch (alg) {
case APK_DIGEST_SHA256:
case APK_DIGEST_SHA256_160:
crypto_hash_sha256(d->data, ptr, sz);
break;
case APK_DIGEST_SHA512:
crypto_hash_sha512(d->data, ptr, sz);
break;
case APK_DIGEST_NONE:
break;
case APK_DIGEST_MD5:
break;
case APK_DIGEST_SHA1:
break;
default:
return -APKE_CRYPTO_NOT_SUPPORTED;
}
d->alg = alg;
return 0;
}
int apk_digest_ctx_init(struct apk_digest_ctx *dctx, uint8_t alg)
{
union digest_state *state = NULL;
const EVP_MD *evp_md = NULL;
dctx->impl = malloc(sizeof(union digest_state));
if (dctx->impl == NULL) {
return -ENOMEM;
}
state = (union digest_state *) dctx->impl;
dctx->alg = alg;
switch (alg) {
case APK_DIGEST_SHA256:
case APK_DIGEST_SHA256_160:
crypto_hash_sha256_init(&state->sha256);
break;
case APK_DIGEST_SHA512:
crypto_hash_sha512_init(&state->sha512);
break;
case APK_DIGEST_NONE:
evp_md = EVP_md_null();
case APK_DIGEST_MD5:
evp_md = EVP_md5();
break;
case APK_DIGEST_SHA1:
evp_md = EVP_sha1();
break;
default:
free(dctx->impl);
return -APKE_CRYPTO_NOT_SUPPORTED;
}
if (evp_md != NULL) {
state->mdctx = EVP_MD_CTX_new();
if (state->mdctx == NULL) {
goto a;
}
#ifdef EVP_MD_CTX_FLAG_FINALISE
EVP_MD_CTX_set_flags(dctx->mdctx, EVP_MD_CTX_FLAG_FINALISE);
#endif
EVP_DigestInit_ex(dctx->mdctx, apk_digest_alg_to_evp(alg), 0);
}
return 0;
a:
free(dctx->impl);
return -APKE_CRYPTO_ERROR;
}
void apk_digest_ctx_reset(struct apk_digest_ctx *dctx, uint8_t alg)
{
apk_digest_ctx_free(dctx);
apk_digest_ctx_init(dctx, alg);
}
void apk_digest_ctx_free(struct apk_digest_ctx *dctx)
{
union digest_state *state = (union digest_state *) dctx->impl;
if (dctx->impl == NULL) {
return;
}
switch (dctx->alg) {
case APK_DIGEST_NONE:
case APK_DIGEST_MD5:
case APK_DIGEST_SHA1:
EVP_MD_CTX_free(state->mdctx);
case APK_DIGEST_SHA256:
case APK_DIGEST_SHA512:
case APK_DIGEST_SHA256_160:
break;
default:
/* illegal state, don't touch impl? */
return;
}
free(dctx->impl);
dctx->impl = NULL;
}
int apk_digest_ctx_update(struct apk_digest_ctx *dctx, const void *ptr, size_t sz)
{
union digest_state *state = (union digest_state *) dctx->impl;
switch (dctx->alg) {
case APK_DIGEST_SHA256:
case APK_DIGEST_SHA256_160:
crypto_hash_sha256_update(&state->sha256, ptr, sz);
break;
case APK_DIGEST_SHA512:
crypto_hash_sha512_update(&state->sha512, ptr, sz);
break;
case APK_DIGEST_NONE:
case APK_DIGEST_MD5:
case APK_DIGEST_SHA1:
if (EVP_DigestUpdate(state->mdctx, ptr, sz) != 1) {
return -APKE_CRYPTO_ERROR;
}
break;
default:
return -APKE_CRYPTO_NOT_SUPPORTED;
}
return 0;
}
int apk_digest_ctx_final(struct apk_digest_ctx *dctx, struct apk_digest *d)
{
union digest_state *state = dctx->impl;
unsigned int mdlen;
switch (dctx->alg) {
case APK_DIGEST_SHA256:
case APK_DIGEST_SHA256_160:
crypto_hash_sha256_final(&state->sha256, d->data);
break;
case APK_DIGEST_SHA512:
crypto_hash_sha512_final(&state->sha512, d->data);
break;
case APK_DIGEST_NONE:
case APK_DIGEST_MD5:
case APK_DIGEST_SHA1:
mdlen = sizeof d->data;
if (EVP_DigestFinal_ex(state->mdctx, d->data, &mdlen) != 1) {
apk_digest_reset(d);
return -APKE_CRYPTO_ERROR;
}
break;
default:
return -APKE_CRYPTO_NOT_SUPPORTED;
}
d->alg = dctx->alg;
d->len = apk_digest_alg_len(d->alg);
return 0;
}

View File

@ -7,6 +7,23 @@
#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_160] = "sha256-160",
[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;
}
int apk_digest_alg_len(uint8_t alg)
{
switch (alg) {

View File

@ -1,232 +0,0 @@
#include <fcntl.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <sodium.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "apk_crypto.h"
union pkey_state {
unsigned char cute_pk[crypto_sign_ed25519_PUBLICKEYBYTES];
unsigned char cute_sk[crypto_sign_ed25519_SECRETKEYBYTES];
EVP_PKEY *pkey;
};
static int load_openssl(int fd, struct apk_pkey *pkey)
{
int r = -APKE_CRYPTO_KEY_FORMAT;
union pkey_state *state;
BIO *bio;
pkey->impl = malloc(sizeof(union pkey_state));
if (pkey->impl == NULL) {
r = -ENOMEM;
goto err_alloc;
}
bio = BIO_new_fd(fd, BIO_NOCLOSE);
if (bio == NULL) {
r = -ENOMEM;
goto err_bio_new;
}
state = (union pkey_state *) pkey->impl;
pkey->type = APK_PKEY_TYPE_PUBLIC;
state->pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
if (state->pkey == NULL) {
pkey->type = APK_PKEY_TYPE_SECRET;
BIO_reset(bio);
state->pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
}
ERR_clear_error();
if (state->pkey == NULL) {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err_load;
}
BIO_free(bio);
return 0;
err_load:
BIO_free(bio);
err_bio_new:
free(pkey->impl);
err_alloc:
return r;
}
static int load_public_cute(int fd, struct apk_pkey *pkey)
{
char b64[APK_PKEY_CUTE_PUBLIC_SIZE];
int r = -APKE_CRYPTO_KEY_FORMAT;
union pkey_state *state;
uint8_t raw[50]; // 2 + 16 + 32
size_t len;
pkey->impl = malloc(sizeof(union pkey_state));
if (pkey->impl == NULL) {
r = -ENOMEM;
goto err_alloc;
}
state = (union pkey_state *) pkey->impl;
if (read(fd, b64, APK_PKEY_CUTE_PUBLIC_SIZE) != APK_PKEY_CUTE_PUBLIC_SIZE) {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err_read;
}
if (sodium_base642bin(raw,
50,
b64,
APK_PKEY_CUTE_PUBLIC_SIZE,
NULL,
&len,
NULL,
sodium_base64_VARIANT_URLSAFE)
!= 0) {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err_b64decode;
}
if (raw[0] != 'q' || raw[1] != 't') {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err_rawheader;
}
pkey->type = APK_PKEY_TYPE_PUBLIC;
pkey->alg = APK_PKEY_ED25519;
memcpy(pkey->id, raw + 2, 16);
memcpy(state->cute_pk, raw + 18, crypto_sign_ed25519_PUBLICKEYBYTES);
return 0;
err_rawheader:
err_b64decode:
err_read:
free(pkey->impl);
err_alloc:
return r;
}
static int load_secret_cute(int fd, struct apk_pkey *pkey)
{
char b64[APK_PKEY_CUTE_SECRET_SIZE];
int r = -APKE_CRYPTO_KEY_FORMAT;
union pkey_state *state;
uint8_t raw[82]; // 2 + 16 + 64
size_t len;
pkey->impl = malloc(sizeof(union pkey_state));
if (pkey->impl == NULL) {
r = -ENOMEM;
goto err_alloc;
}
state = (union pkey_state *) pkey->impl;
if (read(fd, b64, APK_PKEY_CUTE_SECRET_SIZE) != APK_PKEY_CUTE_SECRET_SIZE) {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err_read;
}
if (sodium_base642bin(raw,
82,
b64,
APK_PKEY_CUTE_PUBLIC_SIZE,
NULL,
&len,
NULL,
sodium_base64_VARIANT_URLSAFE)
!= 0) {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err_b64decode;
}
if (len != 82) {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err_decodelen;
}
if (raw[0] != 'q' || raw[1] != 't') {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err_rawheader;
}
pkey->type = APK_PKEY_TYPE_SECRET;
pkey->alg = APK_PKEY_ED25519;
memcpy(pkey->id, raw + 2, 16);
memcpy(state->cute_sk, raw + 18, crypto_sign_ed25519_SECRETKEYBYTES);
return 0;
err_rawheader:
err_decodelen:
err_b64decode:
err_read:
free(pkey->impl);
err_alloc:
return r;
}
void apk_pkey_free(struct apk_pkey *pkey)
{
union pkey_state *state = (union pkey_state *) pkey->impl;
switch (pkey->alg) {
case APK_PKEY_ED25519:
break;
case APK_PKEY_RSAPKCS1v15:
EVP_PKEY_free(state->pkey);
break;
default:
/* invalid state, don't touch impl */
return;
}
free(pkey->impl);
pkey->impl = NULL;
}
int apk_pkey_load(struct apk_pkey *pkey, int dirfd, const char *fn)
{
struct stat st;
int fd, r = 0;
fd = openat(dirfd, fn, O_RDONLY | O_CLOEXEC);
if (fd == -1) {
r = -errno;
goto err_openat;
}
if (fstat(fd, &st) != 0) {
r = -errno;
goto err_fstat;
}
switch (st.st_size) {
case APK_PKEY_CUTE_SECRET_SIZE:
r = load_secret_cute(fd, pkey);
break;
case APK_PKEY_CUTE_PUBLIC_SIZE:
r = load_public_cute(fd, pkey);
break;
default:
r = load_openssl(fd, pkey);
break;
}
err_fstat:
close(fd);
err_openat:
return r;
}

View File

@ -1451,7 +1451,9 @@ static inline int setup_static_cache(struct apk_database *db, struct apk_ctx *ac
db->cache_dir = apk_static_cache_dir;
db->cache_fd = openat(db->root_fd, db->cache_dir, O_RDONLY | O_CLOEXEC);
if (db->cache_fd < 0) {
apk_make_dirs(db->root_fd, db->cache_dir, 0755, 0755);
mkdirat(db->root_fd, "var", 0755);
mkdirat(db->root_fd, "var/cache", 0755);
mkdirat(db->root_fd, "var/cache/apk", 0755);
db->cache_fd = openat(db->root_fd, db->cache_dir, O_RDONLY | O_CLOEXEC);
if (db->cache_fd < 0) {
if (ac->open_flags & APK_OPENF_WRITE) return -EROFS;
@ -1882,8 +1884,15 @@ int apk_db_write_config(struct apk_database *db)
return 0;
if (db->ctx->open_flags & APK_OPENF_CREATE) {
apk_make_dirs(db->root_fd, "lib/apk/db", 0755, 0755);
apk_make_dirs(db->root_fd, "etc/apk", 0755, 0755);
if (faccessat(db->root_fd, "lib/apk/db", F_OK, 0) != 0) {
mkdirat(db->root_fd, "lib", 0755);
mkdirat(db->root_fd, "lib/apk", 0755);
mkdirat(db->root_fd, "lib/apk/db", 0755);
}
if (faccessat(db->root_fd, "etc/apk", F_OK, 0) != 0) {
mkdirat(db->root_fd, "etc", 0755);
mkdirat(db->root_fd, "etc/apk", 0755);
}
} else if (db->lock_fd == 0) {
apk_err(out, "Refusing to write db without write lock!");
return -1;

View File

@ -38,21 +38,6 @@ static inline int atfd_error(int atfd)
return atfd < -1 && atfd != AT_FDCWD;
}
int apk_make_dirs(int root_fd, const char *dirname, mode_t dirmode, mode_t parentmode)
{
char parentdir[PATH_MAX], *slash;
if (faccessat(root_fd, dirname, F_OK, 0) == 0) return 0;
if (mkdirat(root_fd, dirname, dirmode) == 0) return 0;
if (errno != ENOENT || !parentmode) return -1;
slash = strrchr(dirname, '/');
if (!slash || slash == dirname || slash-dirname+1 >= sizeof parentdir) return -1;
strlcpy(parentdir, dirname, slash-dirname+1);
if (apk_make_dirs(root_fd, parentdir, parentmode, parentmode) < 0) return -1;
return mkdirat(root_fd, dirname, dirmode);
}
ssize_t apk_write_fully(int fd, const void *ptr, size_t size)
{
ssize_t i = 0, r;

View File

@ -12,8 +12,6 @@ libapk_src = [
'commit.c',
'common.c',
'context.c',
'crypto_core.c',
'crypto_digest.c',
'crypto_openssl.c',
'database.c',
'extract_v2.c',

View File

@ -768,6 +768,21 @@ int apk_ipkg_add_script(struct apk_installed_package *ipkg,
return apk_ipkg_assign_script(ipkg, type, apk_blob_from_istream(is, size));
}
static inline int make_dirs(int root_fd, const char *dirname, mode_t dirmode, mode_t parentmode)
{
char parentdir[PATH_MAX], *slash;
if (faccessat(root_fd, dirname, F_OK, 0) == 0) return 0;
if (mkdirat(root_fd, dirname, dirmode) == 0) return 0;
if (errno != ENOENT || !parentmode) return -1;
slash = strrchr(dirname, '/');
if (!slash || slash == dirname || slash-dirname+1 >= sizeof parentdir) return -1;
strlcpy(parentdir, dirname, slash-dirname+1);
if (make_dirs(root_fd, parentdir, parentmode, parentmode) < 0) return -1;
return mkdirat(root_fd, dirname, dirmode);
}
#ifdef __linux__
static inline int make_device_tree(struct apk_database *db)
{
@ -819,8 +834,8 @@ void apk_ipkg_run_script(struct apk_installed_package *ipkg,
return;
if (!db->script_dirs_checked) {
if (apk_make_dirs(root_fd, "tmp", 01777, 0) <0 ||
apk_make_dirs(root_fd, script_exec_dir, 0700, 0755) < 0||
if (make_dirs(root_fd, "tmp", 01777, 0) <0 ||
make_dirs(root_fd, script_exec_dir, 0700, 0755) < 0||
make_device_tree(db) < 0) {
apk_err(out, "failed to prepare dirs for hook scripts: %s",
apk_error_str(errno));