Rework tests and AES CPU detection
This commit is contained in:
parent
7540fa7d7c
commit
fe7c7f982b
14
.ci/build.sh
14
.ci/build.sh
@ -27,19 +27,7 @@ ls -lah pegh.static.*
|
|||||||
file pegh.static.*
|
file pegh.static.*
|
||||||
ldd pegh.static.* || true
|
ldd pegh.static.* || true
|
||||||
|
|
||||||
# libsodium only supports AES-256-GCM on certain CPUs that have hardware instructions for it
|
export TEST_BINS="./pegh.static.openssl ./pegh.openssl ./pegh.static.libsodium-openssl ./pegh.libsodium-openssl ./pegh.static.libsodium ./pegh.libsodium"
|
||||||
# we can build them regardless, but we can't test them without that, pegh prints that right away
|
|
||||||
export TEST_BINS="./pegh.static.openssl ./pegh.openssl ./pegh.static.libsodium-openssl ./pegh.libsodium-openssl"
|
|
||||||
set +e
|
|
||||||
if ./pegh.static.libsodium -h 2>&1 >/dev/null | grep '^Error: libsodium'
|
|
||||||
then
|
|
||||||
echo "CPU does not have AES support so can't run libsodium version"
|
|
||||||
else
|
|
||||||
echo "CPU has AES support so can run libsodium version"
|
|
||||||
# we can test everything
|
|
||||||
export TEST_BINS="$TEST_BINS ./pegh.libsodium ./pegh.static.libsodium"
|
|
||||||
fi
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# compile dynamically linked versions (with gcc) to openssl and libsodium, then test all 4 against each other
|
# compile dynamically linked versions (with gcc) to openssl and libsodium, then test all 4 against each other
|
||||||
./test.sh
|
./test.sh
|
||||||
|
53
pegh.c
53
pegh.c
@ -730,9 +730,10 @@ int check_version(uint8_t version, FILE *err) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#ifdef PEGH_LIBSODIUM
|
#ifdef PEGH_LIBSODIUM
|
||||||
else if (version == 0 && crypto_aead_aes256gcm_is_available() == 0) {
|
/* check for AES encrypted but libsodium/hardware AES is not available */
|
||||||
/* AES encrypted but libsodium/hardware AES is not available */
|
|
||||||
#ifdef PEGH_OPENSSL
|
#ifdef PEGH_OPENSSL
|
||||||
|
/* if we've already checked/set this, don't again */
|
||||||
|
else if (gcm_encrypt != gcm_encrypt_openssl && version == 0 && crypto_aead_aes256gcm_is_available() == 0) {
|
||||||
/* swap to OpenSSL AES which is always supported */
|
/* swap to OpenSSL AES which is always supported */
|
||||||
if(NULL != err)
|
if(NULL != err)
|
||||||
fprintf(err, "Warning: libsodium does not support AES-256-GCM on this CPU, falling back to openssl version instead...\n");
|
fprintf(err, "Warning: libsodium does not support AES-256-GCM on this CPU, falling back to openssl version instead...\n");
|
||||||
@ -740,9 +741,10 @@ int check_version(uint8_t version, FILE *err) {
|
|||||||
gcm_decrypt = gcm_decrypt_openssl;
|
gcm_decrypt = gcm_decrypt_openssl;
|
||||||
CHUNK_SIZE_MAX_GCM = CHUNK_SIZE_MAX_OPENSSL_GCM;
|
CHUNK_SIZE_MAX_GCM = CHUNK_SIZE_MAX_OPENSSL_GCM;
|
||||||
#else
|
#else
|
||||||
|
else if (version == 0 && crypto_aead_aes256gcm_is_available() == 0) {
|
||||||
/* nothing we can do */
|
/* nothing we can do */
|
||||||
fprintf(stderr, "Error: libsodium does not support AES-256-GCM on this CPU, compile/use openssl version?\n");
|
fprintf(stderr, "Error: libsodium does not support AES-256-GCM on this CPU, compile/use openssl version?\n");
|
||||||
return 0;
|
return 19;
|
||||||
#endif /* PEGH_OPENSSL */
|
#endif /* PEGH_OPENSSL */
|
||||||
}
|
}
|
||||||
#endif /* PEGH_LIBSODIUM */
|
#endif /* PEGH_LIBSODIUM */
|
||||||
@ -795,6 +797,8 @@ int pegh_decrypt(char *password,
|
|||||||
{
|
{
|
||||||
unsigned char salt[SALT_LEN] = {0};
|
unsigned char salt[SALT_LEN] = {0};
|
||||||
|
|
||||||
|
int version_exit_code;
|
||||||
|
|
||||||
size_t header_read, buffer_size;
|
size_t header_read, buffer_size;
|
||||||
|
|
||||||
uint32_t N;
|
uint32_t N;
|
||||||
@ -808,9 +812,9 @@ int pegh_decrypt(char *password,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
version = salt[0];
|
version = salt[0];
|
||||||
if(1 != check_version(version, err)) {
|
if(1 != (version_exit_code = check_version(version, err))) {
|
||||||
fprintf(stderr, "Error: decryption aborting, this file cannot be decrypted with this version/CPU\n");
|
fprintf(stderr, "Error: decryption aborting, this file cannot be decrypted with this version/CPU\n");
|
||||||
return 0;
|
return version_exit_code;
|
||||||
}
|
}
|
||||||
N = read_uint32_big_endian(salt+1);
|
N = read_uint32_big_endian(salt+1);
|
||||||
r = salt[5];
|
r = salt[5];
|
||||||
@ -922,7 +926,7 @@ uint32_t next_highest_power_of_2(uint32_t v) {
|
|||||||
return ++v;
|
return ++v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns 0 on success, 1 on openssl failure, 2 on other failure */
|
/* returns 0 on success, 1 on cryptography failure, 19 on "libsodium only and CPU does not support AES" error, 2 on other failure */
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int optind, decrypt = 0, append = 0, exit_code = 2, version = -1;
|
int optind, decrypt = 0, append = 0, exit_code = 2, version = -1;
|
||||||
@ -933,6 +937,13 @@ int main(int argc, char **argv)
|
|||||||
FILE *in = stdin, *out = stdout, *err = stderr;
|
FILE *in = stdin, *out = stdout, *err = stderr;
|
||||||
char *in_filename = NULL, *out_filename = NULL;
|
char *in_filename = NULL, *out_filename = NULL;
|
||||||
|
|
||||||
|
#ifdef PEGH_LIBSODIUM
|
||||||
|
if (sodium_init() == -1) {
|
||||||
|
fprintf(stderr, "Error: libsodium could not be initialized, compile/use openssl version?\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif /* PEGH_LIBSODIUM */
|
||||||
|
|
||||||
for (optind = 1; optind < argc; ++optind) {
|
for (optind = 1; optind < argc; ++optind) {
|
||||||
if(strlen(argv[optind]) == 2 && argv[optind][0] == '-') {
|
if(strlen(argv[optind]) == 2 && argv[optind][0] == '-') {
|
||||||
|
|
||||||
@ -988,10 +999,27 @@ int main(int argc, char **argv)
|
|||||||
err = NULL;
|
err = NULL;
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
version = parse_byte_arg(++optind, argc, argv);
|
if(++optind >= argc) {
|
||||||
|
fprintf(stderr, "Error: %s requires an argument\n", argv[optind - 1]);
|
||||||
|
return help(2);
|
||||||
|
}
|
||||||
|
if(strlen(argv[optind]) != 1 || (argv[optind][0] != '0' && argv[optind][0] != '1')) {
|
||||||
|
fprintf(stderr, "Error: unsupported file format version %s, we only support version 0 (AES-256-GCM) and 1 (Chacha20-Poly1305)\n", argv[optind]);
|
||||||
|
return help(2);
|
||||||
|
}
|
||||||
|
if(argv[optind][0] == '0') {
|
||||||
|
version = 0;
|
||||||
|
#ifdef PEGH_LIBSODIUM
|
||||||
|
if(1 != check_version(0, NULL)) {
|
||||||
|
return help(19);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
version = 1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'V':
|
case 'V':
|
||||||
fprintf(stderr, "pegh %s\nformat versions supported: 0\n", PEGH_VERSION);
|
fprintf(stderr, "pegh %s\nformat versions supported: 0 (AES-256-GCM) and 1 (Chacha20-Poly1305)\n", PEGH_VERSION);
|
||||||
return 0;
|
return 0;
|
||||||
case 'h':
|
case 'h':
|
||||||
return help(0);
|
return help(0);
|
||||||
@ -1030,13 +1058,6 @@ int main(int argc, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef PEGH_LIBSODIUM
|
|
||||||
if (sodium_init() == -1) {
|
|
||||||
fprintf(stderr, "Error: libsodium could not be initialized, compile/use openssl version?\n");
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
#endif /* PEGH_LIBSODIUM */
|
|
||||||
|
|
||||||
if(NULL != in_filename) {
|
if(NULL != in_filename) {
|
||||||
in = fopen(in_filename, "rb");
|
in = fopen(in_filename, "rb");
|
||||||
if(!in) {
|
if(!in) {
|
||||||
@ -1089,5 +1110,5 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* to the OS, 0 means success, the above functions 1 means success */
|
/* to the OS, 0 means success, the above functions 1 means success */
|
||||||
return exit_code == 1 ? 0 : 1;
|
return exit_code == 1 ? 0 : (exit_code == 0 ? 1 : exit_code);
|
||||||
}
|
}
|
||||||
|
33
test.sh
33
test.sh
@ -35,28 +35,44 @@ echo "key: $key"
|
|||||||
|
|
||||||
test () {
|
test () {
|
||||||
bin="$1"
|
bin="$1"
|
||||||
bin_decrypt="${2:-$bin}"
|
shift
|
||||||
|
bin_decrypt="${1:-$bin}"
|
||||||
|
shift
|
||||||
|
|
||||||
echo "testing binaries bin: $bin bin_decrypt: $bin_decrypt"
|
echo "testing binaries bin: $bin bin_decrypt: $bin_decrypt"
|
||||||
|
|
||||||
|
set +eu
|
||||||
|
if [ "$2" != "1" ]
|
||||||
|
then
|
||||||
|
# check both binaries through full pipe to see if it fails with an AES error
|
||||||
|
echo a | "$bin" "$@" "$key" | "$bin_decrypt" -d "$key" >/dev/null
|
||||||
|
# 19 is the special return code that means specifically libsodium-only and CPU doesn't support AES
|
||||||
|
[ ${PIPESTATUS[1]} -eq 19 -o ${PIPESTATUS[2]} -eq 19 ] && set -eu && echo "skipping this test because libsodium doesn't support AES on this CPU" && return 0
|
||||||
|
fi
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
|
||||||
|
echo 'encrypting same data with same key should result in different ciphertext'
|
||||||
|
cmp <(echo a | "$bin" "$@" "$key") <(echo a | "$bin" "$@" "$key") && echo "random generation broken? same data and key resulted in same decryption so salt generation is broken and this is insecure" && exit 1 || true
|
||||||
|
|
||||||
echo 'encrypting then decrypting with the same key should succeed'
|
echo 'encrypting then decrypting with the same key should succeed'
|
||||||
"$bin" -e "$key" < "$dummy_file" | "$bin_decrypt" -d "$key" | cmp - "$dummy_file"
|
"$bin" -e "$@" "$key" < "$dummy_file" | "$bin_decrypt" -d "$key" | cmp - "$dummy_file"
|
||||||
|
|
||||||
echo 'test with -s 32 requiring 2gb of ram should succeed'
|
echo 'test with -s 32 requiring 2gb of ram should succeed'
|
||||||
# can send -s 32 or -m 2048 to decrypt command with identical effect
|
# can send -s 32 or -m 2048 to decrypt command with identical effect
|
||||||
#"$bin" -e "$key" -s 32 < "$dummy_file" | "$bin_decrypt" -d "$key" -m 2048 | cmp - "$dummy_file"
|
"$bin" -e "$@" "$key" -s 32 < "$dummy_file" | "$bin_decrypt" -d "$key" -m 2048 | cmp - "$dummy_file"
|
||||||
|
|
||||||
set +e
|
set +e
|
||||||
# these should fail
|
# these should fail
|
||||||
echo 'encrypting with one key and decrypting with another should fail'
|
echo 'encrypting with one key and decrypting with another should fail'
|
||||||
"$bin" -e "$key" -i "$dummy_file" | "$bin_decrypt" -d "$key-wrongkey" | cmp - "$dummy_file" && echo "ERROR: appending -wrongkey to key somehow still worked" && exit 1
|
"$bin" -e "$@" "$key" -i "$dummy_file" | "$bin_decrypt" -d "$key-wrongkey" | cmp - "$dummy_file" && echo "ERROR: appending -wrongkey to key somehow still worked" && exit 1
|
||||||
|
|
||||||
echo 'large values of N without enough memory should fail'
|
echo 'large values of N without enough memory should fail'
|
||||||
"$bin" -e "$key" -N 2000000 -i "$dummy_file" >/dev/null && echo "ERROR: N of 2 million without extra memory worked" && exit 1
|
"$bin" -e "$@" "$key" -N 2000000 -i "$dummy_file" >/dev/null && echo "ERROR: N of 2 million without extra memory worked" && exit 1
|
||||||
"$bin_decrypt" -d "$key" -N 2000000 -i "$dummy_file" >/dev/null && echo "ERROR: N of 2 million without extra memory worked" && exit 1
|
"$bin_decrypt" -d "$key" -N 2000000 -i "$dummy_file" >/dev/null && echo "ERROR: N of 2 million without extra memory worked" && exit 1
|
||||||
|
|
||||||
echo 'bad decryption bytes are never output, file should be 0 bytes'
|
echo 'bad decryption bytes are never output, file should be 0 bytes'
|
||||||
echo 'hopefully this doesnt make it to disk' | "$bin" "$key" | cat - <(echo -n a) | "$bin_decrypt" -d "$key" -o bla.txt && exit 1
|
echo 'hopefully this doesnt make it to disk' | "$bin" "$@" "$key" | cat - <(echo -n a) | "$bin_decrypt" -d "$key" -o bla.txt && exit 1
|
||||||
[ -s bla.txt ] && echo "ERROR: bla.txt should be empty" && exit 1
|
[ -s bla.txt ] && echo "ERROR: bla.txt should be empty" && exit 1
|
||||||
set -e
|
set -e
|
||||||
}
|
}
|
||||||
@ -65,7 +81,12 @@ for bin in $TEST_BINS
|
|||||||
do
|
do
|
||||||
for bin_decrypt in $TEST_BINS
|
for bin_decrypt in $TEST_BINS
|
||||||
do
|
do
|
||||||
|
# test default versions
|
||||||
time test $bin $bin_decrypt
|
time test $bin $bin_decrypt
|
||||||
|
# test aes
|
||||||
|
time test $bin $bin_decrypt -v 0
|
||||||
|
# test chacha
|
||||||
|
time test $bin $bin_decrypt -v 1
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user