diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | Makefile.in | 4 | ||||
-rw-r--r-- | balloon-sha1.c | 55 | ||||
-rw-r--r-- | balloon-sha256.c | 55 | ||||
-rw-r--r-- | balloon-sha384.c | 55 | ||||
-rw-r--r-- | balloon-sha512.c | 55 | ||||
-rw-r--r-- | balloon.c | 149 | ||||
-rw-r--r-- | balloon.h | 98 | ||||
-rw-r--r-- | eccdata.c | 207 | ||||
-rw-r--r-- | testsuite/.gitignore | 1 | ||||
-rw-r--r-- | testsuite/Makefile.in | 2 | ||||
-rw-r--r-- | testsuite/balloon-test.c | 135 |
12 files changed, 720 insertions, 102 deletions
@@ -1,3 +1,9 @@ +2022-09-08 Niels Möller <nisse@lysator.liu.se> + + * eccdata.c (string_toupper): New utility function. + (output_modulo): Move more of the per-modulo output here. + (output_curve): Remove corresponding code. + 2022-08-31 Niels Möller <nisse@lysator.liu.se> * bswap-internal.h (nettle_bswap64, nettle_bswap32) diff --git a/Makefile.in b/Makefile.in index 0f7bf4d6..b9e39581 100644 --- a/Makefile.in +++ b/Makefile.in @@ -83,6 +83,8 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c aes-decrypt-table.c \ nist-keywrap.c \ arcfour.c arcfour-crypt.c \ arctwo.c arctwo-meta.c blowfish.c blowfish-bcrypt.c \ + balloon.c balloon-sha1.c balloon-sha256.c \ + balloon-sha384.c balloon-sha512.c \ base16-encode.c base16-decode.c base16-meta.c \ base64-encode.c base64-decode.c base64-meta.c \ base64url-encode.c base64url-decode.c base64url-meta.c \ @@ -223,7 +225,7 @@ hogweed_SOURCES = sexp.c sexp-format.c \ OPT_SOURCES = fat-arm.c fat-arm64.c fat-ppc.c fat-s390x.c fat-x86_64.c mini-gmp.c -HEADERS = aes.h arcfour.h arctwo.h asn1.h blowfish.h \ +HEADERS = aes.h arcfour.h arctwo.h asn1.h blowfish.h balloon.h \ base16.h base64.h bignum.h buffer.h camellia.h cast128.h \ cbc.h ccm.h cfb.h chacha.h chacha-poly1305.h ctr.h \ curve25519.h curve448.h des.h dsa.h dsa-compat.h eax.h \ diff --git a/balloon-sha1.c b/balloon-sha1.c new file mode 100644 index 00000000..71c86e1d --- /dev/null +++ b/balloon-sha1.c @@ -0,0 +1,55 @@ +/* balloon-sha1.c + + Balloon password-hashing algorithm. + + Copyright (C) 2022 Zoltan Fridrich + Copyright (C) 2022 Red Hat, Inc. + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "balloon.h" +#include "sha1.h" + +void +balloon_sha1(size_t s_cost, size_t t_cost, + size_t passwd_length, const uint8_t *passwd, + size_t salt_length, const uint8_t *salt, + uint8_t *scratch, uint8_t *dst) +{ + struct sha1_ctx ctx; + sha1_init(&ctx); + balloon(&ctx, + (nettle_hash_update_func*)sha1_update, + (nettle_hash_digest_func*)sha1_digest, + SHA1_DIGEST_SIZE, s_cost, t_cost, + passwd_length, passwd, salt_length, salt, scratch, dst); +} diff --git a/balloon-sha256.c b/balloon-sha256.c new file mode 100644 index 00000000..fe31a691 --- /dev/null +++ b/balloon-sha256.c @@ -0,0 +1,55 @@ +/* balloon-sha256.c + + Balloon password-hashing algorithm. + + Copyright (C) 2022 Zoltan Fridrich + Copyright (C) 2022 Red Hat, Inc. + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "balloon.h" +#include "sha2.h" + +void +balloon_sha256(size_t s_cost, size_t t_cost, + size_t passwd_length, const uint8_t *passwd, + size_t salt_length, const uint8_t *salt, + uint8_t *scratch, uint8_t *dst) +{ + struct sha256_ctx ctx; + sha256_init(&ctx); + balloon(&ctx, + (nettle_hash_update_func*)sha256_update, + (nettle_hash_digest_func*)sha256_digest, + SHA256_DIGEST_SIZE, s_cost, t_cost, + passwd_length, passwd, salt_length, salt, scratch, dst); +} diff --git a/balloon-sha384.c b/balloon-sha384.c new file mode 100644 index 00000000..68294496 --- /dev/null +++ b/balloon-sha384.c @@ -0,0 +1,55 @@ +/* balloon-sha384.c + + Balloon password-hashing algorithm. + + Copyright (C) 2022 Zoltan Fridrich + Copyright (C) 2022 Red Hat, Inc. + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "balloon.h" +#include "sha2.h" + +void +balloon_sha384(size_t s_cost, size_t t_cost, + size_t passwd_length, const uint8_t *passwd, + size_t salt_length, const uint8_t *salt, + uint8_t *scratch, uint8_t *dst) +{ + struct sha384_ctx ctx; + sha384_init(&ctx); + balloon(&ctx, + (nettle_hash_update_func*)sha384_update, + (nettle_hash_digest_func*)sha384_digest, + SHA384_DIGEST_SIZE, s_cost, t_cost, + passwd_length, passwd, salt_length, salt, scratch, dst); +} diff --git a/balloon-sha512.c b/balloon-sha512.c new file mode 100644 index 00000000..f19f8aa0 --- /dev/null +++ b/balloon-sha512.c @@ -0,0 +1,55 @@ +/* balloon-sha512.c + + Balloon password-hashing algorithm. + + Copyright (C) 2022 Zoltan Fridrich + Copyright (C) 2022 Red Hat, Inc. + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "balloon.h" +#include "sha2.h" + +void +balloon_sha512(size_t s_cost, size_t t_cost, + size_t passwd_length, const uint8_t *passwd, + size_t salt_length, const uint8_t *salt, + uint8_t *scratch, uint8_t *dst) +{ + struct sha512_ctx ctx; + sha512_init(&ctx); + balloon(&ctx, + (nettle_hash_update_func*)sha512_update, + (nettle_hash_digest_func*)sha512_digest, + SHA512_DIGEST_SIZE, s_cost, t_cost, + passwd_length, passwd, salt_length, salt, scratch, dst); +} diff --git a/balloon.c b/balloon.c new file mode 100644 index 00000000..c744160a --- /dev/null +++ b/balloon.c @@ -0,0 +1,149 @@ +/* balloon.c + + Balloon password-hashing algorithm. + + Copyright (C) 2022 Zoltan Fridrich + Copyright (C) 2022 Red Hat, Inc. + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +/* For a description of the algorithm, see: + * Boneh, D., Corrigan-Gibbs, H., Schechter, S. (2017, May 12). Balloon Hashing: + * A Memory-Hard Function Providing Provable Protection Against Sequential Attacks. + * Retrieved Sep 1, 2022, from https://eprint.iacr.org/2016/027.pdf + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include <string.h> + +#include "balloon.h" +#include "macros.h" + +#define DELTA 3 + +static void +hash(void *ctx, + nettle_hash_update_func *update, + nettle_hash_digest_func *digest, + size_t digest_size, + uint64_t cnt, + size_t a_len, const uint8_t *a, + size_t b_len, const uint8_t *b, + uint8_t *dst) +{ + uint8_t tmp[8]; + LE_WRITE_UINT64(tmp, cnt); + update(ctx, sizeof(tmp), tmp); + if (a && a_len) + update(ctx, a_len, a); + if (b && b_len) + update(ctx, b_len, b); + digest(ctx, digest_size, dst); +} + +static void +hash_ints(void *ctx, + nettle_hash_update_func *update, + nettle_hash_digest_func *digest, + size_t digest_size, + uint64_t i, uint64_t j, uint64_t k, + uint8_t *dst) +{ + uint8_t tmp[24]; + LE_WRITE_UINT64(tmp, i); + LE_WRITE_UINT64(tmp + 8, j); + LE_WRITE_UINT64(tmp + 16, k); + update(ctx, sizeof(tmp), tmp); + digest(ctx, digest_size, dst); +} + +/* Takes length bytes long big number stored + * in little endian format and computes modulus + */ +static size_t +block_to_int(size_t length, const uint8_t *block, size_t mod) +{ + size_t i = length, r = 0; + while (i--) + { + r = (r << 8) + block[i]; + r %= mod; + } + return r; +} + +void +balloon(void *hash_ctx, + nettle_hash_update_func *update, + nettle_hash_digest_func *digest, + size_t digest_size, size_t s_cost, size_t t_cost, + size_t passwd_length, const uint8_t *passwd, + size_t salt_length, const uint8_t *salt, + uint8_t *scratch, uint8_t *dst) +{ + const size_t BS = digest_size; + uint8_t *block = scratch; + uint8_t *buf = scratch + BS; + size_t i, j, k, cnt = 0; + + hash(hash_ctx, update, digest, digest_size, + cnt++, passwd_length, passwd, salt_length, salt, buf); + for (i = 1; i < s_cost; ++i) + hash(hash_ctx, update, digest, digest_size, + cnt++, BS, buf + (i - 1) * BS, 0, NULL, buf + i * BS); + + for (i = 0; i < t_cost; ++i) + { + for (j = 0; j < s_cost; ++j) + { + hash(hash_ctx, update, digest, digest_size, + cnt++, BS, buf + (j ? j - 1 : s_cost - 1) * BS, + BS, buf + j * BS, buf + j * BS); + for (k = 0; k < DELTA; ++k) + { + hash_ints(hash_ctx, update, digest, digest_size, i, j, k, block); + hash(hash_ctx, update, digest, digest_size, + cnt++, salt_length, salt, BS, block, block); + hash(hash_ctx, update, digest, digest_size, + cnt++, BS, buf + j * BS, + BS, buf + block_to_int(BS, block, s_cost) * BS, + buf + j * BS); + } + } + } + memcpy(dst, buf + (s_cost - 1) * BS, BS); +} + +size_t +balloon_itch(size_t digest_size, size_t s_cost) +{ + return (s_cost + 1) * digest_size; +} diff --git a/balloon.h b/balloon.h new file mode 100644 index 00000000..9c021925 --- /dev/null +++ b/balloon.h @@ -0,0 +1,98 @@ +/* balloon.h + + Balloon password-hashing algorithm. + + Copyright (C) 2022 Zoltan Fridrich + Copyright (C) 2022 Red Hat, Inc. + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +/* For a description of the algorithm, see: + * Boneh, D., Corrigan-Gibbs, H., Schechter, S. (2017, May 12). Balloon Hashing: + * A Memory-Hard Function Providing Provable Protection Against Sequential Attacks. + * Retrieved Sep 1, 2022, from https://eprint.iacr.org/2016/027.pdf + */ + +#ifndef NETTLE_BALLOON_H_INCLUDED +#define NETTLE_BALLOON_H_INCLUDED + +#include "nettle-types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Name mangling */ +#define balloon nettle_balloon +#define balloon_itch nettle_balloon_itch +#define balloon_sha1 nettle_balloon_sha1 +#define balloon_sha256 nettle_balloon_sha256 +#define balloon_sha384 nettle_balloon_sha384 +#define balloon_sha512 nettle_balloon_sha512 + +void +balloon(void *hash_ctx, + nettle_hash_update_func *update, + nettle_hash_digest_func *digest, + size_t digest_size, size_t s_cost, size_t t_cost, + size_t passwd_length, const uint8_t *passwd, + size_t salt_length, const uint8_t *salt, + uint8_t *scratch, uint8_t *dst); + +size_t +balloon_itch(size_t digest_size, size_t s_cost); + +void +balloon_sha1(size_t s_cost, size_t t_cost, + size_t passwd_length, const uint8_t *passwd, + size_t salt_length, const uint8_t *salt, + uint8_t *scratch, uint8_t *dst); + +void +balloon_sha256(size_t s_cost, size_t t_cost, + size_t passwd_length, const uint8_t *passwd, + size_t salt_length, const uint8_t *salt, + uint8_t *scratch, uint8_t *dst); + +void +balloon_sha384(size_t s_cost, size_t t_cost, + size_t passwd_length, const uint8_t *passwd, + size_t salt_length, const uint8_t *salt, + uint8_t *scratch, uint8_t *dst); + +void +balloon_sha512(size_t s_cost, size_t t_cost, + size_t passwd_length, const uint8_t *passwd, + size_t salt_length, const uint8_t *salt, + uint8_t *scratch, uint8_t *dst); + +#ifdef __cplusplus +} +#endif + +#endif /* NETTLE_BALLOON_H_INCLUDED */ @@ -1153,138 +1153,145 @@ output_point (const struct ecc_curve *ecc, } static void -output_modulo (const char *limb_name, const char *size_name, const mpz_t x, - unsigned size, unsigned bits_per_limb) +string_toupper (char *buf, size_t size, const char *s) { - mpz_t mod; - unsigned bits; - - mpz_init (mod); - - mpz_setbit (mod, bits_per_limb * size); - mpz_mod (mod, mod, x); - - bits = mpz_sizeinbase (mod, 2); - output_bignum (limb_name, mod, size, bits_per_limb); - printf ("#define %s %u\n", size_name, - (bits + bits_per_limb - 1) / bits_per_limb); - - mpz_clear (mod); + size_t i; + for (i = 0; i < size; i++) + { + buf[i] = toupper ((int)s[i]); + if (!buf[i]) + return; + } + fprintf (stderr, "string '%s' too large for buffer of size %u.\n", + s, (unsigned) size); + abort(); } static void -output_curve (const struct ecc_curve *ecc, unsigned bits_per_limb) +output_modulo (const char *name, const mpz_t x, + unsigned size, unsigned bits_per_limb) { - unsigned limb_size = (ecc->bit_size + bits_per_limb - 1)/bits_per_limb; - unsigned i; - unsigned qbits; - int redc_limbs; + unsigned bit_size; + int shift; + char buf[20]; mpz_t t; - mpz_t z; - mpz_init (t); - mpz_init (z); + snprintf (buf, sizeof (buf), "ecc_%s", name); + output_bignum (buf, x, size, bits_per_limb); - printf ("/* For NULL. */\n#include <stddef.h>\n"); + mpz_init (t); - printf ("#define ECC_LIMB_SIZE %u\n", limb_size); - printf ("#define ECC_PIPPENGER_K %u\n", ecc->pippenger_k); - printf ("#define ECC_PIPPENGER_C %u\n", ecc->pippenger_c); + mpz_setbit (t, bits_per_limb * size); + mpz_mod (t, t, x); - output_bignum ("ecc_p", ecc->p, limb_size, bits_per_limb); - output_bignum ("ecc_b", ecc->b, limb_size, bits_per_limb); - output_bignum ("ecc_q", ecc->q, limb_size, bits_per_limb); + snprintf (buf, sizeof (buf), "ecc_Bmod%s", name); + output_bignum (buf, t, size, bits_per_limb); - output_modulo ("ecc_Bmodp", "ECC_BMODP_SIZE", - ecc->p, limb_size, bits_per_limb); - output_modulo ("ecc_Bmodq", "ECC_BMODQ_SIZE", ecc->q, limb_size, bits_per_limb); + string_toupper (buf, sizeof (buf), name); + printf ("#define ECC_BMOD%s_SIZE %u\n", buf, + (mpz_sizeinbase (t, 2) + bits_per_limb - 1) / bits_per_limb); - qbits = mpz_sizeinbase (ecc->q, 2); - if (qbits < ecc->bit_size) + bit_size = mpz_sizeinbase (x, 2); + + shift = size * bits_per_limb - bit_size; + assert (shift >= 0); + if (shift > 0) { - /* for curve25519, with q = 2^k + q', with a much smaller q' */ - unsigned mbits; - unsigned shift; + mpz_set_ui (t, 0); + mpz_setbit (t, size * bits_per_limb); + mpz_submul_ui (t, x, 2); - /* Shift to align the one bit at B */ - shift = bits_per_limb * limb_size + 1 - qbits; - - mpz_set (t, ecc->q); - mpz_clrbit (t, qbits-1); - mbits = mpz_sizeinbase (t, 2); + snprintf (buf, sizeof (buf), "ecc_Bm2%s", name); + output_bignum (buf, t, size, bits_per_limb); - /* The shifted value must be a limb smaller than q. */ - if (mbits + shift + bits_per_limb <= qbits) + if (bit_size == 253) { - /* q of the form 2^k + q', with q' a limb smaller */ - mpz_mul_2exp (t, t, shift); - output_bignum ("ecc_mBmodq_shifted", t, limb_size, bits_per_limb); - } - } + /* For curve25519, with q = 2^k + q', with a much smaller q' */ + unsigned mbits; + unsigned shift; - if (ecc->bit_size < limb_size * bits_per_limb) - { - int shift; + /* Shift to align the one bit at B */ + shift = bits_per_limb * size + 1 - bit_size; - mpz_set_ui (t, 0); - mpz_setbit (t, limb_size * bits_per_limb); - mpz_submul_ui (t, ecc->p, 2); - output_bignum ("ecc_Bm2p", t, limb_size, bits_per_limb); + mpz_set (t, x); + mpz_clrbit (t, bit_size-1); + mbits = mpz_sizeinbase (t, 2); - mpz_set_ui (t, 0); - mpz_setbit (t, ecc->bit_size); - mpz_sub (t, t, ecc->p); - output_bignum ("ecc_Bmodp_shifted", t, limb_size, bits_per_limb); + /* The shifted value must be a limb smaller than q. */ + assert (mbits + shift + bits_per_limb <= bit_size); - shift = limb_size * bits_per_limb - ecc->bit_size; - assert (shift > 0); + /* q of the form 2^k + q', with q' a limb smaller */ + mpz_mul_2exp (t, t, shift); + snprintf (buf, sizeof (buf), "ecc_mBmod%s_shifted", name); - /* Check condition for reducing hi limbs. If s is the - normalization shift and n is the bit size (so that s + n - = limb_size * bite_per_limb), then we need + output_bignum (buf, t, size, bits_per_limb); + } + else + { + mpz_set_ui (t, 0); + mpz_setbit (t, bit_size); + mpz_sub (t, t, x); - (2^n - 1) + (2^s - 1) (2^n - p) < 2p + snprintf (buf, sizeof (buf), "ecc_Bmod%s_shifted", name); + output_bignum (buf, t, size, bits_per_limb); - or equivalently, + /* Check condition for reducing hi limbs. If s is the + normalization shift and n is the bit size (so that s + n + = limb_size * bits_per_limb), then we need - 2^s (2^n - p) <= p + (2^n - 1) + (2^s - 1) (2^n - p) < 2p - To a allow a carry limb to be added in at the same time, - substitute s+1 for s. - */ - /* FIXME: For ecdsa verify, we actually need the stricter - inequality < 2 q. */ - mpz_mul_2exp (t, t, shift + 1); - if (mpz_cmp (t, ecc->p) > 0) - { - fprintf (stderr, "Reduction condition failed for %u-bit curve.\n", - ecc->bit_size); - exit (EXIT_FAILURE); + or equivalently, + + 2^s (2^n - p) <= p + + To a allow a carry limb to be added in at the same time, + substitute s+1 for s. + */ + /* FIXME: For ecdsa verify, we actually need the stricter + inequality < 2 q. */ + mpz_mul_2exp (t, t, shift + 1); + if (mpz_cmp (t, x) > 0) + { + fprintf (stderr, "Reduction condition failed for %u-bit %s.\n", + bit_size, name); + exit (EXIT_FAILURE); + } } } else { - printf ("#define ecc_Bmodp_shifted ecc_Bmodp\n"); - printf ("#define ecc_Bm2p ecc_Bmodp\n"); + printf ("#define ecc_Bm2%s ecc_Bmod%s\n", name, name); + printf ("#define ecc_Bmod%s_shifted ecc_Bmod%s\n", name, name); } - if (qbits < limb_size * bits_per_limb) - { - mpz_set_ui (t, 0); - mpz_setbit (t, limb_size * bits_per_limb); - mpz_submul_ui (t, ecc->q, 2); - output_bignum ("ecc_Bm2q", t, limb_size, bits_per_limb); + mpz_clear (t); +} + +static void +output_curve (const struct ecc_curve *ecc, unsigned bits_per_limb) +{ + unsigned limb_size = (ecc->bit_size + bits_per_limb - 1)/bits_per_limb; + unsigned i; + unsigned qbits; + int redc_limbs; + mpz_t t; + mpz_t z; + + mpz_init (t); + mpz_init (z); + + printf ("/* For NULL. */\n#include <stddef.h>\n"); + + printf ("#define ECC_LIMB_SIZE %u\n", limb_size); + printf ("#define ECC_PIPPENGER_K %u\n", ecc->pippenger_k); + printf ("#define ECC_PIPPENGER_C %u\n", ecc->pippenger_c); + + output_modulo ("p", ecc->p, limb_size, bits_per_limb); + output_modulo ("q", ecc->q, limb_size, bits_per_limb); + + output_bignum ("ecc_b", ecc->b, limb_size, bits_per_limb); - mpz_set_ui (t, 0); - mpz_setbit (t, qbits); - mpz_sub (t, t, ecc->q); - output_bignum ("ecc_Bmodq_shifted", t, limb_size, bits_per_limb); - } - else - { - printf ("#define ecc_Bmodq_shifted ecc_Bmodq\n"); - printf ("#define ecc_Bm2q ecc_Bmodq\n"); - } mpz_add_ui (t, ecc->p, 1); mpz_fdiv_q_2exp (t, t, 1); output_bignum ("ecc_pp1h", t, limb_size, bits_per_limb); diff --git a/testsuite/.gitignore b/testsuite/.gitignore index 309464d6..8c91d1af 100644 --- a/testsuite/.gitignore +++ b/testsuite/.gitignore @@ -4,6 +4,7 @@ /aes-keywrap-test /arcfour-test /arctwo-test +/balloon-test /base16-test /base64-test /bignum-test diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in index 05442595..025ab72d 100644 --- a/testsuite/Makefile.in +++ b/testsuite/Makefile.in @@ -11,7 +11,7 @@ PRE_CPPFLAGS = -I.. -I$(top_srcdir) PRE_LDFLAGS = -L.. TS_NETTLE_SOURCES = aes-test.c aes-keywrap-test.c arcfour-test.c arctwo-test.c \ - blowfish-test.c bcrypt-test.c cast128-test.c \ + balloon-test.c blowfish-test.c bcrypt-test.c cast128-test.c \ base16-test.c base64-test.c \ camellia-test.c chacha-test.c \ cnd-memcpy-test.c \ diff --git a/testsuite/balloon-test.c b/testsuite/balloon-test.c new file mode 100644 index 00000000..ad63c7a0 --- /dev/null +++ b/testsuite/balloon-test.c @@ -0,0 +1,135 @@ +/* balloon-test.c + + Copyright (C) 2022 Zoltan Fridrich + Copyright (C) 2022 Red Hat, Inc. + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#include "testutils.h" +#include "balloon.h" + +static void +test_balloon(const struct nettle_hash *alg, + size_t password_len, const char *password, + size_t salt_len, const char *salt, + unsigned s_cost, unsigned t_cost, + const struct tstring *expected) +{ + void *ctx = xalloc(alg->context_size); + uint8_t *buf = xalloc(balloon_itch(alg->digest_size, s_cost)); + + alg->init(ctx); + balloon(ctx, alg->update, alg->digest, alg->digest_size, + s_cost, t_cost, password_len, (const uint8_t *)password, + salt_len, (const uint8_t *)salt, buf, buf); + + if (!MEMEQ(alg->digest_size, buf, expected->data)) + { + fprintf(stderr, "test_balloon: result doesn't match the expectation:"); + fprintf(stderr, "\nOutput: "); + print_hex(alg->digest_size, buf); + fprintf(stderr, "\nExpected:"); + tstring_print_hex(expected); + fprintf(stderr, "\n"); + FAIL(); + } + + free(ctx); + free(buf); +} + +static void +test_balloon_sha(const struct nettle_hash *alg, + size_t password_len, const char *password, + size_t salt_len, const char *salt, + unsigned s_cost, unsigned t_cost, + const struct tstring *expected) +{ + uint8_t *buf = xalloc(balloon_itch(alg->digest_size, s_cost)); + + if (alg == &nettle_sha1) + balloon_sha1(s_cost, t_cost, password_len, (const uint8_t *)password, + salt_len, (const uint8_t *)salt, buf, buf); + else if (alg == &nettle_sha256) + balloon_sha256(s_cost, t_cost, password_len, (const uint8_t *)password, + salt_len, (const uint8_t *)salt, buf, buf); + else if (alg == &nettle_sha384) + balloon_sha384(s_cost, t_cost, password_len, (const uint8_t *)password, + salt_len, (const uint8_t *)salt, buf, buf); + else if (alg == &nettle_sha512) + balloon_sha512(s_cost, t_cost, password_len, (const uint8_t *)password, + salt_len, (const uint8_t *)salt, buf, buf); + else + { + fprintf(stderr, "test_balloon_sha: bad test\n"); + FAIL(); + } + + if (!MEMEQ(alg->digest_size, buf, expected->data)) + { + fprintf(stderr, "test_balloon_sha: result doesn't match the expectation:"); + fprintf(stderr, "\nOutput: "); + print_hex(alg->digest_size, buf); + fprintf(stderr, "\nExpected:"); + tstring_print_hex(expected); + fprintf(stderr, "\n"); + FAIL(); + } + + free(buf); +} + +/* Test vectors are taken from: + * <https://github.com/nachonavarro/balloon-hashing> + * <https://github.com/RustCrypto/password-hashes/tree/master/balloon-hash> + */ +void +test_main(void) +{ + test_balloon(&nettle_sha256, 8, "hunter42", 11, "examplesalt", 1024, 3, + SHEX("716043dff777b44aa7b88dcbab12c078abecfac9d289c5b5195967aa63440dfb")); + test_balloon(&nettle_sha256, 0, "", 4, "salt", 3, 3, + SHEX("5f02f8206f9cd212485c6bdf85527b698956701ad0852106f94b94ee94577378")); + test_balloon(&nettle_sha256, 8, "password", 0, "", 3, 3, + SHEX("20aa99d7fe3f4df4bd98c655c5480ec98b143107a331fd491deda885c4d6a6cc")); + test_balloon(&nettle_sha256, 1, "", 1, "", 3, 3, + SHEX("4fc7e302ffa29ae0eac31166cee7a552d1d71135f4e0da66486fb68a749b73a4")); + test_balloon(&nettle_sha256, 8, "password", 4, "salt", 1, 1, + SHEX("eefda4a8a75b461fa389c1dcfaf3e9dfacbc26f81f22e6f280d15cc18c417545")); + + test_balloon_sha(&nettle_sha1, 8, "password", 4, "salt", 3, 3, + SHEX("99393c091fdd3136f85864099ec49a439dcacc21")); + test_balloon_sha(&nettle_sha256, 8, "password", 4, "salt", 3, 3, + SHEX("a4df347f5a312e8b2b14c32164f61a81758c807f1bdcda44f4930e2b80ab2154")); + test_balloon_sha(&nettle_sha384, 8, "password", 4, "salt", 3, 3, + SHEX("78da235f7d0f84aba98b50a432fa6c8f7f3ecb7ea0858cfb316c7e5356aae6c8" + "d7e7b3924c54c4ed71a3d0d68cb0ad68")); + test_balloon_sha(&nettle_sha512, 8, "password", 4, "salt", 3, 3, + SHEX("9baf289dfa42990f4b189d96d4ede0f2610ba71fb644169427829d696f6866d8" + "7af41eb68f9e14fd4b1f1a7ce4832f1ed6117c16e8eae753f9e1d054a7c0a7eb")); +} |