Skip to content

Commit

Permalink
WIP: test updates
Browse files Browse the repository at this point in the history
  • Loading branch information
ebiggers committed Nov 26, 2020
1 parent da6f16a commit 3b5e089
Show file tree
Hide file tree
Showing 4 changed files with 585 additions and 238 deletions.
30 changes: 18 additions & 12 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,24 @@ information on using pull requests.

## Before you submit a pull request

When making any changes to `fscryptctl`, you will need the following commands:
* `make format` which formats all of the C code (requires `clang-format`)
* `make test` which runs the tests for fscryptctl (requires `python3` and the
`pytest` and `keyutils` python packages). Note that to run all of the tests,
the environment variable `TEST_FILESYSTEM_ROOT` must be set to the
mountpoint of an ext4 filesystem setup for encryption that the user can
mount and unmount.
* `make all` - Runs the above commands and builds `fscryptctl`.

Make sure all these commands are run and the tests pass before submitting a pull
request. All the above dependencies can be installed with:
When making any changes to `fscryptctl`, run the following commands:
* `make format`, which formats the source code (requires `clang-format`)
* `make test-all`, which builds `fscryptctl` and runs the tests. The tests
require the `e2fsprogs` and `python3` packages, the `pytest` and `keyutils`
Python packages, and kernel support for ext4 encryption.

The userspace dependencies can be installed with:
``` bash
> sudo apt-get install python3-pip libkeyutils-dev clang-format
> sudo apt-get install e2fsprogs python3-pip libkeyutils-dev clang-format
> sudo -H pip3 install -U pip pytest keyutils
```

Your Linux kernel must be version 5.4 or later and have the following
configuration options enabled:
```
CONFIG_EXT4_FS
CONFIG_FS_ENCRYPTION
CONFIG_CRYPTO_ADIANTUM
CONFIG_CRYPTO_SHA256
CONFIG_CRYPTO_ESSIV (if 5.5 or later)
```
80 changes: 43 additions & 37 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -81,44 +81,50 @@ format-check:

##############################################################################

# Testing targets (root permissions required)
# Testing targets

# IMAGE will be the path to our test ext4 image file.
IMAGE ?= fscryptctl_image

# MOUNT will be the path to the filesystem where our tests are run.
# The 'test' target requires that $(TEST_DIR) point to a directory on a
# filesystem that supports encryption.
#
# 'test-setup' sets up the default TEST_DIR to point to a directory on a
# temporary ext4 filesystem on a loopback device. 'test-teardown' cleans up
# afterwards. Note that both of these use 'sudo'.
#
# Running "make test-setup MOUNT=/foo/bar" creates a test filesystem at that
# location. Be sure to also run "make test-teardown MOUNT=/foo/bar".
# Running "make test MOUNT=/foo/bar" will run all tests on that filesystem. By
# default, it is the one created with "make test-setup".
MOUNT ?= /mnt/fscryptctl_mount
export TEST_FILESYSTEM_ROOT = $(MOUNT)

.PHONY: root test
root:
ifneq ($(shell id -u),0)
$(error You must be root to execute this command)
endif

test: fscryptctl root
ifeq ("$(wildcard $(MOUNT))","")
$(error mountpoint $(MOUNT) does not exist, run "make test-setup")
endif
python3 -m pytest test.py -s -q

.PHONY: test-setup test-teardown
test-setup: root
dd if=/dev/zero of=$(IMAGE) bs=1M count=20
mkfs.ext4 -b 4096 -O encrypt -F $(IMAGE)
mkdir -p $(MOUNT)
mount -o rw,loop,user $(IMAGE) $(MOUNT)
chmod +777 $(MOUNT)

test-teardown: root
umount $(MOUNT)
rmdir $(MOUNT)
rm -f $(IMAGE)
# 'test-all' runs 'test-setup', 'test', and 'test-teardown'.

TEST_IMAGE ?= /tmp/fscryptctl-test-image
TEST_DIR ?= /tmp/fscryptctl-test-dir

.PHONY: test test-setup test-teardown test-all

test: fscryptctl
@if [ ! -e "$(TEST_DIR)" ]; then \
echo 1>&2 "Directory $(TEST_DIR) does not exist, run 'make test-setup'"; \
exit 1; \
fi
TEST_DIR="$(TEST_DIR)" PATH="$$PWD:$$PATH" \
python3 -m pytest test.py -s -q

test-setup:test-teardown
dd if=/dev/zero of="$(TEST_IMAGE)" bs=1M count=32
mkfs.ext4 -b 4096 -O encrypt -F "$(TEST_IMAGE)"
mkdir -p "$(TEST_DIR)"
sudo mount -o rw,loop "$(TEST_IMAGE)" "$(TEST_DIR)"
sudo sh -c 'chown $$SUDO_USER:$$SUDO_USER "$(TEST_DIR)"'
@echo
@echo "$(TEST_DIR) is now set up."

test-teardown:
if mountpoint "$(TEST_DIR)" &> /dev/null; then \
sudo umount "$(TEST_DIR)"; \
fi
rm -rf "$(TEST_DIR)"
rm -f "$(TEST_IMAGE)"

test-all:
$(MAKE) test-setup
$(MAKE) test
$(MAKE) test-teardown

.PHONY: travis-install travis-script
travis-install: test-setup
Expand All @@ -138,6 +144,6 @@ uninstall:
rm -f $(DESTDIR)$(BINDIR)/fscryptctl

clean:
rm -f fscryptctl *.o *.pyc $(IMAGE)
rm -f fscryptctl *.o *.pyc
rm -rf __pycache__
rm -rf .pytest_cache
47 changes: 47 additions & 0 deletions generate_test_key_identifiers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Generates the key descriptors and identifiers for the test keys in test.py
#
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

import hashlib
import test

# For HKDF-SHA512; see
# https://www.pycryptodome.org/en/latest/src/protocol/kdf.html#hkdf
import Crypto.Hash.SHA512
import Crypto.Protocol.KDF


def compute_key_descriptor(raw):
return hashlib.sha512(hashlib.sha512(raw).digest()).hexdigest()[:16]


def compute_key_identifier(raw):
return Crypto.Protocol.KDF.HKDF(raw, 16, "", Crypto.Hash.SHA512,
context=b"fscrypt\0\1").hex()


for key in test.TEST_KEYS:
raw = key["raw"]
descriptor = compute_key_descriptor(raw)
identifier = compute_key_identifier(raw)
if "descriptor" in key:
assert descriptor == key["descriptor"]
if "identifier" in key:
assert identifier == key["identifier"]
print("... = {")
print(" raw: " + str(raw) + ",")
print(' "descriptor": "' + descriptor + '",')
print(' "identifier": "' + identifier + '",')
print("}")

0 comments on commit 3b5e089

Please sign in to comment.