diff options
| author | Mattias Andrée <m@maandree.se> | 2026-05-19 21:07:46 +0200 |
|---|---|---|
| committer | Mattias Andrée <m@maandree.se> | 2026-05-19 21:07:46 +0200 |
| commit | 5937284e86a6994a2621e844d940d8b2692ed428 (patch) | |
| tree | d4afd1b383523dc8db7ae6915e1a33b30d7e2bde | |
| parent | m (diff) | |
| download | librecrypt-master.tar.gz librecrypt-master.tar.bz2 librecrypt-master.tar.xz | |
Signed-off-by: Mattias Andrée <m@maandree.se>
| -rw-r--r-- | librecrypt.h | 3 | ||||
| -rw-r--r-- | librecrypt_verify.3 | 4 | ||||
| -rw-r--r-- | librecrypt_verify.c | 72 |
3 files changed, 71 insertions, 8 deletions
diff --git a/librecrypt.h b/librecrypt.h index 628849e..08efde6 100644 --- a/librecrypt.h +++ b/librecrypt.h @@ -809,7 +809,8 @@ ssize_t librecrypt_crypt(char *restrict out_buffer, size_t size, const char *phr * chained hash algorithm cannot be input the next algorithm * in the chain (either because of format or length issues)) * @throws EINVAL `settings` uses asterisk-encoding to specify random salts - * @thorws EINVAL `settings` uses asterisk-encoding in place of a hash result + * @throws EINVAL `settings` uses asterisk-encoding in place of a hash result + * @throws EINVAL `settings` contains no hash result * @throws ERANGE `len` is too large or too small for the the selected * initial algorithm in the algorithm chain * @throws ENOMEM Failed to allocate internal scratch memory diff --git a/librecrypt_verify.3 b/librecrypt_verify.3 index 8c6e421..1ee86d2 100644 --- a/librecrypt_verify.3 +++ b/librecrypt_verify.3 @@ -83,6 +83,10 @@ uses asterisk-encoding to specify random salts. .I settings uses asterisk-encoding in place of a hash result. .TP +.B EINVAL +.I settings +contains no hash result. +.TP .B ERANGE .I len is too large or too small for the selected 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; |
