Make the bn_rand_interval() API a bit more ergonomic
authortb <tb@openbsd.org>
Thu, 3 Aug 2023 18:53:55 +0000 (18:53 +0000)
committertb <tb@openbsd.org>
Thu, 3 Aug 2023 18:53:55 +0000 (18:53 +0000)
Provide bn_rand_in_range() which is a slightly tweaked version of what was
previously called bn_rand_range().

The way bn_rand_range() is called in libcrypto, the lower bound is always
expressible as a word. In fact, most of the time it is 1, the DH code uses
a 2, the MR tests in BPSW use 3 and an exceptinally high number appears in
the Tonelli-Shanks implementation where we use 32. Converting these lower
bounds to BIGNUMs on the call site is annoying so let bn_rand_interval()
do that internally and route that through bn_rand_in_range(). This way we
can avoid using BN_sub_word().

Adjust the bn_isqrt() test to use bn_rand_in_range() since that's the
only caller that uses actual BIGNUMs as lower bounds.

ok jsing

lib/libcrypto/bn/bn_bpsw.c
lib/libcrypto/bn/bn_local.h
lib/libcrypto/bn/bn_mod_sqrt.c
lib/libcrypto/bn/bn_rand.c
lib/libcrypto/dh/dh_key.c
lib/libcrypto/dsa/dsa_key.c
lib/libcrypto/dsa/dsa_ossl.c
lib/libcrypto/ec/ec_key.c
lib/libcrypto/ec/ecp_smpl.c
lib/libcrypto/ecdsa/ecdsa.c
regress/lib/libcrypto/bn/bn_isqrt.c

index 82a4e87..14f2800 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: bn_bpsw.c,v 1.10 2023/05/10 21:05:24 tb Exp $ */
+/*     $OpenBSD: bn_bpsw.c,v 1.11 2023/08/03 18:53:55 tb Exp $ */
 /*
  * Copyright (c) 2022 Martin Grenouilloux <martin.grenouilloux@lse.epita.fr>
  * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
@@ -385,7 +385,7 @@ bn_miller_rabin(int *is_pseudoprime, const BIGNUM *n, BN_CTX *ctx,
     size_t rounds)
 {
        BN_MONT_CTX *mctx = NULL;
-       BIGNUM *base, *k, *n_minus_one, *three;
+       BIGNUM *base, *k, *n_minus_one;
        size_t i;
        int s;
        int ret = 0;
@@ -398,8 +398,6 @@ bn_miller_rabin(int *is_pseudoprime, const BIGNUM *n, BN_CTX *ctx,
                goto err;
        if ((n_minus_one = BN_CTX_get(ctx)) == NULL)
                goto err;
-       if ((three = BN_CTX_get(ctx)) == NULL)
-               goto err;
 
        if (BN_is_word(n, 2) || BN_is_word(n, 3)) {
                *is_pseudoprime = 1;
@@ -451,11 +449,8 @@ bn_miller_rabin(int *is_pseudoprime, const BIGNUM *n, BN_CTX *ctx,
         * risk of false positives in BPSW.
         */
 
-       if (!BN_set_word(three, 3))
-               goto err;
-
        for (i = 0; i < rounds; i++) {
-               if (!bn_rand_interval(base, three, n_minus_one))
+               if (!bn_rand_interval(base, 3, n_minus_one))
                        goto err;
 
                if (!bn_fermat(is_pseudoprime, n, n_minus_one, k, s, base, ctx,
index 9447ed4..5b7e852 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: bn_local.h,v 1.32 2023/08/02 08:44:38 tb Exp $ */
+/* $OpenBSD: bn_local.h,v 1.33 2023/08/03 18:53:55 tb Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -274,7 +274,8 @@ void bn_div_rem_words(BN_ULONG h, BN_ULONG l, BN_ULONG d, BN_ULONG *out_q,
     BN_ULONG *out_r);
 
 int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom);
-int bn_rand_interval(BIGNUM *rnd, const BIGNUM *lower_inc, const BIGNUM *upper_exc);
+int bn_rand_in_range(BIGNUM *rnd, const BIGNUM *lower_inc, const BIGNUM *upper_exc);
+int bn_rand_interval(BIGNUM *rnd, BN_ULONG lower_word, const BIGNUM *upper_exc);
 
 void   BN_init(BIGNUM *);
 
index bdd5b2c..280002c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: bn_mod_sqrt.c,v 1.2 2023/07/08 12:21:58 beck Exp $ */
+/*     $OpenBSD: bn_mod_sqrt.c,v 1.3 2023/08/03 18:53:55 tb Exp $ */
 
 /*
  * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
@@ -237,7 +237,7 @@ static int
 bn_mod_sqrt_find_sylow_generator(BIGNUM *out_generator, const BIGNUM *p,
     const BIGNUM *q, BN_CTX *ctx)
 {
-       BIGNUM *n, *p_abs, *thirty_two;
+       BIGNUM *n, *p_abs;
        int i, is_non_residue;
        int ret = 0;
 
@@ -245,8 +245,6 @@ bn_mod_sqrt_find_sylow_generator(BIGNUM *out_generator, const BIGNUM *p,
 
        if ((n = BN_CTX_get(ctx)) == NULL)
                goto err;
-       if ((thirty_two = BN_CTX_get(ctx)) == NULL)
-               goto err;
        if ((p_abs = BN_CTX_get(ctx)) == NULL)
                goto err;
 
@@ -259,14 +257,12 @@ bn_mod_sqrt_find_sylow_generator(BIGNUM *out_generator, const BIGNUM *p,
                        goto found;
        }
 
-       if (!BN_set_word(thirty_two, 32))
-               goto err;
        if (!bn_copy(p_abs, p))
                goto err;
        BN_set_negative(p_abs, 0);
 
        for (i = 0; i < 128; i++) {
-               if (!bn_rand_interval(n, thirty_two, p_abs))
+               if (!bn_rand_interval(n, 32, p_abs))
                        goto err;
                if (!bn_mod_sqrt_n_is_non_residue(&is_non_residue, n, p, ctx))
                        goto err;
index f689134..a5b163c 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: bn_rand.c,v 1.28 2023/07/08 12:21:58 beck Exp $ */
+/* $OpenBSD: bn_rand.c,v 1.29 2023/08/03 18:53:55 tb Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -284,29 +284,46 @@ BN_rand_range(BIGNUM *r, const BIGNUM *range)
 LCRYPTO_ALIAS(BN_rand_range);
 
 int
-bn_rand_interval(BIGNUM *rnd, const BIGNUM *lower_inc, const BIGNUM *upper_exc)
+bn_rand_in_range(BIGNUM *rnd, const BIGNUM *lower_inc, const BIGNUM *upper_exc)
 {
-       BIGNUM *len = NULL;
+       BIGNUM *len;
        int ret = 0;
 
-       if (BN_cmp(lower_inc, upper_exc) >= 0)
-               goto err;
-
        if ((len = BN_new()) == NULL)
                goto err;
-
        if (!BN_sub(len, upper_exc, lower_inc))
                goto err;
-
-       if (!bn_rand_range(0, rnd, len))
+       if (!BN_rand_range(rnd, len))
                goto err;
-
        if (!BN_add(rnd, rnd, lower_inc))
                goto err;
 
        ret = 1;
+
  err:
        BN_free(len);
+
+       return ret;
+}
+
+int
+bn_rand_interval(BIGNUM *rnd, BN_ULONG lower_word, const BIGNUM *upper_exc)
+{
+       BIGNUM *lower_inc = NULL;
+       int ret = 0;
+
+       if ((lower_inc = BN_new()) == NULL)
+               goto err;
+       if (!BN_set_word(lower_inc, lower_word))
+               goto err;
+       if (!bn_rand_in_range(rnd, lower_inc, upper_exc))
+               goto err;
+
+       ret = 1;
+
+ err:
+       BN_free(lower_inc);
+
        return ret;
 }
 
index a4bd689..050d114 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: dh_key.c,v 1.39 2023/07/08 15:29:03 beck Exp $ */
+/* $OpenBSD: dh_key.c,v 1.40 2023/08/03 18:53:55 tb Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -109,7 +109,7 @@ generate_key(DH *dh)
        unsigned l;
        BN_CTX *ctx;
        BN_MONT_CTX *mont = NULL;
-       BIGNUM *pub_key = NULL, *priv_key = NULL, *two = NULL;
+       BIGNUM *pub_key = NULL, *priv_key = NULL;
 
        if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
                DHerror(DH_R_MODULUS_TOO_LARGE);
@@ -139,11 +139,7 @@ generate_key(DH *dh)
 
        if (dh->priv_key == NULL) {
                if (dh->q) {
-                       if ((two = BN_new()) == NULL)
-                               goto err;
-                       if (!BN_add(two, BN_value_one(), BN_value_one()))
-                               goto err;
-                       if (!bn_rand_interval(priv_key, two, dh->q))
+                       if (!bn_rand_interval(priv_key, 2, dh->q))
                                goto err;
                } else {
                        /* secret exponent length */
@@ -169,7 +165,7 @@ generate_key(DH *dh)
        if (dh->priv_key == NULL)
                BN_free(priv_key);
        BN_CTX_free(ctx);
-       BN_free(two);
+
        return ok;
 }
 
index c378707..431748a 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: dsa_key.c,v 1.34 2023/07/08 14:28:15 beck Exp $ */
+/* $OpenBSD: dsa_key.c,v 1.35 2023/08/03 18:53:55 tb Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -95,7 +95,7 @@ dsa_builtin_keygen(DSA *dsa)
        if ((ctx = BN_CTX_new()) == NULL)
                goto err;
 
-       if (!bn_rand_interval(priv_key, BN_value_one(), dsa->q))
+       if (!bn_rand_interval(priv_key, 1, dsa->q))
                goto err;
        if (!BN_mod_exp_ct(pub_key, dsa->g, priv_key, dsa->p, ctx))
                goto err;
index 36b2a63..b92d0b8 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: dsa_ossl.c,v 1.52 2023/07/08 14:28:15 beck Exp $ */
+/* $OpenBSD: dsa_ossl.c,v 1.53 2023/08/03 18:53:55 tb Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -172,7 +172,7 @@ dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
         *
         * Where b is a random value in the range [1, q).
         */
-       if (!bn_rand_interval(b, BN_value_one(), dsa->q))
+       if (!bn_rand_interval(b, 1, dsa->q))
                goto err;
        if (BN_mod_inverse_ct(binv, b, dsa->q, ctx) == NULL)
                goto err;
@@ -261,7 +261,7 @@ dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
            !BN_set_bit(m, q_bits))
                goto err;
 
-       if (!bn_rand_interval(k, BN_value_one(), dsa->q))
+       if (!bn_rand_interval(k, 1, dsa->q))
                goto err;
 
        BN_set_flags(k, BN_FLG_CONSTTIME);
index e5ff189..d9ddd5d 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ec_key.c,v 1.36 2023/07/07 13:54:45 beck Exp $ */
+/* $OpenBSD: ec_key.c,v 1.37 2023/08/03 18:53:56 tb Exp $ */
 /*
  * Written by Nils Larsch for the OpenSSL project.
  */
@@ -269,7 +269,7 @@ ec_key_gen(EC_KEY *eckey)
 
        if ((order = EC_GROUP_get0_order(eckey->group)) == NULL)
                goto err;
-       if (!bn_rand_interval(priv_key, BN_value_one(), order))
+       if (!bn_rand_interval(priv_key, 1, order))
                goto err;
        if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, NULL))
                goto err;
index de1f9a3..018aedf 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ecp_smpl.c,v 1.55 2023/07/26 17:15:25 tb Exp $ */
+/* $OpenBSD: ecp_smpl.c,v 1.56 2023/08/03 18:53:56 tb Exp $ */
 /* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
  * for the OpenSSL project.
  * Includes code written by Bodo Moeller for the OpenSSL project.
@@ -1227,7 +1227,7 @@ ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx)
                goto err;
 
        /* Generate lambda in [1, group->field). */
-       if (!bn_rand_interval(lambda, BN_value_one(), &group->field))
+       if (!bn_rand_interval(lambda, 1, &group->field))
                goto err;
 
        if (group->meth->field_encode != NULL &&
index 1252ab2..8160014 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ecdsa.c,v 1.16 2023/07/28 09:18:10 tb Exp $ */
+/* $OpenBSD: ecdsa.c,v 1.17 2023/08/03 18:53:56 tb Exp $ */
 /* ====================================================================
  * Copyright (c) 2000-2002 The OpenSSL Project.  All rights reserved.
  *
@@ -338,7 +338,7 @@ ecdsa_sign_setup(EC_KEY *key, BN_CTX *in_ctx, BIGNUM **out_kinv, BIGNUM **out_r)
        /* Step 11: repeat until r != 0. */
        do {
                /* Step 3: generate random k. */
-               if (!bn_rand_interval(k, BN_value_one(), order))
+               if (!bn_rand_interval(k, 1, order))
                        goto err;
 
                /*
@@ -472,7 +472,7 @@ ecdsa_compute_s(BIGNUM **out_s, const BIGNUM *e, const BIGNUM *kinv,
                goto err;
        }
 
-       if (!bn_rand_interval(b, BN_value_one(), order)) {
+       if (!bn_rand_interval(b, 1, order)) {
                ECerror(ERR_R_BN_LIB);
                goto err;
        }
index 2663bb7..d8a2d27 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: bn_isqrt.c,v 1.3 2023/03/08 06:28:08 tb Exp $ */
+/*     $OpenBSD: bn_isqrt.c,v 1.4 2023/08/03 18:53:56 tb Exp $ */
 /*
  * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
  *
@@ -194,8 +194,8 @@ isqrt_test(void)
        if (!BN_set_bit(upper, UPPER_BITS))
                errx(1, "BN_set_bit(upper, %d)", UPPER_BITS);
 
-       if (!bn_rand_interval(n, lower, upper))
-               errx(1, "bn_rand_interval n");
+       if (!bn_rand_in_range(n, lower, upper))
+               errx(1, "bn_rand_in_range n");
 
        /* n_sqr = n^2 */
        if (!BN_sqr(n_sqr, n, ctx))
@@ -246,8 +246,8 @@ isqrt_test(void)
         */
 
        for (i = 0; i < N_TESTS; i++) {
-               if (!bn_rand_interval(testcase, n_sqr, upper))
-                       errx(1, "bn_rand_interval testcase");
+               if (!bn_rand_in_range(testcase, n_sqr, upper))
+                       errx(1, "bn_rand_in_range testcase");
 
                if (!bn_isqrt(isqrt, &is_perfect_square, testcase, ctx))
                        errx(1, "bn_isqrt testcase");