Exemple #1
0
static int check_mod_inverse(int *out_ok, const BIGNUM *a, const BIGNUM *ainv,
                             const BIGNUM *m, int check_reduced, BN_CTX *ctx) {
  BN_CTX_start(ctx);
  BIGNUM *tmp = BN_CTX_get(ctx);
  int ret = tmp != NULL &&
            bn_mul_consttime(tmp, a, ainv, ctx) &&
            bn_div_consttime(NULL, tmp, tmp, m, ctx);
  if (ret) {
    *out_ok = BN_is_one(tmp);
    if (check_reduced && (BN_is_negative(ainv) || BN_cmp(ainv, m) >= 0)) {
      *out_ok = 0;
    }
  }
  BN_CTX_end(ctx);
  return ret;
}
Exemple #2
0
int RSA_check_key(const RSA *key) {
  BIGNUM n, pm1, qm1, lcm, dmp1, dmq1, iqmp_times_q;
  BN_CTX *ctx;
  int ok = 0, has_crt_values;

  if (RSA_is_opaque(key)) {
    // Opaque keys can't be checked.
    return 1;
  }

  if ((key->p != NULL) != (key->q != NULL)) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_ONLY_ONE_OF_P_Q_GIVEN);
    return 0;
  }

  if (!key->n || !key->e) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING);
    return 0;
  }

  if (!key->d || !key->p) {
    // For a public key, or without p and q, there's nothing that can be
    // checked.
    return 1;
  }

  ctx = BN_CTX_new();
  if (ctx == NULL) {
    OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
    return 0;
  }

  BN_init(&n);
  BN_init(&pm1);
  BN_init(&qm1);
  BN_init(&lcm);
  BN_init(&dmp1);
  BN_init(&dmq1);
  BN_init(&iqmp_times_q);

  int d_ok;
  if (!bn_mul_consttime(&n, key->p, key->q, ctx) ||
      // lcm = lcm(p, q)
      !bn_usub_consttime(&pm1, key->p, BN_value_one()) ||
      !bn_usub_consttime(&qm1, key->q, BN_value_one()) ||
      !bn_lcm_consttime(&lcm, &pm1, &qm1, ctx) ||
      // Other implementations use the Euler totient rather than the Carmichael
      // totient, so allow unreduced |key->d|.
      !check_mod_inverse(&d_ok, key->e, key->d, &lcm,
                         0 /* don't require reduced */, ctx)) {
    OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
    goto out;
  }

  if (BN_cmp(&n, key->n) != 0) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_N_NOT_EQUAL_P_Q);
    goto out;
  }

  if (!d_ok) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_D_E_NOT_CONGRUENT_TO_1);
    goto out;
  }

  if (BN_is_negative(key->d) || BN_cmp(key->d, key->n) >= 0) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_D_OUT_OF_RANGE);
    goto out;
  }

  has_crt_values = key->dmp1 != NULL;
  if (has_crt_values != (key->dmq1 != NULL) ||
      has_crt_values != (key->iqmp != NULL)) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_INCONSISTENT_SET_OF_CRT_VALUES);
    goto out;
  }

  if (has_crt_values) {
    int dmp1_ok, dmq1_ok, iqmp_ok;
    if (!check_mod_inverse(&dmp1_ok, key->e, key->dmp1, &pm1,
                           1 /* check reduced */, ctx) ||
        !check_mod_inverse(&dmq1_ok, key->e, key->dmq1, &qm1,
                           1 /* check reduced */, ctx) ||
        !check_mod_inverse(&iqmp_ok, key->q, key->iqmp, key->p,
                           1 /* check reduced */, ctx)) {
      OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
      goto out;
    }

    if (!dmp1_ok || !dmq1_ok || !iqmp_ok) {
      OPENSSL_PUT_ERROR(RSA, RSA_R_CRT_VALUES_INCORRECT);
      goto out;
    }
  }

  ok = 1;

out:
  BN_free(&n);
  BN_free(&pm1);
  BN_free(&qm1);
  BN_free(&lcm);
  BN_free(&dmp1);
  BN_free(&dmq1);
  BN_free(&iqmp_times_q);
  BN_CTX_free(ctx);

  return ok;
}
Exemple #3
0
static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
  assert(ctx != NULL);

  assert(rsa->n != NULL);
  assert(rsa->e != NULL);
  assert(rsa->d != NULL);
  assert(rsa->p != NULL);
  assert(rsa->q != NULL);
  assert(rsa->dmp1 != NULL);
  assert(rsa->dmq1 != NULL);
  assert(rsa->iqmp != NULL);

  BIGNUM *r1, *m1;
  int ret = 0;

  BN_CTX_start(ctx);
  r1 = BN_CTX_get(ctx);
  m1 = BN_CTX_get(ctx);
  if (r1 == NULL ||
      m1 == NULL) {
    goto err;
  }

  if (!freeze_private_key(rsa, ctx)) {
    goto err;
  }

  // Implementing RSA with CRT in constant-time is sensitive to which prime is
  // larger. Canonicalize fields so that |p| is the larger prime.
  const BIGNUM *dmp1 = rsa->dmp1_fixed, *dmq1 = rsa->dmq1_fixed;
  const BN_MONT_CTX *mont_p = rsa->mont_p, *mont_q = rsa->mont_q;
  if (BN_cmp(rsa->p, rsa->q) < 0) {
    mont_p = rsa->mont_q;
    mont_q = rsa->mont_p;
    dmp1 = rsa->dmq1_fixed;
    dmq1 = rsa->dmp1_fixed;
  }

  // Use the minimal-width versions of |n|, |p|, and |q|. Either works, but if
  // someone gives us non-minimal values, these will be slightly more efficient
  // on the non-Montgomery operations.
  const BIGNUM *n = &rsa->mont_n->N;
  const BIGNUM *p = &mont_p->N;
  const BIGNUM *q = &mont_q->N;

  // This is a pre-condition for |mod_montgomery|. It was already checked by the
  // caller.
  assert(BN_ucmp(I, n) < 0);

  if (// |m1| is the result modulo |q|.
      !mod_montgomery(r1, I, q, mont_q, p, ctx) ||
      !BN_mod_exp_mont_consttime(m1, r1, dmq1, q, ctx, mont_q) ||
      // |r0| is the result modulo |p|.
      !mod_montgomery(r1, I, p, mont_p, q, ctx) ||
      !BN_mod_exp_mont_consttime(r0, r1, dmp1, p, ctx, mont_p) ||
      // Compute r0 = r0 - m1 mod p. |p| is the larger prime, so |m1| is already
      // fully reduced mod |p|.
      !bn_mod_sub_consttime(r0, r0, m1, p, ctx) ||
      // r0 = r0 * iqmp mod p. We use Montgomery multiplication to compute this
      // in constant time. |inv_small_mod_large_mont| is in Montgomery form and
      // r0 is not, so the result is taken out of Montgomery form.
      !BN_mod_mul_montgomery(r0, r0, rsa->inv_small_mod_large_mont, mont_p,
                             ctx) ||
      // r0 = r0 * q + m1 gives the final result. Reducing modulo q gives m1, so
      // it is correct mod p. Reducing modulo p gives (r0-m1)*iqmp*q + m1 = r0,
      // so it is correct mod q. Finally, the result is bounded by [m1, n + m1),
      // and the result is at least |m1|, so this must be the unique answer in
      // [0, n).
      !bn_mul_consttime(r0, r0, q, ctx) ||
      !bn_uadd_consttime(r0, r0, m1) ||
      // The result should be bounded by |n|, but fixed-width operations may
      // bound the width slightly higher, so fix it.
      !bn_resize_words(r0, n->width)) {
    goto err;
  }

  ret = 1;

err:
  BN_CTX_end(ctx);
  return ret;
}
Exemple #4
0
int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
  // See FIPS 186-4 appendix B.3. This function implements a generalized version
  // of the FIPS algorithm. |RSA_generate_key_fips| performs additional checks
  // for FIPS-compliant key generation.

  // Always generate RSA keys which are a multiple of 128 bits. Round |bits|
  // down as needed.
  bits &= ~127;

  // Reject excessively small keys.
  if (bits < 256) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
    return 0;
  }

  // Reject excessively large public exponents. Windows CryptoAPI and Go don't
  // support values larger than 32 bits, so match their limits for generating
  // keys. (|check_modulus_and_exponent_sizes| uses a slightly more conservative
  // value, but we don't need to support generating such keys.)
  // https://github.com/golang/go/issues/3161
  // https://msdn.microsoft.com/en-us/library/aa387685(VS.85).aspx
  if (BN_num_bits(e_value) > 32) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_E_VALUE);
    return 0;
  }

  int ret = 0;
  int prime_bits = bits / 2;
  BN_CTX *ctx = BN_CTX_new();
  if (ctx == NULL) {
    goto bn_err;
  }
  BN_CTX_start(ctx);
  BIGNUM *totient = BN_CTX_get(ctx);
  BIGNUM *pm1 = BN_CTX_get(ctx);
  BIGNUM *qm1 = BN_CTX_get(ctx);
  BIGNUM *sqrt2 = BN_CTX_get(ctx);
  BIGNUM *pow2_prime_bits_100 = BN_CTX_get(ctx);
  BIGNUM *pow2_prime_bits = BN_CTX_get(ctx);
  if (totient == NULL || pm1 == NULL || qm1 == NULL || sqrt2 == NULL ||
      pow2_prime_bits_100 == NULL || pow2_prime_bits == NULL ||
      !BN_set_bit(pow2_prime_bits_100, prime_bits - 100) ||
      !BN_set_bit(pow2_prime_bits, prime_bits)) {
    goto bn_err;
  }

  // We need the RSA components non-NULL.
  if (!ensure_bignum(&rsa->n) ||
      !ensure_bignum(&rsa->d) ||
      !ensure_bignum(&rsa->e) ||
      !ensure_bignum(&rsa->p) ||
      !ensure_bignum(&rsa->q) ||
      !ensure_bignum(&rsa->dmp1) ||
      !ensure_bignum(&rsa->dmq1)) {
    goto bn_err;
  }

  if (!BN_copy(rsa->e, e_value)) {
    goto bn_err;
  }

  // Compute sqrt2 >= ⌊2^(prime_bits-1)×√2⌋.
  if (!bn_set_words(sqrt2, kBoringSSLRSASqrtTwo, kBoringSSLRSASqrtTwoLen)) {
    goto bn_err;
  }
  int sqrt2_bits = kBoringSSLRSASqrtTwoLen * BN_BITS2;
  assert(sqrt2_bits == (int)BN_num_bits(sqrt2));
  if (sqrt2_bits > prime_bits) {
    // For key sizes up to 3072 (prime_bits = 1536), this is exactly
    // ⌊2^(prime_bits-1)×√2⌋.
    if (!BN_rshift(sqrt2, sqrt2, sqrt2_bits - prime_bits)) {
      goto bn_err;
    }
  } else if (prime_bits > sqrt2_bits) {
    // For key sizes beyond 3072, this is approximate. We err towards retrying
    // to ensure our key is the right size and round up.
    if (!BN_add_word(sqrt2, 1) ||
        !BN_lshift(sqrt2, sqrt2, prime_bits - sqrt2_bits)) {
      goto bn_err;
    }
  }
  assert(prime_bits == (int)BN_num_bits(sqrt2));

  do {
    // Generate p and q, each of size |prime_bits|, using the steps outlined in
    // appendix FIPS 186-4 appendix B.3.3.
    if (!generate_prime(rsa->p, prime_bits, rsa->e, NULL, sqrt2,
                        pow2_prime_bits_100, ctx, cb) ||
        !BN_GENCB_call(cb, 3, 0) ||
        !generate_prime(rsa->q, prime_bits, rsa->e, rsa->p, sqrt2,
                        pow2_prime_bits_100, ctx, cb) ||
        !BN_GENCB_call(cb, 3, 1)) {
      goto bn_err;
    }

    if (BN_cmp(rsa->p, rsa->q) < 0) {
      BIGNUM *tmp = rsa->p;
      rsa->p = rsa->q;
      rsa->q = tmp;
    }

    // Calculate d = e^(-1) (mod lcm(p-1, q-1)), per FIPS 186-4. This differs
    // from typical RSA implementations which use (p-1)*(q-1).
    //
    // Note this means the size of d might reveal information about p-1 and
    // q-1. However, we do operations with Chinese Remainder Theorem, so we only
    // use d (mod p-1) and d (mod q-1) as exponents. Using a minimal totient
    // does not affect those two values.
    int no_inverse;
    if (!bn_usub_consttime(pm1, rsa->p, BN_value_one()) ||
        !bn_usub_consttime(qm1, rsa->q, BN_value_one()) ||
        !bn_lcm_consttime(totient, pm1, qm1, ctx) ||
        !bn_mod_inverse_consttime(rsa->d, &no_inverse, rsa->e, totient, ctx)) {
      goto bn_err;
    }

    // Retry if |rsa->d| <= 2^|prime_bits|. See appendix B.3.1's guidance on
    // values for d.
  } while (BN_cmp(rsa->d, pow2_prime_bits) <= 0);

  if (// Calculate n.
      !bn_mul_consttime(rsa->n, rsa->p, rsa->q, ctx) ||
      // Calculate d mod (p-1).
      !bn_div_consttime(NULL, rsa->dmp1, rsa->d, pm1, ctx) ||
      // Calculate d mod (q-1)
      !bn_div_consttime(NULL, rsa->dmq1, rsa->d, qm1, ctx)) {
    goto bn_err;
  }
  bn_set_minimal_width(rsa->n);

  // Sanity-check that |rsa->n| has the specified size. This is implied by
  // |generate_prime|'s bounds.
  if (BN_num_bits(rsa->n) != (unsigned)bits) {
    OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
    goto err;
  }

  // Call |freeze_private_key| to compute the inverse of q mod p, by way of
  // |rsa->mont_p|.
  if (!freeze_private_key(rsa, ctx)) {
    goto bn_err;
  }

  // The key generation process is complex and thus error-prone. It could be
  // disastrous to generate and then use a bad key so double-check that the key
  // makes sense.
  if (!RSA_check_key(rsa)) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_INTERNAL_ERROR);
    goto err;
  }

  ret = 1;

bn_err:
  if (!ret) {
    OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
  }
err:
  if (ctx != NULL) {
    BN_CTX_end(ctx);
    BN_CTX_free(ctx);
  }
  return ret;
}