mirror of
https://github.com/vgough/encfs.git
synced 2024-11-28 02:43:50 +01:00
Merge pull request #23 from rfjakob/master
Add integration tests & Compare MACs in constant time
This commit is contained in:
commit
744f56b95d
@ -206,12 +206,18 @@ ssize_t MACFileIO::readOneBlock( const IORequest &req ) const
|
|||||||
uint64_t mac = cipher->MAC_64( tmp.data + macBytes,
|
uint64_t mac = cipher->MAC_64( tmp.data + macBytes,
|
||||||
readSize - macBytes, key );
|
readSize - macBytes, key );
|
||||||
|
|
||||||
|
// Constant time comparision to prevent timing attacks
|
||||||
|
unsigned char fail = 0;
|
||||||
for(int i=0; i<macBytes; ++i, mac >>= 8)
|
for(int i=0; i<macBytes; ++i, mac >>= 8)
|
||||||
{
|
{
|
||||||
int test = mac & 0xff;
|
int test = mac & 0xff;
|
||||||
int stored = tmp.data[i];
|
int stored = tmp.data[i];
|
||||||
if(test != stored)
|
|
||||||
{
|
fail |= (test ^ stored);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( fail > 0 )
|
||||||
|
{
|
||||||
// uh oh..
|
// uh oh..
|
||||||
long blockNum = req.offset / bs;
|
long blockNum = req.offset / bs;
|
||||||
rWarning(_("MAC comparison failure in block %li"),
|
rWarning(_("MAC comparison failure in block %li"),
|
||||||
@ -222,8 +228,6 @@ ssize_t MACFileIO::readOneBlock( const IORequest &req ) const
|
|||||||
throw ERROR(
|
throw ERROR(
|
||||||
_("MAC comparison failure, refusing to read"));
|
_("MAC comparison failure, refusing to read"));
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
37
tests/default.xml
Normal file
37
tests/default.xml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||||
|
<!DOCTYPE boost_serialization>
|
||||||
|
<boost_serialization signature="serialization::archive" version="10">
|
||||||
|
<cfg class_id="0" tracking_level="0" version="20">
|
||||||
|
<version>20100713</version>
|
||||||
|
<creator>EncFS 1.7.5</creator>
|
||||||
|
<cipherAlg class_id="1" tracking_level="0" version="0">
|
||||||
|
<name>ssl/aes</name>
|
||||||
|
<major>3</major>
|
||||||
|
<minor>0</minor>
|
||||||
|
</cipherAlg>
|
||||||
|
<nameAlg>
|
||||||
|
<name>nameio/block</name>
|
||||||
|
<major>4</major>
|
||||||
|
<minor>0</minor>
|
||||||
|
</nameAlg>
|
||||||
|
<keySize>192</keySize>
|
||||||
|
<blockSize>1024</blockSize>
|
||||||
|
<uniqueIV>1</uniqueIV>
|
||||||
|
<chainedNameIV>1</chainedNameIV>
|
||||||
|
<externalIVChaining>0</externalIVChaining>
|
||||||
|
<blockMACBytes>0</blockMACBytes>
|
||||||
|
<blockMACRandBytes>0</blockMACRandBytes>
|
||||||
|
<allowHoles>1</allowHoles>
|
||||||
|
<encodedKeySize>44</encodedKeySize>
|
||||||
|
<encodedKeyData>
|
||||||
|
AL2iRMLYyuf7RXcFCK0CcegQ/+enbaaqTq1OY3WULMLpcz0yvo8K4KtVw7c=
|
||||||
|
</encodedKeyData>
|
||||||
|
<saltLen>20</saltLen>
|
||||||
|
<saltData>
|
||||||
|
RVCTqJyxxp7ZN0AsLJhgpvSuUB8=
|
||||||
|
</saltData>
|
||||||
|
<kdfIterations>170562</kdfIterations>
|
||||||
|
<desiredKDFDuration>500</desiredKDFDuration>
|
||||||
|
</cfg>
|
||||||
|
</boost_serialization>
|
||||||
|
|
37
tests/mac.xml
Normal file
37
tests/mac.xml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||||
|
<!DOCTYPE boost_serialization>
|
||||||
|
<boost_serialization signature="serialization::archive" version="10">
|
||||||
|
<cfg class_id="0" tracking_level="0" version="20">
|
||||||
|
<version>20100713</version>
|
||||||
|
<creator>EncFS 1.7.5</creator>
|
||||||
|
<cipherAlg class_id="1" tracking_level="0" version="0">
|
||||||
|
<name>ssl/aes</name>
|
||||||
|
<major>3</major>
|
||||||
|
<minor>0</minor>
|
||||||
|
</cipherAlg>
|
||||||
|
<nameAlg>
|
||||||
|
<name>nameio/block</name>
|
||||||
|
<major>4</major>
|
||||||
|
<minor>0</minor>
|
||||||
|
</nameAlg>
|
||||||
|
<keySize>192</keySize>
|
||||||
|
<blockSize>1024</blockSize>
|
||||||
|
<uniqueIV>1</uniqueIV>
|
||||||
|
<chainedNameIV>1</chainedNameIV>
|
||||||
|
<externalIVChaining>0</externalIVChaining>
|
||||||
|
<blockMACBytes>8</blockMACBytes>
|
||||||
|
<blockMACRandBytes>0</blockMACRandBytes>
|
||||||
|
<allowHoles>1</allowHoles>
|
||||||
|
<encodedKeySize>44</encodedKeySize>
|
||||||
|
<encodedKeyData>
|
||||||
|
AL2iRMLYyuf7RXcFCK0CcegQ/+enbaaqTq1OY3WULMLpcz0yvo8K4KtVw7c=
|
||||||
|
</encodedKeyData>
|
||||||
|
<saltLen>20</saltLen>
|
||||||
|
<saltData>
|
||||||
|
RVCTqJyxxp7ZN0AsLJhgpvSuUB8=
|
||||||
|
</saltData>
|
||||||
|
<kdfIterations>170562</kdfIterations>
|
||||||
|
<desiredKDFDuration>500</desiredKDFDuration>
|
||||||
|
</cfg>
|
||||||
|
</boost_serialization>
|
||||||
|
|
109
tests/run.sh
Executable file
109
tests/run.sh
Executable file
@ -0,0 +1,109 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# This is the wrapper script for all tests.
|
||||||
|
# It calls the unit tests and all integration tests.
|
||||||
|
#
|
||||||
|
# Functions that are useful in more than one integration test
|
||||||
|
# should be defined here.
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
# Set up envrionment variables, cd to the correct directory
|
||||||
|
function init {
|
||||||
|
|
||||||
|
# Make sure we are in the "tests" directory
|
||||||
|
TESTDIR=$(dirname $(realpath "$0"))
|
||||||
|
cd $TESTDIR
|
||||||
|
|
||||||
|
# Full path to encfs binary
|
||||||
|
ENCFS=$(realpath ../encfs/encfs)
|
||||||
|
|
||||||
|
# Directory for temporary files (scratch)
|
||||||
|
SCRATCH=$(realpath scratch)
|
||||||
|
LOWER=$SCRATCH/lower
|
||||||
|
UPPER=$SCRATCH/upper
|
||||||
|
|
||||||
|
# Test number counter
|
||||||
|
TESTNO=1
|
||||||
|
|
||||||
|
trap 'echo -e "***\e[31m test(s) FAILED\e[0m"' ERR
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run all test_*.sh files
|
||||||
|
function run_cli_tests {
|
||||||
|
|
||||||
|
cd $TESTDIR
|
||||||
|
for i in $(echo test_*.sh)
|
||||||
|
do
|
||||||
|
cleanup
|
||||||
|
mkdir $SCRATCH
|
||||||
|
echo "*** running $i"
|
||||||
|
source $i
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# fresh_mount CONFIG
|
||||||
|
#
|
||||||
|
# Mount a fresh, empty encfs filesystem using the encfs config file
|
||||||
|
# CONFIG as .encfs6.xml. The password must be set to "a".
|
||||||
|
# The backing files will be at $LOWER, the mounted filesystem at $UPPER.
|
||||||
|
function fresh_mount {
|
||||||
|
cd $TESTDIR
|
||||||
|
fusermount -q -u $UPPER 2> /dev/null || true
|
||||||
|
wait
|
||||||
|
rm -Rf $LOWER $UPPER
|
||||||
|
mkdir -p $LOWER $UPPER
|
||||||
|
touch $UPPER/not_yet_mounted
|
||||||
|
|
||||||
|
cp $TESTDIR/$1 $SCRATCH/lower/.encfs6.xml
|
||||||
|
|
||||||
|
echo a | $ENCFS -f -S -o nonempty $LOWER $UPPER 2> /dev/null &
|
||||||
|
while [ -e $UPPER/not_yet_mounted ]
|
||||||
|
do
|
||||||
|
sleep 0.1s
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Clean up scratch directory
|
||||||
|
function cleanup {
|
||||||
|
test -d $SCRATCH || return 0
|
||||||
|
|
||||||
|
cd $SCRATCH/..
|
||||||
|
fusermount -q -u $UPPER 2> /dev/null || true
|
||||||
|
wait
|
||||||
|
rm -Rf $SCRATCH
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the plain MD5 sum of a file, without the filename that is output
|
||||||
|
# by md5sum
|
||||||
|
# md5sum foo: 5f47bbbd6db883f93f5d00fd05f149ff foo
|
||||||
|
# plain_md5 foo: 5f47bbbd6db883f93f5d00fd05f149ff
|
||||||
|
function md5 {
|
||||||
|
OUTPUT=$(md5sum "$1") # Capture md5sum output
|
||||||
|
ARRAY=($OUTPUT) # Split into array
|
||||||
|
echo ${ARRAY[0]} # Return first element
|
||||||
|
}
|
||||||
|
|
||||||
|
# Indicate beginning of a test
|
||||||
|
# Prints test number and title
|
||||||
|
function test_begin {
|
||||||
|
echo -n "$TESTNO $1: "
|
||||||
|
let TESTNO++
|
||||||
|
}
|
||||||
|
|
||||||
|
# Indicate successful completion of a test
|
||||||
|
function test_ok {
|
||||||
|
echo "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
init
|
||||||
|
|
||||||
|
test_begin "Running unit tests"
|
||||||
|
../encfs/test 2> /dev/null
|
||||||
|
test_ok
|
||||||
|
|
||||||
|
run_cli_tests
|
||||||
|
|
||||||
|
echo -e "***\e[32m All tests OK\e[0m"
|
||||||
|
|
||||||
|
cleanup
|
31
tests/test_corruption.sh
Normal file
31
tests/test_corruption.sh
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
fresh_mount default.xml
|
||||||
|
cd $SCRATCH
|
||||||
|
dd if=/dev/urandom of=foo bs=1M count=1 2> /dev/null
|
||||||
|
A=$(md5 foo)
|
||||||
|
cp foo $UPPER
|
||||||
|
cd $UPPER
|
||||||
|
test_begin "Reading file"
|
||||||
|
B=$(md5 foo)
|
||||||
|
test $A = $B
|
||||||
|
test_ok
|
||||||
|
|
||||||
|
test_begin "Reading corrupted file"
|
||||||
|
echo DEADBEEF >> $LOWER/$(ls $LOWER)
|
||||||
|
B=$(md5 foo)
|
||||||
|
test $A != $B
|
||||||
|
test_ok
|
||||||
|
|
||||||
|
fresh_mount mac.xml
|
||||||
|
cd $SCRATCH
|
||||||
|
cp foo $UPPER
|
||||||
|
cd $UPPER
|
||||||
|
test_begin "Reading file with MAC"
|
||||||
|
B=$(md5 foo)
|
||||||
|
test $A = $B
|
||||||
|
test_ok
|
||||||
|
|
||||||
|
test_begin "Corruption with MAC returns IO error"
|
||||||
|
echo DEADBEEF >> $LOWER/$(ls $LOWER)
|
||||||
|
md5 foo 2>&1 | grep "Input/output error" > /dev/null
|
||||||
|
test_ok
|
||||||
|
|
40
tests/test_file_expansion.sh
Normal file
40
tests/test_file_expansion.sh
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
fresh_mount default.xml
|
||||||
|
cd $UPPER
|
||||||
|
test_begin "Creating files of different sizes: "
|
||||||
|
for i in `seq 0 50` `seq 1000 1050`
|
||||||
|
do
|
||||||
|
OUTPUT=$(dd if=/dev/zero bs=$i count=1 2> /dev/null | tee $i | md5sum)
|
||||||
|
ARRAY=($OUTPUT)
|
||||||
|
A=${ARRAY[0]} # Remove filename
|
||||||
|
B=$(md5 $i)
|
||||||
|
test $A = $B
|
||||||
|
done
|
||||||
|
test_ok
|
||||||
|
|
||||||
|
test_begin "Growing file"
|
||||||
|
rm -f ../grow
|
||||||
|
for i in `seq 0 300`
|
||||||
|
do
|
||||||
|
echo -n "abcdefg" >> ../grow
|
||||||
|
echo -n "abcdefg" >> grow
|
||||||
|
|
||||||
|
A=$(md5 ../grow)
|
||||||
|
B=$(md5 grow)
|
||||||
|
test "$A" = "$B"
|
||||||
|
done
|
||||||
|
test_ok
|
||||||
|
|
||||||
|
test_begin "Internal modification"
|
||||||
|
dd if=/dev/urandom of=../internal bs=1M count=2 2> /dev/null
|
||||||
|
cp ../internal internal
|
||||||
|
for i in 0 30 1020 1200
|
||||||
|
do
|
||||||
|
dd if=/dev/zero of=../internal bs=1 count=1 skip=$i 2> /dev/null
|
||||||
|
dd if=/dev/zero of=internal bs=1 count=1 skip=$i 2> /dev/null
|
||||||
|
|
||||||
|
A=$(md5 ../internal)
|
||||||
|
B=$(md5 internal)
|
||||||
|
test "$A" = "$B"
|
||||||
|
done
|
||||||
|
test_ok
|
||||||
|
|
Loading…
Reference in New Issue
Block a user