From b3db12d705ab44a97cba72af5d4730d2ac4519e0 Mon Sep 17 00:00:00 2001
From: Britney Fransen <brfransen@gmail.com>
Date: Fri, 18 Jul 2025 10:26:22 -0400
Subject: mkinitcpio-openswap: update to 0.1.1

---
 linhes/mkinitcpio-openswap/PKGBUILD         | 12 +++----
 linhes/mkinitcpio-openswap/openswap.conf    | 55 ++++++++++++++++++++++++++---
 linhes/mkinitcpio-openswap/openswap.hook    |  9 +++--
 linhes/mkinitcpio-openswap/openswap.install | 49 +++++++++++++++++++++++++
 4 files changed, 109 insertions(+), 16 deletions(-)

diff --git a/linhes/mkinitcpio-openswap/PKGBUILD b/linhes/mkinitcpio-openswap/PKGBUILD
index a6bad29..ac3bb14 100644
--- a/linhes/mkinitcpio-openswap/PKGBUILD
+++ b/linhes/mkinitcpio-openswap/PKGBUILD
@@ -1,8 +1,9 @@
 # Maintainer: Jenya Sovetkin <e.sovetkin@gmail.com>
+# Maintainer: Adam Bambuch <adam.bambuch2@gmail.com>
 # Contributors: https://aur.archlinux.org/account/f4bio
 pkgname=mkinitcpio-openswap
-pkgver=0.1.0
-pkgrel=3
+pkgver=0.1.1
+pkgrel=1
 pkgdesc="mkinitcpio hook to open swap at boot time"
 arch=(any)
 license=('unknown')
@@ -13,10 +14,9 @@ install="usage.install"
 source=('openswap.hook'
         'openswap.install'
         'openswap.conf')
-sha256sums=('84ef428386b7f4353af036ccfbd4c60901a76e2d0c7a38dd3be2000219ea9d23'
-            '94dd98a953bab2244215a2b20767cdc9500fc438bed9ec27cae72a73766c6b86'
-            '3308f2679bb7c962d98adf2684d25390025d025e3d30bc1e773e3522311ad325')
-                          
+sha256sums=('9e836a588098f2811e651e60dae98096aa59db8a402bc9cb94c42000a5052e3a'
+            '2d60c98d4bd54134a5a4543848ecc7bce598e6faa7bd96a2df0a4767f6e9f3dd'
+            '71516c53543d7deca0fa25efcbf91ca0df869ec0a9fac1ec94e587b18e064c16')
 
 package() {  
   install -Dm 644 openswap.hook \
diff --git a/linhes/mkinitcpio-openswap/openswap.conf b/linhes/mkinitcpio-openswap/openswap.conf
index b7e92e0..6ca341a 100644
--- a/linhes/mkinitcpio-openswap/openswap.conf
+++ b/linhes/mkinitcpio-openswap/openswap.conf
@@ -3,15 +3,60 @@
 swap_device=/dev/disk/by-uuid/2788eb78-074d-4424-9f1d-ebffc9c37262
 crypt_swap_name=cryptswap
 
-## one can optionally provide a keyfile device and path on this device
-## to the keyfile
-keyfile_device=/dev/mapper/cryptroot
-keyfile_filename=etc/keyfile-cryptswap
+## unlock_method can be either password, keyfile or keyfile_raw
+## keyfile will use the keyfile_device and keyfile_filename to unlock the swap
+## keyfile_raw will use the keyfile_device and keyfile_block_number to unlock the swap
+## password will prompt for the password to unlock the swap
+## if unlock_method is not set, then method is keyfile if keyfile_device and keyfile_filename are set
+## otherwise it is password
+unlock_method="password"
+####### WARNING: There is a risk of data loss when using unlock_method="keyfile"
+## You should double-check keyfile_device_mount_options,
+## and note that this method is potentially dangerous regardless.
+## https://docs.kernel.org/power/swsusp.html
+## https://wiki.archlinux.org/title/Dm-crypt/Swap_encryption#busybox-based_initramfs
+
+
+## keyfile_device is the device that contains the keyfile
+## set it to the device that contains the keyfile
+## e.g. /dev/mapper/root-device
+####### THIS OPTION IS MANDATORY IF unlock_method IS keyfile OR keyfile_raw
+keyfile_device=
+
+## keyfile_filename is the path to the keyfile on the keyfile_device
+## e.g. /etc/swap.key
+####### THIS OPTION IS MANDATORY IF unlock_method IS keyfile
+keyfile_filename=
+
+## keyfile_block_number is the block number of the keyfile on the keyfile_device
+## e.g. 12345
+## on the ext4 filesystem, you can get the block number using
+## debugfs $keyfile_device
+## extents $keyfile_filename
+## the relevant block number will appear under the Physical column in the output
+####### THIS OPTION IS MANDATORY IF unlock_method IS keyfile_raw
+keyfile_block_number=
+
+## key_size is the size of the key in bytes
+## e.g., 4096
+## This is the size of the keyfile and should match the actual size of the keyfile.
+## You can get the size of the keyfile using: wc -c <keyfile_filename>
+## The openswap script will fail if the keyfile is fragmented,
+## so keyfile_length should not exceed the filesystem block size.
+## For ext4 filesystems, keyfile_length should not exceed 4096 bytes,
+## and it SHOULD be greater than ~200 bytes to avoid inode inlining.
+####### THIS OPTION IS MANDATORY IF unlock_method IS keyfile_raw
+keyfile_length=4096
 
 ## additional arguments are given to mount for keyfile_device
-## has to start with --options (if so desired)
+## has to start with --options
+## it is important to use the correct options for your filesystem
+## to prevent any writes to the keyfile device and thus
+## minimize the risk of data loss
 #keyfile_device_mount_options="--options=subvol=__active/__"
+keyfile_device_mount_options="--options=ro,noload"
 
 ## additional arguments are given to cryptsetup
 ## --allow-discards options is desired in case swap is on SSD partition
 cryptsetup_options="--type luks"
+
diff --git a/linhes/mkinitcpio-openswap/openswap.hook b/linhes/mkinitcpio-openswap/openswap.hook
index 9a96ad4..3a237c0 100644
--- a/linhes/mkinitcpio-openswap/openswap.hook
+++ b/linhes/mkinitcpio-openswap/openswap.hook
@@ -11,15 +11,14 @@ run_hook ()
     done
     ## End of optional
 
-    if [ -z "$keyfile_device" ] || [ -z "$keyfile_filename" ]
-    then
-      ## case when no keyfile provided in configurations
+    if [ "$unlock_method" = "password" ]; then
       cryptsetup open $cryptsetup_options "$swap_device" "$crypt_swap_name"
-    else
-      ## case when keyfile is provided in configurations
+    elif [ "$unlock_method" = "keyfile" ]; then
       mkdir openswap_keymount
       mount $keyfile_device_mount_options "$keyfile_device" openswap_keymount
       cryptsetup open $cryptsetup_options --key-file "openswap_keymount/$keyfile_filename" "$swap_device" "$crypt_swap_name"
       umount openswap_keymount
+    elif [ "$unlock_method" = "keyfile_raw" ]; then
+      dd "if=$keyfile_device" "bs=$keyfile_length" "skip=$keyfile_block_number" count=1 | cryptsetup open --key-file=- "$swap_device" "$crypt_swap_name"
     fi
 }
diff --git a/linhes/mkinitcpio-openswap/openswap.install b/linhes/mkinitcpio-openswap/openswap.install
index 95d59a3..65dab09 100644
--- a/linhes/mkinitcpio-openswap/openswap.install
+++ b/linhes/mkinitcpio-openswap/openswap.install
@@ -6,9 +6,23 @@ build ()
     grep "keyfile_filename=" /etc/openswap.conf >> "$BUILDROOT/openswap.conf"
     grep "keyfile_device_mount_options=" /etc/openswap.conf >> "$BUILDROOT/openswap.conf"
     grep "cryptsetup_options=" /etc/openswap.conf >> "$BUILDROOT/openswap.conf"
+    grep "keyfile_block_number=" /etc/openswap.conf >> "$BUILDROOT/openswap.conf"
+    grep "unlock_method=" /etc/openswap.conf >> "$BUILDROOT/openswap.conf"
+    grep "keyfile_length=" /etc/openswap.conf >> "$BUILDROOT/openswap.conf"
 
     source "$BUILDROOT/openswap.conf"
 
+    if [ -z "$unlock_method" ]; then
+      # unlock_method is not set, determine it based on keyfile_device and keyfile_filename
+      # for backward compatibility.
+      if [ -z "$keyfile_device" ] || [ -z "$keyfile_filename" ]; then
+        unlock_method="password"
+      else
+        unlock_method="keyfile"
+      fi
+    fi
+    echo "unlock_method=$unlock_method" >> "$BUILDROOT/openswap.conf"
+
     if [ -z "$swap_device" ]; then
       warning "swap_device variable is not set"
     fi
@@ -17,6 +31,41 @@ build ()
       warning "crypt_swap_name variable is not set"
     fi
 
+    if [ "$unlock_method" = "keyfile" ]; then
+      warning "you are using potentially dangerous unlock_method keyfile, please make sure you know what you are doing"
+      warning "https://docs.kernel.org/power/swsusp.html"
+      warning "https://wiki.archlinux.org/title/Dm-crypt/Swap_encryption#busybox-based_initramfs"
+      if [ -z "$keyfile_device" ]; then
+        warning "keyfile_device variable is not set and unlock_method is set to keyfile"
+      fi
+      if [ -z "$keyfile_filename" ]; then
+        warning "keyfile_filename variable is not set and unlock_method is set to keyfile"
+      fi
+
+      if [ -z "$keyfile_device_mount_options" ]; then
+        warning "keyfile_device_mount_options variable is not set and unlock_method is set to keyfile"
+      fi
+    fi
+
+    if [ "$unlock_method" = "keyfile_raw" ]; then
+      if [ -z "$keyfile_device" ]; then
+        warning "keyfile_device variable is not set and unlock_method is set to keyfile_raw"
+      fi
+      if [ -z "$keyfile_block_number" ]; then
+        warning "keyfile_block_number variable is not set and unlock_method is set to keyfile_raw"
+      fi
+      if [ -z "$keyfile_length" ]; then
+        warning "keyfile_length variable is not set and unlock_method is set to keyfile_raw"
+      fi
+    fi
+
+    # check if unlock_method is valid
+    if [ "$unlock_method" != "password" ] && [ "$unlock_method" != "keyfile" ] && [ "$unlock_method" != "keyfile_raw" ]; then
+      error "unlock_method is set to $unlock_method, but it can only be password, keyfile or keyfile_raw"
+      error "please change the unlock_method variable in /etc/openswap.conf"
+      exit 1
+    fi
+
     add_runscript
 }
 help ()
-- 
cgit v0.12

