diff --git a/.gitignore b/.gitignore index 4573ea0..d954773 100644 --- a/.gitignore +++ b/.gitignore @@ -55,9 +55,18 @@ dkms.conf # Eclipse project files .project .cproject +.settings/ # Shufflecake binaries shufflecake +shufflecake-lite +shufflecake-legacy + +# Build directory +bin/ + +# Test images +disks/ # Temporary working directories dm-vvz/ diff --git a/benchmark-suite/veracrypt-benchmark.sh b/benchmark-suite/veracrypt-benchmark.sh index 06ab088..4a69071 100755 --- a/benchmark-suite/veracrypt-benchmark.sh +++ b/benchmark-suite/veracrypt-benchmark.sh @@ -26,7 +26,12 @@ # Variables SCRIPTNAME=$(basename "$0") SCRIPT_DIR="$(dirname "$(realpath "$0")")" +<<<<<<< HEAD CONTAINER_FILENAME="" +======= +LOOP_FILENAME="$SCRIPT_DIR/veracrypt-benchmark-loop-file.img" +LOOP_DEVICE="" +>>>>>>> feature/rewrite-kernel-mod TIMEFORMAT='%3R' # Colors @@ -38,7 +43,11 @@ NC='\033[0m' # No color # Help print_help() { # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 79 chars +<<<<<<< HEAD echo -e "${BLUE}Usage: ${SCRIPTNAME} [OPTION]... [BLOCKDEVICE]${NC}" +======= + echo -e "${BLUE}Usage: ${SCRIPTNAME} [OPTION]... [BLOCKDEVICE]...${NC}" +>>>>>>> feature/rewrite-kernel-mod echo " " echo "This script is used to benchmark VeraCrypt on this machine." echo "This script is part of the Shufflecake benchmark suite." @@ -47,6 +56,7 @@ print_help() { echo " " echo "This script requires root because it operates on block devices, please run it " echo -e "with ${BLUE}sudo${NC}. It does the following:" +<<<<<<< HEAD echo "1) Creates a standard and unformatted VeraCrypt volumes within a given device." echo "2) Creates a hidden ext4 VeraCrypt volume within the standard one." echo "3) Opens the hidden volume, and mounts it." @@ -61,6 +71,22 @@ print_help() { echo " " # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 79 chars echo -e "${BLUE}WARNING: ALL CONTENT OF THE PROVIDED BLOCK DEVICE WILL BE ERASED!${NC}" +======= + echo "1) Creates standard and hidden VeraCrypt volumes within a given device." + echo "2) Opens the hidden volume, formats it with ext4 and mounts it." + echo "3) Performs various fio r/w stress operations on it." + echo "4) Unmounts and closes the used volume." + echo " " +# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 79 chars + echo "You can pass the path to a block device as an optional argument, otherwise the " + echo "script will ask for one. If no path is provided, the script will create a 1 GiB" + echo "local file and use it to back a loop device as a virtual block device to be " + echo "formatted with the appropriate tools. The file will be removed at the end." + echo " " +# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 79 chars + echo "NOTICE: This script has been tested only with VeraCrypt v 1.25.9." + echo -e "${RED}WARNING: ALL CONTENT OF THE PROVIDED BLOCK DEVICE WILL BE ERASED!${NC}" +>>>>>>> feature/rewrite-kernel-mod echo " " exit 0 } @@ -84,7 +110,11 @@ usage() { # Check that this is run as root check_sudo() { if [[ $EUID -ne 0 ]]; then +<<<<<<< HEAD echo -e "${RED}Error: This script must be run as root.${NC}" +======= + echo -e "${RED}Error: This script must be run as root${NC}" +>>>>>>> feature/rewrite-kernel-mod usage exit 1 fi @@ -101,6 +131,7 @@ check_block_device() { fi } +<<<<<<< HEAD check_not_loopdevice() { DEVCHECK=$1 if [[ $DEVCHECK == /dev/loop* ]]; then @@ -121,12 +152,36 @@ create_container_file() { #dd if=/dev/zero of="$CONTAINER_FILENAME" bs=1M count=1024 > /dev/null #echo "Writing of empty file complete." >&2 echo "$CONTAINER_FILENAME" +======= +# Function to create loop device +create_loop_device() { + echo "I will now try to create a file $LOOP_FILENAME" >&2 + if [ -e "$LOOP_FILENAME" ]; then + echo -e "${RED}Error: Impossible to generate file, $LOOP_FILENAME already exists${NC}" + exit 1 + fi + sudo dd if=/dev/zero of="$LOOP_FILENAME" bs=1M count=1024 > /dev/null + echo "Writing of empty file complete. I will now try to attach it to a new loop device..." >&2 + LOOP_DEVICE=$(sudo losetup -f --show "$LOOP_FILENAME") + echo "Successfully created loop device $LOOP_DEVICE" >&2 + echo "$LOOP_DEVICE" +} + +# Generate a suitable VeraCrypt volume name +find_veracryptvolname() { + volname="/dev/mapper/vc01" #placeholder + echo "$volname" +>>>>>>> feature/rewrite-kernel-mod } # Function for user confirmation confirm() { while true; do +<<<<<<< HEAD echo -e "${BLUE}Are you sure you want to proceed? All data in $BLOCK_DEVICE will be erased. (y/n)${NC}" +======= + echo -e "${RED}Are you sure you want to proceed? All data on disk $BLOCK_DEVICE will be erased. (y/n)${NC}" +>>>>>>> feature/rewrite-kernel-mod read -r response case "$response" in [yY]|[yY][eE][sS]) # Responded Yes @@ -136,7 +191,11 @@ confirm() { return 1 # Return 1 for No (error, convention for bash scripting) ;; *) # Responded something else +<<<<<<< HEAD echo "Please press only (y)es or (n)o." +======= + echo "Please press only y or n." +>>>>>>> feature/rewrite-kernel-mod ;; esac done @@ -145,6 +204,7 @@ confirm() { # Benchmarks benchmark() { +<<<<<<< HEAD MNTPOINT="" TESTNAME="vc" RUNTIME="20" # running time in seconds FOR EACH TEST @@ -194,15 +254,35 @@ benchmark() { rmdir $MNTPOINT echo "Volume detached and local mountpoint removed." #end +======= + VOLUME="veracrypt-test" + MNTPOINT="" + PASSPHRASE="mypassword" + echo "Starting benchmark for VeraCrypt" + # TESTS HERE + bpx "THIS IS JUST A SKELETON, VERACRYPT SCRIPT NOT IMPLEMENTED YET, DOING NOTHING..." + # END TESTS + #end +>>>>>>> feature/rewrite-kernel-mod } # Clean up cleanup() { echo "Exiting and cleaning..." +<<<<<<< HEAD if [[ -n $CONTAINER_FILENAME ]]; then echo "Deleting $CONTAINER_FILENAME..." rm -f "$CONTAINER_FILENAME" echo "Container file deleted." +======= + # TODO clean other stuff if necessary + if [[ -n $LOOP_DEVICE ]]; then + echo "Detaching $LOOP_DEVICE" + sudo losetup -d "$LOOP_DEVICE" + echo "Deleting $LOOP_FILENAME" + sudo rm -f "$LOOP_FILENAME" + echo "Loop device detached and backing file deleted." +>>>>>>> feature/rewrite-kernel-mod fi } @@ -215,9 +295,15 @@ cleanup() { # BANNER # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 79 chars +<<<<<<< HEAD echo -e "${BLUE}===============================================================================${NC}" echo -e "${BLUE} Benchmark Suite Script for VeraCrypt${NC}" echo -e "${BLUE}===============================================================================${NC}" +======= +echo -e "${GREEN}===============================================================================${NC}" +echo -e "${GREEN} Benchmark Suite Script for VeraCrypt${NC}" +echo -e "${GREEN}===============================================================================${NC}" +>>>>>>> feature/rewrite-kernel-mod # PRELIMINARY: PARSE HELP, SUDO, AND CHECK VERACRYPT EXISTS @@ -243,12 +329,17 @@ echo " " # PARSER case "$1" in +<<<<<<< HEAD "") # no argument passed +======= + "") +>>>>>>> feature/rewrite-kernel-mod # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 79 chars echo "Now you will be asked to enter the path for a block device to be used for the " echo "benchmarks (all content will be erased). If no path is provided (default" echo "choice), then the script will create a 1 GiB file in the current directory and " +<<<<<<< HEAD echo "use it a VeraCrypt container instead, then the file will be removed at the end." echo " " echo -n "Please enter the path for a (non-loop) block device (default: none): " @@ -262,6 +353,16 @@ case "$1" in BLOCK_DEVICE="$CONTAINER_FILENAME" else check_block_device "$BLOCK_DEVICE" +======= + echo "use it to back a loop device instead, then the file will be removed at the end." + echo " " + echo -n "Please enter the path for a block device (default: none): " + read BLOCK_DEVICE + if [ -z "$BLOCK_DEVICE" ]; then + echo "No path provided, creating a local file and loop device..." + LOOP_DEVICE=$(create_loop_device) + BLOCK_DEVICE=$LOOP_DEVICE +>>>>>>> feature/rewrite-kernel-mod fi ;; @@ -269,16 +370,27 @@ case "$1" in # argument passed *) BLOCK_DEVICE="$1" +<<<<<<< HEAD check_block_device "$BLOCK_DEVICE" ;; esac check_not_loopdevice "$BLOCK_DEVICE" +======= + ;; +esac + +check_block_device "$BLOCK_DEVICE" +>>>>>>> feature/rewrite-kernel-mod # MAIN PROGRAM if confirm; then +<<<<<<< HEAD benchmark +======= + benchmark # Call your disk formatting function here +>>>>>>> feature/rewrite-kernel-mod else echo "Aborting..." fi @@ -286,3 +398,8 @@ fi cleanup +<<<<<<< HEAD +======= + + +>>>>>>> feature/rewrite-kernel-mod diff --git a/dm-sflc/.Kbuild b/dm-sflc/.Kbuild new file mode 100644 index 0000000..89a38fe --- /dev/null +++ b/dm-sflc/.Kbuild @@ -0,0 +1,53 @@ + # + # Copyright The Shufflecake Project Authors (2022) + # Copyright The Shufflecake Project Contributors (2022) + # Copyright Contributors to the The Shufflecake Project. + # + # See the AUTHORS file at the top-level directory of this distribution and at + # + # + # This file is part of the program shufflecake-c, which is part of the + # Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + # layer for Linux. See . + # + # This program is free software: you can redistribute it and/or modify it + # under the terms of the GNU General Public License as published by the Free + # Software Foundation, either version 2 of the License, or (at your option) + # any later version. This program is distributed in the hope that it will be + # useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + # Public License for more details. You should have received a copy of the + # GNU General Public License along with this program. + # If not, see . + # + +MODULE_NAME := dm_sflc +obj-m := $(MODULE_NAME).o + + +OBJ_LIST := sflc.o dev_vol.o sysfs.o + +OBJ_LIST += old/sflc_old.o old/target.o old/sysfs.o +OBJ_LIST += old/device/device.o old/device/volumes.o old/device/rawio.o old/device/rmap.o old/device/iv.o +OBJ_LIST += old/volume/volume.o old/volume/io.o old/volume/read.o old/volume/write.o old/volume/fmap.o +OBJ_LIST += old/utils/string.o old/utils/bio.o old/utils/pools.o old/utils/workqueues.o old/utils/vector.o +OBJ_LIST += old/crypto/rand/rand.o +OBJ_LIST += old/crypto/symkey/symkey.o old/crypto/symkey/skreq_pool.o + +OBJ_LIST += lite/sflc_lite.o lite/sysfs.o +OBJ_LIST += lite/device.o lite/volume.o +OBJ_LIST += lite/posmap.o lite/read.o lite/write.o lite/crypto.o + +$(MODULE_NAME)-y += $(OBJ_LIST) + + +# Normal CC flags +ccflags-y := -O2 +ccflags-y += -I$(src) +ccflags-y += -Wall -Wno-declaration-after-statement + +# Debug CC flags +ccflags-$(CONFIG_SFLC_DEBUG) += -DDEBUG +ccflags-$(CONFIG_SFLC_DEBUG) += -Og -g +ccflags-$(CONFIG_SFLC_DEBUG) += -fsanitize=kernel-address -fno-omit-frame-pointer + diff --git a/dm-sflc/.gitignore b/dm-sflc/.gitignore index ee31866..1ee0110 100644 --- a/dm-sflc/.gitignore +++ b/dm-sflc/.gitignore @@ -1,4 +1,8 @@ .project .cproject .settings/ -bin/ + +!bin/ +*.o +*.symvers +*.ko diff --git a/dm-sflc/Makefile b/dm-sflc/Makefile index b75f428..29c9b12 100644 --- a/dm-sflc/Makefile +++ b/dm-sflc/Makefile @@ -22,25 +22,27 @@ # KERNEL_DIR = /lib/modules/$(shell uname -r)/build -SRC_DIR = $(shell pwd) -BUILD_DIR = $(shell pwd)/bin -BUILD_DIR_MAKEFILE = $(BUILD_DIR)/Makefile +ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) -default: $(BUILD_DIR_MAKEFILE) - make -C $(KERNEL_DIR) M=$(BUILD_DIR) src=$(SRC_DIR) CONFIG_SFLC_DEBUG=$(CONFIG_SFLC_DEBUG) modules - -$(BUILD_DIR_MAKEFILE): $(BUILD_DIR) - echo "# This Makefile is here because of Kbuild" > $@ - -$(BUILD_DIR): - mkdir -p $@ +default: + make -C $(KERNEL_DIR) M=$(ROOT_DIR)/bin CONFIG_SFLC_DEBUG=$(CONFIG_SFLC_DEBUG) modules debug: CONFIG_SFLC_DEBUG=y debug: default install: - make -C $(KERNEL_DIR) M=$(BUILD_DIR) src=$(SRC_DIR) modules_install + make -C $(KERNEL_DIR) M=$(ROOT_DIR)/bin CONFIG_SFLC_DEBUG=$(CONFIG_SFLC_DEBUG) modules_install clean: - rm -rf $(BUILD_DIR) + make -C $(KERNEL_DIR) M=$(ROOT_DIR)/bin CONFIG_SFLC_DEBUG=$(CONFIG_SFLC_DEBUG) clean + +# Reserved +ORIGINALS = $(shell find src/ -type f) +SYMLINKS = $(patsubst src/%, bin/%, $(ORIGINALS)) + +symlinks: $(SYMLINKS) + +bin/%: src/% + @mkdir -p "$(@D)" + ln -s $(shell realpath -m --relative-to=$(@D) $<) $@ diff --git a/dm-sflc/Kbuild b/dm-sflc/bin/Kbuild similarity index 70% rename from dm-sflc/Kbuild rename to dm-sflc/bin/Kbuild index a86d8b9..5e5aa11 100644 --- a/dm-sflc/Kbuild +++ b/dm-sflc/bin/Kbuild @@ -25,14 +25,18 @@ MODULE_NAME := dm-sflc obj-m := $(MODULE_NAME).o -OBJ_LIST := module.o -OBJ_LIST += sysfs/sysfs.o sysfs/devices.o sysfs/volumes.o -OBJ_LIST += target/target.o -OBJ_LIST += device/device.o device/volumes.o device/rawio.o device/rmap.o device/iv.o -OBJ_LIST += volume/volume.o volume/io.o volume/read.o volume/write.o volume/fmap.o -OBJ_LIST += utils/string.o utils/bio.o utils/pools.o utils/workqueues.o utils/vector.o -OBJ_LIST += crypto/rand/rand.o crypto/rand/selftest.o -OBJ_LIST += crypto/symkey/symkey.o crypto/symkey/skreq_pool.o crypto/symkey/selftest.o +OBJ_LIST := sflc.o dev_vol.o sysfs.o + +OBJ_LIST += old/sflc_old.o old/target.o old/sysfs.o +OBJ_LIST += old/device/device.o old/device/volumes.o old/device/rawio.o old/device/rmap.o old/device/iv.o +OBJ_LIST += old/volume/volume.o old/volume/io.o old/volume/read.o old/volume/write.o old/volume/fmap.o +OBJ_LIST += old/utils/string.o old/utils/bio.o old/utils/pools.o old/utils/workqueues.o old/utils/vector.o +OBJ_LIST += old/crypto/rand/rand.o +OBJ_LIST += old/crypto/symkey/symkey.o old/crypto/symkey/skreq_pool.o + +OBJ_LIST += lite/sflc_lite.o lite/sysfs.o +OBJ_LIST += lite/device.o lite/volume.o +OBJ_LIST += lite/posmap.o lite/read.o lite/write.o lite/crypto.o $(MODULE_NAME)-y += $(OBJ_LIST) @@ -41,9 +45,9 @@ $(MODULE_NAME)-y += $(OBJ_LIST) ccflags-y := -O2 ccflags-y += -I$(src) ccflags-y += -Wall -Wno-declaration-after-statement -ccflags-y += -fmacro-prefix-map=$(src)/= # Strip the non-project directories from the filename used in the logs # Debug CC flags ccflags-$(CONFIG_SFLC_DEBUG) += -DDEBUG ccflags-$(CONFIG_SFLC_DEBUG) += -Og -g ccflags-$(CONFIG_SFLC_DEBUG) += -fsanitize=kernel-address -fno-omit-frame-pointer + diff --git a/dm-sflc/bin/dev_vol.c b/dm-sflc/bin/dev_vol.c new file mode 120000 index 0000000..a35e5d5 --- /dev/null +++ b/dm-sflc/bin/dev_vol.c @@ -0,0 +1 @@ +../src/dev_vol.c \ No newline at end of file diff --git a/dm-sflc/bin/lite/crypto.c b/dm-sflc/bin/lite/crypto.c new file mode 120000 index 0000000..1f775dc --- /dev/null +++ b/dm-sflc/bin/lite/crypto.c @@ -0,0 +1 @@ +../../src/lite/crypto.c \ No newline at end of file diff --git a/dm-sflc/bin/lite/device.c b/dm-sflc/bin/lite/device.c new file mode 120000 index 0000000..d2bcea5 --- /dev/null +++ b/dm-sflc/bin/lite/device.c @@ -0,0 +1 @@ +../../src/lite/device.c \ No newline at end of file diff --git a/dm-sflc/bin/lite/dm_io_helper.h b/dm-sflc/bin/lite/dm_io_helper.h new file mode 120000 index 0000000..ec2aa8e --- /dev/null +++ b/dm-sflc/bin/lite/dm_io_helper.h @@ -0,0 +1 @@ +../../src/lite/dm_io_helper.h \ No newline at end of file diff --git a/dm-sflc/bin/lite/posmap.c b/dm-sflc/bin/lite/posmap.c new file mode 120000 index 0000000..e60d53b --- /dev/null +++ b/dm-sflc/bin/lite/posmap.c @@ -0,0 +1 @@ +../../src/lite/posmap.c \ No newline at end of file diff --git a/dm-sflc/bin/lite/read.c b/dm-sflc/bin/lite/read.c new file mode 120000 index 0000000..db9620e --- /dev/null +++ b/dm-sflc/bin/lite/read.c @@ -0,0 +1 @@ +../../src/lite/read.c \ No newline at end of file diff --git a/dm-sflc/bin/lite/sflc_lite.c b/dm-sflc/bin/lite/sflc_lite.c new file mode 120000 index 0000000..1f2a01a --- /dev/null +++ b/dm-sflc/bin/lite/sflc_lite.c @@ -0,0 +1 @@ +../../src/lite/sflc_lite.c \ No newline at end of file diff --git a/dm-sflc/bin/lite/sflc_lite.h b/dm-sflc/bin/lite/sflc_lite.h new file mode 120000 index 0000000..23798f5 --- /dev/null +++ b/dm-sflc/bin/lite/sflc_lite.h @@ -0,0 +1 @@ +../../src/lite/sflc_lite.h \ No newline at end of file diff --git a/dm-sflc/bin/lite/sflite_constants.h b/dm-sflc/bin/lite/sflite_constants.h new file mode 120000 index 0000000..3900993 --- /dev/null +++ b/dm-sflc/bin/lite/sflite_constants.h @@ -0,0 +1 @@ +../../src/lite/sflite_constants.h \ No newline at end of file diff --git a/dm-sflc/bin/lite/sysfs.c b/dm-sflc/bin/lite/sysfs.c new file mode 120000 index 0000000..4fd0f32 --- /dev/null +++ b/dm-sflc/bin/lite/sysfs.c @@ -0,0 +1 @@ +../../src/lite/sysfs.c \ No newline at end of file diff --git a/dm-sflc/bin/lite/volume.c b/dm-sflc/bin/lite/volume.c new file mode 120000 index 0000000..2242793 --- /dev/null +++ b/dm-sflc/bin/lite/volume.c @@ -0,0 +1 @@ +../../src/lite/volume.c \ No newline at end of file diff --git a/dm-sflc/bin/lite/write.c b/dm-sflc/bin/lite/write.c new file mode 120000 index 0000000..665a955 --- /dev/null +++ b/dm-sflc/bin/lite/write.c @@ -0,0 +1 @@ +../../src/lite/write.c \ No newline at end of file diff --git a/dm-sflc/bin/old/crypto/rand/rand.c b/dm-sflc/bin/old/crypto/rand/rand.c new file mode 120000 index 0000000..cd1f529 --- /dev/null +++ b/dm-sflc/bin/old/crypto/rand/rand.c @@ -0,0 +1 @@ +../../../../src/old/crypto/rand/rand.c \ No newline at end of file diff --git a/dm-sflc/bin/old/crypto/rand/rand.h b/dm-sflc/bin/old/crypto/rand/rand.h new file mode 120000 index 0000000..f515491 --- /dev/null +++ b/dm-sflc/bin/old/crypto/rand/rand.h @@ -0,0 +1 @@ +../../../../src/old/crypto/rand/rand.h \ No newline at end of file diff --git a/dm-sflc/bin/old/crypto/symkey/skreq_pool.c b/dm-sflc/bin/old/crypto/symkey/skreq_pool.c new file mode 120000 index 0000000..86e2c3a --- /dev/null +++ b/dm-sflc/bin/old/crypto/symkey/skreq_pool.c @@ -0,0 +1 @@ +../../../../src/old/crypto/symkey/skreq_pool.c \ No newline at end of file diff --git a/dm-sflc/bin/old/crypto/symkey/skreq_pool.h b/dm-sflc/bin/old/crypto/symkey/skreq_pool.h new file mode 120000 index 0000000..26bf22c --- /dev/null +++ b/dm-sflc/bin/old/crypto/symkey/skreq_pool.h @@ -0,0 +1 @@ +../../../../src/old/crypto/symkey/skreq_pool.h \ No newline at end of file diff --git a/dm-sflc/bin/old/crypto/symkey/symkey.c b/dm-sflc/bin/old/crypto/symkey/symkey.c new file mode 120000 index 0000000..f9290b7 --- /dev/null +++ b/dm-sflc/bin/old/crypto/symkey/symkey.c @@ -0,0 +1 @@ +../../../../src/old/crypto/symkey/symkey.c \ No newline at end of file diff --git a/dm-sflc/bin/old/crypto/symkey/symkey.h b/dm-sflc/bin/old/crypto/symkey/symkey.h new file mode 120000 index 0000000..9db23d7 --- /dev/null +++ b/dm-sflc/bin/old/crypto/symkey/symkey.h @@ -0,0 +1 @@ +../../../../src/old/crypto/symkey/symkey.h \ No newline at end of file diff --git a/dm-sflc/bin/old/device/device.c b/dm-sflc/bin/old/device/device.c new file mode 120000 index 0000000..597ebc4 --- /dev/null +++ b/dm-sflc/bin/old/device/device.c @@ -0,0 +1 @@ +../../../src/old/device/device.c \ No newline at end of file diff --git a/dm-sflc/bin/old/device/device.h b/dm-sflc/bin/old/device/device.h new file mode 120000 index 0000000..17a90f4 --- /dev/null +++ b/dm-sflc/bin/old/device/device.h @@ -0,0 +1 @@ +../../../src/old/device/device.h \ No newline at end of file diff --git a/dm-sflc/bin/old/device/iv.c b/dm-sflc/bin/old/device/iv.c new file mode 120000 index 0000000..ba70509 --- /dev/null +++ b/dm-sflc/bin/old/device/iv.c @@ -0,0 +1 @@ +../../../src/old/device/iv.c \ No newline at end of file diff --git a/dm-sflc/bin/old/device/rawio.c b/dm-sflc/bin/old/device/rawio.c new file mode 120000 index 0000000..d1e7e2b --- /dev/null +++ b/dm-sflc/bin/old/device/rawio.c @@ -0,0 +1 @@ +../../../src/old/device/rawio.c \ No newline at end of file diff --git a/dm-sflc/bin/old/device/rmap.c b/dm-sflc/bin/old/device/rmap.c new file mode 120000 index 0000000..1b346c1 --- /dev/null +++ b/dm-sflc/bin/old/device/rmap.c @@ -0,0 +1 @@ +../../../src/old/device/rmap.c \ No newline at end of file diff --git a/dm-sflc/bin/old/device/volumes.c b/dm-sflc/bin/old/device/volumes.c new file mode 120000 index 0000000..531eab0 --- /dev/null +++ b/dm-sflc/bin/old/device/volumes.c @@ -0,0 +1 @@ +../../../src/old/device/volumes.c \ No newline at end of file diff --git a/dm-sflc/bin/old/log/log.h b/dm-sflc/bin/old/log/log.h new file mode 120000 index 0000000..be4c94e --- /dev/null +++ b/dm-sflc/bin/old/log/log.h @@ -0,0 +1 @@ +../../../src/old/log/log.h \ No newline at end of file diff --git a/dm-sflc/bin/old/sflc_old.c b/dm-sflc/bin/old/sflc_old.c new file mode 120000 index 0000000..f003fde --- /dev/null +++ b/dm-sflc/bin/old/sflc_old.c @@ -0,0 +1 @@ +../../src/old/sflc_old.c \ No newline at end of file diff --git a/dm-sflc/bin/old/sflc_old.h b/dm-sflc/bin/old/sflc_old.h new file mode 120000 index 0000000..17e112f --- /dev/null +++ b/dm-sflc/bin/old/sflc_old.h @@ -0,0 +1 @@ +../../src/old/sflc_old.h \ No newline at end of file diff --git a/dm-sflc/bin/old/sysfs.c b/dm-sflc/bin/old/sysfs.c new file mode 120000 index 0000000..a61025a --- /dev/null +++ b/dm-sflc/bin/old/sysfs.c @@ -0,0 +1 @@ +../../src/old/sysfs.c \ No newline at end of file diff --git a/dm-sflc/bin/old/target.c b/dm-sflc/bin/old/target.c new file mode 120000 index 0000000..d853b61 --- /dev/null +++ b/dm-sflc/bin/old/target.c @@ -0,0 +1 @@ +../../src/old/target.c \ No newline at end of file diff --git a/dm-sflc/bin/old/utils/bio.c b/dm-sflc/bin/old/utils/bio.c new file mode 120000 index 0000000..3290da9 --- /dev/null +++ b/dm-sflc/bin/old/utils/bio.c @@ -0,0 +1 @@ +../../../src/old/utils/bio.c \ No newline at end of file diff --git a/dm-sflc/bin/old/utils/bio.h b/dm-sflc/bin/old/utils/bio.h new file mode 120000 index 0000000..287e38d --- /dev/null +++ b/dm-sflc/bin/old/utils/bio.h @@ -0,0 +1 @@ +../../../src/old/utils/bio.h \ No newline at end of file diff --git a/dm-sflc/bin/old/utils/pools.c b/dm-sflc/bin/old/utils/pools.c new file mode 120000 index 0000000..fe89f0f --- /dev/null +++ b/dm-sflc/bin/old/utils/pools.c @@ -0,0 +1 @@ +../../../src/old/utils/pools.c \ No newline at end of file diff --git a/dm-sflc/bin/old/utils/pools.h b/dm-sflc/bin/old/utils/pools.h new file mode 120000 index 0000000..ccc41b3 --- /dev/null +++ b/dm-sflc/bin/old/utils/pools.h @@ -0,0 +1 @@ +../../../src/old/utils/pools.h \ No newline at end of file diff --git a/dm-sflc/bin/old/utils/string.c b/dm-sflc/bin/old/utils/string.c new file mode 120000 index 0000000..7e3ad7b --- /dev/null +++ b/dm-sflc/bin/old/utils/string.c @@ -0,0 +1 @@ +../../../src/old/utils/string.c \ No newline at end of file diff --git a/dm-sflc/bin/old/utils/string.h b/dm-sflc/bin/old/utils/string.h new file mode 120000 index 0000000..8391130 --- /dev/null +++ b/dm-sflc/bin/old/utils/string.h @@ -0,0 +1 @@ +../../../src/old/utils/string.h \ No newline at end of file diff --git a/dm-sflc/bin/old/utils/vector.c b/dm-sflc/bin/old/utils/vector.c new file mode 120000 index 0000000..f340f39 --- /dev/null +++ b/dm-sflc/bin/old/utils/vector.c @@ -0,0 +1 @@ +../../../src/old/utils/vector.c \ No newline at end of file diff --git a/dm-sflc/bin/old/utils/vector.h b/dm-sflc/bin/old/utils/vector.h new file mode 120000 index 0000000..ee1ff17 --- /dev/null +++ b/dm-sflc/bin/old/utils/vector.h @@ -0,0 +1 @@ +../../../src/old/utils/vector.h \ No newline at end of file diff --git a/dm-sflc/bin/old/utils/workqueues.c b/dm-sflc/bin/old/utils/workqueues.c new file mode 120000 index 0000000..d60d1a3 --- /dev/null +++ b/dm-sflc/bin/old/utils/workqueues.c @@ -0,0 +1 @@ +../../../src/old/utils/workqueues.c \ No newline at end of file diff --git a/dm-sflc/bin/old/utils/workqueues.h b/dm-sflc/bin/old/utils/workqueues.h new file mode 120000 index 0000000..b8d2f7e --- /dev/null +++ b/dm-sflc/bin/old/utils/workqueues.h @@ -0,0 +1 @@ +../../../src/old/utils/workqueues.h \ No newline at end of file diff --git a/dm-sflc/bin/old/volume/fmap.c b/dm-sflc/bin/old/volume/fmap.c new file mode 120000 index 0000000..5b46520 --- /dev/null +++ b/dm-sflc/bin/old/volume/fmap.c @@ -0,0 +1 @@ +../../../src/old/volume/fmap.c \ No newline at end of file diff --git a/dm-sflc/bin/old/volume/io.c b/dm-sflc/bin/old/volume/io.c new file mode 120000 index 0000000..d7221c0 --- /dev/null +++ b/dm-sflc/bin/old/volume/io.c @@ -0,0 +1 @@ +../../../src/old/volume/io.c \ No newline at end of file diff --git a/dm-sflc/bin/old/volume/read.c b/dm-sflc/bin/old/volume/read.c new file mode 120000 index 0000000..efdcf3b --- /dev/null +++ b/dm-sflc/bin/old/volume/read.c @@ -0,0 +1 @@ +../../../src/old/volume/read.c \ No newline at end of file diff --git a/dm-sflc/bin/old/volume/volume.c b/dm-sflc/bin/old/volume/volume.c new file mode 120000 index 0000000..8e26280 --- /dev/null +++ b/dm-sflc/bin/old/volume/volume.c @@ -0,0 +1 @@ +../../../src/old/volume/volume.c \ No newline at end of file diff --git a/dm-sflc/bin/old/volume/volume.h b/dm-sflc/bin/old/volume/volume.h new file mode 120000 index 0000000..8f28ef6 --- /dev/null +++ b/dm-sflc/bin/old/volume/volume.h @@ -0,0 +1 @@ +../../../src/old/volume/volume.h \ No newline at end of file diff --git a/dm-sflc/bin/old/volume/write.c b/dm-sflc/bin/old/volume/write.c new file mode 120000 index 0000000..24e67c7 --- /dev/null +++ b/dm-sflc/bin/old/volume/write.c @@ -0,0 +1 @@ +../../../src/old/volume/write.c \ No newline at end of file diff --git a/dm-sflc/bin/sflc.c b/dm-sflc/bin/sflc.c new file mode 120000 index 0000000..d090f9d --- /dev/null +++ b/dm-sflc/bin/sflc.c @@ -0,0 +1 @@ +../src/sflc.c \ No newline at end of file diff --git a/dm-sflc/bin/sflc.h b/dm-sflc/bin/sflc.h new file mode 120000 index 0000000..0b7ccf2 --- /dev/null +++ b/dm-sflc/bin/sflc.h @@ -0,0 +1 @@ +../src/sflc.h \ No newline at end of file diff --git a/dm-sflc/bin/sflc_constants.h b/dm-sflc/bin/sflc_constants.h new file mode 120000 index 0000000..69cd0ab --- /dev/null +++ b/dm-sflc/bin/sflc_constants.h @@ -0,0 +1 @@ +../src/sflc_constants.h \ No newline at end of file diff --git a/dm-sflc/bin/sysfs.c b/dm-sflc/bin/sysfs.c new file mode 120000 index 0000000..e250188 --- /dev/null +++ b/dm-sflc/bin/sysfs.c @@ -0,0 +1 @@ +../src/sysfs.c \ No newline at end of file diff --git a/dm-sflc/crypto/rand/selftest.c b/dm-sflc/crypto/rand/selftest.c deleted file mode 100644 index f0705b9..0000000 --- a/dm-sflc/crypto/rand/selftest.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright The Shufflecake Project Authors (2022) - * Copyright The Shufflecake Project Contributors (2022) - * Copyright Contributors to the The Shufflecake Project. - * - * See the AUTHORS file at the top-level directory of this distribution and at - * - * - * This file is part of the program shufflecake-c, which is part of the - * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) - * layer for Linux. See . - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, either version 2 of the License, or (at your option) - * any later version. This program is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. You should have received a copy of the - * GNU General Public License along with this program. - * If not, see . - */ - -/***************************************************** - * INCLUDE SECTION * - *****************************************************/ - -#include - -#include "rand.h" -#include "log/log.h" - -/***************************************************** - * CONSTANTS * - *****************************************************/ - -/***************************************************** - * PRIVATE VARIABLES * - *****************************************************/ - -/***************************************************** - * PRIVATE FUNCTIONS PROTOTYPES * - *****************************************************/ - -static void dumpHex(u8 * buf, unsigned count); - -/***************************************************** - * PUBLIC FUNCTIONS DEFINITIONS * - *****************************************************/ - -/* Selftest to see (by eye :D) if generated bytes are actually random */ -int sflc_rand_selftest(void) -{ - u8 * buf; - int err; - - buf = kmalloc(32, GFP_KERNEL); - if (!buf) { - pr_err("Could not allocate random scratchpad\n"); - return -ENOMEM; - } - - /* Get random bytes the first time */ - err = sflc_rand_getBytes(buf, 32); - if (err) { - pr_err("Got error when trying to read random bytes the first time: %d\n", err); - kfree(buf); - return err; - } - pr_debug("Here's 32 random bytes, fresh fresh!\n"); - dumpHex(buf, 32); - - /* Do it again */ - err = sflc_rand_getBytes(buf, 32); - if (err) { - pr_err("Got error when trying to read random bytes the second time: %d\n", err); - kfree(buf); - return err; - } - pr_debug("Here's another 32 random bytes, fresh fresh pure questi!\n"); - dumpHex(buf, 32); - - pr_info("All well in the crypto rand self test? (Check random bytes)\n"); - kfree(buf); - - return 0; -} - -/***************************************************** - * PRIVATE FUNCTIONS DEFINITIONS * - *****************************************************/ - -static void dumpHex(u8 * buf, unsigned count) -{ - char * hex; - - hex = kmalloc(6*count + 1, GFP_KERNEL); - if (!hex) { - pr_err("Could not allocate hex dump string\n"); - return; - } - - int i; - for (i = 0; i < count; i++) { - sprintf(hex+6*i, "0x%02X, ", buf[i]); - } - - pr_notice("---- Hex dump ----\n"); - pr_notice("%s", hex); - pr_notice("---- End of hex dump ----\n"); - - kfree(hex); - return; -} diff --git a/dm-sflc/crypto/symkey/selftest.c b/dm-sflc/crypto/symkey/selftest.c deleted file mode 100644 index 332250d..0000000 --- a/dm-sflc/crypto/symkey/selftest.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright The Shufflecake Project Authors (2022) - * Copyright The Shufflecake Project Contributors (2022) - * Copyright Contributors to the The Shufflecake Project. - * - * See the AUTHORS file at the top-level directory of this distribution and at - * - * - * This file is part of the program shufflecake-c, which is part of the - * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) - * layer for Linux. See . - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, either version 2 of the License, or (at your option) - * any later version. This program is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. You should have received a copy of the - * GNU General Public License along with this program. - * If not, see . - */ - -/***************************************************** - * INCLUDE SECTION * - *****************************************************/ - -#include -#include - -#include "symkey.h" -#include "log/log.h" - -/***************************************************** - * CONSTANTS * - *****************************************************/ - -#define KEYS \ -{ \ - {0xF6, 0xD6, 0x6D, 0x6B, 0xD5, 0x2D, 0x59, 0xBB, 0x07, 0x96, 0x36, 0x58, 0x79, 0xEF, 0xF8, 0x86, \ - 0xC6, 0x6D, 0xD5, 0x1A, 0x5B, 0x6A, 0x99, 0x74, 0x4B, 0x50, 0x59, 0x0C, 0x87, 0xA2, 0x38, 0x84}, \ - \ - {0xFF, 0x7A, 0x61, 0x7C, 0xE6, 0x91, 0x48, 0xE4, 0xF1, 0x72, 0x6E, 0x2F, 0x43, 0x58, 0x1D, 0xE2, \ - 0xAA, 0x62, 0xD9, 0xF8, 0x05, 0x53, 0x2E, 0xDF, 0xF1, 0xEE, 0xD6, 0x87, 0xFB, 0x54, 0x15, 0x3D}, \ -} - -#define IVS \ -{ \ - {0x00, 0xFA, 0xAC, 0x24, 0xC1, 0x58, 0x5E, 0xF1, 0x5A, 0x43, 0xD8, 0x75, 0x00, 0x00, 0x00, 0x01}, \ - \ - {0x00, 0x1C, 0xC5, 0xB7, 0x51, 0xA5, 0x1D, 0x70, 0xA1, 0xC1, 0x11, 0x48, 0x00, 0x00, 0x00, 0x01}, \ -} - -#define PLAINTEXTS \ -{ \ - {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, \ - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F}, \ - \ - {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, \ - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F}, \ -} - -#define CIPHERTEXTS \ -{ \ - {0xF0, 0x5E, 0x23, 0x1B, 0x38, 0x94, 0x61, 0x2C, 0x49, 0xEE, 0x00, 0x0B, 0x80, 0x4E, 0xB2, 0xA9, \ - 0xB8, 0x30, 0x6B, 0x50, 0x8F, 0x83, 0x9D, 0x6A, 0x55, 0x30, 0x83, 0x1D, 0x93, 0x44, 0xAF, 0x1C}, \ - \ - {0xEB, 0x6C, 0x52, 0x82, 0x1D, 0x0B, 0xBB, 0xF7, 0xCE, 0x75, 0x94, 0x46, 0x2A, 0xCA, 0x4F, 0xAA, \ - 0xB4, 0x07, 0xDF, 0x86, 0x65, 0x69, 0xFD, 0x07, 0xF4, 0x8C, 0xC0, 0xB5, 0x83, 0xD6, 0x07, 0x1F}, \ -} - -/***************************************************** - * PRIVATE VARIABLES * - *****************************************************/ - -/***************************************************** - * PRIVATE FUNCTIONS PROTOTYPES * - *****************************************************/ - -/* Test encryption or decryption with known test vectors */ -static int testEncdec(bool encrypt); -/* Test that encryption and decryption invert each other */ -static int testRand(void); -static void dumpHex(u8 * buf, unsigned count); - -/***************************************************** - * PUBLIC FUNCTIONS DEFINITIONS * - *****************************************************/ - -/* Self test using known test vectors and random inputs */ -int sflc_sk_selftest(void) -{ - int err; - - /* Test encryption */ - err = testEncdec(true); - if (err) { - pr_err("Error in encryption test: %d\n", err); - return err; - } - - /* Test decryption */ - err = testEncdec(false); - if (err) { - pr_err("Error in decryption test: %d\n", err); - return err; - } - - /* Test with random inputs */ - err = testRand(); - if (err) { - pr_err("Error in random test: %d\n", err); - return err; - } - - pr_info("All good in crypto symkey selftest\n"); - return 0; -} - -/***************************************************** - * PRIVATE FUNCTIONS DEFINITIONS * - *****************************************************/ - -/* Test encryption or decryption with known test vectors */ -static int testEncdec(bool encrypt) -{ - sflc_sk_Context * ctx[2]; - u8 scratchpad[32]; - u8 key[2][32] = KEYS; - u8 iv[2][16] = IVS; - u8 pt[2][32] = PLAINTEXTS; - u8 ct[2][32] = CIPHERTEXTS; - int err; - - int i; - for (i = 0; i < 2; i++) { - memset(scratchpad, 0xa7, 32); - - ctx[i] = sflc_sk_createContext(key[i]); - if (IS_ERR(ctx)) { - err = PTR_ERR(ctx[i]); - pr_err("Could not create sk context; error %d\n", err); - return err; - } - - if (encrypt) { - err = sflc_sk_encrypt(ctx[i], pt[i], scratchpad, 32, iv[i]); - if (err) { - pr_err("Failure during encryption %d; error %d\n", i, err); - sflc_sk_destroyContext(ctx[i]); - return err; - } - if(memcmp(scratchpad, ct[i], 32) != 0) { - pr_err("Mismatch for encryption %d\n", i); - dumpHex(scratchpad, 16); - sflc_sk_destroyContext(ctx[i]); - return -EINVAL; - } - } - else /* decrypt*/ { - err = sflc_sk_decrypt(ctx[i], ct[i], scratchpad, 32, iv[i]); - if (err) { - pr_err("Failure during decryption %d; error %d\n", i, err); - sflc_sk_destroyContext(ctx[i]); - return err; - } - if (memcmp(scratchpad, pt[i], 32) != 0) { - pr_err("Mismatch for decryption %d\n", i); - dumpHex(scratchpad, 32); - sflc_sk_destroyContext(ctx[i]); - return -EINVAL; - } - } - - sflc_sk_destroyContext(ctx[i]); - } - - return 0; -} - -/* Test that encryption and decryption invert each other */ -static int testRand(void) -{ - u8 pt[48]; - u8 scratchpad[48]; - u8 key[32]; - u8 iv[16]; - sflc_sk_Context * ctx; - int err; - - get_random_bytes(key, 32); - ctx = sflc_sk_createContext(key); - if (IS_ERR(ctx)) { - err = PTR_ERR(ctx); - pr_err("Could not create context; error %d\n", err); - return err; - } - memset(iv, 0, 16); - - int i; - for (i = 0; i < 200; i++) { - get_random_bytes(pt, 48); - err = sflc_sk_encrypt(ctx, pt, scratchpad, 48, iv); - if (err) { - pr_err("Could not encrypt; error %d\n", err); - sflc_sk_destroyContext(ctx); - return err; - } - if (memcmp(pt, scratchpad, 48) == 0) { - pr_err("Random iteration %d; pt=scratchpad\n", i); - sflc_sk_destroyContext(ctx); - return -EINVAL; - } - - /* Reset IV */ - iv[15] = 0; - - err = sflc_sk_decrypt(ctx, scratchpad, scratchpad, 48, iv); - if (err) { - pr_err("Could not decrypt; error %d\n", err); - sflc_sk_destroyContext(ctx); - return err; - } - if (memcmp(pt, scratchpad, 48) != 0) { - pr_err("Random iteration %d; mismatch. Dumping plaintext and scratchpad\n", i); - dumpHex(pt, 48); - dumpHex(scratchpad, 48); - sflc_sk_destroyContext(ctx); - return -EINVAL; - } - - /* Reset IV */ - iv[15] = 0; - } - - sflc_sk_destroyContext(ctx); - return 0; -} - -static void dumpHex(u8 * buf, unsigned count) -{ - char * hex; - - hex = kmalloc(6*count + 1, GFP_KERNEL); - if (!hex) { - pr_err("Could not allocate hex dump string\n"); - return; - } - - int i; - for (i = 0; i < count; i++) { - sprintf(hex+6*i, "0x%02X, ", buf[i]); - } - - pr_notice("---- Hex dump ----\n"); - pr_notice("%s", hex); - pr_notice("---- End of hex dump ----\n"); - - kfree(hex); - return; -} diff --git a/dm-sflc/device/device.c b/dm-sflc/device/device.c deleted file mode 100644 index a03f3ea..0000000 --- a/dm-sflc/device/device.c +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright The Shufflecake Project Authors (2022) - * Copyright The Shufflecake Project Contributors (2022) - * Copyright Contributors to the The Shufflecake Project. - * - * See the AUTHORS file at the top-level directory of this distribution and at - * - * - * This file is part of the program shufflecake-c, which is part of the - * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) - * layer for Linux. See . - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, either version 2 of the License, or (at your option) - * any later version. This program is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. You should have received a copy of the - * GNU General Public License along with this program. - * If not, see . - */ - -/* - * This file only implements the device-related device management functions. - */ - -/***************************************************** - * INCLUDE SECTION * - *****************************************************/ - -#include "device.h" -#include "sysfs/sysfs.h" -#include "utils/vector.h" -#include "log/log.h" - -#include -#include - -/***************************************************** - * CONSTANTS * - *****************************************************/ - -/***************************************************** - * PUBLIC VARIABLES DEFINITIONS * - *****************************************************/ - -/* The next available device ID */ -size_t sflc_dev_nextId; - -LIST_HEAD(sflc_dev_list); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,4,0) - DEFINE_SEMAPHORE(sflc_dev_mutex, 1); -#else - DEFINE_SEMAPHORE(sflc_dev_mutex); -#endif - - -/***************************************************** - * PRIVATE VARIABLES * - *****************************************************/ - -/* Array tracking occupation of device IDs */ -static bool *sflc_dev_occupiedIds; - - -/***************************************************** - * PRIVATE FUNCTIONS PROTOTYPES * - *****************************************************/ - -/* Acquire device ID, returns false if not possible */ -static bool sflc_dev_acquireId(size_t id); - -/* Release device ID */ -static void sflc_dev_releaseId(size_t id); - -/* Initialises and pre-shuffles the PSI array */ -static int sflc_dev_initAndShufflePsiArray(u32 *psi_array, u32 len); - - -/***************************************************** - * PUBLIC FUNCTIONS DEFINITIONS * - *****************************************************/ - -/* Inits global variables */ -int sflc_dev_init(void) -{ - /* Allocate occupation array */ - sflc_dev_occupiedIds = kzalloc(SFLC_DEV_MAX_DEVICES_TOT, GFP_KERNEL); - if (!sflc_dev_occupiedIds) { - pr_err("Could not allocate array to track deviceID occupation"); - return -ENOMEM; - } - - /* First available ID is 0 */ - sflc_dev_nextId = 0; - - return 0; -} - -/* Tears down global variables */ -void sflc_dev_exit(void) -{ - kfree(sflc_dev_occupiedIds); -} - -/* Creates Device and adds it to the list. Returns an ERR_PTR() if unsuccessful. */ -sflc_Device * sflc_dev_create(struct dm_target * ti, char * real_dev_path, u32 tot_slices) -{ - sflc_Device * dev; - int err; - int i; - - pr_debug("Called to create sflc_Device on %s\n", real_dev_path); - - /* Allocate device */ - dev = kzalloc(sizeof(sflc_Device), GFP_KERNEL); - if (!dev) { - pr_err("Could not allocate %lu bytes for sflc_Device\n", sizeof(sflc_Device)); - err = -ENOMEM; - goto err_alloc_dev; - } - - /* Init list node here, so it's always safe to list_del() */ - INIT_LIST_HEAD(&dev->list_node); - - /* Set device ID */ - dev->dev_id = sflc_dev_nextId; - if (!sflc_dev_acquireId(sflc_dev_nextId)) { - pr_err("Could not create Device: max number of open devices reached"); - err = -EINVAL; - goto err_dev_id; - } - - /* Set backing real device */ - err = dm_get_device(ti, real_dev_path, dm_table_get_mode(ti->table), &dev->bdev); - if (err) { - pr_err("Could not dm_get_device: error %d\n", err); - goto err_dm_get_dev; - } - /* And its path */ - dev->bdev_path = kmalloc(strlen(real_dev_path) + 1, GFP_KERNEL); - if (!dev->bdev_path) { - pr_err("Could not allocate %lu bytes for dev->real_dev_path\n", strlen(real_dev_path) + 1); - err = -ENOMEM; - goto err_alloc_real_dev_path; - } - strcpy(dev->bdev_path, real_dev_path); - - /* Init volumes */ - for (i = 0; i < SFLC_DEV_MAX_VOLUMES; ++i) { - dev->vol[i] = NULL; - } - dev->vol_cnt = 0; - - /* Set slices info */ - dev->tot_slices = tot_slices; - dev->free_slices = tot_slices; - /* Compute header info (like in userland tool) */ - u32 nr_pmbs_per_vol = DIV_ROUND_UP(tot_slices, SFLC_VOL_HEADER_MAPPINGS_PER_BLOCK); - dev->vol_header_nr_iv_blocks = DIV_ROUND_UP(nr_pmbs_per_vol, SFLC_VOL_LOG_SLICE_SIZE); - dev->vol_header_size = 1 + nr_pmbs_per_vol + dev->vol_header_nr_iv_blocks; - dev->dev_header_size = 1 + (SFLC_DEV_MAX_VOLUMES * dev->vol_header_size); - - /* Init slices lock */ - mutex_init(&dev->slices_lock); - /* Allocate reverse slice map */ - dev->rmap = vmalloc(dev->tot_slices * sizeof(u8)); - if (!dev->rmap) { - pr_err("Could not allocate reverse slice map\n"); - err = -ENOMEM; - goto err_alloc_rmap; - } - /* Initialise it */ - memset(dev->rmap, SFLC_DEV_RMAP_INVALID_VOL, dev->tot_slices * sizeof(u8)); - /* Allocate PSI array */ - dev->prmslices = vmalloc(dev->tot_slices * sizeof(u32)); - if (!dev->prmslices) { - pr_err("Could not allocate PSI array\n"); - err = -ENOMEM; - goto err_alloc_psi_array; - } - /* Initialise it and pre-shuffle it */ - err = sflc_dev_initAndShufflePsiArray(dev->prmslices, dev->tot_slices); - if (err) { - pr_err("Could not init-and-shuffle PSI array: error %d", err); - goto err_initshuffle_psi_array; - } - /* Init related counter */ - dev->prmslices_octr = 0; - - /* Init IV cache lock */ - mutex_init(&dev->iv_cache_lock); - /* Init IV cache waitqueue */ - init_waitqueue_head(&dev->iv_cache_waitqueue); - /* Allocate IV cache */ - dev->iv_cache = vzalloc(dev->tot_slices * sizeof(sflc_dev_IvCacheEntry *)); - if (!dev->iv_cache) { - pr_err("Could not allocate IV cache\n"); - err = -ENOMEM; - goto err_alloc_iv_cache; - } - /* Set it empty */ - dev->iv_cache_nr_entries = 0; - /* Init list head */ - INIT_LIST_HEAD(&dev->iv_lru_list); - - /* Create kobject */ - dev->kobj = sflc_sysfs_devCreateAndAdd(dev); - if (IS_ERR(dev->kobj)) { - err = PTR_ERR(dev->kobj); - pr_err("Could not create kobject; error %d\n", err); - goto err_sysfs; - } - - /* Create dm_io_client */ - dev->dmio_client = dm_io_client_create(); - if (IS_ERR(dev->dmio_client)) { - err = PTR_ERR(dev->dmio_client); - pr_err("Could not create dm_io_client; error %d\n", err); - goto err_dmio; - } - - /* Add to device list */ - list_add_tail(&dev->list_node, &sflc_dev_list); - - return dev; - - -err_dmio: - sflc_sysfs_putDev(dev->kobj); -err_sysfs: - vfree(dev->iv_cache); -err_alloc_iv_cache: -err_initshuffle_psi_array: - vfree(dev->prmslices); -err_alloc_psi_array: - vfree(dev->rmap); -err_alloc_rmap: - kfree(dev->bdev_path); -err_alloc_real_dev_path: - dm_put_device(ti, dev->bdev); -err_dm_get_dev: - sflc_dev_releaseId(dev->dev_id); -err_dev_id: - kfree(dev); -err_alloc_dev: - return ERR_PTR(err); -} - -/* Returns NULL if not found */ -sflc_Device * sflc_dev_lookupByPath(char * real_dev_path) -{ - sflc_Device * dev; - - /* Sweep the list of devices */ - list_for_each_entry(dev, &sflc_dev_list, list_node) { - if (strcmp(real_dev_path, dev->bdev_path) == 0) { - return dev; - } - } - - return NULL; -} - -/* Returns false if still busy (not all volumes have been removed). Frees the Device. */ -bool sflc_dev_destroy(struct dm_target * ti, sflc_Device * dev) -{ - /* Check if we actually have to put this device */ - if (!dev) { - return false; - } - if (dev->vol_cnt > 0) { - pr_warn("Called while still holding %d volumes\n", dev->vol_cnt); - return false; - } - - /* Flush all IVs */ - sflc_dev_flushIvs(dev); - - /* List */ - list_del(&dev->list_node); - - /* dm_io */ - dm_io_client_destroy(dev->dmio_client); - - /* Sysfs */ - sflc_sysfs_putDev(dev->kobj); - - /* IV cache */ - vfree(dev->iv_cache); - - /* PSI array */ - vfree(dev->prmslices); - - /* Reverse slice map */ - vfree(dev->rmap); - - /* Backing device */ - dm_put_device(ti, dev->bdev); - kfree(dev->bdev_path); - - /* Release device ID */ - sflc_dev_releaseId(dev->dev_id); - - /* Free the device itself */ - kfree(dev); - - return true; -} - - -/***************************************************** - * PRIVATE FUNCTIONS DEFINITIONS * - *****************************************************/ - -/* Acquire device ID, returns false if not possible */ -static bool sflc_dev_acquireId(size_t id) -{ - /* Sanity check */ - if (id >= SFLC_DEV_MAX_DEVICES_TOT) { - return false; - } - /* Check occupation */ - if (sflc_dev_occupiedIds[id]) { - return false; - } - - /* Mark as occupied */ - sflc_dev_occupiedIds[id] = true; - - /* Update the nextId if necessary */ - if (id == sflc_dev_nextId) { - /* Jump to the next unoccupied ID */ - for (; id < SFLC_DEV_MAX_DEVICES_TOT && sflc_dev_occupiedIds[id]; id++); - sflc_dev_nextId = id; - } - - return true; -} - -/* Release volume ID */ -static void sflc_dev_releaseId(size_t id) -{ - /* Sanity check */ - if (id >= SFLC_DEV_MAX_DEVICES_TOT) { - return; - } - - /* Mark as unoccupied */ - sflc_dev_occupiedIds[id] = false; - - /* Update the nextId if necessary */ - if (id < sflc_dev_nextId) { - sflc_dev_nextId = id; - } - - return; -} - - -/* Initialises and pre-shuffles the PSI array */ -static int sflc_dev_initAndShufflePsiArray(u32 *psi_array, u32 len) -{ - u32 i; - - /* Init to the identity map */ - for (i = 0; i < len; i++) { - psi_array[i] = i; - } - - /* Permute */ - return sflc_vec_u32shuffle(psi_array, len); -} - diff --git a/dm-sflc/module.c b/dm-sflc/module.c deleted file mode 100644 index 230e60c..0000000 --- a/dm-sflc/module.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright The Shufflecake Project Authors (2022) - * Copyright The Shufflecake Project Contributors (2022) - * Copyright Contributors to the The Shufflecake Project. - * - * See the AUTHORS file at the top-level directory of this distribution and at - * - * - * This file is part of the program shufflecake-c, which is part of the - * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) - * layer for Linux. See . - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, either version 2 of the License, or (at your option) - * any later version. This program is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. You should have received a copy of the - * GNU General Public License along with this program. - * If not, see . - */ - -/***************************************************** - * INCLUDE SECTION * - *****************************************************/ - -#include -#include - -#include "sysfs/sysfs.h" -#include "target/target.h" -#include "crypto/symkey/symkey.h" -#include "crypto/rand/rand.h" -#include "utils/pools.h" -#include "utils/workqueues.h" -#include "log/log.h" - -/***************************************************** - * MODULE FUNCTION PROTOTYPES * - *****************************************************/ - -static int sflc_init(void); -static void sflc_exit(void); - -/***************************************************** - * MODULE FUNCTIONS DEFINITIONS * - *****************************************************/ - -/* Module entry point, called just once, at module-load time */ -static int sflc_init(void) -{ - int ret; - - ret = sflc_dev_init(); - if (ret) { - pr_err("Could not init device module; error %d\n", ret); - goto err_dev_init; - } - - ret = sflc_rand_init(); - if (ret) { - pr_err("Could not init rand; error %d\n", ret); - goto err_rand_init; - } - - /* Run crypto symkey self test */ - ret = sflc_sk_selftest(); - if (ret) { - pr_err("Error in crypto symkey self test: %d\n", ret); - goto err_sk; - } - /* Run crypto rand self test */ - ret = sflc_rand_selftest(); - if (ret) { - pr_err("Error in crypto rand self test: %d\n", ret); - goto err_rand_selftest; - } - - /* Create the first sysfs entries */ - ret = sflc_sysfs_init(); - if (ret) { - pr_err("Could not init sysfs; error %d\n", ret); - goto err_sysfs; - } - - /* Init the memory pools */ - ret = sflc_pools_init(); - if (ret) { - pr_err("Could not init memory pools; error %d\n", ret); - goto err_pools; - } - - /* Init the workqueues */ - ret = sflc_queues_init(); - if (ret) { - pr_err("Could not init workqueues; error %d\n", ret); - goto err_queues; - } - - /* Register the DM callbacks */ - ret = dm_register_target(&sflc_target); - if (ret < 0) { - pr_err("dm_register failed: %d", ret); - goto err_dm; - } - - pr_info("Shufflecake loaded"); - return 0; - - -err_dm: - sflc_queues_exit(); -err_queues: - sflc_pools_exit(); -err_pools: - sflc_sysfs_exit(); -err_sysfs: -err_rand_selftest: -err_sk: - sflc_rand_exit(); -err_rand_init: - sflc_dev_exit(); -err_dev_init: - return ret; -} - -/* Module exit point, called just once, at module-unload time */ -static void sflc_exit(void) -{ - dm_unregister_target(&sflc_target); - sflc_queues_exit(); - sflc_pools_exit(); - sflc_sysfs_exit(); - sflc_rand_exit(); - sflc_dev_exit(); - - pr_info("Shufflecake unloaded"); - return; -} - -/* Declare them as such to the kernel */ -module_init(sflc_init); -module_exit(sflc_exit); - -/***************************************************** - * MODULE INFO * - *****************************************************/ - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Toninov"); diff --git a/dm-sflc/src/dev_vol.c b/dm-sflc/src/dev_vol.c new file mode 100644 index 0000000..3c5e5b3 --- /dev/null +++ b/dm-sflc/src/dev_vol.c @@ -0,0 +1,209 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +#include + +#include "sflc.h" +#include "old/sflc_old.h" + + +/* Create a sflc_device containing the appropriate mode-specific struct */ +struct sflc_device *sflc_dev_create(struct dm_target *ti, int argc, char **argv) +{ + struct sflc_device *sdev; + u32 dev_id; + dev_t devt; + int mode; + int err; + + sdev = kzalloc(sizeof(*sdev), GFP_KERNEL); + if (!sdev) { + DMERR("Could not allocate device"); + return ERR_PTR(-ENOMEM); + } + + /* Parse arguments */ + if (sscanf(argv[0], "%d", &mode) != 1) { + err = -EINVAL; + goto bad_parse; + } + sscanf(argv[1], "%u", &dev_id); + err = lookup_bdev(argv[2], &devt); + if (err) { + DMERR("Could not look up block device"); + goto bad_parse; + } + + /* Assign fields */ + sdev->dev_id = dev_id; + sdev->nr_volumes = 0; + sdev->mode = mode; + format_dev_t(sdev->name, devt); + + /* Register with sysfs */ + err = sflc_sysfs_register_device(sdev); + if (err) + goto bad_sysfs; + + /* Instantiate inner device. Sysfs has to be inited by now */ + switch (mode) + { + case SFLC_MODE_LEGACY: + sdev->sfold_dev = sfold_dev_create(ti, argc, argv, &sdev->kobj); + if (IS_ERR(sdev->sfold_dev)) { + err = PTR_ERR(sdev->sfold_dev); + goto bad_inner; + } + break; + case SFLC_MODE_LITE: + sdev->sflite_dev = sflite_dev_create(ti, argc, argv, &sdev->kobj); + if (IS_ERR(sdev->sflite_dev)) { + err = PTR_ERR(sdev->sflite_dev); + goto bad_inner; + } + break; + default: + DMERR("Invalid Shufflecake mode %d", mode); + err = -EINVAL; + goto bad_mode; + } + + return sdev; + + +bad_mode: +bad_inner: + sflc_sysfs_unregister_device(sdev); +bad_sysfs: +bad_parse: + kfree(sdev); + return ERR_PTR(err); +} + + +void sflc_dev_destroy(struct sflc_device *sdev) +{ + switch (sdev->mode) + { + case SFLC_MODE_LEGACY: + sfold_dev_destroy(sdev->sfold_dev); + break; + case SFLC_MODE_LITE: + sflite_dev_destroy(sdev->sflite_dev); + break; + default: + DMCRIT("Destroying device with invalid Shufflecake mode %d", sdev->mode); + return; + } + + sflc_sysfs_unregister_device(sdev); + kfree(sdev); +} + +/* Create a sflc_volume containing the appropriate mode-specific struct */ +struct sflc_volume *sflc_vol_create(struct sflc_device *sdev, struct dm_target *ti, + int argc, char **argv) +{ + struct sflc_volume *svol; + u32 vol_idx; + int mode; + int err; + + svol = kzalloc(sizeof(*svol), GFP_KERNEL); + if (!svol) { + DMERR("Could not allocate volume"); + return ERR_PTR(-ENOMEM); + } + + /* Parse arguments */ + if (sscanf(argv[0], "%d", &mode) != 1) { + err = -EINVAL; + goto bad_parse; + } + sscanf(argv[3], "%u", &vol_idx); + + /* Assign fields */ + svol->mode = mode; + sprintf(svol->name, "sflc_%u_%u", sdev->dev_id, vol_idx); + svol->sdev = sdev; + + /* Register with sysfs */ + err = sflc_sysfs_register_volume(svol); + if (err) + goto bad_sysfs; + + /* Instantiate inner volume. Sysfs has to be inited by now */ + switch (mode) + { + case SFLC_MODE_LEGACY: + svol->sfold_vol = sfold_vol_create(ti, sdev->sfold_dev, argc, argv, &svol->kobj); + if (IS_ERR(svol->sfold_vol)) { + err = PTR_ERR(svol->sfold_vol); + goto bad_inner; + } + svol->tt = &sfold_target_type; + break; + case SFLC_MODE_LITE: + svol->sflite_vol = sflite_vol_create(ti, sdev->sflite_dev, argc, argv, &svol->kobj); + if (IS_ERR(svol->sflite_vol)) { + err = PTR_ERR(svol->sflite_vol); + goto bad_inner; + } + svol->tt = &sflite_target_type; + break; + default: + DMERR("Invalid Shufflecake mode %d", mode); + err = -EINVAL; + goto bad_mode; + } + + return svol; + + +bad_mode: +bad_inner: + sflc_sysfs_unregister_volume(svol); +bad_sysfs: +bad_parse: + kfree(svol); + return ERR_PTR(err); +} + +void sflc_vol_destroy(struct sflc_volume *svol) +{ + switch (svol->mode) + { + case SFLC_MODE_LEGACY: + sfold_vol_destroy(svol->sfold_vol); + break; + case SFLC_MODE_LITE: + sflite_vol_destroy(svol->sflite_vol); + break; + default: + DMCRIT("Destroying volume with invalid Shufflecake mode %d", svol->mode); + return; + } + + sflc_sysfs_unregister_volume(svol); + kfree(svol); +} diff --git a/dm-sflc/src/lite/crypto.c b/dm-sflc/src/lite/crypto.c new file mode 100644 index 0000000..8e27203 --- /dev/null +++ b/dm-sflc/src/lite/crypto.c @@ -0,0 +1,125 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +#include +#include +#include +#include "sflite_constants.h" + +#include "sflc_lite.h" + + +/** + * Encrypt/decrypt exactly one block, already encoded in the scatterlist. + * All other crypto functions reduce to this one. + * The IV is constructed as the right-0-padded LE representation of the + * physical block number, which is exactly what dm-crypt does when using the + * IV mode "plain64". + */ +static int crypt_sg(struct crypto_skcipher *tfm, struct scatterlist *src, + struct scatterlist *dst, u64 pblk_num, int rw) +{ + u8 iv[SFLITE_XTS_IVLEN]; + struct skcipher_request *req = NULL; + DECLARE_CRYPTO_WAIT(wait); + int err; + + // TODO not too sure about the gfp_mask here + // TODO move @req into struct sflite_io? + req = skcipher_request_alloc(tfm, GFP_NOIO); + if (!req) + return -ENOMEM; + + skcipher_request_set_callback(req, + CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, + crypto_req_done, &wait); + + /* Construct IV */ + memset(iv, 0, SFLITE_XTS_IVLEN); + *(__le64 *)iv = cpu_to_le64(pblk_num); + + skcipher_request_set_crypt(req, src, dst, SFLITE_BLOCK_SIZE, iv); + if (rw == READ) + err = crypto_wait_req(crypto_skcipher_decrypt(req), &wait); + else + err = crypto_wait_req(crypto_skcipher_encrypt(req), &wait); + skcipher_request_free(req); + + return err; +} + +/* Encrypt-decrypt a single block (memory buffer is a page) */ +int sflite_crypt_block_page(struct crypto_skcipher *tfm, struct page *src_page, + struct page *dst_page, u64 pblk_num, int rw) +{ + struct scatterlist dst, src, *p_dst; + bool is_inplace; + + /* Use same scatterlist if in-place */ + is_inplace = (src_page == dst_page); + p_dst = is_inplace ? &src : &dst; + + /* We assume PAGE_SIZE == SFLITE_BLOCK_SIZE */ + /* And orig_bio to start at offset 0 within the page */ + sg_init_table(&src, 1); + sg_set_page(&src, src_page, SFLITE_BLOCK_SIZE, 0); + if (!is_inplace) { + sg_init_table(&dst, 1); + sg_set_page(&dst, dst_page, SFLITE_BLOCK_SIZE, 0); + } + + return crypt_sg(tfm, &src, p_dst, pblk_num, rw); +} + + +/* Encrypt-decrypt consecutive blocks (memory buffer is vmalloc'ed) */ +int sflite_crypt_blocks_vm(struct crypto_skcipher *tfm, void *src_buf, void *dst_buf, + u64 num_blocks, u64 first_pblk_num, int rw) +{ + struct scatterlist dst, src, *p_dst; + u64 pblk_num; + bool is_inplace; + int err; + + /* Use same scatterlist if in-place */ + is_inplace = (src_buf == dst_buf); + p_dst = is_inplace ? &src : &dst; + + for (pblk_num = first_pblk_num; + pblk_num < first_pblk_num + num_blocks; + pblk_num++) { + sg_init_one(&src, src_buf, SFLITE_BLOCK_SIZE); + if (!is_inplace) + sg_init_one(&dst, dst_buf, SFLITE_BLOCK_SIZE); + + err = crypt_sg(tfm, &src, p_dst, pblk_num, rw); + if (err) + return err; + + src_buf += SFLITE_BLOCK_SIZE; + dst_buf += SFLITE_BLOCK_SIZE; + } + + return 0; +} + diff --git a/dm-sflc/src/lite/device.c b/dm-sflc/src/lite/device.c new file mode 100644 index 0000000..e62aa54 --- /dev/null +++ b/dm-sflc/src/lite/device.c @@ -0,0 +1,204 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +#include +#include +#include +#include +#include "sflc_lite.h" + + + +/* Depth of the mempool backing the bio_set */ +#define SFLITE_BIOSET_BIOS 64 + + +/* Fisher-Yates shuffle */ +static void fisheryates_u32(u32 *v, u32 len) +{ + u32 i, j; + + for (i = len-1; i >= 1; i--) { + j = get_random_u32_below(i+1); + swap(v[i], v[j]); + } + + return; +} + +/** + * Arguments: + * argv[0]: Shufflecake mode: legacy/lite + * argv[1]: Shufflecake-unique device ID + * argv[2]: path to underlying physical device + * argv[3]: volume index within the device + * argv[4]: number of 1 MB slices in the underlying device + * argv[5]: 64-byte encryption key (hex-encoded) + */ +struct sflite_device *sflite_dev_create(struct dm_target *ti, int argc, char **argv, struct kobject *kobj) +{ + struct sflite_device *sdev; + dev_t devt; + u32 dev_id; + u32 tot_slices; + int i; + int err; + + sdev = kzalloc(sizeof(*sdev), GFP_KERNEL); + if (!sdev) { + DMERR("Could not allocate device"); + return ERR_PTR(-ENOMEM); + } + + /* Parse args */ + if (argc != 6) { + pr_err("Wrong argument count"); + err = -EINVAL; + goto bad_parse; + } + sscanf(argv[1], "%u", &dev_id); + if (sscanf(argv[4], "%u", &tot_slices) != 1) { + pr_err("Could not decode tot_slices\n"); + err = -EINVAL; + goto bad_parse; + } + + sdev->dev_id = dev_id; + + /* Look up block device and set name */ + err = lookup_bdev(argv[2], &devt); + if (err) { + DMERR("Could not look up block device"); + goto bad_lookup; + } + format_dev_t(sdev->name, devt); + + /* Compute sizes */ + sdev->tot_slices = tot_slices; + sdev->nr_free_slices = tot_slices; + /* Enough posmap blocks to fit all the entries */ + sdev->posmap_size_sectors = SFLITE_BLOCK_SCALE * + DIV_ROUND_UP(tot_slices, SFLITE_PSIS_PER_BLOCK); + /* DMB + VMBs + PosMaps */ + sdev->dev_header_size_sectors = SFLITE_BLOCK_SCALE + + (SFLITE_DEV_MAX_VOLUMES * SFLITE_BLOCK_SCALE) + + (SFLITE_DEV_MAX_VOLUMES * sdev->posmap_size_sectors); + + /* Shuffled PSIs */ + mutex_init(&sdev->slices_lock); + sdev->slices_ofld = vzalloc(tot_slices * sizeof(bool)); + if (!sdev->slices_ofld) { + DMERR("Could not allocate PSI occupation bitfield"); + err = -ENOMEM; + goto bad_ofld; + } + + sdev->prmslices = vmalloc(tot_slices * sizeof(u32)); + if (!sdev->prmslices) { + DMERR("Could not allocate shuffled PSI array"); + err = -ENOMEM; + goto bad_prmslices; + } + /* Generate a permutation */ + for (i = 0; i < tot_slices; i++) + sdev->prmslices[i] = i; + fisheryates_u32(sdev->prmslices, tot_slices); + sdev->prmslices_octr = 0; + + /* Bioset */ + err = bioset_init(&sdev->bioset, SFLITE_BIOSET_BIOS, 0, BIOSET_NEED_BVECS); + if (err) { + DMERR("Could not init bioset; error %d", err); + goto bad_bioset; + } + + /* Client for dm-io */ + sdev->io_client = dm_io_client_create(); + if (IS_ERR(sdev->io_client)) { + err = PTR_ERR(sdev->io_client); + DMERR("Could not create dm-io client; error %d", err); + goto bad_dmio_client; + } + + /* I/O workqueue */ + sdev->io_queue = alloc_workqueue("sflite_%s_io", + WQ_MEM_RECLAIM | WQ_CPU_INTENSIVE, + 0, sdev->name); + if (!sdev->io_queue) { + err = -ENOMEM; + DMERR("Could not allocate I/O workqueue"); + goto bad_io_wq; + } + /* Decryption workqueue */ + sdev->crypt_queue = alloc_workqueue("sflite_%s_crypt", + WQ_MEM_RECLAIM | WQ_CPU_INTENSIVE, + 0, sdev->name); + if (!sdev->crypt_queue) { + err = -ENOMEM; + DMERR("Could not allocate decryption workqueue"); + goto bad_crypt_wq; + } + + /* Add to sysfs, once initialised */ + sdev->kobj_parent = kobj; + err = sflite_sysfs_add_device(sdev); + if (err) + goto bad_sysfs; + + return sdev; + + +bad_sysfs: + destroy_workqueue(sdev->crypt_queue); +bad_crypt_wq: + destroy_workqueue(sdev->io_queue); +bad_io_wq: + dm_io_client_destroy(sdev->io_client); +bad_dmio_client: + bioset_exit(&sdev->bioset); +bad_bioset: + vfree(sdev->prmslices); +bad_prmslices: + vfree(sdev->slices_ofld); +bad_ofld: +bad_lookup: +bad_parse: + kfree(sdev); + return ERR_PTR(err); +} + + +void sflite_dev_destroy(struct sflite_device *sdev) +{ + sflite_sysfs_remove_device(sdev); + destroy_workqueue(sdev->crypt_queue); + destroy_workqueue(sdev->io_queue); + dm_io_client_destroy(sdev->io_client); + bioset_exit(&sdev->bioset); + vfree(sdev->prmslices); + vfree(sdev->slices_ofld); + kfree(sdev); + + return; +} + diff --git a/dm-sflc/src/lite/dm_io_helper.h b/dm-sflc/src/lite/dm_io_helper.h new file mode 100644 index 0000000..7e0d915 --- /dev/null +++ b/dm-sflc/src/lite/dm_io_helper.h @@ -0,0 +1,56 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +#ifndef _SFLITE_DMIOHELPER_H +#define _SFLITE_DMIOHELPER_H + +#include +#include + +/** + * The function dm_io() has changed signature in recent kernels. + * Here we provide a version-independent adapter, which uses a default value + * for the fifth parameter (the new one). + * The new signature is present for kernel 6.1.x with x>=83, 6.6.x with x>=23, + * 6.7.x with x>=11, 6.8.x with x>=2, 6.x with x>=9 + */ +#if LINUX_VERSION_MAJOR <= 5 // Old +#define sflc_dm_io(ioreq, numreg, region, err) dm_io(ioreq, numreg, region, err) +#elif LINUX_VERSION_MAJOR >= 7 // New +#define sflc_dm_io(ioreq, numreg, region, err) dm_io(ioreq, numreg, region, err, IOPRIO_DEFAULT) +// Ok LINUX_VERSION_MAJOR is 6 +#elif LINUX_VERSION_PATCHLEVEL >= 9 // New +#define sflc_dm_io(ioreq, numreg, region, err) dm_io(ioreq, numreg, region, err, IOPRIO_DEFAULT) +#elif LINUX_VERSION_PATCHLEVEL == 8 && LINUX_VERSION_SUBLEVEL >= 2 // New +#define sflc_dm_io(ioreq, numreg, region, err) dm_io(ioreq, numreg, region, err, IOPRIO_DEFAULT) +#elif LINUX_VERSION_PATCHLEVEL == 7 && LINUX_VERSION_SUBLEVEL >= 11 // New +#define sflc_dm_io(ioreq, numreg, region, err) dm_io(ioreq, numreg, region, err, IOPRIO_DEFAULT) +#elif LINUX_VERSION_PATCHLEVEL == 6 && LINUX_VERSION_SUBLEVEL >= 23 // New +#define sflc_dm_io(ioreq, numreg, region, err) dm_io(ioreq, numreg, region, err, IOPRIO_DEFAULT) +#elif LINUX_VERSION_PATCHLEVEL == 1 && LINUX_VERSION_SUBLEVEL >= 83 // New +#define sflc_dm_io(ioreq, numreg, region, err) dm_io(ioreq, numreg, region, err, IOPRIO_DEFAULT) +#else // Old +#define sflc_dm_io(ioreq, numreg, region, err) dm_io(ioreq, numreg, region, err) +#endif + +#endif /* _SFLITE_DMIOHELPER_H */ diff --git a/dm-sflc/src/lite/posmap.c b/dm-sflc/src/lite/posmap.c new file mode 100644 index 0000000..3ee2551 --- /dev/null +++ b/dm-sflc/src/lite/posmap.c @@ -0,0 +1,377 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +#include +#include +#include "dm_io_helper.h" +#include "sflc_lite.h" + + +/* Helpers */ + +#define IS_PSI_TAKEN(sdev, psi) ( (sdev)->slices_ofld[(psi)] ) +#define NEXT_RANDOM_PSI(sdev) ( (sdev)->prmslices[(sdev)->prmslices_octr] ) +#define IS_LAST_LSI_IN_BLOCK(lsi, sdev) ( (((lsi)+1) % SFLITE_PSIS_PER_BLOCK == 0) || \ + (((lsi)+1) == (sdev)->tot_slices) ) + + +/* + *---------------------------- + * Create slice mapping + *---------------------------- + */ + +/** + * Return the next free PSI in the device's shuffled array, without modifying + * the device state. + * + * MUTEX: @sdev->slices_lock must be held. + */ +static int peek_next_free_psi(struct sflite_device *sdev, u32 *psi) +{ + if (unlikely(!sdev->nr_free_slices)) + return -ENOSPC; + if (unlikely(sdev->prmslices_octr >= sdev->tot_slices)) { + DMCRIT("octr = %u, tot_slices = %u, free_slices = %u", sdev->prmslices_octr, sdev->tot_slices, sdev->nr_free_slices); + print_hex_dump(KERN_CRIT, "prmslices(REV) ", DUMP_PREFIX_OFFSET, 32, 4, sdev->prmslices, 4*sdev->tot_slices, false); + msleep(10000); + print_hex_dump(KERN_CRIT, "ofld(REV) ", DUMP_PREFIX_OFFSET, 32, 1, sdev->slices_ofld, sdev->tot_slices, false); + msleep(10000); + return -ENOTRECOVERABLE; // Grave inconsistency + } + + /* Invariant: @prmslices_octr points to a free slice */ + *psi = NEXT_RANDOM_PSI(sdev); + if (unlikely(IS_PSI_TAKEN(sdev, *psi))){ + DMCRIT("octr = %u, tot_slices = %u, free_slices = %u", sdev->prmslices_octr, sdev->tot_slices, sdev->nr_free_slices); + DMCRIT("PSI %u is occupied", *psi); + print_hex_dump(KERN_CRIT, "prmslices ", DUMP_PREFIX_OFFSET, 32, 4, sdev->prmslices, 4*sdev->tot_slices, false); + msleep(10000); + print_hex_dump(KERN_CRIT, "ofld ", DUMP_PREFIX_OFFSET, 32, 1, sdev->slices_ofld, sdev->tot_slices, false); + msleep(10000); + return -ENOTRECOVERABLE; // Grave inconsistency + } + + return 0; +} + +/** + * Map LSI => PSI, only in memory. + * Sanity checks to be performed by the caller. + * + * MUTEX: @sdev->slices_lock must be held. + * MUTEX: @svol->posmap_lock must be held, except under volume ctor. + */ +static void _create_local_slice_mapping(struct sflite_volume *svol, u32 lsi, u32 psi) +{ + struct sflite_device *sdev = svol->sdev; + + /* Grab it from the device */ + sdev->slices_ofld[psi] = true; + sdev->nr_free_slices--; + // Preserve the invariant: @prmslices_octr must point to a free slice + while(sdev->prmslices_octr < sdev->tot_slices && + IS_PSI_TAKEN(sdev, NEXT_RANDOM_PSI(sdev))) { + sdev->prmslices_octr++; + } + + /* Insert in the volume */ + svol->posmap[lsi] = psi; + svol->nr_mapped_slices++; + + return; +} + +/** + * Delete mapping for the given LSI, only in memory. + * Sanity checks to be performed by the caller. + * + * MUTEX: @svol->posmap_lock must be held, except under volume ctor. + */ +static void _delete_local_slice_mapping(struct sflite_volume *svol, u32 lsi) +{ + /* Delete mapping in the volume */ + svol->posmap[lsi] = SFLITE_PSI_INVALID; + svol->nr_mapped_slices--; + + /* Don't do anything in the device though, leave it there: we don't yet + * have an obvious way to release PSIs. + * This means a PSI will be incorrectly marked as occupied, but that's + * not too bad: the PSI shuffling and its occupation counter are + * ephemeral, so they reset if you close and reopen all the volumes. */ + return; +} + +/** + * Synchronously store (and flush) the given posmap block + * + * MUTEX: @svol->posmap_lock must be held, except under volume ctor. + */ +static int store_posmap_block(struct sflite_volume *svol, u32 posmap_block_num) +{ + struct sflite_device *sdev = svol->sdev; + struct page *page; + struct bio *bio; + int err; + + /* Sync + flush TODO GFP mask ok? */ + bio = bio_alloc_bioset(svol->dm_dev->bdev, 1, + REQ_OP_WRITE | REQ_SYNC | REQ_FUA, GFP_NOIO, + &sdev->bioset); + if (!bio) { + DMERR("Could not allocate posmap block bio"); + return -ENOMEM; + } + bio->bi_iter.bi_sector = SFLITE_POSMAP_START_SECTOR(svol) + + (posmap_block_num << SFLITE_BLOCK_SHIFT); + + /* Alloc and add page TODO GFP mask */ + page = alloc_page(GFP_NOIO); + if (!page) { + DMERR("Could not allocate posmap block page"); + err = -ENOMEM; + goto bad_alloc_page; + } + // TODO remove this error check + if (unlikely(!bio_add_page(bio, page, SFLITE_BLOCK_SIZE, 0))) { + DMCRIT("Could not add posmap block page to bio!"); + err = -ENOTRECOVERABLE; + goto bad_add_page; + } + + /* Serialise posmap block onto the page */ + void *page_ptr = kmap_local_page(page); + u32 first_lsi = posmap_block_num * SFLITE_PSIS_PER_BLOCK; + u32 last_lsi = min(first_lsi + SFLITE_PSIS_PER_BLOCK, sdev->tot_slices); + u32 lsi; + for (lsi = first_lsi; lsi < last_lsi; lsi++) { + u32 psi = svol->posmap[lsi]; + __be32 *be_psi = (__be32*) (page_ptr + ((lsi-first_lsi) * sizeof(__be32))); + *be_psi = cpu_to_be32(psi); + } + +// print_hex_dump(KERN_WARNING, "page_ptr(REV) ", DUMP_PREFIX_OFFSET, 32, 4, page_ptr, SFLITE_BLOCK_SIZE, false); +// msleep(100); + + kunmap_local(page_ptr); + + /* Encrypt the block in place */ + err = sflite_crypt_block_page(svol->tfm, page, page, + bio->bi_iter.bi_sector >> SFLITE_BLOCK_SHIFT, WRITE); + if (err) { + DMERR("Could not encrypt posmap block; error %d", err); + goto bad_encrypt; + } + + /* Submit */ + err = submit_bio_wait(bio); + if (err) + DMERR("Could not complete posmap block bio; error %d", err); + +bad_encrypt: +bad_add_page: + __free_page(page); +bad_alloc_page: + bio_put(bio); + return err; +} + + +/** + * Create a new mapping for the given LSI, and synchronise back to disk. + * + * MUTEX: @svol->posmap_lock must be held, except under volume ctor. + * MUTEX: takes @sdev->slices_lock. + * + * Syncing to disk means the posmap lock will be held (by the caller) for a long + * time thus blocking out all the other incoming bio's, even unrelated ones + * (falling in different slices). Several strategies are possible to avoid this + * problem, but for now we keep this simple implementation. + */ +int sflite_create_persistent_slice_mapping(struct sflite_volume *svol, u32 lsi, u32 *psi) +{ + struct sflite_device *sdev = svol->sdev; + int err; + + /* Bounds check TODO redundant? */ + if(unlikely(lsi >= svol->sdev->tot_slices)) + return -EINVAL; + /* Check mapping not existent TODO redundant? */ + if (unlikely(svol->posmap[lsi] != SFLITE_PSI_INVALID)) + return -EINVAL; + + /* Create mapping */ + if (mutex_lock_interruptible(&sdev->slices_lock)) + return -ERESTARTSYS; + err = peek_next_free_psi(sdev, psi); + if (err) { + mutex_unlock(&sdev->slices_lock); + return err; + } + _create_local_slice_mapping(svol, lsi, *psi); + mutex_unlock(&sdev->slices_lock); + + /* Write posmap block to disk */ + err = store_posmap_block(svol, lsi/SFLITE_PSIS_PER_BLOCK); + if (err) { + DMERR("Could not store posmap block; error %d", err); + _delete_local_slice_mapping(svol, lsi); + return err; + } + + return 0; +} + + +/* + *---------------------------- + * Load position map + *---------------------------- + */ + +/** + * Synchronously read the entire on-disk encrypted position map + * + * MUTEX: no need for the caller to hold @svol->posmap_lock (we are in ctor). + */ +static int read_encrypted_posmap(struct sflite_volume *svol) +{ + struct dm_io_request io_req = { + .bi_opf = REQ_OP_READ | REQ_SYNC, + .mem.type = DM_IO_VMA, + .mem.ptr.vma = svol->posmap, + .notify.fn = NULL, + .client = svol->sdev->io_client + }; + struct dm_io_region io_region = { + .bdev = svol->dm_dev->bdev, + .sector = SFLITE_POSMAP_START_SECTOR(svol), + .count = svol->sdev->posmap_size_sectors + }; + + return sflc_dm_io(&io_req, 1, &io_region, NULL); +} + +/** + * De-serialise the position map entries. On the fly, if a conflict is detected, + * resolve it by sampling a new PSI, and sync to disk (block by block). + * + * MUTEX: no need for the caller to hold @svol->posmap_lock (we are in ctor). + * MUTEX: @sdev->slices_lock must be held. + */ +static int _deserialise_and_sanitise_posmap(struct sflite_volume *svol) +{ + struct sflite_device *sdev = svol->sdev; + void *posmap_ptr = svol->posmap; + u32 lsi; + bool posmap_block_dirty; + int err; + + for (lsi = 0; lsi < sdev->tot_slices; lsi++) { + /* Reset dirty bit at the start of every posmap block */ + if (lsi % SFLITE_PSIS_PER_BLOCK == 0) + posmap_block_dirty = false; + + /* De-serialise posmap entry */ + __be32 *be_psi = (__be32*) (posmap_ptr + (lsi * sizeof(__be32))); + u32 psi = be32_to_cpu(*be_psi); + + /* If LSI unmapped, skip mapping creation */ + if (psi == SFLITE_PSI_INVALID) { + svol->posmap[lsi] = psi; + goto skip_create_mapping; + } + + /* If PSI out of bounds, something's seriously wrong */ + if (psi >= sdev->tot_slices) { + DMERR("Decrypted PSI out of bounds: %u >= %u", psi, sdev->tot_slices); + return -EDOM; + } + + /* If PSI already taken, sample a new one */ + if (sdev->slices_ofld[psi]) { + DMWARN("Corruption of volume %u: LSI %u was evicted from PSI %u", + svol->vol_idx, lsi, psi); + err = peek_next_free_psi(sdev, &psi); + if (err) + return err; + posmap_block_dirty = true; + } + /* Whether sanitised or not, create the mapping locally */ + _create_local_slice_mapping(svol, lsi, psi); + +skip_create_mapping: + + /* Only check dirty bit at the end of the posmap block */ + if (posmap_block_dirty && + IS_LAST_LSI_IN_BLOCK(lsi, sdev)) { + err = store_posmap_block(svol, lsi/SFLITE_PSIS_PER_BLOCK); + if (err) + return err; + } + } + + return 0; +} + + +/** + * Load the volume's position map from the disk. If some conflicts are present + * (i.e. an LSI is mapped to a PSI that's already taken), then resolve them + * (i.e. re-sample a free PSI for the "unlucky" LSI) and sync back to disk. + * + * MUTEX: no need for the caller to hold @svol->posmap_lock (we are in ctor). + * MUTEX: takes @sdev->slices_lock. + */ +int sflite_load_and_sanitise_posmap(struct sflite_volume *svol) +{ + int err; + struct sflite_device *sdev = svol->sdev; + + /* Read raw posmap from disk */ + err = read_encrypted_posmap(svol); + if (err) + return err; + + /* Decrypt in place */ + err = sflite_crypt_blocks_vm(svol->tfm, svol->posmap, svol->posmap, + svol->sdev->posmap_size_sectors >> SFLITE_BLOCK_SHIFT, + SFLITE_POSMAP_START_SECTOR(svol) >> SFLITE_BLOCK_SHIFT, + READ); + if (err) + return err; + + /* Deserialise and sanitise as you go */ + if (mutex_lock_interruptible(&sdev->slices_lock)) + return -ERESTARTSYS; + err = _deserialise_and_sanitise_posmap(svol); + mutex_unlock(&sdev->slices_lock); + if (err) + return err; + +// print_hex_dump(KERN_CRIT, "posmap(REV) ", DUMP_PREFIX_OFFSET, 32, 4, svol->posmap, 4*sdev->tot_slices, false); +// msleep(2000); + + return 0; +} + diff --git a/dm-sflc/src/lite/read.c b/dm-sflc/src/lite/read.c new file mode 100644 index 0000000..c7a2016 --- /dev/null +++ b/dm-sflc/src/lite/read.c @@ -0,0 +1,168 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +#include "sflc_lite.h" +#include + + +static void sflite_read_endio(struct bio *phys_bio); +static void sflite_decrypt_work_fn(struct work_struct *work); + + +/* Landing here from ->map() through the io_queue */ +void sflite_read_work_fn(struct work_struct *work) +{ + struct sflite_io *sio = container_of(work, struct sflite_io, work); + struct sflite_volume *svol = sio->svol; + struct sflite_device *sdev = svol->sdev; + struct bio *orig_bio = sio->orig_bio; + struct bio *phys_bio; + u32 lsi = sio->lsi; + u32 block_offset = sio->block_offset; + u32 psi; + + /* Read position map */ + if (mutex_lock_interruptible(&svol->posmap_lock)) { + orig_bio->bi_status = BLK_STS_IOERR; + goto endio; + } + psi = svol->posmap[lsi]; + mutex_unlock(&svol->posmap_lock); + + /* If LSI is unmapped, short-circuit and return all zeros */ + if (psi == SFLITE_PSI_INVALID) { + + zero_fill_bio(orig_bio); + orig_bio->bi_status = BLK_STS_OK; + goto endio; + } + sio->psi = psi; + +// DMWARN("READ: LSI=%u, PSI=%u, offset=%u", lsi, psi, sio->block_offset); +// msleep(100); + + /* Shallow-copy the bio and submit it (different bi_endio). + We can shallow-copy because we don't need to own the pages, + we can decrypt in place. */ + + + //DMWARN("READ: shallow copying"); + //msleep(500); + + /* Shallow copy */ + phys_bio = bio_alloc_clone(svol->dm_dev->bdev, orig_bio, GFP_NOIO, &sdev->bioset); + if (!phys_bio) { + DMERR("Could not clone original bio"); + orig_bio->bi_status = BLK_STS_IOERR; + goto endio; + } + /* Insert in the I/O struct */ + sio->phys_bio = phys_bio; + +// DMWARN("READ: submitting bio"); +// msleep(500); + + /* Remap sector */ + phys_bio->bi_iter.bi_sector = SFLITE_PHYS_BIO_SECTOR(sdev, psi, block_offset); + /* Set fields for the endio */ + phys_bio->bi_private = sio; + phys_bio->bi_end_io = sflite_read_endio; + /* Submit */ + dm_submit_bio_remap(orig_bio, phys_bio); + + return; + + +endio: + bio_endio(orig_bio); + return; +} + + +/* ISR for the phys_bio */ +static void sflite_read_endio(struct bio *phys_bio) +{ + struct sflite_io *sio = phys_bio->bi_private; + +// DMWARN("READ ENDIO: queueing decryption"); +// //msleep(500); + + /* Can't decrypt here in ISR: submit to decryption workqueue. + * Can reuse the same work item, though, since it was popped out of the + * io_queue already */ + INIT_WORK(&sio->work, sflite_decrypt_work_fn); + queue_work(sio->svol->sdev->crypt_queue, &sio->work); +} + + +/* Decrypt and endio */ +static void sflite_decrypt_work_fn(struct work_struct *work) +{ + struct sflite_io *sio = container_of(work, struct sflite_io, work); + struct sflite_volume *svol = sio->svol; + struct bio *orig_bio = sio->orig_bio; + struct bio *phys_bio = sio->phys_bio; + struct bio_vec bvl = bio_iovec(orig_bio); + int err; + + /* If physical bio failed, then fail-fast */ + if (phys_bio->bi_status != BLK_STS_OK) { + orig_bio->bi_status = phys_bio->bi_status; + goto endio; + } + +// DMWARN("DECRYPT FN: decrypting page in place"); +// msleep(2000); + + /* Decrypt page in-place */ + err = sflite_crypt_block_page(svol->tfm, bvl.bv_page, bvl.bv_page, + SFLITE_PHYS_BIO_SECTOR(svol->sdev, sio->psi, sio->block_offset) >> SFLITE_BLOCK_SHIFT, + READ); + if (err) { + DMERR("Could not decrypt bio; error %d", err); + orig_bio->bi_status = BLK_STS_IOERR; + goto endio; + } + +// print_hex_dump(KERN_WARNING, "readpage ", DUMP_PREFIX_OFFSET, 32, 1, bvl.bv_page, SFLITE_BLOCK_SIZE, true); +// msleep(2000); + +// DMWARN("DECRYPT FN: bio_advance"); +// msleep(300); + + /* Advance original bio by one block */ + bio_advance(orig_bio, SFLITE_BLOCK_SIZE); + orig_bio->bi_status = BLK_STS_OK; + +endio: + /* Free the physical bio */ +// DMWARN("DECRYPT FN: bio_put"); +// msleep(300); + bio_put(phys_bio); + /* End original bio */ +// DMWARN("DECRYPT FN: bio_endio\n\n\n\n"); +// msleep(300); + bio_endio(orig_bio); + + return; +} diff --git a/dm-sflc/src/lite/sflc_lite.c b/dm-sflc/src/lite/sflc_lite.c new file mode 100644 index 0000000..edc245f --- /dev/null +++ b/dm-sflc/src/lite/sflc_lite.c @@ -0,0 +1,161 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +#include +#include +#include +#include "sflite_constants.h" +#include "sflc_lite.h" + +// Only to import the definition of struct sflc_volume +#include "sflc.h" + +#include + + +/* + *---------------------------- + * Device mapper target + *---------------------------- + */ + +static int sflite_map(struct dm_target *ti, struct bio *bio) +{ + struct sflite_io *sio = dm_per_bio_data(bio, sizeof(struct sflite_io)); + struct sflc_volume *top_vol = ti->private; + struct sflite_volume *svol = top_vol->sflite_vol; + sector_t lblk_num = bio->bi_iter.bi_sector >> SFLITE_BLOCK_SHIFT; + + if (unlikely(!bio_has_data(bio))) { +// DMWARN("No-data bio: bio_op() = %d, bi_opf = %u, bi_io_vec = %p, bi_idx = %u", bio_op(bio), bio->bi_opf, bio->bi_io_vec, bio->bi_iter.bi_idx); +// msleep(100); + } + + /* Flush requests are just passed down, since our position map is + * currently write-through, so we have no volatile cache */ + if (unlikely(bio->bi_opf & REQ_PREFLUSH)) { + /* Has to be empty though */ + if (bio_sectors(bio)) { + DMWARN("Non-empty flush request!"); + msleep(3000); + return DM_MAPIO_KILL; + } +// DMWARN("REQ_PREFLUSH empty (phew), sector: %llu", bio->bi_iter.bi_sector); +// msleep(100); + bio_set_dev(bio, svol->dm_dev->bdev); + return DM_MAPIO_REMAPPED; + } + + /* Accept one block at a time TODO improve */ + if (unlikely(bio->bi_iter.bi_size > SFLITE_BLOCK_SIZE)) { + DMWARN("Big bio: %u", bio->bi_iter.bi_size); + msleep(300); + dm_accept_partial_bio(bio, SFLITE_BLOCK_SCALE); + } + /* Only one segment, single page, starting at 0 TODO improve */ + if (unlikely(bio_segments(bio) > 1 || + bio_offset(bio) != 0)) { + DMWARN("Unaligned bio!"); + msleep(3000); + return DM_MAPIO_KILL; + } + if (unlikely(bio->bi_iter.bi_size != SFLITE_BLOCK_SIZE)) { + DMWARN("Wrong bio size: %u", bio->bi_iter.bi_size); + msleep(3000); + return DM_MAPIO_KILL; + } + + /* Init I/O struct */ + sio->svol = svol; + sio->orig_bio = bio; + sio->lsi = lblk_num >> SFLITE_SLICE_SHIFT; + sio->block_offset = lblk_num & ((1U << SFLITE_SLICE_SHIFT) - 1); + + /* Enqueue */ + if (bio_data_dir(bio) == READ) + INIT_WORK(&sio->work, sflite_read_work_fn); + else + INIT_WORK(&sio->work, sflite_write_work_fn); + queue_work(svol->sdev->io_queue, &sio->work); + + return DM_MAPIO_SUBMITTED; +} + + +static void sflite_io_hints(struct dm_target *ti, struct queue_limits *limits) +{ + // Currently, we only handle one block at a time TODO improve + limits->logical_block_size = SFLITE_BLOCK_SIZE; + limits->physical_block_size = SFLITE_BLOCK_SIZE; + limits->io_min = SFLITE_BLOCK_SIZE; + limits->io_opt = SFLITE_BLOCK_SIZE; + + return; +} + + +static int sflite_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data) +{ + struct sflc_volume *top_vol = ti->private; + struct sflite_volume *svol = top_vol->sflite_vol; + struct sflite_device *sdev = svol->sdev; + + if (!fn) { + dump_stack(); + msleep(2000); + return -EINVAL; + } + return fn(ti, svol->dm_dev, 0, sdev->dev_header_size_sectors + ti->len, data); +} + + +struct target_type sflite_target_type = { + .map = sflite_map, + .io_hints = sflite_io_hints, + .iterate_devices = sflite_iterate_devices, +}; + + +/* + *---------------------------- + * Init and exit + *---------------------------- + */ + +int sflite_init(void) +{ + /* For the moment, we assume PAGE_SIZE == SFLITE_BLOCK_SIZE TODO improve */ + if (SFLITE_BLOCK_SIZE != PAGE_SIZE) { + DMERR("Error, PAGE_SIZE != %d bytes not yet supported", SFLITE_BLOCK_SIZE); + return -ENOTRECOVERABLE; + } + + return 0; +} + + +void sflite_exit(void) +{ + return; +} + diff --git a/dm-sflc/src/lite/sflc_lite.h b/dm-sflc/src/lite/sflc_lite.h new file mode 100644 index 0000000..1c2e5a7 --- /dev/null +++ b/dm-sflc/src/lite/sflc_lite.h @@ -0,0 +1,182 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +#ifndef _SFLITE_SFLITE_H +#define _SFLITE_SFLITE_H + +#include +#include +#include +#include +#include "sflite_constants.h" +#include "sflc_constants.h" + + +/* + *---------------------------- + * Structs + *---------------------------- + */ + +struct sflite_device +{ + /* Shufflecake-unique device ID */ + u32 dev_id; + /* : */ + char name[16]; + + /* Logical size of each volume */ + u32 tot_slices; + /* Header sizes in 512-byte sectors */ + sector_t posmap_size_sectors; + sector_t dev_header_size_sectors; + + /* Shuffled array of PSIs */ + struct mutex slices_lock; + u32 *prmslices; + u32 prmslices_octr; + bool *slices_ofld; + u32 nr_free_slices; + + /* Parent sysfs directory */ + struct kobject *kobj_parent; + + /* Resource sharing */ + struct bio_set bioset; + struct dm_io_client *io_client; + struct workqueue_struct *io_queue; + struct workqueue_struct *crypt_queue; +}; + +struct sflite_volume +{ + /* Backing device */ + struct sflite_device *sdev; + + /* Underlying block device. This can't go in the sflite_device struct, + * because each ti grabs its own reference. */ + struct dm_dev *dm_dev; + struct dm_target *ti; + + /* Volume index within the device */ + u32 vol_idx; + /* Volume name: sflite__ */ + char name[32]; + + /* Position map */ + struct mutex posmap_lock; + u32 *posmap; + u32 nr_mapped_slices; + + /* Parent sysfs directory */ + struct kobject *kobj_parent; + + /* Crypto */ + u8 enckey[SFLITE_XTS_KEYLEN]; + struct crypto_skcipher *tfm; +}; + +struct sflite_io +{ + struct sflite_volume *svol; + + struct bio *orig_bio; + struct bio *phys_bio; + u32 lsi; + u32 block_offset; + u32 psi; + + struct work_struct work; +}; + + +/* + *---------------------------- + * Macros + *---------------------------- + */ + +/* Starting sector of position map */ +#define SFLITE_POSMAP_START_SECTOR(svol) \ + (SFLITE_BLOCK_SCALE * (1 + SFLITE_DEV_MAX_VOLUMES) + \ + (svol)->vol_idx * (svol)->sdev->posmap_size_sectors) + + +/* Physical sector of a remapped bio */ +#define SFLITE_PHYS_BIO_SECTOR(sdev, psi, off) ( \ + (sdev)->dev_header_size_sectors + ( \ + ((psi << SFLITE_SLICE_SHIFT) + off) << SFLITE_BLOCK_SHIFT \ + ) \ +) + + +/* + *---------------------------- + * Public variables + *---------------------------- + */ + +extern struct target_type sflite_target_type; + + +/* + *---------------------------- + * Functions + *---------------------------- + */ + +/* Init and exit */ +int sflite_init(void); +void sflite_exit(void); + +/* Device */ +struct sflite_device *sflite_dev_create(struct dm_target *ti, int argc, char **argv, struct kobject *kobj); +void sflite_dev_destroy(struct sflite_device *sdev); + +/* Volume */ +struct sflite_volume *sflite_vol_create(struct dm_target *ti, struct sflite_device *sdev, + int argc, char **argv, struct kobject *kobj); +void sflite_vol_destroy(struct sflite_volume *svol); + +/* Sysfs */ +int sflite_sysfs_add_device(struct sflite_device *sdev); +void sflite_sysfs_remove_device(struct sflite_device *sdev); +int sflite_sysfs_add_volume(struct sflite_volume *svol); +void sflite_sysfs_remove_volume(struct sflite_volume *svol); + +/* Bio mapping */ +void sflite_read_work_fn(struct work_struct *work); +void sflite_write_work_fn(struct work_struct *work); + +/* Position map */ +int sflite_load_and_sanitise_posmap(struct sflite_volume *svol); +int sflite_create_persistent_slice_mapping(struct sflite_volume *svol, u32 lsi, u32 *psi); + +/* Crypto */ +int sflite_crypt_blocks_vm(struct crypto_skcipher *tfm, void *src_buf, void *dst_buf, + u64 num_blocks, u64 first_pblk_num, int rw); +int sflite_crypt_block_page(struct crypto_skcipher *tfm, struct page *src_page, + struct page *dst_page, u64 pblk_num, int rw); + + +#endif /* _SFLITE_SFLITE_H */ diff --git a/dm-sflc/src/lite/sflite_constants.h b/dm-sflc/src/lite/sflite_constants.h new file mode 100644 index 0000000..801ff59 --- /dev/null +++ b/dm-sflc/src/lite/sflite_constants.h @@ -0,0 +1,53 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +/* Constants specific to Shufflecake Lite */ + +#ifndef _SFLITE_SFLITE_CONSTANTS_H_ +#define _SFLITE_SFLITE_CONSTANTS_H_ + + +#define SFLITE_BLOCK_SIZE 4096 /* bytes */ +#define SFLITE_BLOCK_SHIFT 3 +#define SFLITE_BLOCK_SCALE (1 << SFLITE_BLOCK_SHIFT) /* 8 sectors in a block */ +#define SFLITE_SLICE_SHIFT 8 +#define SFLITE_SLICE_SCALE (1 << SFLITE_SLICE_SHIFT) /* 256 blocks in a slice */ + + +/* XTS requires doubling the key size */ +#define SFLITE_XTS_KEYLEN 64 /* bytes */ +/* The IV is the right-0-padded LE physical block number */ +#define SFLITE_XTS_IVLEN 16 /* bytes */ + + +#define SFLITE_DEV_MAX_VOLUMES 15 +#define SFLITE_MAX_DEVS 1024 + + +#define SFLITE_PSI_INVALID 0xFFFFFFFF +/* PosMap entries are 4 bytes, therefore there are 1024 of them in a block */ +#define SFLITE_PSIS_PER_BLOCK 1024 + + + +#endif /* _SFLITE_SFLITE_CONSTANTS_H_ */ diff --git a/dm-sflc/src/lite/sysfs.c b/dm-sflc/src/lite/sysfs.c new file mode 100644 index 0000000..88e2d06 --- /dev/null +++ b/dm-sflc/src/lite/sysfs.c @@ -0,0 +1,116 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +#include "sflc_lite.h" + +// Only to import the definitions of structs sflc_volume and sflc_device +#include "sflc.h" + +/* + *---------------------------- + * Device entries + *---------------------------- + */ + +static ssize_t tot_slices_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf) +{ + struct sflc_device *top_dev = container_of(kobj, struct sflc_device, kobj); + struct sflite_device *sdev = top_dev->sflite_dev; + + return sysfs_emit(buf, "%u\n", sdev->tot_slices); +} + +static ssize_t free_slices_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf) +{ + struct sflc_device *top_dev = container_of(kobj, struct sflc_device, kobj); + struct sflite_device *sdev = top_dev->sflite_dev; + int ret; + + if (mutex_lock_interruptible(&sdev->slices_lock)) + return -ERESTARTSYS; + ret = sysfs_emit(buf, "%u\n", sdev->nr_free_slices); + mutex_unlock(&sdev->slices_lock); + + return ret; +} + +static struct kobj_attribute tot_slices_kattr = __ATTR_RO(tot_slices); +static struct kobj_attribute free_slices_kattr = __ATTR_RO(free_slices); +static struct attribute *sflite_device_attrs[] = { + &tot_slices_kattr.attr, + &free_slices_kattr.attr, + NULL +}; +static const struct attribute_group sflite_device_attr_group = { + .attrs = sflite_device_attrs, +}; + +int sflite_sysfs_add_device(struct sflite_device *sdev) +{ + return sysfs_create_group(sdev->kobj_parent, &sflite_device_attr_group); +} + +void sflite_sysfs_remove_device(struct sflite_device *sdev) +{ + sysfs_remove_group(sdev->kobj_parent, &sflite_device_attr_group); +} + + +/* + *---------------------------- + * Volume entries + *---------------------------- + */ + +static ssize_t mapped_slices_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf) +{ + struct sflc_volume *top_vol = container_of(kobj, struct sflc_volume, kobj); + struct sflite_volume *svol = top_vol->sflite_vol; + int ret; + + if (mutex_lock_interruptible(&svol->posmap_lock)) + return -ERESTARTSYS; + ret = sysfs_emit(buf, "%u\n", svol->nr_mapped_slices); + mutex_unlock(&svol->posmap_lock); + + return ret; +} + +static struct kobj_attribute mapped_slices_kattr = __ATTR_RO(mapped_slices); +static struct attribute *sflite_volume_attrs[] = { + &mapped_slices_kattr.attr, + NULL +}; +static const struct attribute_group sflite_volume_attr_group = { + .attrs = sflite_volume_attrs, +}; + +int sflite_sysfs_add_volume(struct sflite_volume *svol) +{ + return sysfs_create_group(svol->kobj_parent, &sflite_volume_attr_group); +} + +void sflite_sysfs_remove_volume(struct sflite_volume *svol) +{ + sysfs_remove_group(svol->kobj_parent, &sflite_volume_attr_group); +} diff --git a/dm-sflc/src/lite/volume.c b/dm-sflc/src/lite/volume.c new file mode 100644 index 0000000..e37d9c1 --- /dev/null +++ b/dm-sflc/src/lite/volume.c @@ -0,0 +1,163 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +#include +#include "sflc_lite.h" + + +/** + * Arguments: + * argv[0]: Shufflecake mode: legacy/lite + * argv[1]: Shufflecake-unique device ID + * argv[2]: path to underlying physical device + * argv[3]: volume index within the device + * argv[4]: number of 1 MB slices in the underlying device + * argv[5]: 64-byte encryption key (hex-encoded) + */ +struct sflite_volume *sflite_vol_create(struct dm_target *ti, struct sflite_device* sdev, + int argc, char **argv, struct kobject *kobj) +{ + struct sflite_volume *svol; + u32 vol_idx; + int err; + + svol = kzalloc(sizeof(*svol), GFP_KERNEL); + if (!svol) { + DMERR("Could not allocate volume"); + return ERR_PTR(-ENOMEM); + } + + /* Parse arguments */ + if (argc != 6) { + DMERR("Wrong argument count"); + err = -EINVAL; + goto bad_parse; + } + if (sscanf(argv[3], "%u", &vol_idx) != 1) { + DMERR("Could not decode tot_slices\n"); + err = -EINVAL; + goto bad_parse; + } + /* Decode the encryption key */ + if (strlen(argv[5]) != 2 * SFLITE_XTS_KEYLEN) { + DMERR("Invalid key length"); + err = -EINVAL; + goto bad_parse; + } + err = hex2bin(svol->enckey, argv[5], SFLITE_XTS_KEYLEN); + if (err) { + DMERR("Could not decode hexadecimal encryption key"); + err = -EINVAL; + goto bad_parse; + } + + svol->sdev = sdev; + svol->vol_idx = vol_idx; + sprintf(svol->name, "sflc_%u_%u", sdev->dev_id, vol_idx); + + svol->ti = ti; + err = dm_get_device(ti, sdev->name, + dm_table_get_mode(ti->table), &svol->dm_dev); + if (err) { + ti->error = "Device lookup failed"; + goto bad_dm_dev; + } + + /* Crypto */ + svol->tfm = crypto_alloc_skcipher("xts(aes)", 0, 0); + if (IS_ERR(svol->tfm)) { + err = PTR_ERR(svol->tfm); + DMERR("Could not allocate AES-XTS cipher handle; error %d", err); + goto bad_tfm_alloc; + } + err = crypto_skcipher_setkey(svol->tfm, svol->enckey, SFLITE_XTS_KEYLEN); + if (err) { + DMERR("Could not set key in crypto transform; error %d", err); + goto bad_tfm_setkey; + } + + /* Position map */ + mutex_init(&svol->posmap_lock); + /* Slight over-allocation, to fit a whole number of blocks */ + svol->posmap = vmalloc(sdev->posmap_size_sectors * SECTOR_SIZE); + if (!svol->posmap) { + DMERR("Could not allocate position map"); + err = -ENOMEM; + goto bad_posmap_alloc; + } + svol->nr_mapped_slices = 0; + /* Load from disk */ + err = sflite_load_and_sanitise_posmap(svol); + if (err) { + DMERR("Could not load position map from disk; error %d", err); + goto bad_posmap_load; + } + + /* Add to sysfs, once initialised */ + svol->kobj_parent = kobj; + err = sflite_sysfs_add_volume(svol); + if (err) { + DMERR("Could not register volume with sysfs; error %d", err); + goto bad_sysfs; + } + + /* Only accept one block per request for simplicity TODO: improve to one slice*/ + ti->max_io_len = SFLITE_BLOCK_SCALE; + ti->flush_supported = true; + ti->num_flush_bios = 1; + ti->discards_supported = false; + ti->num_discard_bios = 0; + ti->num_secure_erase_bios = 0; + ti->num_write_zeroes_bios = 0; + ti->accounts_remapped_io = true; + ti->per_io_data_size = sizeof(struct sflite_io); + ti->private = svol; + + return svol; + + +bad_sysfs: +bad_posmap_load: + vfree(svol->posmap); +bad_posmap_alloc: +bad_tfm_setkey: + crypto_free_skcipher(svol->tfm); +bad_tfm_alloc: + dm_put_device(ti, svol->dm_dev); +bad_dm_dev: +bad_parse: + kfree(svol); + return ERR_PTR(err); +} + + +void sflite_vol_destroy(struct sflite_volume *svol) +{ + sflite_sysfs_remove_volume(svol); + vfree(svol->posmap); + crypto_free_skcipher(svol->tfm); + dm_put_device(svol->ti, svol->dm_dev); + kfree(svol); + + return; +} diff --git a/dm-sflc/src/lite/write.c b/dm-sflc/src/lite/write.c new file mode 100644 index 0000000..5b2fb66 --- /dev/null +++ b/dm-sflc/src/lite/write.c @@ -0,0 +1,148 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +#include "sflc_lite.h" +#include + + +static void sflite_write_endio(struct bio *phys_bio); + + +void sflite_write_work_fn(struct work_struct *work) +{ + struct sflite_io *sio = container_of(work, struct sflite_io, work); + struct sflite_volume *svol = sio->svol; + struct sflite_device *sdev = svol->sdev; + struct bio *orig_bio = sio->orig_bio; + struct bio_vec bvl = bio_iovec(orig_bio); + struct bio *phys_bio; + struct page *page; + u32 lsi = sio->lsi; + u32 block_offset = sio->block_offset; + u32 psi; + int err; + +// DMWARN("WRITE: dequeued. Sector = %llu", orig_bio->bi_iter.bi_sector); +// msleep(100); + + + /* Read existing mapping, or create new one */ + if (mutex_lock_interruptible(&svol->posmap_lock)) { + orig_bio->bi_status = BLK_STS_IOERR; + goto endio; + } + psi = svol->posmap[lsi]; + /* If LSI unmapped, create new mapping, while holding the lock */ + if (psi == SFLITE_PSI_INVALID) { +// DMWARN("WRITE: unmapped LSI %u, sampling PSI", lsi); +// msleep(100); + + err = sflite_create_persistent_slice_mapping(svol, lsi, &psi); + if (err){ + DMERR("Could not create slice mapping; error %d", err); + mutex_unlock(&svol->posmap_lock); + orig_bio->bi_status = BLK_STS_IOERR; + goto endio; + } +// DMWARN("WRITE: sampled PSI %u for LSI %u", psi, lsi); +// msleep(100); + } + mutex_unlock(&svol->posmap_lock); + sio->psi = psi; + + /* Allocate physical bio */ + phys_bio = bio_alloc_bioset(svol->dm_dev->bdev, 1, orig_bio->bi_opf, + GFP_NOIO, &sdev->bioset); + if (!phys_bio) { + DMERR("Could not allocate physical bio"); + orig_bio->bi_status = BLK_STS_IOERR; + goto endio; + } + /* Insert in the I/O struct */ + sio->phys_bio = phys_bio; + + /* Physical bio needs its own page */ + page = alloc_pages(GFP_NOIO, 0); + if (!page) { + DMERR("Could not allocate page for physical bio"); + orig_bio->bi_status = BLK_STS_IOERR; + goto bad_alloc_page; + } + + /* Remap sector */ + phys_bio->bi_iter.bi_sector = SFLITE_PHYS_BIO_SECTOR(sdev, psi, block_offset); + /* Encrypt */ + err = sflite_crypt_block_page(svol->tfm, bvl.bv_page, page, + phys_bio->bi_iter.bi_sector >> SFLITE_BLOCK_SHIFT, WRITE); + if (err) { + DMERR("Could not encrypt bio; error %d", err); + orig_bio->bi_status = BLK_STS_IOERR; + goto bad_encrypt; + } + + /* Add page to bio */ + __bio_add_page(phys_bio, page, SFLITE_BLOCK_SIZE, 0); + /* Set fields for the endio */ + phys_bio->bi_private = sio; + phys_bio->bi_end_io = sflite_write_endio; + /* Submit */ + dm_submit_bio_remap(orig_bio, phys_bio); + + return; + + +bad_encrypt: + __free_page(page); +bad_alloc_page: + bio_put(phys_bio); +endio: + bio_endio(orig_bio); + return; +} + +static void sflite_write_endio(struct bio *phys_bio) +{ + struct sflite_io *sio = phys_bio->bi_private; + struct bio *orig_bio = sio->orig_bio; + + /* If physical bio failed, then fail-fast */ + if (phys_bio->bi_status != BLK_STS_OK) { + orig_bio->bi_status = phys_bio->bi_status; + DMWARN("WRITE ENDIO: phys_bio failed"); + goto endio; + } + + /* Advance original bio by one block */ + bio_advance(orig_bio, SFLITE_BLOCK_SIZE); + orig_bio->bi_status = BLK_STS_OK; + +endio: + /* Free the physical bio and its page */ + bio_free_pages(phys_bio); + bio_put(phys_bio); + /* End original bio */ + bio_endio(orig_bio); + + return; +} + diff --git a/dm-sflc/crypto/rand/rand.c b/dm-sflc/src/old/crypto/rand/rand.c similarity index 77% rename from dm-sflc/crypto/rand/rand.c rename to dm-sflc/src/old/crypto/rand/rand.c index 150a909..4981967 100644 --- a/dm-sflc/crypto/rand/rand.c +++ b/dm-sflc/src/old/crypto/rand/rand.c @@ -28,55 +28,55 @@ #include #include -#include "rand.h" -#include "log/log.h" +#include "old/crypto/rand/rand.h" +#include "old/log/log.h" /***************************************************** * CONSTANTS * *****************************************************/ -#define SFLC_RAND_RNG_NAME "drbg_nopr_sha256" +#define SFOLD_RAND_RNG_NAME "drbg_nopr_sha256" /***************************************************** * PRIVATE VARIABLES * *****************************************************/ -static struct mutex sflc_rand_tfm_lock; -static struct crypto_rng * sflc_rand_tfm = NULL; +static struct mutex sfold_rand_tfm_lock; +static struct crypto_rng * sfold_rand_tfm = NULL; /***************************************************** * PRIVATE FUNCTIONS PROTOTYPES * *****************************************************/ /* Flexible to accommodate for both required and non-required reseeding */ -static int sflc_rand_reseed(void); +static int sfold_rand_reseed(void); /***************************************************** * PUBLIC FUNCTIONS DEFINITIONS * *****************************************************/ /* Init the submodule */ -int sflc_rand_init(void) +int sfold_rand_init(void) { int err; /* Init the lock governing the SFLC RNG */ - mutex_init(&sflc_rand_tfm_lock); + mutex_init(&sfold_rand_tfm_lock); /* Allocate module-wide RNG */ - sflc_rand_tfm = crypto_alloc_rng(SFLC_RAND_RNG_NAME, CRYPTO_ALG_TYPE_RNG, 0); - if (IS_ERR(sflc_rand_tfm)) { - err = PTR_ERR(sflc_rand_tfm); - sflc_rand_tfm = NULL; - pr_err("Could not allocate RNG %s; error %d\n", SFLC_RAND_RNG_NAME, err); + sfold_rand_tfm = crypto_alloc_rng(SFOLD_RAND_RNG_NAME, CRYPTO_ALG_TYPE_RNG, 0); + if (IS_ERR(sfold_rand_tfm)) { + err = PTR_ERR(sfold_rand_tfm); + sfold_rand_tfm = NULL; + pr_err("Could not allocate RNG %s; error %d\n", SFOLD_RAND_RNG_NAME, err); return err; } /* The new RNG comes not seeded, right? */ - err = sflc_rand_reseed(); + err = sfold_rand_reseed(); if (err) { pr_err("Could not seed the RNG; error %d\n", err); - sflc_rand_exit(); + sfold_rand_exit(); return err; } @@ -84,26 +84,26 @@ int sflc_rand_init(void) } /* Get random bytes. Might sleep for re-seeding (not implemented yet), or for contention (mutex). */ -int sflc_rand_getBytes(u8 * buf, unsigned count) +int sfold_rand_getBytes(u8 * buf, unsigned count) { int ret; /* Acquire lock */ - if (mutex_lock_interruptible(&sflc_rand_tfm_lock)) { + if (mutex_lock_interruptible(&sfold_rand_tfm_lock)) { pr_err("Got error while waiting for SFLC RNG\n"); return -EINTR; } - ret = crypto_rng_get_bytes(sflc_rand_tfm, buf, count); + ret = crypto_rng_get_bytes(sfold_rand_tfm, buf, count); /* End of critical region */ - mutex_unlock(&sflc_rand_tfm_lock); + mutex_unlock(&sfold_rand_tfm_lock); return ret; } /* Get a random s32 from 0 (inclusive) to max (exclusive). Returns < 0 if error. */ -s32 sflc_rand_uniform(s32 max) +s32 sfold_rand_uniform(s32 max) { s32 rand; s32 thresh; @@ -120,7 +120,7 @@ s32 sflc_rand_uniform(s32 max) thresh = S32_MAX - (S32_MAX % max); do { /* Sample a random signed integer, then make it positive */ - int err = sflc_rand_getBytes((void *) &rand, sizeof(rand)); + int err = sfold_rand_getBytes((void *) &rand, sizeof(rand)); /* Can't make it positive if it's all 1's */ if (rand == S32_MIN) { continue; @@ -140,11 +140,11 @@ s32 sflc_rand_uniform(s32 max) } /* Tear down the submodule */ -void sflc_rand_exit(void) +void sfold_rand_exit(void) { - if (sflc_rand_tfm) { - crypto_free_rng(sflc_rand_tfm); - sflc_rand_tfm = NULL; + if (sfold_rand_tfm) { + crypto_free_rng(sfold_rand_tfm); + sfold_rand_tfm = NULL; } return; @@ -155,12 +155,12 @@ void sflc_rand_exit(void) *****************************************************/ /* Flexible to accommodate for both required and non-required reseeding */ -static int sflc_rand_reseed(void) +static int sfold_rand_reseed(void) { int err; /* Reseed the RNG */ - err = crypto_rng_reset(sflc_rand_tfm, NULL, crypto_rng_seedsize(sflc_rand_tfm)); + err = crypto_rng_reset(sfold_rand_tfm, NULL, crypto_rng_seedsize(sfold_rand_tfm)); if (err) { pr_err("Could not feed seed to the RNG; error %d\n", err); return err; diff --git a/dm-sflc/crypto/rand/rand.h b/dm-sflc/src/old/crypto/rand/rand.h similarity index 85% rename from dm-sflc/crypto/rand/rand.h rename to dm-sflc/src/old/crypto/rand/rand.h index 4d5f8a7..d7de86a 100644 --- a/dm-sflc/crypto/rand/rand.h +++ b/dm-sflc/src/old/crypto/rand/rand.h @@ -27,8 +27,8 @@ * no need to make it more fine grained. */ -#ifndef _SFLC_CRYPTO_RAND_RAND_H_ -#define _SFLC_CRYPTO_RAND_RAND_H_ +#ifndef _SFOLD_CRYPTO_RAND_RAND_H_ +#define _SFOLD_CRYPTO_RAND_RAND_H_ /***************************************************** * INCLUDE SECTION * @@ -40,20 +40,17 @@ * PUBLIC FUNCTIONS PROTOTYPES * *****************************************************/ -/* Selftest to see (by eye :D) if generated bytes are actually random */ -int sflc_rand_selftest(void); - /* Init the submodule */ -int sflc_rand_init(void); +int sfold_rand_init(void); /* Get random bytes. Might sleep for re-seeding (not implemented yet), or for contention (mutex). */ -int sflc_rand_getBytes(u8 * buf, unsigned count); +int sfold_rand_getBytes(u8 * buf, unsigned count); /* Get a random s32 from 0 (inclusive) to max (exclusive). Returns < 0 if error. */ -s32 sflc_rand_uniform(s32 max); +s32 sfold_rand_uniform(s32 max); /* Tear down the submodule */ -void sflc_rand_exit(void); +void sfold_rand_exit(void); -#endif /* _SFLC_CRYPTO_RAND_RAND_H_ */ +#endif /* _SFOLD_CRYPTO_RAND_RAND_H_ */ diff --git a/dm-sflc/crypto/symkey/skreq_pool.c b/dm-sflc/src/old/crypto/symkey/skreq_pool.c similarity index 82% rename from dm-sflc/crypto/symkey/skreq_pool.c rename to dm-sflc/src/old/crypto/symkey/skreq_pool.c index d77c9e1..a91fbf8 100644 --- a/dm-sflc/crypto/symkey/skreq_pool.c +++ b/dm-sflc/src/old/crypto/symkey/skreq_pool.c @@ -25,8 +25,8 @@ * INCLUDE SECTION * *****************************************************/ -#include "skreq_pool.h" -#include "log/log.h" +#include "old/crypto/symkey/skreq_pool.h" +#include "old/log/log.h" /***************************************************** * CONSTANTS * @@ -37,17 +37,17 @@ *****************************************************/ /* A mempool_alloc_t using skcipher_request_alloc as backend */ -static void * sflc_sk_allocRequest(gfp_t gfp_mask, void * pool_data); +static void * sfold_sk_allocRequest(gfp_t gfp_mask, void * pool_data); /* A mempool_free_t using skcipher_request_free as backend */ -static void sflc_sk_freeRequest(void * element, void * pool_data); +static void sfold_sk_freeRequest(void * element, void * pool_data); /***************************************************** * PUBLIC FUNCTIONS DEFINITIONS * *****************************************************/ -mempool_t * sflc_sk_createReqPool(int min_nr, sflc_sk_Context * ctx) +mempool_t * sfold_sk_createReqPool(int min_nr, sfold_sk_Context * ctx) { - return mempool_create(min_nr, sflc_sk_allocRequest, sflc_sk_freeRequest, (void *) ctx); + return mempool_create(min_nr, sfold_sk_allocRequest, sfold_sk_freeRequest, (void *) ctx); } /***************************************************** @@ -55,9 +55,9 @@ mempool_t * sflc_sk_createReqPool(int min_nr, sflc_sk_Context * ctx) *****************************************************/ /* A mempool_alloc_t using skcipher_request_alloc as backend */ -static void * sflc_sk_allocRequest(gfp_t gfp_mask, void * pool_data) +static void * sfold_sk_allocRequest(gfp_t gfp_mask, void * pool_data) { - sflc_sk_Context * ctx = pool_data; + sfold_sk_Context * ctx = pool_data; struct skcipher_request * skreq; skreq = skcipher_request_alloc(ctx->tfm, gfp_mask); @@ -70,7 +70,7 @@ static void * sflc_sk_allocRequest(gfp_t gfp_mask, void * pool_data) } /* A mempool_free_t using skcipher_request_free as backend */ -static void sflc_sk_freeRequest(void * element, void * pool_data) +static void sfold_sk_freeRequest(void * element, void * pool_data) { struct skcipher_request * skreq = element; diff --git a/dm-sflc/crypto/symkey/skreq_pool.h b/dm-sflc/src/old/crypto/symkey/skreq_pool.h similarity index 89% rename from dm-sflc/crypto/symkey/skreq_pool.h rename to dm-sflc/src/old/crypto/symkey/skreq_pool.h index cb57f53..5c5ebba 100644 --- a/dm-sflc/crypto/symkey/skreq_pool.h +++ b/dm-sflc/src/old/crypto/symkey/skreq_pool.h @@ -26,8 +26,8 @@ * functions to the mempool interface. */ -#ifndef _SFLC_CRYPTO_SYMKEY_SKREQ_POOL_H_ -#define _SFLC_CRYPTO_SYMKEY_SKREQ_POOL_H_ +#ifndef _SFOLD_CRYPTO_SYMKEY_SKREQ_POOL_H_ +#define _SFOLD_CRYPTO_SYMKEY_SKREQ_POOL_H_ /***************************************************** * INCLUDE SECTION * @@ -35,7 +35,7 @@ #include -#include "symkey.h" +#include "old/crypto/symkey/symkey.h" /***************************************************** * CONSTANTS * @@ -49,7 +49,7 @@ * PUBLIC FUNCTIONS PROTOTYPES * *****************************************************/ -mempool_t * sflc_sk_createReqPool(int min_nr, sflc_sk_Context * ctx); +mempool_t * sfold_sk_createReqPool(int min_nr, sfold_sk_Context * ctx); -#endif /* _SFLC_CRYPTO_SYMKEY_SKREQ_POOL_H_ */ +#endif /* _SFOLD_CRYPTO_SYMKEY_SKREQ_POOL_H_ */ diff --git a/dm-sflc/crypto/symkey/symkey.c b/dm-sflc/src/old/crypto/symkey/symkey.c similarity index 75% rename from dm-sflc/crypto/symkey/symkey.c rename to dm-sflc/src/old/crypto/symkey/symkey.c index 2a78085..668e1ec 100644 --- a/dm-sflc/crypto/symkey/symkey.c +++ b/dm-sflc/src/old/crypto/symkey/symkey.c @@ -27,66 +27,66 @@ #include -#include "symkey.h" -#include "skreq_pool.h" -#include "log/log.h" +#include "old/crypto/symkey/symkey.h" +#include "old/crypto/symkey/skreq_pool.h" +#include "old/log/log.h" /***************************************************** * CONSTANTS * *****************************************************/ -#define SFLC_SK_REQ_POOL_SIZE 1024 +#define SFOLD_SK_REQ_POOL_SIZE 1024 -#define SFLC_SK_ENCRYPT 0 -#define SFLC_SK_DECRYPT 1 +#define SFOLD_SK_ENCRYPT 0 +#define SFOLD_SK_DECRYPT 1 /***************************************************** * PRIVATE FUNCTIONS PROTOTYPES * *****************************************************/ -static int sflc_sk_encdec(sflc_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv, int op); +static int sfold_sk_encdec(sfold_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv, int op); /***************************************************** * PUBLIC FUNCTIONS DEFINITIONS * *****************************************************/ /* Create a new context with the given key. Returns an ERR_PTR() on failure. */ -sflc_sk_Context * sflc_sk_createContext(u8 * key) +sfold_sk_Context * sfold_sk_createContext(u8 * key) { - sflc_sk_Context * ctx; + sfold_sk_Context * ctx; int err; /* Allocate context */ - ctx = kzalloc(sizeof(sflc_sk_Context), GFP_KERNEL); + ctx = kzalloc(sizeof(sfold_sk_Context), GFP_KERNEL); if (!ctx) { - pr_err("Could not allocate %lu bytes for the sflc_sk_Context\n", sizeof(sflc_sk_Context)); + pr_err("Could not allocate %lu bytes for the sfold_sk_Context\n", sizeof(sfold_sk_Context)); return ERR_PTR(-ENOMEM); } /* Allocate crypto transform */ - ctx->tfm = crypto_alloc_skcipher(SFLC_SK_CIPHER_NAME, CRYPTO_ALG_ASYNC, 0); + ctx->tfm = crypto_alloc_skcipher(SFOLD_SK_CIPHER_NAME, CRYPTO_ALG_ASYNC, 0); if (IS_ERR(ctx->tfm)) { err = PTR_ERR(ctx->tfm); ctx->tfm = NULL; pr_err("Could not allocate skcipher handle: error %d\n", err); - sflc_sk_destroyContext(ctx); + sfold_sk_destroyContext(ctx); return ERR_PTR(err); } /* Copy and set key */ - memcpy(ctx->key, key, SFLC_SK_KEY_LEN); - err = crypto_skcipher_setkey(ctx->tfm, ctx->key, SFLC_SK_KEY_LEN); + memcpy(ctx->key, key, SFOLD_SK_KEY_LEN); + err = crypto_skcipher_setkey(ctx->tfm, ctx->key, SFOLD_SK_KEY_LEN); if (err) { pr_err("Could not set key in crypto transform: error %d\n", err); - sflc_sk_destroyContext(ctx); + sfold_sk_destroyContext(ctx); return ERR_PTR(err); } /* Create request memory pool */ - ctx->sk_req_pool = sflc_sk_createReqPool(SFLC_SK_REQ_POOL_SIZE, ctx); + ctx->sk_req_pool = sfold_sk_createReqPool(SFOLD_SK_REQ_POOL_SIZE, ctx); if (!ctx->sk_req_pool) { pr_err("Could not allocate skcipher_request memory pool\n"); - sflc_sk_destroyContext(ctx); + sfold_sk_destroyContext(ctx); return ERR_PTR(-ENOMEM); } @@ -94,7 +94,7 @@ sflc_sk_Context * sflc_sk_createContext(u8 * key) } /* Destroy the given context */ -void sflc_sk_destroyContext(sflc_sk_Context * ctx) +void sfold_sk_destroyContext(sfold_sk_Context * ctx) { if (!ctx) { return; @@ -116,21 +116,21 @@ void sflc_sk_destroyContext(sflc_sk_Context * ctx) } /* Encrypt synchronously. Provide src = dst for in-place operation. */ -int sflc_sk_encrypt(sflc_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv) +int sfold_sk_encrypt(sfold_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv) { - return sflc_sk_encdec(ctx, src, dst, len, iv, SFLC_SK_ENCRYPT); + return sfold_sk_encdec(ctx, src, dst, len, iv, SFOLD_SK_ENCRYPT); } -int sflc_sk_decrypt(sflc_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv) +int sfold_sk_decrypt(sfold_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv) { - return sflc_sk_encdec(ctx, src, dst, len, iv, SFLC_SK_DECRYPT); + return sfold_sk_encdec(ctx, src, dst, len, iv, SFOLD_SK_DECRYPT); } /***************************************************** * PRIVATE FUNCTIONS DEFINITIONS * *****************************************************/ -static int sflc_sk_encdec(sflc_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv, int op) +static int sfold_sk_encdec(sfold_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv, int op) { struct skcipher_request * skreq; struct scatterlist srcsg; @@ -162,7 +162,7 @@ static int sflc_sk_encdec(sflc_sk_Context * ctx, u8 * src, u8 * dst, unsigned in crypto_req_done, &skreq_wait); /* Do it */ - if (op == SFLC_SK_ENCRYPT) { + if (op == SFOLD_SK_ENCRYPT) { ret = crypto_skcipher_encrypt(skreq); } else { ret = crypto_skcipher_decrypt(skreq); diff --git a/dm-sflc/crypto/symkey/symkey.h b/dm-sflc/src/old/crypto/symkey/symkey.h similarity index 78% rename from dm-sflc/crypto/symkey/symkey.h rename to dm-sflc/src/old/crypto/symkey/symkey.h index 1b6d40b..3f4d440 100644 --- a/dm-sflc/crypto/symkey/symkey.h +++ b/dm-sflc/src/old/crypto/symkey/symkey.h @@ -25,8 +25,8 @@ * A thin wrapper around the kernel's synchronous block cipher API. */ -#ifndef _SFLC_CRYPTO_SYMKEY_SYMKEY_H_ -#define _SFLC_CRYPTO_SYMKEY_SYMKEY_H_ +#ifndef _SFOLD_CRYPTO_SYMKEY_SYMKEY_H_ +#define _SFOLD_CRYPTO_SYMKEY_SYMKEY_H_ /***************************************************** * INCLUDE SECTION * @@ -39,9 +39,9 @@ * CONSTANTS * *****************************************************/ -#define SFLC_SK_CIPHER_NAME "ctr(aes)" -#define SFLC_SK_KEY_LEN 32 -#define SFLC_SK_IV_LEN 16 +#define SFOLD_SK_CIPHER_NAME "ctr(aes)" +#define SFOLD_SK_KEY_LEN 32 +#define SFOLD_SK_IV_LEN 16 /***************************************************** * TYPES * @@ -51,34 +51,31 @@ * There is one of these Context's for each volume. * No need for locking, methods can be called in parallel. */ -typedef struct sflc_sk_context_s +typedef struct sfold_sk_context_s { /* Only one transform for now */ struct crypto_skcipher * tfm; /* 32-byte key */ - u8 key[SFLC_SK_KEY_LEN]; + u8 key[SFOLD_SK_KEY_LEN]; /* Memory pool for skcipher_request's */ mempool_t * sk_req_pool; -} sflc_sk_Context; +} sfold_sk_Context; /***************************************************** * PUBLIC FUNCTIONS PROTOTYPES * *****************************************************/ -/* Self test using known test vectors and random inputs */ -int sflc_sk_selftest(void); - /* Create a new context with the given key. Returns an ERR_PTR() on failure. */ -sflc_sk_Context * sflc_sk_createContext(u8 * key); +sfold_sk_Context * sfold_sk_createContext(u8 * key); /* Destroy the given context */ -void sflc_sk_destroyContext(sflc_sk_Context * ctx); +void sfold_sk_destroyContext(sfold_sk_Context * ctx); /* Encrypt/decrypt synchronously. Provide src = dst for in-place operation. */ -int sflc_sk_encrypt(sflc_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv); -int sflc_sk_decrypt(sflc_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv); +int sfold_sk_encrypt(sfold_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv); +int sfold_sk_decrypt(sfold_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv); -#endif /* _SFLC_CRYPTO_SYMKEY_SYMKEY_H_ */ +#endif /* _SFOLD_CRYPTO_SYMKEY_SYMKEY_H_ */ diff --git a/dm-sflc/src/old/device/device.c b/dm-sflc/src/old/device/device.c new file mode 100644 index 0000000..b5045c1 --- /dev/null +++ b/dm-sflc/src/old/device/device.c @@ -0,0 +1,259 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +/* + * This file only implements the device-related device management functions. + */ + +/***************************************************** + * INCLUDE SECTION * + *****************************************************/ + +#include "old/sflc_old.h" +#include "old/device/device.h" +#include "old/utils/vector.h" +#include "old/log/log.h" + +#include + +/***************************************************** + * CONSTANTS * + *****************************************************/ + +/***************************************************** + * PUBLIC VARIABLES DEFINITIONS * + *****************************************************/ + + +/* Initialises and pre-shuffles the PSI array */ +static int sfold_dev_initAndShufflePsiArray(u32 *psi_array, u32 len); + + +/***************************************************** + * PUBLIC FUNCTIONS DEFINITIONS * + *****************************************************/ + +/** + * Creates Device. Returns an ERR_PTR() if unsuccessful. + * Arguments: + * argv[0]: Shufflecake mode: legacy/lite + * argv[1]: Shufflecake-unique device ID + * argv[2]: path to underlying physical device + * argv[3]: volume index within the device + * argv[4]: number of 1 MB slices in the underlying device + * argv[5]: 32-byte encryption key (hex-encoded) + */ +sfold_Device *sfold_dev_create(struct dm_target *ti, int argc, char **argv, struct kobject *kobj) +{ + sfold_Device * dev; + u32 tot_slices; + u32 dev_id; + int err; + int i; + + /* Allocate device */ + dev = kzalloc(sizeof(sfold_Device), GFP_KERNEL); + if (!dev) { + pr_err("Could not allocate %lu bytes for sfold_Device\n", sizeof(sfold_Device)); + err = -ENOMEM; + goto err_alloc_dev; + } + + /* Parse args */ + if (argc != 6) { + pr_err("Wrong argument count"); + err = -EINVAL; + goto err_parse; + } + sscanf(argv[1], "%u", &dev_id); + if (sscanf(argv[4], "%u", &tot_slices) != 1) { + pr_err("Could not decode tot_slices\n"); + err = -EINVAL; + goto err_parse; + } + + /* Init list node here, so it's always safe to list_del() */ + INIT_LIST_HEAD(&dev->list_node); + + /* Set device ID */ + dev->dev_id = dev_id; + + /* Set backing real device */ + err = dm_get_device(ti, argv[2], dm_table_get_mode(ti->table), &dev->bdev); + if (err) { + pr_err("Could not dm_get_device: error %d\n", err); + goto err_dm_get_dev; + } + dev->ti = ti; + /* And its path */ + dev->bdev_path = kmalloc(strlen(argv[2]) + 1, GFP_KERNEL); + if (!dev->bdev_path) { + pr_err("Could not allocate %lu bytes for dev->real_dev_path\n", strlen(argv[2]) + 1); + err = -ENOMEM; + goto err_alloc_real_dev_path; + } + strcpy(dev->bdev_path, argv[2]); + + /* Init volumes */ + for (i = 0; i < SFOLD_DEV_MAX_VOLUMES; ++i) { + dev->vol[i] = NULL; + } + dev->vol_cnt = 0; + + /* Set slices info */ + dev->tot_slices = tot_slices; + dev->free_slices = tot_slices; + /* Compute header info (like in userland tool) */ + u32 nr_pmbs_per_vol = DIV_ROUND_UP(tot_slices, SFOLD_VOL_HEADER_MAPPINGS_PER_BLOCK); + dev->vol_header_nr_iv_blocks = DIV_ROUND_UP(nr_pmbs_per_vol, SFOLD_VOL_LOG_SLICE_SIZE); + dev->vol_header_size = 1 + nr_pmbs_per_vol + dev->vol_header_nr_iv_blocks; + dev->dev_header_size = 1 + (SFOLD_DEV_MAX_VOLUMES * dev->vol_header_size); + + /* Init slices lock */ + mutex_init(&dev->slices_lock); + /* Allocate reverse slice map */ + dev->rmap = vmalloc(dev->tot_slices * sizeof(u8)); + if (!dev->rmap) { + pr_err("Could not allocate reverse slice map\n"); + err = -ENOMEM; + goto err_alloc_rmap; + } + /* Initialise it */ + memset(dev->rmap, SFOLD_DEV_RMAP_INVALID_VOL, dev->tot_slices * sizeof(u8)); + /* Allocate PSI array */ + dev->shuffled_psi_array = vmalloc(dev->tot_slices * sizeof(u32)); + if (!dev->shuffled_psi_array) { + pr_err("Could not allocate PSI array\n"); + err = -ENOMEM; + goto err_alloc_psi_array; + } + /* Initialise it and pre-shuffle it */ + err = sfold_dev_initAndShufflePsiArray(dev->shuffled_psi_array, dev->tot_slices); + if (err) { + pr_err("Could not init-and-shuffle PSI array: error %d", err); + goto err_initshuffle_psi_array; + } + /* Init related counter */ + dev->shuffled_psi_ctr = 0; + + /* Init IV cache lock */ + mutex_init(&dev->iv_cache_lock); + /* Init IV cache waitqueue */ + init_waitqueue_head(&dev->iv_cache_waitqueue); + /* Allocate IV cache */ + dev->iv_cache = kzalloc(dev->tot_slices * sizeof(sfold_dev_IvCacheEntry *), GFP_KERNEL); + if (!dev->iv_cache) { + pr_err("Could not allocate IV cache\n"); + err = -ENOMEM; + goto err_alloc_iv_cache; + } + /* Set it empty */ + dev->iv_cache_nr_entries = 0; + /* Init list head */ + INIT_LIST_HEAD(&dev->iv_lru_list); + + /* Add to sysfs */ + dev->kobj_parent = kobj; + err = sfold_sysfs_add_device(dev); + if (err) { + pr_err("Could not add device to sysfs; error %d\n", err); + goto err_sysfs; + } + + return dev; + + +err_sysfs: + kfree(dev->iv_cache); +err_alloc_iv_cache: +err_initshuffle_psi_array: + vfree(dev->shuffled_psi_array); +err_alloc_psi_array: + vfree(dev->rmap); +err_alloc_rmap: + kfree(dev->bdev_path); +err_alloc_real_dev_path: + dm_put_device(ti, dev->bdev); +err_dm_get_dev: +err_parse: + kfree(dev); +err_alloc_dev: + return ERR_PTR(err); +} + + +/* Returns false if still busy (not all volumes have been removed). Frees the Device. */ +bool sfold_dev_destroy(sfold_Device * dev) +{ + /* Check if we actually have to put this device */ + if (!dev) { + return false; + } + if (dev->vol_cnt > 0) { + pr_warn("Called while still holding %d volumes\n", dev->vol_cnt); + return false; + } + + /* Flush all IVs */ + sfold_dev_flushIvs(dev); + + /* List */ + list_del(&dev->list_node); + + /* Sysfs */ + sfold_sysfs_remove_device(dev); + + /* IV cache */ + kfree(dev->iv_cache); + + /* PSI array */ + vfree(dev->shuffled_psi_array); + + /* Reverse slice map */ + vfree(dev->rmap); + + /* Backing device */ + dm_put_device(dev->ti, dev->bdev); + kfree(dev->bdev_path); + + /* Free the device itself */ + kfree(dev); + + return true; +} + + +/* Initialises and pre-shuffles the PSI array */ +static int sfold_dev_initAndShufflePsiArray(u32 *psi_array, u32 len) +{ + u32 i; + + /* Init to the identity map */ + for (i = 0; i < len; i++) { + psi_array[i] = i; + } + + /* Permute */ + return sfold_vec_u32shuffle(psi_array, len); +} + diff --git a/dm-sflc/device/device.h b/dm-sflc/src/old/device/device.h similarity index 65% rename from dm-sflc/device/device.h rename to dm-sflc/src/old/device/device.h index 68ef3dc..f893772 100644 --- a/dm-sflc/device/device.h +++ b/dm-sflc/src/old/device/device.h @@ -30,8 +30,8 @@ * are stored in increasing degree of "secrecy"). */ -#ifndef _SFLC_DEVICE_DEVICE_H_ -#define _SFLC_DEVICE_DEVICE_H_ +#ifndef _SFOLD_DEVICE_DEVICE_H_ +#define _SFOLD_DEVICE_DEVICE_H_ /***************************************************** @@ -40,8 +40,8 @@ /* Necessary since device.h, volume.h, and sysfs.h all include each other */ -typedef struct sflc_device_s sflc_Device; -typedef struct sflc_dev_iv_cache_entry_s sflc_dev_IvCacheEntry; +typedef struct sfold_device_s sfold_Device; +typedef struct sfold_dev_iv_cache_entry_s sfold_dev_IvCacheEntry; /***************************************************** @@ -49,11 +49,10 @@ typedef struct sflc_dev_iv_cache_entry_s sflc_dev_IvCacheEntry; *****************************************************/ #include -#include -#include "volume/volume.h" -#include "crypto/symkey/symkey.h" -#include "sysfs/sysfs.h" +#include "old/sflc_old.h" +#include "old/volume/volume.h" +#include "old/crypto/symkey/symkey.h" /***************************************************** @@ -61,30 +60,30 @@ typedef struct sflc_dev_iv_cache_entry_s sflc_dev_IvCacheEntry; *****************************************************/ /* We need 4096-byte sectors to amortise the space overhead of the IVs */ -#define SFLC_DEV_SECTOR_SIZE 4096 +#define SFOLD_DEV_SECTOR_SIZE 4096 /* A SFLC sector encompasses 8 kernel sectors */ -#define SFLC_DEV_SECTOR_SCALE (SFLC_DEV_SECTOR_SIZE / SECTOR_SIZE) +#define SFOLD_DEV_SECTOR_SCALE (SFOLD_DEV_SECTOR_SIZE / SECTOR_SIZE) /* An IV block holds IVs for 256 data blocks */ -#define SFLC_DEV_SECTOR_TO_IV_RATIO (SFLC_DEV_SECTOR_SIZE / SFLC_SK_IV_LEN) +#define SFOLD_DEV_SECTOR_TO_IV_RATIO (SFOLD_DEV_SECTOR_SIZE / SFOLD_SK_IV_LEN) /* Max number of volumes linked to a single device */ -#define SFLC_DEV_MAX_VOLUMES 15 +#define SFOLD_DEV_MAX_VOLUMES 15 /* A physical slice contains the 256 encrypted data blocks and the IV block */ -#define SFLC_DEV_PHYS_SLICE_SIZE (SFLC_VOL_LOG_SLICE_SIZE + (SFLC_VOL_LOG_SLICE_SIZE / SFLC_DEV_SECTOR_TO_IV_RATIO)) +#define SFOLD_DEV_PHYS_SLICE_SIZE (SFOLD_VOL_LOG_SLICE_SIZE + (SFOLD_VOL_LOG_SLICE_SIZE / SFOLD_DEV_SECTOR_TO_IV_RATIO)) /* Value marking a PSI as unassigned */ -#define SFLC_DEV_RMAP_INVALID_VOL 0xFFU +#define SFOLD_DEV_RMAP_INVALID_VOL 0xFFU /* Maximum number of open devices in total across shufflecake */ -#define SFLC_DEV_MAX_DEVICES_TOT 1024 +#define SFOLD_DEV_MAX_DEVICES_TOT 1024 /***************************************************** * TYPES * *****************************************************/ -struct sflc_dev_iv_cache_entry_s +struct sfold_dev_iv_cache_entry_s { /* The PSI it refers to */ u32 psi; @@ -100,23 +99,25 @@ struct sflc_dev_iv_cache_entry_s struct list_head lru_node; }; -struct sflc_device_s +struct sfold_device_s { /* Underlying block device */ struct dm_dev * bdev; char * bdev_path; + /* Target instance that owns the bdev reference */ + struct dm_target *ti; /* Shufflecake-unique numeric ID of this device */ - size_t dev_id; + u32 dev_id; /* All volumes linked to this device */ - sflc_Volume * vol[SFLC_DEV_MAX_VOLUMES]; + sfold_Volume * vol[SFOLD_DEV_MAX_VOLUMES]; int vol_cnt; /* Reverse slice map, associating PSIs to volume indices */ u8 * rmap; /* Shuffled array of PSIs, with advancement counter */ - u32 *prmslices; - u32 prmslices_octr; + u32 *shuffled_psi_array; + u32 shuffled_psi_ctr; /* Lock for all three of these objects */ struct mutex slices_lock; @@ -129,98 +130,57 @@ struct sflc_device_s u32 vol_header_size; u32 dev_header_size; + /* Parent sysfs directory */ + struct kobject *kobj_parent; + /* LRU cache of IV blocks */ struct mutex iv_cache_lock; wait_queue_head_t iv_cache_waitqueue; - sflc_dev_IvCacheEntry ** iv_cache; + sfold_dev_IvCacheEntry ** iv_cache; u32 iv_cache_nr_entries; struct list_head iv_lru_list; - /* Sysfs stuff */ - sflc_sysfs_Device * kobj; - - /* DM-io */ - struct dm_io_client *dmio_client; - /* We keep all devices in a list */ struct list_head list_node; }; -/***************************************************** - * MACROS * - *****************************************************/ - -#define sflc_dev_psiToIvBlock(dev, psi) (dev->dev_header_size + (sector_t)(psi) * SFLC_DEV_PHYS_SLICE_SIZE) - - -/***************************************************** - * PUBLIC VARIABLES DECLARATIONS * - *****************************************************/ - -/* The next available device ID */ -extern size_t sflc_dev_nextId; - -/* List of all devices */ -extern struct list_head sflc_dev_list; -/* Big, coarse-grained lock for all modifying operations on any device or the device list */ -extern struct semaphore sflc_dev_mutex; - - /***************************************************** * PUBLIC FUNCTIONS PROTOTYPES * *****************************************************/ - -/* Inits global variables */ -int sflc_dev_init(void); -/* Tears down global variables */ -void sflc_dev_exit(void); - /* * None of these functions acquire the big device lock: it must be held * by the caller. */ /* Creates Device and adds it to the list. Returns an ERR_PTR() if unsuccessful. */ -sflc_Device * sflc_dev_create(struct dm_target * ti, char * real_dev_path, u32 tot_slices); - -/* Returns NULL if not found */ -sflc_Device * sflc_dev_lookupByPath(char * real_dev_path); +sfold_Device * sfold_dev_create(struct dm_target *ti, int argc, char **argv, struct kobject *kobj); /* Returns false if still busy (not all volumes have been removed) Frees the Device. */ -bool sflc_dev_destroy(struct dm_target * ti, sflc_Device * dev); +bool sfold_dev_destroy(sfold_Device * dev); /* Returns false if volume index was already occupied. */ -bool sflc_dev_addVolume(sflc_Device * dev, sflc_Volume * vol, int vol_idx); - -/* Looks at all volumes in all devices. Returns NULL if not found */ -sflc_Volume * sflc_dev_lookupVolumeByName(char * vol_name); +bool sfold_dev_addVolume(sfold_Device * dev, sfold_Volume * vol, int vol_idx); /* Does not put the volume. Returns false if was already NULL. */ -bool sflc_dev_removeVolume(sflc_Device * dev, int vol_idx); +bool sfold_dev_removeVolume(sfold_Device * dev, int vol_idx); /* Synchronously reads/writes one 4096-byte sector from/to the underlying device to/from the provided page */ -int sflc_dev_rwSector(sflc_Device * dev, struct page * page, sector_t sector, int rw); - -/* Synchronously read/write entire PSI (257 blocks) to/from VMA */ -int sflc_dev_rwPsi(sflc_Device *dev, void *vma, u32 psi, int rw); +int sfold_dev_rwSector(sfold_Device * dev, struct page * page, sector_t sector, int rw); /* The caller needs to hold slices_lock to call these functions */ -/* Checks if PSI is free */ -bool sflc_dev_isPsiFree(sflc_Device *dev, u32 psi); - /* Sets the PSI as owned by the given volume (also decreases free_slices). * Returns < 0 if already taken. */ -int sflc_dev_markPsiTaken(sflc_Device * dev, u32 psi, u8 vol_idx); +int sfold_dev_markPsiTaken(sfold_Device * dev, u32 psi, u8 vol_idx); /* Returns a random free physical slice, or < 0 if error */ -s32 sflc_dev_getNextRandomFreePsi(sflc_Device * dev); +s32 sfold_dev_getNextRandomFreePsi(sfold_Device * dev); /* These functions provide concurrent-safe access to the entries of the IV cache. @@ -231,13 +191,13 @@ s32 sflc_dev_getNextRandomFreePsi(sflc_Device * dev); When the refcount reaches 0, the IV block is flushed. */ /* Get a pointer to the specified IV block. Increases the refcount and possibly the dirtyness (if WRITE). */ -u8 * sflc_dev_getIvBlockRef(sflc_Device * dev, u32 psi, int rw); +u8 * sfold_dev_getIvBlockRef(sfold_Device * dev, u32 psi, int rw); /* Signal end of usage of an IV block. Decreases the refcount. */ -int sflc_dev_putIvBlockRef(sflc_Device * dev, u32 psi); +int sfold_dev_putIvBlockRef(sfold_Device * dev, u32 psi); /* Flush all dirty IV blocks */ -void sflc_dev_flushIvs(sflc_Device * dev); +void sfold_dev_flushIvs(sfold_Device * dev); -#endif /* _SFLC_DEVICE_DEVICE_H_ */ +#endif /* _SFOLD_DEVICE_DEVICE_H_ */ diff --git a/dm-sflc/device/iv.c b/dm-sflc/src/old/device/iv.c similarity index 81% rename from dm-sflc/device/iv.c rename to dm-sflc/src/old/device/iv.c index 48acdfa..c2c0fb1 100644 --- a/dm-sflc/device/iv.c +++ b/dm-sflc/src/old/device/iv.c @@ -25,24 +25,30 @@ * INCLUDE SECTION * *****************************************************/ -#include "device.h" -#include "utils/pools.h" -#include "log/log.h" + +#include "old/device/device.h" +#include "old/utils/pools.h" +#include "old/log/log.h" /***************************************************** * CONSTANTS * *****************************************************/ /* Capacity of IV cache */ -#define SFLC_DEV_IV_CACHE_CAPACITY 1024 +#define SFOLD_DEV_IV_CACHE_CAPACITY 1024 +/***************************************************** + * MACROS * + *****************************************************/ + +#define sfold_dev_psiToIvBlockSector(dev, psi) (dev->dev_header_size + (sector_t)(psi) * SFOLD_DEV_PHYS_SLICE_SIZE) /***************************************************** * PRIVATE FUNCTIONS PROTOTYPES * *****************************************************/ -static sflc_dev_IvCacheEntry * sflc_dev_newIvCacheEntry(sflc_Device * dev, u32 psi); -static int sflc_dev_destroyIvCacheEntry(sflc_Device * dev, sflc_dev_IvCacheEntry * entry); +static sfold_dev_IvCacheEntry * sfold_dev_newIvCacheEntry(sfold_Device * dev, u32 psi); +static int sfold_dev_destroyIvCacheEntry(sfold_Device * dev, sfold_dev_IvCacheEntry * entry); /***************************************************** * PUBLIC FUNCTIONS DEFINITIONS * @@ -50,9 +56,9 @@ static int sflc_dev_destroyIvCacheEntry(sflc_Device * dev, sflc_dev_IvCacheEntry /* Get a read/write pointer to the specified IV block. Increases the refcount. Returns an ERR_PTR() if error. */ -u8 * sflc_dev_getIvBlockRef(sflc_Device * dev, u32 psi, int rw) +u8 * sfold_dev_getIvBlockRef(sfold_Device * dev, u32 psi, int rw) { - sflc_dev_IvCacheEntry * entry; + sfold_dev_IvCacheEntry * entry; int err; /* Lock + waitqueue pattern */ @@ -65,13 +71,13 @@ u8 * sflc_dev_getIvBlockRef(sflc_Device * dev, u32 psi, int rw) } /* Check for either of two conditions in order to go through */ - while (dev->iv_cache[psi] == NULL && dev->iv_cache_nr_entries >= SFLC_DEV_IV_CACHE_CAPACITY) { + while (dev->iv_cache[psi] == NULL && dev->iv_cache_nr_entries >= SFOLD_DEV_IV_CACHE_CAPACITY) { /* We can't go through, yield the lock */ mutex_unlock(&dev->iv_cache_lock); /* Sleep in the waitqueue (same conditions) */ if (wait_event_interruptible(dev->iv_cache_waitqueue, dev->iv_cache[psi] != NULL || - dev->iv_cache_nr_entries < SFLC_DEV_IV_CACHE_CAPACITY)) { + dev->iv_cache_nr_entries < SFOLD_DEV_IV_CACHE_CAPACITY)) { err = -EINTR; pr_err("Interrupted while waiting in waitqueue\n"); goto err_wait_queue; @@ -93,7 +99,7 @@ u8 * sflc_dev_getIvBlockRef(sflc_Device * dev, u32 psi, int rw) entry = dev->iv_cache[psi]; if (!entry) { /* Create it */ - entry = sflc_dev_newIvCacheEntry(dev, psi); + entry = sfold_dev_newIvCacheEntry(dev, psi); if (IS_ERR(entry)) { err = PTR_ERR(entry); pr_err("Could not create new cache entry; error %d\n", err); @@ -133,9 +139,9 @@ err_lock_cache: } /* Signal end of usage of an IV block. Decreases the refcount. */ -int sflc_dev_putIvBlockRef(sflc_Device * dev, u32 psi) +int sfold_dev_putIvBlockRef(sfold_Device * dev, u32 psi) { - sflc_dev_IvCacheEntry * entry; + sfold_dev_IvCacheEntry * entry; int err; /* No condition needed besides mutual exclusion: just grab the lock (no waitqueue) */ @@ -156,12 +162,12 @@ int sflc_dev_putIvBlockRef(sflc_Device * dev, u32 psi) list_add(&entry->lru_node, &dev->iv_lru_list); /* If cache is not full, we can return now */ - if (dev->iv_cache_nr_entries < SFLC_DEV_IV_CACHE_CAPACITY) { + if (dev->iv_cache_nr_entries < SFOLD_DEV_IV_CACHE_CAPACITY) { goto out; } /* Otherwise, let's look for the least recent unreffed entry, and evict it */ - sflc_dev_IvCacheEntry * evicted; + sfold_dev_IvCacheEntry * evicted; bool found = false; list_for_each_entry_reverse(evicted, &dev->iv_lru_list, lru_node) { if (evicted->refcnt == 0) { @@ -182,7 +188,7 @@ int sflc_dev_putIvBlockRef(sflc_Device * dev, u32 psi) /* Pull it out of the LRU list */ __list_del_entry(&evicted->lru_node); /* Destroy it (free and flush to disk) */ - err = sflc_dev_destroyIvCacheEntry(dev, evicted); + err = sfold_dev_destroyIvCacheEntry(dev, evicted); if (err) { pr_err("Could not evict cache entry for PSI %u; error %d\n", evicted->psi, err); goto err_destroy_entry; @@ -210,9 +216,9 @@ err_lock_cache: } /* Flush all dirty IV blocks */ -void sflc_dev_flushIvs(sflc_Device * dev) +void sfold_dev_flushIvs(sfold_Device * dev) { - sflc_dev_IvCacheEntry * entry, * _next; + sfold_dev_IvCacheEntry * entry, * _next; int err; /* Iterate over all entries */ @@ -221,7 +227,7 @@ void sflc_dev_flushIvs(sflc_Device * dev) __list_del_entry(&entry->lru_node); /* Destroy it */ - err = sflc_dev_destroyIvCacheEntry(dev, entry); + err = sfold_dev_destroyIvCacheEntry(dev, entry); if (err) { pr_err("Could not destroy IV cache entry for PSI %u; error %d\n", entry->psi, err); } @@ -232,16 +238,16 @@ void sflc_dev_flushIvs(sflc_Device * dev) * PRIVATE FUNCTIONS PROTOTYPES * *****************************************************/ -static sflc_dev_IvCacheEntry * sflc_dev_newIvCacheEntry(sflc_Device * dev, u32 psi) +static sfold_dev_IvCacheEntry * sfold_dev_newIvCacheEntry(sfold_Device * dev, u32 psi) { - sflc_dev_IvCacheEntry * entry; + sfold_dev_IvCacheEntry * entry; int err; sector_t sector; /* Allocate and init structure */ /* Allocate structure */ - entry = kmem_cache_alloc(sflc_pools_ivSlab, GFP_NOIO); + entry = kmem_cache_alloc(sfold_pools_ivSlab, GFP_NOIO); if (!entry) { pr_err("Could not allocate IvCacheEntry structure\n"); err = -ENOMEM; @@ -251,7 +257,7 @@ static sflc_dev_IvCacheEntry * sflc_dev_newIvCacheEntry(sflc_Device * dev, u32 p /* Set PSI */ entry->psi = psi; /* Allocate page */ - entry->iv_page = mempool_alloc(sflc_pools_pagePool, GFP_NOIO); + entry->iv_page = mempool_alloc(sfold_pools_pagePool, GFP_NOIO); if (!entry->iv_page) { pr_err("Could not allocate IV page\n"); err = -ENOMEM; @@ -271,10 +277,10 @@ static sflc_dev_IvCacheEntry * sflc_dev_newIvCacheEntry(sflc_Device * dev, u32 p /* Read from disk */ /* Position on disk */ - sector = sflc_dev_psiToIvBlock(dev, psi); + sector = sfold_dev_psiToIvBlockSector(dev, psi); /* Read */ - err = sflc_dev_rwSector(dev, entry->iv_page, sector, READ); + err = sfold_dev_rwSector(dev, entry->iv_page, sector, READ); if (err) { pr_err("Could not read IV block from disk; error %d\n", err); goto err_read; @@ -285,14 +291,14 @@ static sflc_dev_IvCacheEntry * sflc_dev_newIvCacheEntry(sflc_Device * dev, u32 p err_read: kunmap(entry->iv_page); - mempool_free(entry->iv_page, sflc_pools_pagePool); + mempool_free(entry->iv_page, sfold_pools_pagePool); err_alloc_page: - kmem_cache_free(sflc_pools_ivSlab, entry); + kmem_cache_free(sfold_pools_ivSlab, entry); err_alloc_entry: return ERR_PTR(err); } -static int sflc_dev_destroyIvCacheEntry(sflc_Device * dev, sflc_dev_IvCacheEntry * entry) +static int sfold_dev_destroyIvCacheEntry(sfold_Device * dev, sfold_dev_IvCacheEntry * entry) { int err; sector_t sector; @@ -300,11 +306,11 @@ static int sflc_dev_destroyIvCacheEntry(sflc_Device * dev, sflc_dev_IvCacheEntry /* Write to disk */ /* Position on disk */ - sector = sflc_dev_psiToIvBlock(dev, entry->psi); + sector = sfold_dev_psiToIvBlockSector(dev, entry->psi); /* Write (if necessary) */ if (entry->dirtyness) { - err = sflc_dev_rwSector(dev, entry->iv_page, sector, WRITE); + err = sfold_dev_rwSector(dev, entry->iv_page, sector, WRITE); if (err) { pr_err("Could not write IV block to disk; error %d\n", err); return err; @@ -317,10 +323,10 @@ static int sflc_dev_destroyIvCacheEntry(sflc_Device * dev, sflc_dev_IvCacheEntry /* Kunmap page */ kunmap(entry->iv_page); /* Free it */ - mempool_free(entry->iv_page, sflc_pools_pagePool); + mempool_free(entry->iv_page, sfold_pools_pagePool); /* Free structure */ - kmem_cache_free(sflc_pools_ivSlab, entry); + kmem_cache_free(sfold_pools_ivSlab, entry); return 0; } diff --git a/dm-sflc/device/rawio.c b/dm-sflc/src/old/device/rawio.c similarity index 75% rename from dm-sflc/device/rawio.c rename to dm-sflc/src/old/device/rawio.c index 3c4ee0e..ec70147 100644 --- a/dm-sflc/device/rawio.c +++ b/dm-sflc/src/old/device/rawio.c @@ -25,14 +25,12 @@ * INCLUDE SECTION * *****************************************************/ -#include "device.h" -#include "utils/pools.h" -#include "log/log.h" +#include "old/device/device.h" +#include "old/utils/pools.h" +#include "old/log/log.h" #include -#include #include -//#include /***************************************************** * CONSTANTS * @@ -48,7 +46,7 @@ /* Synchronously reads/writes one 4096-byte sector from/to the underlying device to/from the provided page */ -int sflc_dev_rwSector(sflc_Device * dev, struct page * page, sector_t sector, int rw) +int sfold_dev_rwSector(sfold_Device * dev, struct page * page, sector_t sector, int rw) { struct bio *bio; blk_opf_t opf; @@ -59,16 +57,16 @@ int sflc_dev_rwSector(sflc_Device * dev, struct page * page, sector_t sector, in opf |= REQ_SYNC; /* Allocate bio */ - bio = bio_alloc_bioset(dev->bdev->bdev, 1, opf, GFP_NOIO, &sflc_pools_bioset); + bio = bio_alloc_bioset(dev->bdev->bdev, 1, opf, GFP_NOIO, &sfold_pools_bioset); if (!bio) { pr_err("Could not allocate bio\n"); return -ENOMEM; } /* Set sector */ - bio->bi_iter.bi_sector = sector * SFLC_DEV_SECTOR_SCALE; + bio->bi_iter.bi_sector = sector * SFOLD_DEV_SECTOR_SCALE; /* Add page */ - if (!bio_add_page(bio, page, SFLC_DEV_SECTOR_SIZE, 0)) { + if (!bio_add_page(bio, page, SFOLD_DEV_SECTOR_SIZE, 0)) { pr_err("Catastrophe: could not add page to bio! WTF?\n"); err = EINVAL; goto out; @@ -83,32 +81,6 @@ out: return err; } - -/* -// Synchronously read/write entire PSI (257 blocks) to/from VMA -int sflc_dev_rwPsi(sflc_Device *dev, void *vma, u32 psi, int rw) -{ - struct dm_io_request io_req = { - .bi_opf = ((rw == READ) ? REQ_OP_READ : REQ_OP_WRITE) | REQ_SYNC, - - .mem.type = DM_IO_VMA, - .mem.offset = 0, - .mem.ptr.vma = vma, - - .notify.fn = NULL, - - .client = dev->dmio_client - }; - struct dm_io_region io_reg = { - .bdev = dev->bdev->bdev, - .sector = sflc_dev_psiToIvBlock(dev, psi) * SFLC_DEV_SECTOR_SCALE, - .count = SFLC_DEV_PHYS_SLICE_SIZE * SFLC_DEV_SECTOR_SCALE - }; - - return dm_io(&io_req, 1, &io_reg, NULL); -} -*/ - /***************************************************** * PRIVATE FUNCTIONS DEFINITIONS * *****************************************************/ diff --git a/dm-sflc/device/rmap.c b/dm-sflc/src/old/device/rmap.c similarity index 78% rename from dm-sflc/device/rmap.c rename to dm-sflc/src/old/device/rmap.c index 8e3635d..d196462 100644 --- a/dm-sflc/device/rmap.c +++ b/dm-sflc/src/old/device/rmap.c @@ -29,9 +29,9 @@ * INCLUDE SECTION * *****************************************************/ -#include "device.h" -#include "crypto/rand/rand.h" -#include "log/log.h" +#include "old/device/device.h" +#include "old/crypto/rand/rand.h" +#include "old/log/log.h" /***************************************************** * CONSTANTS * @@ -41,18 +41,12 @@ * PUBLIC FUNCTIONS DEFINITIONS * *****************************************************/ -/* Checks if PSI is free */ -bool sflc_dev_isPsiFree(sflc_Device *dev, u32 psi) -{ - return ((psi < dev->tot_slices) && - (dev->rmap[psi] == SFLC_DEV_RMAP_INVALID_VOL)); -} - - /* Sets the PSI as owned by the given volume (also decreases free_slices). * Returns < 0 if already taken. */ -int sflc_dev_markPsiTaken(sflc_Device * dev, u32 psi, u8 vol_idx) +int sfold_dev_markPsiTaken(sfold_Device * dev, u32 psi, u8 vol_idx) { + u8 prev_vol_idx; + /* Bounds check */ if (psi >= dev->tot_slices) { pr_err("Requested to set ownership for invalid PSI\n"); @@ -60,7 +54,8 @@ int sflc_dev_markPsiTaken(sflc_Device * dev, u32 psi, u8 vol_idx) } /* Check that it's free */ - if (dev->rmap[psi] != SFLC_DEV_RMAP_INVALID_VOL) { + prev_vol_idx = dev->rmap[psi]; + if (prev_vol_idx != SFOLD_DEV_RMAP_INVALID_VOL) { pr_err("Requested to set ownership for already-owned PSI\n"); return -EINVAL; } @@ -74,7 +69,7 @@ int sflc_dev_markPsiTaken(sflc_Device * dev, u32 psi, u8 vol_idx) /* Returns a random free physical slice, or < 0 if error */ -s32 sflc_dev_getNextRandomFreePsi(sflc_Device * dev) +s32 sfold_dev_getNextRandomFreePsi(sfold_Device * dev) { u32 psi; @@ -87,15 +82,14 @@ s32 sflc_dev_getNextRandomFreePsi(sflc_Device * dev) /* Repeatedly advance the counter in the shuffled array * until you find a free one */ do { - if (dev->prmslices_octr >= dev->tot_slices) { - pr_err("Double catastrophe! No free PSIs on the device, " - "and didn't catch it before!\n"); + psi = dev->shuffled_psi_array[dev->shuffled_psi_ctr]; + dev->shuffled_psi_ctr += 1; + + if (dev->shuffled_psi_ctr >= dev->tot_slices) { + pr_err("Double catastrophe! No free PSIs on the device, and didn't catch it before!\n"); return -ENOSPC; } - - psi = dev->prmslices[dev->prmslices_octr]; - dev->prmslices_octr += 1; - } while (dev->rmap[psi] != SFLC_DEV_RMAP_INVALID_VOL); + } while (dev->rmap[psi] != SFOLD_DEV_RMAP_INVALID_VOL); return psi; } diff --git a/dm-sflc/device/volumes.c b/dm-sflc/src/old/device/volumes.c similarity index 70% rename from dm-sflc/device/volumes.c rename to dm-sflc/src/old/device/volumes.c index b6ec553..7b12ab2 100644 --- a/dm-sflc/device/volumes.c +++ b/dm-sflc/src/old/device/volumes.c @@ -29,8 +29,8 @@ * INCLUDE SECTION * *****************************************************/ -#include "device.h" -#include "log/log.h" +#include "old/device/device.h" +#include "old/log/log.h" /***************************************************** * CONSTANTS * @@ -41,22 +41,13 @@ *****************************************************/ /* Returns false if volume index was already occupied. */ -bool sflc_dev_addVolume(sflc_Device * dev, sflc_Volume * vol, int vol_idx) +bool sfold_dev_addVolume(sfold_Device * dev, sfold_Volume * vol, int vol_idx) { - int err; - if (dev->vol[vol_idx]) { pr_err("Something's wrong, asked to set volume number %d, already occupied\n", vol_idx); return false; } - /* Update sysfs */ - err = sflc_sysfs_addVolumeToDevice(dev->kobj, vol->kvol); - if (err) { - pr_err("Could not add volume symlink in sysfs device subdir; error %d\n", err); - return false; - } - /* Update fields */ dev->vol[vol_idx] = vol; dev->vol_cnt += 1; @@ -64,39 +55,15 @@ bool sflc_dev_addVolume(sflc_Device * dev, sflc_Volume * vol, int vol_idx) return true; } -/* Looks at all volumes in all devices. Returns NULL if not found */ -sflc_Volume * sflc_dev_lookupVolumeByName(char * vol_name) -{ - sflc_Device * dev; - sflc_Volume * vol; - - /* Sweep all devices */ - list_for_each_entry(dev, &sflc_dev_list, list_node) { - /* Sweep all volumes */ - int i; - for (i = 0; i < SFLC_DEV_MAX_VOLUMES; ++i) { - vol = dev->vol[i]; - if (vol && (strcmp(vol_name, vol->vol_name) == 0)) { - return vol; - } - } - } - - return NULL; -} /* Does not put the volume. Returns false if was already NULL. */ -bool sflc_dev_removeVolume(sflc_Device * dev, int vol_idx) +bool sfold_dev_removeVolume(sfold_Device * dev, int vol_idx) { if (!dev->vol[vol_idx]) { pr_err("Something's wrong, asked to unset volume number %d, already NULL\n", vol_idx); return false; } - - /* Remove sysfs entry */ - if (dev->vol[vol_idx]->kvol) { - sflc_sysfs_removeVolumeFromDevice(dev->kobj, dev->vol[vol_idx]->kvol); - } + /* Update fields */ dev->vol[vol_idx] = NULL; diff --git a/dm-sflc/log/log.h b/dm-sflc/src/old/log/log.h similarity index 95% rename from dm-sflc/log/log.h rename to dm-sflc/src/old/log/log.h index 7ef7729..8386d98 100644 --- a/dm-sflc/log/log.h +++ b/dm-sflc/src/old/log/log.h @@ -25,8 +25,8 @@ * Logging format */ -#ifndef _SFLC_LOG_LOG_H_ -#define _SFLC_LOG_LOG_H_ +#ifndef _SFOLD_LOG_LOG_H_ +#define _SFOLD_LOG_LOG_H_ /***************************************************** * INCLUDE SECTION * @@ -41,4 +41,4 @@ #undef pr_fmt #define pr_fmt(fmt) "[%s] %s in %s:%d: " fmt, KBUILD_MODNAME, __func__, __FILE__, __LINE__ -#endif /* _SFLC_LOG_LOG_H_ */ +#endif /* _SFOLD_LOG_LOG_H_ */ diff --git a/dm-sflc/src/old/sflc_old.c b/dm-sflc/src/old/sflc_old.c new file mode 100644 index 0000000..4f1a839 --- /dev/null +++ b/dm-sflc/src/old/sflc_old.c @@ -0,0 +1,87 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +/***************************************************** + * INCLUDE SECTION * + *****************************************************/ + +#include +#include + +#include "old/sflc_old.h" +#include "old/crypto/symkey/symkey.h" +#include "old/crypto/rand/rand.h" +#include "old/utils/pools.h" +#include "old/utils/workqueues.h" +#include "old/log/log.h" + + +/***************************************************** + * MODULE FUNCTIONS DEFINITIONS * + *****************************************************/ + +/* Module entry point, called just once, at module-load time */ +int sfold_init(void) +{ + int ret; + + ret = sfold_rand_init(); + if (ret) { + pr_err("Could not init rand; error %d\n", ret); + goto err_rand_init; + } + + /* Init the memory pools */ + ret = sfold_pools_init(); + if (ret) { + pr_err("Could not init memory pools; error %d\n", ret); + goto err_pools; + } + + /* Init the workqueues */ + ret = sfold_queues_init(); + if (ret) { + pr_err("Could not init workqueues; error %d\n", ret); + goto err_queues; + } + + return 0; + + +err_queues: + sfold_pools_exit(); +err_pools: + sfold_rand_exit(); +err_rand_init: + return ret; +} + +/* Module exit point, called just once, at module-unload time */ +void sfold_exit(void) +{ + sfold_queues_exit(); + sfold_pools_exit(); + sfold_rand_exit(); + + return; +} diff --git a/dm-sflc/target/target.h b/dm-sflc/src/old/sflc_old.h similarity index 69% rename from dm-sflc/target/target.h rename to dm-sflc/src/old/sflc_old.h index 43eb64e..7f86748 100644 --- a/dm-sflc/target/target.h +++ b/dm-sflc/src/old/sflc_old.h @@ -20,25 +20,27 @@ * GNU General Public License along with this program. * If not, see . */ - -/* - * Methods of our DM target - */ -#ifndef _SFLC_TARGET_TARGET_H_ -#define _SFLC_TARGET_TARGET_H_ - -/***************************************************** - * INCLUDE SECTION * - *****************************************************/ - -#include - -/***************************************************** - * PUBLIC VARIABLES DECLARATIONS * - *****************************************************/ - -extern struct target_type sflc_target; +#ifndef _SFOLD_SFOLD_H +#define _SFOLD_SFOLD_H -#endif /* _SFLC_TARGET_TARGET_H_ */ +// For the definition of sfold_Device and its functions +#include "old/device/device.h" +// For the definition of sfold_Volume and its functions +#include "old/volume/volume.h" + + +extern struct target_type sfold_target_type; + + +int sfold_init(void); +void sfold_exit(void); + +int sfold_sysfs_add_device(sfold_Device *dev); +void sfold_sysfs_remove_device(sfold_Device *dev); +int sfold_sysfs_add_volume(sfold_Volume *vol); +void sfold_sysfs_remove_volume(sfold_Volume *vol); + + +#endif /* _SFOLD_SFOLD_H */ diff --git a/dm-sflc/src/old/sysfs.c b/dm-sflc/src/old/sysfs.c new file mode 100644 index 0000000..5445d8f --- /dev/null +++ b/dm-sflc/src/old/sysfs.c @@ -0,0 +1,142 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +/***************************************************** + * INCLUDE SECTION * + *****************************************************/ + +#include + +#include "old/sflc_old.h" +#include "old/log/log.h" + +// Only to import the definitions of structs sflc_volume and sflc_device +#include "sflc.h" + + +/* + *---------------------------- + * Devices + *---------------------------- + */ + +/* Show the total number of slices in a device */ +static ssize_t tot_slices_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf) +{ + struct sflc_device *top_dev; + sfold_Device * dev; + ssize_t ret; + + top_dev = container_of(kobj, struct sflc_device, kobj); + dev = top_dev->sfold_dev; + + /* Write the tot_slices */ + ret = sysfs_emit(buf, "%u\n", dev->tot_slices); + + return ret; +} + +/* Show the number of free slices in a device */ +static ssize_t free_slices_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf) +{ + struct sflc_device *top_dev; + sfold_Device * dev; + ssize_t ret; + + top_dev = container_of(kobj, struct sflc_device, kobj); + dev = top_dev->sfold_dev; + + /* Write the free_slices */ + if (mutex_lock_interruptible(&dev->slices_lock)) + return -ERESTARTSYS; + ret = sysfs_emit(buf, "%u\n", dev->free_slices); + mutex_unlock(&dev->slices_lock); + + return ret; +} + +static struct kobj_attribute tot_slices_kattr = __ATTR_RO(tot_slices); +static struct kobj_attribute free_slices_kattr = __ATTR_RO(free_slices); +static struct attribute *sfold_device_attrs[] = { + &tot_slices_kattr.attr, + &free_slices_kattr.attr, + NULL +}; +static const struct attribute_group sfold_device_attr_group = { + .attrs = sfold_device_attrs, +}; + +int sfold_sysfs_add_device(sfold_Device *dev) +{ + return sysfs_create_group(dev->kobj_parent, &sfold_device_attr_group); +} + +void sfold_sysfs_remove_device(sfold_Device *dev) +{ + sysfs_remove_group(dev->kobj_parent, &sfold_device_attr_group); +} + + +/* + *---------------------------- + * Volumes + *---------------------------- + */ + +/* Show the number of mapped slices in a volume */ +static ssize_t mapped_slices_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf) +{ + struct sflc_volume *top_vol; + sfold_Volume * vol; + ssize_t ret; + + top_vol = container_of(kobj, struct sflc_volume, kobj); + vol = top_vol->sfold_vol; + + /* Write the free_slices */ + if (mutex_lock_interruptible(&vol->fmap_lock)) + return -ERESTARTSYS; + ret = sysfs_emit(buf, "%u\n", vol->mapped_slices); + mutex_unlock(&vol->fmap_lock); + + return ret; +} + +static struct kobj_attribute mapped_slices_kattr = __ATTR_RO(mapped_slices); +static struct attribute *sfold_volume_attrs[] = { + &mapped_slices_kattr.attr, + NULL +}; +static const struct attribute_group sfold_volume_attr_group = { + .attrs = sfold_volume_attrs, +}; + +int sfold_sysfs_add_volume(sfold_Volume *vol) +{ + return sysfs_create_group(vol->kobj_parent, &sfold_volume_attr_group); +} + +void sfold_sysfs_remove_volume(sfold_Volume *vol) +{ + sysfs_remove_group(vol->kobj_parent, &sfold_volume_attr_group); +} diff --git a/dm-sflc/src/old/target.c b/dm-sflc/src/old/target.c new file mode 100644 index 0000000..4ceb71d --- /dev/null +++ b/dm-sflc/src/old/target.c @@ -0,0 +1,150 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +/* + * Methods of our DM target + */ + +/***************************************************** + * INCLUDE SECTION * + *****************************************************/ + +#include "old/device/device.h" +#include "old/volume/volume.h" +#include "old/utils/bio.h" +#include "old/utils/string.h" +#include "old/log/log.h" + +// Only to import the definition of struct sflc_volume +#include "sflc.h" + +/***************************************************** + * CONSTANTS * + *****************************************************/ + +/***************************************************** + * PRIVATE FUNCTIONS PROTOTYPES * + *****************************************************/ + +static int sfold_tgt_map(struct dm_target *ti, struct bio *bio); +static void sfold_tgt_ioHints(struct dm_target *ti, struct queue_limits *limits); +static int sfold_tgt_iterateDevices(struct dm_target *ti, iterate_devices_callout_fn fn, + void *data); + +/***************************************************** + * PUBLIC VARIABLES DEFINITIONS * + *****************************************************/ + +struct target_type sfold_target_type = { + .map = sfold_tgt_map, + .io_hints = sfold_tgt_ioHints, + .iterate_devices = sfold_tgt_iterateDevices, +}; + +/***************************************************** + * PRIVATE FUNCTIONS DEFINITIONS * + *****************************************************/ + + +/* Callback for every bio submitted to our virtual block device */ +static int sfold_tgt_map(struct dm_target *ti, struct bio *bio) +{ + int err; + struct sflc_volume *top_vol = ti->private; + sfold_Volume *vol = top_vol->sfold_vol; + + /* If no data, just quickly remap the sector and the block device (no crypto) */ + /* TODO: this is dangerous for deniability, will need more filtering */ + if (unlikely(!bio_has_data(bio))) { + pr_debug("No-data bio: bio_op = %d", bio_op(bio)); + err = sfold_vol_remapBioFast(vol, bio); + if (err) { + pr_err("Could not remap bio; error %d\n", err); + return DM_MAPIO_KILL; + } + return DM_MAPIO_REMAPPED; + } + + /* At this point, the bio has data. Do a few sanity checks */ + /* TODO: I think we can get rid of all of them */ + + /* Check that it is properly aligned and it doesn't cross vector boundaries */ + if (unlikely(!sfold_bio_isAligned(bio))) { + pr_err("Unaligned bio!\n"); + return DM_MAPIO_KILL; + } + /* If it contains more than one SFLC sector, complain with the DM layer and continue */ + if (unlikely(bio->bi_iter.bi_size > SFOLD_DEV_SECTOR_SIZE)) { + pr_notice("Large bio of size %u\n", bio->bi_iter.bi_size); + dm_accept_partial_bio(bio, SFOLD_DEV_SECTOR_SCALE); + } + /* Check that it contains exactly one SFLC sector */ + if (unlikely(bio->bi_iter.bi_size != SFOLD_DEV_SECTOR_SIZE)) { + pr_err("Wrong length (%u) of bio\n", bio->bi_iter.bi_size); + return DM_MAPIO_KILL; + } + + /* Now it is safe, process it */ + err = sfold_vol_processBio(vol, bio); + if (err) { + pr_err("Could not enqueue bio\n"); + return DM_MAPIO_KILL; + } + + return DM_MAPIO_SUBMITTED; +} + +/* Callback executed to inform the DM about our 4096-byte sector size */ +static void sfold_tgt_ioHints(struct dm_target *ti, struct queue_limits *limits) +{ + struct sflc_volume *top_vol = ti->private; + sfold_Volume *vol = top_vol->sfold_vol; + + pr_info("Called io_hints on volume \"%s\"\n", vol->vol_name); + + limits->logical_block_size = SFOLD_DEV_SECTOR_SIZE; + limits->physical_block_size = SFOLD_DEV_SECTOR_SIZE; + + limits->io_min = SFOLD_DEV_SECTOR_SIZE; + limits->io_opt = SFOLD_DEV_SECTOR_SIZE; + + return; +} + +/* Callback needed for God knows what, otherwise io_hints never gets called */ +static int sfold_tgt_iterateDevices(struct dm_target *ti, iterate_devices_callout_fn fn, + void *data) +{ + struct sflc_volume *top_vol = ti->private; + sfold_Volume *vol = top_vol->sfold_vol; + sfold_Device * dev = vol->dev; + + pr_debug("Called iterate_devices on volume \"%s\"\n", vol->vol_name); + + if (!fn) { + return -EINVAL; + } + return fn(ti, vol->dev->bdev, 0, + (dev->dev_header_size + dev->tot_slices * SFOLD_DEV_PHYS_SLICE_SIZE) * SFOLD_DEV_SECTOR_SCALE, + data); +} diff --git a/dm-sflc/utils/bio.c b/dm-sflc/src/old/utils/bio.c similarity index 88% rename from dm-sflc/utils/bio.c rename to dm-sflc/src/old/utils/bio.c index 7591c52..6607f89 100644 --- a/dm-sflc/utils/bio.c +++ b/dm-sflc/src/old/utils/bio.c @@ -29,8 +29,8 @@ * INCLUDE SECTION * *****************************************************/ -#include "bio.h" -#include "log/log.h" +#include "old/utils/bio.h" +#include "old/log/log.h" /***************************************************** @@ -41,7 +41,7 @@ * Checks whether each of the bio's segments contains a whole * number of 4096-byte sectors. */ -bool sflc_bio_isAligned(struct bio * bio) +bool sfold_bio_isAligned(struct bio * bio) { bool ret = true; @@ -51,12 +51,12 @@ bool sflc_bio_isAligned(struct bio * bio) return false; } /* Unlikely because we tell the DM layer about our sector size */ - if (unlikely(bio->bi_iter.bi_size % SFLC_DEV_SECTOR_SIZE != 0)) { + if (unlikely(bio->bi_iter.bi_size % SFOLD_DEV_SECTOR_SIZE != 0)) { pr_err("Abnormal bi_size = %u\n", bio->bi_iter.bi_size); return false; } /* Unlikely because we tell the DM layer about our sector size */ - if (unlikely(bio->bi_iter.bi_sector % SFLC_DEV_SECTOR_SCALE != 0)) { + if (unlikely(bio->bi_iter.bi_sector % SFOLD_DEV_SECTOR_SCALE != 0)) { pr_err("Abnormal bi_sector = %llu\n", bio->bi_iter.bi_sector); return false; } @@ -64,7 +64,7 @@ bool sflc_bio_isAligned(struct bio * bio) struct bio_vec bvl; struct bvec_iter iter; bio_for_each_segment(bvl, bio, iter) { - if ((bvl.bv_len == 0) || (bvl.bv_len % SFLC_DEV_SECTOR_SIZE != 0)) { + if ((bvl.bv_len == 0) || (bvl.bv_len % SFOLD_DEV_SECTOR_SIZE != 0)) { pr_err("Abnormal vector: bv_len = %u\n", bvl.bv_len); ret = false; } diff --git a/dm-sflc/utils/bio.h b/dm-sflc/src/old/utils/bio.h similarity index 91% rename from dm-sflc/utils/bio.h rename to dm-sflc/src/old/utils/bio.h index d7bf7b2..51917e6 100644 --- a/dm-sflc/utils/bio.h +++ b/dm-sflc/src/old/utils/bio.h @@ -25,14 +25,14 @@ * A collection of utility bio functions */ -#ifndef _SFLC_UTILS_BIO_H_ -#define _SFLC_UTILS_BIO_H_ +#ifndef _SFOLD_UTILS_BIO_H_ +#define _SFOLD_UTILS_BIO_H_ /***************************************************** * INCLUDE SECTION * *****************************************************/ -#include "device/device.h" +#include "old/device/device.h" /***************************************************** * PUBLIC FUNCTIONS PROTOTYPES * @@ -42,7 +42,7 @@ * Checks whether each of the bio's segments contains a whole * number of 4096-byte sectors. */ -bool sflc_bio_isAligned(struct bio * bio); +bool sfold_bio_isAligned(struct bio * bio); -#endif /* _SFLC_UTILS_BIO_H_ */ +#endif /* _SFOLD_UTILS_BIO_H_ */ diff --git a/dm-sflc/utils/pools.c b/dm-sflc/src/old/utils/pools.c similarity index 56% rename from dm-sflc/utils/pools.c rename to dm-sflc/src/old/utils/pools.c index 9e9af0b..5e67faf 100644 --- a/dm-sflc/utils/pools.c +++ b/dm-sflc/src/old/utils/pools.c @@ -29,100 +29,100 @@ * INCLUDE SECTION * *****************************************************/ -#include "pools.h" -#include "log/log.h" +#include "old/utils/pools.h" +#include "old/log/log.h" /***************************************************** * CONSTANTS * *****************************************************/ /* Pool sizes */ -#define SFLC_POOLS_BIOSET_POOL_SIZE 1024 -#define SFLC_POOLS_PAGE_POOL_SIZE 1024 -#define SFLC_POOLS_WRITE_WORK_POOL_SIZE 1024 -#define SFLC_POOLS_DECRYPT_WORK_POOL_SIZE 1024 +#define SFOLD_POOLS_BIOSET_POOL_SIZE 1024 +#define SFOLD_POOLS_PAGE_POOL_SIZE 1024 +#define SFOLD_POOLS_WRITE_WORK_POOL_SIZE 1024 +#define SFOLD_POOLS_DECRYPT_WORK_POOL_SIZE 1024 /* Slab cache names */ -#define SFLC_POOLS_WRITE_WORK_SLAB_NAME "sflc_write_work_slab" -#define SFLC_POOLS_DECRYPT_WORK_SLAB_NAME "sflc_decrypt_work_slab" -#define SFLC_POOLS_IV_SLAB_NAME "sflc_iv_slab" +#define SFOLD_POOLS_WRITE_WORK_SLAB_NAME "sfold_write_work_slab" +#define SFOLD_POOLS_DECRYPT_WORK_SLAB_NAME "sfold_decrypt_work_slab" +#define SFOLD_POOLS_IV_SLAB_NAME "sfold_iv_slab" /***************************************************** * PUBLIC VARIABLES DEFINITIONS * *****************************************************/ -struct bio_set sflc_pools_bioset; -mempool_t * sflc_pools_pagePool; -mempool_t * sflc_pools_writeWorkPool; -mempool_t * sflc_pools_decryptWorkPool; -struct kmem_cache * sflc_pools_ivSlab; +struct bio_set sfold_pools_bioset; +mempool_t * sfold_pools_pagePool; +mempool_t * sfold_pools_writeWorkPool; +mempool_t * sfold_pools_decryptWorkPool; +struct kmem_cache * sfold_pools_ivSlab; /***************************************************** * PRIVATE VARIABLES * *****************************************************/ -static struct kmem_cache * sflc_pools_writeWorkSlab; -static struct kmem_cache * sflc_pools_decryptWorkSlab; +static struct kmem_cache * sfold_pools_writeWorkSlab; +static struct kmem_cache * sfold_pools_decryptWorkSlab; /***************************************************** * PUBLIC FUNCTIONS DEFINITIONS * *****************************************************/ -int sflc_pools_init(void) +int sfold_pools_init(void) { int err; /* Memory pools: bioset */ - err = bioset_init(&sflc_pools_bioset, SFLC_POOLS_BIOSET_POOL_SIZE, 0, BIOSET_NEED_BVECS); + err = bioset_init(&sfold_pools_bioset, SFOLD_POOLS_BIOSET_POOL_SIZE, 0, BIOSET_NEED_BVECS); if (err) { pr_err("Could not init bioset: error %d\n", err); goto err_bioset; } /* Memory pools: page_pool */ - sflc_pools_pagePool = mempool_create_page_pool(SFLC_POOLS_PAGE_POOL_SIZE, 0); - if (!sflc_pools_pagePool) { + sfold_pools_pagePool = mempool_create_page_pool(SFOLD_POOLS_PAGE_POOL_SIZE, 0); + if (!sfold_pools_pagePool) { pr_err("Could not create page pool\n"); err = -ENOMEM; goto err_pagepool; } /* Memory pools: writeWork slab cache */ - sflc_pools_writeWorkSlab = kmem_cache_create(SFLC_POOLS_WRITE_WORK_SLAB_NAME, sizeof(sflc_vol_WriteWork), 0, SLAB_POISON | SLAB_RED_ZONE, NULL); - if (IS_ERR(sflc_pools_writeWorkSlab)) { - err = PTR_ERR(sflc_pools_writeWorkSlab); + sfold_pools_writeWorkSlab = kmem_cache_create(SFOLD_POOLS_WRITE_WORK_SLAB_NAME, sizeof(sfold_vol_WriteWork), 0, SLAB_POISON | SLAB_RED_ZONE, NULL); + if (IS_ERR(sfold_pools_writeWorkSlab)) { + err = PTR_ERR(sfold_pools_writeWorkSlab); pr_err("Could not create writeWork slab cache; error %d\n", err); goto err_create_write_work_slab; } /* Memory pools: writeWork pool */ - sflc_pools_writeWorkPool = mempool_create_slab_pool(SFLC_POOLS_WRITE_WORK_POOL_SIZE, sflc_pools_writeWorkSlab); - if (!sflc_pools_writeWorkPool) { + sfold_pools_writeWorkPool = mempool_create_slab_pool(SFOLD_POOLS_WRITE_WORK_POOL_SIZE, sfold_pools_writeWorkSlab); + if (!sfold_pools_writeWorkPool) { pr_err("Could not create writeWork pool\n"); err = -ENOMEM; goto err_write_work_pool; } /* Memory pools: decryptWork slab cache */ - sflc_pools_decryptWorkSlab = kmem_cache_create(SFLC_POOLS_DECRYPT_WORK_SLAB_NAME, sizeof(sflc_vol_DecryptWork), 0, SLAB_POISON | SLAB_RED_ZONE, NULL); - if (IS_ERR(sflc_pools_decryptWorkSlab)) { - err = PTR_ERR(sflc_pools_decryptWorkSlab); + sfold_pools_decryptWorkSlab = kmem_cache_create(SFOLD_POOLS_DECRYPT_WORK_SLAB_NAME, sizeof(sfold_vol_DecryptWork), 0, SLAB_POISON | SLAB_RED_ZONE, NULL); + if (IS_ERR(sfold_pools_decryptWorkSlab)) { + err = PTR_ERR(sfold_pools_decryptWorkSlab); pr_err("Could not create decryptWork slab cache; error %d\n", err); goto err_create_decrypt_work_slab; } /* Memory pools: decryptWork pool */ - sflc_pools_decryptWorkPool = mempool_create_slab_pool(SFLC_POOLS_DECRYPT_WORK_POOL_SIZE, sflc_pools_decryptWorkSlab); - if (!sflc_pools_decryptWorkPool) { + sfold_pools_decryptWorkPool = mempool_create_slab_pool(SFOLD_POOLS_DECRYPT_WORK_POOL_SIZE, sfold_pools_decryptWorkSlab); + if (!sfold_pools_decryptWorkPool) { pr_err("Could not create decryptWork pool\n"); err = -ENOMEM; goto err_decrypt_work_pool; } /* Memory pools: IV slab cache */ - sflc_pools_ivSlab = kmem_cache_create(SFLC_POOLS_IV_SLAB_NAME, sizeof(sflc_dev_IvCacheEntry), 0, SLAB_POISON | SLAB_RED_ZONE, NULL); - if (IS_ERR(sflc_pools_ivSlab)) { - err = PTR_ERR(sflc_pools_ivSlab); + sfold_pools_ivSlab = kmem_cache_create(SFOLD_POOLS_IV_SLAB_NAME, sizeof(sfold_dev_IvCacheEntry), 0, SLAB_POISON | SLAB_RED_ZONE, NULL); + if (IS_ERR(sfold_pools_ivSlab)) { + err = PTR_ERR(sfold_pools_ivSlab); pr_err("Could not create IV slab cache; error %d\n", err); goto err_create_iv_slab; } @@ -131,28 +131,28 @@ int sflc_pools_init(void) err_create_iv_slab: - mempool_destroy(sflc_pools_decryptWorkPool); + mempool_destroy(sfold_pools_decryptWorkPool); err_decrypt_work_pool: - kmem_cache_destroy(sflc_pools_decryptWorkSlab); + kmem_cache_destroy(sfold_pools_decryptWorkSlab); err_create_decrypt_work_slab: - mempool_destroy(sflc_pools_writeWorkPool); + mempool_destroy(sfold_pools_writeWorkPool); err_write_work_pool: - kmem_cache_destroy(sflc_pools_writeWorkSlab); + kmem_cache_destroy(sfold_pools_writeWorkSlab); err_create_write_work_slab: - mempool_destroy(sflc_pools_pagePool); + mempool_destroy(sfold_pools_pagePool); err_pagepool: - bioset_exit(&sflc_pools_bioset); + bioset_exit(&sfold_pools_bioset); err_bioset: return err; } -void sflc_pools_exit(void) +void sfold_pools_exit(void) { - kmem_cache_destroy(sflc_pools_ivSlab); - mempool_destroy(sflc_pools_decryptWorkPool); - kmem_cache_destroy(sflc_pools_decryptWorkSlab); - mempool_destroy(sflc_pools_writeWorkPool); - kmem_cache_destroy(sflc_pools_writeWorkSlab); - mempool_destroy(sflc_pools_pagePool); - bioset_exit(&sflc_pools_bioset); + kmem_cache_destroy(sfold_pools_ivSlab); + mempool_destroy(sfold_pools_decryptWorkPool); + kmem_cache_destroy(sfold_pools_decryptWorkSlab); + mempool_destroy(sfold_pools_writeWorkPool); + kmem_cache_destroy(sfold_pools_writeWorkSlab); + mempool_destroy(sfold_pools_pagePool); + bioset_exit(&sfold_pools_bioset); } diff --git a/dm-sflc/utils/pools.h b/dm-sflc/src/old/utils/pools.h similarity index 81% rename from dm-sflc/utils/pools.h rename to dm-sflc/src/old/utils/pools.h index e0a1261..b87d6c6 100644 --- a/dm-sflc/utils/pools.h +++ b/dm-sflc/src/old/utils/pools.h @@ -25,31 +25,31 @@ * A set of memory pools */ -#ifndef _SFLC_UTILS_POOLS_H_ -#define _SFLC_UTILS_POOLS_H_ +#ifndef _SFOLD_UTILS_POOLS_H_ +#define _SFOLD_UTILS_POOLS_H_ /***************************************************** * INCLUDE SECTION * *****************************************************/ -#include "device/device.h" +#include "old/device/device.h" /***************************************************** * PUBLIC VARIABLES DECLARATIONS * *****************************************************/ -extern struct bio_set sflc_pools_bioset; -extern mempool_t * sflc_pools_pagePool; -extern mempool_t * sflc_pools_writeWorkPool; -extern mempool_t * sflc_pools_decryptWorkPool; -extern struct kmem_cache * sflc_pools_ivSlab; +extern struct bio_set sfold_pools_bioset; +extern mempool_t * sfold_pools_pagePool; +extern mempool_t * sfold_pools_writeWorkPool; +extern mempool_t * sfold_pools_decryptWorkPool; +extern struct kmem_cache * sfold_pools_ivSlab; /***************************************************** * PUBLIC FUNCTIONS PROTOTYPES * *****************************************************/ -int sflc_pools_init(void); -void sflc_pools_exit(void); +int sfold_pools_init(void); +void sfold_pools_exit(void); -#endif /* _SFLC_UTILS_POOLS_H_ */ +#endif /* _SFOLD_UTILS_POOLS_H_ */ diff --git a/dm-sflc/utils/string.c b/dm-sflc/src/old/utils/string.c similarity index 92% rename from dm-sflc/utils/string.c rename to dm-sflc/src/old/utils/string.c index 0199dae..8d533c6 100644 --- a/dm-sflc/utils/string.c +++ b/dm-sflc/src/old/utils/string.c @@ -31,15 +31,15 @@ #include -#include "string.h" -#include "log/log.h" +#include "old/utils/string.h" +#include "old/log/log.h" /***************************************************** * PUBLIC FUNCTIONS DEFINITIONS * *****************************************************/ -int sflc_str_hexDecode(char * hex, u8 * bin) +int sfold_str_hexDecode(char * hex, u8 * bin) { char buf[3]; unsigned len; @@ -64,7 +64,7 @@ int sflc_str_hexDecode(char * hex, u8 * bin) } -void sflc_str_replaceAll(char * str, char old, char new) +void sfold_str_replaceAll(char * str, char old, char new) { int i; diff --git a/dm-sflc/utils/string.h b/dm-sflc/src/old/utils/string.h similarity index 88% rename from dm-sflc/utils/string.h rename to dm-sflc/src/old/utils/string.h index 8ac29df..98e0565 100644 --- a/dm-sflc/utils/string.h +++ b/dm-sflc/src/old/utils/string.h @@ -25,8 +25,8 @@ * A collection of utility string functions */ -#ifndef _SFLC_UTILS_STRING_H_ -#define _SFLC_UTILS_STRING_H_ +#ifndef _SFOLD_UTILS_STRING_H_ +#define _SFOLD_UTILS_STRING_H_ /***************************************************** * INCLUDE SECTION * @@ -38,8 +38,8 @@ * PUBLIC FUNCTIONS PROTOTYPES * *****************************************************/ -int sflc_str_hexDecode(char * hex, u8 * bin); -void sflc_str_replaceAll(char * str, char old, char new); +int sfold_str_hexDecode(char * hex, u8 * bin); +void sfold_str_replaceAll(char * str, char old, char new); -#endif /* _SFLC_UTILS_STRING_H_ */ +#endif /* _SFOLD_UTILS_STRING_H_ */ diff --git a/dm-sflc/utils/vector.c b/dm-sflc/src/old/utils/vector.c similarity index 83% rename from dm-sflc/utils/vector.c rename to dm-sflc/src/old/utils/vector.c index 5ad0939..4c73814 100644 --- a/dm-sflc/utils/vector.c +++ b/dm-sflc/src/old/utils/vector.c @@ -29,9 +29,9 @@ * INCLUDE SECTION * *****************************************************/ -#include "vector.h" -#include "crypto/rand/rand.h" -#include "log/log.h" +#include "old/utils/vector.h" +#include "old/crypto/rand/rand.h" +#include "old/log/log.h" /***************************************************** @@ -39,22 +39,22 @@ *****************************************************/ /* Shuffle a vector of u32's with the Fisher-Yates algorithm */ -int sflc_vec_u32shuffle(u32 *v, u32 len) +int sfold_vec_u32shuffle(u32 *v, u32 len) { u32 i; for (i = len-1; i >= 1; i--) { /* Sample a random index from 0 to i (inclusive) */ - s32 j = sflc_rand_uniform(i+1); + s32 j = sfold_rand_uniform(i+1); if (j < 0) { pr_err("Could not sample j; error %d", j); return j; } - /* Swap v[i] and v[j] */ - u32 tmp = v[i]; - v[i] = v[j]; - v[j] = tmp; + /* Swap v[i] and v[j] (without third variable 'cuz we're cool) */ + v[i] ^= v[j]; // v[i] <- a XOR b + v[j] ^= v[i]; // v[j] <- b XOR (a XOR b) = a + v[i] ^= v[j]; // v[i] <- (a XOR b) XOR a = b } return 0; diff --git a/dm-sflc/utils/vector.h b/dm-sflc/src/old/utils/vector.h similarity index 92% rename from dm-sflc/utils/vector.h rename to dm-sflc/src/old/utils/vector.h index 4edc7ff..ae75ca0 100644 --- a/dm-sflc/utils/vector.h +++ b/dm-sflc/src/old/utils/vector.h @@ -25,8 +25,8 @@ * A collection of utility vector functions */ -#ifndef _SFLC_UTILS_VECTOR_H_ -#define _SFLC_UTILS_VECTOR_H_ +#ifndef _SFOLD_UTILS_VECTOR_H_ +#define _SFOLD_UTILS_VECTOR_H_ /***************************************************** * INCLUDE SECTION * @@ -39,7 +39,7 @@ *****************************************************/ /* Shuffle a vector of u32's */ -int sflc_vec_u32shuffle(u32 *v, u32 len); +int sfold_vec_u32shuffle(u32 *v, u32 len); -#endif /* _SFLC_UTILS_VECTOR_H_ */ +#endif /* _SFOLD_UTILS_VECTOR_H_ */ diff --git a/dm-sflc/utils/workqueues.c b/dm-sflc/src/old/utils/workqueues.c similarity index 76% rename from dm-sflc/utils/workqueues.c rename to dm-sflc/src/old/utils/workqueues.c index 15697b1..942b765 100644 --- a/dm-sflc/utils/workqueues.c +++ b/dm-sflc/src/old/utils/workqueues.c @@ -28,42 +28,42 @@ * INCLUDE SECTION * *****************************************************/ -#include "workqueues.h" -#include "log/log.h" +#include "old/utils/workqueues.h" +#include "old/log/log.h" /***************************************************** * CONSTANTS * *****************************************************/ -#define SFLC_QUEUES_WRITE_WQ_NAME "sflc_write_workqueue" -#define SFLC_QUEUES_DECRYPT_WQ_NAME "sflc_decrypt_workqueue" +#define SFOLD_QUEUES_WRITE_WQ_NAME "sfold_write_workqueue" +#define SFOLD_QUEUES_DECRYPT_WQ_NAME "sfold_decrypt_workqueue" /***************************************************** * PUBLIC VARIABLES DEFINITIONS * *****************************************************/ -struct workqueue_struct * sflc_queues_writeQueue; -struct workqueue_struct * sflc_queues_decryptQueue; +struct workqueue_struct * sfold_queues_writeQueue; +struct workqueue_struct * sfold_queues_decryptQueue; /***************************************************** * PUBLIC FUNCTIONS DEFINITIONS * *****************************************************/ -int sflc_queues_init(void) +int sfold_queues_init(void) { int err; /* Write workqueue */ - sflc_queues_writeQueue = create_workqueue(SFLC_QUEUES_WRITE_WQ_NAME); - if (!sflc_queues_writeQueue) { + sfold_queues_writeQueue = create_workqueue(SFOLD_QUEUES_WRITE_WQ_NAME); + if (!sfold_queues_writeQueue) { pr_err("Could not create write workqueue\n"); err = -ENOMEM; goto err_write_queue; } /* Decrypt workqueue */ - sflc_queues_decryptQueue = create_workqueue(SFLC_QUEUES_DECRYPT_WQ_NAME); - if (!sflc_queues_decryptQueue) { + sfold_queues_decryptQueue = create_workqueue(SFOLD_QUEUES_DECRYPT_WQ_NAME); + if (!sfold_queues_decryptQueue) { pr_err("Could not create decrypt workqueue\n"); err = -ENOMEM; goto err_decrypt_queue; @@ -73,13 +73,13 @@ int sflc_queues_init(void) err_decrypt_queue: - destroy_workqueue(sflc_queues_writeQueue); + destroy_workqueue(sfold_queues_writeQueue); err_write_queue: return err; } -void sflc_queues_exit(void) +void sfold_queues_exit(void) { - destroy_workqueue(sflc_queues_decryptQueue); - destroy_workqueue(sflc_queues_writeQueue); + destroy_workqueue(sfold_queues_decryptQueue); + destroy_workqueue(sfold_queues_writeQueue); } diff --git a/dm-sflc/utils/workqueues.h b/dm-sflc/src/old/utils/workqueues.h similarity index 86% rename from dm-sflc/utils/workqueues.h rename to dm-sflc/src/old/utils/workqueues.h index 38fb031..3026a6d 100644 --- a/dm-sflc/utils/workqueues.h +++ b/dm-sflc/src/old/utils/workqueues.h @@ -25,8 +25,8 @@ * A set of workqueues */ -#ifndef _SFLC_UTILS_QUEUES_H_ -#define _SFLC_UTILS_QUEUES_H_ +#ifndef _SFOLD_UTILS_QUEUES_H_ +#define _SFOLD_UTILS_QUEUES_H_ /***************************************************** * INCLUDE SECTION * @@ -38,15 +38,15 @@ * PUBLIC VARIABLES DECLARATIONS * *****************************************************/ -extern struct workqueue_struct * sflc_queues_writeQueue; -extern struct workqueue_struct * sflc_queues_decryptQueue; +extern struct workqueue_struct * sfold_queues_writeQueue; +extern struct workqueue_struct * sfold_queues_decryptQueue; /***************************************************** * PUBLIC FUNCTIONS PROTOTYPES * *****************************************************/ -int sflc_queues_init(void); -void sflc_queues_exit(void); +int sfold_queues_init(void); +void sfold_queues_exit(void); -#endif /* _SFLC_UTILS_QUEUES_H_ */ +#endif /* _SFOLD_UTILS_QUEUES_H_ */ diff --git a/dm-sflc/volume/fmap.c b/dm-sflc/src/old/volume/fmap.c similarity index 69% rename from dm-sflc/volume/fmap.c rename to dm-sflc/src/old/volume/fmap.c index f7af843..63b837b 100644 --- a/dm-sflc/volume/fmap.c +++ b/dm-sflc/src/old/volume/fmap.c @@ -29,12 +29,10 @@ * INCLUDE SECTION * *****************************************************/ -#include - -#include "volume.h" -#include "crypto/rand/rand.h" -#include "utils/pools.h" -#include "log/log.h" +#include "old/volume/volume.h" +#include "old/crypto/rand/rand.h" +#include "old/utils/pools.h" +#include "old/log/log.h" /***************************************************** * CONSTANTS * @@ -44,8 +42,7 @@ * PRIVATE FUNCTIONS PROTOTYPES * *****************************************************/ -static s32 sflc_vol_mapSlice(sflc_Volume * vol, u32 lsi, int op); -static int sflc_vol_reassignLsi(sflc_Volume *vol, u32 lsi, u32 old_psi); +static s32 sfold_vol_mapSlice(sfold_Volume * vol, u32 lsi, int op); /***************************************************** * PUBLIC FUNCTIONS DEFINITIONS * @@ -53,28 +50,28 @@ static int sflc_vol_reassignLsi(sflc_Volume *vol, u32 lsi, u32 old_psi); /* Maps a logical 512-byte sector to a physical 512-byte sector. Returns < 0 if error. * Specifically, if op == READ, and the logical slice is unmapped, -ENXIO is returned. */ -s64 sflc_vol_remapSector(sflc_Volume * vol, sector_t log_sector, int op, u32 * psi_out, u32 * off_in_slice_out) +s64 sfold_vol_remapSector(sfold_Volume * vol, sector_t log_sector, int op, u32 * psi_out, u32 * off_in_slice_out) { u32 lsi; u32 off_in_slice; s32 psi; sector_t phys_sector; - sflc_Device *dev = vol->dev; + sfold_Device *dev = vol->dev; /* Start by scaling down to a Shufflecake sector */ - log_sector /= SFLC_DEV_SECTOR_SCALE; + log_sector /= SFOLD_DEV_SECTOR_SCALE; /* Get the logical slice index it belongs to */ - lsi = log_sector / SFLC_VOL_LOG_SLICE_SIZE; + lsi = log_sector / SFOLD_VOL_LOG_SLICE_SIZE; /* Get which block it is within the slice */ - off_in_slice = log_sector % SFLC_VOL_LOG_SLICE_SIZE; + off_in_slice = log_sector % SFOLD_VOL_LOG_SLICE_SIZE; /* Output the off_in_slice */ if (off_in_slice_out) { *off_in_slice_out = off_in_slice; } /* Map it to a physical slice */ - psi = sflc_vol_mapSlice(vol, lsi, op); + psi = sfold_vol_mapSlice(vol, lsi, op); /* -ENXIO is a special case */ if (psi == -ENXIO) { pr_debug("mapSlice returned -ENXIO: stupid READ\n"); @@ -91,20 +88,20 @@ s64 sflc_vol_remapSector(sflc_Volume * vol, sector_t log_sector, int op, u32 * p } /* Get the physical sector (the first of every slice contains the IVs) */ - phys_sector = ((sector_t)psi * SFLC_DEV_PHYS_SLICE_SIZE) + 1 + off_in_slice; + phys_sector = ((sector_t)psi * SFOLD_DEV_PHYS_SLICE_SIZE) + 1 + off_in_slice; /* Add the device header */ phys_sector += dev->dev_header_size; /* Scale it back up to a kernel sector */ - phys_sector *= SFLC_DEV_SECTOR_SCALE; + phys_sector *= SFOLD_DEV_SECTOR_SCALE; return phys_sector; } /* Loads (and decrypts) the position map from the volume's header */ -int sflc_vol_loadFmap(sflc_Volume * vol) +int sfold_vol_loadFmap(sfold_Volume * vol) { - sflc_Device * dev = vol->dev; + sfold_Device * dev = vol->dev; sector_t sector; struct page * iv_page; u8 * iv_ptr; @@ -114,12 +111,12 @@ int sflc_vol_loadFmap(sflc_Volume * vol) int err; /* Allocate pages */ - iv_page = mempool_alloc(sflc_pools_pagePool, GFP_NOIO); + iv_page = mempool_alloc(sfold_pools_pagePool, GFP_NOIO); if (!iv_page) { pr_err("Could not allocate IV page\n"); return -ENOMEM; } - data_page = mempool_alloc(sflc_pools_pagePool, GFP_NOIO); + data_page = mempool_alloc(sfold_pools_pagePool, GFP_NOIO); if (!data_page) { pr_err("Could not allocate data page\n"); return -ENOMEM; @@ -148,7 +145,7 @@ int sflc_vol_loadFmap(sflc_Volume * vol) int i; for (i = 0; i < dev->vol_header_nr_iv_blocks && lsi < dev->tot_slices; i++) { /* Load the IV block */ - err = sflc_dev_rwSector(dev, iv_page, sector, READ); + err = sfold_dev_rwSector(dev, iv_page, sector, READ); if (err) { pr_err("Could not read IV block i=%d at sector %llu; error %d\n", i, sector, err); goto out; @@ -157,9 +154,9 @@ int sflc_vol_loadFmap(sflc_Volume * vol) /* Loop over the 256 data blocks */ int j; - for (j = 0; j < SFLC_DEV_SECTOR_TO_IV_RATIO && lsi < dev->tot_slices; j++) { + for (j = 0; j < SFOLD_DEV_SECTOR_TO_IV_RATIO && lsi < dev->tot_slices; j++) { /* Load the data block */ - err = sflc_dev_rwSector(dev, data_page, sector, READ); + err = sfold_dev_rwSector(dev, data_page, sector, READ); if (err) { pr_err("Could not read data block i=%d, j=%d at sector %llu; error %d\n", i, j, sector, err); goto out; @@ -167,7 +164,7 @@ int sflc_vol_loadFmap(sflc_Volume * vol) sector += 1; /* Decrypt it in place */ - err = sflc_sk_decrypt(vol->skctx, data_ptr, data_ptr, SFLC_DEV_SECTOR_SIZE, (iv_ptr + j*SFLC_SK_IV_LEN)); + err = sfold_sk_decrypt(vol->skctx, data_ptr, data_ptr, SFOLD_DEV_SECTOR_SIZE, (iv_ptr + j*SFOLD_SK_IV_LEN)); if (err) { pr_err("Could not decrypt data block i=%d, j=%d at sector %llu; error %d\n", i, j, sector, err); goto out; @@ -175,42 +172,22 @@ int sflc_vol_loadFmap(sflc_Volume * vol) /* Loop over the 1024 fmap entries in this data block */ int k; - for (k = 0; k < SFLC_VOL_HEADER_MAPPINGS_PER_BLOCK && lsi < dev->tot_slices; k++) { + for (k = 0; k < SFOLD_VOL_HEADER_MAPPINGS_PER_BLOCK && lsi < dev->tot_slices; k++) { /* An entry is just a single big-endian PSI, the LSI is implicitly the index of this entry */ __be32 * be_psi = (void *) (data_ptr + (k * sizeof(__be32))); u32 psi = be32_to_cpu(*be_psi); - /* If unassigned, just move on */ - if (psi == SFLC_VOL_FMAP_INVALID_PSI) { - vol->fmap[lsi] = psi; - /* Next iteration */ - lsi += 1; - continue; + /* Add mapping to the volume's fmap */ + vol->fmap[lsi] = psi; + /* Also add it to the device's rmap and to the count, if LSI is actually mapped */ + if (psi != SFOLD_VOL_FMAP_INVALID_PSI) { + sfold_dev_markPsiTaken(dev, psi, vol->vol_idx); + vol->mapped_slices += 1; } - /* If already assigned to lower-order volume, sample a new one */ - if (!sflc_dev_isPsiFree(dev, psi)) { - pr_warn("Corruption of volume %d: LSI %u was evicted from PSI %u\n", - vol->vol_idx, lsi, psi); - err = sflc_vol_reassignLsi(vol, lsi, psi); - if (err) { - pr_err("Could not reassign evicted LSI; " - "error %d\n", err); - goto out; - } - - /* Next iteration */ - lsi += 1; - } else { - /* Just assign */ - vol->fmap[lsi] = psi; - sflc_dev_markPsiTaken(dev, psi, vol->vol_idx); - vol->mapped_slices += 1; - - /* Next iteration */ - lsi += 1; - } + /* Next iteration */ + lsi += 1; } } } @@ -225,16 +202,16 @@ out: kunmap(iv_page); kunmap(data_page); /* Free them */ - mempool_free(iv_page, sflc_pools_pagePool); - mempool_free(data_page, sflc_pools_pagePool); + mempool_free(iv_page, sfold_pools_pagePool); + mempool_free(data_page, sfold_pools_pagePool); return err; } /* Stores (and encrypts) the position map to the volume's header */ -int sflc_vol_storeFmap(sflc_Volume * vol) +int sfold_vol_storeFmap(sfold_Volume * vol) { - sflc_Device * dev = vol->dev; + sfold_Device * dev = vol->dev; sector_t sector; struct page * iv_page; u8 * iv_ptr; @@ -244,12 +221,12 @@ int sflc_vol_storeFmap(sflc_Volume * vol) int err; /* Allocate pages */ - iv_page = mempool_alloc(sflc_pools_pagePool, GFP_NOIO); + iv_page = mempool_alloc(sfold_pools_pagePool, GFP_NOIO); if (!iv_page) { pr_err("Could not allocate IV page\n"); return -ENOMEM; } - data_page = mempool_alloc(sflc_pools_pagePool, GFP_NOIO); + data_page = mempool_alloc(sfold_pools_pagePool, GFP_NOIO); if (!data_page) { pr_err("Could not allocate data page\n"); return -ENOMEM; @@ -278,13 +255,13 @@ int sflc_vol_storeFmap(sflc_Volume * vol) int i; for (i = 0; i < dev->vol_header_nr_iv_blocks && lsi < dev->tot_slices; i++) { /* Fill the IV block with random bytes */ - err = sflc_rand_getBytes(iv_ptr, SFLC_DEV_SECTOR_SIZE); + err = sfold_rand_getBytes(iv_ptr, SFOLD_DEV_SECTOR_SIZE); if (err) { pr_err("Could not sample random IV for block i=%d at sector %llu; error %d\n", i, sector, err); goto out; } /* Store it on the disk (before it gets changed by the encryption) */ - err = sflc_dev_rwSector(dev, iv_page, sector, WRITE); + err = sfold_dev_rwSector(dev, iv_page, sector, WRITE); if (err) { pr_err("Could not read IV block i=%d at sector %llu; error %d\n", i, sector, err); goto out; @@ -293,10 +270,10 @@ int sflc_vol_storeFmap(sflc_Volume * vol) /* Loop over the 256 data blocks */ int j; - for (j = 0; j < SFLC_DEV_SECTOR_TO_IV_RATIO && lsi < dev->tot_slices; j++) { + for (j = 0; j < SFOLD_DEV_SECTOR_TO_IV_RATIO && lsi < dev->tot_slices; j++) { /* Loop over the 1024 fmap entries that fit in this data block */ int k; - for (k = 0; k < SFLC_VOL_HEADER_MAPPINGS_PER_BLOCK && lsi < dev->tot_slices; k++) { + for (k = 0; k < SFOLD_VOL_HEADER_MAPPINGS_PER_BLOCK && lsi < dev->tot_slices; k++) { /* Get the PSI for the current LSI */ u32 psi = vol->fmap[lsi]; /* Write it into the block as big-endian */ @@ -308,14 +285,14 @@ int sflc_vol_storeFmap(sflc_Volume * vol) } /* Encrypt it in place */ - err = sflc_sk_encrypt(vol->skctx, data_ptr, data_ptr, SFLC_DEV_SECTOR_SIZE, (iv_ptr + j*SFLC_SK_IV_LEN)); + err = sfold_sk_encrypt(vol->skctx, data_ptr, data_ptr, SFOLD_DEV_SECTOR_SIZE, (iv_ptr + j*SFOLD_SK_IV_LEN)); if (err) { pr_err("Could not encrypt data block i=%d, j=%d at sector %llu; error %d\n", i, j, sector, err); goto out; } /* Store the data block */ - err = sflc_dev_rwSector(dev, data_page, sector, WRITE); + err = sfold_dev_rwSector(dev, data_page, sector, WRITE); if (err) { pr_err("Could not write data block i=%d, j=%d at sector %llu; error %d\n", i, j, sector, err); goto out; @@ -334,8 +311,8 @@ out: kunmap(iv_page); kunmap(data_page); /* Free them */ - mempool_free(iv_page, sflc_pools_pagePool); - mempool_free(data_page, sflc_pools_pagePool); + mempool_free(iv_page, sfold_pools_pagePool); + mempool_free(data_page, sfold_pools_pagePool); return err; } @@ -344,10 +321,10 @@ out: * PRIVATE FUNCTIONS DEFINITIONS * *****************************************************/ -static s32 sflc_vol_mapSlice(sflc_Volume * vol, u32 lsi, int op) +static s32 sfold_vol_mapSlice(sfold_Volume * vol, u32 lsi, int op) { s32 psi; - sflc_Device * dev = vol->dev; + sfold_Device * dev = vol->dev; /* Lock the volume's forward map */ if (mutex_lock_interruptible(&vol->fmap_lock)) { @@ -356,7 +333,7 @@ static s32 sflc_vol_mapSlice(sflc_Volume * vol, u32 lsi, int op) } /* If slice is already mapped, just return the mapping */ - if (vol->fmap[lsi] != SFLC_VOL_FMAP_INVALID_PSI) { + if (vol->fmap[lsi] != SFOLD_VOL_FMAP_INVALID_PSI) { mutex_unlock(&vol->fmap_lock); return vol->fmap[lsi]; } @@ -377,7 +354,7 @@ static s32 sflc_vol_mapSlice(sflc_Volume * vol, u32 lsi, int op) } /* Get a free physical slice */ - psi = sflc_dev_getNextRandomFreePsi(dev); + psi = sfold_dev_getNextRandomFreePsi(dev); if (psi < 0) { pr_err("Could not get a random free physical slice; error %d\n", psi); mutex_unlock(&dev->slices_lock); @@ -389,7 +366,7 @@ static s32 sflc_vol_mapSlice(sflc_Volume * vol, u32 lsi, int op) vol->fmap[lsi] = psi; vol->mapped_slices += 1; /* And in the device's rmap */ - sflc_dev_markPsiTaken(dev, psi, vol->vol_idx); + sfold_dev_markPsiTaken(dev, psi, vol->vol_idx); /* Unlock both maps */ mutex_unlock(&dev->slices_lock); @@ -397,58 +374,3 @@ static s32 sflc_vol_mapSlice(sflc_Volume * vol, u32 lsi, int op) return psi; } - - -static int sflc_vol_reassignLsi(sflc_Volume *vol, u32 lsi, u32 old_psi) -{ - sflc_Device *dev = vol->dev; - s32 new_psi; -// void *vma; - int err; - -// /* Allocate array holding the raw PSI */ -// vma = vmalloc(SFLC_DEV_PHYS_SLICE_SIZE * SFLC_DEV_SECTOR_SIZE); -// if (!vma) { -// pr_err("Could not allocate VMA for raw PSI"); -// return -ENOMEM; -// } - - /* Sample new PSI */ - new_psi = sflc_dev_getNextRandomFreePsi(dev); - if (new_psi < 0) { - err = new_psi; - pr_err("Could not sample new PSI for evicted LSI; " - "error %d\n", err); - goto out; - } - -// /* Read PSI contents */ -// err = sflc_dev_rwPsi(dev, vma, old_psi, READ); -// if (err) { -// pr_err("Could not read PSI; error %d", err); -// goto out; -// } -// -// /* Write them to new location */ -// err = sflc_dev_rwPsi(dev, vma, new_psi, WRITE); -// if (err) { -// pr_err("Could not write PSI; error %d", err); -// goto out; -// } - - /* Assign */ - vol->fmap[lsi] = new_psi; - sflc_dev_markPsiTaken(dev, new_psi, vol->vol_idx); - vol->mapped_slices += 1; - - pr_notice("Volume %d reassign LSI %u -> PSI %u", - vol->vol_idx, lsi, new_psi); - - /* No prob */ - err = 0; - -out: -// vfree(vma); - return err; -} - diff --git a/dm-sflc/volume/io.c b/dm-sflc/src/old/volume/io.c similarity index 83% rename from dm-sflc/volume/io.c rename to dm-sflc/src/old/volume/io.c index 71ecc9c..6296834 100644 --- a/dm-sflc/volume/io.c +++ b/dm-sflc/src/old/volume/io.c @@ -29,10 +29,10 @@ * INCLUDE SECTION * *****************************************************/ -#include "volume.h" -#include "utils/pools.h" -#include "utils/workqueues.h" -#include "log/log.h" +#include "old/volume/volume.h" +#include "old/utils/pools.h" +#include "old/utils/workqueues.h" +#include "old/log/log.h" /***************************************************** * CONSTANTS * @@ -47,7 +47,7 @@ *****************************************************/ /* Remaps the underlying block device and the sector number */ -int sflc_vol_remapBioFast(sflc_Volume * vol, struct bio * bio) +int sfold_vol_remapBioFast(sfold_Volume * vol, struct bio * bio) { s64 phys_sector; int err; @@ -56,7 +56,7 @@ int sflc_vol_remapBioFast(sflc_Volume * vol, struct bio * bio) bio_set_dev(bio, vol->dev->bdev->bdev); /* Remap the starting sector (we don't care about PSI and off_in_slice). Also no slice allocation */ - phys_sector = sflc_vol_remapSector(vol, bio->bi_iter.bi_sector, READ, NULL, NULL); + phys_sector = sfold_vol_remapSector(vol, bio->bi_iter.bi_sector, READ, NULL, NULL); if (phys_sector < 0) { err = (int) phys_sector; pr_err("Could not remap sector; error %d\n", err); @@ -68,18 +68,18 @@ int sflc_vol_remapBioFast(sflc_Volume * vol, struct bio * bio) } /* Submits the bio to the device's workqueue */ -int sflc_vol_processBio(sflc_Volume * vol, struct bio * bio) +int sfold_vol_processBio(sfold_Volume * vol, struct bio * bio) { - sflc_vol_WriteWork * write_work; + sfold_vol_WriteWork * write_work; /* If it is a READ, no need to pass it through a workqueue */ if (bio_data_dir(bio) == READ) { - sflc_vol_doRead(vol, bio); + sfold_vol_doRead(vol, bio); return 0; } /* Allocate writeWork structure */ - write_work = mempool_alloc(sflc_pools_writeWorkPool, GFP_NOIO); + write_work = mempool_alloc(sfold_pools_writeWorkPool, GFP_NOIO); if (!write_work) { pr_err("Failed allocation of work structure\n"); return -ENOMEM; @@ -88,10 +88,10 @@ int sflc_vol_processBio(sflc_Volume * vol, struct bio * bio) /* Set fields */ write_work->vol = vol; write_work->orig_bio = bio; - INIT_WORK(&write_work->work, sflc_vol_doWrite); + INIT_WORK(&write_work->work, sfold_vol_doWrite); /* Enqueue */ - queue_work(sflc_queues_writeQueue, &write_work->work); + queue_work(sfold_queues_writeQueue, &write_work->work); return 0; } diff --git a/dm-sflc/volume/read.c b/dm-sflc/src/old/volume/read.c similarity index 72% rename from dm-sflc/volume/read.c rename to dm-sflc/src/old/volume/read.c index 2d64784..30e2927 100644 --- a/dm-sflc/volume/read.c +++ b/dm-sflc/src/old/volume/read.c @@ -32,10 +32,10 @@ * INCLUDE SECTION * *****************************************************/ -#include "volume.h" -#include "utils/pools.h" -#include "utils/workqueues.h" -#include "log/log.h" +#include "old/volume/volume.h" +#include "old/utils/pools.h" +#include "old/utils/workqueues.h" +#include "old/log/log.h" #include @@ -47,28 +47,28 @@ * PRIVATE FUNCTIONS PROTOTYPES * *****************************************************/ -static void sflc_vol_fillBioWithZeros(struct bio * orig_bio); -static void sflc_vol_readEndIo(struct bio * phys_bio); -static void sflc_vol_readEndIoBottomHalf(struct work_struct * work); -static int sflc_vol_decryptBio(sflc_Volume * vol, struct bio * orig_bio, u32 psi, u32 off_in_slice); -static int sflc_vol_fetchIv(sflc_Volume * vol, u8 * iv, u32 psi, u32 off_in_slice); +static void sfold_vol_fillBioWithZeros(struct bio * orig_bio); +static void sfold_vol_readEndIo(struct bio * phys_bio); +static void sfold_vol_readEndIoBottomHalf(struct work_struct * work); +static int sfold_vol_decryptBio(sfold_Volume * vol, struct bio * orig_bio, u32 psi, u32 off_in_slice); +static int sfold_vol_fetchIv(sfold_Volume * vol, u8 * iv, u32 psi, u32 off_in_slice); /***************************************************** * PUBLIC FUNCTIONS DEFINITIONS * *****************************************************/ -/* Executed in context from sflc_tgt_map() */ -void sflc_vol_doRead(sflc_Volume * vol, struct bio * bio) +/* Executed in context from sfold_tgt_map() */ +void sfold_vol_doRead(sfold_Volume * vol, struct bio * bio) { - sflc_Device * dev = vol->dev; + sfold_Device * dev = vol->dev; struct bio * orig_bio = bio; struct bio * phys_bio; s64 phys_sector; - sflc_vol_DecryptWork * dec_work; + sfold_vol_DecryptWork * dec_work; blk_status_t status; /* Allocate decryptWork structure */ - dec_work = mempool_alloc(sflc_pools_decryptWorkPool, GFP_NOIO); + dec_work = mempool_alloc(sfold_pools_decryptWorkPool, GFP_NOIO); if (!dec_work) { pr_err("Could not allocate decryptWork structure\n"); status = BLK_STS_IOERR; @@ -83,7 +83,7 @@ void sflc_vol_doRead(sflc_Volume * vol, struct bio * bio) we can decrypt in place. */ /* Shallow copy */ - phys_bio = bio_alloc_clone(dev->bdev->bdev, orig_bio, GFP_NOIO, &sflc_pools_bioset); + phys_bio = bio_alloc_clone(dev->bdev->bdev, orig_bio, GFP_NOIO, &sfold_pools_bioset); if (!phys_bio) { pr_err("Could not clone original bio\n"); status = BLK_STS_IOERR; @@ -91,11 +91,11 @@ void sflc_vol_doRead(sflc_Volume * vol, struct bio * bio) } /* Remap sector */ - phys_sector = sflc_vol_remapSector(vol, orig_bio->bi_iter.bi_sector, READ, &dec_work->psi, &dec_work->off_in_slice); + phys_sector = sfold_vol_remapSector(vol, orig_bio->bi_iter.bi_sector, READ, &dec_work->psi, &dec_work->off_in_slice); /* If -ENXIO, special case: stupid READ */ if (phys_sector == -ENXIO) { pr_debug("Stupid READ. Returning all zeros\n"); - sflc_vol_fillBioWithZeros(orig_bio); + sfold_vol_fillBioWithZeros(orig_bio); status = BLK_STS_OK; goto err_stupid_read; } @@ -113,7 +113,7 @@ void sflc_vol_doRead(sflc_Volume * vol, struct bio * bio) dec_work->orig_bio = orig_bio; dec_work->phys_bio = phys_bio; /* Set fields for the endio */ - phys_bio->bi_end_io = sflc_vol_readEndIo; + phys_bio->bi_end_io = sfold_vol_readEndIo; phys_bio->bi_private = dec_work; /* Only submit the physical bio */ @@ -127,7 +127,7 @@ err_stupid_read: bio_put(phys_bio); err_clone_orig_bio: bio_put(orig_bio); - mempool_free(dec_work, sflc_pools_decryptWorkPool); + mempool_free(dec_work, sfold_pools_decryptWorkPool); err_alloc_dec_work: orig_bio->bi_status = status; @@ -139,42 +139,42 @@ err_alloc_dec_work: * PRIVATE FUNCTIONS DEFINITIONS * *****************************************************/ -static void sflc_vol_fillBioWithZeros(struct bio * orig_bio) +static void sfold_vol_fillBioWithZeros(struct bio * orig_bio) { struct bio_vec bvl = bio_iovec(orig_bio); void * sector_ptr = kmap(bvl.bv_page) + bvl.bv_offset; - memset(sector_ptr, 0, SFLC_DEV_SECTOR_SIZE); - bio_advance(orig_bio, SFLC_DEV_SECTOR_SIZE); + memset(sector_ptr, 0, SFOLD_DEV_SECTOR_SIZE); + bio_advance(orig_bio, SFOLD_DEV_SECTOR_SIZE); kunmap(bvl.bv_page); return; } /* Pushes all the decryption work to a workqueue bottom half */ -static void sflc_vol_readEndIo(struct bio * phys_bio) +static void sfold_vol_readEndIo(struct bio * phys_bio) { - sflc_vol_DecryptWork * dec_work = phys_bio->bi_private; + sfold_vol_DecryptWork * dec_work = phys_bio->bi_private; /* Init work structure */ - INIT_WORK(&dec_work->work, sflc_vol_readEndIoBottomHalf); + INIT_WORK(&dec_work->work, sfold_vol_readEndIoBottomHalf); /* Enqueue it */ - queue_work(sflc_queues_decryptQueue, &dec_work->work); + queue_work(sfold_queues_decryptQueue, &dec_work->work); return; } -static void sflc_vol_readEndIoBottomHalf(struct work_struct * work) +static void sfold_vol_readEndIoBottomHalf(struct work_struct * work) { - sflc_vol_DecryptWork * dec_work = container_of(work, sflc_vol_DecryptWork, work); - sflc_Volume * vol = dec_work->vol; + sfold_vol_DecryptWork * dec_work = container_of(work, sfold_vol_DecryptWork, work); + sfold_Volume * vol = dec_work->vol; struct bio * orig_bio = dec_work->orig_bio; struct bio * phys_bio = dec_work->phys_bio; blk_status_t status = phys_bio->bi_status; int err; /* Decrypt the physical bio and advance the original bio */ - err = sflc_vol_decryptBio(vol, orig_bio, dec_work->psi, dec_work->off_in_slice); + err = sfold_vol_decryptBio(vol, orig_bio, dec_work->psi, dec_work->off_in_slice); if (err) { pr_err("Could not decrypt bio; error %d\n", err); status = BLK_STS_IOERR; @@ -189,19 +189,19 @@ static void sflc_vol_readEndIoBottomHalf(struct work_struct * work) /* Free the physical bio */ bio_put(phys_bio); /* Free the work item */ - mempool_free(dec_work, sflc_pools_decryptWorkPool); + mempool_free(dec_work, sfold_pools_decryptWorkPool); return; } /* Decrypts the content of the physical bio, and at the same time it advances the original bio */ -static int sflc_vol_decryptBio(sflc_Volume * vol, struct bio * orig_bio, u32 psi, u32 off_in_slice) +static int sfold_vol_decryptBio(sfold_Volume * vol, struct bio * orig_bio, u32 psi, u32 off_in_slice) { - u8 iv[SFLC_SK_IV_LEN]; + u8 iv[SFOLD_SK_IV_LEN]; int err; /* Fetch IV */ - err = sflc_vol_fetchIv(vol, iv, psi, off_in_slice); + err = sfold_vol_fetchIv(vol, iv, psi, off_in_slice); if (err) { pr_err("Could not fetch IV; error %d\n", err); return err; @@ -210,7 +210,7 @@ static int sflc_vol_decryptBio(sflc_Volume * vol, struct bio * orig_bio, u32 psi /* Decrypt sector in place */ struct bio_vec bvl = bio_iovec(orig_bio); void * sector_ptr = kmap(bvl.bv_page) + bvl.bv_offset; - err = sflc_sk_decrypt(vol->skctx, sector_ptr, sector_ptr, SFLC_DEV_SECTOR_SIZE, iv); + err = sfold_sk_decrypt(vol->skctx, sector_ptr, sector_ptr, SFOLD_DEV_SECTOR_SIZE, iv); kunmap(bvl.bv_page); if (err) { pr_err("Error while decrypting sector: %d\n", err); @@ -218,19 +218,19 @@ static int sflc_vol_decryptBio(sflc_Volume * vol, struct bio * orig_bio, u32 psi } /* Advance original bio by one sector */ - bio_advance(orig_bio, SFLC_DEV_SECTOR_SIZE); + bio_advance(orig_bio, SFOLD_DEV_SECTOR_SIZE); return 0; } -static int sflc_vol_fetchIv(sflc_Volume * vol, u8 * iv, u32 psi, u32 off_in_slice) +static int sfold_vol_fetchIv(sfold_Volume * vol, u8 * iv, u32 psi, u32 off_in_slice) { - sflc_Device * dev = vol->dev; + sfold_Device * dev = vol->dev; u8 * iv_block; int err; /* Acquire a reference to the whole relevant IV block */ - iv_block = sflc_dev_getIvBlockRef(dev, psi, READ); + iv_block = sfold_dev_getIvBlockRef(dev, psi, READ); if (IS_ERR(iv_block)) { err = PTR_ERR(iv_block); pr_err("Could not acquire reference to IV block; error %ld\n", PTR_ERR(iv_block)); @@ -238,10 +238,10 @@ static int sflc_vol_fetchIv(sflc_Volume * vol, u8 * iv, u32 psi, u32 off_in_slic } /* Copy the relevant portion */ - memcpy(iv, iv_block + (off_in_slice * SFLC_SK_IV_LEN), SFLC_SK_IV_LEN); + memcpy(iv, iv_block + (off_in_slice * SFOLD_SK_IV_LEN), SFOLD_SK_IV_LEN); /* Release reference to the IV block */ - err = sflc_dev_putIvBlockRef(dev, psi); + err = sfold_dev_putIvBlockRef(dev, psi); if (err) { pr_err("Could not release reference to IV block; error %d\n", err); goto err_put_iv_block_ref; diff --git a/dm-sflc/volume/volume.c b/dm-sflc/src/old/volume/volume.c similarity index 56% rename from dm-sflc/volume/volume.c rename to dm-sflc/src/old/volume/volume.c index ec4dedc..862d8f5 100644 --- a/dm-sflc/volume/volume.c +++ b/dm-sflc/src/old/volume/volume.c @@ -29,8 +29,9 @@ * INCLUDE SECTION * *****************************************************/ -#include "volume.h" -#include "log/log.h" +#include "old/volume/volume.h" +#include "old/utils/string.h" +#include "old/log/log.h" #include @@ -39,35 +40,69 @@ * PUBLIC FUNCTIONS DEFINITIONS * *****************************************************/ -/* Creates volume and adds it to the device. Returns an ERR_PTR() if unsuccessful */ -sflc_Volume * sflc_vol_create(struct dm_target *ti, sflc_Device *dev, int vol_idx, u8 * enckey) +/** + * Creates volume. Returns an ERR_PTR() if unsuccessful + * Arguments: + * argv[0]: Shufflecake mode: legacy/lite + * argv[1]: Shufflecake-unique device ID + * argv[2]: path to underlying physical device + * argv[3]: volume index within the device + * argv[4]: number of 1 MB slices in the underlying device + * argv[5]: 32-byte encryption key (hex-encoded) + */ +sfold_Volume * sfold_vol_create(struct dm_target * ti, sfold_Device* dev, + int argc, char **argv, struct kobject *kobj) { - sflc_Volume * vol; + sfold_Volume * vol; + int vol_idx; + u8 enckey[SFOLD_SK_KEY_LEN]; int err; - pr_debug("Called to create sflc_Volume #%d on Device %s\n", vol_idx, dev->bdev_path); - /* Allocate volume */ - vol = kzalloc(sizeof(sflc_Volume), GFP_KERNEL); + vol = kzalloc(sizeof(sfold_Volume), GFP_KERNEL); if (!vol) { - pr_err("Could not allocate %lu bytes for sflc_Volume\n", sizeof(sflc_Volume)); + pr_err("Could not allocate %lu bytes for sfold_Volume\n", sizeof(sfold_Volume)); err = -ENOMEM; goto err_alloc_vol; } + /* Parse args */ + if (argc != 6) { + pr_err("Wrong argument count"); + err = -EINVAL; + goto err_parse; + } + if (sscanf(argv[3], "%u", &vol_idx) != 1) { + pr_err("Could not decode tot_slices\n"); + err = -EINVAL; + goto err_parse; + } + /* Decode the encryption key */ + if (strlen(argv[5]) != 2 * SFOLD_SK_KEY_LEN) { + pr_err("Hexadecimal key (length %lu): %s\n", strlen(argv[5]), argv[5]); + err = -EINVAL; + goto err_parse; + } + err = sfold_str_hexDecode(argv[5], enckey); + if (err) { + pr_err("Could not decode hexadecimal encryption key"); + err = -EINVAL; + goto err_parse; + } + /* Set volume name */ - sprintf(vol->vol_name, "sflc_%lu_%d", dev->dev_id, vol_idx); + sprintf(vol->vol_name, "sflc_%u_%d", dev->dev_id, vol_idx); /* Sysfs stuff */ - vol->kvol = sflc_sysfs_volCreateAndAdd(vol); - if (IS_ERR(vol->kvol)) { - err = PTR_ERR(vol->kvol); - pr_err("Could not create sysfs entry; error %d\n", err); + vol->kobj_parent = kobj; + err = sfold_sysfs_add_volume(vol); + if (err) { + pr_err("Could not add volume to sysfs; error %d\n", err); goto err_sysfs; } /* Backing device */ - if (!sflc_dev_addVolume(dev, vol, vol_idx)) { + if (!sfold_dev_addVolume(dev, vol, vol_idx)) { pr_err("Could not add volume to device\n"); err = -EINVAL; goto err_add_to_dev; @@ -76,7 +111,7 @@ sflc_Volume * sflc_vol_create(struct dm_target *ti, sflc_Device *dev, int vol_id vol->vol_idx = vol_idx; /* Crypto */ - vol->skctx = sflc_sk_createContext(enckey); + vol->skctx = sfold_sk_createContext(enckey); if (IS_ERR(vol->skctx)) { err = PTR_ERR(vol->skctx); pr_err("Could not create crypto context\n"); @@ -97,38 +132,52 @@ sflc_Volume * sflc_vol_create(struct dm_target *ti, sflc_Device *dev, int vol_id /* Initialise fmap */ pr_notice("Volume opening for volume %s: loading fmap from header\n", vol->vol_name); - err = sflc_vol_loadFmap(vol); + err = sfold_vol_loadFmap(vol); if (err) { pr_err("Could not load position map; error %d\n", err); goto err_load_fmap; } pr_debug("Successfully loaded position map for volume %s\n", vol->vol_name); + + /* Tell DM we want one SFLC sector at a time */ + ti->max_io_len = SFOLD_DEV_SECTOR_SCALE; + /* Enable REQ_OP_FLUSH bios */ + ti->num_flush_bios = 1; + /* Disable REQ_OP_WRITE_ZEROES and REQ_OP_SECURE_ERASE (can't be passed through as + they would break deniability, and they would be too complicated to handle individually) */ + ti->num_secure_erase_bios = 0; + ti->num_write_zeroes_bios = 0; + /* Momentarily disable REQ_OP_DISCARD_BIOS + TODO: will need to support them to release slice mappings */ + ti->num_discard_bios = 0; + return vol; err_load_fmap: vfree(vol->fmap); err_alloc_fmap: - sflc_sk_destroyContext(vol->skctx); + sfold_sk_destroyContext(vol->skctx); err_create_skctx: - sflc_dev_removeVolume(vol->dev, vol->vol_idx); + sfold_dev_removeVolume(vol->dev, vol->vol_idx); err_add_to_dev: - sflc_sysfs_putVol(vol->kvol); + sfold_sysfs_remove_volume(vol); err_sysfs: +err_parse: kfree(vol); err_alloc_vol: return ERR_PTR(err); } /* Removes the volume from the device and frees it. */ -void sflc_vol_destroy(struct dm_target * ti, sflc_Volume * vol) +void sfold_vol_destroy(sfold_Volume * vol) { int err; /* Store fmap */ pr_notice("Going to store position map of volume %s\n", vol->vol_name); - err = sflc_vol_storeFmap(vol); + err = sfold_vol_storeFmap(vol); if (err) { pr_err("Could not store position map; error %d\n", err); } @@ -137,13 +186,13 @@ void sflc_vol_destroy(struct dm_target * ti, sflc_Volume * vol) vfree(vol->fmap); /* Skctx */ - sflc_sk_destroyContext(vol->skctx); + sfold_sk_destroyContext(vol->skctx); /* Remove from device */ - sflc_dev_removeVolume(vol->dev, vol->vol_idx); + sfold_dev_removeVolume(vol->dev, vol->vol_idx); /* Destroy sysfs entries */ - sflc_sysfs_putVol(vol->kvol); + sfold_sysfs_remove_volume(vol); /* Free volume structure */ kfree(vol); diff --git a/dm-sflc/volume/volume.h b/dm-sflc/src/old/volume/volume.h similarity index 70% rename from dm-sflc/volume/volume.h rename to dm-sflc/src/old/volume/volume.h index 401cd97..38faf40 100644 --- a/dm-sflc/volume/volume.h +++ b/dm-sflc/src/old/volume/volume.h @@ -26,8 +26,8 @@ * a "real" device represented by a device. */ -#ifndef _SFLC_VOLUME_VOLUME_H_ -#define _SFLC_VOLUME_VOLUME_H_ +#ifndef _SFOLD_VOLUME_VOLUME_H_ +#define _SFOLD_VOLUME_VOLUME_H_ /***************************************************** @@ -36,9 +36,9 @@ /* Necessary since device.h, volume.h, and sysfs.h all include each other */ -typedef struct sflc_vol_write_work_s sflc_vol_WriteWork; -typedef struct sflc_vol_decrypt_work_s sflc_vol_DecryptWork; -typedef struct sflc_volume_s sflc_Volume; +typedef struct sfold_vol_write_work_s sfold_vol_WriteWork; +typedef struct sfold_vol_decrypt_work_s sfold_vol_DecryptWork; +typedef struct sfold_volume_s sfold_Volume; /***************************************************** @@ -47,9 +47,9 @@ typedef struct sflc_volume_s sflc_Volume; #include -#include "device/device.h" -#include "crypto/symkey/symkey.h" -#include "sysfs/sysfs.h" +#include "old/sflc_old.h" +#include "old/device/device.h" +#include "old/crypto/symkey/symkey.h" /***************************************************** @@ -57,26 +57,26 @@ typedef struct sflc_volume_s sflc_Volume; *****************************************************/ /* A single header data block contains 1024 fmap mappings */ -#define SFLC_VOL_HEADER_MAPPINGS_PER_BLOCK (SFLC_DEV_SECTOR_SIZE / sizeof(u32)) +#define SFOLD_VOL_HEADER_MAPPINGS_PER_BLOCK (SFOLD_DEV_SECTOR_SIZE / sizeof(u32)) /* We split the volume's logical addressing space into 1 MB slices */ -#define SFLC_VOL_LOG_SLICE_SIZE 256 // In 4096-byte sectors +#define SFOLD_VOL_LOG_SLICE_SIZE 256 // In 4096-byte sectors /* Value marking an LSI as unassigned */ -#define SFLC_VOL_FMAP_INVALID_PSI 0xFFFFFFFFU +#define SFOLD_VOL_FMAP_INVALID_PSI 0xFFFFFFFFU /* The volume name is "sflc--" */ -#define SFLC_VOL_NAME_MAX_LEN 12 +#define SFOLD_VOL_NAME_MAX_LEN 12 /***************************************************** * TYPES * *****************************************************/ -struct sflc_vol_write_work_s +struct sfold_vol_write_work_s { /* Essential information */ - sflc_Volume * vol; + sfold_Volume * vol; struct bio * orig_bio; /* Write requests need to allocate own page */ @@ -86,10 +86,10 @@ struct sflc_vol_write_work_s struct work_struct work; }; -struct sflc_vol_decrypt_work_s +struct sfold_vol_decrypt_work_s { /* Essential information */ - sflc_Volume * vol; + sfold_Volume * vol; struct bio * orig_bio; struct bio * phys_bio; @@ -101,15 +101,15 @@ struct sflc_vol_decrypt_work_s struct work_struct work; }; -struct sflc_volume_s +struct sfold_volume_s { - /* Name of the volume, sflc--*/ - char vol_name[SFLC_VOL_NAME_MAX_LEN + 1]; + /* Name of the volume, sflc__*/ + char vol_name[SFOLD_VOL_NAME_MAX_LEN + 1]; /* Backing device */ - sflc_Device * dev; + sfold_Device * dev; /* Index of this volume within the device's volume array */ - int vol_idx; + u32 vol_idx; /* Forward position map */ struct mutex fmap_lock; @@ -117,11 +117,11 @@ struct sflc_volume_s /* Stats on the fmap */ u32 mapped_slices; - /* Sysfs stuff */ - sflc_sysfs_Volume * kvol; + /* Parent sysfs directory */ + struct kobject *kobj_parent; /* Crypto */ - sflc_sk_Context * skctx; + sfold_sk_Context * skctx; }; @@ -130,27 +130,28 @@ struct sflc_volume_s *****************************************************/ /* Creates volume and adds it to the device. Returns an ERR_PTR() if unsuccessful */ -sflc_Volume * sflc_vol_create(struct dm_target * ti, sflc_Device* dev, int vol_idx, u8 * enckey); +sfold_Volume * sfold_vol_create(struct dm_target * ti, sfold_Device* dev, + int argc, char **argv, struct kobject *kobj); /* Removes the volume from the device and frees it. */ -void sflc_vol_destroy(struct dm_target * ti, sflc_Volume * vol); +void sfold_vol_destroy(sfold_Volume * vol); /* Remaps the underlying block device and the sector number */ -int sflc_vol_remapBioFast(sflc_Volume * vol, struct bio * bio); +int sfold_vol_remapBioFast(sfold_Volume * vol, struct bio * bio); /* Processes the bio in the normal indirection+crypto way */ -int sflc_vol_processBio(sflc_Volume * vol, struct bio * bio); +int sfold_vol_processBio(sfold_Volume * vol, struct bio * bio); /* Executed in top half */ -void sflc_vol_doRead(sflc_Volume * vol, struct bio * bio); +void sfold_vol_doRead(sfold_Volume * vol, struct bio * bio); /* Executed in bottom half */ -void sflc_vol_doWrite(struct work_struct * work); +void sfold_vol_doWrite(struct work_struct * work); /* Maps a logical 512-byte sector to a physical 512-byte sector. Returns < 0 if error. * Specifically, if op == READ, and the logical slice is unmapped, -ENXIO is returned. */ -s64 sflc_vol_remapSector(sflc_Volume * vol, sector_t log_sector, int op, u32 * psi_out, u32 * off_in_slice_out); +s64 sfold_vol_remapSector(sfold_Volume * vol, sector_t log_sector, int op, u32 * psi_out, u32 * off_in_slice_out); /* Loads (and decrypts) the position map from the volume's header */ -int sflc_vol_loadFmap(sflc_Volume * vol); +int sfold_vol_loadFmap(sfold_Volume * vol); /* Stores (and encrypts) the position map to the volume's header */ -int sflc_vol_storeFmap(sflc_Volume * vol); +int sfold_vol_storeFmap(sfold_Volume * vol); -#endif /* _SFLC_VOLUME_VOLUME_H_ */ +#endif /* _SFOLD_VOLUME_VOLUME_H_ */ diff --git a/dm-sflc/volume/write.c b/dm-sflc/src/old/volume/write.c similarity index 77% rename from dm-sflc/volume/write.c rename to dm-sflc/src/old/volume/write.c index d6903d9..bbf113c 100644 --- a/dm-sflc/volume/write.c +++ b/dm-sflc/src/old/volume/write.c @@ -32,10 +32,10 @@ * INCLUDE SECTION * *****************************************************/ -#include "volume.h" -#include "crypto/rand/rand.h" -#include "utils/pools.h" -#include "log/log.h" +#include "old/volume/volume.h" +#include "old/crypto/rand/rand.h" +#include "old/utils/pools.h" +#include "old/log/log.h" #include @@ -47,9 +47,9 @@ * PRIVATE FUNCTIONS PROTOTYPES * *****************************************************/ -static int sflc_vol_encryptOrigBio(sflc_Volume * vol, struct bio * orig_bio, struct bio * phys_bio, u32 psi, u32 off_in_slice); -static int sflc_vol_sampleAndWriteIv(sflc_Volume * vol, u8 * iv, u32 psi, u32 off_in_slice); -static void sflc_vol_writeEndIo(struct bio * phys_bio); +static int sfold_vol_encryptOrigBio(sfold_Volume * vol, struct bio * orig_bio, struct bio * phys_bio, u32 psi, u32 off_in_slice); +static int sfold_vol_sampleAndWriteIv(sfold_Volume * vol, u8 * iv, u32 psi, u32 off_in_slice); +static void sfold_vol_writeEndIo(struct bio * phys_bio); /***************************************************** * PRIVATE VARIABLES * @@ -60,11 +60,11 @@ static void sflc_vol_writeEndIo(struct bio * phys_bio); *****************************************************/ /* Executed in workqueue bottom half */ -void sflc_vol_doWrite(struct work_struct * work) +void sfold_vol_doWrite(struct work_struct * work) { - sflc_vol_WriteWork * write_work = container_of(work, sflc_vol_WriteWork, work); - sflc_Volume * vol = write_work->vol; - sflc_Device * dev = vol->dev; + sfold_vol_WriteWork * write_work = container_of(work, sfold_vol_WriteWork, work); + sfold_Volume * vol = write_work->vol; + sfold_Device * dev = vol->dev; struct bio * orig_bio = write_work->orig_bio; struct bio * phys_bio; s64 phys_sector; @@ -80,14 +80,14 @@ void sflc_vol_doWrite(struct work_struct * work) non-owned bio's. So we need our own. */ /* Allocate an empty bio */ - phys_bio = bio_alloc_bioset(dev->bdev->bdev, bio_segments(orig_bio), orig_bio->bi_opf, GFP_NOIO, &sflc_pools_bioset); + phys_bio = bio_alloc_bioset(dev->bdev->bdev, bio_segments(orig_bio), orig_bio->bi_opf, GFP_NOIO, &sfold_pools_bioset); if (!phys_bio) { pr_err("Could not allocate bio\n"); goto err_alloc_phys_bio; } /* Remap sector */ - phys_sector = sflc_vol_remapSector(vol, orig_bio->bi_iter.bi_sector, WRITE, &psi, &off_in_slice); + phys_sector = sfold_vol_remapSector(vol, orig_bio->bi_iter.bi_sector, WRITE, &psi, &off_in_slice); if (phys_sector < 0) { pr_err("Could not remap sector for physical bio; error %d\n", (int) phys_sector); goto err_remap_sector; @@ -95,11 +95,11 @@ void sflc_vol_doWrite(struct work_struct * work) phys_bio->bi_iter.bi_sector = phys_sector; /* Set fields for the endio */ - phys_bio->bi_end_io = sflc_vol_writeEndIo; + phys_bio->bi_end_io = sfold_vol_writeEndIo; phys_bio->bi_private = write_work; /* Encrypt the original bio into the physical bio (newly-allocated pages) */ - int err = sflc_vol_encryptOrigBio(vol, orig_bio, phys_bio, psi, off_in_slice); + int err = sfold_vol_encryptOrigBio(vol, orig_bio, phys_bio, psi, off_in_slice); if (err) { pr_err("Could not encrypt original bio; error %d\n", err); goto err_encrypt_orig_bio; @@ -119,7 +119,6 @@ err_alloc_phys_bio: orig_bio->bi_status = BLK_STS_IOERR; bio_endio(orig_bio); - mempool_free(write_work, sflc_pools_writeWorkPool); return; } @@ -128,14 +127,14 @@ err_alloc_phys_bio: *****************************************************/ /* Encrypts the contents of the original bio into newly-allocated pages for the physical bio */ -static int sflc_vol_encryptOrigBio(sflc_Volume * vol, struct bio * orig_bio, struct bio * phys_bio, u32 psi, u32 off_in_slice) +static int sfold_vol_encryptOrigBio(sfold_Volume * vol, struct bio * orig_bio, struct bio * phys_bio, u32 psi, u32 off_in_slice) { - sflc_vol_WriteWork * write_work = phys_bio->bi_private; - u8 iv[SFLC_SK_IV_LEN]; + sfold_vol_WriteWork * write_work = phys_bio->bi_private; + u8 iv[SFOLD_SK_IV_LEN]; int err; /* Allocate new page for the physical bio */ - write_work->page = mempool_alloc(sflc_pools_pagePool, GFP_NOIO); + write_work->page = mempool_alloc(sfold_pools_pagePool, GFP_NOIO); if (!write_work->page) { pr_err("Could not allocate page\n"); err = -ENOMEM; @@ -143,14 +142,14 @@ static int sflc_vol_encryptOrigBio(sflc_Volume * vol, struct bio * orig_bio, str } /* Add it to physical bio */ - if (!bio_add_page(phys_bio, write_work->page, SFLC_DEV_SECTOR_SIZE, 0)) { + if (!bio_add_page(phys_bio, write_work->page, SFOLD_DEV_SECTOR_SIZE, 0)) { pr_err("Catastrophe. Could not add page to copy bio. WTF?\n"); err = -EIO; goto err_bio_add_page; } /* Sample a random IV and write it in the IV block */ - err = sflc_vol_sampleAndWriteIv(vol, iv, psi, off_in_slice); + err = sfold_vol_sampleAndWriteIv(vol, iv, psi, off_in_slice); if (err) { pr_err("Could not sample and write IV; error %d\n", err); err = -EIO; @@ -161,7 +160,7 @@ static int sflc_vol_encryptOrigBio(sflc_Volume * vol, struct bio * orig_bio, str struct bio_vec bvl = bio_iovec(orig_bio); void * enc_sector_ptr = kmap(write_work->page); void * plain_sector_ptr = kmap(bvl.bv_page) + bvl.bv_offset; - err = sflc_sk_encrypt(vol->skctx, plain_sector_ptr, enc_sector_ptr, SFLC_DEV_SECTOR_SIZE, iv); + err = sfold_sk_encrypt(vol->skctx, plain_sector_ptr, enc_sector_ptr, SFOLD_DEV_SECTOR_SIZE, iv); kunmap(bvl.bv_page); kunmap(write_work->page); if (err) { @@ -175,21 +174,21 @@ static int sflc_vol_encryptOrigBio(sflc_Volume * vol, struct bio * orig_bio, str err_encrypt: err_sample_and_write_iv: err_bio_add_page: - mempool_free(write_work->page, sflc_pools_pagePool); + mempool_free(write_work->page, sfold_pools_pagePool); err_alloc_page: return err; } /* Allocates the io_work's IV (will need to be freed afterwards), fills it with random bytes, and writes it into the IV block pointed by the io_work's PSI and off_in_slice. */ -static int sflc_vol_sampleAndWriteIv(sflc_Volume * vol, u8 * iv, u32 psi, u32 off_in_slice) +static int sfold_vol_sampleAndWriteIv(sfold_Volume * vol, u8 * iv, u32 psi, u32 off_in_slice) { - sflc_Device * dev = vol->dev; + sfold_Device * dev = vol->dev; u8 * iv_block; int err; /* Sample IV */ - err = sflc_rand_getBytes(iv, SFLC_SK_IV_LEN); + err = sfold_rand_getBytes(iv, SFOLD_SK_IV_LEN); if (err) { pr_err("Could not sample IV; error %d\n", err); err = -EIO; @@ -197,7 +196,7 @@ static int sflc_vol_sampleAndWriteIv(sflc_Volume * vol, u8 * iv, u32 psi, u32 of } /* Acquire a reference to the whole relevant IV block */ - iv_block = sflc_dev_getIvBlockRef(dev, psi, WRITE); + iv_block = sfold_dev_getIvBlockRef(dev, psi, WRITE); if (IS_ERR(iv_block)) { err = PTR_ERR(iv_block); pr_err("Could not acquire reference to IV block; error %d\n", err); @@ -205,10 +204,10 @@ static int sflc_vol_sampleAndWriteIv(sflc_Volume * vol, u8 * iv, u32 psi, u32 of } /* Copy it into the relevant portion of the block */ - memcpy(iv_block + (off_in_slice * SFLC_SK_IV_LEN), iv, SFLC_SK_IV_LEN); + memcpy(iv_block + (off_in_slice * SFOLD_SK_IV_LEN), iv, SFOLD_SK_IV_LEN); /* Release reference to the IV block */ - err = sflc_dev_putIvBlockRef(dev, psi); + err = sfold_dev_putIvBlockRef(dev, psi); if (err) { pr_err("Could not release reference to IV block; error %d\n", err); goto err_put_iv_block_ref; @@ -223,9 +222,9 @@ err_sample_iv: return err; } -static void sflc_vol_writeEndIo(struct bio * phys_bio) +static void sfold_vol_writeEndIo(struct bio * phys_bio) { - sflc_vol_WriteWork * write_work = phys_bio->bi_private; + sfold_vol_WriteWork * write_work = phys_bio->bi_private; struct bio * orig_bio = write_work->orig_bio; unsigned completed_bytes; @@ -246,8 +245,8 @@ static void sflc_vol_writeEndIo(struct bio * phys_bio) if (unlikely(page_ref_count(write_work->page) != 1)) { pr_err("WTF: page_ref_count = %d\n", page_ref_count(write_work->page)); } - mempool_free(write_work->page, sflc_pools_pagePool); - mempool_free(write_work, sflc_pools_writeWorkPool); + mempool_free(write_work->page, sfold_pools_pagePool); + mempool_free(write_work, sfold_pools_writeWorkPool); return; } diff --git a/dm-sflc/src/sflc.c b/dm-sflc/src/sflc.c new file mode 100644 index 0000000..67676b2 --- /dev/null +++ b/dm-sflc/src/sflc.c @@ -0,0 +1,293 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +#include +#include +#include + +#include "sflc.h" +#include "old/sflc_old.h" +#include "lite/sflc_lite.h" + +#include + + +// Global variables +DEFINE_MUTEX(sflc_alldevs_lock); +struct sflc_device **sflc_alldevs = NULL; +u32 sflc_free_devid = 0; /* The lowest free devID */ + + +/* Add a device to the global array, and advance next_dev_id */ +static int sflc_add_device_global(u32 dev_id, struct sflc_device *sdev) +{ + int i; + + if (mutex_lock_interruptible(&sflc_alldevs_lock)) + return -ERESTARTSYS; + + /* Check for dev_id conflict, possible because a read() to next_dev_id + * in sysfs can return the same value to two processes */ + if (sflc_alldevs[dev_id]) { + mutex_unlock(&sflc_alldevs_lock); + DMERR("A device with this ID already exists. Retry"); + return -EINVAL; + } + // Add to the global array, and advance free_devid + sflc_alldevs[dev_id] = sdev; + for (i = sflc_free_devid; i < SFLC_MAX_DEVS && sflc_alldevs[i]; i++); + sflc_free_devid = i; + + mutex_unlock(&sflc_alldevs_lock); + + return 0; +} + +/* Remove a device from the global array, and update next_dev_id */ +static void sflc_remove_device_global(u32 dev_id) +{ + if (mutex_lock_interruptible(&sflc_alldevs_lock)) + return; + sflc_alldevs[dev_id] = NULL; + if (dev_id < sflc_free_devid) + sflc_free_devid = dev_id; + mutex_unlock(&sflc_alldevs_lock); +} + + +/* + * Create volume and, if not existent, the underlying device. + * Arguments: + * argv[0]: Shufflecake mode: legacy/lite + * argv[1]: Shufflecake-unique device ID + * argv[2]: path to underlying physical device + * argv[3]: volume index within the device + * argv[4:]: mode-specific parameters + */ +static int sflc_ctr(struct dm_target *ti, unsigned int argc, char **argv) +{ + u32 dev_id; + u32 vol_idx; + struct sflc_device *sdev; + struct sflc_volume *svol; + int err; + + /* Parse arguments */ + if (argc < 4) { + ti->error = "Invalid argument count"; + return -EINVAL; + } + if (sscanf(argv[1], "%u", &dev_id) != 1) { + ti->error = "Could not decode device ID"; + return -EINVAL; + } + if (sscanf(argv[3], "%u", &vol_idx) != 1) { + ti->error = "Could not decode volume index"; + return -EINVAL; + } + /* Sanity checks */ + if (dev_id >= SFLC_MAX_DEVS) { + ti->error = "Device ID out of bounds"; + return -EINVAL; + } + if (vol_idx >= SFLC_DEV_MAX_VOLUMES) { + ti->error = "Volume index out of bounds"; + return -EINVAL; + } + + /* Create device, if this is the first volume, otherwise retrieve it */ + if (vol_idx == 0) { + sdev = sflc_dev_create(ti, argc, argv); + if (IS_ERR(sdev)) { + ti->error = "Could not instantiate device"; + return PTR_ERR(sdev); + } + /* Insert in global array */ + err = sflc_add_device_global(dev_id, sdev); + if (err) { + ti->error = "Could not add device to global array"; + goto bad_dev_global; + } + } else { + if (mutex_lock_interruptible(&sflc_alldevs_lock)) + return -ERESTARTSYS; + sdev = sflc_alldevs[dev_id]; + mutex_unlock(&sflc_alldevs_lock); + + if (!sdev) { + ti->error = "Could not find device with specified ID"; + return -EINVAL; + } + } + + /* Create volume */ + svol = sflc_vol_create(sdev, ti, argc, argv); + if (IS_ERR(svol)) { + ti->error = "Could not instantiate volume"; + err = PTR_ERR(svol); + goto bad_vol_create; + } + /* We expect ->ctr() calls to be strictly sequential, so we don't need locking */ + sdev->nr_volumes++; + + ti->private = svol; + + return 0; + + +bad_vol_create: + if (vol_idx == 0) { + sflc_remove_device_global(dev_id); +bad_dev_global: + sflc_dev_destroy(sdev); + } + return err; +} + + +/* Destroy volume and, if needed, the underlying device */ +static void sflc_dtr(struct dm_target *ti) +{ + struct sflc_volume *svol = ti->private; + struct sflc_device *sdev = svol->sdev; + + sflc_vol_destroy(svol); + /* We expect ->dtr() calls to be strictly sequential, so we don't need locking */ + sdev->nr_volumes--; + + if (sdev->nr_volumes == 0) { + sflc_remove_device_global(sdev->dev_id); + sflc_dev_destroy(sdev); + } + + return; +} + + +static int sflc_map(struct dm_target *ti, struct bio *bio) +{ + struct sflc_volume *svol = ti->private; + return svol->tt->map(ti, bio); +} + +static void sflc_io_hints(struct dm_target *ti, struct queue_limits *limits) +{ + struct sflc_volume *svol = ti->private; + svol->tt->io_hints(ti, limits); + return; +} + +static int sflc_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data) +{ + struct sflc_volume *svol = ti->private; + return svol->tt->iterate_devices(ti, fn, data); +} + + +/* + *---------------------------- + * Kernel module + *---------------------------- + */ + +static struct target_type sflc_target_type = { + .name = SFLC_TARGET_NAME, + .version = {SFLC_VER_MAJOR, SFLC_VER_MINOR, SFLC_VER_REVISION}, + .module = THIS_MODULE, + .ctr = sflc_ctr, + .dtr = sflc_dtr, + .map = sflc_map, + .io_hints = sflc_io_hints, + .iterate_devices = sflc_iterate_devices, +}; + + +/* Module entry point */ +static int sflc_init(void) +{ + int ret; + + sflc_alldevs = vzalloc(SFLC_MAX_DEVS * sizeof(*sflc_alldevs)); + if (!sflc_alldevs) { + DMERR("Could not allocate sflc_alldevs"); + ret = -ENOMEM; + goto bad_alldevs_alloc; + } + + /* Create the first sysfs entries */ + ret = sflc_sysfs_init(); + if (ret) + goto err_sysfs; + + /* Init the Legacy module */ + ret = sfold_init(); + if (ret) + goto err_sfold; + + /* Init the Lite module */ + ret = sflite_init(); + if (ret) + goto err_sflite; + + /* Register the DM callbacks */ + ret = dm_register_target(&sflc_target_type); + if (ret < 0) + goto err_dm; + + DMINFO("loaded"); + return 0; + + +err_dm: + sflite_exit(); +err_sflite: + sfold_exit(); +err_sfold: + sflc_sysfs_exit(); +err_sysfs: + vfree(sflc_alldevs); +bad_alldevs_alloc: + DMERR("not loaded"); + return ret; +} + + +/* Module exit point */ +static void sflc_exit(void) +{ + dm_unregister_target(&sflc_target_type); + sfold_exit(); + sflite_exit(); + sflc_sysfs_exit(); + vfree(sflc_alldevs); + + DMINFO("unloaded"); + return; +} + + +module_init(sflc_init); +module_exit(sflc_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Toninov"); diff --git a/dm-sflc/src/sflc.h b/dm-sflc/src/sflc.h new file mode 100644 index 0000000..1462d16 --- /dev/null +++ b/dm-sflc/src/sflc.h @@ -0,0 +1,120 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +#ifndef _SFLC_H +#define _SFLC_H + + +#include + +#include "sflc_constants.h" +#include "old/sflc_old.h" +#include "lite/sflc_lite.h" + + +/* + *---------------------------- + * Structs + *---------------------------- + */ + +struct sflc_device +{ + /* Shufflecake-unique device ID */ + u32 dev_id; + /* : */ + char name[16]; + /* Number of volumes */ + u32 nr_volumes; + + /* Mode-specific device struct */ + int mode; + union { + sfold_Device *sfold_dev; + struct sflite_device *sflite_dev; + }; + + /* Sysfs */ + struct kobject kobj; + struct completion kobj_released; +}; + +struct sflc_volume +{ + /* Backing device */ + struct sflc_device *sdev; + /* Volume name: sflc__ */ + char name[32]; + + /* Mode-specific volume struct */ + int mode; + union { + sfold_Volume *sfold_vol; + struct sflite_volume *sflite_vol; + }; + /* Pointers to concrete, mode-specific callbacks */ + struct target_type *tt; + + /* Sysfs */ + struct kobject kobj; + struct completion kobj_released; +}; + + +/* + *---------------------------- + * Global variables + *---------------------------- + */ + +extern struct mutex sflc_alldevs_lock; +extern struct sflc_device **sflc_alldevs; +/* Next free device id */ +extern u32 sflc_free_devid; /* The lowest free devID */ + + +/* + *---------------------------- + * Functions + *---------------------------- + */ + +/* Device */ +struct sflc_device *sflc_dev_create(struct dm_target *ti, int argc, char **argv); +void sflc_dev_destroy(struct sflc_device *sdev); + +/* Volume */ +struct sflc_volume *sflc_vol_create(struct sflc_device *sdev, struct dm_target *ti, + int argc, char **argv); +void sflc_vol_destroy(struct sflc_volume *svol); + +/* Sysfs */ +int sflc_sysfs_init(void); +void sflc_sysfs_exit(void); +int sflc_sysfs_register_device(struct sflc_device *sdev); +void sflc_sysfs_unregister_device(struct sflc_device *sdev); +int sflc_sysfs_register_volume(struct sflc_volume *svol); +void sflc_sysfs_unregister_volume(struct sflc_volume *svol); + + +#endif /* _SFLC_H */ diff --git a/dm-sflc/sflc_constants.h b/dm-sflc/src/sflc_constants.h similarity index 65% rename from dm-sflc/sflc_constants.h rename to dm-sflc/src/sflc_constants.h index a425d88..c978796 100644 --- a/dm-sflc/sflc_constants.h +++ b/dm-sflc/src/sflc_constants.h @@ -21,17 +21,20 @@ * If not, see . */ -/***************************************************** - * PLACEHOLDER * - *****************************************************/ +/* Here we gather Shufflecake-wide constants, independent of the mode (legacy/lite) */ -/* This is just a placeholder for defining constants and parameters that must be the same across shufflecake components (kernel module, userland tool, etc) such as block size, slice size etc */ +#ifndef _SFLC_CONSTANTS_H_ +#define _SFLC_CONSTANTS_H_ + + +#define SFLC_TARGET_NAME "shufflecake" +#define DM_MSG_PREFIX "sflc" #define SFLC_VER_MAJOR 0 -#define SFLC_VER_MINOR 4 -#define SFLC_VER_REVISION 5 -#define SFLC_VER_SPECIAL "" +#define SFLC_VER_MINOR 5 +#define SFLC_VER_REVISION 0 +#define SFLC_VER_SPECIAL "rc1" #define STRINGIFY0(s) # s #define STRINGIFY(s) STRINGIFY0(s) @@ -39,3 +42,20 @@ #define SFLC_VERSION STRINGIFY(SFLC_VER_MAJOR)"."STRINGIFY(SFLC_VER_MINOR)"."STRINGIFY(SFLC_VER_REVISION)""SFLC_VER_SPECIAL +/* Each device can be formatted and used with a mode of choice, irrespective of the other devices */ +#define SFLC_MODE_LEGACY 0 +#define SFLC_MODE_LITE 1 + + +/* Max number of volumes per device */ +#define SFLC_DEV_MAX_VOLUMES 15 +/* Max number of open devices at any given time */ +#define SFLC_MAX_DEVS 1024 + + +/* Sysfs entries under /sys/module/dm_sflc/ */ +#define SFLC_SYSFS_BDEVS "bdevs" +#define SFLC_SYSFS_DEVID "next_dev_id" + + +#endif /* _SFLC_CONSTANTS_H_ */ diff --git a/dm-sflc/src/sysfs.c b/dm-sflc/src/sysfs.c new file mode 100644 index 0000000..2ef402d --- /dev/null +++ b/dm-sflc/src/sysfs.c @@ -0,0 +1,203 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +#include "sflc.h" + +#include + +/* + *---------------------------- + * Top-level entries + *---------------------------- + */ + +static ssize_t next_dev_id_show(struct module_attribute *mattr, struct module_kobject *mkobj, char *buf) +{ + ssize_t ret; + + if (mutex_lock_interruptible(&sflc_alldevs_lock)) + return -ERESTARTSYS; + ret = sysfs_emit(buf, "%u\n", sflc_free_devid); + mutex_unlock(&sflc_alldevs_lock); + + return ret; +} + +static struct kset *bdevs_kset; +static struct module_attribute devid_mattr = __ATTR_RO(next_dev_id); + +int sflc_sysfs_init() +{ + int err; + + bdevs_kset = kset_create_and_add(SFLC_SYSFS_BDEVS, NULL, &THIS_MODULE->mkobj.kobj); + if (!bdevs_kset) { + err = -ENOMEM; + DMERR("Could not create %s kset", SFLC_SYSFS_BDEVS); + goto bad_bdevs; + } + + err = sysfs_create_file(&THIS_MODULE->mkobj.kobj, &devid_mattr.attr); + if (err) { + DMERR("Could not create %s file", SFLC_SYSFS_DEVID); + goto bad_devid; + } + + return 0; + + +bad_devid: + kset_unregister(bdevs_kset); +bad_bdevs: + return err; +} + +void sflc_sysfs_exit() +{ + sysfs_remove_file(&THIS_MODULE->mkobj.kobj, &devid_mattr.attr); + kset_unregister(bdevs_kset); +} + + +/* + *---------------------------- + * Device entries + *---------------------------- + */ + +static ssize_t dev_id_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf) +{ + struct sflc_device *sdev = container_of(kobj, struct sflc_device, kobj); + + return sysfs_emit(buf, "%u\n", sdev->dev_id); +} + +static ssize_t volumes_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf) +{ + struct sflc_device *sdev = container_of(kobj, struct sflc_device, kobj); + + return sysfs_emit(buf, "%u\n", sdev->nr_volumes); +} + + +static struct kobj_attribute dev_id_kattr = __ATTR_RO(dev_id); +static struct kobj_attribute volumes_kattr = __ATTR_RO(volumes); +static struct attribute *sflc_device_default_attrs[] = { + &dev_id_kattr.attr, + &volumes_kattr.attr, + NULL +}; +ATTRIBUTE_GROUPS(sflc_device_default); + +static void sflc_device_kobj_release(struct kobject *kobj) +{ + struct sflc_device *sdev = container_of(kobj, struct sflc_device, kobj); + complete(&sdev->kobj_released); +} + +static struct kobj_type sflc_device_ktype = { + .release = sflc_device_kobj_release, + .sysfs_ops = &kobj_sysfs_ops, + .default_groups = sflc_device_default_groups +}; + +int sflc_sysfs_register_device(struct sflc_device *sdev) +{ + int err; + + /* Completion */ + init_completion(&sdev->kobj_released); + + /* Register directory :/ under bdevs/ */ + sdev->kobj.kset = bdevs_kset; + err = kobject_init_and_add(&sdev->kobj, &sflc_device_ktype, NULL, + "%s", sdev->name); + if (err) + goto bad; + /* Emit uevent */ + kobject_uevent(&sdev->kobj, KOBJ_ADD); + + return 0; + + +bad: + kobject_put(&sdev->kobj); + wait_for_completion(&sdev->kobj_released); + return err; +} + +void sflc_sysfs_unregister_device(struct sflc_device *sdev) +{ + kobject_put(&sdev->kobj); + wait_for_completion(&sdev->kobj_released); +} + + +/* + *---------------------------- + * Volume entries + *---------------------------- + */ + +static void sflc_volume_kobj_release(struct kobject *kobj) +{ + struct sflc_volume *svol = container_of(kobj, struct sflc_volume, kobj); + + complete(&svol->kobj_released); +} + +static struct kobj_type sflc_volume_ktype = { + .release = sflc_volume_kobj_release, + .sysfs_ops = &kobj_sysfs_ops, +}; + +int sflc_sysfs_register_volume(struct sflc_volume *svol) +{ + int err; + + /* Completion */ + init_completion(&svol->kobj_released); + + /* Register directory name>/ under device directory */ + err = kobject_init_and_add(&svol->kobj, &sflc_volume_ktype, &svol->sdev->kobj, + "%s", svol->name); + if (err) + goto bad; + + /* Emit uevent */ + kobject_uevent(&svol->kobj, KOBJ_ADD); + + return 0; + + +bad: + kobject_put(&svol->kobj); + wait_for_completion(&svol->kobj_released); + return err; +} + +void sflc_sysfs_unregister_volume(struct sflc_volume *svol) +{ + kobject_put(&svol->kobj); + wait_for_completion(&svol->kobj_released); +} diff --git a/dm-sflc/sysfs/devices.c b/dm-sflc/sysfs/devices.c deleted file mode 100644 index 7729145..0000000 --- a/dm-sflc/sysfs/devices.c +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright The Shufflecake Project Authors (2022) - * Copyright The Shufflecake Project Contributors (2022) - * Copyright Contributors to the The Shufflecake Project. - * - * See the AUTHORS file at the top-level directory of this distribution and at - * - * - * This file is part of the program shufflecake-c, which is part of the - * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) - * layer for Linux. See . - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, either version 2 of the License, or (at your option) - * any later version. This program is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. You should have received a copy of the - * GNU General Public License along with this program. - * If not, see . - */ - -/***************************************************** - * INCLUDE SECTION * - *****************************************************/ - -#include "sysfs.h" -#include "utils/string.h" -#include "log/log.h" - - -/***************************************************** - * CONSTANTS * - *****************************************************/ - -#define SFLC_SYSFS_DEV_VOLUMES_ATTR_NAME "volumes" -#define SFLC_SYSFS_DEV_TOT_SLICES_ATTR_NAME "tot_slices" -#define SFLC_SYSFS_DEV_FREE_SLICES_ATTR_NAME "free_slices" - - -/***************************************************** - * PRIVATE FUNCTIONS PROTOTYPES * - *****************************************************/ - -/* Functions that will go in the sysfs_ops */ -static ssize_t sflc_sysfs_devShow(struct kobject * kobj, struct attribute * attr, char * buf); -static ssize_t sflc_sysfs_devStore(struct kobject * kobj, struct attribute * attr, const char * buf, size_t len); - -/* Concrete file showers */ -static ssize_t sflc_sysfs_showDeviceVolumes(struct kobject * kobj, struct attribute * attr, char * buf); -static ssize_t sflc_sysfs_showDeviceTotSlices(struct kobject * kobj, struct attribute * attr, char * buf); -static ssize_t sflc_sysfs_showDeviceFreeSlices(struct kobject * kobj, struct attribute * attr, char * buf); - -/* Release function for the sysfs_Device */ -static void sflc_sysfs_releaseDev(struct kobject * kobj); - - -/***************************************************** - * PRIVATE VARIABLES DEFINITIONS * - *****************************************************/ - -/* The attribute representing the volumes file */ -static const struct attribute sflc_sysfs_devVolumesAttr = { - .name = SFLC_SYSFS_DEV_VOLUMES_ATTR_NAME, - .mode = 0444 -}; - -/* The attribute representing the tot_slices file */ -static const struct attribute sflc_sysfs_devTotSlicesAttr = { - .name = SFLC_SYSFS_DEV_TOT_SLICES_ATTR_NAME, - .mode = 0444 -}; - -/* The attribute representing the free_slices file */ -static const struct attribute sflc_sysfs_devFreeSlicesAttr = { - .name = SFLC_SYSFS_DEV_FREE_SLICES_ATTR_NAME, - .mode = 0444 -}; - -/* The sysfs_ops struct encapsulating the access methods */ -static const struct sysfs_ops sflc_sysfs_devSysfsOps = { - .show = sflc_sysfs_devShow, - .store = sflc_sysfs_devStore -}; - -/* The type for our sysfs_Device */ -static struct kobj_type sflc_sysfs_devType = { - .release = sflc_sysfs_releaseDev, - .sysfs_ops = &sflc_sysfs_devSysfsOps, -}; - - -/***************************************************** - * PUBLIC FUNCTIONS DEFINITIONS * - *****************************************************/ - -/* Creates and registers a sysfs_Device instance. Return ERR_PTR() on error. */ -sflc_sysfs_Device * sflc_sysfs_devCreateAndAdd(sflc_Device * pdev) -{ - sflc_sysfs_Device * dev; - int err; - - /* Allocate outer structure */ - dev = kzalloc(sizeof(sflc_sysfs_Device), GFP_KERNEL); - if (!dev) { - err = -ENOMEM; - pr_err("Could not allocate sysfs_Device\n"); - goto err_dev_alloc; - } - - /* Set device */ - dev->pdev = pdev; - - /* Allocate inner string */ - dev->dirname = kzalloc(strlen(pdev->bdev_path) + 1, GFP_KERNEL); - if (!dev->dirname) { - err = -ENOMEM; - pr_err("Could not allocate dirname\n"); - goto err_dirname_alloc; - } - - /* Copy it and substitute slashes with underscores */ - strcpy(dev->dirname, pdev->bdev_path); - sflc_str_replaceAll(dev->dirname, '/', '_'); - - /* Init and add kobject */ - err = kobject_init_and_add(&dev->kobj, &sflc_sysfs_devType, - sflc_sysfs_bdevs, dev->dirname); - if (err) { - pr_err("Could not init and add internal kobject; error %d\n", err); - goto err_kobj_init_add; - } - - /* Create the volumes file */ - err = sysfs_create_file(&dev->kobj, &sflc_sysfs_devVolumesAttr); - if (err) { - pr_err("Could not add volumes file; error %d\n", err); - goto err_vol_file; - } - /* Create the tot_slices file */ - err = sysfs_create_file(&dev->kobj, &sflc_sysfs_devTotSlicesAttr); - if (err) { - pr_err("Could not add tot_slices file; error %d\n", err); - goto err_tot_slices_file; - } - /* Create the volumes file */ - err = sysfs_create_file(&dev->kobj, &sflc_sysfs_devFreeSlicesAttr); - if (err) { - pr_err("Could not add free_slices file; error %d\n", err); - goto err_free_slices_file; - } - - return dev; - - -err_free_slices_file: -err_tot_slices_file: -err_vol_file: - kobject_put(&dev->kobj); -err_kobj_init_add: - kfree(dev->dirname); -err_dirname_alloc: - kfree(dev); -err_dev_alloc: - return ERR_PTR(err); -} - -/* Releases a reference to a sysfs_Device instance */ -void sflc_sysfs_putDev(sflc_sysfs_Device * dev) -{ - kobject_put(&dev->kobj); -} - -/* Creates a symlink inside the device's directory (under /sys/modules/dm_sflc/bdevs/) - * pointing to the volume's directory (under /sys/devices/sflc/) */ -int sflc_sysfs_addVolumeToDevice(sflc_sysfs_Device * dev, sflc_sysfs_Volume * vol) -{ - return sysfs_create_link(&dev->kobj, &vol->kdev.kobj, vol->kdev.kobj.name); -} - -/* Removes the symlink created before */ -void sflc_sysfs_removeVolumeFromDevice(sflc_sysfs_Device * dev, sflc_sysfs_Volume * vol) -{ - sysfs_remove_link(&dev->kobj, vol->kdev.kobj.name); -} - - -/***************************************************** - * PRIVATE FUNCTIONS PROTOTYPES * - *****************************************************/ - -/* Dispatch to the right shower */ -static ssize_t sflc_sysfs_devShow(struct kobject * kobj, struct attribute * attr, char * buf) -{ - /* Dispatch based on name */ - if (strcmp(attr->name, SFLC_SYSFS_DEV_VOLUMES_ATTR_NAME) == 0) { - return sflc_sysfs_showDeviceVolumes(kobj, attr, buf); - } - if (strcmp(attr->name, SFLC_SYSFS_DEV_TOT_SLICES_ATTR_NAME) == 0) { - return sflc_sysfs_showDeviceTotSlices(kobj, attr, buf); - } - if (strcmp(attr->name, SFLC_SYSFS_DEV_FREE_SLICES_ATTR_NAME) == 0) { - return sflc_sysfs_showDeviceFreeSlices(kobj, attr, buf); - } - - /* Else, error */ - pr_err("Error, unknown attribute %s\n", attr->name); - return -EIO; -} - -/* Do nothing */ -static ssize_t sflc_sysfs_devStore(struct kobject * kobj, struct attribute * attr, const char * buf, size_t len) -{ - return -EIO; -} - -/* Show the list of mounted volumes */ -static ssize_t sflc_sysfs_showDeviceVolumes(struct kobject * kobj, struct attribute * attr, char * buf) -{ - sflc_sysfs_Device * dev; - sflc_Device * pdev; - ssize_t ret; - - /* Cast to a sysfs_Device */ - dev = container_of(kobj, sflc_sysfs_Device, kobj); - /* Get the device */ - pdev = dev->pdev; - - /* File contents */ - ret = 0; - ssize_t written; - /* Write the volume count */ - written = sprintf(buf, "%d", pdev->vol_cnt); - ret += written; - buf += written; - /* And all the volume names, space-separated */ - int i; - for (i = 0; i < pdev->vol_cnt; i++) { - written = sprintf(buf, " %s", pdev->vol[i]->vol_name); - ret += written; - buf += written; - } - /* Add newline */ - written = sprintf(buf, "\n"); - ret += written; - buf += written; - - return ret; -} - -/* Show the number of slices */ -static ssize_t sflc_sysfs_showDeviceTotSlices(struct kobject * kobj, struct attribute * attr, char * buf) -{ - sflc_sysfs_Device * dev; - sflc_Device * pdev; - ssize_t ret; - - /* Cast to a DeviceKobject */ - dev = container_of(kobj, sflc_sysfs_Device, kobj); - /* Get the device */ - pdev = dev->pdev; - - /* Write the tot_slices */ - ret = sprintf(buf, "%u\n", pdev->tot_slices); - - return ret; -} - -/* Show the number of free slices */ -static ssize_t sflc_sysfs_showDeviceFreeSlices(struct kobject * kobj, struct attribute * attr, char * buf) -{ - sflc_sysfs_Device * dev; - sflc_Device * pdev; - ssize_t ret; - - /* Cast to a DeviceKobject */ - dev = container_of(kobj, sflc_sysfs_Device, kobj); - /* Get the device */ - pdev = dev->pdev; - - /* Write the free_slices */ - ret = sprintf(buf, "%u\n", pdev->free_slices); - - return ret; -} - -/* Release function for the DeviceKobject */ -static void sflc_sysfs_releaseDev(struct kobject * kobj) -{ - sflc_sysfs_Device * dev; - - /* Cast to a DeviceKobject */ - dev = container_of(kobj, sflc_sysfs_Device, kobj); - - /* Free everything */ - kfree(dev->dirname); - kfree(dev); - - return; -} diff --git a/dm-sflc/sysfs/sysfs.c b/dm-sflc/sysfs/sysfs.c deleted file mode 100644 index a5854c4..0000000 --- a/dm-sflc/sysfs/sysfs.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright The Shufflecake Project Authors (2022) - * Copyright The Shufflecake Project Contributors (2022) - * Copyright Contributors to the The Shufflecake Project. - * - * See the AUTHORS file at the top-level directory of this distribution and at - * - * - * This file is part of the program shufflecake-c, which is part of the - * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) - * layer for Linux. See . - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, either version 2 of the License, or (at your option) - * any later version. This program is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. You should have received a copy of the - * GNU General Public License along with this program. - * If not, see . - */ - -/***************************************************** - * INCLUDE SECTION * - *****************************************************/ - -#include - -#include "sysfs.h" -#include "log/log.h" - - -/***************************************************** - * CONSTANTS * - *****************************************************/ - -#define SFLC_SYSFS_BDEVS_ENTRY_NAME "bdevs" -#define SFLC_SYSFS_ROOT_DEVICE_NAME "sflc" -#define SFLC_SYSFS_NEXT_DEV_ID_ATTR_NAME next_dev_id - - -/***************************************************** - * PUBLIC VARIABLES DEFINITIONS * - *****************************************************/ - -/* Kobject associated to the /sys/module/dm_sflc/bdevs entry */ -struct kobject * sflc_sysfs_bdevs; - -/* Root device that will be every volume's parent */ -struct device * sflc_sysfs_root; - - -/***************************************************** - * PRIVATE FUNCTIONS PROTOTYPES * - *****************************************************/ - -static ssize_t sflc_sysfs_showNextDevId(struct device *kdev, struct device_attribute *attr, char *buf); - - -/***************************************************** - * PRIVATE VARIABLES DEFINITIONS * - *****************************************************/ - -/* Attribute showing the next device ID */ -static const struct device_attribute sflc_sysfs_nextDevIdAttr = __ATTR( - SFLC_SYSFS_NEXT_DEV_ID_ATTR_NAME, - 0444, - sflc_sysfs_showNextDevId, - NULL -); - - -/***************************************************** - * PUBLIC FUNCTIONS DEFINITIONS * - *****************************************************/ - -/* Called on module load */ -int sflc_sysfs_init(void) -{ - int err; - - /* Create the bdevs entry under /sys/module/dm_sflc */ - sflc_sysfs_bdevs = kobject_create_and_add(SFLC_SYSFS_BDEVS_ENTRY_NAME, &THIS_MODULE->mkobj.kobj); - if (!sflc_sysfs_bdevs) { - err = -ENOMEM; - pr_err("Could not create bdevs kobject\n"); - goto err_realdevs; - } - - /* Create the root sflc device */ - sflc_sysfs_root = root_device_register(SFLC_SYSFS_ROOT_DEVICE_NAME); - if (IS_ERR(sflc_sysfs_root)) { - err = PTR_ERR(sflc_sysfs_root); - pr_err("Could not register sflc root device; error %d\n", err); - goto err_rootdev; - } - - /* Add next_dev_id attribute to it */ - err = device_create_file(sflc_sysfs_root, &sflc_sysfs_nextDevIdAttr); - if (err) { - pr_err("Could not create mapped_slices device file; error %d\n", err); - goto err_dev_create_file; - } - - return 0; - -err_dev_create_file: - root_device_unregister(sflc_sysfs_root); -err_rootdev: - kobject_put(sflc_sysfs_bdevs); -err_realdevs: - return err; -} - -/* Called on module unload */ -void sflc_sysfs_exit(void) -{ - root_device_unregister(sflc_sysfs_root); - kobject_put(sflc_sysfs_bdevs); -} - - -/***************************************************** - * PRIVATE FUNCTIONS DEFINITIONS * - *****************************************************/ - -static ssize_t sflc_sysfs_showNextDevId(struct device *kdev, struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%lu\n", sflc_dev_nextId); -} - diff --git a/dm-sflc/sysfs/sysfs.h b/dm-sflc/sysfs/sysfs.h deleted file mode 100644 index 62fc014..0000000 --- a/dm-sflc/sysfs/sysfs.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright The Shufflecake Project Authors (2022) - * Copyright The Shufflecake Project Contributors (2022) - * Copyright Contributors to the The Shufflecake Project. - * - * See the AUTHORS file at the top-level directory of this distribution and at - * - * - * This file is part of the program shufflecake-c, which is part of the - * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) - * layer for Linux. See . - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, either version 2 of the License, or (at your option) - * any later version. This program is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. You should have received a copy of the - * GNU General Public License along with this program. - * If not, see . - */ - -/* - * Sysfs functions - */ - -#ifndef _SFLC_SYSFS_SYSFS_H_ -#define _SFLC_SYSFS_SYSFS_H_ - - -/***************************************************** - * TYPES FORWARD DECLARATIONS * - *****************************************************/ - -/* Necessary since device.h, volume.h, and sysfs.h all include each other */ - -typedef struct sflc_sysfs_device_s sflc_sysfs_Device; -typedef struct sflc_sysfs_volume_s sflc_sysfs_Volume; - - -/***************************************************** - * INCLUDE SECTION * - *****************************************************/ - -#include -#include - -#include "device/device.h" -#include "volume/volume.h" - - -/***************************************************** - * TYPES * - *****************************************************/ - -/* This embeds a struct kobject */ -struct sflc_sysfs_device_s -{ - /* The Device it represents */ - sflc_Device * pdev; - /* The name of this device's subdirectoy under realdevs */ - char * dirname; - - /* The embedded kobject */ - struct kobject kobj; -}; - -/* This embeds a struct device */ -struct sflc_sysfs_volume_s -{ - /* The Volume it represents */ - sflc_Volume * pvol; - - /* The embedded device */ - struct device kdev; -}; - - -/***************************************************** - * PUBLIC VARIABLES DECLARATIONS * - *****************************************************/ - -/* Kobject associated to the /sys/module/dm_sflc/bdevs entry */ -extern struct kobject * sflc_sysfs_bdevs; - -/* Root device (/sys/devices/sflc) that will be every volume's parent. - A bit overkill to have a sflc root device, but it does the trick. */ -extern struct device * sflc_sysfs_root; - - -/***************************************************** - * PUBLIC FUNCTIONS PROTOTYPES * - *****************************************************/ - -/* Called on module load/unload */ -int sflc_sysfs_init(void); -void sflc_sysfs_exit(void); - - -/* Device-related functions */ - -/* Creates and registers a sysfs_Device instance. Returns ERR_PTR() on error. */ -sflc_sysfs_Device * sflc_sysfs_devCreateAndAdd(sflc_Device * pdev); - -/* Releases a reference to a sysfs_Device instance */ -void sflc_sysfs_putDev(sflc_sysfs_Device * dev); - -/* Creates a symlink inside the device's subdirectory pointing to the volume's subdirectory */ -int sflc_sysfs_addVolumeToDevice(sflc_sysfs_Device * dev, sflc_sysfs_Volume * vol); - -/* Removes the symlink created before */ -void sflc_sysfs_removeVolumeFromDevice(sflc_sysfs_Device * dev, sflc_sysfs_Volume * vol); - - -/* Volume-related functions */ - -/* Creates and registers a sysfs_Volume instance. Returns ERR_PTR() on error. */ -sflc_sysfs_Volume * sflc_sysfs_volCreateAndAdd(sflc_Volume * pvol); - -/* Releases a reference to a sysfs_Volume instance */ -void sflc_sysfs_putVol(sflc_sysfs_Volume * vol); - - -#endif /* _SFLC_SYSFS_SYSFS_H_ */ diff --git a/dm-sflc/sysfs/volumes.c b/dm-sflc/sysfs/volumes.c deleted file mode 100644 index 2ca2e7f..0000000 --- a/dm-sflc/sysfs/volumes.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright The Shufflecake Project Authors (2022) - * Copyright The Shufflecake Project Contributors (2022) - * Copyright Contributors to the The Shufflecake Project. - * - * See the AUTHORS file at the top-level directory of this distribution and at - * - * - * This file is part of the program shufflecake-c, which is part of the - * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) - * layer for Linux. See . - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, either version 2 of the License, or (at your option) - * any later version. This program is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. You should have received a copy of the - * GNU General Public License along with this program. - * If not, see . - */ - -/***************************************************** - * INCLUDE SECTION * - *****************************************************/ - -#include "sysfs.h" -#include "utils/string.h" -#include "log/log.h" - - -/***************************************************** - * CONSTANTS * - *****************************************************/ - -#define SFLC_SYSFS_VOL_NR_SLICES_ATTR_NAME mapped_slices - - -/***************************************************** - * PRIVATE FUNCTIONS PROTOTYPES * - *****************************************************/ - -static void sflc_sysfs_volRelease(struct device * kdev); -static ssize_t sflc_sysfs_showVolNrSlices(struct device * dev, struct device_attribute * attr, char * buf); - - -/***************************************************** - * PRIVATE VARIABLES DEFINITIONS * - *****************************************************/ - -/* Attribute showing the number of slices utilised by the volume */ -static const struct device_attribute sflc_sysfs_volNrSlicesAttr = __ATTR( - SFLC_SYSFS_VOL_NR_SLICES_ATTR_NAME, - 0444, - sflc_sysfs_showVolNrSlices, - NULL -); - - -/***************************************************** - * PUBLIC FUNCTIONS DEFINITIONS * - *****************************************************/ - -/* Creates and registers a sysfs_Volume instance. Returns ERR_PTR() on error. */ -sflc_sysfs_Volume * sflc_sysfs_volCreateAndAdd(sflc_Volume * pvol) -{ - sflc_sysfs_Volume * vol; - int err; - - /* Allocate device */ - vol = kzalloc(sizeof(sflc_sysfs_Volume), GFP_KERNEL); - if (!vol) { - err = -ENOMEM; - pr_err("Could not allocate sysfs_Volume\n"); - goto err_vol_alloc; - } - - /* Set volume */ - vol->pvol = pvol; - - /* Set name */ - err = dev_set_name(&vol->kdev, "%s", pvol->vol_name); - if (err) { - pr_err("Could not set device name %s; error %d\n", pvol->vol_name, err); - goto err_dev_set_name; - } - - /* Set destructor */ - vol->kdev.release = sflc_sysfs_volRelease; - /* Set parent */ - vol->kdev.parent = sflc_sysfs_root; - - /* Register */ - err = device_register(&vol->kdev); - if (err) { - pr_err("Could not register volume %s; error %d\n", pvol->vol_name, err); - goto err_dev_register; - } - - /* Add mapped_slices attribute */ - err = device_create_file(&vol->kdev, &sflc_sysfs_volNrSlicesAttr); - if (err) { - pr_err("Could not create mapped_slices device file; error %d\n", err); - goto err_dev_create_file; - } - - return vol; - - -err_dev_create_file: - device_unregister(&vol->kdev); -err_dev_register: - put_device(&vol->kdev); -err_dev_set_name: - kfree(vol); -err_vol_alloc: - return ERR_PTR(err); -} - -/* Releases a reference to a sysfs_Device instance */ -void sflc_sysfs_putVol(sflc_sysfs_Volume * vol) -{ - device_unregister(&vol->kdev); -} - - -/***************************************************** - * PRIVATE FUNCTIONS PROTOTYPES * - *****************************************************/ - -static ssize_t sflc_sysfs_showVolNrSlices(struct device * kdev, struct device_attribute * attr, char * buf) -{ - sflc_sysfs_Volume * vol = container_of(kdev, sflc_sysfs_Volume, kdev); - sflc_Volume * pvol = vol->pvol; - - return sprintf(buf, "%u\n", pvol->mapped_slices); -} - -static void sflc_sysfs_volRelease(struct device * kdev) -{ - sflc_sysfs_Volume * vol; - - /* Cast */ - vol = container_of(kdev, sflc_sysfs_Volume, kdev); - - /* Just free */ - kfree(vol); - - return; -} diff --git a/dm-sflc/target/target.c b/dm-sflc/target/target.c deleted file mode 100644 index afb143a..0000000 --- a/dm-sflc/target/target.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright The Shufflecake Project Authors (2022) - * Copyright The Shufflecake Project Contributors (2022) - * Copyright Contributors to the The Shufflecake Project. - * - * See the AUTHORS file at the top-level directory of this distribution and at - * - * - * This file is part of the program shufflecake-c, which is part of the - * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) - * layer for Linux. See . - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, either version 2 of the License, or (at your option) - * any later version. This program is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. You should have received a copy of the - * GNU General Public License along with this program. - * If not, see . - */ - -/* - * Methods of our DM target - */ - -/***************************************************** - * INCLUDE SECTION * - *****************************************************/ - -#include "target.h" -#include "device/device.h" -#include "volume/volume.h" -#include "utils/bio.h" -#include "utils/string.h" -#include "log/log.h" - -/***************************************************** - * CONSTANTS * - *****************************************************/ - -/***************************************************** - * PRIVATE FUNCTIONS PROTOTYPES * - *****************************************************/ - -static int sflc_tgt_ctr(struct dm_target *ti, unsigned int argc, char **argv); -static void sflc_tgt_dtr(struct dm_target *ti); -static int sflc_tgt_map(struct dm_target *ti, struct bio *bio); -static void sflc_tgt_ioHints(struct dm_target *ti, struct queue_limits *limits); -static int sflc_tgt_iterateDevices(struct dm_target *ti, iterate_devices_callout_fn fn, - void *data); - -/***************************************************** - * PUBLIC VARIABLES DEFINITIONS * - *****************************************************/ - -struct target_type sflc_target = { - .name = "shufflecake", - .version = {1, 0, 0}, - .module = THIS_MODULE, - .ctr = sflc_tgt_ctr, - .dtr = sflc_tgt_dtr, - .map = sflc_tgt_map, - .status = NULL, - .io_hints = sflc_tgt_ioHints, - .iterate_devices = sflc_tgt_iterateDevices, -}; - -/***************************************************** - * PRIVATE FUNCTIONS DEFINITIONS * - *****************************************************/ - -/* Called every time we create a volume with the userland tool */ -static int sflc_tgt_ctr(struct dm_target *ti, unsigned int argc, char **argv) -{ - char * bdev_path; - int vol_idx; - char * enckey_hex; - u8 enckey[SFLC_SK_KEY_LEN]; - u32 tot_slices; - sflc_Device * dev; - sflc_Volume * vol; - int err; - - /* - * Parse arguments. - * - * argv[0]: underlying block device path - * argv[1]: volume index within the device - * argv[2]: number of 1 MB slices in the underlying device - * argv[3]: 32-byte encryption key (hex-encoded) - */ - if (argc != 4) { - ti->error = "Invalid argument count"; - return -EINVAL; - } - bdev_path = argv[0]; - sscanf(argv[1], "%d", &vol_idx); - sscanf(argv[2], "%u", &tot_slices); - enckey_hex = argv[3]; - - /* Decode the encryption key */ - if (strlen(enckey_hex) != 2 * SFLC_SK_KEY_LEN) { - pr_err("Hexadecimal key (length %lu): %s\n", strlen(enckey_hex), enckey_hex); - ti->error = "Invalid key length"; - return -EINVAL; - } - err = sflc_str_hexDecode(enckey_hex, enckey); - if (err) { - ti->error = "Could not decode hexadecimal encryption key"; - return err; - } - - /* Acquire the big device lock */ - if (down_interruptible(&sflc_dev_mutex)) { - ti->error = "Interrupted while waiting for access to Device"; - return -EINTR; - } - - /* Check if we already have a Device for this bdev */ - dev = sflc_dev_lookupByPath(bdev_path); - if (IS_ERR(dev)) { - ti->error = "Could not look up device by path (interrupted)"; - up(&sflc_dev_mutex); - return PTR_ERR(dev); - } - - /* Otherwise create it (also adds it to the device list) */ - if (!dev) { - pr_notice("Device for %s didn't exist before, going to create it\n", bdev_path); - dev = sflc_dev_create(ti, bdev_path, tot_slices); - } else { - pr_notice("Device on %s already existed\n", bdev_path); - } - - /* Check for device creation errors */ - if (IS_ERR(dev)) { - ti->error = "Could not create device"; - up(&sflc_dev_mutex); - return PTR_ERR(dev); - } - - /* Create the volume (also adds it to the device) */ - vol = sflc_vol_create(ti, dev, vol_idx, enckey); - if (IS_ERR(vol)) { - ti->error = "Error creating volume"; - up(&sflc_dev_mutex); - return PTR_ERR(vol); - } - pr_debug("Now %d volumes are linked to device %s\n", dev->vol_cnt, bdev_path); - - /* Release the big device lock */ - up(&sflc_dev_mutex); - - /* Tell DM we want one SFLC sector at a time */ - ti->max_io_len = SFLC_DEV_SECTOR_SCALE; - /* Enable REQ_OP_FLUSH bios */ - ti->num_flush_bios = 1; - /* Disable REQ_OP_WRITE_ZEROES and REQ_OP_SECURE_ERASE (can't be passed through as - they would break deniability, and they would be too complicated to handle individually) */ - ti->num_secure_erase_bios = 0; - ti->num_write_zeroes_bios = 0; - /* Momentarily disable REQ_OP_DISCARD_BIOS - TODO: will need to support them to release slice mappings */ - ti->num_discard_bios = 0; - /* When we receive a ->map call, we won't need to take the device lock anymore */ - ti->private = vol; - - return 0; -} - -/* Called every time we destroy a volume with the userland tool */ -static void sflc_tgt_dtr(struct dm_target *ti) -{ - sflc_Volume * vol = ti->private; - sflc_Device * dev = vol->dev; - - pr_debug("Destroying volume \"%s\"\n", vol->vol_name); - - /* We do need to take the device lock here, as we'll be modifying the device */ - if (down_interruptible(&sflc_dev_mutex)) { - pr_err("Interrupted while waiting to destroy volume\n"); - return; - } - - /* Destroy volume (also decreases refcount in device) */ - sflc_vol_destroy(ti, vol); - - /* Destroy the device */ - if (dev->vol_cnt == 0) { - pr_notice("Removed the last volume from device\n"); - sflc_dev_destroy(ti, dev); - } - - /* End of critical section */ - up(&sflc_dev_mutex); - - return; -} - -/* Callback for every bio submitted to our virtual block device */ -static int sflc_tgt_map(struct dm_target *ti, struct bio *bio) -{ - int err; - sflc_Volume * vol = ti->private; - - /* If no data, just quickly remap the sector and the block device (no crypto) */ - /* TODO: this is dangerous for deniability, will need more filtering */ - if (unlikely(!bio_has_data(bio))) { - pr_debug("No-data bio: bio_op = %d", bio_op(bio)); - err = sflc_vol_remapBioFast(vol, bio); - if (err) { - pr_err("Could not remap bio; error %d\n", err); - return DM_MAPIO_KILL; - } - return DM_MAPIO_REMAPPED; - } - - /* At this point, the bio has data. Do a few sanity checks */ - /* TODO: I think we can get rid of all of them */ - - /* Check that it is properly aligned and it doesn't cross vector boundaries */ - if (unlikely(!sflc_bio_isAligned(bio))) { - pr_err("Unaligned bio!\n"); - return DM_MAPIO_KILL; - } - /* If it contains more than one SFLC sector, complain with the DM layer and continue */ - if (unlikely(bio->bi_iter.bi_size > SFLC_DEV_SECTOR_SIZE)) { - pr_notice("Large bio of size %u\n", bio->bi_iter.bi_size); - dm_accept_partial_bio(bio, SFLC_DEV_SECTOR_SCALE); - } - /* Check that it contains exactly one SFLC sector */ - if (unlikely(bio->bi_iter.bi_size != SFLC_DEV_SECTOR_SIZE)) { - pr_err("Wrong length (%u) of bio\n", bio->bi_iter.bi_size); - return DM_MAPIO_KILL; - } - - /* Now it is safe, process it */ - err = sflc_vol_processBio(vol, bio); - if (err) { - pr_err("Could not enqueue bio\n"); - return DM_MAPIO_KILL; - } - - return DM_MAPIO_SUBMITTED; -} - -/* Callback executed to inform the DM about our 4096-byte sector size */ -static void sflc_tgt_ioHints(struct dm_target *ti, struct queue_limits *limits) -{ - sflc_Volume * vol = ti->private; - - pr_info("Called io_hints on volume \"%s\"\n", vol->vol_name); - - limits->logical_block_size = SFLC_DEV_SECTOR_SIZE; - limits->physical_block_size = SFLC_DEV_SECTOR_SIZE; - - limits->io_min = SFLC_DEV_SECTOR_SIZE; - limits->io_opt = SFLC_DEV_SECTOR_SIZE; - - return; -} - -/* Callback needed for God knows what, otherwise io_hints never gets called */ -static int sflc_tgt_iterateDevices(struct dm_target *ti, iterate_devices_callout_fn fn, - void *data) -{ - sflc_Volume * vol = ti->private; - sflc_Device * dev = vol->dev; - - pr_debug("Called iterate_devices on volume \"%s\"\n", vol->vol_name); - - if (!fn) { - return -EINVAL; - } - return fn(ti, vol->dev->bdev, 0, - (dev->dev_header_size + dev->tot_slices * SFLC_DEV_PHYS_SLICE_SIZE) * SFLC_DEV_SECTOR_SCALE, - data); -} diff --git a/shufflecake-userland/Makefile.sources b/shufflecake-userland/Makefile.sources index 0e2a80b..d2313c8 100644 --- a/shufflecake-userland/Makefile.sources +++ b/shufflecake-userland/Makefile.sources @@ -28,9 +28,9 @@ #### PROJ_SRCS := $(addprefix utils/,crypto.c disk.c dm.c file.c string.c input.c) -PROJ_SRCS += $(addprefix header/,position_map.c volume_master_block.c device_master_block.c) -PROJ_SRCS += $(addprefix operations/,volume_header.c devmapper.c dmb.c) -PROJ_SRCS += $(addprefix commands/,init.c open.c close.c test_pwd.c change_pwd.c) +PROJ_SRCS += $(addprefix header/,position_map_legacy.c position_map_lite.c volume_master_block_legacy.c volume_master_block_lite.c device_master_block.c) +PROJ_SRCS += $(addprefix operations/,volume_header_legacy.c volume_header_lite.c devmapper_legacy.c devmapper_lite.c dmb.c) +PROJ_SRCS += $(addprefix commands/,init_legacy.c init_lite.c open_legacy.c open_lite.c close.c test_pwd.c change_pwd.c) PROJ_SRCS += $(addprefix cli/,dispatch.c init.c open.c close.c testpwd.c changepwd.c) PROJ_SRCS += main.c diff --git a/shufflecake-userland/include/cli.h b/shufflecake-userland/include/cli.h index 838f618..1c53043 100644 --- a/shufflecake-userland/include/cli.h +++ b/shufflecake-userland/include/cli.h @@ -49,9 +49,9 @@ int sflc_cli_dispatch(int argc, char **argv); /* Initializes device and create empty volumes */ -int sflc_cli_init(char *block_device, int num_volumes, int skip_randfill); +int sflc_cli_init(char *block_device, int sflc_mode, int num_volumes, int skip_randfill); /* Open volumes */ -int sflc_cli_open(char *block_device); +int sflc_cli_open(char *block_device, int sflc_mode); /* Close volumes */ int sflc_cli_close(char *block_device); /* Test password */ diff --git a/shufflecake-userland/include/commands.h b/shufflecake-userland/include/commands.h index 68a14ac..6531bf0 100644 --- a/shufflecake-userland/include/commands.h +++ b/shufflecake-userland/include/commands.h @@ -50,13 +50,13 @@ typedef struct { /* Underlying block device */ char *bdev_path; - + /* Shufflecake mode */ + int sflc_mode; /* Number of volumes */ size_t nr_vols; /* Volumes' passwords */ char **pwds; size_t *pwd_lens; - /* Option to skip random filling */ bool no_randfill; @@ -68,7 +68,8 @@ typedef struct { /* Underlying block device */ char *bdev_path; - + /* Shufflecake mode */ + int sflc_mode; /* The only password provided */ char *pwd; size_t pwd_len; @@ -79,10 +80,10 @@ typedef struct { /* Underlying block device */ char *bdev_path; - + /* Shufflecake mode (legacy,lite,full) */ + int sflc_mode; /* Content of the DMB cell */ sflc_DmbCell *dmb_cell; - /* The new password */ char *new_pwd; size_t new_pwd_len; @@ -94,11 +95,15 @@ typedef struct * PUBLIC FUNCTIONS PROTOTYPES * *****************************************************/ -/* Create N volumes (only formats the device header, does not open the volumes) */ -int sflc_cmd_initVolumes(sflc_cmd_InitArgs *args); +/* Create N volumes (only formats the device header, does not open the volumes). LITE version */ +int sflite_cmd_initVolumes(sflc_cmd_InitArgs *args); +/* Create N volumes (only formats the device header, does not open the volumes). LEGACY version */ +int sfold_cmd_initVolumes(sflc_cmd_InitArgs *args); -/* Open M volumes, from the first down to the one whose pwd is provided */ -int sflc_cmd_openVolumes(sflc_cmd_OpenArgs *args); +/* Open M volumes, from the first down to the one whose pwd is provided. LITE version */ +int sflite_cmd_openVolumes(sflc_cmd_OpenArgs *args); +/* Open M volumes, from the first down to the one whose pwd is provided. LEGACY version */ +int sfold_cmd_openVolumes(sflc_cmd_OpenArgs *args); /* Close all volumes on the device (reads the list from sysfs) */ int sflc_cmd_closeVolumes(char *bdev_path); diff --git a/shufflecake-userland/include/header.h b/shufflecake-userland/include/header.h index 869b868..1062a21 100644 --- a/shufflecake-userland/include/header.h +++ b/shufflecake-userland/include/header.h @@ -33,6 +33,7 @@ #include #include "utils/crypto.h" +#include "utils/math.h" /***************************************************** @@ -40,18 +41,18 @@ *****************************************************/ /* The DMB contains one IV + one VMB key + one MAC for each volume */ -#define SFLC_DMB_CELL_SIZE (SFLC_AESGCM_PADDED_IVLEN + SFLC_CRYPTO_KEYLEN + SFLC_AESGCM_TAGLEN) +#define SFLC_DMB_CELL_SIZE (SFLC_AESGCM_PADDED_IVLEN + SFLC_STANDARD_KEYLEN + SFLC_AESGCM_TAGLEN) /* Let us enforce that the one DMB can fit cells for all volumes */ -#if SFLC_ARGON_SALTLEN + (SFLC_DEV_MAX_VOLUMES * SFLC_DMB_CELL) > SFLC_SECTOR_SIZE -#error "Invalid combination of parameters: probably SFLC_DEV_MAX_VOLUMES is too big" +#if SFLC_ARGON_SALTLEN + (SFLC_DEV_MAX_VOLUMES * SFLC_DMB_CELL_SIZE) > SFLC_BLOCK_SIZE +#error "Invalid combination of parameters: probably SFLITE_DEV_MAX_VOLUMES is too big" #endif // The VMB cleartext occupies the last 4064 bytes on-disk (4096 bytes minus IV and MAC) -#define SFLC_CLEAR_VMB_LEN (SFLC_SECTOR_SIZE - \ - SFLC_AESGCM_PADDED_IVLEN - \ - SFLC_AESGCM_TAGLEN) +#define SFLC_CLEAR_VMB_LEN (SFLC_BLOCK_SIZE - \ + SFLC_AESGCM_PADDED_IVLEN - \ + SFLC_AESGCM_TAGLEN) @@ -66,21 +67,20 @@ */ typedef struct { // Each volume's VMB key - char vmb_keys[SFLC_DEV_MAX_VOLUMES][SFLC_CRYPTO_KEYLEN]; + char vmb_keys[SFLC_DEV_MAX_VOLUMES][SFLC_STANDARD_KEYLEN]; // How many of these need actually be encrypted size_t nr_vols; } sflc_Dmb; - /** * When unsealing a DMB, only one VMB key can be unlocked with a password. * An invalid value for vol_idx means no VMB key could be unlocked (wrong pwd) */ typedef struct { // The unlocked VMB key - char vmb_key[SFLC_CRYPTO_KEYLEN]; + char vmb_key[SFLC_STANDARD_KEYLEN]; // The index of the volume opened by this VMB key size_t vol_idx; @@ -94,20 +94,24 @@ typedef struct { * only contains the useful info, in the clear. */ typedef struct { + int mode; + // The key that encrypts the volume's data section - char volume_key[SFLC_CRYPTO_KEYLEN]; + union { + char volume_key_lite[SFLC_AESXTS_KEYLEN]; + char volume_key_legacy[SFLC_STANDARD_KEYLEN]; + }; // The key that encrypts the previous volume's master block - char prev_vmb_key[SFLC_CRYPTO_KEYLEN]; + char prev_vmb_key[SFLC_STANDARD_KEYLEN]; // The total number of logical slices virtually available to this volume size_t nr_slices; } sflc_Vmb; - /** - * This struct represents an encrypted empty position map. + * This struct represents an encrypted empty position map. LEGACY version. * On-disk, the layout interleaves one IV block with 256 PosMap blocks (each * encrypted by an IV in the IV block). Many such "runs" can be concatenated, * until the position map is big enough to index the desired number of slices. @@ -132,7 +136,21 @@ typedef struct { // The number of PosMapBlocks in the last array size_t nr_last_pmbs; -} sflc_EncPosMap; +} sfold_EncPosMap; + + +/***************************************************** + * INLINE FUNCTIONS * + *****************************************************/ + + +// Starting block of a volume's position map. LITE version +static inline uint64_t sflite_pmStartBlock(size_t vol_idx, size_t nr_slices) +{ + return 1 + + SFLC_DEV_MAX_VOLUMES + + vol_idx*ceil(nr_slices, SFLC_SLICE_IDX_PER_BLOCK); +} /***************************************************** @@ -147,15 +165,22 @@ int sflc_dmb_unseal(char *disk_block, char *pwd, size_t pwd_len, sflc_DmbCell *d int sflc_dmb_setCell(char *disk_block, sflc_DmbCell *dmb_cell, char *pwd, size_t pwd_len); -/* "Encrypt" a VMB with a VMB key, so it's ready to be written on-disk */ -int sflc_vmb_seal(sflc_Vmb *vmb, char *vmb_key, char *disk_block); -/* "Decrypt" a VMB coming from the disk, directly using its key */ -int sflc_vmb_unseal(char *disk_block, char *vmb_key, sflc_Vmb *vmb); +/* "Encrypt" a VMB with a VMB key, so it's ready to be written on-disk. LITE version */ +int sflite_vmb_seal(sflc_Vmb *vmb, char *vmb_key, char *disk_block); +/* "Decrypt" a VMB coming from the disk, directly using its key. LITE version */ +int sflite_vmb_unseal(char *disk_block, char *vmb_key, sflc_Vmb *vmb); + +/* "Encrypt" a VMB with a VMB key, so it's ready to be written on-disk. LEGACY version */ +int sfold_vmb_seal(sflc_Vmb *vmb, char *vmb_key, char *disk_block); +/* "Decrypt" a VMB coming from the disk, directly using its key. LEGACY version */ +int sfold_vmb_unseal(char *disk_block, char *vmb_key, sflc_Vmb *vmb); -/* Create an encrypted empty position map for the given number of slices (allocates memory) */ -int sflc_epm_create(size_t nr_slices, char *volume_key, sflc_EncPosMap *epm); +/* Create an encrypted empty position map for the given number of slices (allocates memory). LITE version */ +void *sflite_epm_create(size_t nr_slices, size_t vol_idx, char *volume_key); +/* Create an encrypted empty position map for the given number of slices (allocates memory). LEGACY version */ +int sfold_epm_create(size_t nr_slices, char *volume_key, sfold_EncPosMap *epm); #endif /* _HEADER_H_ */ diff --git a/shufflecake-userland/include/operations.h b/shufflecake-userland/include/operations.h index 8de9ab6..c4aaa81 100644 --- a/shufflecake-userland/include/operations.h +++ b/shufflecake-userland/include/operations.h @@ -41,22 +41,22 @@ * INLINE FUNCTIONS * *****************************************************/ -// Size, in 4096-byte blocks, of a whole volume header (VMB+PM) -static inline size_t sflc_volHeaderSize(size_t nr_slices) +// Size, in 4096-byte blocks, of a whole volume header (VMB+PM). LEGACY version +static inline size_t sfold_volHeaderSize(size_t nr_slices) { // Each PosMapBlock holds up to 1024 PSIs (Physical Slice Index) size_t nr_pmbs = ceil(nr_slices, SFLC_SLICE_IDX_PER_BLOCK); // Each array holds up to 256 PosMapBlocks - size_t nr_arrays = ceil(nr_pmbs, SFLC_BLOCKS_PER_LOG_SLICE); + size_t nr_arrays = ceil(nr_pmbs, SFLC_SLICE_SCALE); // 1 VMB, the PMBs, and the IV blocks return 1 + nr_pmbs + nr_arrays; } -// Position of the VMB for the given volume -static inline uint64_t sflc_vmbPosition(size_t vol_idx, size_t nr_slices) +// Position of the VMB for the given volume. LEGACY version +static inline uint64_t sfold_vmbPosition(size_t vol_idx, size_t nr_slices) { - return 1 + ((uint64_t) vol_idx) * ((uint64_t) sflc_volHeaderSize(nr_slices)); + return 1 + ((uint64_t) vol_idx) * ((uint64_t) sfold_volHeaderSize(nr_slices)); } @@ -71,14 +71,26 @@ int sflc_ops_readDmb(char *bdev_path, char *pwd, size_t pwd_len, sflc_DmbCell *d /* Reads the DMB from disk, changes the relevant DMB cell, and writes it back */ int sflc_ops_rewriteDmbCell(char *bdev_path, sflc_DmbCell *dmb_cell, char *new_pwd, size_t new_pwd_len); -/* Encrypts and writes a volume header (VMB+PM) on-disk */ -int sflc_ops_writeVolumeHeader(char *bdev_path, char *vmb_key, sflc_Vmb *vmb, size_t vol_idx); -/* Reads a VMB from disk and unlocks it */ -int sflc_ops_readVmb(char *bdev_path, char *vmb_key, size_t nr_slices, size_t vol_idx, sflc_Vmb *vmb); -/* Build parameter list for ctor in dm_sflc, and send DM ioctl to create virtual block device */ -int sflc_ops_openVolume(char *bdev_path, size_t dev_id, size_t vol_idx, sflc_Vmb *vmb); -/* Close the volume via the appropriate ioctl to DM */ -int sflc_ops_closeVolume(char *label); +/* Encrypts and writes a volume header (VMB+PM) on-disk. LITE version */ +int sflite_ops_writeVolumeHeader(char *bdev_path, char *vmb_key, sflc_Vmb *vmb, size_t vol_idx); +/* Reads a VMB from disk and unlocks it. LITE version */ +int sflite_ops_readVmb(char *bdev_path, char *vmb_key, size_t nr_slices, size_t vol_idx, sflc_Vmb *vmb); + +/* Encrypts and writes a volume header (VMB+PM) on-disk. LEGACY version */ +int sfold_ops_writeVolumeHeader(char *bdev_path, char *vmb_key, sflc_Vmb *vmb, size_t vol_idx); +/* Reads a VMB from disk and unlocks it. LEGACY version */ +int sfold_ops_readVmb(char *bdev_path, char *vmb_key, size_t nr_slices, size_t vol_idx, sflc_Vmb *vmb); + + +/* Build parameter list for ctor in dm_sflc, and send DM ioctl to create virtual block device. LITE version */ +int sflite_ops_openVolume(char *bdev_path, size_t dev_id, size_t vol_idx, sflc_Vmb *vmb); +/* Close the volume via the appropriate ioctl to DM. LITE version */ +int sflite_ops_closeVolume(char *label); + +/* Build parameter list for ctor in dm_sflc, and send DM ioctl to create virtual block device. LEGACY version */ +int sfold_ops_openVolume(char *bdev_path, size_t dev_id, size_t vol_idx, sflc_Vmb *vmb); +/* Close the volume via the appropriate ioctl to DM. LEGACY version */ +int sfold_ops_closeVolume(char *label); #endif /* _OPERATIONS_H_ */ diff --git a/shufflecake-userland/include/sflc_constants.h b/shufflecake-userland/include/sflc_constants.h deleted file mode 120000 index fab9e42..0000000 --- a/shufflecake-userland/include/sflc_constants.h +++ /dev/null @@ -1 +0,0 @@ -../../dm-sflc/sflc_constants.h \ No newline at end of file diff --git a/shufflecake-userland/include/utils/crypto.h b/shufflecake-userland/include/utils/crypto.h index 15ac111..8366134 100644 --- a/shufflecake-userland/include/utils/crypto.h +++ b/shufflecake-userland/include/utils/crypto.h @@ -41,20 +41,21 @@ *****************************************************/ // Key length, for input into AES-CTR and AES-GCM, and for output from Argon -#define SFLC_CRYPTO_KEYLEN 32 /* bytes */ +#define SFLC_STANDARD_KEYLEN 32 /* bytes */ +// Key length for AES-XTS +#define SFLC_AESXTS_KEYLEN 64 /* bytes */ // IV length for AES-CTR #define SFLC_AESCTR_IVLEN 16 /* bytes */ +// IV length for AES-XTS +#define SFLC_AESXTS_IVLEN 16 /* bytes */ // IV length for AES-GCM #define SFLC_AESGCM_IVLEN 12 /* bytes */ - // IVs occupy 16 bytes on-disk, but only the *FIRST* 12 are used for AES-GCM #define SFLC_AESGCM_PADDED_IVLEN 16 /* bytes */ - // MAC length for AES-GCM #define SFLC_AESGCM_TAGLEN 16 /* bytes */ - // Content of output plaintext upon MAC verification failure #define SFLC_AESGCM_POISON_PT 0xFF @@ -81,9 +82,9 @@ * PUBLIC FUNCTIONS PROTOTYPES * *****************************************************/ -/* Get slow, true random bytes (suited for keys) */ +/* Get slow, strong random bytes (suited for keys) */ int sflc_rand_getStrongBytes(char *buf, size_t buflen); -/* Get fast, pseudo random bytes (suited for IVs and padding) */ +/* Get fast, weak(er) random bytes (suited for IVs and padding) */ int sflc_rand_getWeakBytes(char *buf, size_t buflen); /* AES256-CTR encryption, does not touch the IV. Set ct = NULL for in-place. */ @@ -91,6 +92,10 @@ int sflc_aes256ctr_encrypt(char *key, char *pt, size_t pt_len, char *iv, char *c /* AES256-CTR decryption, does not touch the IV. Set pt = NULL for in-place. */ int sflc_aes256ctr_decrypt(char *key, char *ct, size_t ct_len, char *iv, char *pt); +/* AES256-XTS encryption. Set ct = NULL for in-place. + * The IV is intepreted as a little-endian "sector number" */ +int sflc_aes256xts_encrypt(char *key, char *pt, size_t pt_len, char *iv, char *ct); + /* AES256-GCM encryption, does not touch the IV */ int sflc_aes256gcm_encrypt(char *key, char *pt, size_t pt_len, char *iv, char *ct, char *tag); /* AES256-GCM decryption, does not touch the IV (only decrypts if MAC is valid) */ diff --git a/shufflecake-userland/include/utils/disk.h b/shufflecake-userland/include/utils/disk.h index 7666609..426921f 100644 --- a/shufflecake-userland/include/utils/disk.h +++ b/shufflecake-userland/include/utils/disk.h @@ -35,6 +35,7 @@ #include #include +#include "utils/math.h" #include "utils/sflc.h" @@ -43,65 +44,60 @@ *****************************************************/ /** - * Max slices for given disk size (in 4096-byte blocks). - * - * The bigger a disk is, the more slices it can host. However, the more slices we format it with, - * the bigger the position map needed to index them: the header size grows with the number of slices, - * taking up part of the space that's supposed to host those slices. - * To settle the matter, let us derive an upper bound on the header size, yielding a "safe" value - * for the number of slices (given a disk size). - * - * To index s slices, we need pm := ceil(s/1024) <= s/1024 + 1 PosMap blocks, since each PosMap - * block (4096 bytes) can host 1024 slice indices (4 bytes each). - * - * To encrypt those PosMap blocks, we need iv := ceil(pm/256) <= pm IV blocks, since each IV block - * (4096 bytes) can encrypt 256 data blocks (IVs are 16 bytes). - * - * Therefore, a position map indexing s slices occupies pm+iv <= 2*pm <= 2*s/1024 + 2 blocks. - * - * A single volume's header contains the Volume Master Block and the position map, therefore it - * occupies 1+pm+iv <= 2*s/1024 + 3 blocks. - * - * The entire device's header simply contains 15 volume headers of the same size, therefore it - * occupies h := 15 * (1+pm+iv) <= 15*2*s/1024 + 3*15 <= s + 3*15 blocks. - * The last inequality follows from 15*2/1024 <= 1 (we need to enforce this on the symbolic values). - * - * To actually host the s slices, the data section needs 257*s blocks (256 data blocks + 1 IV block - * per slice). - * - * Therefore, in order to format a disk with s slices, we need at most (s + 3*15) + 257*s = - * = (1 + 257)*s + 3*15 blocks. - * - * If we are given d blocks on the disk, a safe value for s is one that satisfies - * (1 + 257)*s + 3*15 <= d <==> s <= (d - 3*15) / (1 + 257) + * Max slices for given disk size (in 4096-byte blocks). LITE version */ -#define sflc_disk_maxSlices(size) (size - 3*SFLC_DEV_MAX_VOLUMES) / (1 + SFLC_BLOCKS_PER_PHYS_SLICE) +static inline uint32_t sflite_disk_maxSlices(uint64_t size) { + uint64_t nr_slices; + // Start from upper bound + nr_slices = size / SFLC_SLICE_SCALE; + while(true) { + if (nr_slices == 0) + break; -/* Let us enforce, on the symbolic values, the inequality used in the previous bound */ + // Stop when this nr_slices can fit in size, including the header + uint64_t posmap_blocks = ceil(nr_slices, SFLC_SLICE_IDX_PER_BLOCK); + uint64_t header_size = 1 + SFLC_DEV_MAX_VOLUMES * (1 + posmap_blocks); + if (header_size + nr_slices*SFLC_SLICE_SCALE <= size) + break; + + nr_slices--; + } + + return nr_slices > SFLC_MAX_SLICES ? SFLC_MAX_SLICES : (uint32_t) nr_slices; +} + +/* LEGACY version */ +#define sfold_disk_maxSlices(size) (size - 3*SFLC_DEV_MAX_VOLUMES) / (1 + SFOLD_BLOCKS_PER_PHYS_SLICE) +/* We need this inequality to hold, in order for the previous bound to be true */ #if SFLC_DEV_MAX_VOLUMES * 2 > SFLC_SLICE_IDX_PER_BLOCK #error "Invalid combination of parameters, probably SFLC_DEV_MAX_VOLUMES is too big" #endif + + /***************************************************** * PUBLIC FUNCTIONS PROTOTYPES * *****************************************************/ +/* Returns a malloc'ed string formatted as : */ +char *sflc_disk_getDeviceName(char *bdev_path); + /* Checks whether the given path points to a block device */ bool sflc_disk_isBlockDevice(char *path); /* Returns the size in 4096-byte sectors (or < 0 if error) */ -int64_t sflc_disk_getSize(char * bdev_path); +int64_t sflc_disk_getSize(char *bdev_path); -/* Reads a single 4096-byte sector from the disk */ -int sflc_disk_readSector(char * bdev_path, uint64_t sector, char * buf); +/* Reads a single 4096-byte block from the disk */ +int sflc_disk_readBlock(char *bdev_path, uint64_t bnum, char *buf); -/* Writes a single 4096-byte sector to the disk */ -int sflc_disk_writeSector(char * bdev_path, uint64_t sector, char * buf); +/* Writes many 4096-byte blocks to the disk */ +int sflc_disk_writeManyBlocks(char *bdev_path, uint64_t bnum, char *buf, size_t num_blocks); -/* Writes many 4096-byte sectors to the disk */ -int sflc_disk_writeManySectors(char * bdev_path, uint64_t sector, char * buf, size_t num_sectors); +/* Writes a single 4096-byte block to the disk */ +#define sflc_disk_writeBlock(bdev_path, bnum, buf) sflc_disk_writeManyBlocks(bdev_path, bnum, buf, 1) #endif /* _UTILS_DISK_H_ */ diff --git a/shufflecake-userland/include/utils/input.h b/shufflecake-userland/include/utils/input.h index 9463999..52e07fb 100644 --- a/shufflecake-userland/include/utils/input.h +++ b/shufflecake-userland/include/utils/input.h @@ -43,4 +43,4 @@ int sflc_safeReadLine(char *buf, size_t bufsize); /* Reads a password or passphrase (discarding the newline) from stdin in a secure way (no echo) */ int sflc_safeReadPassphrase(char *buf, size_t bufsize); -#endif /* _UTILS_FILE_H_ */ +#endif /* _UTILS_INPUT_H_ */ diff --git a/shufflecake-userland/include/utils/log.h b/shufflecake-userland/include/utils/log.h index 2088fbb..0fd35d7 100644 --- a/shufflecake-userland/include/utils/log.h +++ b/shufflecake-userland/include/utils/log.h @@ -120,13 +120,13 @@ static inline void sflc_log_hex(char *str, size_t len) for (i = 0; i < len; i++) { printf("%02x ", s[i]); // Nice aligned wrapping - if (i % 16 == 15) { + if (i % 32 == 31) { printf("\n"); } } // Always end with a newline - if (i % 16 != 0) { + if (i % 32 != 0) { printf("\n"); } diff --git a/shufflecake-userland/include/utils/sflc.h b/shufflecake-userland/include/utils/sflc.h index e8135e4..499f5ae 100644 --- a/shufflecake-userland/include/utils/sflc.h +++ b/shufflecake-userland/include/utils/sflc.h @@ -41,10 +41,20 @@ /* Name of the DM target in the kernel */ #define SFLC_DM_TARGET_NAME "shufflecake" -/* Disk constants */ -#define SFLC_SECTOR_SIZE 4096 /* bytes */ -#define KERNEL_SECTOR_SIZE 512 /* bytes */ -#define SFLC_SECTOR_SCALE (SFLC_SECTOR_SIZE / KERNEL_SECTOR_SIZE) +/* Modes */ +#define SFLC_MODE_LEGACY 0 +#define SFLC_MODE_LITE 1 +#define SFLC_MODE_FULL 2 + +/* Sizes */ +#define KERNEL_SECTOR_SIZE 512 /* bytes */ +#define SFLC_BLOCK_SIZE 4096 /* bytes */ +#define SFLC_BLOCK_SCALE (SFLC_BLOCK_SIZE / KERNEL_SECTOR_SIZE) +#define SFLC_SLICE_SCALE 256 /* blocks in a slice */ +#define SFLC_MAX_SLICES (UINT32_MAX - 1) /* 0xFFFFFFFF is reserved */ + +/* For legacy */ +#define SFOLD_BLOCKS_PER_PHYS_SLICE (SFLC_SLICE_SCALE + 1) /* Max number of volumes in a device */ #define SFLC_DEV_MAX_VOLUMES 15 @@ -57,27 +67,20 @@ /* A slice index is represented over 32 bits */ #define SFLC_SLICE_IDX_WIDTH 4 /* bytes */ /* A position map block contains 1024 slice indices */ -#define SFLC_SLICE_IDX_PER_BLOCK (SFLC_SECTOR_SIZE / SFLC_SLICE_IDX_WIDTH) +#define SFLC_SLICE_IDX_PER_BLOCK (SFLC_BLOCK_SIZE / SFLC_SLICE_IDX_WIDTH) -// IV length for AES-CTR -#define SFLC_AESCTR_IVLEN 16 /* bytes */ - -/* An IV block can encrypt 256 data blocks */ -#define SFLC_DATA_BLOCKS_PER_IV_BLOCK (SFLC_SECTOR_SIZE / SFLC_AESCTR_IVLEN) -/* A logical slice spans 256 blocks of data (1 MiB) */ -#define SFLC_BLOCKS_PER_LOG_SLICE SFLC_DATA_BLOCKS_PER_IV_BLOCK -/* A physical slice also includes the IV block */ -#define SFLC_BLOCKS_PER_PHYS_SLICE (1 + SFLC_BLOCKS_PER_LOG_SLICE) /* A PSI of 0xFFFFFFFF indicates an unassigned LSI */ #define SFLC_EPM_FILLER 0xFF /* The sysfs file containing the next available device ID */ -#define SFLC_SYSFS_NEXTDEVID "/sys/devices/sflc/next_dev_id" +#define SFLC_SYSFS_NEXTDEVID "/sys/module/dm_sflc/next_dev_id" /* The sysfs directory containing a subdir for each (underlying) block device */ #define SFLC_SYSFS_BDEVS_DIR "/sys/module/dm_sflc/bdevs" -/* Within each bdev's subdir, this file lists its open volumes */ +/* Within each bdev's subdir, this file shows its number of open volumes */ #define SFLC_SYSFS_OPENVOLUMES_FILENAME "volumes" +/* Within each bdev's subdir, this file shows its Shufflecake device ID */ +#define SFLC_SYSFS_DEVID_FILENAME "dev_id" /* TODO: reasonable? */ #define SFLC_BDEV_PATH_MAX_LEN 1024 diff --git a/shufflecake-userland/src/cli/close.c b/shufflecake-userland/src/cli/close.c index fdbaa28..da4c02f 100644 --- a/shufflecake-userland/src/cli/close.c +++ b/shufflecake-userland/src/cli/close.c @@ -47,14 +47,14 @@ */ int sflc_cli_close(char *block_device) { // Requires: block_device is a correct block device path -// char bdev_path[SFLC_BDEV_PATH_MAX_LEN + 2]; +// char bdev_path[SFLITE_BDEV_PATH_MAX_LEN + 2]; // int err; // /* Gather (absolute) path to underlying block device */ // printf("Enter the absolute path to the underlying block device containing the Shufflecake volumes to close: "); -// err = sflc_safeReadLine(bdev_path, SFLC_BDEV_PATH_MAX_LEN + 2); +// err = sflite_safeReadLine(bdev_path, SFLITE_BDEV_PATH_MAX_LEN + 2); // if (err) { -// sflc_log_error("Could not read path to underlying block device; error %d", err); +// sflite_log_error("Could not read path to underlying block device; error %d", err); // return err; // } // /* Check that it is absolute */ @@ -66,7 +66,7 @@ int sflc_cli_close(char *block_device) /* Actually perform the command */ -// return sflc_cmd_closeVolumes(bdev_path); +// return sflite_cmd_closeVolumes(bdev_path); return sflc_cmd_closeVolumes(block_device); diff --git a/shufflecake-userland/src/cli/dispatch.c b/shufflecake-userland/src/cli/dispatch.c index 01da250..0bed6ff 100644 --- a/shufflecake-userland/src/cli/dispatch.c +++ b/shufflecake-userland/src/cli/dispatch.c @@ -35,7 +35,6 @@ #include "utils/sflc.h" #include "utils/disk.h" #include "utils/log.h" -#include "sflc_constants.h" /***************************************************** @@ -43,13 +42,14 @@ *****************************************************/ /* Used by argp to provide the automatic "-V" option */ -const char *argp_program_version = SFLC_VERSION; +const char *argp_program_version = "0.5.0"; // Temporary hack /* Used by argp to provide the automatic "--help" option */ const char *argp_program_bug_address = ""; /* Signed integer values representing a handle for each option */ #define SFLC_OPT_NUMVOLS_KEY 'n' // Positive and printable: also serves as short command-line option #define SFLC_OPT_SKIPRAND_KEY (-'r') // Negative, because we don't want a short option available for this +#define SFLC_OPT_LEGACY_KEY (-'l') /***************************************************** @@ -67,6 +67,7 @@ enum sflc_cli_action { struct sflc_cli_arguments { enum sflc_cli_action act; char *block_device; + int sflc_mode; int num_volumes; bool skip_randfill; }; @@ -115,6 +116,7 @@ static struct argp_option options[] = { "Specify number of volumes to be created with `init'. Must be an integer between 1 and 15.", 0 }, // TODO: define MAX_VOLS instead of hardcoding 15 {"skip-randfill", SFLC_OPT_SKIPRAND_KEY, 0, 0, "Skip pre-overwriting block device with random data, only valid with `init'. Faster but less secure. Use only for debugging or testing."}, + {"legacy", SFLC_OPT_LEGACY_KEY, 0, 0, "Use the old (pre-v0.5.0) Shufflecake format. Only valid with `init` and `open'. Use of this option is not recommended. This mode is going to be deprecated in future versions."}, {0} }; @@ -141,6 +143,7 @@ int sflc_cli_dispatch(int argc, char **argv) { arguments.act = -1; arguments.block_device = NULL; + arguments.sflc_mode = SFLC_MODE_LITE; arguments.num_volumes = 0; arguments.skip_randfill = false; @@ -153,6 +156,13 @@ int sflc_cli_dispatch(int argc, char **argv) { return EINVAL; } /* Check options consistency */ + if (arguments.sflc_mode == SFLC_MODE_LEGACY && + arguments.act != SFLC_ACT_INIT && + arguments.act != SFLC_ACT_OPEN) { + printf("Error: --legacy (-l) can only be combined with `init' or 'open'.\n"); + return EINVAL; + } + /* Check options consistency */ if (arguments.skip_randfill && arguments.act != SFLC_ACT_INIT) { printf("Error: --skip-randfill can only be combined with `init'.\n"); return EINVAL; @@ -165,10 +175,10 @@ int sflc_cli_dispatch(int argc, char **argv) { /* Dispatch to specific command */ if (arguments.act == SFLC_ACT_INIT) { - return sflc_cli_init(arguments.block_device, arguments.num_volumes, arguments.skip_randfill); + return sflc_cli_init(arguments.block_device, arguments.sflc_mode, arguments.num_volumes, arguments.skip_randfill); } if (arguments.act == SFLC_ACT_OPEN) { - return sflc_cli_open(arguments.block_device); + return sflc_cli_open(arguments.block_device, arguments.sflc_mode); } if (arguments.act == SFLC_ACT_CLOSE) { return sflc_cli_close(arguments.block_device); @@ -225,6 +235,9 @@ static error_t _parseArgpKey(int key, char *arg, struct argp_state *state) { case SFLC_OPT_NUMVOLS_KEY: arguments->num_volumes = atoi(arg); break; + case SFLC_OPT_LEGACY_KEY: + arguments->sflc_mode = SFLC_MODE_LEGACY; + break; case SFLC_OPT_SKIPRAND_KEY: arguments->skip_randfill = true; break; diff --git a/shufflecake-userland/src/cli/init.c b/shufflecake-userland/src/cli/init.c index 302a96d..85f5074 100644 --- a/shufflecake-userland/src/cli/init.c +++ b/shufflecake-userland/src/cli/init.c @@ -45,7 +45,7 @@ * * @return Error code, 0 on success */ -int sflc_cli_init(char *block_device, int num_volumes, int skip_randfill) +int sflc_cli_init(char *block_device, int sflc_mode, int num_volumes, int skip_randfill) { // Requires: block_device is a correct block device path sflc_cmd_InitArgs args; char str_nrvols[SFLC_BIGBUFSIZE]; @@ -54,6 +54,7 @@ int sflc_cli_init(char *block_device, int num_volumes, int skip_randfill) int err; args.bdev_path = block_device; + args.sflc_mode = sflc_mode; // Check if number of volumes was nonzero passed by command line already if (num_volumes) { @@ -114,5 +115,15 @@ int sflc_cli_init(char *block_device, int num_volumes, int skip_randfill) args.no_randfill = skip_randfill; /* Actually perform the command */ - return sflc_cmd_initVolumes(&args); + switch(sflc_mode) + { + case SFLC_MODE_LEGACY: + return sfold_cmd_initVolumes(&args); + case SFLC_MODE_LITE: + return sflite_cmd_initVolumes(&args); + default: + sflc_log_error("WTF, sflc_mode out of bounds!"); + return ENOTRECOVERABLE; + } + } diff --git a/shufflecake-userland/src/cli/open.c b/shufflecake-userland/src/cli/open.c index 45464c9..ae1cb8d 100644 --- a/shufflecake-userland/src/cli/open.c +++ b/shufflecake-userland/src/cli/open.c @@ -45,7 +45,7 @@ * * @return Error code, 0 on success */ -int sflc_cli_open(char *block_device) +int sflc_cli_open(char *block_device, int sflc_mode) { // Requires: block_device is a correct block device path sflc_cmd_OpenArgs args; char pwd[SFLC_BIGBUFSIZE]; @@ -73,5 +73,15 @@ int sflc_cli_open(char *block_device) args.pwd_len = pwd_len; /* Actually perform the command */ - return sflc_cmd_openVolumes(&args); + /* Actually perform the command */ + switch(sflc_mode) + { + case SFLC_MODE_LEGACY: + return sfold_cmd_openVolumes(&args); + case SFLC_MODE_LITE: + return sflite_cmd_openVolumes(&args); + default: + sflc_log_error("WTF, sflc_mode out of bounds!"); + return ENOTRECOVERABLE; + } } diff --git a/shufflecake-userland/src/commands/change_pwd.c b/shufflecake-userland/src/commands/change_pwd.c index 2ef64e0..b823662 100644 --- a/shufflecake-userland/src/commands/change_pwd.c +++ b/shufflecake-userland/src/commands/change_pwd.c @@ -53,6 +53,6 @@ */ int sflc_cmd_changePwd(sflc_cmd_ChangePwdArgs *args) { - /* Delegate entirely to the function reading the DMB */ + /* Delegate entirely to the function rewriting the DMB */ return sflc_ops_rewriteDmbCell(args->bdev_path, args->dmb_cell, args->new_pwd, args->new_pwd_len); } diff --git a/shufflecake-userland/src/commands/close.c b/shufflecake-userland/src/commands/close.c index 4c180f6..28e63d4 100644 --- a/shufflecake-userland/src/commands/close.c +++ b/shufflecake-userland/src/commands/close.c @@ -35,6 +35,7 @@ #include "utils/crypto.h" #include "utils/string.h" #include "utils/file.h" +#include "utils/disk.h" #include "utils/log.h" @@ -43,7 +44,7 @@ *****************************************************/ /* Reads the list of volumes from sysfs */ -static int _readVolumesList(char *bdev_path, char **labels, size_t *nr_vols); +static int _buildVolumesList(char *bdev_path, char **labels, size_t *nr_vols); /* Close them all (in reverse order of opening) */ static int _closeVolumes(char **labels, size_t nr_vols); @@ -77,7 +78,7 @@ int sflc_cmd_closeVolumes(char *bdev_path) } /* Read them */ - err = _readVolumesList(bdev_path, labels, &nr_vols); + err = _buildVolumesList(bdev_path, labels, &nr_vols); if (err) { sflc_log_error("Could not read volume list from sysfs; error %d", err); goto out; @@ -106,31 +107,50 @@ out: * PRIVATE FUNCTIONS PROTOTYPES * *****************************************************/ -/* Reads the list of volumes from sysfs */ -static int _readVolumesList(char *bdev_path, char **labels, size_t *nr_vols) +/* Reads from sysfs to build the volumes list */ +static int _buildVolumesList(char *bdev_path, char **labels, size_t *nr_vols) { - char bdev_path_noslash[SFLC_BDEV_PATH_MAX_LEN + 1]; - char openvolumes_path[SFLC_BIGBUFSIZE]; - char *str_openvolumes; + char *bdev_name; + char devid_path[SFLC_BIGBUFSIZE]; + char *str_devid; + size_t dev_id; + char nrvolumes_path[SFLC_BIGBUFSIZE]; + char *str_nrvolumes; - /* Remove the slashes from the bdev_path (replace with underscores) */ - strcpy(bdev_path_noslash, bdev_path); - sflc_str_replaceAll(bdev_path_noslash, '/', '_'); - /* Build path to sysfsy file containing open volumes list */ - sprintf(openvolumes_path, "%s/%s/%s", SFLC_SYSFS_BDEVS_DIR, bdev_path_noslash, SFLC_SYSFS_OPENVOLUMES_FILENAME); + /* Get device name as : */ + bdev_name = sflc_disk_getDeviceName(bdev_path); + if(!bdev_name) { + sflc_log_error("Could not allocate device name"); + return ENOMEM; + } + /* Build path to sysfs file containing device ID */ + sprintf(devid_path, "%s/%s/%s", SFLC_SYSFS_BDEVS_DIR, bdev_name, SFLC_SYSFS_DEVID_FILENAME); + /* Build path to sysfs file containing number of open volumes */ + sprintf(nrvolumes_path, "%s/%s/%s", SFLC_SYSFS_BDEVS_DIR, bdev_name, SFLC_SYSFS_OPENVOLUMES_FILENAME); - /* Read the sysfs file */ - str_openvolumes = sflc_readFile(openvolumes_path); - if (!str_openvolumes) { - sflc_log_error("Could not read file %s", openvolumes_path); + /* Read the device ID */ + str_devid = sflc_readFile(devid_path); + if (!str_devid) { + sflc_log_error("Could not read file %s", devid_path); + return EBADF; + } + /* Parse the device ID */ + if (sscanf(str_devid, "%lu", &dev_id) != 1) { + sflc_log_error("Could not parse device ID:\n%s", str_devid); return EBADF; } + /* Read the number of volumes */ + str_nrvolumes = sflc_readFile(nrvolumes_path); + if (!str_nrvolumes) { + sflc_log_error("Could not read file %s", nrvolumes_path); + return EBADF; + } /* Parse the number of volumes */ - char *endptr; - *nr_vols = strtoul(str_openvolumes, &endptr, 10); - /* Skip past the number of volumes (lands on a whitespace before the first label) */ - str_openvolumes = endptr; + if (sscanf(str_nrvolumes, "%lu", nr_vols) != 1) { + sflc_log_error("Could not parse number of volumes:\n%s", str_nrvolumes); + return EBADF; + } /* Just to be sure */ if (*nr_vols > SFLC_DEV_MAX_VOLUMES) { @@ -138,18 +158,10 @@ static int _readVolumesList(char *bdev_path, char **labels, size_t *nr_vols) return EBADF; } - /* Read labels */ + /* Build labels */ size_t i; for (i = 0; i < *nr_vols; i++) { - /* Trust the content of the sysfs file */ - if (sscanf(str_openvolumes, " %s", labels[i]) != 1) { - sflc_log_error("Could not read volume label %lu. Sysfs content:\n%s", i, str_openvolumes); - return EBADF; - } - sflc_log_debug("Label %lu to close: %s", i, labels[i]); - - /* Skip past the whitespace and the label */ - str_openvolumes += 1 + strlen(labels[i]); + sprintf(labels[i], "sflc_%lu_%lu", dev_id, i); } return 0; @@ -164,7 +176,7 @@ static int _closeVolumes(char **labels, size_t nr_vols) /* Eazy peazy */ int i; for (i = nr_vols-1; i >= 0; i--) { - err = sflc_ops_closeVolume(labels[i]); + err = sflite_ops_closeVolume(labels[i]); if (err) { sflc_log_error("Could not close volume %s; error %d", labels[i], err); return err; diff --git a/shufflecake-userland/src/commands/init_legacy.c b/shufflecake-userland/src/commands/init_legacy.c new file mode 100644 index 0000000..3ee1c81 --- /dev/null +++ b/shufflecake-userland/src/commands/init_legacy.c @@ -0,0 +1,202 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +/***************************************************** + * INCLUDE SECTION * + *****************************************************/ + +#include +#include +#include + +#include "commands.h" +#include "operations.h" +#include "utils/sflc.h" +#include "utils/disk.h" +#include "utils/crypto.h" +#include "utils/log.h" + + +/***************************************************** + * CONSTANTS * + *****************************************************/ + +/* The device is randomised in chunks of 1024 blocks (arbitrary number) */ +#define SFLC_BLOCKS_IN_RAND_CHUNK 1024 +/* That's 4 MiB */ +#define SFLC_RAND_CHUNK_SIZE (SFLC_BLOCKS_IN_RAND_CHUNK * SFLC_BLOCK_SIZE) + + +/***************************************************** + * PRIVATE FUNCTIONS PROTOTYPES * + *****************************************************/ + +/* Fill the device with random data */ +static int _fillDiskWithRandom(char *bdev_path, uint64_t dev_size); + + +/***************************************************** + * PUBLIC FUNCTIONS DEFINITIONS * + *****************************************************/ + +/** + * Create N volumes (only formats the device header, does not open the volumes). + * Creates them in order from 0 to N-1, so as to induce a back-linked list on the device. + * + * @param args->bdev_path The path to the underlying block device + * @param args->nr_vols The number of volumes to create + * @param args->pwds The array of passwords for the various volumes + * @param args->pwd_lens The length of each password + * @param args->no_randfill A boolean switch indicating that the volume should not + * be filled entirely with random data prior to formatting. + * + * @return Error code, 0 on success + */ +int sfold_cmd_initVolumes(sflc_cmd_InitArgs *args) +{ + sflc_Dmb dmb; + sflc_Vmb vmb; + int64_t dev_size; + size_t nr_slices; + int err; + + /* Sanity check */ + if (args->nr_vols > SFLC_DEV_MAX_VOLUMES) { + sflc_log_error("Cannot create %lu volumes on a single device", args->nr_vols); + return EINVAL; + } + + /* Get device size */ + dev_size = sflc_disk_getSize(args->bdev_path); + if (dev_size < 0) { + err = -dev_size; + sflc_log_error("Could not get device size for %s; error %d", args->bdev_path, err); + return err; + } + /* Convert to number of slices */ + nr_slices = sfold_disk_maxSlices(dev_size); + sflc_log_debug("Device %s has %ld blocks, corresponding to %lu logical slices", args->bdev_path, dev_size, nr_slices); + + /* Fill disk with random bytes, if requested */ + if (!args->no_randfill) { + err = _fillDiskWithRandom(args->bdev_path, (uint64_t) dev_size); + if (err) { + sflc_log_error("Could not fill device %s with random bytes; error %d", args->bdev_path, err); + return err; + } + } + + /* Fill the DMB */ + dmb.nr_vols = args->nr_vols; + /* Sample the VMB keys */ + size_t i; + for (i = 0; i < dmb.nr_vols; i++) { + err = sflc_rand_getStrongBytes(dmb.vmb_keys[i], SFLC_STANDARD_KEYLEN); + if (err) { + sflc_log_error("Could not sample VMB key number %lu; error %d", i , err); + return err; + } + } + /* And write (encrypted) to disk */ + err = sflc_ops_writeDmb(args->bdev_path, args->pwds, args->pwd_lens, &dmb); + if (err) { + sflc_log_error("Could not create DMB and write it to disk; error %d", err); + return err; + } + + /* Write the volume headers */ + vmb.nr_slices = nr_slices; + for (i = 0; i < args->nr_vols; i++) { + /* This volume's prev_vmb_key */ + if (i > 0) { + memcpy(vmb.prev_vmb_key, dmb.vmb_keys[i-1], SFLC_STANDARD_KEYLEN); + } + /* Sample this volume's VEK */ + sflc_rand_getStrongBytes(vmb.volume_key_legacy, SFLC_STANDARD_KEYLEN); + + /* Write complete volume header (VMB + PM) */ + err = sfold_ops_writeVolumeHeader(args->bdev_path, dmb.vmb_keys[i], &vmb, i); + if (err) { + sflc_log_error("Error writing volume header %lu on device %s; error %d", i, args->bdev_path, err); + return err; + } + } + printf("Created %lu volumes on device %s\n", args->nr_vols, args->bdev_path); + + return 0; +} + + +/***************************************************** + * PRIVATE FUNCTIONS PROTOTYPES * + *****************************************************/ + +/* Fill the device with random data */ +static int _fillDiskWithRandom(char *bdev_path, uint64_t dev_size) +{ + char *rand_chunk; + int err; + + /* Allocate chunk */ + rand_chunk = malloc(SFLC_RAND_CHUNK_SIZE); + if (!rand_chunk) { + sflc_log_error("Could not allocate %d bytes for chunk of random data", SFLC_RAND_CHUNK_SIZE); + return ENOMEM; + } + + /* Loop to write random data in chunks */ + uint64_t blocks_remaining = dev_size; + uint64_t sector = 0; + while (blocks_remaining > 0) { + uint64_t blocks_to_write = + (blocks_remaining > SFLC_BLOCKS_IN_RAND_CHUNK) ? SFLC_BLOCKS_IN_RAND_CHUNK : blocks_remaining; + uint64_t bytes_to_write = blocks_to_write * SFLC_BLOCK_SIZE; + + /* Sample random bytes */ + err = sflc_rand_getWeakBytes(rand_chunk, bytes_to_write); + if (err) { + sflc_log_error("Could not sample %lu random bytes to write on disk; error %d", bytes_to_write, err); + goto out; + } + + /* Write on disk */ + err = sflc_disk_writeManyBlocks(bdev_path, sector, rand_chunk, blocks_to_write); + if (err) { + sflc_log_error("Could not write random bytes on disk; error %d", err); + goto out; + } + + /* Advance loop */ + sector += blocks_to_write; + blocks_remaining -= blocks_to_write; + } + + /* No prob */ + err = 0; + + +out: + free(rand_chunk); + return err; +} + diff --git a/shufflecake-userland/src/commands/init.c b/shufflecake-userland/src/commands/init_lite.c similarity index 90% rename from shufflecake-userland/src/commands/init.c rename to shufflecake-userland/src/commands/init_lite.c index cd21b03..f65d1b6 100644 --- a/shufflecake-userland/src/commands/init.c +++ b/shufflecake-userland/src/commands/init_lite.c @@ -44,7 +44,7 @@ /* The device is randomised in chunks of 1024 blocks (arbitrary number) */ #define SFLC_BLOCKS_IN_RAND_CHUNK 1024 /* That's 4 MiB */ -#define SFLC_RAND_CHUNK_SIZE (SFLC_BLOCKS_IN_RAND_CHUNK * SFLC_SECTOR_SIZE) +#define SFLC_RAND_CHUNK_SIZE (SFLC_BLOCKS_IN_RAND_CHUNK * SFLC_BLOCK_SIZE) /***************************************************** @@ -72,7 +72,7 @@ static int _fillDiskWithRandom(char *bdev_path, uint64_t dev_size); * * @return Error code, 0 on success */ -int sflc_cmd_initVolumes(sflc_cmd_InitArgs *args) +int sflite_cmd_initVolumes(sflc_cmd_InitArgs *args) { sflc_Dmb dmb; sflc_Vmb vmb; @@ -94,7 +94,7 @@ int sflc_cmd_initVolumes(sflc_cmd_InitArgs *args) return err; } /* Convert to number of slices */ - nr_slices = sflc_disk_maxSlices(dev_size); + nr_slices = sflite_disk_maxSlices(dev_size); sflc_log_debug("Device %s has %ld blocks, corresponding to %lu logical slices", args->bdev_path, dev_size, nr_slices); /* Fill disk with random bytes, if requested */ @@ -111,7 +111,7 @@ int sflc_cmd_initVolumes(sflc_cmd_InitArgs *args) /* Sample the VMB keys */ size_t i; for (i = 0; i < dmb.nr_vols; i++) { - err = sflc_rand_getStrongBytes(dmb.vmb_keys[i], SFLC_CRYPTO_KEYLEN); + err = sflc_rand_getStrongBytes(dmb.vmb_keys[i], SFLC_STANDARD_KEYLEN); if (err) { sflc_log_error("Could not sample VMB key number %lu; error %d", i , err); return err; @@ -129,13 +129,13 @@ int sflc_cmd_initVolumes(sflc_cmd_InitArgs *args) for (i = 0; i < args->nr_vols; i++) { /* This volume's prev_vmb_key */ if (i > 0) { - memcpy(vmb.prev_vmb_key, dmb.vmb_keys[i-1], SFLC_CRYPTO_KEYLEN); + memcpy(vmb.prev_vmb_key, dmb.vmb_keys[i-1], SFLC_STANDARD_KEYLEN); } /* Sample this volume's VEK */ - sflc_rand_getStrongBytes(vmb.volume_key, SFLC_CRYPTO_KEYLEN); + sflc_rand_getStrongBytes(vmb.volume_key_lite, SFLC_AESXTS_KEYLEN); /* Write complete volume header (VMB + PM) */ - err = sflc_ops_writeVolumeHeader(args->bdev_path, dmb.vmb_keys[i], &vmb, i); + err = sflite_ops_writeVolumeHeader(args->bdev_path, dmb.vmb_keys[i], &vmb, i); if (err) { sflc_log_error("Error writing volume header %lu on device %s; error %d", i, args->bdev_path, err); return err; @@ -170,7 +170,7 @@ static int _fillDiskWithRandom(char *bdev_path, uint64_t dev_size) while (blocks_remaining > 0) { uint64_t blocks_to_write = (blocks_remaining > SFLC_BLOCKS_IN_RAND_CHUNK) ? SFLC_BLOCKS_IN_RAND_CHUNK : blocks_remaining; - uint64_t bytes_to_write = blocks_to_write * SFLC_SECTOR_SIZE; + uint64_t bytes_to_write = blocks_to_write * SFLC_BLOCK_SIZE; /* Sample random bytes */ err = sflc_rand_getWeakBytes(rand_chunk, bytes_to_write); @@ -180,7 +180,7 @@ static int _fillDiskWithRandom(char *bdev_path, uint64_t dev_size) } /* Write on disk */ - err = sflc_disk_writeManySectors(bdev_path, sector, rand_chunk, blocks_to_write); + err = sflc_disk_writeManyBlocks(bdev_path, sector, rand_chunk, blocks_to_write); if (err) { sflc_log_error("Could not write random bytes on disk; error %d", err); goto out; diff --git a/shufflecake-userland/src/commands/open.c b/shufflecake-userland/src/commands/open_legacy.c similarity index 89% rename from shufflecake-userland/src/commands/open.c rename to shufflecake-userland/src/commands/open_legacy.c index da0c4f0..66660d4 100644 --- a/shufflecake-userland/src/commands/open.c +++ b/shufflecake-userland/src/commands/open_legacy.c @@ -65,7 +65,7 @@ static int _getNextDevId(size_t *next_dev_id); * * @return Error code (also if no volume could be opened), 0 on success */ -int sflc_cmd_openVolumes(sflc_cmd_OpenArgs *args) +int sfold_cmd_openVolumes(sflc_cmd_OpenArgs *args) { int64_t dev_size; size_t nr_slices; @@ -73,18 +73,19 @@ int sflc_cmd_openVolumes(sflc_cmd_OpenArgs *args) sflc_Vmb vmbs[SFLC_DEV_MAX_VOLUMES]; size_t dev_id; int err; - char bdev_path_noslash[SFLC_BDEV_PATH_MAX_LEN + 1]; + char *bdev_name; char opendev_path[SFLC_BIGBUFSIZE]; DIR* opendev_dir; /* Check if device is already opened and abort if so. */ - /* Step 1: rebuild sysfs directory name of device to be checked. */ - /* TODO: this is duplicate code from close.c we might want to modularize it. */ - /* Remove the slashes from the bdev_path (replace with underscores). */ - strcpy(bdev_path_noslash, args->bdev_path); - sflc_str_replaceAll(bdev_path_noslash, '/', '_'); + /* Get device name as : */ + bdev_name = sflc_disk_getDeviceName(args->bdev_path); + if(!bdev_name) { + sflc_log_error("Could not allocate device name"); + return ENOMEM; + } /* Build sysfs path of opened device */ - sprintf(opendev_path, "%s/%s", SFLC_SYSFS_BDEVS_DIR, bdev_path_noslash); + sprintf(opendev_path, "%s/%s", SFLC_SYSFS_BDEVS_DIR, bdev_name); /* Step 2: check if directory exists. */ opendev_dir = opendir(opendev_path); if (opendev_dir) { @@ -102,7 +103,7 @@ int sflc_cmd_openVolumes(sflc_cmd_OpenArgs *args) sflc_log_error("Could not read device size for %s; error %d", args->bdev_path, err); return err; } - nr_slices = sflc_disk_maxSlices(dev_size); + nr_slices = sfold_disk_maxSlices(dev_size); /* Find volume opened by the pwd */ err = sflc_ops_readDmb(args->bdev_path, args->pwd, args->pwd_len, &dmb_cell); @@ -131,7 +132,7 @@ int sflc_cmd_openVolumes(sflc_cmd_OpenArgs *args) } /* Read and unlock VMB */ - err = sflc_ops_readVmb(args->bdev_path, vmb_key, nr_slices, (size_t) i, &vmbs[i]); + err = sfold_ops_readVmb(args->bdev_path, vmb_key, nr_slices, (size_t) i, &vmbs[i]); if (err) { sflc_log_error("Could not read VMB %d on device %s; error %d", i, args->bdev_path, err); @@ -149,7 +150,7 @@ int sflc_cmd_openVolumes(sflc_cmd_OpenArgs *args) /* Open volumes "in order" */ for (i = 0; i <= dmb_cell.vol_idx; i++) { - err = sflc_ops_openVolume(args->bdev_path, dev_id, (size_t) i, &vmbs[i]); + err = sfold_ops_openVolume(args->bdev_path, dev_id, (size_t) i, &vmbs[i]); if (err) { sflc_log_error("Could not open volume %d; error %d. " "Previous volumes on the device might have already " diff --git a/shufflecake-userland/src/commands/open_lite.c b/shufflecake-userland/src/commands/open_lite.c new file mode 100644 index 0000000..4604719 --- /dev/null +++ b/shufflecake-userland/src/commands/open_lite.c @@ -0,0 +1,206 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +/***************************************************** + * INCLUDE SECTION * + *****************************************************/ + +#include +#include +#include +#include + +#include "commands.h" +#include "operations.h" +#include "utils/sflc.h" +#include "utils/crypto.h" +#include "utils/disk.h" +#include "utils/file.h" +#include "utils/log.h" + + +/***************************************************** + * PRIVATE FUNCTIONS PROTOTYPES * + *****************************************************/ + +/* Read the next device ID in sysfs */ +static int _getNextDevId(size_t *next_dev_id); + + +/***************************************************** + * PUBLIC FUNCTIONS DEFINITIONS * + *****************************************************/ + +/** + * Open M volumes, from the first one down to the one whose pwd is provided. + * Scans the DMB cells to find which one is unlocked by the provided pwd; then, + * using the decrypted VMB key, unlocks the M-th VMB; then, iteratively using + * the prev_vmb_key field, unlocks all the previous VMBs; then, using the + * decrypted VMB keys, opens the volumes "in order" from 1 to M. + * + * @param args->bdev_path The underlying block device + * @param args->pwd The password + * @param args->pwd_len The password length + * + * @return Error code (also if no volume could be opened), 0 on success + */ +int sflite_cmd_openVolumes(sflc_cmd_OpenArgs *args) +{ + int64_t dev_size; + size_t nr_slices; + sflc_DmbCell dmb_cell; + sflc_Vmb vmbs[SFLC_DEV_MAX_VOLUMES]; + size_t dev_id; + char *bdev_name; + char opendev_path[SFLC_BIGBUFSIZE]; + DIR* opendev_dir; + int err; + + /* Check if device is already opened and abort if so. */ + /* Get device name as : */ + bdev_name = sflc_disk_getDeviceName(args->bdev_path); + if(!bdev_name) { + sflc_log_error("Could not allocate device name"); + return ENOMEM; + } + /* Build sysfs path of opened device */ + sprintf(opendev_path, "%s/%s", SFLC_SYSFS_BDEVS_DIR, bdev_name); + /* Step 2: check if directory exists. */ + opendev_dir = opendir(opendev_path); + if (opendev_dir) { + /* Directory exists. */ + closedir(opendev_dir); + err = EEXIST; + sflc_log_error("Device %s seems to be already open; error %d", args->bdev_path, err); + return err; + } + + /* Get number of slices */ + dev_size = sflc_disk_getSize(args->bdev_path); + if (dev_size < 0) { + err = -dev_size; + sflc_log_error("Could not read device size for %s; error %d", args->bdev_path, err); + return err; + } + nr_slices = sflite_disk_maxSlices(dev_size); + + /* Find volume opened by the pwd */ + err = sflc_ops_readDmb(args->bdev_path, args->pwd, args->pwd_len, &dmb_cell); + if (err) { + sflc_log_error("Could not read DMB; error %d", err); + return err; + } + /* Was there one? */ + if (dmb_cell.vol_idx >= SFLC_DEV_MAX_VOLUMES) { + sflc_log_error("The provided password opens no volume on the device"); + return EINVAL; + } + printf("Password is correct! Opening volumes...\n"); + + /* Unlock VMBs "backwards" */ + int i; // Needs sign, because loop ends on i>=0 + for (i = dmb_cell.vol_idx; i >= 0; i--) { + /* Which VMB key to use? */ + char *vmb_key; + if (i == dmb_cell.vol_idx) { + // The one unlocked by pwd + vmb_key = dmb_cell.vmb_key; + } else { + // Or the prev_vmb_key from last iteration + vmb_key = vmbs[i+1].prev_vmb_key; + } + + /* Read and unlock VMB */ + err = sflite_ops_readVmb(args->bdev_path, vmb_key, nr_slices, (size_t) i, &vmbs[i]); + if (err) { + sflc_log_error("Could not read VMB %d on device %s; error %d", + i, args->bdev_path, err); + return err; + } + } + + /* Get the ID that will be assigned to the block device */ + err = _getNextDevId(&dev_id); + if (err) { + sflc_log_error("Could not get next device ID; error %d", err); + return err; + } + sflc_log_debug("Next device ID is %lu", dev_id); + + /* Open volumes "in order" */ + for (i = 0; i <= dmb_cell.vol_idx; i++) { + err = sflite_ops_openVolume(args->bdev_path, dev_id, (size_t) i, &vmbs[i]); + if (err) { + sflc_log_error("Could not open volume %d; error %d. " + "Previous volumes on the device might have already " + "been opened, it's recommended you close them", + i, err); + return err; + } + sflc_log_debug("Successfully opened volume %d with VMB key", i); + printf("Opened volume /dev/mapper/sflc_%lu_%d\n", dev_id, i); + } + + return 0; +} + + +/***************************************************** + * PRIVATE FUNCTIONS PROTOTYPES * + *****************************************************/ + +/* Read the next device ID in sysfs */ +static int _getNextDevId(size_t *next_dev_id) +{ + char *str_nextdevid; + int err; + + /* Read sysfs entry */ + str_nextdevid = sflc_readFile(SFLC_SYSFS_NEXTDEVID); + if (!str_nextdevid) { + sflc_log_error("Could not read sysfs entry %s", SFLC_SYSFS_NEXTDEVID); + return EINVAL; + } + + /* Parse integer */ + if (sscanf(str_nextdevid, "%lu", next_dev_id) != 1) { + sflc_log_error("Error parsing content of file %s", SFLC_SYSFS_NEXTDEVID); + err = EINVAL; + goto err_devid; + } + /* Sanity check */ + if (*next_dev_id >= SFLC_TOT_MAX_DEVICES) { + sflc_log_error("There are already %d open devices, this is the maximum allowed", SFLC_TOT_MAX_DEVICES); + err = E2BIG; + goto err_devid; + } + + /* All good */ + err = 0; + + +err_devid: + free(str_nextdevid); + return err; +} + diff --git a/shufflecake-userland/src/header/device_master_block.c b/shufflecake-userland/src/header/device_master_block.c index cdd1f8c..1cfcd9b 100644 --- a/shufflecake-userland/src/header/device_master_block.c +++ b/shufflecake-userland/src/header/device_master_block.c @@ -72,7 +72,7 @@ int sflc_dmb_seal(sflc_Dmb *dmb, char **pwds, size_t *pwd_lens, char *disk_block } /* Randomise whole block */ - err = sflc_rand_getWeakBytes(disk_block, SFLC_SECTOR_SIZE); + err = sflc_rand_getWeakBytes(disk_block, SFLC_BLOCK_SIZE); if (err) { sflc_log_error("Could not randomise DMB; error %d", err); return err; @@ -115,9 +115,9 @@ int sflc_dmb_unseal(char *disk_block, char *pwd, size_t pwd_len, sflc_DmbCell *d // KDF salt char *salt; // The KDF-derived key - char kek[SFLC_CRYPTO_KEYLEN]; + char kek[SFLC_STANDARD_KEYLEN]; // The unlocked VMB key - char vmb_key[SFLC_CRYPTO_KEYLEN]; + char vmb_key[SFLC_STANDARD_KEYLEN]; // Error code int err; @@ -149,7 +149,7 @@ int sflc_dmb_unseal(char *disk_block, char *pwd, size_t pwd_len, sflc_DmbCell *d if (match) { sflc_log_debug("The provided password unlocks volume %lu", i); dmb_cell->vol_idx = i; - memcpy(dmb_cell->vmb_key, vmb_key, SFLC_CRYPTO_KEYLEN); + memcpy(dmb_cell->vmb_key, vmb_key, SFLC_STANDARD_KEYLEN); } } @@ -160,7 +160,7 @@ int sflc_dmb_unseal(char *disk_block, char *pwd, size_t pwd_len, sflc_DmbCell *d bad_decrypt: bad_kdf: /* Always wipe the key from memory, even on success */ - memset(kek, 0, SFLC_CRYPTO_KEYLEN); + memset(kek, 0, SFLC_STANDARD_KEYLEN); return err; } @@ -211,9 +211,9 @@ static int _encryptVmbKeyWithPwd(char *salt, char *pwd, size_t pwd_len, char *vm // Pointers inside the block char *iv = dmb_cell; char *enc_vmb_key = iv + SFLC_AESGCM_PADDED_IVLEN; - char *mac = enc_vmb_key + SFLC_CRYPTO_KEYLEN; + char *mac = enc_vmb_key + SFLC_STANDARD_KEYLEN; // Key-encryption-key derived from KDF - char kek[SFLC_CRYPTO_KEYLEN]; + char kek[SFLC_STANDARD_KEYLEN]; // Error code int err; @@ -234,7 +234,7 @@ static int _encryptVmbKeyWithPwd(char *salt, char *pwd, size_t pwd_len, char *vm sflc_log_debug("Successfully sampled prologue IV"); /* Encrypt the VMB key */ - err = sflc_aes256gcm_encrypt(kek, vmb_key, SFLC_CRYPTO_KEYLEN, iv, enc_vmb_key, mac); + err = sflc_aes256gcm_encrypt(kek, vmb_key, SFLC_STANDARD_KEYLEN, iv, enc_vmb_key, mac); if (err) { sflc_log_error("Could not encrypt the VMB key: error %d", err); goto bad_encrypt; @@ -249,7 +249,7 @@ bad_encrypt: bad_sample_iv: bad_kdf: /* Always wipe the key from memory, even on success */ - memset(kek, 0, SFLC_CRYPTO_KEYLEN); + memset(kek, 0, SFLC_STANDARD_KEYLEN); return err; } @@ -259,12 +259,12 @@ static int _decryptVmbKeyWithPwd(char *dmb_cell, char *kek, char *vmb_key, bool // Pointers inside the block char *iv = dmb_cell; char *enc_vmb_key = iv + SFLC_AESGCM_PADDED_IVLEN; - char *mac = enc_vmb_key + SFLC_CRYPTO_KEYLEN; + char *mac = enc_vmb_key + SFLC_STANDARD_KEYLEN; // Error code int err; /* Decrypt the VMB key */ - err = sflc_aes256gcm_decrypt(kek, enc_vmb_key, SFLC_CRYPTO_KEYLEN, mac, iv, vmb_key, match); + err = sflc_aes256gcm_decrypt(kek, enc_vmb_key, SFLC_STANDARD_KEYLEN, mac, iv, vmb_key, match); if (err) { sflc_log_error("Error while decrypting VMB key: error %d", err); return err; diff --git a/shufflecake-userland/src/header/position_map.c b/shufflecake-userland/src/header/position_map_legacy.c similarity index 88% rename from shufflecake-userland/src/header/position_map.c rename to shufflecake-userland/src/header/position_map_legacy.c index f2b8144..923a830 100644 --- a/shufflecake-userland/src/header/position_map.c +++ b/shufflecake-userland/src/header/position_map_legacy.c @@ -50,7 +50,7 @@ * @param epm The EncPosMap struct to be initialised. * * @return Error code, 0 on success */ -int sflc_epm_create(size_t nr_slices, char *volume_key, sflc_EncPosMap *epm) +int sfold_epm_create(size_t nr_slices, char *volume_key, sfold_EncPosMap *epm) { size_t nr_pmbs; size_t nr_arrays; @@ -59,12 +59,12 @@ int sflc_epm_create(size_t nr_slices, char *volume_key, sflc_EncPosMap *epm) // Each PosMapBlock holds up to 1024 PSIs (Physical Slice Index) nr_pmbs = ceil(nr_slices, SFLC_SLICE_IDX_PER_BLOCK); // Each array holds up to 256 PosMapBlocks - nr_arrays = ceil(nr_pmbs, SFLC_BLOCKS_PER_LOG_SLICE); + nr_arrays = ceil(nr_pmbs, SFLC_SLICE_SCALE); // Fill the EPM numeric fields epm->nr_arrays = nr_arrays; // All arrays are full except the last one - epm->nr_last_pmbs = nr_pmbs - (SFLC_BLOCKS_PER_LOG_SLICE * (nr_arrays - 1)); + epm->nr_last_pmbs = nr_pmbs - (SFLC_SLICE_SCALE * (nr_arrays - 1)); // Allocate array of IV blocks epm->iv_blocks = malloc(nr_arrays * sizeof(char *)); @@ -85,13 +85,13 @@ int sflc_epm_create(size_t nr_slices, char *volume_key, sflc_EncPosMap *epm) int i; for (i = 0; i < nr_arrays; i++) { // The last PMB array might be smaller - size_t nr_pmbs_here = ((i == nr_arrays - 1) ? epm->nr_last_pmbs : SFLC_BLOCKS_PER_LOG_SLICE); - size_t pmb_array_size = SFLC_SECTOR_SIZE * nr_pmbs_here; + size_t nr_pmbs_here = ((i == nr_arrays - 1) ? epm->nr_last_pmbs : SFLC_SLICE_SCALE); + size_t pmb_array_size = SFLC_BLOCK_SIZE * nr_pmbs_here; char *iv_block; char *pmb_array; // Allocate IV block - epm->iv_blocks[i] = malloc(SFLC_SECTOR_SIZE); + epm->iv_blocks[i] = malloc(SFLC_BLOCK_SIZE); if (!epm->iv_blocks[i]) { sflc_log_error("Could not allocate IV block number %d", i); err = ENOMEM; @@ -109,7 +109,7 @@ int sflc_epm_create(size_t nr_slices, char *volume_key, sflc_EncPosMap *epm) pmb_array = epm->pmb_arrays[i]; // Fill the IV block with random data (can ignore return value) - sflc_rand_getWeakBytes(iv_block, SFLC_SECTOR_SIZE); + sflc_rand_getWeakBytes(iv_block, SFLC_BLOCK_SIZE); // Fill the PMB array with 0xFF memset(pmb_array, SFLC_EPM_FILLER, pmb_array_size); @@ -117,10 +117,10 @@ int sflc_epm_create(size_t nr_slices, char *volume_key, sflc_EncPosMap *epm) int j; for (j = 0; j < nr_pmbs_here; j++) { char *iv = iv_block + (j * SFLC_AESCTR_IVLEN); - char *pmb = pmb_array + (j * SFLC_SECTOR_SIZE); + char *pmb = pmb_array + (j * SFLC_BLOCK_SIZE); // Encrypt in-place - err = sflc_aes256ctr_encrypt(volume_key, pmb, SFLC_SECTOR_SIZE, iv, NULL); + err = sflc_aes256ctr_encrypt(volume_key, pmb, SFLC_BLOCK_SIZE, iv, NULL); if (err) { sflc_log_error("Could not encrypt PMB %d of array %d", j, i); goto out; diff --git a/shufflecake-userland/src/header/position_map_lite.c b/shufflecake-userland/src/header/position_map_lite.c new file mode 100644 index 0000000..ae2b48a --- /dev/null +++ b/shufflecake-userland/src/header/position_map_lite.c @@ -0,0 +1,97 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +/***************************************************** + * INCLUDE SECTION * + *****************************************************/ + +#include +#include +#include +#include + +#include "header.h" +#include "utils/sflc.h" +#include "utils/crypto.h" +#include "utils/math.h" +#include "utils/log.h" + + +/***************************************************** + * PUBLIC FUNCTIONS DEFINITIONS * + *****************************************************/ + +/* Create an encrypted empty position map for the given number of slices. + * Allocates the memory (whole number of blocks) needed to host it. + * + * @param nr_slices The number of slices the device will be composed of. + * @param volume_key The volume's data section encryption key, used to encrypt the + * position map as well. + * + * @return The memory buffer containing the position map */ +void *sflite_epm_create(size_t nr_slices, size_t vol_idx, char *volume_key) +{ + char pmb[SFLC_BLOCK_SIZE]; + char iv[SFLC_AESXTS_IVLEN]; + void *epm; + size_t nr_pmbs; + uint64_t pblk_num; + int err; + + // Each PosMapBlock holds up to 1024 PSIs (Physical Slice Index) + nr_pmbs = ceil(nr_slices, SFLC_SLICE_IDX_PER_BLOCK); + + // Allocate EPM + epm = malloc(nr_pmbs * SFLC_BLOCK_SIZE); + if (!epm) { + sflc_log_error("Could not malloc EPM"); + return NULL; + } + + // Fill cleartext PMB with 0xFF + memset(pmb, SFLC_EPM_FILLER, SFLC_BLOCK_SIZE); + // First physical block number + pblk_num = sflite_pmStartBlock(vol_idx, nr_slices); + + // Loop to encrypt each PMB + int i; + for (i = 0; i < nr_pmbs; i++) { + // Set IV + memset(iv, 0, SFLC_AESXTS_IVLEN); + *((uint64_t*)iv) = htole64(pblk_num); + + // Encrypt + err = sflc_aes256xts_encrypt(volume_key, pmb, SFLC_BLOCK_SIZE, iv, + epm + i*SFLC_BLOCK_SIZE); + if (err) { + sflc_log_error("Could not encrypt %d-th block of PosMap; error %d", i , err); + free(epm); + return NULL; + } + + // Increment block number + pblk_num++; + } + + return epm; +} diff --git a/shufflecake-userland/src/header/volume_master_block_legacy.c b/shufflecake-userland/src/header/volume_master_block_legacy.c new file mode 100644 index 0000000..d8b7529 --- /dev/null +++ b/shufflecake-userland/src/header/volume_master_block_legacy.c @@ -0,0 +1,223 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +/***************************************************** + * INCLUDE SECTION * + *****************************************************/ + +#include +#include +#include +#include // Network byte order + +#include "header.h" +#include "utils/crypto.h" +#include "utils/string.h" +#include "utils/log.h" + + +/***************************************************** + * PRIVATE FUNCTIONS PROTOTYPES * + *****************************************************/ + +/* Serialise the VMB before encrypting it */ +static void _serialiseVmb(sflc_Vmb *vmb, char *clear_vmb); + +/* Deserialise the VMB after decrypting it */ +static int _deserialiseVmb(char *clear_vmb, sflc_Vmb *vmb); + + +/***************************************************** + * PUBLIC FUNCTIONS DEFINITIONS * + *****************************************************/ + +/** + * Builds the on-disk master block (indistinguishable from random). + * + * @param vmb The useful information stored in this volume master block + * @param vmb_key The key encrypting the VMB + * @param disk_block The 4096-byte buffer that will contain the random-looking + * bytes to be written on-disk + * + * @return The error code, 0 on success + */ +int sfold_vmb_seal(sflc_Vmb *vmb, char *vmb_key, char *disk_block) +{ + // Pointers inside the block + char *iv = disk_block; + char *enc_vmb = iv + SFLC_AESCTR_IVLEN; + // Serialised VMB (dynamically allocated), to be encrypted + char *clear_vmb; + // Error code + int err; + + /* Allocate large buffer on the heap */ + clear_vmb = malloc(SFLC_CLEAR_VMB_LEN); + if (!clear_vmb) { + sflc_log_error("Could not allocate %d bytes for VMB cleartext", SFLC_CLEAR_VMB_LEN); + err = ENOMEM; + goto bad_clear_alloc; + } + sflc_log_debug("Successfully allocated %d bytes for VMB cleartext", SFLC_CLEAR_VMB_LEN); + + /* Serialise the struct */ + _serialiseVmb(vmb, clear_vmb); + sflc_log_debug("Serialised VMB struct"); + + /* Sample VMB IV */ + err = sflc_rand_getWeakBytes(iv, SFLC_AESGCM_PADDED_IVLEN); + if (err) { + sflc_log_error("Could not sample VMB IV: error %d", err); + goto bad_sample_iv; + } + sflc_log_debug("Successfully sampled VMB IV"); + + /* Encrypt the VMB */ + err = sflc_aes256ctr_encrypt(vmb_key, clear_vmb, SFLC_CLEAR_VMB_LEN, iv, enc_vmb); + if (err) { + sflc_log_error("Could not encrypt VMB: error %d", err); + goto bad_encrypt; + } + sflc_log_debug("Successfully encrypted VMB"); + + // No prob + err = 0; + + +bad_encrypt: +bad_sample_iv: + /* Always wipe and free the cleartext VMB, even on success */ + memset(clear_vmb, 0, SFLC_CLEAR_VMB_LEN); + free(clear_vmb); +bad_clear_alloc: + return err; +} + + +/** + * Decrypt the VMB payload using the VMB key. + * + * @param disk_block The content of the on-disk encrypted VMB + * @param vmb_key The proposed VMB key to unseal its payload + * @param vmb A pointer to the output struct that will contain all the VMB fields + * + * @return An error code, 0 on success + */ +int sfold_vmb_unseal(char *disk_block, char *vmb_key, sflc_Vmb *vmb) +{ + // Pointers inside the block + char *iv = disk_block; + char *enc_vmb = iv + SFLC_AESCTR_IVLEN; + // Decrypted VMB (dynamically allocated), to be deserialised + char *clear_vmb; + // Error code + int err; + + /* Allocate large buffer on the heap */ + clear_vmb = malloc(SFLC_CLEAR_VMB_LEN); + if (!clear_vmb) { + sflc_log_error("Could not allocate %d bytes for VMB cleartext", SFLC_CLEAR_VMB_LEN); + err = ENOMEM; + goto bad_clear_alloc; + } + sflc_log_debug("Successfully allocated %d bytes for VMB cleartext", SFLC_CLEAR_VMB_LEN); + + /* Decrypt the VMB */ + err = sflc_aes256ctr_decrypt(vmb_key, enc_vmb, SFLC_CLEAR_VMB_LEN, iv, clear_vmb); + if (err) { + sflc_log_error("Error while decrypting VMB: error %d", err); + goto bad_decrypt; + } + sflc_log_debug("Successfully decrypted VMB"); + + /* Deserialise the struct */ + err = _deserialiseVmb(clear_vmb, vmb); + if (err) { + sflc_log_error("Error while deserialising VMB: error %d", err); + goto bad_deserialise; + } + sflc_log_debug("Deserialised VMB struct"); + + // No prob + err = 0; + + +bad_deserialise: +bad_decrypt: + /* Always wipe and free the VMB cleartext, even on success */ + memset(clear_vmb, 0, SFLC_CLEAR_VMB_LEN); + free(clear_vmb); +bad_clear_alloc: + return err; +} + + +/***************************************************** + * PRIVATE FUNCTIONS PROTOTYPES * + *****************************************************/ + +/* Serialise the payload before encrypting it */ +static void _serialiseVmb(sflc_Vmb *vmb, char *clear_vmb) +{ + // Pointers inside the VMB + char *p_vol_key = clear_vmb; + char *p_prev_vmb_key = p_vol_key + SFLC_STANDARD_KEYLEN; + char *p_nr_slices = p_prev_vmb_key + SFLC_STANDARD_KEYLEN; + + /* Copy the volume key */ + memcpy(p_vol_key, vmb->volume_key_legacy, SFLC_STANDARD_KEYLEN); + + /* Copy the previous volume's VMB key */ + memcpy(p_prev_vmb_key, vmb->prev_vmb_key, SFLC_STANDARD_KEYLEN); + + /* Write the number of slices (network byte order) */ + *((uint32_t *) p_nr_slices) = htonl(vmb->nr_slices); + + // Leave the rest uninitialised + + return; +} + + +/* Deserialise the VMB after decrypting it */ +static int _deserialiseVmb(char *clear_vmb, sflc_Vmb *vmb) +{ + // Pointers inside the VMB + char *p_vol_key = clear_vmb; + char *p_prev_vmb_key = p_vol_key + SFLC_STANDARD_KEYLEN; + char *p_nr_slices = p_prev_vmb_key + SFLC_STANDARD_KEYLEN; + + /* Copy the volume key */ + memcpy(vmb->volume_key_legacy, p_vol_key, SFLC_STANDARD_KEYLEN); + + /* Copy the previous volume's VMB key */ + memcpy(vmb->prev_vmb_key, p_prev_vmb_key, SFLC_STANDARD_KEYLEN); + + /* Read number of slices (network byte order) */ + vmb->nr_slices = ntohl( *((uint32_t *) p_nr_slices) ); + + // Ignore the rest + + return 0; +} + diff --git a/shufflecake-userland/src/header/volume_master_block.c b/shufflecake-userland/src/header/volume_master_block_lite.c similarity index 90% rename from shufflecake-userland/src/header/volume_master_block.c rename to shufflecake-userland/src/header/volume_master_block_lite.c index 9347582..d61099f 100644 --- a/shufflecake-userland/src/header/volume_master_block.c +++ b/shufflecake-userland/src/header/volume_master_block_lite.c @@ -61,7 +61,7 @@ static int _deserialiseVmb(char *clear_vmb, sflc_Vmb *vmb); * * @return The error code, 0 on success */ -int sflc_vmb_seal(sflc_Vmb *vmb, char *vmb_key, char *disk_block) +int sflite_vmb_seal(sflc_Vmb *vmb, char *vmb_key, char *disk_block) { // Pointers inside the block char *iv = disk_block; @@ -123,7 +123,7 @@ bad_clear_alloc: * * @return An error code, 0 on success */ -int sflc_vmb_unseal(char *disk_block, char *vmb_key, sflc_Vmb *vmb) +int sflite_vmb_unseal(char *disk_block, char *vmb_key, sflc_Vmb *vmb) { // Pointers inside the block char *iv = disk_block; @@ -181,14 +181,14 @@ static void _serialiseVmb(sflc_Vmb *vmb, char *clear_vmb) { // Pointers inside the VMB char *p_vol_key = clear_vmb; - char *p_prev_vmb_key = p_vol_key + SFLC_CRYPTO_KEYLEN; - char *p_nr_slices = p_prev_vmb_key + SFLC_CRYPTO_KEYLEN; + char *p_prev_vmb_key = p_vol_key + SFLC_AESXTS_KEYLEN; + char *p_nr_slices = p_prev_vmb_key + SFLC_STANDARD_KEYLEN; /* Copy the volume key */ - memcpy(p_vol_key, vmb->volume_key, SFLC_CRYPTO_KEYLEN); + memcpy(p_vol_key, vmb->volume_key_lite, SFLC_AESXTS_KEYLEN); /* Copy the previous volume's VMB key */ - memcpy(p_prev_vmb_key, vmb->prev_vmb_key, SFLC_CRYPTO_KEYLEN); + memcpy(p_prev_vmb_key, vmb->prev_vmb_key, SFLC_STANDARD_KEYLEN); /* Write the number of slices (network byte order) */ *((uint32_t *) p_nr_slices) = htonl(vmb->nr_slices); @@ -204,14 +204,14 @@ static int _deserialiseVmb(char *clear_vmb, sflc_Vmb *vmb) { // Pointers inside the VMB char *p_vol_key = clear_vmb; - char *p_prev_vmb_key = p_vol_key + SFLC_CRYPTO_KEYLEN; - char *p_nr_slices = p_prev_vmb_key + SFLC_CRYPTO_KEYLEN; + char *p_prev_vmb_key = p_vol_key + SFLC_AESXTS_KEYLEN; + char *p_nr_slices = p_prev_vmb_key + SFLC_STANDARD_KEYLEN; /* Copy the volume key */ - memcpy(vmb->volume_key, p_vol_key, SFLC_CRYPTO_KEYLEN); + memcpy(vmb->volume_key_lite, p_vol_key, SFLC_AESXTS_KEYLEN); /* Copy the previous volume's VMB key */ - memcpy(vmb->prev_vmb_key, p_prev_vmb_key, SFLC_CRYPTO_KEYLEN); + memcpy(vmb->prev_vmb_key, p_prev_vmb_key, SFLC_STANDARD_KEYLEN); /* Read number of slices (network byte order) */ vmb->nr_slices = ntohl( *((uint32_t *) p_nr_slices) ); diff --git a/shufflecake-userland/src/operations/devmapper_legacy.c b/shufflecake-userland/src/operations/devmapper_legacy.c new file mode 100644 index 0000000..a0417da --- /dev/null +++ b/shufflecake-userland/src/operations/devmapper_legacy.c @@ -0,0 +1,111 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +/***************************************************** + * INCLUDE SECTION * + *****************************************************/ + +#include +#include +#include +#include +#include + +#include "header.h" +#include "operations.h" +#include "utils/sflc.h" +#include "utils/crypto.h" +#include "utils/file.h" +#include "utils/string.h" +#include "utils/dm.h" +#include "utils/log.h" + + +/***************************************************** + * PUBLIC FUNCTIONS DEFINITIONS * + *****************************************************/ + +/** + * Build parameter list for ctor in dm_sflc, and send DM ioctl to create + * virtual block device. + * + * @param bdev_path The path to the underlying device + * @param dev_id The ID of the underlying block device + * @param vol_idx The index of the volume within the device + * @param vmb Volume metadata + * + * @return Error code, 0 on success + */ +int sfold_ops_openVolume(char *bdev_path, size_t dev_id, size_t vol_idx, sflc_Vmb *vmb) +{ + char label[SFLC_BIGBUFSIZE]; + char *hex_key; + char params[SFLC_BIGBUFSIZE]; + uint64_t num_sectors; + int err; + + /* Build volume label */ + sprintf(label, "sflc_%lu_%lu", dev_id, vol_idx); + + /* Get the hex version of the volume's data section key */ + hex_key = sflc_toHex(vmb->volume_key_legacy, SFLC_STANDARD_KEYLEN); + if (!hex_key) { + sflc_log_error("Could not encode volume key to hexadecimal"); + err = ENOMEM; + goto err_hexkey; + } + + /* Get the number of logical 512-byte sectors composing the volume */ + num_sectors = ((uint64_t) vmb->nr_slices) * SFLC_SLICE_SCALE * SFLC_BLOCK_SCALE; + + /* Build param list */ + sprintf(params, "%d %lu %s %lu %lu %s", SFLC_MODE_LEGACY, dev_id, bdev_path, vol_idx, vmb->nr_slices, hex_key); + + /* Issue ioctl */ + err = sflc_dm_create(label, num_sectors, params); + if (err) { + sflc_log_error("Could not issue ioctl CREATE command to device mapper; error %d", err); + goto err_dmcreate; + } + err = 0; + + +err_dmcreate: + free(hex_key); +err_hexkey: + return err; +} + + +/** + * Close the volume by issuing the appropriate ioctl to the DM. + * + * @param label The only needed parameter: the ID of the volume. + * + * @return Error code, 0 on success + */ +int sfold_ops_closeVolume(char *label) +{ + /* Issue ioctl */ + return sflc_dm_destroy(label); +} diff --git a/shufflecake-userland/src/operations/devmapper_lite.c b/shufflecake-userland/src/operations/devmapper_lite.c new file mode 100644 index 0000000..5dc610b --- /dev/null +++ b/shufflecake-userland/src/operations/devmapper_lite.c @@ -0,0 +1,112 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +/***************************************************** + * INCLUDE SECTION * + *****************************************************/ + +#include +#include +#include +#include +#include + +#include "header.h" +#include "operations.h" +#include "utils/sflc.h" +#include "utils/crypto.h" +#include "utils/file.h" +#include "utils/string.h" +#include "utils/dm.h" +#include "utils/log.h" + + +/***************************************************** + * PUBLIC FUNCTIONS DEFINITIONS * + *****************************************************/ + +/** + * Build parameter list for ctor in dm_sflc, and send DM ioctl to create + * virtual block device. + * + * @param bdev_path The path to the underlying device + * @param dev_id The ID of the underlying block device + * @param vol_idx The index of the volume within the device + * @param vmb Volume metadata + * + * @return Error code, 0 on success + */ +int sflite_ops_openVolume(char *bdev_path, size_t dev_id, size_t vol_idx, sflc_Vmb *vmb) +{ + char label[SFLC_BIGBUFSIZE]; + char *hex_key; + char params[SFLC_BIGBUFSIZE]; + uint64_t num_sectors; + int err; + + /* Build volume label */ + sprintf(label, "sflc_%lu_%lu", dev_id, vol_idx); + + /* Get the hex version of the volume's data section key */ + hex_key = sflc_toHex(vmb->volume_key_lite, SFLC_AESXTS_KEYLEN); + if (!hex_key) { + sflc_log_error("Could not encode volume key to hexadecimal"); + err = ENOMEM; + goto err_hexkey; + } + + /* Get the number of logical 512-byte sectors composing the volume */ + num_sectors = ((uint64_t) vmb->nr_slices) * SFLC_SLICE_SCALE * SFLC_BLOCK_SCALE; + + /* Build param list */ + sprintf(params, "%d %lu %s %lu %lu %s", SFLC_MODE_LITE, dev_id, bdev_path, vol_idx, vmb->nr_slices, hex_key); + + /* Issue ioctl */ + err = sflc_dm_create(label, num_sectors, params); + if (err) { + sflc_log_error("Could not issue ioctl CREATE command to device mapper; error %d", err); + goto err_dmcreate; + } + err = 0; + + +err_dmcreate: + memset(hex_key, 0, strlen(hex_key)); + free(hex_key); +err_hexkey: + return err; +} + + +/** + * Close the volume by issuing the appropriate ioctl to the DM. + * + * @param label The only needed parameter: the ID of the volume. + * + * @return Error code, 0 on success + */ +int sflite_ops_closeVolume(char *label) +{ + /* Issue ioctl */ + return sflc_dm_destroy(label); +} diff --git a/shufflecake-userland/src/operations/dmb.c b/shufflecake-userland/src/operations/dmb.c index d529966..662742e 100644 --- a/shufflecake-userland/src/operations/dmb.c +++ b/shufflecake-userland/src/operations/dmb.c @@ -57,7 +57,7 @@ int sflc_ops_writeDmb(char *bdev_path, char **pwds, size_t *pwd_lens, sflc_Dmb *dmb) { /* On-disk DMB */ - char enc_dmb[SFLC_SECTOR_SIZE]; + char enc_dmb[SFLC_BLOCK_SIZE]; /* Error code */ int err; @@ -75,7 +75,7 @@ int sflc_ops_writeDmb(char *bdev_path, char **pwds, size_t *pwd_lens, sflc_Dmb * } /* Write it to disk (at sector 0) */ - err = sflc_disk_writeSector(bdev_path, 0, enc_dmb); + err = sflc_disk_writeBlock(bdev_path, 0, enc_dmb); if (err) { sflc_log_error("Could not write DMB to disk; error %d", err); return err; @@ -99,11 +99,11 @@ int sflc_ops_writeDmb(char *bdev_path, char **pwds, size_t *pwd_lens, sflc_Dmb * */ int sflc_ops_readDmb(char *bdev_path, char *pwd, size_t pwd_len, sflc_DmbCell *dmb) { - char enc_dmb[SFLC_SECTOR_SIZE]; + char enc_dmb[SFLC_BLOCK_SIZE]; int err; /* Read DMB from disk (at sector 0) */ - err = sflc_disk_readSector(bdev_path, 0, enc_dmb); + err = sflc_disk_readBlock(bdev_path, 0, enc_dmb); if (err) { sflc_log_error("Could not read DMB from disk; error %d", err); return err; @@ -131,7 +131,7 @@ int sflc_ops_readDmb(char *bdev_path, char *pwd, size_t pwd_len, sflc_DmbCell *d */ int sflc_ops_rewriteDmbCell(char *bdev_path, sflc_DmbCell *dmb_cell, char *new_pwd, size_t new_pwd_len) { - char enc_dmb[SFLC_SECTOR_SIZE]; + char enc_dmb[SFLC_BLOCK_SIZE]; int err; /* Sanity check */ @@ -141,7 +141,7 @@ int sflc_ops_rewriteDmbCell(char *bdev_path, sflc_DmbCell *dmb_cell, char *new_p } /* Read DMB from disk (at sector 0) */ - err = sflc_disk_readSector(bdev_path, 0, enc_dmb); + err = sflc_disk_readBlock(bdev_path, 0, enc_dmb); if (err) { sflc_log_error("Could not read DMB from disk; error %d", err); return err; @@ -155,7 +155,7 @@ int sflc_ops_rewriteDmbCell(char *bdev_path, sflc_DmbCell *dmb_cell, char *new_p } /* Write it to disk (at sector 0) */ - err = sflc_disk_writeSector(bdev_path, 0, enc_dmb); + err = sflc_disk_writeBlock(bdev_path, 0, enc_dmb); if (err) { sflc_log_error("Could not write DMB to disk; error %d", err); return err; diff --git a/shufflecake-userland/src/operations/volume_header.c b/shufflecake-userland/src/operations/volume_header_legacy.c similarity index 83% rename from shufflecake-userland/src/operations/volume_header.c rename to shufflecake-userland/src/operations/volume_header_legacy.c index 1088290..44ec50c 100644 --- a/shufflecake-userland/src/operations/volume_header.c +++ b/shufflecake-userland/src/operations/volume_header_legacy.c @@ -53,23 +53,23 @@ * * @return Error code, 0 on success */ -int sflc_ops_writeVolumeHeader(char *bdev_path, char *vmb_key, sflc_Vmb *vmb, size_t vol_idx) +int sfold_ops_writeVolumeHeader(char *bdev_path, char *vmb_key, sflc_Vmb *vmb, size_t vol_idx) { - char enc_vmb[SFLC_SECTOR_SIZE]; - sflc_EncPosMap epm; + char enc_vmb[SFLC_BLOCK_SIZE]; + sfold_EncPosMap epm; uint64_t sector; int err; // Encrypt VMB - err = sflc_vmb_seal(vmb, vmb_key, enc_vmb); + err = sfold_vmb_seal(vmb, vmb_key, enc_vmb); if (err) { sflc_log_error("Could not seal VMB; error %d", err); goto out; } // Write it to disk - sector = sflc_vmbPosition(vol_idx, vmb->nr_slices); - err = sflc_disk_writeSector(bdev_path, sector, enc_vmb); + sector = sfold_vmbPosition(vol_idx, vmb->nr_slices); + err = sflc_disk_writeBlock(bdev_path, sector, enc_vmb); if (err) { sflc_log_error("Could not write VMB to disk; error %d", err); goto out; @@ -77,7 +77,7 @@ int sflc_ops_writeVolumeHeader(char *bdev_path, char *vmb_key, sflc_Vmb *vmb, si sector += 1; // Create encrypted empty position map - err = sflc_epm_create(vmb->nr_slices, vmb->volume_key, &epm); + err = sfold_epm_create(vmb->nr_slices, vmb->volume_key_legacy, &epm); if (err) { sflc_log_error("Could not create encrypted empty position map; error %d", err); goto out; @@ -88,10 +88,10 @@ int sflc_ops_writeVolumeHeader(char *bdev_path, char *vmb_key, sflc_Vmb *vmb, si for (i = 0; i < epm.nr_arrays; i++) { char *iv_block = epm.iv_blocks[i]; char *pmb_array = epm.pmb_arrays[i]; - size_t nr_pmbs = ((i == epm.nr_arrays-1) ? epm.nr_last_pmbs : SFLC_BLOCKS_PER_LOG_SLICE); + size_t nr_pmbs = ((i == epm.nr_arrays-1) ? epm.nr_last_pmbs : SFLC_SLICE_SCALE); // First write the IV block - err = sflc_disk_writeSector(bdev_path, sector, iv_block); + err = sflc_disk_writeBlock(bdev_path, sector, iv_block); if (err) { sflc_log_error("Could not write IV block to disk; error %d", err); goto out; @@ -99,7 +99,7 @@ int sflc_ops_writeVolumeHeader(char *bdev_path, char *vmb_key, sflc_Vmb *vmb, si sector += 1; // Then the whole PMB array - err = sflc_disk_writeManySectors(bdev_path, sector, pmb_array, nr_pmbs); + err = sflc_disk_writeManyBlocks(bdev_path, sector, pmb_array, nr_pmbs); if (err) { sflc_log_error("Could not write PMB array to disk; error %d", err); goto out; @@ -133,22 +133,22 @@ out: * * @return Error code, 0 on success */ -int sflc_ops_readVmb(char *bdev_path, char *vmb_key, size_t nr_slices, size_t vol_idx, sflc_Vmb *vmb) +int sfold_ops_readVmb(char *bdev_path, char *vmb_key, size_t nr_slices, size_t vol_idx, sflc_Vmb *vmb) { - char enc_vmb[SFLC_SECTOR_SIZE]; + char enc_vmb[SFLC_BLOCK_SIZE]; uint64_t sector; int err; /* Read encrypted VMB from disk */ - sector = sflc_vmbPosition(vol_idx, nr_slices); - err = sflc_disk_readSector(bdev_path, sector, enc_vmb); + sector = sfold_vmbPosition(vol_idx, nr_slices); + err = sflc_disk_readBlock(bdev_path, sector, enc_vmb); if (err) { sflc_log_error("Could not read VMB from disk; error %d", err); return err; } /* Unseal it */ - err = sflc_vmb_unseal(enc_vmb, vmb_key, vmb); + err = sfold_vmb_unseal(enc_vmb, vmb_key, vmb); if (err) { sflc_log_error("Could not unseal VMB; error %d", err); return err; diff --git a/shufflecake-userland/src/operations/volume_header_lite.c b/shufflecake-userland/src/operations/volume_header_lite.c new file mode 100644 index 0000000..ce649ab --- /dev/null +++ b/shufflecake-userland/src/operations/volume_header_lite.c @@ -0,0 +1,142 @@ +/* + * Copyright The Shufflecake Project Authors (2022) + * Copyright The Shufflecake Project Contributors (2022) + * Copyright Contributors to the The Shufflecake Project. + * + * See the AUTHORS file at the top-level directory of this distribution and at + * + * + * This file is part of the program shufflecake-c, which is part of the + * Shufflecake Project. Shufflecake is a plausible deniability (hidden storage) + * layer for Linux. See . + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the + * GNU General Public License along with this program. + * If not, see . + */ + +/***************************************************** + * INCLUDE SECTION * + *****************************************************/ + +#include +#include +#include +#include + +#include "header.h" +#include "header.h" +#include "operations.h" +#include "utils/sflc.h" +#include "utils/disk.h" +#include "utils/crypto.h" +#include "utils/log.h" + + +/***************************************************** + * PUBLIC FUNCTIONS DEFINITIONS * + *****************************************************/ + +/** + * Writes a volume header (VMB+PM) on-disk. + * + * @param bdev_path The underlying block device to write the volume header + * @param vmb_key The key to encrypt the VMB + * @param vmb The VMB to encrypt + * @param vol_idx The index of the volume within the device + * + * @return Error code, 0 on success + */ +int sflite_ops_writeVolumeHeader(char *bdev_path, char *vmb_key, sflc_Vmb *vmb, size_t vol_idx) +{ + char enc_vmb[SFLC_BLOCK_SIZE]; + void *epm; + uint64_t sector; + int err; + + // Encrypt VMB + err = sflite_vmb_seal(vmb, vmb_key, enc_vmb); + if (err) { + sflc_log_error("Could not seal VMB; error %d", err); + goto out; + } + + // Write it to disk + sector = 1 + vol_idx; + err = sflc_disk_writeBlock(bdev_path, sector, enc_vmb); + if (err) { + sflc_log_error("Could not write VMB to disk; error %d", err); + goto out; + } + + // Create encrypted empty position map + epm = sflite_epm_create(vmb->nr_slices, vol_idx, vmb->volume_key_lite); + if (!epm) { + sflc_log_error("Could not create encrypted empty position map."); + err = ENOMEM; + goto out; + } + + // Write to disk + sector = sflite_pmStartBlock(vol_idx, vmb->nr_slices); + err = sflc_disk_writeManyBlocks(bdev_path, sector, epm, + ceil(vmb->nr_slices, SFLC_SLICE_IDX_PER_BLOCK)); + if (err) { + sflc_log_error("Could not write encrypted PosMap; error %d", err); + } + free(epm); + + +out: + return err; +} + + +/** + * Reads a VMB from disk and unlocks it + * + * @param bdev_path The underlying block device + * @param vmb_key The key to decrypt the VMB + * @param nr_slices The number of slices in the device + * @param vol_idx The index of the volume within the device + * + * @output vmb The decrypted VMB + * + * @return Error code, 0 on success + */ +int sflite_ops_readVmb(char *bdev_path, char *vmb_key, size_t nr_slices, size_t vol_idx, sflc_Vmb *vmb) +{ + char enc_vmb[SFLC_BLOCK_SIZE]; + uint64_t sector; + int err; + + /* Read encrypted VMB from disk */ + sector = 1 + vol_idx; + err = sflc_disk_readBlock(bdev_path, sector, enc_vmb); + if (err) { + sflc_log_error("Could not read VMB from disk; error %d", err); + return err; + } + + /* Unseal it */ + err = sflite_vmb_unseal(enc_vmb, vmb_key, vmb); + if (err) { + sflc_log_error("Could not unseal VMB; error %d", err); + return err; + } + + /* Compare the number of slices */ + if (nr_slices != vmb->nr_slices) { + sflc_log_error("Incompatible header size: the device size was different when the volumes" + "were created. Did you resize the device %s since last time?", bdev_path); + return EINVAL; + } + + return 0; +} diff --git a/shufflecake-userland/src/utils/crypto.c b/shufflecake-userland/src/utils/crypto.c index b42f50f..4494dd1 100644 --- a/shufflecake-userland/src/utils/crypto.c +++ b/shufflecake-userland/src/utils/crypto.c @@ -95,7 +95,7 @@ int sflc_aes256ctr_encrypt(char *key, char *pt, size_t pt_len, char *iv, char *c sflc_log_debug("Successfully instantiated AES256-CTR cipher handle"); // Set the key - err = gcry_cipher_setkey(hd, key, SFLC_CRYPTO_KEYLEN); + err = gcry_cipher_setkey(hd, key, SFLC_STANDARD_KEYLEN); if (err) { sflc_log_error("Could not set AES key: error %d", err); goto bad_setkey; @@ -163,7 +163,7 @@ int sflc_aes256ctr_decrypt(char *key, char *ct, size_t ct_len, char *iv, char *p sflc_log_debug("Successfully instantiated AES256-CTR cipher handle"); // Set the key - err = gcry_cipher_setkey(hd, key, SFLC_CRYPTO_KEYLEN); + err = gcry_cipher_setkey(hd, key, SFLC_STANDARD_KEYLEN); if (err) { sflc_log_error("Could not set AES key: error %d", err); goto bad_setkey; @@ -205,6 +205,76 @@ bad_open: } +/** + * AES256-XTS encryption. Set ct = NULL for in-place. + * The IV is intepreted as a little-endian "sector number". + * + * @param key The 64-byte AES-XTS key + * @param pt The plaintext + * @param pt_len The length of the plaintext, must be a multiple of the AES + * block size (16 bytes) + * @param iv The 16-byte AES-XTS IV + * @param ct A caller-allocated buffer that will contain the output ciphertext, + * cannot overlap with pt. If NULL, in-place encryption. + * + * @return The error code (0 on success) + */ +int sflc_aes256xts_encrypt(char *key, char *pt, size_t pt_len, char *iv, char *ct) +{ + gcry_cipher_hd_t hd; + gcry_error_t err; + + // Instantiate the handle + err = gcry_cipher_open(&hd, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_XTS, GCRY_CIPHER_SECURE); + if (err) { + sflc_log_error("Could not instantiate AES256-XTS cipher handle: error %d", err); + goto bad_open; + } + sflc_log_debug("Successfully instantiated AES256-XTS cipher handle"); + + // Set the key + err = gcry_cipher_setkey(hd, key, SFLC_AESXTS_KEYLEN); + if (err) { + sflc_log_error("Could not set AES-XTS key: error %d", err); + goto bad_setkey; + } + sflc_log_debug("Successfully set the AES-XTS key"); + + // Set the IV (not a counter, as per Gcrypt docs) + err = gcry_cipher_setiv(hd, iv, SFLC_AESXTS_IVLEN); + if (err) { + sflc_log_error("Could not set AES-XTS IV: error %d", err); + goto bad_setiv; + } + sflc_log_debug("Successfully set the IV"); + + // Encrypt + if (ct == NULL) { // In-place + err = gcry_cipher_encrypt(hd, pt, pt_len, NULL, 0); + } + else { // Out-of-place + err = gcry_cipher_encrypt(hd, ct, pt_len, pt, pt_len); + } + // Error check + if (err) { + sflc_log_error("Could not encrypt: error %d", err); + goto bad_encrypt; + } + sflc_log_debug("Successfully encrypted"); + + // No prob? + err = 0; + + +bad_encrypt: +bad_setiv: +bad_setkey: + gcry_cipher_close(hd); +bad_open: + return err; +} + + /** *AES-GCM encryption, does not touch the IV. * @@ -233,7 +303,7 @@ int sflc_aes256gcm_encrypt(char *key, char *pt, size_t pt_len, char *iv, char *c sflc_log_debug("Successfully instantiated AES256-GCM cipher handle"); // Set the key - err = gcry_cipher_setkey(hd, key, SFLC_CRYPTO_KEYLEN); + err = gcry_cipher_setkey(hd, key, SFLC_STANDARD_KEYLEN); if (err) { sflc_log_error("Could not set AES key: error %d", err); goto bad_setkey; @@ -308,7 +378,7 @@ int sflc_aes256gcm_decrypt(char *key, char *ct, size_t ct_len, char *tag, char * sflc_log_debug("Successfully instantiated AES256-GCM cipher handle"); // Set the key - err = gcry_cipher_setkey(hd, key, SFLC_CRYPTO_KEYLEN); + err = gcry_cipher_setkey(hd, key, SFLC_STANDARD_KEYLEN); if (err) { sflc_log_error("Could not set AES key: error %d", err); goto bad_setkey; @@ -378,7 +448,7 @@ int sflc_argon2id_derive(char *pwd, size_t pwd_len, char *salt, char *hash) { gcry_kdf_hd_t hd; const unsigned long argon_params[4] = - {SFLC_CRYPTO_KEYLEN, SFLC_ARGON_T, SFLC_ARGON_M, SFLC_ARGON_P}; + {SFLC_STANDARD_KEYLEN, SFLC_ARGON_T, SFLC_ARGON_M, SFLC_ARGON_P}; gcry_error_t err; // Instantiate Argon2id handle @@ -405,7 +475,7 @@ int sflc_argon2id_derive(char *pwd, size_t pwd_len, char *salt, char *hash) sflc_log_debug("Successfully run Argon2id computation"); // Finalise hash - err = gcry_kdf_final(hd, SFLC_CRYPTO_KEYLEN, hash); + err = gcry_kdf_final(hd, SFLC_STANDARD_KEYLEN, hash); if (err) { sflc_log_error("Could not finalise Argon2id hash: error %d", err); goto bad_final; diff --git a/shufflecake-userland/src/utils/disk.c b/shufflecake-userland/src/utils/disk.c index 2f78598..7da8c86 100644 --- a/shufflecake-userland/src/utils/disk.c +++ b/shufflecake-userland/src/utils/disk.c @@ -30,11 +30,13 @@ *****************************************************/ #include +#include #include #include #include #include #include +#include #include #include @@ -47,6 +49,30 @@ *****************************************************/ +/** + * Returns a malloc'ed string formatted as : + * + * @param bdev_path The path to the block device + * + * @return A string version of the device ID + */ +char *sflc_disk_getDeviceName(char *bdev_path) +{ + struct stat sb; + char *dev_name; + + if (stat(bdev_path, &sb) != 0) + return NULL; + dev_name = malloc(SFLC_BIGBUFSIZE); + if (!dev_name) + return NULL; + + sprintf(dev_name, "%u:%u", major(sb.st_rdev), minor(sb.st_rdev)); + + return dev_name; +} + + /** * Checks whether the given path points to a block device. * @@ -96,7 +122,7 @@ int64_t sflc_disk_getSize(char * bdev_path) sflc_log_debug("Size of %s is %lu bytes", bdev_path, size_bytes); /* Compute size in SFLC sectors */ - ret = (size_bytes / SFLC_SECTOR_SIZE); + ret = (size_bytes / SFLC_BLOCK_SIZE); bad_ioctl: close(fd); @@ -114,7 +140,7 @@ bad_open: * * @return The error code (0 on success) */ -int sflc_disk_readSector(char * bdev_path, uint64_t sector, char * buf) +int sflc_disk_readBlock(char * bdev_path, uint64_t sector, char * buf) { int fd; int err; @@ -130,7 +156,7 @@ int sflc_disk_readSector(char * bdev_path, uint64_t sector, char * buf) sflc_log_debug("Opened file %s", bdev_path); /* Set offset in bytes */ - if (lseek(fd, sector * SFLC_SECTOR_SIZE, SEEK_SET) < 0) { + if (lseek(fd, sector * SFLC_BLOCK_SIZE, SEEK_SET) < 0) { sflc_log_error("Could not lseek file %s to sector %lu", bdev_path, sector); perror("Cause: "); err = errno; @@ -139,7 +165,7 @@ int sflc_disk_readSector(char * bdev_path, uint64_t sector, char * buf) sflc_log_debug("Successful lseek on file %s to sector %lu", bdev_path, sector); /* Read in a loop */ - size_t bytes_to_read = SFLC_SECTOR_SIZE; + size_t bytes_to_read = SFLC_BLOCK_SIZE; while (bytes_to_read > 0) { /* Read syscall */ ssize_t bytes_read = read(fd, buf, bytes_to_read); @@ -172,22 +198,6 @@ bad_open: } -/** - * Writes a single 4096-byte sector to the disk. - * - * @param bdev_path The path of the block device - * @param sector The index of the desired sector - * @param The caller-allocated buffer (must hold 4096 bytes) where the data - * comes from - * - * @return The error code (0 on success) - */ -int sflc_disk_writeSector(char * bdev_path, uint64_t sector, char * buf) -{ - return sflc_disk_writeManySectors(bdev_path, sector, buf, 1); -} - - /** * Writes many 4096-byte sectors to the disk. * @@ -199,7 +209,7 @@ int sflc_disk_writeSector(char * bdev_path, uint64_t sector, char * buf) * * @return The error code (0 on success) */ -int sflc_disk_writeManySectors(char * bdev_path, uint64_t sector, char * buf, size_t num_sectors) +int sflc_disk_writeManyBlocks(char * bdev_path, uint64_t sector, char * buf, size_t num_sectors) { int fd; int err; @@ -215,7 +225,7 @@ int sflc_disk_writeManySectors(char * bdev_path, uint64_t sector, char * buf, si sflc_log_debug("Opened file %s", bdev_path); /* Set offset in bytes */ - if (lseek(fd, sector * SFLC_SECTOR_SIZE, SEEK_SET) < 0) { + if (lseek(fd, sector * SFLC_BLOCK_SIZE, SEEK_SET) < 0) { sflc_log_error("Could not lseek file %s to sector %lu", bdev_path, sector); perror("Cause: "); err = errno; @@ -224,7 +234,7 @@ int sflc_disk_writeManySectors(char * bdev_path, uint64_t sector, char * buf, si sflc_log_debug("Successful lseek on file %s to sector %lu", bdev_path, sector); /* Write in a loop */ - size_t bytes_to_write = SFLC_SECTOR_SIZE * num_sectors; + size_t bytes_to_write = SFLC_BLOCK_SIZE * num_sectors; while (bytes_to_write > 0) { /* Write syscall */ ssize_t bytes_written = write(fd, buf, bytes_to_write); diff --git a/shufflecake-userland/src/utils/dm.c b/shufflecake-userland/src/utils/dm.c index 6c2d054..275d61e 100644 --- a/shufflecake-userland/src/utils/dm.c +++ b/shufflecake-userland/src/utils/dm.c @@ -35,6 +35,7 @@ #include #include "utils/dm.h" +#include "utils/sflc.h" #include "utils/log.h" diff --git a/shufflecake-userland/test/crypto/test_aes256ctr.c b/shufflecake-userland/test/crypto/test_aes256ctr.c index 700a910..ce2676b 100644 --- a/shufflecake-userland/test/crypto/test_aes256ctr.c +++ b/shufflecake-userland/test/crypto/test_aes256ctr.c @@ -56,10 +56,10 @@ char *test_aes256ctr_encrypt_inplace() char iv[] = AES256CTR_TEST_IV; int err; - sflc_log_blue("Testing AES256-CTR encryption in-place"); + sflite_log_blue("Testing AES256-CTR encryption in-place"); // Encrypt in-place - err = sflc_aes256ctr_encrypt(key, msg, msg_len, iv, NULL); + err = sflite_aes256ctr_encrypt(key, msg, msg_len, iv, NULL); // Check error mu_assert("Error while encrypting", !err); @@ -73,7 +73,7 @@ char *test_aes256ctr_encrypt_inplace() // Check IV untouched mu_assert("IV changed", memcmp(iv, IV, sizeof(iv)) == 0); - sflc_log_green("OK"); + sflite_log_green("OK"); return NULL; } @@ -87,10 +87,10 @@ char *test_aes256ctr_encrypt_outofplace() char iv[] = AES256CTR_TEST_IV; int err; - sflc_log_blue("Testing AES256-CTR encryption out-of-place"); + sflite_log_blue("Testing AES256-CTR encryption out-of-place"); // Encrypt out-of-place - err = sflc_aes256ctr_encrypt(key, msg, msg_len, iv, ct); + err = sflite_aes256ctr_encrypt(key, msg, msg_len, iv, ct); // Check error mu_assert("Error while encrypting", !err); @@ -107,7 +107,7 @@ char *test_aes256ctr_encrypt_outofplace() // Check IV untouched mu_assert("IV changed", memcmp(iv, IV, sizeof(iv)) == 0); - sflc_log_green("OK"); + sflite_log_green("OK"); return NULL; } @@ -120,10 +120,10 @@ char *test_aes256ctr_decrypt_inplace() char iv[] = AES256CTR_TEST_IV; int err; - sflc_log_blue("Testing AES256-CTR decryption in-place"); + sflite_log_blue("Testing AES256-CTR decryption in-place"); // Decrypt in-place - err = sflc_aes256ctr_decrypt(key, msg, msg_len, iv, NULL); + err = sflite_aes256ctr_decrypt(key, msg, msg_len, iv, NULL); // Check error mu_assert("Error while decrypting", !err); @@ -137,7 +137,7 @@ char *test_aes256ctr_decrypt_inplace() // Check IV untouched mu_assert("IV changed", memcmp(iv, IV, sizeof(iv)) == 0); - sflc_log_green("OK"); + sflite_log_green("OK"); return NULL; } @@ -151,10 +151,10 @@ char *test_aes256ctr_decrypt_outofplace() char iv[] = AES256CTR_TEST_IV; int err; - sflc_log_blue("Testing AES256-CTR decryption out-of-place"); + sflite_log_blue("Testing AES256-CTR decryption out-of-place"); // Decrypt out-of-place - err = sflc_aes256ctr_decrypt(key, msg, msg_len, iv, pt); + err = sflite_aes256ctr_decrypt(key, msg, msg_len, iv, pt); // Check error mu_assert("Error while decrypting", !err); @@ -171,7 +171,7 @@ char *test_aes256ctr_decrypt_outofplace() // Check IV untouched mu_assert("IV changed", memcmp(iv, IV, sizeof(iv)) == 0); - sflc_log_green("OK"); + sflite_log_green("OK"); return NULL; } diff --git a/shufflecake-userland/test/crypto/test_aes256gcm.c b/shufflecake-userland/test/crypto/test_aes256gcm.c index b332c51..da5458a 100644 --- a/shufflecake-userland/test/crypto/test_aes256gcm.c +++ b/shufflecake-userland/test/crypto/test_aes256gcm.c @@ -56,20 +56,20 @@ char *test_aes256gcm_encrypt() char key[] = AES256GCM_TEST_KEY; char iv[] = AES256GCM_TEST_IV; char ct[sizeof(pt)]; - char tag[SFLC_AESGCM_TAGLEN]; + char tag[SFLITE_AESGCM_TAGLEN]; int err; - sflc_log_blue("Testing AES256-GCM encryption"); + sflite_log_blue("Testing AES256-GCM encryption"); // Encrypt - err = sflc_aes256gcm_encrypt(key, pt, pt_len, iv, ct, tag); + err = sflite_aes256gcm_encrypt(key, pt, pt_len, iv, ct, tag); // Check error mu_assert("Error while encrypting", !err); // Check outcome mu_assert("Ciphertext mismatch", memcmp(ct, CT, pt_len) == 0); - mu_assert("MAC mismatch", memcmp(tag, TAG, SFLC_AESGCM_TAGLEN) == 0); + mu_assert("MAC mismatch", memcmp(tag, TAG, SFLITE_AESGCM_TAGLEN) == 0); // Check key untouched mu_assert("Key changed", memcmp(key, KEY, sizeof(key)) == 0); @@ -77,7 +77,7 @@ char *test_aes256gcm_encrypt() // Check IV untouched mu_assert("IV changed", memcmp(iv, IV, sizeof(iv)) == 0); - sflc_log_green("OK"); + sflite_log_green("OK"); return NULL; } @@ -93,10 +93,10 @@ char *test_aes256gcm_decrypt_good() char pt[sizeof(ct)]; int err; - sflc_log_blue("Testing AES256-GCM decryption with the proper MAC"); + sflite_log_blue("Testing AES256-GCM decryption with the proper MAC"); // Decrypt - err = sflc_aes256gcm_decrypt(key, ct, ct_len, tag, iv, pt, &match); + err = sflite_aes256gcm_decrypt(key, ct, ct_len, tag, iv, pt, &match); // Check error mu_assert("Error while decrypting", !err); @@ -114,7 +114,7 @@ char *test_aes256gcm_decrypt_good() // Check MAC untouched mu_assert("MAC changed", memcmp(tag, TAG, sizeof(tag)) == 0); - sflc_log_green("OK"); + sflite_log_green("OK"); return NULL; } @@ -130,13 +130,13 @@ char *test_aes256gcm_decrypt_fail() char pt[sizeof(ct)]; int err; - sflc_log_blue("Testing AES256-GCM decryption without the proper MAC"); + sflite_log_blue("Testing AES256-GCM decryption without the proper MAC"); // Corrupt the MAC tag[0] += 1; // Decrypt - err = sflc_aes256gcm_decrypt(key, ct, ct_len, tag, iv, pt, &match); + err = sflite_aes256gcm_decrypt(key, ct, ct_len, tag, iv, pt, &match); // Check error mu_assert("Error while decrypting", !err); @@ -154,7 +154,7 @@ char *test_aes256gcm_decrypt_fail() mu_assert("Tail of MAC changed", memcmp(tag+1, TAG+1, sizeof(tag)-1) == 0); mu_assert("Head of MAC changed", tag[0] == TAG[0]+1); - sflc_log_green("OK"); + sflite_log_green("OK"); return NULL; } diff --git a/shufflecake-userland/test/crypto/test_argon2id.c b/shufflecake-userland/test/crypto/test_argon2id.c index 0ded58b..b50bf3e 100644 --- a/shufflecake-userland/test/crypto/test_argon2id.c +++ b/shufflecake-userland/test/crypto/test_argon2id.c @@ -39,7 +39,7 @@ * CONSTANT VARIABLES * *****************************************************/ -char SALT[SFLC_ARGON_SALTLEN+1] = "Poor Petrol Pump"; +char SALT[SFLITE_ARGON_SALTLEN+1] = "Poor Petrol Pump"; /***************************************************** @@ -48,17 +48,17 @@ char SALT[SFLC_ARGON_SALTLEN+1] = "Poor Petrol Pump"; char *test_argon2id() { - char pwd[SFLC_BIGBUFSIZE]; - char key[SFLC_CRYPTO_KEYLEN]; + char pwd[SFLITE_BIGBUFSIZE]; + char key[SFLITE_STANDARD_KEYLEN]; int err; - sflc_log_blue("Testing Argon2id interactively with a fixed salt"); + sflite_log_blue("Testing Argon2id interactively with a fixed salt"); // Loop until user breaks out while (true) { /* Collect password */ printf("Choose password to hash (empty to skip): "); - err = sflc_safeReadLine(pwd, SFLC_BIGBUFSIZE); + err = sflite_safeReadLine(pwd, SFLITE_BIGBUFSIZE); mu_assert("Could not read password", !err); /* Check if empty */ @@ -67,15 +67,15 @@ char *test_argon2id() } /* Hash it */ - err = sflc_argon2id_derive(pwd, strlen(pwd), SALT, key); + err = sflite_argon2id_derive(pwd, strlen(pwd), SALT, key); mu_assert("Could not hash password", !err); /* Print it */ printf("Salt used ASCII: \"%s\". Hex:\n", SALT); - sflc_log_hex(SALT, SFLC_ARGON_SALTLEN); + sflite_log_hex(SALT, SFLITE_ARGON_SALTLEN); printf("Argon2id hash (m = %d, t = %d, p = %d):\n", - SFLC_ARGON_M, SFLC_ARGON_T, SFLC_ARGON_P); - sflc_log_hex(key, SFLC_CRYPTO_KEYLEN); + SFLITE_ARGON_M, SFLITE_ARGON_T, SFLITE_ARGON_P); + sflite_log_hex(key, SFLITE_STANDARD_KEYLEN); printf("Go check the result online\n\n"); } diff --git a/shufflecake-userland/test/main.c b/shufflecake-userland/test/main.c index 565aa2c..1f3a506 100644 --- a/shufflecake-userland/test/main.c +++ b/shufflecake-userland/test/main.c @@ -49,10 +49,10 @@ int main() char *result = all_tests(); if (result != NULL) { - sflc_log_red("\nTEST FAILED: %s", result); + sflite_log_red("\nTEST FAILED: %s", result); } else { - sflc_log_green("\nALL TESTS PASSED"); + sflite_log_green("\nALL TESTS PASSED"); } return result != NULL; @@ -65,7 +65,7 @@ int main() static char *all_tests() { - sflc_log_yellow("Running crypto tests"); + sflite_log_yellow("Running crypto tests"); mu_run_test(test_aes256ctr_encrypt_inplace); mu_run_test(test_aes256ctr_encrypt_outofplace); mu_run_test(test_aes256ctr_decrypt_inplace);