From aff22d5d2f207a6b57f7f1a2b29a9b69f82e2fd7 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Thu, 21 May 2026 21:32:38 +0200 Subject: Add test and fix a bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- librecrypt_hash.c | 96 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 69 insertions(+), 27 deletions(-) (limited to 'librecrypt_hash.c') diff --git a/librecrypt_hash.c b/librecrypt_hash.c index 06bfe65..35aa8e4 100644 --- a/librecrypt_hash.c +++ b/librecrypt_hash.c @@ -14,8 +14,17 @@ librecrypt_hash(char *restrict out_buffer, size_t size, const char *phrase, #else +#define SP4 " " +#define SP20 SP4 SP4 SP4 SP4 SP4 +#define SP80 SP20 SP20 SP20 SP20 +#define SP84 SP80 SP4 + +#define GET_ARGON2_SCRATCH_SIZE(HASHLEN) ((HASHLEN) > 64u ? ((HASHLEN) + 63u) & ~31u : (HASHLEN)) + + static void -check(const char *phrase, const char *settings, const char *chain, const char *hash, size_t scratchsize) +check(const char *phrase, const char *settings, const char *chain, + const char *hash, size_t scratchsize, LIBRECRYPT_CONTEXT *ctx) { size_t hashlen = strlen(hash); size_t len = strlen(phrase); @@ -28,47 +37,47 @@ check(const char *phrase, const char *settings, const char *chain, const char *h assert(hashlen < sizeof(expected)); CANARY_FILL(buf); - EXPECT(librecrypt_hash(buf, sizeof(buf), phrase, len, settings, NULL) == (ssize_t)hashlen); + EXPECT(librecrypt_hash(buf, sizeof(buf), phrase, len, settings, ctx) == (ssize_t)hashlen); EXPECT(!memcmp(hash, buf, hashlen + 1u)); CANARY_X_CHECK(buf, hashlen + 1u, scratchsize); CANARY_FILL(buf); - EXPECT(librecrypt_hash(buf, hashlen + 1u, phrase, len, settings, NULL) == (ssize_t)hashlen); + EXPECT(librecrypt_hash(buf, hashlen + 1u, phrase, len, settings, ctx) == (ssize_t)hashlen); EXPECT(!memcmp(hash, buf, hashlen + 1u)); CANARY_X_CHECK(buf, hashlen + 1u, scratchsize); CANARY_FILL(buf); - EXPECT(librecrypt_hash(buf, hashlen, phrase, len, settings, NULL) == (ssize_t)hashlen); + EXPECT(librecrypt_hash(buf, hashlen, phrase, len, settings, ctx) == (ssize_t)hashlen); EXPECT(!memcmp(hash, buf, hashlen - 1u)); EXPECT(!buf[hashlen - 1]); CANARY_X_CHECK(buf, hashlen, scratchsize); CANARY_FILL(buf); - EXPECT(librecrypt_hash(buf, 2u, phrase, len, settings, NULL) == (ssize_t)hashlen); + EXPECT(librecrypt_hash(buf, 2u, phrase, len, settings, ctx) == (ssize_t)hashlen); EXPECT(!memcmp(hash, buf, 1u)); EXPECT(!buf[1u]); CANARY_X_CHECK(buf, 2u, 2u); CANARY_FILL(buf); - EXPECT(librecrypt_hash(buf, 1u, phrase, len, settings, NULL) == (ssize_t)hashlen); + EXPECT(librecrypt_hash(buf, 1u, phrase, len, settings, ctx) == (ssize_t)hashlen); EXPECT(!buf[0u]); CANARY_X_CHECK(buf, 1u, 1u); CANARY_FILL(buf); - EXPECT(librecrypt_hash(buf, 0u, phrase, len, settings, NULL) == (ssize_t)hashlen); + EXPECT(librecrypt_hash(buf, 0u, phrase, len, settings, ctx) == (ssize_t)hashlen); CANARY_X_CHECK(buf, 0u, 0u); - EXPECT(librecrypt_hash(NULL, 0u, phrase, len, settings, NULL) == (ssize_t)hashlen); + EXPECT(librecrypt_hash(NULL, 0u, phrase, len, settings, ctx) == (ssize_t)hashlen); - lut = librecrypt_get_encoding(settings, strlen(settings), &pad, &strict_pad, 1, NULL); + lut = librecrypt_get_encoding(settings, strlen(settings), &pad, &strict_pad, 1, ctx); assert(lut); r = librecrypt_decode(expected, sizeof(expected), hash, strlen(hash), lut, pad, strict_pad); assert(r > 0 && (size_t)r <= sizeof(expected)); CANARY_FILL(buf); CANARY_FILL(buf2); - EXPECT(librecrypt_hash(buf, sizeof(buf), expected, (size_t)r, settings, NULL) == (ssize_t)hashlen); + EXPECT(librecrypt_hash(buf, sizeof(buf), expected, (size_t)r, settings, ctx) == (ssize_t)hashlen); errno = 0; - EXPECT(librecrypt_hash(buf2, sizeof(buf2), phrase, len, chain, NULL) == (ssize_t)hashlen); + EXPECT(librecrypt_hash(buf2, sizeof(buf2), phrase, len, chain, ctx) == (ssize_t)hashlen); EXPECT(!memcmp(buf, buf2, hashlen + 1u)); CANARY_X_CHECK(buf, hashlen + 2, scratchsize); CANARY_X_CHECK(buf2, hashlen + 2, scratchsize); @@ -78,41 +87,41 @@ check(const char *phrase, const char *settings, const char *chain, const char *h #define CHECK(PHRASE, CONF, HASHLEN, IS_DEFAULT_HASHLEN, HASH)\ do {\ size_t scratchsize = GET_SCRATCH_SIZE(HASHLEN);\ - check(PHRASE, CONF HASH, CONF "*" #HASHLEN ">" CONF HASH, HASH, scratchsize);\ - check(PHRASE, CONF "*" #HASHLEN, CONF "*" #HASHLEN ">" CONF "*" #HASHLEN, HASH, scratchsize);\ + check(PHRASE, CONF HASH, CONF "*" #HASHLEN ">" CONF HASH, HASH, scratchsize, ctx);\ + check(PHRASE, CONF "*" #HASHLEN, CONF "*" #HASHLEN ">" CONF "*" #HASHLEN, HASH, scratchsize, ctx);\ if (IS_DEFAULT_HASHLEN)\ - check(PHRASE, CONF, CONF ">" CONF, HASH, scratchsize);\ + check(PHRASE, CONF, CONF ">" CONF, HASH, scratchsize, ctx);\ } while (0) #define CHECK_BAD(ALGO)\ do {\ errno = 0;\ - EXPECT(librecrypt_hash(NULL, 0u, NULL, 0u, ALGO"m=0,t=999999999999999999,p=0$AAAABBBB$*0", NULL) == -1);\ + EXPECT(librecrypt_hash(NULL, 0u, NULL, 0u, ALGO"m=0,t=999999999999999999,p=0$AAAABBBB$*0", ctx) == -1);\ EXPECT(errno == EINVAL);\ errno = 0;\ - EXPECT(librecrypt_hash(NULL, 0u, NULL, 0u, ALGO"m=4096,t=10,p=1$*32$", NULL) == -1);\ + EXPECT(librecrypt_hash(NULL, 0u, NULL, 0u, ALGO"m=4096,t=10,p=1$*32$", ctx) == -1);\ EXPECT(errno == EINVAL);\ errno = 0;\ - EXPECT(librecrypt_hash(NULL, 0u, NULL, 0u, ALGO"m=4096,t=10,p=1$AAAABBBBCCCCDDDD$*0", NULL) == -1);\ + EXPECT(librecrypt_hash(NULL, 0u, NULL, 0u, ALGO"m=4096,t=10,p=1$AAAABBBBCCCCDDDD$*0", ctx) == -1);\ EXPECT(errno == EINVAL);\ errno = 0;\ - EXPECT(librecrypt_hash(NULL, 0u, NULL, 0u, ALGO"m=4096,t=10,p=1$AAAABBBBCCCCDDDD$*x", NULL) == -1);\ + EXPECT(librecrypt_hash(NULL, 0u, NULL, 0u, ALGO"m=4096,t=10,p=1$AAAABBBBCCCCDDDD$*x", ctx) == -1);\ EXPECT(errno == EINVAL);\ errno = 0;\ - EXPECT(librecrypt_hash(NULL, 0u, NULL, 0u, ALGO"m=4096,t=10,p=1$AAAABBBBCCCCDDDD$*2x", NULL) == -1);\ + EXPECT(librecrypt_hash(NULL, 0u, NULL, 0u, ALGO"m=4096,t=10,p=1$AAAABBBBCCCCDDDD$*2x", ctx) == -1);\ EXPECT(errno == EINVAL);\ errno = 0;\ - EXPECT(librecrypt_hash(NULL, 0u, NULL, 0u, ALGO"m=4096,t=10,p=1$AAAABBBBCCCCDDDD$*9999999999999999999999999999999", NULL) == -1);\ + EXPECT(librecrypt_hash(NULL, 0u, NULL, 0u, ALGO"m=4096,t=10,p=1$AAAABBBBCCCCDDDD$*9999999999999999999999999999999", ctx) == -1);\ EXPECT(errno == EINVAL);\ errno = 0;\ - EXPECT(librecrypt_hash(NULL, 0u, NULL, 0u, ALGO"m=4096,t=10,p=1$AAAABBBBCCCCDDDD$AAAABBBBCCCCDDDDEEEEFFFF>", NULL) == -1);\ + EXPECT(librecrypt_hash(NULL, 0u, NULL, 0u, ALGO"m=4096,t=10,p=1$AAAABBBBCCCCDDDD$AAAABBBBCCCCDDDDEEEEFFFF>", ctx) == -1);\ EXPECT(errno == EINVAL);\ errno = 0;\ - EXPECT(librecrypt_hash(NULL, 0u, NULL, 0u, ALGO"m=4096,t=10,p=1$AAAABBBBCCCCDDDD$AAAABBBBCCCCDDDDEEEEFFFFG", NULL) == -1);\ + EXPECT(librecrypt_hash(NULL, 0u, NULL, 0u, ALGO"m=4096,t=10,p=1$AAAABBBBCCCCDDDD$AAAABBBBCCCCDDDDEEEEFFFFG", ctx) == -1);\ EXPECT(errno == EINVAL);\ errno = 0;\ - EXPECT(librecrypt_hash(NULL, 0u, NULL, 0u, ALGO"m=4096,t=10,p=1$AAAABBBBCCCCDDDD$AAAABBBBCCCCDDDDEEEEFFFF~", NULL) == -1);\ + EXPECT(librecrypt_hash(NULL, 0u, NULL, 0u, ALGO"m=4096,t=10,p=1$AAAABBBBCCCCDDDD$AAAABBBBCCCCDDDDEEEEFFFF~", ctx) == -1);\ EXPECT(errno == EINVAL);\ } while (0) @@ -120,18 +129,19 @@ check(const char *phrase, const char *settings, const char *chain, const char *h int main(void) { - char conf[256]; + char conf[256], nuls[256]; + LIBRECRYPT_CONTEXT *ctx = NULL; int r; SET_UP_ALARM(); INIT_RESOURCE_TEST(); -#define GET_SCRATCH_SIZE(HASHLEN) ((HASHLEN) > 64u ? ((HASHLEN) + 63u) & ~31u : (HASHLEN)) +#define GET_SCRATCH_SIZE(HASHLEN) GET_ARGON2_SCRATCH_SIZE(HASHLEN) #if defined(SUPPORT_ARGON2I) r = snprintf(conf, sizeof(conf), "$argon2i$m=256,t=8,p=1$AAAABBBBCCCC$*%zu", SIZE_MAX / 4u * 3u + 3u); assert(r > 0 && (size_t)r < sizeof(conf)); errno = 0; - EXPECT(librecrypt_hash(NULL, 0u, NULL, 0u, conf, NULL) == -1); + EXPECT(librecrypt_hash(NULL, 0u, NULL, 0u, conf, ctx) == -1); # if SIZE_MAX > UINT32_MAX EXPECT(errno == EINVAL); # else @@ -140,7 +150,7 @@ main(void) char buf[1024]; libtest_pretend_allocation_successful = 1; errno = 0; - EXPECT(librecrypt_hash(buf, sizeof(buf), NULL, 0u, conf, NULL) == -1); + EXPECT(librecrypt_hash(buf, sizeof(buf), NULL, 0u, conf, ctx) == -1); libtest_pretend_allocation_successful = 0; EXPECT(errno == EOVERFLOW); } @@ -166,6 +176,38 @@ main(void) #endif #undef GET_SCRATCH_SIZE + ctx = librecrypt_create_context(); + assert(ctx != NULL); + memset(nuls, 0, sizeof(nuls)); + +#if defined(SUPPORT_ARGON2I) +# define GET_SCRATCH_SIZE(HASHLEN) GET_ARGON2_SCRATCH_SIZE(HASHLEN) + assert(sizeof(nuls) >= 4u); + assert(librecrypt_set_pepper(ctx, LIBRECRYPT_ARGON2I_V1_3, nuls, 4u) == 0); + CHECK(" ", "$argon2i$v=19$m=8,t=1,p=1$ICAgICAgICA$", 8, 0, "Mhl4o3AkJuA"); + CHECK(SP84, "$argon2i$v=19$m=8,t=1,p=1$ICAgICAgICA$", 8, 0, "+hlEcRn+F3s"); + CHECK(SP80, "$argon2i$v=19$m=8,t=1,p=1$ICAgICAgICA$", 8, 0, "z2d6ce8UqS0"); + + assert(sizeof(nuls) >= 140u); + assert(librecrypt_set_pepper(ctx, LIBRECRYPT_ARGON2I_V1_3, nuls, 140u) == 0); + CHECK(SP80, "$argon2i$v=19$m=8,t=1,p=1$ICAgICAgICA$", 8, 0, "15FAGe1KIX8"); + + assert(sizeof(nuls) >= 160u); + assert(librecrypt_set_pepper(ctx, LIBRECRYPT_ARGON2I_V1_3, nuls, 160u) == 0); + CHECK(SP80, "$argon2i$v=19$m=8,t=1,p=1$ICAgICAgICA$", 8, 0, "oH3H5atuca8"); + + assert(sizeof(nuls) >= 128u); + assert(librecrypt_set_pepper(ctx, LIBRECRYPT_ARGON2I_V1_3, nuls, 128u) == 0); + CHECK(SP80, "$argon2i$v=19$m=8,t=1,p=1$ICAgICAgICA$", 8, 0, "TsimqI1YC08"); + + assert(sizeof(nuls) >= 256u); + assert(librecrypt_set_pepper(ctx, LIBRECRYPT_ARGON2I_V1_3, nuls, 256u) == 0); + CHECK(SP80, "$argon2i$v=19$m=8,t=1,p=1$ICAgICAgICA$", 8, 0, "mzPlVOVjVos"); +# undef GET_SCRATCH_SIZE +#endif + + librecrypt_free_context(ctx); + STOP_RESOURCE_TEST(); return 0; } -- cgit v1.3.1