text: /*
   * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
   *
   * Licensed under the Apache License 2.0 (the "License").  You may not use
   * this file except in compliance with the License.  You can obtain a copy
   * in the file LICENSE in the source distribution or at
   * https://www.openssl.org/source/license.html
   */
  
  #include <stdio.h>
  #include <time.h>
  #include "internal/cryptlib.h"
  #include "internal/rand_int.h"
  #include "bn_lcl.h"
  #include <openssl/rand.h>
  #include <openssl/sha.h>
  #include <openssl/evp.h>
  
  typedef enum bnrand_flag_e {
      NORMAL, TESTING, PRIVATE
  } BNRAND_FLAG;
  
  static int bnrand(BNRAND_FLAG flag, BIGNUM *rnd, int bits, int top, int bottom,
                    BN_CTX *ctx)
  {
      unsigned char *buf = NULL;
      int b, ret = 0, bit, bytes, mask;
      OPENSSL_CTX *libctx = bn_get_lib_ctx(ctx);
  
      if (bits == 0) {
          if (top != BN_RAND_TOP_ANY || bottom != BN_RAND_BOTTOM_ANY)
              goto toosmall;
          BN_zero(rnd);
          return 1;
      }
      if (bits < 0 || (bits == 1 && top > 0))
          goto toosmall;
  
      bytes = (bits + 7) / 8;
      bit = (bits - 1) % 8;
      mask = 0xff << (bit + 1);
  
      buf = OPENSSL_malloc(bytes);
      if (buf == NULL) {
          BNerr(BN_F_BNRAND, ERR_R_MALLOC_FAILURE);
          goto err;
      }
  
      /* make a random number and set the top and bottom bits */
      b = flag == NORMAL ? rand_bytes_ex(libctx, buf, bytes)
                         : rand_priv_bytes_ex(libctx, buf, bytes);
      if (b <= 0)
          goto err;
  
      if (flag == TESTING) {
          /*
           * generate patterns that are more likely to trigger BN library bugs
           */
          int i;
          unsigned char c;
  
          for (i = 0; i < bytes; i++) {
              if (rand_bytes_ex(libctx, &c, 1) <= 0)
                  goto err;
              if (c >= 128 && i > 0)
                  buf[i] = buf[i - 1];
              else if (c < 42)
                  buf[i] = 0;
              else if (c < 84)
                  buf[i] = 255;
          }
      }
  
      if (top >= 0) {
          if (top) {
              if (bit == 0) {
                  buf[0] = 1;
                  buf[1] |= 0x80;
              } else {
                  buf[0] |= (3 << (bit - 1));
              }
          } else {
              buf[0] |= (1 << bit);
          }
      }
      buf[0] &= ~mask;
      if (bottom)                 /* set bottom bit if requested */
          buf[bytes - 1] |= 1;
      if (!BN_bin2bn(buf, bytes, rnd))
          goto err;
      ret = 1;
   err:
      OPENSSL_clear_free(buf, bytes);
      bn_check_top(rnd);
      return ret;
  
  toosmall:
      BNerr(BN_F_BNRAND, BN_R_BITS_TOO_SMALL);
      return 0;
  }
  
  int BN_rand_ex(BIGNUM *rnd, int bits, int top, int bottom, BN_CTX *ctx)
  {
      return bnrand(NORMAL, rnd, bits, top, bottom, ctx);
  }
  #ifndef FIPS_MODE
  int BN_rand(BIGNUM *rnd, int bits, int top, int bottom)
  {
      return bnrand(NORMAL, rnd, bits, top, bottom, NULL);
  }
  
  int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom)
  {
      return bnrand(TESTING, rnd, bits, top, bottom, NULL);
  }
  #endif
  
  int BN_priv_rand_ex(BIGNUM *rnd, int bits, int top, int bottom, BN_CTX *ctx)
  {
      return bnrand(PRIVATE, rnd, bits, top, bottom, ctx);
  }
  
  #ifndef FIPS_MODE
  int BN_priv_rand(BIGNUM *rnd, int bits, int top, int bottom)
  {
      return bnrand(PRIVATE, rnd, bits, top, bottom, NULL);
  }
  #endif
  
  /* random number r:  0 <= r < range */
  static int bnrand_range(BNRAND_FLAG flag, BIGNUM *r, const BIGNUM *range,
                          BN_CTX *ctx)
  {
      int n;
      int count = 100;
  
      if (range->neg || BN_is_zero(range)) {
          BNerr(BN_F_BNRAND_RANGE, BN_R_INVALID_RANGE);
          return 0;
      }
  
      n = BN_num_bits(range);     /* n > 0 */
  
      /* BN_is_bit_set(range, n - 1) always holds */
  
      if (n == 1)
          BN_zero(r);
      else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) {
          /*
           * range = 100..._2, so 3*range (= 11..._2) is exactly one bit longer
           * than range
           */
          do {
              if (!bnrand(flag, r, n + 1, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY,
                          ctx))
                  return 0;
  
              /*
               * If r < 3*range, use r := r MOD range (which is either r, r -
               * range, or r - 2*range). Otherwise, iterate once more. Since
               * 3*range = 11..._2, each iteration succeeds with probability >=
               * .75.
               */
              if (BN_cmp(r, range) >= 0) {
                  if (!BN_sub(r, r, range))
                      return 0;
                  if (BN_cmp(r, range) >= 0)
                      if (!BN_sub(r, r, range))
                          return 0;
              }
  
              if (!--count) {
                  BNerr(BN_F_BNRAND_RANGE, BN_R_TOO_MANY_ITERATIONS);
                  return 0;
              }
  
          }
          while (BN_cmp(r, range) >= 0);
      } else {
          do {
              /* range = 11..._2  or  range = 101..._2 */
              if (!bnrand(flag, r, n, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, ctx))
                  return 0;
  
              if (!--count) {
                  BNerr(BN_F_BNRAND_RANGE, BN_R_TOO_MANY_ITERATIONS);
                  return 0;
              }
          }
          while (BN_cmp(r, range) >= 0);
      }
  
      bn_check_top(r);
      return 1;
  }
  
  int BN_rand_range_ex(BIGNUM *r, const BIGNUM *range, BN_CTX *ctx)
  {
      return bnrand_range(NORMAL, r, range, ctx);
  }
  
  #ifndef FIPS_MODE
  int BN_rand_range(BIGNUM *r, const BIGNUM *range)
  {
      return bnrand_range(NORMAL, r, range, NULL);
  }
  #endif
  
  int BN_priv_rand_range_ex(BIGNUM *r, const BIGNUM *range, BN_CTX *ctx)
  {
      return bnrand_range(PRIVATE, r, range, ctx);
  }
  
  #ifndef FIPS_MODE
  int BN_priv_rand_range(BIGNUM *r, const BIGNUM *range)
  {
      return bnrand_range(PRIVATE, r, range, NULL);
  }
  
  int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom)
  {
      return BN_rand(rnd, bits, top, bottom);
  }
  
  int BN_pseudo_rand_range(BIGNUM *r, const BIGNUM *range)
  {
      return BN_rand_range(r, range);
  }
  #endif
  
  /*
   * BN_generate_dsa_nonce generates a random number 0 <= out < range. Unlike
   * BN_rand_range, it also includes the contents of |priv| and |message| in
   * the generation so that an RNG failure isn't fatal as long as |priv|
   * remains secret. This is intended for use in DSA and ECDSA where an RNG
   * weakness leads directly to private key exposure unless this function is
   * used.
   */
  int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range,
                            const BIGNUM *priv, const unsigned char *message,
                            size_t message_len, BN_CTX *ctx)
  {
      EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
      /*
       * We use 512 bits of random data per iteration to ensure that we have at
       * least |range| bits of randomness.
       */
      unsigned char random_bytes[64];
      unsigned char digest[SHA512_DIGEST_LENGTH];
      unsigned done, todo;
      /* We generate |range|+8 bytes of random output. */
      const unsigned num_k_bytes = BN_num_bytes(range) + 8;
      unsigned char private_bytes[96];
      unsigned char *k_bytes = NULL;
      int ret = 0;
      EVP_MD *md = NULL;
      OPENSSL_CTX *libctx = bn_get_lib_ctx(ctx);
  
      if (mdctx == NULL)
          goto err;
  
      k_bytes = OPENSSL_malloc(num_k_bytes);
      if (k_bytes == NULL)
          goto err;
  
      /* We copy |priv| into a local buffer to avoid exposing its length. */
      todo = sizeof(priv->d[0]) * priv->top;
      if (todo > sizeof(private_bytes)) {
          /*
           * No reasonable DSA or ECDSA key should have a private key this
           * large and we don't handle this case in order to avoid leaking the
           * length of the private key.
           */
          BNerr(BN_F_BN_GENERATE_DSA_NONCE, BN_R_PRIVATE_KEY_TOO_LARGE);
          goto err;
      }
      memcpy(private_bytes, priv->d, todo);
      memset(private_bytes + todo, 0, sizeof(private_bytes) - todo);
  
      md = EVP_MD_fetch(libctx, "SHA512", NULL);
      if (md == NULL) {
          BNerr(BN_F_BN_GENERATE_DSA_NONCE, BN_R_NO_SUITABLE_DIGEST);
          goto err;
      }
      for (done = 0; done < num_k_bytes;) {
          if (!rand_priv_bytes_ex(libctx, random_bytes, sizeof(random_bytes)))
              goto err;
  
          if (!EVP_DigestInit_ex(mdctx, md, NULL)
                  || !EVP_DigestUpdate(mdctx, &done, sizeof(done))
                  || !EVP_DigestUpdate(mdctx, private_bytes,
                                       sizeof(private_bytes))
                  || !EVP_DigestUpdate(mdctx, message, message_len)
                  || !EVP_DigestUpdate(mdctx, random_bytes, sizeof(random_bytes))
                  || !EVP_DigestFinal_ex(mdctx, digest, NULL))
              goto err;
  
          todo = num_k_bytes - done;
          if (todo > SHA512_DIGEST_LENGTH)
              todo = SHA512_DIGEST_LENGTH;
          memcpy(k_bytes + done, digest, todo);
          done += todo;
      }
  
      if (!BN_bin2bn(k_bytes, num_k_bytes, out))
          goto err;
      if (BN_mod(out, out, range, ctx) != 1)
          goto err;
      ret = 1;
  
   err:
      EVP_MD_CTX_free(mdctx);
      EVP_MD_meth_free(md);
      OPENSSL_free(k_bytes);
      OPENSSL_cleanse(private_bytes, sizeof(private_bytes));
      return ret;
  }
  