apk: add package

APK (Alpine Package Keeper) is the package manager of Alpine Linux and
has multiple advantages over OPKG. While Alpine uses APK version 2, this
commit adds version 3 with a heavily optimised database structure and
additional feature making it suitable for OpenWrt.

This commit will be followed by many more to add APK build capabilities
to the OpenWrt build system, firstly enabling side by side builds of APK
and OPKG packages, later replacing OPKG entirely.

Signed-off-by: Paul Spooren <mail@aparcar.org>
This commit is contained in:
Paul Spooren 2024-03-17 18:11:48 +01:00
parent 7d5f7b8b6c
commit 00b86168bd
3 changed files with 1025 additions and 0 deletions

View File

@ -0,0 +1,87 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=apk
PKG_RELEASE:=1
PKG_SOURCE_URL=https://gitlab.alpinelinux.org/alpine/apk-tools.git
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2024-04-16
PKG_SOURCE_VERSION:=ba6c31a5469ef74fb85119508e55de9631ffef41
PKG_MIRROR_HASH:=3455d5799481add9ece3db685576d58be6303f3a13140133979b965cbd3c9966
PKG_VERSION=3.0.0_pre$(subst -,,$(PKG_SOURCE_DATE))
PKG_MAINTAINER:=Paul Spooren <mail@aparcar.org>
PKG_LICENSE:=GPL-2.0-only
PKG_LICENSE_FILES:=LICENSE
PKG_INSTALL:=1
HOST_BUILD_PREFIX:=$(STAGING_DIR_HOST)
HOST_BUILD_DEPENDS:=lua/host
PKG_BUILD_DEPENDS:=$(HOST_BUILD_DEPENDS)
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/host-build.mk
include $(INCLUDE_DIR)/meson.mk
define Package/apk/default
SECTION:=base
CATEGORY:=Base system
TITLE:=apk package manager
DEPENDS:=+zlib
URL:=$(PKG_SOURCE_URL)
endef
define Package/apk-mbedtls
$(Package/apk/default)
TITLE += (mbedtls)
DEPENDS +=+libmbedtls
VARIANT:=mbedtls
DEFAULT_VARIANT:=1
CONFLICTS:=apk-openssl
endef
define Package/apk-openssl
$(Package/apk/default)
TITLE += (openssl)
DEPENDS +=+libopenssl
VARIANT:=openssl
endef
MESON_HOST_VARS+=VERSION=$(PKG_VERSION)
MESON_VARS+=VERSION=$(PKG_VERSION)
MESON_HOST_ARGS += \
-Dlua_version=5.1 \
-Dcompressed-help=false \
-Ddocs=disabled \
-Dcrypto_backend=openssl \
-Dzstd=false
MESON_ARGS += \
-Dlua_version=5.1 \
-Dcompressed-help=false \
-Ddocs=disabled \
-Durl_backend=wget \
-Dcrypto_backend=$(BUILD_VARIANT) \
-Dzstd=false
HOST_LDFLAGS += \
-Wl,-rpath $(STAGING_DIR_HOST)/lib
define Package/apk/default/install
$(INSTALL_DIR) $(1)/lib/apk/db
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/apk $(1)/usr/bin/apk
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libapk.so.* $(1)/usr/lib/
endef
Package/apk-mbedtls/install = $(Package/apk/default/install)
Package/apk-openssl/install = $(Package/apk/default/install)
$(eval $(call BuildPackage,apk-mbedtls))
$(eval $(call BuildPackage,apk-openssl))
$(eval $(call HostBuild))

View File

@ -0,0 +1,21 @@
From 9918c683fcc2f148328332d58d030ec5750a1473 Mon Sep 17 00:00:00 2001
From: Paul Spooren <mail@aparcar.org>
Date: Sat, 19 Feb 2022 17:20:37 +0100
Subject: [PATCH 1/4] openwrt: move layer db to temp folder
Signed-off-by: Paul Spooren <mail@aparcar.org>
---
src/database.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/src/database.c
+++ b/src/database.c
@@ -1604,7 +1604,7 @@ const char *apk_db_layer_name(int layer)
{
switch (layer) {
case APK_DB_LAYER_ROOT: return "lib/apk/db";
- case APK_DB_LAYER_UVOL: return "lib/apk/db-uvol";
+ case APK_DB_LAYER_UVOL: return "tmp/run/uvol/.meta/apk";
default:
assert("invalid layer");
return 0;

View File

@ -0,0 +1,917 @@
From 74ea482102e1a7c1845b3eec19cbdb21264836d4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
Date: Fri, 5 Apr 2024 12:06:56 +0300
Subject: [PATCH 1/4] add alternate url wget implementation
---
.gitlab-ci.yml | 16 ++++-
meson.build | 6 +-
meson_options.txt | 1 +
src/io_url_wget.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++
src/meson.build | 4 +-
5 files changed, 173 insertions(+), 4 deletions(-)
create mode 100644 src/io_url_wget.c
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 7fc86563..b7e00008 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -24,7 +24,19 @@ test:alpine:
script:
- apk update
- apk add make gcc git musl-dev openssl-dev linux-headers zlib-dev zstd-dev lua5.3-dev lua5.3-lzlib meson zlib-static zstd-static openssl-libs-static
- - meson build
+ - meson setup build -Dstatic_apk=true
+ - ninja -C build
+ tags:
+ - docker-alpine
+ - x86_64
+
+test:alpine-alt-config:
+ image: alpine
+ stage: test
+ script:
+ - apk update
+ - apk add make gcc git musl-dev openssl-dev linux-headers zlib-dev lua5.3-dev lua5.3-lzlib meson
+ - meson setup build -Durl_backend=wget -Dzstd=false
- ninja -C build
tags:
- docker-alpine
@@ -38,7 +50,7 @@ test:debian:
- apt-get install -y make gcc git libssl-dev zlib1g-dev libzstd-dev lua5.3-dev lua5.2 lua-zlib-dev sudo meson
- unlink /bin/sh
- ln -s /bin/bash /bin/sh
- - meson build
+ - meson setup build
- ninja -C build
tags:
- docker-alpine
diff --git a/meson.build b/meson.build
index 1a44c11f..9a14cac0 100644
--- a/meson.build
+++ b/meson.build
@@ -33,6 +33,10 @@ subproject = meson.is_subproject()
subdir('doc')
subdir('portability')
-subdir('libfetch')
+if get_option('url_backend') == 'libfetch'
+ subdir('libfetch')
+else
+ libfetch_dep = dependency('', required: false)
+endif
subdir('src')
subdir('tests')
diff --git a/meson_options.txt b/meson_options.txt
index 693f46ec..940fe9a4 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -5,5 +5,6 @@ option('help', description: 'Build help into apk binaries, needs lua', type: 'fe
option('lua', description: 'Build luaapk (lua bindings)', type: 'feature', value: 'auto')
option('lua_version', description: 'Lua version to build against', type: 'string', value: '5.3')
option('static_apk', description: 'Also build apk.static', type: 'boolean', value: false)
+option('url_backend', description: 'URL backend', type: 'combo', choices: ['libfetch', 'wget'], value: 'libfetch')
option('uvol_db_target', description: 'Default target for uvol database layer', type: 'string')
option('zstd', description: 'Build with zstd support', type: 'boolean', value: true)
diff --git a/src/io_url_wget.c b/src/io_url_wget.c
new file mode 100644
index 00000000..9a929222
--- /dev/null
+++ b/src/io_url_wget.c
@@ -0,0 +1,150 @@
+/* io_url_wget.c - Alpine Package Keeper (APK)
+ *
+ * Copyright (C) 2005-2008 Natanael Copa <n@tanael.org>
+ * Copyright (C) 2008-2011 Timo Teräs <timo.teras@iki.fi>
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ */
+
+#include <spawn.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include "apk_io.h"
+
+static char wget_timeout[16];
+static char wget_no_check_certificate;
+
+static int wget_translate_status(int status)
+{
+ if (!WIFEXITED(status)) return -EFAULT;
+ switch (WEXITSTATUS(status)) {
+ case 0: return 0;
+ case 3: return -EIO;
+ case 4: return -ENETUNREACH;
+ case 5: return -EACCES;
+ case 6: return -EACCES;
+ case 7: return -EPROTO;
+ default: return -APKE_REMOTE_IO;
+ }
+}
+
+struct apk_wget_istream {
+ struct apk_istream is;
+ int fd;
+ pid_t pid;
+};
+
+static int wget_spawn(const char *url, pid_t *pid, int *fd)
+{
+ int i = 0, r, pipefds[2];
+ posix_spawn_file_actions_t act;
+ char *argv[16];
+
+ argv[i++] = "wget";
+ argv[i++] = "-q";
+ argv[i++] = "-T";
+ argv[i++] = wget_timeout;
+ if (wget_no_check_certificate) argv[i++] = "--no-check-certificate";
+ argv[i++] = (char *) url;
+ argv[i++] = "-O";
+ argv[i++] = "-";
+ argv[i++] = 0;
+
+ if (pipe2(pipefds, O_CLOEXEC) != 0) return -errno;
+
+ posix_spawn_file_actions_init(&act);
+ posix_spawn_file_actions_adddup2(&act, pipefds[1], STDOUT_FILENO);
+ r = posix_spawnp(pid, "wget", &act, 0, argv, environ);
+ posix_spawn_file_actions_destroy(&act);
+ if (r != 0) return -r;
+ close(pipefds[1]);
+ *fd = pipefds[0];
+ return 0;
+}
+
+static int wget_check_exit(struct apk_wget_istream *wis)
+{
+ int status;
+
+ if (wis->pid == 0) return apk_istream_error(&wis->is, 0);
+ if (waitpid(wis->pid, &status, 0) == wis->pid) {
+ wis->pid = 0;
+ return apk_istream_error(&wis->is, wget_translate_status(status));
+ }
+ return 0;
+}
+
+static void wget_get_meta(struct apk_istream *is, struct apk_file_meta *meta)
+{
+}
+
+static ssize_t wget_read(struct apk_istream *is, void *ptr, size_t size)
+{
+ struct apk_wget_istream *wis = container_of(is, struct apk_wget_istream, is);
+ ssize_t r;
+
+ r = read(wis->fd, ptr, size);
+ if (r < 0) return -errno;
+ if (r == 0) return wget_check_exit(wis);
+ return r;
+}
+
+static int wget_close(struct apk_istream *is)
+{
+ int r = is->err;
+ struct apk_wget_istream *wis = container_of(is, struct apk_wget_istream, is);
+
+ while (wis->pid != 0)
+ wget_check_exit(wis);
+
+ close(wis->fd);
+ free(wis);
+ return r < 0 ? r : 0;
+}
+
+static const struct apk_istream_ops wget_istream_ops = {
+ .get_meta = wget_get_meta,
+ .read = wget_read,
+ .close = wget_close,
+};
+
+struct apk_istream *apk_io_url_istream(const char *url, time_t since)
+{
+ struct apk_wget_istream *wis;
+ int r;
+
+ wis = malloc(sizeof(*wis) + apk_io_bufsize);
+ if (wis == NULL) return ERR_PTR(-ENOMEM);
+
+ *wis = (struct apk_wget_istream) {
+ .is.ops = &wget_istream_ops,
+ .is.buf = (uint8_t *)(wis + 1),
+ .is.buf_size = apk_io_bufsize,
+ };
+ r = wget_spawn(url, &wis->pid, &wis->fd);
+ if (r != 0) {
+ free(wis);
+ return ERR_PTR(r);
+ }
+
+ return &wis->is;
+}
+
+void apk_io_url_no_check_certificate(void)
+{
+ wget_no_check_certificate = 1;
+}
+
+void apk_io_url_set_timeout(int timeout)
+{
+ snprintf(wget_timeout, sizeof wget_timeout, "%d", timeout);
+}
+
+void apk_io_url_set_redirect_callback(void (*cb)(int, const char *))
+{
+}
+
+void apk_io_url_init(void)
+{
+}
diff --git a/src/meson.build b/src/meson.build
index c1aae550..38e9d3b0 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,3 +1,5 @@
+url_backend = get_option('url_backend')
+
libapk_so_version = '2.99.0'
libapk_src = [
'adb.c',
@@ -22,8 +24,8 @@ libapk_src = [
'fs_uvol.c',
'hash.c',
'io.c',
- 'io_url_libfetch.c',
'io_gunzip.c',
+ 'io_url_@0@.c'.format(url_backend),
'package.c',
'pathbuilder.c',
'print.c',
--
GitLab
From b9fe78fbf19bb10e1d0b8eb1cb1de123bee2ed7e Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Tue, 16 Apr 2024 17:55:15 +0200
Subject: [PATCH 2/4] add option to configure url backend in legacy make build
system
Can be configured by setting URL_BACKEND. If not set libfetch is
selected by default.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
src/Makefile | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/src/Makefile b/src/Makefile
index f7873cb1..efdc68df 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -9,8 +9,8 @@ else
$(error Lua interpreter not found. Please specify LUA interpreter, or use LUA=no to build without help.)
endif
-OPENSSL_CFLAGS := $(shell $(PKG_CONFIG) --cflags openssl)
-OPENSSL_LIBS := $(shell $(PKG_CONFIG) --libs openssl)
+OPENSSL_CFLAGS := $(shell $(PKG_CONFIG) --cflags openssl)
+OPENSSL_LIBS := $(shell $(PKG_CONFIG) --libs openssl)
ZLIB_CFLAGS := $(shell $(PKG_CONFIG) --cflags zlib)
ZLIB_LIBS := $(shell $(PKG_CONFIG) --libs zlib)
@@ -21,10 +21,18 @@ 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.o crypto_openssl.o ctype.o database.o hash.o \
- extract_v2.o extract_v3.o fs_fsys.o fs_uvol.o io.o io_gunzip.o io_url_libfetch.o \
- tar.o package.o pathbuilder.o print.o solver.o trust.o version.o
+ extract_v2.o extract_v3.o fs_fsys.o fs_uvol.o io.o io_gunzip.o tar.o package.o pathbuilder.o \
+ print.o solver.o trust.o version.o
-libapk.so.$(libapk_soname)-libs := libfetch/libfetch.a
+libapk.so.$(libapk_soname)-libs :=
+
+ifeq ($(URL_BACKEND),wget)
+libapk.so.$(libapk_soname)-objs += io_url_wget.o
+else
+CFLAGS_ALL += -Ilibfetch
+libapk.so.$(libapk_soname)-objs += io_url_libfetch.o
+libapk.so.$(libapk_soname)-libs += libfetch/libfetch.a
+endif
# ZSTD support can be disabled
ifneq ($(ZSTD),no)
@@ -79,7 +87,7 @@ LIBS_apk := -lapk
LIBS_apk-test := -lapk
LIBS_apk.so := -L$(obj) -lapk
-CFLAGS_ALL += -D_ATFILE_SOURCE -Ilibfetch -Iportability
+CFLAGS_ALL += -D_ATFILE_SOURCE -Iportability
CFLAGS_apk.o := -DAPK_VERSION=\"$(VERSION)\"
CFLAGS_apk-static.o := -DAPK_VERSION=\"$(VERSION)\" -DOPENSSL_NO_ENGINE
CFLAGS_apk-test.o := -DAPK_VERSION=\"$(VERSION)\" -DOPENSSL_NO_ENGINE -DTEST_MODE
--
GitLab
From 0418b684898403c49905c1f0e4b7c5ca522b2d50 Mon Sep 17 00:00:00 2001
From: Jonas Jelonek <jelonek.jonas@gmail.com>
Date: Sun, 14 Apr 2024 00:20:14 +0200
Subject: [PATCH 3/4] crypto: add support for mbedtls as backend
backend is selected at compile-time with crypto_backend option
Co-developed-by: Christian Marangi <ansuelsmth@gmail.com>
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
---
libfetch/meson.build | 2 +-
meson.build | 14 +-
meson_options.txt | 1 +
portability/getrandom.c | 19 +++
portability/meson.build | 3 +-
portability/sys/random.h | 6 +
src/apk_crypto.h | 5 +
src/apk_crypto_mbedtls.h | 30 +++++
src/crypto_mbedtls.c | 285 +++++++++++++++++++++++++++++++++++++++
src/meson.build | 21 ++-
10 files changed, 373 insertions(+), 13 deletions(-)
create mode 100644 portability/getrandom.c
create mode 100644 portability/sys/random.h
create mode 100644 src/apk_crypto_mbedtls.h
create mode 100644 src/crypto_mbedtls.c
diff --git a/libfetch/meson.build b/libfetch/meson.build
index 431ba197..e24f95eb 100644
--- a/libfetch/meson.build
+++ b/libfetch/meson.build
@@ -40,7 +40,7 @@ libfetch = static_library(
c_args: libfetch_cargs,
dependencies: [
libportability_dep.partial_dependency(compile_args: true, includes: true),
- openssl_dep.partial_dependency(compile_args: true, includes: true)
+ crypto_dep.partial_dependency(compile_args: true, includes: true)
],
)
diff --git a/meson.build b/meson.build
index 9a14cac0..3a83f4e1 100644
--- a/meson.build
+++ b/meson.build
@@ -13,15 +13,21 @@ apk_libdir = get_option('libdir')
lua_bin = find_program('lua' + get_option('lua_version'), required: get_option('help'))
lua_dep = dependency('lua' + get_option('lua_version'), required: get_option('lua'))
scdoc_dep = dependency('scdoc', version: '>=1.10', required: get_option('docs'))
-openssl_dep = dependency('openssl')
-openssl_static_dep = dependency('openssl', static: true)
zlib_dep = dependency('zlib')
zlib_static_dep = dependency('zlib', static: true)
libzstd_dep = dependency('libzstd', required: get_option('zstd'))
libzstd_static_dep = dependency('libzstd', required: get_option('zstd'), static: true)
-shared_deps = [ openssl_dep, zlib_dep, libzstd_dep ]
-static_deps = [ openssl_static_dep, zlib_static_dep, libzstd_static_dep ]
+if get_option('crypto_backend') == 'openssl'
+ crypto_dep = dependency('openssl')
+ crypto_static_dep = dependency('openssl', static: true)
+elif get_option('crypto_backend') == 'mbedtls'
+ crypto_dep = [ dependency('mbedtls'), dependency('mbedcrypto') ]
+ crypto_static_dep = [ dependency('mbedtls', static: true), dependency('mbedcrypto', static: true) ]
+endif
+
+shared_deps = [ crypto_dep, zlib_dep, libzstd_dep ]
+static_deps = [ crypto_static_dep, zlib_static_dep, libzstd_static_dep ]
add_project_arguments('-D_GNU_SOURCE', language: 'c')
diff --git a/meson_options.txt b/meson_options.txt
index 940fe9a4..df0b07dc 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -1,4 +1,5 @@
option('arch_prefix', description: 'Define a custom arch prefix for default arch', type: 'string')
+option('crypto_backend', description: 'Crypto backend', type: 'combo', choices: ['openssl', 'mbedtls'], value: 'openssl')
option('compressed-help', description: 'Compress help database, needs lua-zlib', type: 'boolean', value: true)
option('docs', description: 'Build manpages with scdoc', type: 'feature', value: 'auto')
option('help', description: 'Build help into apk binaries, needs lua', type: 'feature', value: 'auto')
diff --git a/portability/getrandom.c b/portability/getrandom.c
new file mode 100644
index 00000000..b2f4a07c
--- /dev/null
+++ b/portability/getrandom.c
@@ -0,0 +1,19 @@
+#include <sys/random.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+ssize_t getrandom(void *buf, size_t buflen, unsigned int flags)
+{
+ int fd;
+ ssize_t ret;
+
+ fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC);
+ if (fd < 0)
+ return -1;
+
+ ret = read(fd, buf, buflen);
+ close(fd);
+ return ret;
+}
+
diff --git a/portability/meson.build b/portability/meson.build
index 89957c3c..3172044e 100644
--- a/portability/meson.build
+++ b/portability/meson.build
@@ -3,7 +3,8 @@ cc = meson.get_compiler('c')
libportability_src = []
check_symbols = [
- ['memrchr', 'memrchr.c', 'NEED_MEMRCHR', 'string.h'],
+ ['getrandom', 'getrandom.c', 'NEED_GETRANDOM', 'sys/random.h'],
+ ['memrchr', 'memrchr.c', 'NEED_MEMRCHR', 'string.h'],
['mknodat', 'mknodat.c', 'NEED_MKNODAT', 'sys/stat.h'],
['pipe2', 'pipe2.c', 'NEED_PIPE2', 'unistd.h'],
['qsort_r', 'qsort_r.c', 'NEED_QSORT_R', 'stdlib.h'],
diff --git a/portability/sys/random.h b/portability/sys/random.h
new file mode 100644
index 00000000..02d5b1ca
--- /dev/null
+++ b/portability/sys/random.h
@@ -0,0 +1,6 @@
+#include_next <sys/random.h>
+#include <sys/types.h>
+
+#ifdef NEED_GETRANDOM
+ssize_t getrandom(void *buf, size_t buflen, unsigned int flags);
+#endif
diff --git a/src/apk_crypto.h b/src/apk_crypto.h
index 7de88dfc..5cae3bfe 100644
--- a/src/apk_crypto.h
+++ b/src/apk_crypto.h
@@ -12,7 +12,12 @@
#include <string.h>
#include "apk_defines.h"
#include "apk_blob.h"
+
+#if defined(CRYPTO_USE_OPENSSL)
#include "apk_crypto_openssl.h"
+#elif defined(CRYPTO_USE_MBEDTLS)
+#include "apk_crypto_mbedtls.h"
+#endif
// Digest
diff --git a/src/apk_crypto_mbedtls.h b/src/apk_crypto_mbedtls.h
new file mode 100644
index 00000000..5481d149
--- /dev/null
+++ b/src/apk_crypto_mbedtls.h
@@ -0,0 +1,30 @@
+/* apk_crypto_mbedtls.h - Alpine Package Keeper (APK)
+ *
+ * Copyright (C) 2024
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ */
+
+#ifndef APK_CRYPTO_MBEDTLS_H
+#define APK_CRYPTO_MBEDTLS_H
+
+#include <mbedtls/md.h>
+#include <mbedtls/pk.h>
+#include <mbedtls/bignum.h>
+
+struct apk_pkey {
+ uint8_t id[16];
+ mbedtls_pk_context key;
+};
+
+struct apk_digest_ctx {
+ mbedtls_md_context_t mdctx;
+ struct apk_pkey *sigver_key;
+ uint8_t alg;
+};
+
+/* based on mbedtls' internal pkwrite.h calculations */
+#define APK_ENC_KEY_MAX_LENGTH (38 + 2 * MBEDTLS_MPI_MAX_SIZE)
+
+#endif
diff --git a/src/crypto_mbedtls.c b/src/crypto_mbedtls.c
new file mode 100644
index 00000000..73d60e9d
--- /dev/null
+++ b/src/crypto_mbedtls.c
@@ -0,0 +1,285 @@
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/random.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <mbedtls/platform.h>
+#include <mbedtls/md.h>
+#include <mbedtls/pk.h>
+#include <mbedtls/entropy.h>
+
+#ifdef MBEDTLS_PSA_CRYPTO_C
+#include <psa/crypto.h>
+#endif
+
+#include "apk_crypto.h"
+
+static inline const mbedtls_md_type_t apk_digest_alg_to_mbedtls_type(uint8_t alg) {
+ switch (alg) {
+ case APK_DIGEST_NONE: return MBEDTLS_MD_NONE;
+ case APK_DIGEST_MD5: return MBEDTLS_MD_MD5;
+ case APK_DIGEST_SHA1: return MBEDTLS_MD_SHA1;
+ case APK_DIGEST_SHA256_160:
+ case APK_DIGEST_SHA256: return MBEDTLS_MD_SHA256;
+ case APK_DIGEST_SHA512: return MBEDTLS_MD_SHA512;
+ default:
+ assert(alg);
+ return MBEDTLS_MD_NONE;
+ }
+}
+
+static inline const mbedtls_md_info_t *apk_digest_alg_to_mdinfo(uint8_t alg)
+{
+ return mbedtls_md_info_from_type(
+ apk_digest_alg_to_mbedtls_type(alg)
+ );
+}
+
+int apk_digest_calc(struct apk_digest *d, uint8_t alg, const void *ptr, size_t sz)
+{
+ if (mbedtls_md(apk_digest_alg_to_mdinfo(alg), ptr, sz, d->data))
+ return -APKE_CRYPTO_ERROR;
+
+ apk_digest_set(d, alg);
+ return 0;
+}
+
+int apk_digest_ctx_init(struct apk_digest_ctx *dctx, uint8_t alg)
+{
+ dctx->alg = alg;
+
+ mbedtls_md_init(&dctx->mdctx);
+ if (alg == APK_DIGEST_NONE) return 0;
+ if (mbedtls_md_setup(&dctx->mdctx, apk_digest_alg_to_mdinfo(alg), 0) ||
+ mbedtls_md_starts(&dctx->mdctx))
+ return -APKE_CRYPTO_ERROR;
+
+ return 0;
+}
+
+int apk_digest_ctx_reset(struct apk_digest_ctx *dctx)
+{
+ if (dctx->alg == APK_DIGEST_NONE) return 0;
+ if (mbedtls_md_starts(&dctx->mdctx)) return -APKE_CRYPTO_ERROR;
+ return 0;
+}
+
+int apk_digest_ctx_reset_alg(struct apk_digest_ctx *dctx, uint8_t alg)
+{
+ mbedtls_md_free(&dctx->mdctx);
+
+ dctx->alg = alg;
+ if (alg == APK_DIGEST_NONE) return 0;
+ if (mbedtls_md_setup(&dctx->mdctx, apk_digest_alg_to_mdinfo(alg), 0) ||
+ mbedtls_md_starts(&dctx->mdctx))
+ return -APKE_CRYPTO_ERROR;
+
+ return 0;
+}
+
+void apk_digest_ctx_free(struct apk_digest_ctx *dctx)
+{
+ mbedtls_md_free(&dctx->mdctx);
+}
+
+int apk_digest_ctx_update(struct apk_digest_ctx *dctx, const void *ptr, size_t sz)
+{
+ if (dctx->alg == APK_DIGEST_NONE) return 0;
+ return mbedtls_md_update(&dctx->mdctx, ptr, sz) == 0 ? 0 : -APKE_CRYPTO_ERROR;
+}
+
+int apk_digest_ctx_final(struct apk_digest_ctx *dctx, struct apk_digest *d)
+{
+ if (mbedtls_md_finish(&dctx->mdctx, d->data)) {
+ apk_digest_reset(d);
+ return -APKE_CRYPTO_ERROR;
+ }
+
+ d->alg = dctx->alg;
+ d->len = apk_digest_alg_len(d->alg);
+ return 0;
+}
+
+static int apk_load_file_at(int dirfd, const char *fn, unsigned char **buf, size_t *n)
+{
+ struct stat stats;
+ size_t size;
+ int fd;
+
+ if ((fd = openat(dirfd, fn, O_RDONLY|O_CLOEXEC)) < 0)
+ return -errno;
+
+ if (fstat(fd, &stats)) {
+ close(fd);
+ return -errno;
+ }
+
+ size = (size_t)stats.st_size;
+ *n = size;
+
+ if (size == 0 || (*buf = mbedtls_calloc(1, size + 1)) == NULL)
+ return MBEDTLS_ERR_PK_ALLOC_FAILED;
+
+ if (read(fd, *buf, size) != size) {
+ close(fd);
+
+ mbedtls_platform_zeroize(*buf, size);
+ mbedtls_free(*buf);
+
+ return MBEDTLS_ERR_PK_FILE_IO_ERROR;
+ }
+ close(fd);
+
+ (*buf)[size] = '\0';
+
+ if (strstr((const char *) *buf, "-----BEGIN ") != NULL) {
+ ++*n;
+ }
+
+ return 0;
+}
+
+static int apk_pkey_init(struct apk_pkey *pkey)
+{
+ unsigned char dig[APK_DIGEST_MAX_LENGTH];
+ unsigned char pub[APK_ENC_KEY_MAX_LENGTH] = {};
+ unsigned char *c;
+ int len, r = -APKE_CRYPTO_ERROR;
+
+ c = pub + APK_ENC_KEY_MAX_LENGTH;
+
+ // key is written backwards into pub starting at c!
+ if ((len = mbedtls_pk_write_pubkey(&c, pub, &pkey->key)) < 0) return -APKE_CRYPTO_ERROR;
+ if (!mbedtls_md(apk_digest_alg_to_mdinfo(APK_DIGEST_SHA512), c, len, dig)) {
+ memcpy(pkey->id, dig, sizeof pkey->id);
+ r = 0;
+ }
+
+ return r;
+}
+
+void apk_pkey_free(struct apk_pkey *pkey)
+{
+ mbedtls_pk_free(&pkey->key);
+}
+
+static int apk_random(void *ctx, unsigned char *out, size_t len)
+{
+ return (int)getrandom(out, len, 0);
+}
+
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+static inline int apk_mbedtls_parse_privkey(struct apk_pkey *pkey, const unsigned char *buf, size_t blen)
+{
+ return mbedtls_pk_parse_key(&pkey->key, buf, blen, NULL, 0, apk_random, NULL);
+}
+static inline int apk_mbedtls_sign(struct apk_digest_ctx *dctx, struct apk_digest *dig,
+ unsigned char *sig, size_t *sig_len)
+{
+ return mbedtls_pk_sign(&dctx->sigver_key->key, apk_digest_alg_to_mbedtls_type(dctx->alg),
+ (const unsigned char *)&dig->data, dig->len, sig, sizeof *sig, sig_len,
+ apk_random, NULL);
+}
+#else
+static inline int apk_mbedtls_parse_privkey(struct apk_pkey *pkey, const unsigned char *buf, size_t blen)
+{
+ return mbedtls_pk_parse_key(&pkey->key, buf, blen, NULL, 0);
+}
+static inline int apk_mbedtls_sign(struct apk_digest_ctx *dctx, struct apk_digest *dig,
+ unsigned char *sig, size_t *sig_len)
+{
+ return mbedtls_pk_sign(&dctx->sigver_key->key, apk_digest_alg_to_mbedtls_type(dctx->alg),
+ (const unsigned char *)&dig->data, dig->len, sig, sig_len, apk_random, NULL);
+}
+#endif
+
+int apk_pkey_load(struct apk_pkey *pkey, int dirfd, const char *fn)
+{
+ unsigned char *buf = NULL;
+ size_t blen = 0;
+ int ret;
+
+ if (apk_load_file_at(dirfd, fn, &buf, &blen))
+ return -APKE_CRYPTO_ERROR;
+
+ mbedtls_pk_init(&pkey->key);
+ if ((ret = mbedtls_pk_parse_public_key(&pkey->key, buf, blen)) != 0)
+ ret = apk_mbedtls_parse_privkey(pkey, buf, blen);
+
+ mbedtls_platform_zeroize(buf, blen);
+ mbedtls_free(buf);
+ if (ret != 0)
+ return -APKE_CRYPTO_KEY_FORMAT;
+
+ return apk_pkey_init(pkey);
+}
+
+int apk_sign_start(struct apk_digest_ctx *dctx, uint8_t alg, struct apk_pkey *pkey)
+{
+ if (apk_digest_ctx_reset_alg(dctx, alg))
+ return -APKE_CRYPTO_ERROR;
+
+ dctx->sigver_key = pkey;
+
+ return 0;
+}
+
+int apk_sign(struct apk_digest_ctx *dctx, void *sig, size_t *len)
+{
+ struct apk_digest dig;
+ int r = 0;
+
+ if (apk_digest_ctx_final(dctx, &dig))
+ return -APKE_SIGNATURE_GEN_FAILURE;
+
+ if (apk_mbedtls_sign(dctx, &dig, sig, len))
+ r = -APKE_SIGNATURE_GEN_FAILURE;
+
+ dctx->sigver_key = NULL;
+ return r;
+}
+
+int apk_verify_start(struct apk_digest_ctx *dctx, uint8_t alg, struct apk_pkey *pkey)
+{
+ if (apk_digest_ctx_reset_alg(dctx, alg))
+ return -APKE_CRYPTO_ERROR;
+
+ dctx->sigver_key = pkey;
+
+ return 0;
+}
+
+int apk_verify(struct apk_digest_ctx *dctx, void *sig, size_t len)
+{
+ struct apk_digest dig;
+ int r = 0;
+
+ if (apk_digest_ctx_final(dctx, &dig))
+ return -APKE_SIGNATURE_GEN_FAILURE;
+
+ if (mbedtls_pk_verify(&dctx->sigver_key->key, apk_digest_alg_to_mbedtls_type(dctx->alg),
+ (const unsigned char *)&dig.data, dig.len, sig, len))
+ r = -APKE_SIGNATURE_INVALID;
+
+ dctx->sigver_key = NULL;
+ return r;
+}
+
+static void apk_crypto_cleanup(void)
+{
+#ifdef MBEDTLS_PSA_CRYPTO_C
+ mbedtls_psa_crypto_free();
+#endif
+}
+
+void apk_crypto_init(void)
+{
+ atexit(apk_crypto_cleanup);
+
+#ifdef MBEDTLS_PSA_CRYPTO_C
+ psa_crypto_init();
+#endif
+}
diff --git a/src/meson.build b/src/meson.build
index 38e9d3b0..e1204fc0 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,3 +1,4 @@
+crypto_backend = get_option('crypto_backend')
url_backend = get_option('url_backend')
libapk_so_version = '2.99.0'
@@ -15,7 +16,7 @@ libapk_src = [
'common.c',
'context.c',
'crypto.c',
- 'crypto_openssl.c',
+ 'crypto_@0@.c'.format(crypto_backend),
'ctype.c',
'database.c',
'extract_v2.c',
@@ -40,7 +41,7 @@ libapk_headers = [
'apk_atom.h',
'apk_blob.h',
'apk_crypto.h',
- 'apk_crypto_openssl.h',
+ 'apk_crypto_@0@.h'.format(crypto_backend),
'apk_ctype.h',
'apk_database.h',
'apk_defines.h',
@@ -89,6 +90,17 @@ apk_src = [
'applet.c',
]
+apk_cargs = [
+ '-DAPK_VERSION="' + meson.project_version() + '"',
+ '-D_ATFILE_SOURCE',
+]
+
+if crypto_backend == 'openssl'
+ apk_cargs += [ '-DCRYPTO_USE_OPENSSL' ]
+elif crypto_backend == 'mbedtls'
+ apk_cargs += [ '-DCRYPTO_USE_MBEDTLS' ]
+endif
+
if lua_bin.found()
genhelp_script = files('genhelp.lua')
genhelp_args = [lua_bin, genhelp_script, '@INPUT@']
@@ -115,11 +127,6 @@ endif
apk_src += [ generated_help ]
-apk_cargs = [
- '-DAPK_VERSION="' + meson.project_version() + '"',
- '-D_ATFILE_SOURCE',
-]
-
apk_arch_prefix = get_option('arch_prefix')
if apk_arch_prefix != ''
apk_cargs += ['-DAPK_ARCH_PREFIX="@0@"'.format(apk_arch_prefix)]
--
GitLab
From 34bb1021284dccbf97f02b0a0bb9e751b8887cad Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Tue, 16 Apr 2024 17:56:45 +0200
Subject: [PATCH 4/4] add option to configure crypto backend in legacy make
build system
Define CRYPTO to select mbedtls as alternative crypto backend. By
default openssl is used.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
src/Makefile | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/src/Makefile b/src/Makefile
index efdc68df..97db0e72 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -20,9 +20,9 @@ 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.o crypto_openssl.o ctype.o database.o hash.o \
- extract_v2.o extract_v3.o fs_fsys.o fs_uvol.o io.o io_gunzip.o tar.o package.o pathbuilder.o \
- print.o solver.o trust.o version.o
+ atom.o blob.o commit.o common.o context.o crypto.o ctype.o database.o hash.o extract_v2.o \
+ extract_v3.o fs_fsys.o fs_uvol.o io.o io_gunzip.o tar.o package.o pathbuilder.o print.o \
+ solver.o trust.o version.o
libapk.so.$(libapk_soname)-libs :=
@@ -34,6 +34,16 @@ libapk.so.$(libapk_soname)-objs += io_url_libfetch.o
libapk.so.$(libapk_soname)-libs += libfetch/libfetch.a
endif
+ifeq ($(CRYPTO),mbedtls)
+CRYPTO_CFLAGS := $(shell $(PKG_CONFIG) --cflags mbedtls mbedcrypto) -DCRYPTO_USE_MBEDTLS
+CRYPTO_LIBS := $(shell $(PKG_CONFIG) --libs mbedtls mbedcrypto)
+libapk.so.$(libapk_soname)-objs += crypto_mbedtls.o
+else
+CRYPTO_CFLAGS := $(shell $(PKG_CONFIG) --cflags openssl) -DCRYPTO_USE_OPENSSL
+CRYPTO_LIBS := $(shell $(PKG_CONFIG) --libs openssl)
+libapk.so.$(libapk_soname)-objs += crypto_openssl.o
+endif
+
# ZSTD support can be disabled
ifneq ($(ZSTD),no)
ZSTD_CFLAGS := $(shell $(PKG_CONFIG) --cflags libzstd)
@@ -100,9 +110,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) $(ZSTD_CFLAGS)
+CFLAGS_ALL += $(CRYPTO_CFLAGS) $(ZLIB_CFLAGS) $(ZSTD_CFLAGS)
LIBS := -Wl,--as-needed \
- $(OPENSSL_LIBS) $(ZLIB_LIBS) $(ZSTD_LIBS) \
+ $(CRYPTO_LIBS) $(ZLIB_LIBS) $(ZSTD_LIBS) \
-Wl,--no-as-needed
# Help generation
--
GitLab