diff --git a/.gitignore b/.gitignore index 010439ab..fa81cd5d 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,8 @@ *.o # In-tree binaries /scrypt +/tests/check-params/check-params-normal +/tests/check-params/check-params-reference /tests/libscrypt-kdf/sample-libscrypt-kdf /tests/valgrind/potential-memleaks /tests/verify-strings/test_scrypt diff --git a/Makefile.am b/Makefile.am index bf654d2d..f3212b4a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,7 @@ bin_PROGRAMS= scrypt noinst_PROGRAMS= \ + tests/check-params/check-params-normal \ + tests/check-params/check-params-reference \ tests/valgrind/potential-memleaks \ tests/verify-strings/test_scrypt dist_man_MANS=$(scrypt_man_MANS) @@ -218,6 +220,45 @@ tests_libscrypt_kdf_sample_libscrypt_kdf_CPPFLAGS= \ -I$(srcdir)/libscrypt-kdf/ tests_libscrypt_kdf_sample_libscrypt_kdf_LDADD= libscrypt-kdf.la +# Check scrypt parameter-handling (normal program, including intrinsics). +tests_check_params_check_params_normal_SOURCES= \ + tests/check-params/check-params.c \ + $(crypto_scrypt_files) +tests_check_params_check_params_normal_LDADD= \ + libcperciva_arm_sha256.la \ + libcperciva_cpusupport_detect.la \ + libcperciva_shani.la \ + libscrypt_sse2.la \ + ${LDADD_POSIX} + +# Check scrypt parameter-handling (reference code only, no intrinsics). +# We need a separate library for this because we need to re-compile these +# files without -DCPUSUPPORT_CONFIG_FILE. +noinst_LTLIBRARIES+= libscrypt-reference.la +libscrypt_reference_la_SOURCES= \ + lib/crypto/crypto_scrypt-ref.c \ + libcperciva/alg/sha256.c \ + libcperciva/alg/sha256.h \ + libcperciva/util/insecure_memzero.c \ + libcperciva/util/insecure_memzero.h \ + libcperciva/util/sysendian.h \ + libcperciva/util/warnp.c \ + libcperciva/util/warnp.h +libscrypt_reference_la_CPPFLAGS= \ + -I$(srcdir)/lib-platform/crypto \ + -I$(srcdir)/lib/crypto \ + -I$(srcdir)/libcperciva/alg \ + -I$(srcdir)/libcperciva/cpusupport \ + -I$(srcdir)/libcperciva/util \ + -D_POSIX_C_SOURCE=200809L \ + -D_XOPEN_SOURCE=700 \ + ${CFLAGS_POSIX} +tests_check_params_check_params_reference_SOURCES= \ + tests/check-params/check-params.c +tests_check_params_check_params_reference_LDADD= \ + libscrypt-reference.la \ + ${LDADD_POSIX} + # crypto_aesctr_shared.c is in this list because it can't be included in the # _SOURCES because it should only be included as part of another translation # unit. @@ -230,7 +271,6 @@ EXTRA_DIST= \ STYLE \ get-version.sh \ lib/README \ - lib/crypto/crypto_scrypt-ref.c \ libcperciva/POSIX/README \ libcperciva/POSIX/posix-abstract-declarator.c \ libcperciva/POSIX/posix-cflags.sh \ @@ -268,6 +308,7 @@ EXTRA_DIST= \ tests/07-passphrase-env.sh \ tests/08-passphrase-file.sh \ tests/09-explicit-params.sh \ + tests/10-check-params.sh \ tests/shared_test_functions.sh \ tests/shared_valgrind_functions.sh \ tests/test_scrypt.sh \ diff --git a/tests/10-check-params.sh b/tests/10-check-params.sh new file mode 100644 index 00000000..b4e84f19 --- /dev/null +++ b/tests/10-check-params.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +### Constants +c_valgrind_min=1 + +### Actual command +scenario_cmd() { + # Check parameters with the normal function. + setup_check "check-params-normal" + ${c_valgrind_cmd} "${bindir}/tests/check-params/check-params-normal" + echo $? > "${c_exitfile}" + + # Check parameters with the reference function. + setup_check "check-params-reference" + ${c_valgrind_cmd} "${bindir}/tests/check-params/check-params-reference" + echo $? > "${c_exitfile}" +} diff --git a/tests/check-params/check-params.c b/tests/check-params/check-params.c new file mode 100644 index 00000000..5c6e582c --- /dev/null +++ b/tests/check-params/check-params.c @@ -0,0 +1,94 @@ +#include +#include +#include + +#include "warnp.h" + +#include "crypto_scrypt.h" + +/* How much data should scrypt return? */ +#define OUTPUT_BUFLEN 8 + +static struct testcase { + uint64_t N; + uint32_t r; + uint32_t p; + int desired_errno; /* 0 indicates no failure / errno is unset. */ +} tests[] = { + /* Should fail. */ + { 0, 0, 0, EINVAL }, + { 1, 1, 1, EINVAL }, + { 2, 0, 1, EINVAL }, + { 2, 1, 0, EINVAL }, + { 3, 1, 1, EINVAL }, + { 16384, 1, 2147483648, EFBIG }, + { 16384, 2147483648, 1, EFBIG }, + { 16384, 32768, 32768, EFBIG }, + { 16384, 65536, 65537, EFBIG }, + { (UINT64_C(1) << 62) + 1, 1, 1, EINVAL }, + + /* Should succeed. */ + { 2, 1, 1, 0 }, + { 2, 3, 1, 0 }, + { 2, 1, 3, 0 } +}; + +static int +check_params(uint64_t N, uint32_t r, uint32_t p, int desired_errno) +{ + const char * passwd = "hunter2"; + const char * salt = "DANGER -- this should be a random salt -- DANGER"; + uint8_t output[OUTPUT_BUFLEN]; + int rc; + + /* Call crypto_scrypt. */ + rc = crypto_scrypt((const uint8_t *)passwd, strlen(passwd), + (const uint8_t *)salt, strlen(salt), N, r, p, + output, OUTPUT_BUFLEN); + + if (desired_errno == 0) { + if (rc != 0) { + warn0("Should have succeeded with N=%" PRIu64 + " r=%" PRIu32 " p=%" PRIu32, N, r, p); + goto err0; + } + } else { + if ((rc != -1) || (errno != desired_errno)) { + warn0("Should have errno %i with N=%" PRIu64 + " r=%" PRIu32 " p=%" PRIu32, + desired_errno, N, r, p); + goto err0; + } + } + + /* Success! */ + return (0); + +err0: + /* Failure! */ + return (-1); +} + +int +main(int argc, char * argv[]) +{ + size_t i; + + WARNP_INIT; + + (void)argc; /* UNUSED */ + + /* Run test cases. */ + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + if (check_params(tests[i].N, tests[i].r, tests[i].p, + tests[i].desired_errno)) + goto err0; + } + + /* Success! */ + return (0); + +err0: + /* Failure! */ + return (1); +}