diff options
| author | Mattias Andrée <m@maandree.se> | 2026-05-14 22:20:02 +0200 |
|---|---|---|
| committer | Mattias Andrée <m@maandree.se> | 2026-05-14 22:20:02 +0200 |
| commit | f07a9f80fb6f3099d75534c1e64f448d4b397931 (patch) | |
| tree | 30ebf4afafb0e66226fa7f642db083341c8c96e4 | |
| parent | librecrypt.h: add @since (diff) | |
| download | librecrypt-f07a9f80fb6f3099d75534c1e64f448d4b397931.tar.gz librecrypt-f07a9f80fb6f3099d75534c1e64f448d4b397931.tar.bz2 librecrypt-f07a9f80fb6f3099d75534c1e64f448d4b397931.tar.xz | |
Fix minor errors in the test and check that we are not writing out of bounds
Signed-off-by: Mattias Andrée <m@maandree.se>
| -rw-r--r-- | argon2/hash.c | 22 | ||||
| -rw-r--r-- | argon2/make_settings.c | 35 | ||||
| -rw-r--r-- | common.h | 26 | ||||
| -rw-r--r-- | librecrypt_add_algorithm.c | 33 | ||||
| -rw-r--r-- | librecrypt_crypt.c | 46 | ||||
| -rw-r--r-- | librecrypt_decode.c | 30 | ||||
| -rw-r--r-- | librecrypt_decompose_chain.c | 27 | ||||
| -rw-r--r-- | librecrypt_decompose_chain1.c | 2 | ||||
| -rw-r--r-- | librecrypt_encode.c | 10 | ||||
| -rw-r--r-- | librecrypt_fill_with_random_.c | 20 | ||||
| -rw-r--r-- | librecrypt_hash.c | 34 | ||||
| -rw-r--r-- | librecrypt_hash_.c | 29 | ||||
| -rw-r--r-- | librecrypt_hash_binary.c | 26 | ||||
| -rw-r--r-- | librecrypt_make_settings.c | 20 | ||||
| -rw-r--r-- | librecrypt_realise_salts.c | 8 | ||||
| -rw-r--r-- | librecrypt_rng_.c | 6 |
16 files changed, 295 insertions, 79 deletions
diff --git a/argon2/hash.c b/argon2/hash.c index fd4609a..9223e55 100644 --- a/argon2/hash.c +++ b/argon2/hash.c @@ -160,7 +160,7 @@ static int discarded_int; static void -check(const char *phrase, const char *settings, const char *hash, size_t hashlen) +check(const char *phrase, const char *settings, const char *hash, size_t hashlen, size_t scratchsize) { size_t i, len = strlen(phrase); size_t prefix = strlen(settings); @@ -176,21 +176,26 @@ check(const char *phrase, const char *settings, const char *hash, size_t hashlen argon2__PAD, argon2__STRICT_PAD); assert(r > 0 && (size_t)r == hashlen); - memset(buf, 0, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt__argon2__hash(buf, sizeof(buf), phrase, len, settings, prefix, NULL) == 0); EXPECT(!memcmp(expected, buf, hashlen)); + CANARY_X_CHECK(buf, hashlen, scratchsize); - memset(buf, 0, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt__argon2__hash(buf, hashlen, phrase, len, settings, prefix, NULL) == 0); EXPECT(!memcmp(expected, buf, hashlen)); + CANARY_X_CHECK(buf, hashlen, scratchsize); + CANARY_FILL(buf); EXPECT(librecrypt__argon2__hash(buf, 0u, phrase, len, settings, prefix, NULL) == 0); + CANARY_X_CHECK(buf, 0u, 0u); EXPECT(librecrypt__argon2__hash(NULL, 0u, phrase, len, settings, prefix, NULL) == 0); for (i = 1u; i <= hashlen * 2u; i++) { - memset(buf, 0, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt__argon2__hash(buf, i, phrase, len, settings, prefix, NULL) == 0); EXPECT(!memcmp(expected, buf, MIN(i, hashlen))); + CANARY_X_CHECK(buf, MIN(i, hashlen), scratchsize); } } @@ -201,10 +206,11 @@ check(const char *phrase, const char *settings, const char *hash, size_t hashlen #define CHECK(PHRASE, CONF, HASHLEN, HASH)\ do {\ - check(PHRASE, CONF HASH, HASH, (size_t)HASHLEN);\ + size_t scratchsize = GET_SCRATCH_SIZE(HASHLEN);\ + check(PHRASE, CONF HASH, HASH, (size_t)HASHLEN, scratchsize);\ if ((size_t)HASHLEN == argon2__HASH_SIZE)\ - check(PHRASE, CONF, HASH, (size_t)HASHLEN);\ - check(PHRASE, CONF "*" #HASHLEN, HASH, (size_t)HASHLEN);\ + check(PHRASE, CONF, HASH, (size_t)HASHLEN, scratchsize);\ + check(PHRASE, CONF "*" #HASHLEN, HASH, (size_t)HASHLEN, scratchsize);\ } while (0) @@ -268,6 +274,7 @@ main(void) INIT_TEST_ABORT(); INIT_RESOURCE_TEST(); +#define GET_SCRATCH_SIZE(HASHLEN) ((HASHLEN) > 64u ? ((HASHLEN) + 63u) & ~31u : (HASHLEN)) #if defined(SUPPORT_ARGON2I) CHECK("password", "$argon2i$" "m=256,t=2,p=1$c29tZXNhbHQ$", 32, "/U3YPXYsSb3q9XxHvc0MLxur+GP960kN9j7emXX8zwY"); CHECK("password", "$argon2i$v=19$m=256,t=2,p=1$c29tZXNhbHQ$", 32, "iekCn0Y3spW+sCcFanM2xBT63UP2sghkUoHLIUpWRS8"); @@ -287,6 +294,7 @@ main(void) "yLKZMg+DIOXVc9z1po9ZlZG8+Gp4g5brqfza3lvkR9vw"); CHECK_BAD("$argon2d$"); #endif +#undef GET_SCRATCH_SIZE STOP_RESOURCE_TEST(); return 0; diff --git a/argon2/make_settings.c b/argon2/make_settings.c index 924b33f..4354196 100644 --- a/argon2/make_settings.c +++ b/argon2/make_settings.c @@ -164,14 +164,17 @@ check(ssize_t (*gen)(char *, size_t, const char *, size_t, uintmax_t, ssize_t r; if (!algo_out) { + CANARY_FILL(buf); errno = 0; EXPECT((*gen)(buf, sizeof(buf), algo_in, 0u, 0u, 0, &saltgen, &saltbyte) == -1); EXPECT(errno == ENOSYS); + CANARY_CHECK(buf, 0u); return; } off = strlen(algo_out); + CANARY_FILL(buf); r = (*gen)(buf, sizeof(buf), algo_in, 0u, 0u, 0, &saltgen, &saltbyte); EXPECT(r > 0 && (size_t)r < sizeof(buf)); EXPECT(!buf[r] && (size_t)r == strlen(buf)); @@ -179,40 +182,53 @@ check(ssize_t (*gen)(char *, size_t, const char *, size_t, uintmax_t, EXPECT(!strcmp(&buf[off], "m=4096,t=10,p=1$*16$*32")); assert(LIBAR2_MIN_SALTLEN <= 16u && 16u <= LIBAR2_MAX_SALTLEN); assert(LIBAR2_MIN_HASHLEN <= 32u && 32u <= LIBAR2_MAX_HASHLEN); + CANARY_CHECK(buf, (size_t)r + 1u); EXPECT((*gen)(NULL, 0u, algo_in, 0u, 0u, 0, &saltgen, &saltbyte) == r); for (i = 1u; i <= (size_t)r; i++) { + CANARY_FILL(buf2); EXPECT((*gen)(buf2, i, algo_in, 0u, 0u, 0, &saltgen, &saltbyte) == r); EXPECT(!buf2[i - 1u]); EXPECT(!memcmp(buf2, buf, i - 1u)); + CANARY_CHECK(buf2, i); } + CANARY_FILL(buf); r = (*gen)(buf, sizeof(buf), algo_in, 8192u << 10, 0u, 0, &saltgen, &saltbyte); EXPECT(r > 0 && (size_t)r < sizeof(buf)); EXPECT(!buf[r] && (size_t)r == strlen(buf)); EXPECT(!strncmp(buf, algo_out, off)); EXPECT(!strcmp(&buf[off], "m=8192,t=5,p=1$*16$*32")); + CANARY_CHECK(buf, (size_t)r + 1u); + CANARY_FILL(buf); r = (*gen)(buf, sizeof(buf), algo_in, 8192u << 10, (uintmax_t)81920u, 0, &saltgen, &saltbyte); EXPECT(r > 0 && (size_t)r < sizeof(buf)); EXPECT(!buf[r] && (size_t)r == strlen(buf)); EXPECT(!strncmp(buf, algo_out, off)); EXPECT(!strcmp(&buf[off], "m=8192,t=10,p=1$*16$*32")); + CANARY_CHECK(buf, (size_t)r + 1u); + CANARY_FILL(buf); saltbyte = 0u; r = (*gen)(buf, sizeof(buf), algo_in, 8192u << 10, (uintmax_t)81920u, 1, &saltgen, &saltbyte); EXPECT(r > 0 && (size_t)r < sizeof(buf)); EXPECT(!buf[r] && (size_t)r == strlen(buf)); EXPECT(!strncmp(buf, algo_out, off)); EXPECT(!strcmp(&buf[off], "m=8192,t=10,p=1$AAAAAAAAAAAAAAAAAAAAAA$*32")); + CANARY_CHECK(buf, (size_t)r + 1u); + CANARY_FILL(buf); EXPECT((*gen)(buf, sizeof(buf), algo_in, 8192u << 10, (uintmax_t)81920u, 1, &saltgen, &saltbyte) == r); for (i = 1u; i <= (size_t)r; i++) { + CANARY_FILL(buf2); EXPECT((*gen)(buf2, i, algo_in, 8192u << 10, (uintmax_t)81920u, 1, &saltgen, &saltbyte) == r); EXPECT(!buf2[i - 1u]); EXPECT(!memcmp(buf2, buf, i - 1u)); + CANARY_CHECK(buf2, i); } + CANARY_FILL(buf); r = (*gen)(buf, sizeof(buf), algo_in, 8192u << 10, (uintmax_t)81920u, 1, NULL, &saltbyte); EXPECT(r > 0 && (size_t)r < sizeof(buf)); EXPECT(!buf[r] && (size_t)r == strlen(buf)); @@ -221,51 +237,67 @@ check(ssize_t (*gen)(char *, size_t, const char *, size_t, uintmax_t, memcpy(buf2, buf, (size_t)r); memset(&buf[off + sizeof("m=8192,t=10,p=1$") - 1u], 'A', 22u); EXPECT(!strcmp(&buf[off], "m=8192,t=10,p=1$AAAAAAAAAAAAAAAAAAAAAA$*32")); + CANARY_CHECK(buf, (size_t)r + 1u); + CANARY_FILL(buf); EXPECT((*gen)(buf, sizeof(buf), algo_in, 8192u << 10, (uintmax_t)81920u, 1, NULL, &saltbyte) == r); EXPECT(r > 0 && (size_t)r < sizeof(buf)); EXPECT(!buf[r] && (size_t)r == strlen(buf)); EXPECT(memcmp(buf, buf2, (size_t)r)); memset(&buf[off + sizeof("m=8192,t=10,p=1$") - 1u], 'A', 22u); EXPECT(!strcmp(&buf[off], "m=8192,t=10,p=1$AAAAAAAAAAAAAAAAAAAAAA$*32")); + CANARY_CHECK(buf, (size_t)r + 1u); + CANARY_FILL(buf); saltbyte = 255u; r = (*gen)(buf, sizeof(buf), algo_in, 8192u << 10, (uintmax_t)81920u, 1, &saltgen, &saltbyte); EXPECT(r > 0 && (size_t)r < sizeof(buf)); EXPECT(!buf[r] && (size_t)r == strlen(buf)); EXPECT(!strncmp(buf, algo_out, off)); EXPECT(!strcmp(&buf[off], "m=8192,t=10,p=1$/////////////////////w$*32")); + CANARY_CHECK(buf, (size_t)r + 1u); + CANARY_FILL(buf); r = (*gen)(buf, sizeof(buf), algo_in, 0u, (uintmax_t)81920u, 0, &saltgen, &saltbyte); EXPECT(r > 0 && (size_t)r < sizeof(buf)); EXPECT(!buf[r] && (size_t)r == strlen(buf)); EXPECT(!strncmp(buf, algo_out, off)); EXPECT(!strcmp(&buf[off], "m=4096,t=20,p=1$*16$*32")); + CANARY_CHECK(buf, (size_t)r + 1u); + CANARY_FILL(buf); r = (*gen)(buf, sizeof(buf), algo_in, 1u, 1u, 0, &saltgen, &saltbyte); EXPECT(r > 0 && (size_t)r < sizeof(buf)); EXPECT(!buf[r] && (size_t)r == strlen(buf)); EXPECT(!strncmp(buf, algo_out, off)); EXPECT(!strcmp(&buf[off], "m=8,t=1,p=1$*16$*32")); + CANARY_CHECK(buf, (size_t)r + 1u); + CANARY_FILL(buf); r = (*gen)(buf, sizeof(buf), algo_in, 1u, 1u, 0, &saltgen, &saltbyte); EXPECT(r > 0 && (size_t)r < sizeof(buf)); EXPECT(!buf[r] && (size_t)r == strlen(buf)); EXPECT(!strncmp(buf, algo_out, off)); EXPECT(!strcmp(&buf[off], "m=8,t=1,p=1$*16$*32")); + CANARY_CHECK(buf, (size_t)r + 1u); + CANARY_FILL(buf); r = (*gen)(buf, sizeof(buf), algo_in, (10u << 10) + 512u, 1u, 0, &saltgen, &saltbyte); EXPECT(r > 0 && (size_t)r < sizeof(buf)); EXPECT(!buf[r] && (size_t)r == strlen(buf)); EXPECT(!strncmp(buf, algo_out, off)); EXPECT(!strcmp(&buf[off], "m=11,t=1,p=1$*16$*32")); + CANARY_CHECK(buf, (size_t)r + 1u); + CANARY_FILL(buf); r = (*gen)(buf, sizeof(buf), algo_in, (10u << 10) + 511u, 1u, 0, &saltgen, &saltbyte); EXPECT(r > 0 && (size_t)r < sizeof(buf)); EXPECT(!buf[r] && (size_t)r == strlen(buf)); EXPECT(!strncmp(buf, algo_out, off)); EXPECT(!strcmp(&buf[off], "m=10,t=1,p=1$*16$*32")); + CANARY_CHECK(buf, (size_t)r + 1u); + CANARY_FILL(buf); r = (*gen)(buf, sizeof(buf), algo_in, SIZE_MAX, 1u, 0, &saltgen, &saltbyte); EXPECT(r > 0 && (size_t)r < sizeof(buf)); EXPECT(!buf[r] && (size_t)r == strlen(buf)); @@ -280,7 +312,9 @@ check(ssize_t (*gen)(char *, size_t, const char *, size_t, uintmax_t, v = v * 10u + d; } EXPECT(v <= (uintmax_t)LIBAR2_MAX_M_COST); + CANARY_CHECK(buf, (size_t)r + 1u); + CANARY_FILL(buf); r = (*gen)(buf, sizeof(buf), algo_in, 1u, UINTMAX_MAX, 0, &saltgen, &saltbyte); EXPECT(r > 0 && (size_t)r < sizeof(buf)); EXPECT(!buf[r] && (size_t)r == strlen(buf)); @@ -295,6 +329,7 @@ check(ssize_t (*gen)(char *, size_t, const char *, size_t, uintmax_t, v = v * 10u + d; } EXPECT(v <= (uintmax_t)LIBAR2_MAX_T_COST); + CANARY_CHECK(buf, (size_t)r + 1u); errno = 0; EXPECT((*gen)(buf, sizeof(buf), algo_in, 0u, 0u, 1, &saltfail, NULL) == -1); @@ -556,4 +556,30 @@ int librecrypt_check_settings_(const char *settings, size_t len, const char *fmt exit(2);\ }\ } while (0) + +# define CANARY_FILL(BUF) CANARY_C_FILL(99, BUF) +# define CANARY_CHECK(BUF, OFF) CANARY_C_CHECK(99, BUF, OFF) +# define CANARY_X_CHECK(BUF, OFF1, OFF2) CANARY_XC_CHECK(99, BUF, OFF1, OFF2) + +# define CANARY_C_FILL(C, BUF)\ + memset((BUF), (C), sizeof(BUF)) + +# define CANARY_C_CHECK(C, BUF, OFF)\ + do {\ + size_t canary_i__;\ + for (canary_i__ = (OFF); canary_i__ < sizeof(BUF); canary_i__++)\ + EXPECT(((unsigned char *)(BUF))[canary_i__] == (unsigned char)(C));\ + } while (0) + +# define CANARY_XC_CHECK(C, BUF, OFF1, OFF2)\ + CANARY_XCC_CHECK(0, C, BUF, OFF1, OFF2) + +# define CANARY_XCC_CHECK(C1, C2, BUF, OFF1, OFF2)\ + do {\ + if ((OFF2) > (OFF1))\ + CANARY_C_CHECK((C2), (BUF), (OFF2));\ + memset(&(BUF)[(OFF1)], (C1), sizeof(BUF) - (OFF1));\ + CANARY_C_CHECK((C1), (BUF), (OFF1));\ + } while (0) + #endif diff --git a/librecrypt_add_algorithm.c b/librecrypt_add_algorithm.c index cf7f6eb..920577d 100644 --- a/librecrypt_add_algorithm.c +++ b/librecrypt_add_algorithm.c @@ -184,40 +184,55 @@ main(void) #define CHECK(AUGEND, AUGMENT, RESULT)\ do {\ + CANARY_FILL(buf);\ r = librecrypt_add_algorithm(buf, sizeof(buf), (AUGEND), (AUGMENT), NULL);\ EXPECT(r > 0);\ EXPECT((size_t)r == strlen(RESULT));\ assert((size_t)r < sizeof(buf) + 1u);\ EXPECT(!buf[r]);\ EXPECT(!memcmp(buf, (RESULT), (size_t)r));\ + CANARY_CHECK(buf, (size_t)r + 1u);\ \ for (i = (size_t)r + 2u;; i--) {\ - memset(buf, 99, sizeof(buf));\ + CANARY_FILL(buf);\ EXPECT(librecrypt_add_algorithm(buf, i, (AUGEND), (AUGMENT), NULL) == r);\ - if (!i)\ + if (!i) {\ + CANARY_CHECK(buf, 0u);\ break;\ + }\ min = MIN(i - 1u, (size_t)r);\ EXPECT(!buf[min]);\ EXPECT(!memcmp(buf, (RESULT), min));\ + CANARY_CHECK(buf, min + 1u);\ }\ \ EXPECT(librecrypt_add_algorithm(NULL, 0u, (AUGEND), (AUGMENT), NULL) == r);\ \ assert(sizeof(buf) > strlen(AUGEND));\ - stpcpy(buf, (AUGEND));\ \ + CANARY_FILL(buf);\ + stpcpy(buf, (AUGEND));\ EXPECT(librecrypt_add_algorithm(buf, sizeof(buf), buf, (AUGMENT), NULL) == r);\ EXPECT(!buf[r]);\ EXPECT(!memcmp(buf, (RESULT), (size_t)r));\ + n = strlen(AUGEND) + 1u;\ + n = MAX(n, (size_t)r + 1u);\ + CANARY_CHECK(buf, n);\ \ for (i = (size_t)r + 2u;; i--) {\ + CANARY_FILL(buf);\ stpcpy(buf, (AUGEND));\ + n = strlen(AUGEND) + 1u;\ EXPECT(librecrypt_add_algorithm(buf, i, buf, (AUGMENT), NULL) == r);\ - if (!i)\ + if (!i) {\ + CANARY_CHECK(buf, n);\ break;\ + }\ min = MIN(i - 1u, (size_t)r);\ EXPECT(!buf[min]);\ EXPECT(!memcmp(buf, (RESULT), min));\ + n = MAX(n, min + 1u);\ + CANARY_CHECK(buf, n);\ }\ } while (0) @@ -262,10 +277,12 @@ main(void) CHECK("$argon2d$m=8,t=1,p=1$$", "$argon2i$m=8,t=4,p=2$$", "$argon2d$m=8,t=1,p=1$$>" "$argon2i$m=8,t=4,p=2$$"); + CANARY_FILL(buf); errno = 0; EXPECT(librecrypt_add_algorithm(buf, sizeof(buf), "$argon2d$m=8,t=1,p=1$"SALT1"$"HASH1, "$argon2i$m=8,t=4,p=1$$", NULL) == -1); EXPECT(errno == EINVAL); + CANARY_CHECK(buf, sizeof("$argon2d$m=8,t=1,p=1$"SALT1"$"HASH1)); errno = 0; EXPECT(librecrypt_add_algorithm(NULL, 0u, "$argon2d$m=8,t=1,p=1$"SALT1"$"HASH1, @@ -294,32 +311,40 @@ main(void) "$argon2i$m=8,t=4,p=1$"SALT2"$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", expected); if (libtest_have_custom_malloc()) { + CANARY_FILL(buf); libtest_set_alloc_failure_in(1u); errno = 0; EXPECT(librecrypt_add_algorithm(buf, sizeof(buf), "$argon2d$m=8,t=1,p=1$"SALT1"$"HASH1, "$argon2d$m=8,t=1,p=1$"SALT2"$", NULL) == -1); EXPECT(errno == ENOMEM); assert(libtest_get_alloc_failure_in() == 0u); + CANARY_CHECK(buf, 0u); } + CANARY_FILL(buf); errno = 0; EXPECT(librecrypt_add_algorithm(buf, sizeof(buf), "$argon2d$m=8,t=1,p=1$"SALT1"$" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", "$argon2d$m=8,t=1,p=1$"SALT2"$", NULL) == -1); EXPECT(errno == EINVAL); + CANARY_CHECK(buf, 0u); #endif + CANARY_FILL(buf); errno = 0; EXPECT(librecrypt_add_algorithm(buf, sizeof(buf), "$argon2d$m=8,t=1,p=1$"SALT1"$"HASH1, "$~no~such~algorithm~$", NULL) == -1); EXPECT(errno == ENOSYS); + CANARY_CHECK(buf, sizeof("$argon2d$m=8,t=1,p=1$"SALT1"$"HASH1)); + CANARY_FILL(buf); errno = 0; EXPECT(librecrypt_add_algorithm(buf, sizeof(buf), "$~no~such~algorithm~$"HASH1, "$argon2d$m=8,t=1,p=1$"SALT1"$", NULL) == -1); EXPECT(errno == ENOSYS); + CANARY_CHECK(buf, 0u); STOP_RESOURCE_TEST(); return 0; diff --git a/librecrypt_crypt.c b/librecrypt_crypt.c index ac35191..d116f87 100644 --- a/librecrypt_crypt.c +++ b/librecrypt_crypt.c @@ -14,7 +14,8 @@ librecrypt_crypt(char *restrict out_buffer, size_t size, const char *phrase, siz static void -check(const char *phrase, const char *settings, const char *chain, size_t chain_prefix, const char *hash, size_t hash_prefix) +check(const char *phrase, const char *settings, const char *chain, size_t chain_prefix, const char *hash, + size_t hash_prefix, size_t scratchsize) { size_t hashlen = strlen(hash); size_t len = strlen(phrase); @@ -25,27 +26,32 @@ check(const char *phrase, const char *settings, const char *chain, size_t chain_ assert(hashlen <= sizeof(buf)); - memset(buf, 0, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt_crypt(buf, sizeof(buf), phrase, len, settings, NULL) == (ssize_t)hashlen); EXPECT(!memcmp(hash, buf, hashlen + 1u)); + CANARY_X_CHECK(buf, hashlen + 1u, scratchsize); - memset(buf, 0, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt_crypt(buf, hashlen + 1u, phrase, len, settings, NULL) == (ssize_t)hashlen); EXPECT(!memcmp(hash, buf, hashlen + 1u)); + CANARY_X_CHECK(buf, hashlen + 1u, scratchsize); - memset(buf, 0, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt_crypt(buf, hashlen, phrase, len, settings, NULL) == (ssize_t)hashlen); EXPECT(!memcmp(hash, buf, hashlen - 1u)); - EXPECT(!buf[hashlen]); + EXPECT(!buf[hashlen - 1u]); + CANARY_X_CHECK(buf, hashlen, scratchsize); - memset(buf, 0, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt_crypt(buf, 2u, phrase, len, settings, NULL) == (ssize_t)hashlen); EXPECT(!memcmp(hash, buf, 1u)); EXPECT(!buf[1u]); + CANARY_X_CHECK(buf, 2u, 2u); - memset(buf, 0, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt_crypt(buf, 1u, phrase, len, settings, NULL) == (ssize_t)hashlen); EXPECT(!buf[0u]); + CANARY_X_CHECK(buf, 1u, 1u); EXPECT(librecrypt_crypt(buf, 0u, phrase, len, settings, NULL) == (ssize_t)hashlen); EXPECT(librecrypt_crypt(NULL, 0u, phrase, len, settings, NULL) == (ssize_t)hashlen); @@ -55,22 +61,29 @@ check(const char *phrase, const char *settings, const char *chain, size_t chain_ r = librecrypt_decode(expected, sizeof(expected), &hash[hash_prefix], hashlen - hash_prefix, lut, pad, strict_pad); assert(r > 0 && (size_t)r <= sizeof(expected)); + CANARY_FILL(buf); + CANARY_FILL(buf2); EXPECT(librecrypt_crypt(buf, sizeof(buf), expected, (size_t)r, settings, NULL) == (ssize_t)hashlen); errno = 0; EXPECT(librecrypt_crypt(buf2, sizeof(buf2), phrase, len, chain, NULL) == (ssize_t)(hashlen - hash_prefix + chain_prefix)); EXPECT(!memcmp(buf2, chain, chain_prefix)); EXPECT(!memcmp(&buf[hash_prefix], &buf2[chain_prefix], hashlen - hash_prefix + 1u)); + CANARY_X_CHECK(buf, hashlen, scratchsize); + CANARY_X_CHECK(buf2, hashlen - hash_prefix + chain_prefix, scratchsize); } #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,\ - sizeof(CONF "*" #HASHLEN ">" CONF) - 1u, CONF HASH, sizeof(CONF) - 1u);\ + sizeof(CONF "*" #HASHLEN ">" CONF) - 1u, CONF HASH, sizeof(CONF) - 1u, scratchsize);\ check(PHRASE, CONF "*" #HASHLEN, CONF "*" #HASHLEN ">" CONF "*" #HASHLEN,\ - sizeof(CONF "*" #HASHLEN ">" CONF) - 1u, CONF HASH, sizeof(CONF) - 1u);\ - if (IS_DEFAULT_HASHLEN)\ - check(PHRASE, CONF, CONF ">" CONF, sizeof(CONF ">" CONF) - 1u, CONF HASH, sizeof(CONF) - 1u);\ + sizeof(CONF "*" #HASHLEN ">" CONF) - 1u, CONF HASH, sizeof(CONF) - 1u, scratchsize);\ + if (IS_DEFAULT_HASHLEN) {\ + check(PHRASE, CONF, CONF ">" CONF, sizeof(CONF ">" CONF) - 1u,\ + CONF HASH, sizeof(CONF) - 1u, scratchsize);\ + }\ } while (0) @@ -96,6 +109,7 @@ main(void) libtest_getrandom_error = ENOSYS; #endif +#define GET_SCRATCH_SIZE(HASHLEN) ((HASHLEN) > 64u ? ((HASHLEN) + 63u) & ~31u : (HASHLEN)) #if defined(SUPPORT_ARGON2I) CHECK("password", "$argon2i$" "m=256,t=2,p=1$c29tZXNhbHQ$", 32, 1, "/U3YPXYsSb3q9XxHvc0MLxur+GP960kN9j7emXX8zwY"); CHECK("password", "$argon2i$v=19$m=256,t=2,p=1$c29tZXNhbHQ$", 32, 1, "iekCn0Y3spW+sCcFanM2xBT63UP2sghkUoHLIUpWRS8"); @@ -115,7 +129,6 @@ main(void) "yLKZMg+DIOXVc9z1po9ZlZG8+Gp4g5brqfza3lvkR9vw"); CHECK_BAD("$argon2d$"); #endif - #if defined(SUPPORT_ARGON2ID) assert(!libtest_getentropy_error); @@ -127,6 +140,7 @@ main(void) * of "ABCD", rather the become "AAECAwABAgMAAQIDAAECAwAB" */ libtest_random_pattern_length = 4u; libtest_random_pattern_offset = 0u; + CANARY_FILL(buf); r = librecrypt_crypt(buf, sizeof(buf), "", 0u, "$argon2id$v=19$m=8,t=1,p=1$*18$*33", NULL); libtest_random_pattern = NULL; libtest_random_pattern_length = 0u; @@ -136,15 +150,19 @@ main(void) assert((size_t)r < sizeof(buf)); EXPECT((size_t)r == sizeof("$argon2id$v=19$m=8,t=1,p=1$$") - 1u + 24u + 44u); EXPECT(!buf[r]); + CANARY_FILL(buf2); EXPECT(librecrypt_crypt(buf2, sizeof(buf2), "", 0u, buf, NULL) == r); EXPECT(!memcmp(buf, buf2, (size_t)r + 1u)); EXPECT(!memcmp(buf, "$argon2id$v=19$m=8,t=1,p=1$ABCDABCDABCDABCDABCDABCD$", sizeof("$argon2id$v=19$m=8,t=1,p=1$ABCDABCDABCDABCDABCDABCD$") - 1u)); + CANARY_X_CHECK(buf, (size_t)r + 1u, 33u); + CANARY_X_CHECK(buf2, (size_t)r + 1u, 33u); libtest_getentropy_real = 0; libtest_random_pattern = (const unsigned char *)"\x00\x01\x02\03"; libtest_random_pattern_length = 4u; libtest_random_pattern_offset = 0u; + CANARY_FILL(buf); r = librecrypt_crypt(buf, sizeof(buf), "", 0u, "$argon2id$v=19$m=8,t=1,p=1$*18$*33>" "$argon2id$v=19$m=8,t=1,p=1$*18$*33", NULL); libtest_random_pattern = NULL; @@ -155,13 +173,17 @@ main(void) assert((size_t)r < sizeof(buf)); EXPECT((size_t)r == sizeof("$argon2id$v=19$m=8,t=1,p=1$$*33>$argon2id$v=19$m=8,t=1,p=1$$") - 1u + 2u * 24u + 44u); EXPECT(!buf[r]); + CANARY_FILL(buf2); EXPECT(librecrypt_crypt(buf2, sizeof(buf2), "", 0u, buf, NULL) == r); EXPECT(!memcmp(buf, buf2, (size_t)r + 1u)); EXPECT(!memcmp(buf, "$argon2id$v=19$m=8,t=1,p=1$ABCDABCDABCDABCDABCDABCD$*33>" "$argon2id$v=19$m=8,t=1,p=1$ABCDABCDABCDABCDABCDABCD$", sizeof("$argon2id$v=19$m=8,t=1,p=1$ABCDABCDABCDABCDABCDABCD$*33>" "$argon2id$v=19$m=8,t=1,p=1$ABCDABCDABCDABCDABCDABCD$") - 1u)); + CANARY_X_CHECK(buf, (size_t)r + 1u, 33u); + CANARY_X_CHECK(buf2, (size_t)r + 1u, 33u); #endif +#undef GET_SCRATCH_SIZE #if defined(__linux__) libtest_getrandom_real = 1; diff --git a/librecrypt_decode.c b/librecrypt_decode.c index 3981612..5d09efa 100644 --- a/librecrypt_decode.c +++ b/librecrypt_decode.c @@ -184,34 +184,30 @@ check(const char *binary, size_t binary_len, const char *ascii, size_t unpadded_ /* Test output, with and without truncation */ for (i = 0u; i < sizeof(buf); i++) { - memset(buf, 99, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt_decode(buf, i, ascii, unpadded_len, lut, '\0', 0) == (ssize_t)binary_len); j = MIN(i, binary_len); EXPECT(!memcmp(buf, binary, j)); - for (; j < sizeof(buf); j++) - EXPECT(buf[j] == 99); + CANARY_CHECK(buf, j); - memset(buf, 99, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt_decode(buf, i, ascii, unpadded_len, lut, '\0', 1) == (ssize_t)binary_len); j = MIN(i, binary_len); EXPECT(!memcmp(buf, binary, j)); - for (; j < sizeof(buf); j++) - EXPECT(buf[j] == 99); + CANARY_CHECK(buf, j); - memset(buf, 99, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt_decode(buf, i, ascii, unpadded_len, lut, '=', 0) == (ssize_t)binary_len); j = MIN(i, binary_len); EXPECT(!memcmp(buf, binary, j)); - for (; j < sizeof(buf); j++) - EXPECT(buf[j] == 99); + CANARY_CHECK(buf, j); if (padded_len == unpadded_len) { - memset(buf, 99, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt_decode(buf, i, ascii, unpadded_len, lut, '=', 1) == (ssize_t)binary_len); j = MIN(i, binary_len); EXPECT(!memcmp(buf, binary, j)); - for (; j < sizeof(buf); j++) - EXPECT(buf[j] == 99); + CANARY_CHECK(buf, j); } else { errno = 0; EXPECT(librecrypt_decode(buf, i, ascii, unpadded_len, lut, '=', 1) == -1); @@ -226,20 +222,18 @@ check(const char *binary, size_t binary_len, const char *ascii, size_t unpadded_ EXPECT(errno == EINVAL); } - memset(buf, 99, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt_decode(buf, i, ascii, padded_len, lut, '=', 0) == (ssize_t)binary_len); j = MIN(i, binary_len); EXPECT(!memcmp(buf, binary, j)); - for (; j < sizeof(buf); j++) - EXPECT(buf[j] == 99); + CANARY_CHECK(buf, j); if (check_good_padding) { - memset(buf, 99, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt_decode(buf, i, ascii, padded_len, lut, '=', 1) == (ssize_t)binary_len); j = MIN(i, binary_len); EXPECT(!memcmp(buf, binary, j)); - for (; j < sizeof(buf); j++) - EXPECT(buf[j] == 99); + CANARY_CHECK(buf, j); } } diff --git a/librecrypt_decompose_chain.c b/librecrypt_decompose_chain.c index ae58c6c..9db1d6c 100644 --- a/librecrypt_decompose_chain.c +++ b/librecrypt_decompose_chain.c @@ -46,26 +46,33 @@ main(void) INIT_RESOURCE_TEST(); /* Check HASH_1 with different sizes of `chain` */ + CANARY_FILL(buf); stpcpy(buf, HASH_1); EXPECT(librecrypt_decompose_chain(buf, chain, 0u) == 1u); EXPECT(!strcmp(buf, HASH_1)); + CANARY_CHECK(buf, sizeof(HASH_1)); NULL_OUT(chain); EXPECT(librecrypt_decompose_chain(buf, chain, 1u) == 1u); EXPECT(!strcmp(buf, HASH_1)); EXPECT(chain[0u] == buf); + CANARY_CHECK(buf, sizeof(HASH_1)); NULL_OUT(chain); EXPECT(librecrypt_decompose_chain(buf, chain, ELEMSOF(chain)) == 1u); EXPECT(!strcmp(buf, HASH_1)); EXPECT(chain[0u] == buf); + CANARY_CHECK(buf, sizeof(HASH_1)); /* Check HASH_2 with different sizes of `chain` */ + CANARY_FILL(buf); stpcpy(buf, HASH_2); EXPECT(librecrypt_decompose_chain(buf, chain, 0u) == 3u); EXPECT(!strcmp(buf, HASH_2)); + CANARY_CHECK(buf, sizeof(HASH_2)); NULL_OUT(chain); EXPECT(librecrypt_decompose_chain(buf, chain, 1u) == 3u); EXPECT(!strcmp(buf, HASH_2)); EXPECT(chain[0u] == buf); + CANARY_CHECK(buf, sizeof(HASH_2)); NULL_OUT(chain); EXPECT(librecrypt_decompose_chain(buf, chain, 2u) == 3u); EXPECT(chain[0u] != NULL); @@ -73,6 +80,9 @@ main(void) EXPECT(chain[2u] == NULL); EXPECT(!strcmp(chain[0u], HASH_2_A)); EXPECT(!strcmp(chain[1u], HASH_2_BC)); + CANARY_CHECK(buf, sizeof(HASH_2)); + + CANARY_FILL(buf); stpcpy(buf, HASH_2); NULL_OUT(chain); EXPECT(librecrypt_decompose_chain(buf, chain, ELEMSOF(chain)) == 3u); @@ -83,15 +93,19 @@ main(void) EXPECT(!strcmp(chain[0u], HASH_2_A)); EXPECT(!strcmp(chain[1u], HASH_2_B)); EXPECT(!strcmp(chain[2u], HASH_2_C)); + CANARY_CHECK(buf, sizeof(HASH_2)); /* Check HASH_3 with different sizes of `chain` */ + CANARY_FILL(buf); stpcpy(buf, HASH_3); EXPECT(librecrypt_decompose_chain(buf, chain, 0u) == 5u); EXPECT(!strcmp(buf, HASH_3)); + CANARY_CHECK(buf, sizeof(HASH_3)); NULL_OUT(chain); EXPECT(librecrypt_decompose_chain(buf, chain, 1u) == 5u); EXPECT(!strcmp(buf, HASH_3)); EXPECT(chain[0u] == buf); + CANARY_CHECK(buf, sizeof(HASH_3)); NULL_OUT(chain); EXPECT(librecrypt_decompose_chain(buf, chain, 2u) == 5u); EXPECT(chain[0u] != NULL); @@ -99,6 +113,9 @@ main(void) EXPECT(chain[2u] == NULL); EXPECT(!strcmp(chain[0u], HASH_3_A)); EXPECT(!strcmp(chain[1u], HASH_3_BCDE)); + CANARY_CHECK(buf, sizeof(HASH_3)); + + CANARY_FILL(buf); stpcpy(buf, HASH_3); NULL_OUT(chain); EXPECT(librecrypt_decompose_chain(buf, chain, 3u) == 5u); @@ -109,6 +126,9 @@ main(void) EXPECT(!strcmp(chain[0u], HASH_3_A)); EXPECT(!strcmp(chain[1u], HASH_3_B)); EXPECT(!strcmp(chain[2u], HASH_3_CDE)); + CANARY_CHECK(buf, sizeof(HASH_3)); + + CANARY_FILL(buf); stpcpy(buf, HASH_3); NULL_OUT(chain); EXPECT(librecrypt_decompose_chain(buf, chain, 4u) == 5u); @@ -121,6 +141,9 @@ main(void) EXPECT(!strcmp(chain[1u], HASH_3_B)); EXPECT(!strcmp(chain[2u], HASH_3_C)); EXPECT(!strcmp(chain[3u], HASH_3_DE)); + CANARY_CHECK(buf, sizeof(HASH_3)); + + CANARY_FILL(buf); stpcpy(buf, HASH_3); NULL_OUT(chain); EXPECT(librecrypt_decompose_chain(buf, chain, 5u) == 5u); @@ -135,6 +158,9 @@ main(void) EXPECT(!strcmp(chain[2u], HASH_3_C)); EXPECT(!strcmp(chain[3u], HASH_3_D)); EXPECT(!strcmp(chain[4u], HASH_3_E)); + CANARY_CHECK(buf, sizeof(HASH_3)); + + CANARY_FILL(buf); stpcpy(buf, HASH_3); NULL_OUT(chain); EXPECT(librecrypt_decompose_chain(buf, chain, 6u) == 5u); @@ -149,6 +175,7 @@ main(void) EXPECT(!strcmp(chain[2u], HASH_3_C)); EXPECT(!strcmp(chain[3u], HASH_3_D)); EXPECT(!strcmp(chain[4u], HASH_3_E)); + CANARY_CHECK(buf, sizeof(HASH_3)); STOP_RESOURCE_TEST(); return 0; diff --git a/librecrypt_decompose_chain1.c b/librecrypt_decompose_chain1.c index 6eece8d..6fc8a63 100644 --- a/librecrypt_decompose_chain1.c +++ b/librecrypt_decompose_chain1.c @@ -13,11 +13,13 @@ extern inline size_t librecrypt_decompose_chain1(char *hash); do {\ assert(sizeof(IN) <= sizeof(buf));\ assert(sizeof(IN) == sizeof(OUT));\ + CANARY_FILL(buf);\ stpcpy(buf, (IN));\ n = librecrypt_decompose_chain1(buf);\ EXPECT(n == (N));\ EXPECT(n == librecrypt_chain_length(IN));\ EXPECT(!memcmp(buf, (OUT), sizeof(IN)));\ + CANARY_CHECK(buf, sizeof(IN));\ } while (0) diff --git a/librecrypt_encode.c b/librecrypt_encode.c index 6c81b33..ec371cc 100644 --- a/librecrypt_encode.c +++ b/librecrypt_encode.c @@ -156,17 +156,16 @@ check(const char *binary, size_t binary_len, const char *ascii, size_t ascii_len /* Check encoding requests, with and without truncation, without padding */ for (i = 0u; i <= ascii_len; i++) { - memset(buf, 99, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt_encode(buf, i + 1u, binary, binary_len, lut, '\0') == ascii_len); EXPECT(!memcmp(buf, ascii, i)); EXPECT(buf[i] == '\0'); - for (j = i + 1u; j < sizeof(buf); j++) - EXPECT(buf[j] == 99); + CANARY_CHECK(buf, i + 1u); } /* Check encoding requests, with and without truncation, with padding */ for (i = 0u; i <= padded_ascii_len; i++) { - memset(buf, 99, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt_encode(buf, i + 1u, binary, binary_len, lut, '=') == padded_ascii_len); j = MIN(i, ascii_len); n = MIN(i, padded_ascii_len); @@ -174,8 +173,7 @@ check(const char *binary, size_t binary_len, const char *ascii, size_t ascii_len for (; j < n; j++) EXPECT(buf[j] == '='); EXPECT(buf[j++] == '\0'); - for (; j < sizeof(buf); j++) - EXPECT(buf[j] == 99); + CANARY_CHECK(buf, j); } } diff --git a/librecrypt_fill_with_random_.c b/librecrypt_fill_with_random_.c index 1361652..a1acc84 100644 --- a/librecrypt_fill_with_random_.c +++ b/librecrypt_fill_with_random_.c @@ -106,8 +106,17 @@ main(void) EXPECT(librecrypt_fill_with_random_(buf2, sizeof(buf1), NULL, NULL) == 0); EXPECT(memcmp(buf1, buf2, sizeof(buf1))); + /* Check that it is not writing too much */ + CANARY_FILL(buf1); + CANARY_FILL(buf2); + EXPECT(librecrypt_fill_with_random_(buf1, sizeof(buf1) / 2u, NULL, NULL) == 0); + EXPECT(librecrypt_fill_with_random_(buf2, sizeof(buf2) / 2u, NULL, NULL) == 0); + EXPECT(memcmp(buf1, buf2, sizeof(buf1) / 2u)); + CANARY_CHECK(buf1, sizeof(buf1) / 2u); + CANARY_CHECK(buf2, sizeof(buf2) / 2u); + /* Check stateless all-at-once RNG */ - memset(buf1, 99, sizeof(buf1)); + CANARY_FILL(buf1); errno = 0; EXPECT(librecrypt_fill_with_random_(buf1, sizeof(buf1), &zero, NULL) == 0); EXPECT(errno == 0); @@ -115,7 +124,7 @@ main(void) EXPECT(!buf1[i]); /* Check stateful chunked RNG (importantly, chunks are smaller than pattern) */ - memset(buf1, 99, sizeof(buf1)); + CANARY_FILL(buf1); s = 0u; errno = 0; EXPECT(librecrypt_fill_with_random_(buf1, sizeof(buf1), &seq, &s) == 0); @@ -124,7 +133,7 @@ main(void) EXPECT(buf1[i] == s); /* Check stateful one-byte-per-call RNG */ - memset(buf1, 99, sizeof(buf1)); + CANARY_FILL(buf1); s = 0u; errno = 0; EXPECT(librecrypt_fill_with_random_(buf1, sizeof(buf1), &next, &s) == 0); @@ -133,13 +142,12 @@ main(void) EXPECT(buf1[i] == s); /* Check failure in RNG */ - memset(buf1, 99, sizeof(buf1)); + CANARY_FILL(buf1); s = 0u; errno = 0; EXPECT(librecrypt_fill_with_random_(buf1, sizeof(buf1), &failer, NULL) == -1); EXPECT(errno == EDOM); - for (s = 0u, i = 0u; i < sizeof(buf1); i++, s++) - EXPECT(buf1[i] == 99); + CANARY_CHECK(buf1, 0u); /* Check function abort(3)s if RNG returns 0 */ EXPECT_ABORT(rv = librecrypt_fill_with_random_(buf1, sizeof(buf1), &zero_ret, NULL)); diff --git a/librecrypt_hash.c b/librecrypt_hash.c index 66784d4..69b8dcf 100644 --- a/librecrypt_hash.c +++ b/librecrypt_hash.c @@ -14,7 +14,7 @@ librecrypt_hash(char *restrict out_buffer, size_t size, const char *phrase, size static void -check(const char *phrase, const char *settings, const char *chain, const char *hash) +check(const char *phrase, const char *settings, const char *chain, const char *hash, size_t scratchsize) { size_t hashlen = strlen(hash); size_t len = strlen(phrase); @@ -26,29 +26,36 @@ check(const char *phrase, const char *settings, const char *chain, const char *h assert(hashlen <= sizeof(buf)); assert(hashlen < sizeof(expected)); - memset(buf, 0, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt_hash(buf, sizeof(buf), phrase, len, settings, NULL) == (ssize_t)hashlen); EXPECT(!memcmp(hash, buf, hashlen + 1u)); + CANARY_X_CHECK(buf, hashlen + 1u, scratchsize); - memset(buf, 0, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt_hash(buf, hashlen + 1u, phrase, len, settings, NULL) == (ssize_t)hashlen); EXPECT(!memcmp(hash, buf, hashlen + 1u)); + CANARY_X_CHECK(buf, hashlen + 1u, scratchsize); - memset(buf, 0, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt_hash(buf, hashlen, phrase, len, settings, NULL) == (ssize_t)hashlen); EXPECT(!memcmp(hash, buf, hashlen - 1u)); - EXPECT(!buf[hashlen]); + EXPECT(!buf[hashlen - 1]); + CANARY_X_CHECK(buf, hashlen, scratchsize); - memset(buf, 0, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt_hash(buf, 2u, phrase, len, settings, NULL) == (ssize_t)hashlen); EXPECT(!memcmp(hash, buf, 1u)); EXPECT(!buf[1u]); + CANARY_X_CHECK(buf, 2u, 2u); - memset(buf, 0, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt_hash(buf, 1u, phrase, len, settings, NULL) == (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); + CANARY_X_CHECK(buf, 0u, 0u); EXPECT(librecrypt_hash(NULL, 0u, phrase, len, settings, NULL) == (ssize_t)hashlen); lut = librecrypt_get_encoding(settings, strlen(settings), &pad, &strict_pad, 1); @@ -56,19 +63,24 @@ check(const char *phrase, const char *settings, const char *chain, const char *h 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); errno = 0; EXPECT(librecrypt_hash(buf2, sizeof(buf2), phrase, len, chain, NULL) == (ssize_t)hashlen); EXPECT(!memcmp(buf, buf2, hashlen + 1u)); + CANARY_X_CHECK(buf, hashlen + 2, scratchsize); + CANARY_X_CHECK(buf2, hashlen + 2, scratchsize); } #define CHECK(PHRASE, CONF, HASHLEN, IS_DEFAULT_HASHLEN, HASH)\ do {\ - check(PHRASE, CONF HASH, CONF "*" #HASHLEN ">" CONF HASH, HASH);\ - check(PHRASE, CONF "*" #HASHLEN, CONF "*" #HASHLEN ">" CONF "*" #HASHLEN, HASH);\ + 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);\ if (IS_DEFAULT_HASHLEN)\ - check(PHRASE, CONF, CONF ">" CONF, HASH);\ + check(PHRASE, CONF, CONF ">" CONF, HASH, scratchsize);\ } while (0) @@ -110,6 +122,7 @@ main(void) SET_UP_ALARM(); INIT_RESOURCE_TEST(); +#define GET_SCRATCH_SIZE(HASHLEN) ((HASHLEN) > 64u ? ((HASHLEN) + 63u) & ~31u : (HASHLEN)) #if defined(SUPPORT_ARGON2I) CHECK("password", "$argon2i$" "m=256,t=2,p=1$c29tZXNhbHQ$", 32, 1, "/U3YPXYsSb3q9XxHvc0MLxur+GP960kN9j7emXX8zwY"); CHECK("password", "$argon2i$v=19$m=256,t=2,p=1$c29tZXNhbHQ$", 32, 1, "iekCn0Y3spW+sCcFanM2xBT63UP2sghkUoHLIUpWRS8"); @@ -129,6 +142,7 @@ main(void) "yLKZMg+DIOXVc9z1po9ZlZG8+Gp4g5brqfza3lvkR9vw"); CHECK_BAD("$argon2d$"); #endif +#undef GET_SCRATCH_SIZE STOP_RESOURCE_TEST(); return 0; diff --git a/librecrypt_hash_.c b/librecrypt_hash_.c index a09d921..7438a48 100644 --- a/librecrypt_hash_.c +++ b/librecrypt_hash_.c @@ -368,19 +368,26 @@ main(void) # define ARGON2ID_PREFIX "$argon2id$v=19$m=8,t=1,p=1$" # define ARGON2ID_STR ARGON2ID_PREFIX SALT"$*32" + CANARY_FILL(buf); errno = 0; EXPECT(librecrypt_hash_(buf, sizeof(buf), "hello", 5u, "!"ARGON2ID_STR, NULL, ASCII_CRYPT) == -1); EXPECT(errno == ENOSYS); + CANARY_CHECK(buf, 0u); + CANARY_FILL(buf); errno = 0; EXPECT(librecrypt_hash_(buf, sizeof(buf), "hello", 5u, ARGON2ID_PREFIX"*"LARGE"$", NULL, ASCII_CRYPT) == -1); EXPECT(errno == ENOMEM); + CANARY_CHECK(buf, sizeof(ARGON2ID_PREFIX"*")); 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++) + for (i = 0u; i <= sizeof(sbuf); i++) { + CANARY_FILL(sbuf); EXPECT(librecrypt_hash_(sbuf, i, NULL, 0u, ARGON2ID_PREFIX"*1000$", NULL, ASCII_CRYPT) == r); + CANARY_X_CHECK(sbuf, (size_t)r, MIN(i, 32u)); + } if (libtest_have_custom_malloc()) { /* target if-statement in zero_generator, using alloc failure as guarding; @@ -434,6 +441,7 @@ main(void) } + CANARY_FILL(buf1); memset(buf1, 99, sizeof(buf1)); r1 = librecrypt_hash_(buf1, sizeof(buf1), NULL, 0u, X2(ARGON2ID_STR), NULL, ASCII_CRYPT); EXPECT(r1 > 0); @@ -445,13 +453,13 @@ main(void) EXPECT(r1c > 0); EXPECT(r1c == r1 + 2 * (ssize_t)sizeof(ARGON2ID_STR)); - memset(buf2, 99, sizeof(buf2)); + CANARY_FILL(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(librecrypt_hash_(buf, sizeof(buf), NULL, 0u, X4(ARGON2ID_STR), NULL, ASCII_HASH) == r2); EXPECT(r2 < r1); - memset(buf3, 99, sizeof(buf3)); + CANARY_FILL(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); @@ -460,30 +468,37 @@ main(void) 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)); + CANARY_C_FILL(88, buf); EXPECT(librecrypt_hash_(buf, i, NULL, 0u, X2(ARGON2ID_STR), NULL, ASCII_CRYPT) == r1); if (i) { n = MIN(i - 1u, (size_t)r1); EXPECT(!memcmp(buf, buf1, n)); EXPECT(buf[n] == '\0'); } + CANARY_X_CHECK(buf, (size_t)r1, MIN(i, 32u)); } if (i <= (size_t)r2 + 10u) { - memset(buf, 88, sizeof(buf)); + CANARY_C_FILL(88, buf); EXPECT(librecrypt_hash_(buf, i, NULL, 0u, X2(ARGON2ID_STR), NULL, ASCII_HASH) == r2); if (i) { n = MIN(i - 1u, (size_t)r2); EXPECT(!memcmp(buf, buf2, n)); EXPECT(buf[n] == '\0'); } + CANARY_X_CHECK(buf, (size_t)r2, MIN(i, 32u)); } if (i <= (size_t)r3 + 10u) { - memset(buf, 88, sizeof(buf)); + CANARY_C_FILL(88, buf); EXPECT(librecrypt_hash_(buf, i, NULL, 0u, X2(ARGON2ID_STR), NULL, BINARY_HASH) == r3); EXPECT(!memcmp(buf, buf3, MIN(i, (size_t)r3))); + CANARY_X_CHECK(buf, MIN(i, (size_t)r3), MIN(i, 32u)); } } + CANARY_X_CHECK(buf1, (size_t)r1, 32u); + CANARY_X_CHECK(buf2, (size_t)r2, 32u); + CANARY_X_CHECK(buf3, (size_t)r3, 32u); + 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); diff --git a/librecrypt_hash_binary.c b/librecrypt_hash_binary.c index ee2b8ca..9987758 100644 --- a/librecrypt_hash_binary.c +++ b/librecrypt_hash_binary.c @@ -14,7 +14,7 @@ librecrypt_hash_binary(char *restrict out_buffer, size_t size, const char *phras static void -check(const char *phrase, const char *settings, const char *chain, const char *hash, size_t hashlen) +check(const char *phrase, const char *settings, const char *chain, const char *hash, size_t hashlen, size_t scratchsize) { size_t len = strlen(phrase); char buf[1024], buf2[sizeof(buf)], expected[256], pad; @@ -31,34 +31,44 @@ check(const char *phrase, const char *settings, const char *chain, const char *h r = librecrypt_decode(expected, sizeof(expected), hash, strlen(hash), lut, pad, strict_pad); assert(r > 0 && (size_t)r == hashlen); - memset(buf, 0, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt_hash_binary(buf, sizeof(buf), phrase, len, settings, NULL) == (ssize_t)hashlen); EXPECT(!memcmp(buf, expected, hashlen)); + CANARY_X_CHECK(buf, hashlen, scratchsize); - memset(buf, 0, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt_hash_binary(buf, hashlen, phrase, len, settings, NULL) == (ssize_t)hashlen); EXPECT(!memcmp(buf, expected, hashlen)); + CANARY_X_CHECK(buf, hashlen, scratchsize); - memset(buf, 0, sizeof(buf)); + CANARY_FILL(buf); EXPECT(librecrypt_hash_binary(buf, 1u, phrase, len, settings, NULL) == (ssize_t)hashlen); EXPECT(!memcmp(buf, expected, 1u)); + CANARY_X_CHECK(buf, 1u, 1u); + CANARY_FILL(buf); EXPECT(librecrypt_hash_binary(buf, 0u, phrase, len, settings, NULL) == (ssize_t)hashlen); + CANARY_X_CHECK(buf, 0u, 0u); EXPECT(librecrypt_hash_binary(NULL, 0u, phrase, len, settings, NULL) == (ssize_t)hashlen); + CANARY_FILL(buf); + CANARY_FILL(buf2); EXPECT(librecrypt_hash_binary(buf, sizeof(buf), expected, hashlen, settings, NULL) == (ssize_t)hashlen); errno = 0; EXPECT(librecrypt_hash_binary(buf2, sizeof(buf2), phrase, len, chain, NULL) == (ssize_t)hashlen); EXPECT(!memcmp(buf, buf2, hashlen)); + CANARY_X_CHECK(buf, hashlen, scratchsize); + CANARY_X_CHECK(buf2, hashlen, scratchsize); } #define CHECK(PHRASE, CONF, HASHLEN, IS_DEFAULT_HASHLEN, HASH)\ do {\ - check(PHRASE, CONF HASH, CONF "*" #HASHLEN ">" CONF HASH, HASH, (size_t)HASHLEN);\ - check(PHRASE, CONF "*" #HASHLEN, CONF "*" #HASHLEN ">" CONF "*" #HASHLEN, HASH, (size_t)HASHLEN);\ + size_t scratchsize = GET_SCRATCH_SIZE(HASHLEN);\ + check(PHRASE, CONF HASH, CONF "*" #HASHLEN ">" CONF HASH, HASH, (size_t)HASHLEN, scratchsize);\ + check(PHRASE, CONF "*" #HASHLEN, CONF "*" #HASHLEN ">" CONF "*" #HASHLEN, HASH, (size_t)HASHLEN, scratchsize);\ if (IS_DEFAULT_HASHLEN)\ - check(PHRASE, CONF, CONF ">" CONF, HASH, (size_t)HASHLEN);\ + check(PHRASE, CONF, CONF ">" CONF, HASH, (size_t)HASHLEN, scratchsize);\ } while (0) @@ -79,6 +89,7 @@ main(void) SET_UP_ALARM(); INIT_RESOURCE_TEST(); +#define GET_SCRATCH_SIZE(HASHLEN) ((HASHLEN) > 64u ? ((HASHLEN) + 63u) & ~31u : (HASHLEN)) #if defined(SUPPORT_ARGON2I) CHECK("password", "$argon2i$" "m=256,t=2,p=1$c29tZXNhbHQ$", 32, 1, "/U3YPXYsSb3q9XxHvc0MLxur+GP960kN9j7emXX8zwY"); CHECK("password", "$argon2i$v=19$m=256,t=2,p=1$c29tZXNhbHQ$", 32, 1, "iekCn0Y3spW+sCcFanM2xBT63UP2sghkUoHLIUpWRS8"); @@ -98,6 +109,7 @@ main(void) "yLKZMg+DIOXVc9z1po9ZlZG8+Gp4g5brqfza3lvkR9vw"); CHECK_BAD("$argon2d$"); #endif +#undef GET_SCRATCH_SIZE STOP_RESOURCE_TEST(); return 0; diff --git a/librecrypt_make_settings.c b/librecrypt_make_settings.c index 7688061..5bdc6f5 100644 --- a/librecrypt_make_settings.c +++ b/librecrypt_make_settings.c @@ -97,40 +97,48 @@ main(void) #if defined(SUPPORT_ARGON2I) saltbyte = 0u; + CANARY_FILL(buf); r = librecrypt_make_settings(buf, sizeof(buf), "$argon2i$", 8192u << 10, (uintmax_t)81920u, 1, &saltgen, &saltbyte); EXPECT(r > 0 && (size_t)r < sizeof(buf)); EXPECT(!buf[r] && (size_t)r == strlen(buf)); EXPECT(!strcmp(buf, "$argon2i$v=19$m=8192,t=10,p=1$AAAAAAAAAAAAAAAAAAAAAA$*32")); + CANARY_CHECK(buf, (size_t)r + 1u); any_supported = 1; any_salted = 1; #endif #if defined(SUPPORT_ARGON2D) saltbyte = 0u; + CANARY_FILL(buf); r = librecrypt_make_settings(buf, sizeof(buf), "$argon2d$", 8192u << 10, (uintmax_t)81920u, 1, &saltgen, &saltbyte); EXPECT(r > 0 && (size_t)r < sizeof(buf)); EXPECT(!buf[r] && (size_t)r == strlen(buf)); EXPECT(!strcmp(buf, "$argon2d$v=19$m=8192,t=10,p=1$AAAAAAAAAAAAAAAAAAAAAA$*32")); + CANARY_CHECK(buf, (size_t)r + 1u); any_supported = 1; any_salted = 1; #endif #if defined(SUPPORT_ARGON2ID) saltbyte = 0u; + CANARY_FILL(buf); r = librecrypt_make_settings(buf, sizeof(buf), "$argon2id$", 8192u << 10, (uintmax_t)81920u, 1, &saltgen, &saltbyte); EXPECT(r > 0 && (size_t)r < sizeof(buf)); EXPECT(!buf[r] && (size_t)r == strlen(buf)); EXPECT(!strcmp(buf, "$argon2id$v=19$m=8192,t=10,p=1$AAAAAAAAAAAAAAAAAAAAAA$*32")); + CANARY_CHECK(buf, (size_t)r + 1u); any_supported = 1; any_salted = 1; #endif #if defined(SUPPORT_ARGON2DS) saltbyte = 0u; + CANARY_FILL(buf); r = librecrypt_make_settings(buf, sizeof(buf), "$argon2ds$", 8192u << 10, (uintmax_t)81920u, 1, &saltgen, &saltbyte); EXPECT(r > 0 && (size_t)r < sizeof(buf)); EXPECT(!buf[r] && (size_t)r == strlen(buf)); EXPECT(!strcmp(buf, "$argon2ds$v=19$m=8192,t=10,p=1$AAAAAAAAAAAAAAAAAAAAAA$*32")); + CANARY_CHECK(buf, (size_t)r + 1u); any_supported = 1; any_salted = 1; #endif @@ -147,26 +155,38 @@ main(void) EXPECT(librecrypt_make_settings(buf, sizeof(buf), NULL, 0u, 0u, 1, &saltfail, NULL) > 0); } + CANARY_FILL(buf); + CANARY_FILL(buf2); r = librecrypt_make_settings(buf, sizeof(buf), NULL, 0u, 0u, 0, &saltfail, NULL); EXPECT(r > 0 && (size_t)r < sizeof(buf)); EXPECT(!buf[r] && (size_t)r == strlen(buf)); EXPECT(librecrypt_make_settings(buf2, sizeof(buf2), NULL, 0u, 0u, 0, &saltfail, NULL) == r); EXPECT(!buf2[r] && (size_t)r == strlen(buf2)); EXPECT(!strcmp(buf, buf2)); + CANARY_CHECK(buf, (size_t)r + 1u); + CANARY_CHECK(buf2, (size_t)r + 1u); + CANARY_FILL(buf); + CANARY_FILL(buf2); r = librecrypt_make_settings(buf, sizeof(buf), NULL, 0u, 0u, 0, NULL, NULL); EXPECT(r > 0 && (size_t)r < sizeof(buf)); EXPECT(!buf[r] && (size_t)r == strlen(buf)); EXPECT(librecrypt_make_settings(buf2, sizeof(buf2), NULL, 0u, 0u, 0, NULL, NULL) == r); EXPECT(!buf2[r] && (size_t)r == strlen(buf2)); EXPECT(!strcmp(buf, buf2)); + CANARY_CHECK(buf, (size_t)r + 1u); + CANARY_CHECK(buf2, (size_t)r + 1u); + CANARY_FILL(buf); + CANARY_FILL(buf2); r = librecrypt_make_settings(buf, sizeof(buf), NULL, 0u, 0u, 1, NULL, NULL); EXPECT(r > 0 && (size_t)r < sizeof(buf)); EXPECT(!buf[r] && (size_t)r == strlen(buf)); EXPECT(librecrypt_make_settings(buf2, sizeof(buf2), NULL, 0u, 0u, 1, NULL, NULL) == r); EXPECT(!buf2[r] && (size_t)r == strlen(buf2)); EXPECT(strcmp(buf, buf2)); + CANARY_CHECK(buf, (size_t)r + 1u); + CANARY_CHECK(buf2, (size_t)r + 1u); } else { errno = 0; EXPECT(librecrypt_make_settings(NULL, 0u, NULL, 0u, 0u, 0, NULL, NULL) == -1); diff --git a/librecrypt_realise_salts.c b/librecrypt_realise_salts.c index 195afaf..8a4b769 100644 --- a/librecrypt_realise_salts.c +++ b/librecrypt_realise_salts.c @@ -270,7 +270,9 @@ main(void) EXPECT(librecrypt_realise_salts(NULL, 0u, ALGO"*"LARGE"$", &saltgen, &saltbyte) == -1); EXPECT(errno == ERANGE); + CANARY_FILL(buf); EXPECT(librecrypt_realise_salts(buf, sizeof(ALGO) - 1u, ALGO"*3$", &saltfail, NULL) == (ssize_t)sizeof(ALGO"$") - 1 + 4); + CANARY_CHECK(buf, sizeof(ALGO) - 1u); errno = 0; EXPECT(librecrypt_realise_salts(buf, sizeof(buf), ALGO"*3$", &saltfail, NULL) == -1); EXPECT(errno == EDOM); @@ -293,13 +295,15 @@ main(void) EXPECT(librecrypt_realise_salts(NULL, 0u, conf, &saltgen, &saltbyte) == -1); EXPECT(errno == ERANGE); - memset(buf, 99, sizeof(buf)); - memset(buf2, 99, sizeof(buf2)); + CANARY_FILL(buf); + CANARY_FILL(buf2); EXPECT(librecrypt_realise_salts(buf, sizeof(buf), ALGO"*30$", NULL, NULL) == (ssize_t)sizeof(ALGO"$") - 1 + 40); EXPECT(librecrypt_realise_salts(buf2, sizeof(buf2), ALGO"*30$", NULL, NULL) == (ssize_t)sizeof(ALGO"$") - 1 + 40); EXPECT(!buf[sizeof(ALGO"$") - 1u + 40u]); EXPECT(!buf2[sizeof(ALGO"$") - 1u + 40u]); EXPECT(memcmp(buf, buf2, sizeof(ALGO"$") - 1u + 40u)); + CANARY_CHECK(buf, sizeof(ALGO"$") + 40u); + CANARY_CHECK(buf2, sizeof(ALGO"$") + 40u); #endif STOP_RESOURCE_TEST(); diff --git a/librecrypt_rng_.c b/librecrypt_rng_.c index e620c6f..4c6d5dc 100644 --- a/librecrypt_rng_.c +++ b/librecrypt_rng_.c @@ -374,18 +374,24 @@ main(void) #define CHECK1()\ do {\ + CANARY_FILL(buf1);\ n1 = librecrypt_rng_(buf1, sizeof(buf1), NULL);\ EXPECT(n1 >= 128 && (size_t)n1 <= sizeof(buf1));\ EXPECT(memcmp(buf1, buf2, (size_t)MIN(n1, n2)));\ + CANARY_CHECK(buf1, (size_t)n1);\ } while (0) #define CHECK2()\ do {\ + CANARY_FILL(buf1);\ + CANARY_FILL(buf2);\ n1 = librecrypt_rng_(buf1, sizeof(buf1), NULL);\ n2 = librecrypt_rng_(buf2, sizeof(buf2), &user);\ EXPECT(n1 >= 128 && (size_t)n1 <= sizeof(buf1));\ EXPECT(n2 >= 128 && (size_t)n2 <= sizeof(buf2));\ EXPECT(memcmp(buf1, buf2, (size_t)MIN(n1, n2)));\ + CANARY_CHECK(buf1, (size_t)n1);\ + CANARY_CHECK(buf2, (size_t)n2);\ } while (0) /* Test with output pattern (useful for other tests) */ |
