From: Peter Korsgaard <peter@korsgaard.com>
To: buildroot@buildroot.org
Cc: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
Subject: [Buildroot] [PATCH v2] package/agec: new package
Date: Fri, 19 Jun 2026 11:20:03 +0200 [thread overview]
Message-ID: <20260619092004.3158146-1-peter@korsgaard.com> (raw)
Agec is a simple file encryption tool that implements the
age format in C with minimal dependencies. The tool supports
asymmetric encryption based on X25519, and a passphrase
encryption based on scrypt.
https://git.sr.ht/~min/agec
https://age-encryption.org
Encryption is silently broken for files <35 bytes, so add a patch submitted
upstream to fix that.
Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
---
Changes since v1:
- Add patch submitted upstream fixing encryption of files <35 bytes
- Add runtime test
DEVELOPERS | 2 +
package/Config.in | 1 +
...mor-do-not-set-eof-for-35-byte-files.patch | 35 +++++++++++
package/agec/Config.in | 10 +++
package/agec/agec.hash | 3 +
package/agec/agec.mk | 24 ++++++++
support/testing/tests/package/test_agec.py | 61 +++++++++++++++++++
7 files changed, 136 insertions(+)
create mode 100644 package/agec/0001-io.c-isarmor-do-not-set-eof-for-35-byte-files.patch
create mode 100644 package/agec/Config.in
create mode 100644 package/agec/agec.hash
create mode 100644 package/agec/agec.mk
create mode 100644 support/testing/tests/package/test_agec.py
diff --git a/DEVELOPERS b/DEVELOPERS
index d591c62805..7bc4768ca7 100644
--- a/DEVELOPERS
+++ b/DEVELOPERS
@@ -2647,6 +2647,7 @@ F: configs/orangepi_pc_defconfig
F: configs/orangepi_r1_defconfig
F: configs/sheevaplug_defconfig
F: configs/visionfive_defconfig
+F: package/agec/
F: package/bats-core/
F: package/dfu-programmer/
F: package/docker-compose/
@@ -2681,6 +2682,7 @@ F: package/triggerhappy/
F: package/ugetty/
F: package/wireguard-linux-compat/
F: package/wireguard-tools/
+F: support/testing/tests/package/test_agec.py
F: support/testing/tests/package/test_docker_compose.py
F: support/testing/tests/package/test_python_hid.py
diff --git a/package/Config.in b/package/Config.in
index 96e113e226..b8374fbab5 100644
--- a/package/Config.in
+++ b/package/Config.in
@@ -2728,6 +2728,7 @@ comment "Shells"
source "package/nushell/Config.in"
source "package/zsh/Config.in"
comment "Utilities"
+ source "package/agec/Config.in"
source "package/apg/Config.in"
source "package/at/Config.in"
source "package/bash-completion/Config.in"
diff --git a/package/agec/0001-io.c-isarmor-do-not-set-eof-for-35-byte-files.patch b/package/agec/0001-io.c-isarmor-do-not-set-eof-for-35-byte-files.patch
new file mode 100644
index 0000000000..fa4af2a9c0
--- /dev/null
+++ b/package/agec/0001-io.c-isarmor-do-not-set-eof-for-35-byte-files.patch
@@ -0,0 +1,35 @@
+From eb8ccfe5bb32273226d80236caab7a9386d71071 Mon Sep 17 00:00:00 2001
+From: Peter Korsgaard <peter@korsgaard.com>
+Date: Thu, 18 Jun 2026 15:12:38 +0200
+Subject: [PATCH] io.c: isarmor(): do not set eof for <35 byte files
+
+Encryption is silently broken for <35 byte files since commit b374d8de5a
+("stop reading after first EOF"), as readall() sets the eof flag when it was
+unable to read the entire 35 bytes in isarmor(), causing bread() to return
+EOF and ignore the <35 bytes already read.
+
+Fix it by only setting the eof flag in isarmor() if nothing could be read.
+
+Upstream: mailed to amin@firemail.cc
+Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
+---
+ io.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/io.c b/io.c
+index 15ed4f7..2773022 100644
+--- a/io.c
++++ b/io.c
+@@ -128,8 +128,7 @@ isarmor(Ibuf *b)
+ nr = readall(b->fd, b->buf, sizeof(armorfirst) - 1, &b->eof);
+ if(nr == -1)
+ return -1;
+- if(nr == 0)
+- b->eof = 1;
++ b->eof = (nr == 0);
+ b->size = nr;
+ if((usize)nr < sizeof(armorfirst) - 1)
+ return 0;
+--
+2.47.3
+
diff --git a/package/agec/Config.in b/package/agec/Config.in
new file mode 100644
index 0000000000..8ca9240917
--- /dev/null
+++ b/package/agec/Config.in
@@ -0,0 +1,10 @@
+config BR2_PACKAGE_AGEC
+ bool "agec"
+ select BR2_PACKAGE_OPENSSL
+ help
+ Agec is a simple file encryption tool that implements the
+ age format in C with minimal dependencies. The tool supports
+ asymmetric encryption based on X25519, and a passphrase
+ encryption based on scrypt.
+
+ https://git.sr.ht/~min/agec
diff --git a/package/agec/agec.hash b/package/agec/agec.hash
new file mode 100644
index 0000000000..0b6982f913
--- /dev/null
+++ b/package/agec/agec.hash
@@ -0,0 +1,3 @@
+# Locally calculated
+sha256 97958ff82eaa6aa89328f4319d585e362130168c478cf6a85ba3f4d05e453669 0.1.0.tar.gz
+sha256 f7f37a8bb7d993825b10f5ce2838c1c452d902eda63cd180fdabc7c3a5dd0341 LICENSE
diff --git a/package/agec/agec.mk b/package/agec/agec.mk
new file mode 100644
index 0000000000..b19eac94a4
--- /dev/null
+++ b/package/agec/agec.mk
@@ -0,0 +1,24 @@
+################################################################################
+#
+# agec
+#
+################################################################################
+
+AGEC_VERSION = 0.1.0
+AGEC_SOURCE = $(AGEC_VERSION).tar.gz
+AGEC_SITE = https://git.sr.ht/~min/agec/archive
+AGEC_LICENSE = BSD-0-Clause
+AGEC_LICENSE_FILES = LICENSE
+AGEC_DEPENDENCIES = host-pkgconf openssl
+
+define AGEC_BUILD_CMDS
+ $(MAKE) -C $(@D) $(TARGET_CONFIGURE_OPTS) \
+ LIBS="`$(PKG_CONFIG_HOST_BINARY) --libs openssl`"
+endef
+
+define AGEC_INSTALL_TARGET_CMDS
+ $(MAKE) -C $(@D) $(TARGET_CONFIGURE_OPTS) \
+ PREFIX=$(TARGET_DIR)/usr install
+endef
+
+$(eval $(generic-package))
diff --git a/support/testing/tests/package/test_agec.py b/support/testing/tests/package/test_agec.py
new file mode 100644
index 0000000000..7f43e60b1f
--- /dev/null
+++ b/support/testing/tests/package/test_agec.py
@@ -0,0 +1,61 @@
+import os
+
+import infra.basetest
+
+
+class TestAgec(infra.basetest.BRTest):
+ config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + """
+ BR2_PACKAGE_AGEC=y
+ BR2_TARGET_ROOTFS_CPIO=y
+ """
+
+ # generate keypair in file and return pubkey
+ def generate_keypair(self, filename):
+ self.assertRunOk(f"agec-keygen > {filename}")
+
+ output, exit_code = self.emulator.run(f"agec-keygen -y < {filename}")
+ self.assertEqual(exit_code, 0)
+ pubkey = output[0].strip()
+ self.assertNotEqual(pubkey, "")
+ return pubkey
+
+ def test_run(self):
+ cpio_file = os.path.join(self.builddir, "images", "rootfs.cpio")
+ self.emulator.boot(arch="armv5",
+ kernel="builtin",
+ options=["-initrd", cpio_file])
+ self.emulator.login()
+
+ # We define two keypairs
+ key1 = "/tmp/key1.txt"
+ key2 = "/tmp/key2.txt"
+
+ # And files to work on
+ orig_file = "/bin/busybox"
+ decrypted_file = "/tmp/busybox"
+ encrypted_file = decrypted_file + ".age"
+
+ # should output a valid looking keypair to stdout
+ output, exit_code = self.emulator.run("agec-keygen")
+ self.assertEqual(exit_code, 0)
+ self.assertIn("public key:", output[0])
+ self.assertIn("AGE-SECRET-KEY-", output[1])
+
+ # generate keypairs and extract pubkeys
+ pubkey1 = self.generate_keypair(key1)
+ pubkey2 = self.generate_keypair(key2)
+
+ # encrypt file
+ self.assertRunOk(f"agec -r {pubkey1} {orig_file} > {encrypted_file}")
+
+ # should be encrypted
+ self.assertRunNotOk(f"cmp {orig_file} {encrypted_file}")
+
+ # should be decryptable with key1
+ self.assertRunOk(f"agec -d -i {key1} {encrypted_file} > {decrypted_file}")
+
+ # and equal to original
+ self.assertRunOk(f"cmp {orig_file} {decrypted_file} ")
+
+ # should NOT be decryptable with key2
+ self.assertRunNotOk(f"agec -d -i {key2} {encrypted_file} > {decrypted_file}")
--
2.47.3
_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot
reply other threads:[~2026-06-19 9:20 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260619092004.3158146-1-peter@korsgaard.com \
--to=peter@korsgaard.com \
--cc=buildroot@buildroot.org \
--cc=thomas.petazzoni@bootlin.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox