From 5937284e86a6994a2621e844d940d8b2692ed428 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Tue, 19 May 2026 21:07:46 +0200 Subject: Test and fix librecrypt_verify MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- librecrypt_verify.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 7 deletions(-) (limited to 'librecrypt_verify.c') diff --git a/librecrypt_verify.c b/librecrypt_verify.c index 18d8cd8..990f37e 100644 --- a/librecrypt_verify.c +++ b/librecrypt_verify.c @@ -12,40 +12,49 @@ librecrypt_verify(const char *phrase, size_t len, const char *settings, void *re ssize_t n; int ret, err; + /* Measure base64 hash size */ n = librecrypt_hash_(NULL, 0u, phrase, len, settings, reserved, ASCII_HASH); if (n < 0) { if (errno == EOVERFLOW) - errno = ENOMEM; + errno = ENOMEM; /* $covered$ (on 32-bit) */ return -1; } - off = librecrypt_settings_prefix(hash, NULL, reserved); - if (hash[off] == '*') { - if ('0'> hash[off + 1u] || hash[off + 1u] > '9') { + /* Get position of hash in `settings` */ + off = librecrypt_settings_prefix(settings, NULL, reserved); + if (settings[off] == '*') { + if ('0' <= settings[off + 1u] && settings[off + 1u] <= '9') { errno = EINVAL; return -1; } + } else if (!settings[off]) { + errno = EINVAL; + return -1; } + /* Allocate hash output buffer for comparsion */ size = (size_t)n + 128u; /* a little extra so the hasher don't need to allocate output scratch */ hash = malloc(size); if (!hash) return -1; + /* Calculate password hash and encode to base64 */ n = librecrypt_hash_(hash, size, phrase, len, settings, reserved, ASCII_HASH); if (n < 0) { err = errno; librecrypt_wipe(hash, size); free(hash); if (err == EOVERFLOW) - err = ENOMEM; + err = ENOMEM; /* $covered$ (impossible) */ errno = err; return -1; } if ((size_t)n > size) - abort(); + abort(); /* $covered$ (impossible) */ + /* Compare hash */ ret = librecrypt_equal(hash, &settings[off]); + librecrypt_wipe(hash, size); free(hash); return ret; @@ -58,10 +67,59 @@ librecrypt_verify(const char *phrase, size_t len, const char *settings, void *re int main(void) { + char conf[256]; + int r; + SET_UP_ALARM(); INIT_RESOURCE_TEST(); - /* TODO test */ + errno = 0; + EXPECT(librecrypt_verify(NULL, 0u, "$~no~such~algorithm~$", NULL) == -1); + EXPECT(errno == ENOSYS); + +#if defined(SUPPORT_ARGON2ID) + EXPECT(librecrypt_verify("password", 8u, "$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4", NULL) == 1); + EXPECT(librecrypt_verify("password", 8u, "$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/", NULL) == 0); + EXPECT(librecrypt_verify("password", 8u, "$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4x", NULL) == 0); + EXPECT(librecrypt_verify("password", 8u, "$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/a", NULL) == 0); + EXPECT(librecrypt_verify("password", 8u, "$argon2id$v=19$m=256,t=2,p=1$a29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/a", NULL) == 0); + EXPECT(librecrypt_verify("password", 8u, "$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$af65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4", NULL) == 0); + EXPECT(librecrypt_verify("password", 8u, "$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMRauIPnA4rEsF5h7TKyQwu9U1bMCHGi/4", NULL) == 0); + + errno = 0; + EXPECT(librecrypt_verify("password", 8u, "$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$", NULL) == -1); + EXPECT(errno == EINVAL); + errno = 0; + EXPECT(librecrypt_verify("password", 8u, "$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$*64", NULL) == -1); + EXPECT(errno == EINVAL); + errno = 0; + EXPECT(librecrypt_verify("password", 8u, "$argon2id$v=19$m=256,t=2,p=1$*16$nf65EOgLrQMRauIPnA4rEsF5h7TKyQwu9U1bMCHGi/4", NULL) == -1); + EXPECT(errno == EINVAL); + + if (libtest_have_custom_malloc()) { + libtest_set_alloc_failure_in(1u); + errno = 0; + EXPECT(librecrypt_verify("password", 8u, "$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4", NULL) == -1); + assert(errno == ENOMEM); + assert(libtest_get_alloc_failure_in() == 0u); + + libtest_set_alloc_failure_in(2u); + errno = 0; + EXPECT(librecrypt_verify("password", 8u, "$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4", NULL) == -1); + assert(errno == ENOMEM); + assert(libtest_get_alloc_failure_in() == 0u); + } + + r = snprintf(conf, sizeof(conf), "$argon2id$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_verify(NULL, 0u, conf, NULL) == -1); +# if SIZE_MAX > UINT32_MAX + EXPECT(errno == EINVAL); +# else + EXPECT(errno == EOVERFLOW); +# endif +#endif STOP_RESOURCE_TEST(); return 0; -- cgit v1.2.3-70-g09d2