int ec_GFp_simple_group_set_curve(EC_GROUP *group, const BIGNUM *p,
                                  const BIGNUM *a, const BIGNUM *b,
                                  BN_CTX *ctx) {
  int ret = 0;
  BN_CTX *new_ctx = NULL;
  BIGNUM *tmp_a;

  // p must be a prime > 3
  if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) {
    OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FIELD);
    return 0;
  }

  if (ctx == NULL) {
    ctx = new_ctx = BN_CTX_new();
    if (ctx == NULL) {
      return 0;
    }
  }

  BN_CTX_start(ctx);
  tmp_a = BN_CTX_get(ctx);
  if (tmp_a == NULL) {
    goto err;
  }

  // group->field
  if (!BN_copy(&group->field, p)) {
    goto err;
  }
  BN_set_negative(&group->field, 0);
  // Store the field in minimal form, so it can be used with |BN_ULONG| arrays.
  bn_set_minimal_width(&group->field);

  // group->a
  if (!BN_nnmod(tmp_a, a, &group->field, ctx)) {
    goto err;
  }
  if (group->meth->field_encode) {
    if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) {
      goto err;
    }
  } else if (!BN_copy(&group->a, tmp_a)) {
    goto err;
  }

  // group->b
  if (!BN_nnmod(&group->b, b, &group->field, ctx)) {
    goto err;
  }
  if (group->meth->field_encode &&
      !group->meth->field_encode(group, &group->b, &group->b, ctx)) {
    goto err;
  }

  // group->a_is_minus3
  if (!BN_add_word(tmp_a, 3)) {
    goto err;
  }
  group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field));

  if (group->meth->field_encode != NULL) {
    if (!group->meth->field_encode(group, &group->one, BN_value_one(), ctx)) {
      goto err;
    }
  } else if (!BN_copy(&group->one, BN_value_one())) {
    goto err;
  }

  ret = 1;

err:
  BN_CTX_end(ctx);
  BN_CTX_free(new_ctx);
  return ret;
}
Exemple #2
0
// freeze_private_key finishes initializing |rsa|'s private key components.
// After this function has returned, |rsa| may not be changed. This is needed
// because |RSA| is a public struct and, additionally, OpenSSL 1.1.0 opaquified
// it wrong (see https://github.com/openssl/openssl/issues/5158).
static int freeze_private_key(RSA *rsa, BN_CTX *ctx) {
  CRYPTO_MUTEX_lock_read(&rsa->lock);
  int flags = rsa->flags;
  CRYPTO_MUTEX_unlock_read(&rsa->lock);
  if (flags & RSA_FLAG_PRIVATE_KEY_FROZEN) {
    return 1;
  }

  int ret = 0;
  CRYPTO_MUTEX_lock_write(&rsa->lock);
  if (rsa->flags & RSA_FLAG_PRIVATE_KEY_FROZEN) {
    ret = 1;
    goto err;
  }

  // |rsa->n| is public. Normalize the width.
  bn_set_minimal_width(rsa->n);
  if (rsa->mont_n == NULL) {
    rsa->mont_n = BN_MONT_CTX_new_for_modulus(rsa->n, ctx);
    if (rsa->mont_n == NULL) {
      goto err;
    }
  }

  // The only public upper-bound of |rsa->d| is the bit length of |rsa->n|. The
  // ASN.1 serialization of RSA private keys unfortunately leaks the byte length
  // of |rsa->d|, but normalize it so we only leak it once, rather than per
  // operation.
  if (rsa->d != NULL &&
      !bn_resize_words(rsa->d, rsa->n->width)) {
    goto err;
  }

  if (rsa->p != NULL && rsa->q != NULL) {
    // |p| and |q| have public bit lengths.
    bn_set_minimal_width(rsa->p);
    bn_set_minimal_width(rsa->q);

    if (rsa->mont_p == NULL) {
      rsa->mont_p = BN_MONT_CTX_new_for_modulus(rsa->p, ctx);
      if (rsa->mont_p == NULL) {
        goto err;
      }
    }

    if (rsa->mont_q == NULL) {
      rsa->mont_q = BN_MONT_CTX_new_for_modulus(rsa->q, ctx);
      if (rsa->mont_q == NULL) {
        goto err;
      }
    }

    if (rsa->dmp1 != NULL && rsa->dmq1 != NULL) {
      // Key generation relies on this function to compute |iqmp|.
      if (rsa->iqmp == NULL) {
        BIGNUM *iqmp = BN_new();
        if (iqmp == NULL ||
            !bn_mod_inverse_secret_prime(iqmp, rsa->q, rsa->p, ctx,
                                         rsa->mont_p)) {
          BN_free(iqmp);
          goto err;
        }
        rsa->iqmp = iqmp;
      }

      // CRT components are only publicly bounded by their corresponding
      // moduli's bit lengths.
      if (!bn_resize_words(rsa->dmp1, rsa->p->width) ||
          !bn_resize_words(rsa->dmq1, rsa->q->width) ||
          !bn_resize_words(rsa->iqmp, rsa->p->width)) {
        goto err;
      }

      // Compute |inv_small_mod_large_mont|. Note that it is always modulo the
      // larger prime, independent of what is stored in |rsa->iqmp|.
      if (rsa->inv_small_mod_large_mont == NULL) {
        BIGNUM *inv_small_mod_large_mont = BN_new();
        int ok;
        if (BN_cmp(rsa->p, rsa->q) < 0) {
          ok = inv_small_mod_large_mont != NULL &&
               bn_mod_inverse_secret_prime(inv_small_mod_large_mont, rsa->p,
                                           rsa->q, ctx, rsa->mont_q) &&
               BN_to_montgomery(inv_small_mod_large_mont,
                                inv_small_mod_large_mont, rsa->mont_q, ctx);
        } else {
          ok = inv_small_mod_large_mont != NULL &&
               BN_to_montgomery(inv_small_mod_large_mont, rsa->iqmp,
                                rsa->mont_p, ctx);
        }
        if (!ok) {
          BN_free(inv_small_mod_large_mont);
          goto err;
        }
        rsa->inv_small_mod_large_mont = inv_small_mod_large_mont;
      }
    }
  }

  rsa->flags |= RSA_FLAG_PRIVATE_KEY_FROZEN;
  ret = 1;

err:
  CRYPTO_MUTEX_unlock_write(&rsa->lock);
  return ret;
}
Exemple #3
0
int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
  int max, min, dif;
  register BN_ULONG t1, t2, *ap, *bp, *rp;
  int i, carry;

  max = bn_minimal_width(a);
  min = bn_minimal_width(b);
  dif = max - min;

  if (dif < 0)  // hmm... should not be happening
  {
    OPENSSL_PUT_ERROR(BN, BN_R_ARG2_LT_ARG3);
    return 0;
  }

  if (!bn_wexpand(r, max)) {
    return 0;
  }

  ap = a->d;
  bp = b->d;
  rp = r->d;

  carry = 0;
  for (i = min; i != 0; i--) {
    t1 = *(ap++);
    t2 = *(bp++);
    if (carry) {
      carry = (t1 <= t2);
      t1 -= t2 + 1;
    } else {
      carry = (t1 < t2);
      t1 -= t2;
    }
    *(rp++) = t1;
  }

  if (carry)  // subtracted
  {
    if (!dif) {
      // error: a < b
      return 0;
    }

    while (dif) {
      dif--;
      t1 = *(ap++);
      t2 = t1 - 1;
      *(rp++) = t2;
      if (t1) {
        break;
      }
    }
  }

  if (dif > 0 && rp != ap) {
    OPENSSL_memcpy(rp, ap, sizeof(*rp) * dif);
  }

  r->width = max;
  r->neg = 0;
  bn_set_minimal_width(r);

  return 1;
}