aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--argon2/hash.c82
-rw-r--r--common.h7
-rw-r--r--librecrypt_hash_.c197
-rw-r--r--librecrypt_realise_salts.c2
-rw-r--r--librecrypt_rng_.c28
-rw-r--r--librecrypt_settings_prefix.c56
-rw-r--r--libtest/alloc.c85
-rw-r--r--libtest/random.c5
9 files changed, 381 insertions, 83 deletions
diff --git a/Makefile b/Makefile
index 5f41657..40e6476 100644
--- a/Makefile
+++ b/Makefile
@@ -91,7 +91,7 @@ $(TEST): $(HDR) librecrypt.a libtest/libtest.a libtest/libtest.h
$(CC) -fPIC -c -o $@ $< $(ALL_CFLAGS) $(COV_CFLAGS) $(ALL_CPPFLAGS) $(COV_CPPFLAGS)
.c.to:
- $(CC) -DTEST -c -o $@ $< $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(COV_CPPFLAGS)
+ $(CC) -DTEST -c -o $@ $< $(G) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(COV_CPPFLAGS)
.to.t:
$(CC) -o $@ $< librecrypt.a libtest/libtest.a $(G) $(ALL_LDFLAGS) $(TEST_LDFLAGS) $(COV_LDFLAGS)
diff --git a/argon2/hash.c b/argon2/hash.c
index dbb7c53..6ca665f 100644
--- a/argon2/hash.c
+++ b/argon2/hash.c
@@ -27,17 +27,6 @@ librecrypt__argon2__hash(char *restrict out_buffer, size_t size, const char *phr
/* Not yet used */
(void) reserved;
- /* Gives us memory allocation and threading support;
- * so we don't have to implement any of that ourselves */
- libar2simplified_init_context(&ctx);
- /* Configure automatic erasure of input memory */
- ctx.autoerase_message = 0; /* allows `phrase` to be read-only */
- ctx.autoerase_secret = 0; /* alloes to params.key, which we are not using, but maybe in the future */
- ctx.autoerase_associated_data = 0; /* alloes to params.ad, which we are not using, but maybe in the future */
- ctx.autoerase_salt = 1; /* since we are decoding the salt, we do a memory allocation,
- * and our testing always checks that allocated memory is earse;
- * it doesn't really matter, but it's paranoid, and that's good */
-
/* Parse `settings` */
r = librecrypt_check_settings_(settings, prefix,
"$argon2%^s$%^sm=%^p,t=%^p,p=%^p$%&b$%^h",
@@ -53,6 +42,35 @@ librecrypt__argon2__hash(char *restrict out_buffer, size_t size, const char *phr
return -1;
}
+ /* If not output, will just validate the input and return 0 */
+ if (!size) {
+ /* Argon2 has a maximum passphrase length of 2³²-1 */
+#if SIZE_MAX > UINT32_MAX
+ if (len > (size_t)UINT32_MAX) {
+ errno = EINVAL;
+ return -1;
+ }
+#endif
+ /* This is important because the caller may have skipped calculating
+ * an intermediate hash, and instead pass `NULL` (= assume non-text)
+ * to us as `phrase`, but leave `len` non-zero is it can be validated,
+ * because we are not provided any output buffer so the input passphrase
+ * does not affect us. So we must return so that libar2_hash(3) does
+ * not attempt to read the passphrase from `NULL`. */
+ return 0;
+ }
+
+ /* Gives us memory allocation and threading support;
+ * so we don't have to implement any of that ourselves */
+ libar2simplified_init_context(&ctx);
+ /* Configure automatic erasure of input memory */
+ ctx.autoerase_message = 0; /* allows `phrase` to be read-only */
+ ctx.autoerase_secret = 0; /* alloes to params.key, which we are not using, but maybe in the future */
+ ctx.autoerase_associated_data = 0; /* alloes to params.ad, which we are not using, but maybe in the future */
+ ctx.autoerase_salt = 1; /* since we are decoding the salt, we do a memory allocation,
+ * and our testing always checks that allocated memory is earse;
+ * it doesn't really matter, but it's paranoid, and that's good */
+
/* Decode salt */
if (!salt_encoded) /* this would be if asterisk-notation is used, but it is not */
abort(); /* $covered$ */
@@ -140,13 +158,14 @@ static int discarded_int;
static void
check(const char *phrase, const char *settings, const char *hash, size_t hashlen)
{
- size_t len = strlen(phrase);
+ size_t i, len = strlen(phrase);
size_t prefix = strlen(settings);
char buf[1024], expected[256];
ssize_t r;
assert(hashlen <= sizeof(buf));
assert(hashlen <= sizeof(expected));
+ assert(2u * hashlen <= sizeof(buf));
r = librecrypt_decode(expected, sizeof(expected), hash, strlen(hash),
librecrypt_common_rfc4848s4_decoding_lut_,
@@ -161,12 +180,15 @@ check(const char *phrase, const char *settings, const char *hash, size_t hashlen
EXPECT(librecrypt__argon2__hash(buf, hashlen, phrase, len, settings, prefix, NULL) == 0);
EXPECT(!memcmp(expected, buf, hashlen));
- memset(buf, 0, sizeof(buf));
- EXPECT(librecrypt__argon2__hash(buf, 1u, phrase, len, settings, prefix, NULL) == 0);
- EXPECT(!memcmp(expected, buf, 1u));
-
EXPECT(librecrypt__argon2__hash(buf, 0u, phrase, len, settings, prefix, NULL) == 0);
EXPECT(librecrypt__argon2__hash(NULL, 0u, phrase, len, settings, prefix, NULL) == 0);
+
+ for (i = 1u; i <= hashlen * 2u; i++) {
+ memset(buf, 0, sizeof(buf));
+ EXPECT(librecrypt__argon2__hash(buf, i, phrase, len, settings, prefix, NULL) == 0);
+ EXPECT(!memcmp(expected, buf, i < hashlen ? i : hashlen));
+ }
+
}
@@ -182,14 +204,30 @@ check(const char *phrase, const char *settings, const char *hash, size_t hashlen
} while (0)
+#if SIZE_MAX > UINT32_MAX
+# define CHECK_MEGAPASSPHRASE(ALGO)\
+ libtest_set_alloc_failure_in(3u);\
+ errno = 0;\
+ EXPECT(librecrypt__argon2__hash(NULL, 0u, NULL, (size_t)UINT32_MAX + 1u,\
+ S(ALGO"m=1024,t=10,p=1$ABCDabcdABCDabcd$"), NULL) == -1);\
+ EXPECT(errno == EINVAL)
+#else
+# define CHECK_MEGAPASSPHRASE(ALGO)\
+ ((void)0)
+#endif
+
+
+#define COMMON buf, 1u, NULL, 0u
#define CHECK_BAD(ALGO)\
do {\
errno = 0;\
- EXPECT(librecrypt__argon2__hash(NULL, 0u, NULL, 0u, S(ALGO"m=0,t=999999999999999999,p=0$AAAABBBB$*0"), NULL) == -1);\
+ EXPECT(librecrypt__argon2__hash(COMMON, S(ALGO"m=0,t=999999999999999999,p=0$AAAABBBB$*0"), NULL) == -1);\
EXPECT(errno == EINVAL);\
\
+ CHECK_MEGAPASSPHRASE(ALGO);\
+ \
/* target `if (!salt_encoded)` */\
- EXPECT_ABORT(discarded_int = librecrypt__argon2__hash(NULL, 0u, NULL, 0u, S(ALGO"m=1024,t=10,p=1$*10$"), NULL));\
+ EXPECT_ABORT(discarded_int = librecrypt__argon2__hash(COMMON, S(ALGO"m=1024,t=10,p=1$*10$"), NULL));\
\
if (!libtest_have_custom_malloc())\
break;\
@@ -197,19 +235,19 @@ check(const char *phrase, const char *settings, const char *hash, size_t hashlen
/* target `salt = malloc((size_t)r);` */\
libtest_set_alloc_failure_in(1u);\
errno = 0;\
- EXPECT(librecrypt__argon2__hash(NULL, 0u, NULL, 0u, S(ALGO"m=1024,t=10,p=1$AAAABBBBCCCCDDDD$"), NULL) == -1);\
+ EXPECT(librecrypt__argon2__hash(COMMON, S(ALGO"m=1024,t=10,p=1$AAAABBBBCCCCDDDD$"), NULL) == -1);\
EXPECT(errno == ENOMEM);\
\
/* target `scratch = malloc(scratch_size);` */\
libtest_set_alloc_failure_in(2u);\
errno = 0;\
- EXPECT(librecrypt__argon2__hash(NULL, 0u, NULL, 0u, S(ALGO"m=1024,t=10,p=1$AAAABBBBCCCCDDDD$"), NULL) == -1);\
+ EXPECT(librecrypt__argon2__hash(COMMON, S(ALGO"m=1024,t=10,p=1$BBBBCCCCDDDDAAAA$"), NULL) == -1);\
EXPECT(errno == ENOMEM);\
\
/* target `libar2_hash` */\
libtest_set_alloc_failure_in(3u);\
errno = 0;\
- EXPECT(librecrypt__argon2__hash(NULL, 0u, NULL, 0u, S(ALGO"m=1024,t=10,p=1$AAAABBBBCCCCDDDD$"), NULL) == -1);\
+ EXPECT(librecrypt__argon2__hash(COMMON, S(ALGO"m=1024,t=10,p=1$CCCCDDDDAAAABBBB$"), NULL) == -1);\
EXPECT(errno == ENOMEM);\
\
assert(!libtest_get_alloc_failure_in());\
@@ -219,6 +257,8 @@ check(const char *phrase, const char *settings, const char *hash, size_t hashlen
int
main(void)
{
+ char buf[1024];
+
SET_UP_ALARM();
INIT_TEST_ABORT();
INIT_RESOURCE_TEST();
diff --git a/common.h b/common.h
index 6c44769..1c41d21 100644
--- a/common.h
+++ b/common.h
@@ -525,9 +525,11 @@ int librecrypt_check_settings_(const char *settings, size_t len, const char *fmt
# define EXPECT(EXPR)\
do {\
if (!(EXPR)) {\
+ int test_expect_saved_errno__ = errno;\
libtest_expect_zeroed_on_free(0);\
libtest_stop_tracking();\
- fprintf(stderr, "Failure at %s:%i: %s\n", __FILE__, __LINE__, #EXPR);\
+ fprintf(stderr, "Failure at %s:%i: %s (errno = %i)\n",\
+ __FILE__, __LINE__, #EXPR, test_expect_saved_errno__);\
libtest_dump_stack(NULL, "\t");\
exit(1);\
}\
@@ -538,7 +540,8 @@ int librecrypt_check_settings_(const char *settings, size_t len, const char *fmt
if (!(EXPR)) {\
libtest_expect_zeroed_on_free(0);\
libtest_stop_tracking();\
- fprintf(stderr, "Assertion failure at %s:%i: %s\n", __FILE__, __LINE__, #EXPR);\
+ fprintf(stderr, "Assertion failure at %s:%i: %s\n",\
+ __FILE__, __LINE__, #EXPR);\
libtest_dump_stack(NULL, "\t");\
exit(2);\
}\
diff --git a/librecrypt_hash_.c b/librecrypt_hash_.c
index dc32df1..d9da5e4 100644
--- a/librecrypt_hash_.c
+++ b/librecrypt_hash_.c
@@ -8,7 +8,7 @@ zero_generator(void *out, size_t n, void *user)
{
(void) user;
if (n > (size_t)SSIZE_MAX)
- n = (size_t)SSIZE_MAX;
+ n = (size_t)SSIZE_MAX; /* $covered$ (impossible, but covered otherwise) */
memset(out, 0, n);
return (ssize_t)n;
}
@@ -17,14 +17,28 @@ zero_generator(void *out, size_t n, void *user)
static int
has_asterisk_encoded_salt(const char *settings)
{
- const char *asterisk;
- /* Check whether there is an asterisk */
- asterisk = strchr(settings, '*');
- if (!asterisk)
- return 0;
- /* Check that the first asterisk is not part of the hash result
- * (would specify hash size) rather than be a salt */
- return !!strchr(&asterisk[1u], LIBRECRYPT_HASH_COMPOSITION_DELIMITER);
+ int asterisk = 0;
+ for (; *settings; settings++) {
+ if (*settings == '*') {
+ /* Require digit after '*' to recognise as asterisk-encoding */
+ if ('0' <= settings[1u] && settings[1u] <= '9') {
+ settings++;
+ asterisk = 1;
+ }
+ } else if (*settings == LIBRECRYPT_HASH_COMPOSITION_DELIMITER) {
+ /* If asterisk was found before a '$' in an algorithm
+ * it it was for the salt (or other random parameter) */
+ if (asterisk)
+ return 1;
+ } else if (*settings == LIBRECRYPT_ALGORITHM_LINK_DELIMITER) {
+ /* If asterisk was found between '$' and '>', it was
+ * the hash size specificiation */
+ asterisk = 0;
+ }
+ }
+ /* If asterisk was found after the last '$' or '>', or if
+ * there was no '$', it was the hash size specificiation */
+ return 0;
}
@@ -78,7 +92,7 @@ librecrypt_hash_(char *restrict out_buffer, size_t size, const char *phrase, siz
if (!settings_scratch)
return -1;
if (librecrypt_realise_salts(settings_scratch, (size_t)r_len + 1u, settings, rng, NULL) != r_len)
- abort();
+ abort(); /* $covered$ (impossible) */
settings = settings_scratch;
}
}
@@ -107,15 +121,15 @@ next:
prefix = i + 1u;
if (n && !prefix && settings[i] == '_') {
/* Special case for bsdicrypt */
- prefix = 1u;
+ prefix = 1u; /* $covered$ (TODO we currently don't have an algorithm to trigger this) */
}
if (!algo->flexible_hash_size && prefix != n)
- goto einval;
+ goto einval; /* $covered$ (TODO we currently don't have an algorithm to trigger this) */
/* Get hash size */
if (!algo->flexible_hash_size) {
/* fixed */
- hash_size = algo->hash_size;
+ hash_size = algo->hash_size; /* $covered$ (TODO we currently don't have an algorithm to trigger this) */
} else if (prefix == n) {
/* default */
hash_size = algo->hash_size;
@@ -144,6 +158,7 @@ next:
break;
hash_size = i - prefix;
if (algo->pad && algo->strict_pad) {
+ /* $covered{$ (TODO we currently don't have an algorithm to trigger this) */
for (; i < n; i++)
if (settings[i] != algo->pad)
break;
@@ -151,6 +166,7 @@ next:
goto einval;
if (i - prefix - hash_size >= 4u)
goto einval;
+ /* $covered}$ */
}
if (i != n)
goto einval;
@@ -224,7 +240,7 @@ next:
ascii_len = hash_size % 3u;
if (ascii_len) {
if (algo->pad && algo->strict_pad)
- ascii_len = 4u; /* padding to for bytes */
+ ascii_len = 4u; /* padding to for bytes */ /* $covered$ (TODO we currently don't have an algorithm to trigger this) */
else
ascii_len += 1u; /* 3n+m bytes: 4n+m+1 chars, unless m=0 */
}
@@ -260,7 +276,7 @@ next:
/* For `librecrypt_crypt`: add '>' to the password hash string */
if (action == ASCII_CRYPT) {
ret += 1u;
- if (size) {
+ if (size > 1u) {
*out_buffer++ = LIBRECRYPT_ALGORITHM_LINK_DELIMITER;
size -= 1u;
}
@@ -320,6 +336,20 @@ fail:
int
main(void)
{
+#define SALT "saltSALTsaltSALTsaltSALTsaltSALTsaltSALT"
+#define LARGE "99999999999999999999999999999999999999999999999999999999999999999999999999"
+#define X2(X) X">"X
+#define X3(X) X">"X">"X
+#define X4(X) X">"X">"X">"X
+
+ char buf[1024];
+ char buf1[sizeof(buf)];
+ char buf2[sizeof(buf)];
+ char buf3[sizeof(buf)];
+ char sbuf[160];
+ size_t i, n;
+ ssize_t r, r1, r1b, r1c, r2, r3;
+
SET_UP_ALARM();
INIT_RESOURCE_TEST();
@@ -331,6 +361,143 @@ main(void)
EXPECT(librecrypt_hash_(NULL, 0u, NULL, 0u, "$~no~such~algorithm~$", NULL, ASCII_CRYPT) == -1);
EXPECT(errno == ENOSYS);
+ errno = 0;
+ EXPECT(librecrypt_hash_(NULL, 0u, NULL, 0u, "$~no~such~algorithm~$*100$", NULL, ASCII_CRYPT) == -1);
+ EXPECT(errno == ENOSYS);
+
+#if defined(SUPPORT_ARGON2ID)
+# define ARGON2ID_PREFIX "$argon2id$v=19$m=8,t=1,p=1$"
+# define ARGON2ID_STR ARGON2ID_PREFIX SALT"$*32"
+
+ errno = 0;
+ EXPECT(librecrypt_hash_(buf, sizeof(buf), "hello", 5u, "!"ARGON2ID_STR, NULL, ASCII_CRYPT) == -1);
+ EXPECT(errno == ENOSYS);
+
+ errno = 0;
+ EXPECT(librecrypt_hash_(buf, sizeof(buf), "hello", 5u, ARGON2ID_PREFIX"*"LARGE"$", NULL, ASCII_CRYPT) == -1);
+ EXPECT(errno == ENOMEM);
+
+ r = librecrypt_hash_(NULL, 0u, "hello", 5u, ARGON2ID_PREFIX"*1000$", NULL, ASCII_CRYPT);
+ EXPECT(r > 0);
+ EXPECT(librecrypt_hash_(NULL, 0u, NULL, 0u, ARGON2ID_PREFIX"*1000$", NULL, ASCII_CRYPT) == r);
+ for (i = 0u; i <= sizeof(sbuf); i++)
+ EXPECT(librecrypt_hash_(sbuf, i, NULL, 0u, ARGON2ID_PREFIX"*1000$", NULL, ASCII_CRYPT) == r);
+
+ if (libtest_have_custom_malloc()) {
+ /* target if-statement in zero_generator, using alloc failure as guarding;
+ * however librecrypt_realise_salts should return ERANGE, which
+ * librecrypt_hash_ coverts to ENOMEM */
+ libtest_set_alloc_failure_in(1u);
+ r = (ssize_t)snprintf(buf, sizeof(buf), "%s*%zu$", ARGON2ID_PREFIX, (size_t)SSIZE_MAX + 1u);
+ assert(r > 0 && r < sizeof(buf));
+ errno = 0;
+ EXPECT(librecrypt_hash_(NULL, 0u, NULL, 0u, buf, NULL, ASCII_CRYPT) == -1);
+ EXPECT(errno == ENOMEM);
+ libtest_set_alloc_failure_in(0u);
+
+ /* target settings_scratch */
+ errno = 0;
+ libtest_set_alloc_failure_in(1u);
+ EXPECT(librecrypt_hash_(NULL, 0, "hello", 5u, ARGON2ID_PREFIX"*1000$", NULL, ASCII_CRYPT) == -1);
+ EXPECT(errno == ENOMEM);
+ EXPECT(libtest_get_alloc_failure_in() == 0u);
+
+ /* target phrase_scratches */
+ errno = 0;
+ libtest_set_alloc_failure_in(1u);
+ EXPECT(librecrypt_hash_(buf, sizeof(buf), "hello", 5u, X2(ARGON2ID_STR), NULL, ASCII_CRYPT) == -1);
+ EXPECT(errno == ENOMEM);
+ EXPECT(libtest_get_alloc_failure_in() == 0u);
+
+ /* target *algo->hash */
+ errno = 0;
+ libtest_set_alloc_failure_in(2u);
+ EXPECT(librecrypt_hash_(buf, sizeof(buf), "hello", 5u, X2(ARGON2ID_STR), NULL, ASCII_CRYPT) == -1);
+ EXPECT(errno == ENOMEM);
+ EXPECT(libtest_get_alloc_failure_in() == 0u);
+
+ /* target deallocation of settings_scratch */
+ errno = 0;
+ libtest_set_alloc_failure_in(2u);
+ EXPECT(librecrypt_hash_(buf, 1u, "hello", 5u, ARGON2ID_PREFIX"*1000$>"ARGON2ID_STR, NULL, ASCII_CRYPT) == -1);
+ EXPECT(errno == ENOMEM);
+ EXPECT(libtest_get_alloc_failure_in() == 0u);
+
+ /* target deallocation of phrase_scratches[1] */
+ libtest_set_alloc_failure_in(SIZE_MAX);
+ EXPECT(librecrypt_hash_(buf, 1u, "hello", 5u, X3(ARGON2ID_STR), NULL, ASCII_CRYPT) > 0);
+ n = SIZE_MAX - libtest_get_alloc_failure_in();
+ errno = 0;
+ libtest_set_alloc_failure_in(n);
+ EXPECT(librecrypt_hash_(buf, 1u, "hello", 5u, X3(ARGON2ID_STR), NULL, ASCII_CRYPT) == -1);
+ EXPECT(errno == ENOMEM);
+ EXPECT(libtest_get_alloc_failure_in() == 0u);
+
+ }
+
+ memset(buf1, 99, sizeof(buf1));
+ r1 = librecrypt_hash_(buf1, sizeof(buf1), NULL, 0u, X2(ARGON2ID_STR), NULL, ASCII_CRYPT);
+ EXPECT(r1 > 0);
+ EXPECT(r1 > 2 * (ssize_t)sizeof(ARGON2ID_STR));
+ r1b = librecrypt_hash_(buf, sizeof(buf), NULL, 0u, X3(ARGON2ID_STR), NULL, ASCII_CRYPT);
+ EXPECT(r1b > 0);
+ EXPECT(r1b == r1 + 1 * (ssize_t)sizeof(ARGON2ID_STR));
+ r1c = librecrypt_hash_(buf, sizeof(buf), NULL, 0u, X4(ARGON2ID_STR), NULL, ASCII_CRYPT);
+ EXPECT(r1c > 0);
+ EXPECT(r1c == r1 + 2 * (ssize_t)sizeof(ARGON2ID_STR));
+
+ memset(buf2, 99, sizeof(buf2));
+ EXPECT((r2 = librecrypt_hash_(buf2, sizeof(buf2), NULL, 0u, X2(ARGON2ID_STR), NULL, ASCII_HASH)) > 0);
+ EXPECT(librecrypt_hash_(buf, sizeof(buf), NULL, 0u, X3(ARGON2ID_STR), NULL, ASCII_HASH) == r2);
+ EXPECT(librecrypt_hash_(buf, sizeof(buf), NULL, 0u, X4(ARGON2ID_STR), NULL, ASCII_HASH == r2));
+ EXPECT(r2 < r1);
+
+ memset(buf3, 99, sizeof(buf3));
+ EXPECT((r3 = librecrypt_hash_(buf3, sizeof(buf3), NULL, 0u, X2(ARGON2ID_STR), NULL, BINARY_HASH)) > 0);
+ EXPECT(librecrypt_hash_(buf, sizeof(buf), NULL, 0u, X3(ARGON2ID_STR), NULL, BINARY_HASH) == r3);
+ EXPECT(librecrypt_hash_(buf, sizeof(buf), NULL, 0u, X4(ARGON2ID_STR), NULL, BINARY_HASH) == r3);
+ EXPECT(r3 < r2);
+
+ assert((size_t)r1 < sizeof(buf) - 11u);
+ for (i = (size_t)r1 + 11u; i < SIZE_MAX; i--) {
+ if (i <= (size_t)r1 + 10u) {
+ memset(buf, 88, sizeof(buf));
+ EXPECT(librecrypt_hash_(buf, i, NULL, 0u, X2(ARGON2ID_STR), NULL, ASCII_CRYPT) == r1);
+ if (i) {
+ n = i - 1u < (size_t)r1 ? i - 1u : (size_t)r1;
+ EXPECT(!memcmp(buf, buf1, n));
+ EXPECT(buf[n] == '\0');
+ }
+ }
+ if (i <= (size_t)r2 + 10u) {
+ memset(buf, 88, sizeof(buf));
+ EXPECT(librecrypt_hash_(buf, i, NULL, 0u, X2(ARGON2ID_STR), NULL, ASCII_HASH) == r2);
+ if (i) {
+ n = i - 1u < (size_t)r2 ? i - 1u : (size_t)r2;
+ EXPECT(!memcmp(buf, buf2, n));
+ EXPECT(buf[n] == '\0');
+ }
+ }
+ if (i <= (size_t)r3 + 10u) {
+ memset(buf, 88, sizeof(buf));
+ EXPECT(librecrypt_hash_(buf, i, NULL, 0u, X2(ARGON2ID_STR), NULL, BINARY_HASH) == r3);
+ EXPECT(!memcmp(buf, buf3, i < (size_t)r3 ? i : (size_t)r3));
+ }
+ }
+
+ EXPECT(librecrypt_hash_(NULL, 0u, NULL, 0u, X2(ARGON2ID_STR), NULL, ASCII_CRYPT) == r1);
+ EXPECT(librecrypt_hash_(NULL, 0u, NULL, 0u, X3(ARGON2ID_STR), NULL, ASCII_CRYPT) == r1b);
+ EXPECT(librecrypt_hash_(NULL, 0u, NULL, 0u, X4(ARGON2ID_STR), NULL, ASCII_CRYPT) == r1c);
+
+ EXPECT(librecrypt_hash_(NULL, 0u, NULL, 0u, X2(ARGON2ID_STR), NULL, ASCII_HASH) == r2);
+ EXPECT(librecrypt_hash_(NULL, 0u, NULL, 0u, X3(ARGON2ID_STR), NULL, ASCII_HASH) == r2);
+ EXPECT(librecrypt_hash_(NULL, 0u, NULL, 0u, X4(ARGON2ID_STR), NULL, ASCII_HASH) == r2);
+
+ EXPECT(librecrypt_hash_(NULL, 0u, NULL, 0u, X2(ARGON2ID_STR), NULL, BINARY_HASH) == r3);
+ EXPECT(librecrypt_hash_(NULL, 0u, NULL, 0u, X3(ARGON2ID_STR), NULL, BINARY_HASH) == r3);
+ EXPECT(librecrypt_hash_(NULL, 0u, NULL, 0u, X4(ARGON2ID_STR), NULL, BINARY_HASH) == r3);
+#endif
+
STOP_RESOURCE_TEST();
return 0;
}
diff --git a/librecrypt_realise_salts.c b/librecrypt_realise_salts.c
index 58ba6d3..3fcce88 100644
--- a/librecrypt_realise_salts.c
+++ b/librecrypt_realise_salts.c
@@ -126,7 +126,7 @@ librecrypt_realise_salts(char *restrict out_buffer, size_t size, const char *set
/* Write padding charaters */
right = right < size ? right : size;
for (i = 0u; i < right; i++)
- out_buffer[right] = pad;
+ out_buffer[right] = pad; /* $covered$ (TODO we currently don't have an algorithm to trigger this) */
out_buffer = &out_buffer[right];
size -= right;
}
diff --git a/librecrypt_rng_.c b/librecrypt_rng_.c
index f9a6cc7..e5fe6ec 100644
--- a/librecrypt_rng_.c
+++ b/librecrypt_rng_.c
@@ -75,7 +75,7 @@ librecrypt_rng_(void *out, size_t n, void *user)
fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_CLOFORK);
if (fd < 0)
goto no_urandom; /* this is a goto to make coverage test more comprehensive */
- /* TODO we should make sure this is a character special device */
+ /* TODO we should make sure this is a character special device and validate output */
for (;;) {
r = read(fd, buf, n);
if (r < 0) {
@@ -347,11 +347,10 @@ test_oversized(void)
buf[0] = 99;
libtest_getentropy_jmp_val = 1;
- if (!setjmp(libtest_getentropy_jmp)) {
+ if (!setjmp(libtest_getentropy_jmp))
EXPECT(librecrypt_rng_(buf, beyond_ssize_max, NULL) == 9999);
- } else {
+ else
jumped = 1;
- }
EXPECT(jumped);
EXPECT(buf[0] == 99);
@@ -365,6 +364,7 @@ main(void)
unsigned char buf1[1024u];
unsigned char buf2[sizeof(buf1)];
ssize_t n1, n2;
+ size_t i;
void *user = NULL;
SET_UP_ALARM();
@@ -388,7 +388,25 @@ main(void)
EXPECT(memcmp(buf1, buf2, (size_t)(n1 < n2 ? n1 : n2)));\
} while (0)
- /* TODO Test with output pattern (useful for other tests) */
+ /* Test with output pattern (useful for other tests) */
+#if defined(__linux__)
+ libtest_getrandom_real = 0;
+#endif
+ libtest_getentropy_real = 0;
+ libtest_random_pattern = buf2;
+ libtest_random_pattern_offset = 0u;
+ libtest_random_pattern_length = 32u;
+ for (i = 0u; i < sizeof(buf2); i++)
+ buf2[i] = (unsigned char)(i % libtest_random_pattern_length * 3u + 1u);
+ EXPECT(librecrypt_rng_(buf1, 128u, NULL) == 128);
+ EXPECT(!memcmp(buf1, buf2, 128u));
+ libtest_random_pattern = NULL;
+ libtest_random_pattern_offset = 0u;
+ libtest_random_pattern_length = 0u;
+#if defined(__linux__)
+ libtest_getrandom_real = 1;
+#endif
+ libtest_getentropy_real = 1;
/* Check that output is random */
CHECK2();
diff --git a/librecrypt_settings_prefix.c b/librecrypt_settings_prefix.c
index 0fcf8ae..a2a75f9 100644
--- a/librecrypt_settings_prefix.c
+++ b/librecrypt_settings_prefix.c
@@ -33,8 +33,10 @@ librecrypt_settings_prefix(const char *hash, size_t *hashsize_out)
goto zero;
/* Return 0 as hash size if algorithm cannot be identified or has fixed hash size */
algo = librecrypt_find_first_algorithm_(&hash[last_offset], len - last_offset);
- if (!algo || !algo->flexible_hash_size)
+ if (!algo)
goto zero;
+ if (!algo->flexible_hash_size)
+ goto zero; /* $covered$ (TODO we currently don't have an algorithm to trigger this) */
/* Get the hash size */
if (!librecrypt_check_settings_(&hash[ret], len - ret, "%^b",
@@ -61,14 +63,6 @@ out:
EXPECT(librecrypt_settings_prefix(PREFIX, NULL) == sizeof(PREFIX) - 1u); \
} while (0)
-#if 0
-#define CHECK_ASTERISK(PREFIX, SUFFIX, HASH)\
- do {\
- size_t hashsize = 99999u;\
- EXPECT(librecrypt_settings_prefix(PREFIX SUFFIX #HASH, &hashsize) == sizeof(PREFIX) - 1u);\
- EXPECT(hashsize == HASH##u);\
- } while (0)
-
#define CHECK_ZERO(PREFIX, SUFFIX)\
do {\
size_t hashsize = 99999u;\
@@ -76,13 +70,12 @@ out:
EXPECT(hashsize == 0u);\
} while (0)
-#define CHECK_HASHED(PREFIX, SUFFIX, HASH)\
+#define CHECK_HASH(PREFIX, SUFFIX, HASH)\
do {\
size_t hashsize = 99999u;\
EXPECT(librecrypt_settings_prefix(PREFIX SUFFIX, &hashsize) == sizeof(PREFIX) - 1u);\
EXPECT(hashsize == HASH##u);\
} while (0)
-#endif
int
@@ -115,7 +108,46 @@ main(void)
CHECK_NULL("_", "");
CHECK_NULL("$x$*10>_", "_");
- /* TODO test hash size output (requires algorithms) */
+ /* Check without hash */
+ CHECK_ZERO("a$b$", "");
+ CHECK_ZERO("a$b$>", "");
+ CHECK_ZERO("a$b$x>", "");
+ CHECK_ZERO("a$b$*10>", "");
+
+ /* Check without invalid algorithm */
+ CHECK_ZERO("$~no~such~algorithm~$", "hash");
+
+ /* Check without hash and hashlen */
+#if defined(SUPPORT_ARGON2I)
+ CHECK_HASH("$argon2i$m=8,t=1,p=1$*99$", "*100", 100);
+ CHECK_HASH("x$*99>$argon2i$m=8,t=1,p=1$*99$", "*100", 100);
+ CHECK_HASH("$argon2i$m=8,t=1,p=1$*99$", "NineByteHash", 9);
+ CHECK_HASH("x$*99>$argon2i$m=8,t=1,p=1$*99$", "NineByteHash", 9);
+#endif
+#if defined(SUPPORT_ARGON2ID)
+ CHECK_HASH("$argon2id$m=8,t=1,p=1$*99$", "*100", 100);
+ CHECK_HASH("x$*99>$argon2id$m=8,t=1,p=1$*99$", "*100", 100);
+ CHECK_HASH("$argon2id$m=8,t=1,p=1$*99$", "NineByteHash", 9);
+ CHECK_HASH("x$*99>$argon2id$m=8,t=1,p=1$*99$", "NineByteHash", 9);
+#endif
+#if defined(SUPPORT_ARGON2D)
+ CHECK_HASH("$argon2d$m=8,t=1,p=1$*99$", "*100", 100);
+ CHECK_HASH("x$*99>$argon2d$m=8,t=1,p=1$*99$", "*100", 100);
+ CHECK_HASH("$argon2d$m=8,t=1,p=1$*99$", "NineByteHash", 9);
+ CHECK_HASH("x$*99>$argon2d$m=8,t=1,p=1$*99$", "NineByteHash", 9);
+#endif
+#if defined(SUPPORT_ARGON2DS)
+ CHECK_HASH("$argon2ds$m=8,t=1,p=1$*99$", "*100", 100);
+ CHECK_HASH("x$*99>$argon2ds$m=8,t=1,p=1$*99$", "*100", 100);
+ CHECK_HASH("$argon2ds$m=8,t=1,p=1$*99$", "NineByteHash", 9);
+ CHECK_HASH("x$*99>$argon2ds$m=8,t=1,p=1$*99$", "NineByteHash", 9);
+#endif
+
+ /* Check without invalid hash */
+ IF__argon2i__SUPPORTED(CHECK_ZERO("$argon2i$m=8,t=1,p=1$*99$", "#");)
+ IF__argon2d__SUPPORTED(CHECK_ZERO("$argon2d$m=8,t=1,p=1$*99$", "#");)
+ IF__argon2id__SUPPORTED(CHECK_ZERO("$argon2id$m=8,t=1,p=1$*99$", "#");)
+ IF__argon2ds__SUPPORTED(CHECK_ZERO("$argon2ds$m=8,t=1,p=1$*99$", "#");)
STOP_RESOURCE_TEST();
return 0;
diff --git a/libtest/alloc.c b/libtest/alloc.c
index f89ba94..e154624 100644
--- a/libtest/alloc.c
+++ b/libtest/alloc.c
@@ -717,8 +717,6 @@ check(int use_free)
free(p);
else
free_aligned_sized(p, sizeof(void *), 11u);
-
- /* TODO mmap, munmap, mremap */
}
@@ -728,6 +726,7 @@ check_successfuls(void)
size_t pagesize;
char *s;
wchar_t *w;
+ void *q;
check(1);
check(0);
@@ -817,7 +816,12 @@ check_successfuls(void)
EXPECT(!memcmp(w, (wchar_t[]){11, 22, 0}, 3u * sizeof(wchar_t)));
free(w);
- /* TODO mmap, munmap, mremap */
+ p = mmap(NULL, 1u, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ assert(p != MAP_FAILED);
+ p = mremap(p, 1u, 2u, 0);
+ assert(p != MAP_FAILED);
+ assert(malloc_usable_size(p) >= 6u);
+ asser(!munmap(p, 2u));
}
@@ -826,55 +830,64 @@ check_failures(void)
{
void *q;
- libtest_set_alloc_failure_in(1u);
+ libtest_set_alloc_failure_in(2u);
+ p = malloc(1u);
+ EXPECT(p);
+ free(p);
+ assert(libtest_get_alloc_failure_in() == 1u);
errno = 0;
- EXPECT(!malloc(1u));
+ p = malloc(1u);
+ EXPECT(!p);
EXPECT(errno == ENOMEM);
EXPECT(!libtest_get_alloc_failure_in());
libtest_set_alloc_failure_in(1u);
errno = 0;
- EXPECT(!calloc(1u, 1u));
+ p = calloc(1u, 1u);
+ EXPECT(!p);
EXPECT(errno == ENOMEM);
EXPECT(!libtest_get_alloc_failure_in());
libtest_set_alloc_failure_in(1u);
errno = 0;
- EXPECT(!realloc(NULL, 1u));
+ p = realloc(NULL, 1u);
+ EXPECT(!p);
EXPECT(errno == ENOMEM);
EXPECT(!libtest_get_alloc_failure_in());
- q = realloc(NULL, 1u);
- assert(q);
+ p = realloc(NULL, 1u);
+ assert(p);
libtest_set_alloc_failure_in(1u);
errno = 0;
- EXPECT(!realloc(q, 1u));
+ EXPECT(!realloc(p, 1u));
EXPECT(errno == ENOMEM);
EXPECT(!libtest_get_alloc_failure_in());
- free(q);
+ free(p);
libtest_set_alloc_failure_in(1u);
errno = 0;
EXPECT(!reallocarray(NULL, 1u, 1u));
EXPECT(errno == ENOMEM);
EXPECT(!libtest_get_alloc_failure_in());
- q = reallocarray(NULL, 1u, 1u);
- assert(q);
+ p = reallocarray(NULL, 1u, 1u);
+ assert(p);
libtest_set_alloc_failure_in(1u);
errno = 0;
- EXPECT(!reallocarray(q, 1u, 1u));
+ EXPECT(!reallocarray(p, 1u, 1u));
EXPECT(errno == ENOMEM);
EXPECT(!libtest_get_alloc_failure_in());
- free(q);
+ free(p);
libtest_set_alloc_failure_in(1u);
errno = 0;
- EXPECT(!memalign(1u, 1u));
+ p = memalign(1u, 1u);
+ EXPECT(!p);
EXPECT(errno == ENOMEM);
EXPECT(!libtest_get_alloc_failure_in());
libtest_set_alloc_failure_in(1u);
errno = 0;
- EXPECT(!aligned_alloc(1u, 1u));
+ p = aligned_alloc(1u, 1u);
+ EXPECT(!p);
EXPECT(errno == ENOMEM);
EXPECT(!libtest_get_alloc_failure_in());
@@ -885,47 +898,69 @@ check_failures(void)
libtest_set_alloc_failure_in(1u);
errno = 0;
- EXPECT(!valloc(1u));
+ p = valloc(1u);
+ EXPECT(!p);
EXPECT(errno == ENOMEM);
EXPECT(!libtest_get_alloc_failure_in());
libtest_set_alloc_failure_in(1u);
errno = 0;
- EXPECT(!pvalloc(1u));
+ p = pvalloc(1u);
+ EXPECT(!p);
EXPECT(errno == ENOMEM);
EXPECT(!libtest_get_alloc_failure_in());
libtest_set_alloc_failure_in(1u);
errno = 0;
- EXPECT(!strdup("x"));
+ p = strdup("x");
+ EXPECT(!p);
EXPECT(errno == ENOMEM);
EXPECT(!libtest_get_alloc_failure_in());
libtest_set_alloc_failure_in(1u);
errno = 0;
- EXPECT(!strndup("x", 1u));
+ p = strndup("x", 1u);
+ EXPECT(!p);
EXPECT(errno == ENOMEM);
EXPECT(!libtest_get_alloc_failure_in());
libtest_set_alloc_failure_in(1u);
errno = 0;
- EXPECT(!wcsdup((wchar_t[]){1, 0}));
+ p = wcsdup((wchar_t[]){1, 0});
+ EXPECT(!p);
EXPECT(errno == ENOMEM);
EXPECT(!libtest_get_alloc_failure_in());
libtest_set_alloc_failure_in(1u);
errno = 0;
- EXPECT(!wcsndup((wchar_t[]){1, 0}, 1u));
+ p = wcsndup((wchar_t[]){1, 0}, 1u);
+ EXPECT(!p);
EXPECT(errno == ENOMEM);
EXPECT(!libtest_get_alloc_failure_in());
libtest_set_alloc_failure_in(1u);
errno = 0;
- EXPECT(!memdup("x", 1u));
+ p = memdup("x", 1u);
+ EXPECT(!p);
EXPECT(errno == ENOMEM);
EXPECT(!libtest_get_alloc_failure_in());
- /* TODO mmap, munmap, mremap */
+ libtest_set_alloc_failure_in(1u);
+ errno = 0;
+ p = mmap(NULL, 1u, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ EXPECT(p == MAP_FAILED);
+ EXPECT(errno == ENOMEM);
+ EXPECT(!libtest_get_alloc_failure_in());
+
+ p = mmap(NULL, 1u, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ assert(p != MAP_FAILED);
+ q = p;
+ libtest_set_alloc_failure_in(1u);
+ errno = 0;
+ p = mremap(p, 1u, 2u, 0);
+ EXPECT(errno == ENOMEM);
+ EXPECT(!libtest_get_alloc_failure_in());
+ munmap(q, 1u);
}
diff --git a/libtest/random.c b/libtest/random.c
index 77e9218..2eb22e6 100644
--- a/libtest/random.c
+++ b/libtest/random.c
@@ -12,10 +12,13 @@ genpattern(void *buf, size_t size)
{
unsigned char *out = buf;
size_t n;
+ ssize_t ret;
if (size > (size_t)SSIZE_MAX)
size = (size_t)SSIZE_MAX;
+ ret = (ssize_t)size;
+
if (libtest_random_pattern_length) {
while (size) {
if (libtest_random_pattern_offset == libtest_random_pattern_length)
@@ -33,7 +36,7 @@ genpattern(void *buf, size_t size)
out[0] = (unsigned char)rand();
}
- return (ssize_t)size;
+ return ret;
}