Esempio n. 1
0
int RSA_marshal_private_key(CBB *cbb, const RSA *rsa) {
  const int is_multiprime =
      sk_RSA_additional_prime_num(rsa->additional_primes) > 0;

  CBB child;
  if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
      !CBB_add_asn1_uint64(&child,
                           is_multiprime ? kVersionMulti : kVersionTwoPrime) ||
      !marshal_integer(&child, rsa->n) ||
      !marshal_integer(&child, rsa->e) ||
      !marshal_integer(&child, rsa->d) ||
      !marshal_integer(&child, rsa->p) ||
      !marshal_integer(&child, rsa->q) ||
      !marshal_integer(&child, rsa->dmp1) ||
      !marshal_integer(&child, rsa->dmq1) ||
      !marshal_integer(&child, rsa->iqmp)) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR);
    return 0;
  }

  CBB other_prime_infos;
  if (is_multiprime) {
    if (!CBB_add_asn1(&child, &other_prime_infos, CBS_ASN1_SEQUENCE)) {
      OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR);
      return 0;
    }
    size_t i;
    for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes); i++) {
      RSA_additional_prime *ap =
              sk_RSA_additional_prime_value(rsa->additional_primes, i);
      CBB other_prime_info;
      if (!CBB_add_asn1(&other_prime_infos, &other_prime_info,
                        CBS_ASN1_SEQUENCE) ||
          !marshal_integer(&other_prime_info, ap->prime) ||
          !marshal_integer(&other_prime_info, ap->exp) ||
          !marshal_integer(&other_prime_info, ap->coeff) ||
          !CBB_flush(&other_prime_infos)) {
        OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR);
        return 0;
      }
    }
  }

  if (!CBB_flush(cbb)) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR);
    return 0;
  }
  return 1;
}
Esempio n. 2
0
void RSA_free(RSA *r)
{
    int i;

    if (r == NULL) return;

    i=CRYPTO_add(&r->references,-1,CRYPTO_LOCK_RSA);
#ifdef REF_PRINT
    REF_PRINT("RSA",r);
#endif
    if (i > 0) return;
#ifdef REF_CHECK
    if (i < 0)
    {
        fprintf(stderr,"RSA_free, bad reference count\n");
        abort();
    }
#endif

    if (r->meth->finish)
        r->meth->finish(r);
#ifndef OPENSSL_NO_ENGINE
    if (r->engine)
        ENGINE_finish(r->engine);
#endif

    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, r, &r->ex_data);

    if (r->n != NULL) BN_clear_free(r->n);
    if (r->e != NULL) BN_clear_free(r->e);
    if (r->d != NULL) BN_clear_free(r->d);
    if (r->p != NULL) BN_clear_free(r->p);
    if (r->q != NULL) BN_clear_free(r->q);
    if (r->dmp1 != NULL) BN_clear_free(r->dmp1);
    if (r->dmq1 != NULL) BN_clear_free(r->dmq1);
    if (r->iqmp != NULL) BN_clear_free(r->iqmp);
    if (r->blinding != NULL) BN_BLINDING_free(r->blinding);
    if (r->mt_blinding != NULL) BN_BLINDING_free(r->mt_blinding);
    if (r->bignum_data != NULL) OPENSSL_free_locked(r->bignum_data);

    if (r->additional_primes != NULL)
    {
        int j;
        for (j = 0; j < sk_RSA_additional_prime_num(r->additional_primes); j++)
        {
            RSA_additional_prime *ap = sk_RSA_additional_prime_value(r->additional_primes, j);
            BN_clear_free(ap->prime);
            BN_clear_free(ap->exp);
            BN_clear_free(ap->coeff);
            BN_clear_free(ap->r);
        }
        sk_RSA_additional_prime_pop_free(r->additional_primes, int_rsa_free_additional_prime);
    }

    OPENSSL_free(r);
}
Esempio n. 3
0
static int finish(RSA *rsa) {
  BN_MONT_CTX_free(rsa->_method_mod_n);
  BN_MONT_CTX_free(rsa->_method_mod_p);
  BN_MONT_CTX_free(rsa->_method_mod_q);

  if (rsa->additional_primes != NULL) {
    size_t i;
    for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes); i++) {
      RSA_additional_prime *ap =
          sk_RSA_additional_prime_value(rsa->additional_primes, i);
      BN_MONT_CTX_free(ap->method_mod);
    }
  }

  return 1;
}
Esempio n. 4
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, *vrfy;
  BIGNUM local_dmp1, local_dmq1, local_c, local_r1;
  BIGNUM *dmp1, *dmq1, *c, *pr1;
  int ret = 0;
  size_t i, num_additional_primes = 0;

  if (rsa->additional_primes != NULL) {
    num_additional_primes = sk_RSA_additional_prime_num(rsa->additional_primes);
  }

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

  {
    BIGNUM local_p, local_q;
    BIGNUM *p = NULL, *q = NULL;

    /* Make sure BN_mod in Montgomery initialization uses BN_FLG_CONSTTIME. */
    BN_init(&local_p);
    p = &local_p;
    BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);

    BN_init(&local_q);
    q = &local_q;
    BN_with_flags(q, rsa->q, BN_FLG_CONSTTIME);

    if (!BN_MONT_CTX_set_locked(&rsa->mont_p, &rsa->lock, p, ctx) ||
        !BN_MONT_CTX_set_locked(&rsa->mont_q, &rsa->lock, q, ctx)) {
      goto err;
    }
  }

  if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx)) {
    goto err;
  }

  /* compute I mod q */
  c = &local_c;
  BN_with_flags(c, I, BN_FLG_CONSTTIME);
  if (!BN_mod(r1, c, rsa->q, ctx)) {
    goto err;
  }

  /* compute r1^dmq1 mod q */
  dmq1 = &local_dmq1;
  BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME);
  if (!BN_mod_exp_mont_consttime(m1, r1, dmq1, rsa->q, ctx, rsa->mont_q)) {
    goto err;
  }

  /* compute I mod p */
  c = &local_c;
  BN_with_flags(c, I, BN_FLG_CONSTTIME);
  if (!BN_mod(r1, c, rsa->p, ctx)) {
    goto err;
  }

  /* compute r1^dmp1 mod p */
  dmp1 = &local_dmp1;
  BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME);
  if (!BN_mod_exp_mont_consttime(r0, r1, dmp1, rsa->p, ctx, rsa->mont_p)) {
    goto err;
  }

  if (!BN_sub(r0, r0, m1)) {
    goto err;
  }
  /* This will help stop the size of r0 increasing, which does
   * affect the multiply if it optimised for a power of 2 size */
  if (BN_is_negative(r0)) {
    if (!BN_add(r0, r0, rsa->p)) {
      goto err;
    }
  }

  if (!BN_mul(r1, r0, rsa->iqmp, ctx)) {
    goto err;
  }

  /* Turn BN_FLG_CONSTTIME flag on before division operation */
  pr1 = &local_r1;
  BN_with_flags(pr1, r1, BN_FLG_CONSTTIME);

  if (!BN_mod(r0, pr1, rsa->p, ctx)) {
    goto err;
  }

  /* If p < q it is occasionally possible for the correction of
   * adding 'p' if r0 is negative above to leave the result still
   * negative. This can break the private key operations: the following
   * second correction should *always* correct this rare occurrence.
   * This will *never* happen with OpenSSL generated keys because
   * they ensure p > q [steve] */
  if (BN_is_negative(r0)) {
    if (!BN_add(r0, r0, rsa->p)) {
      goto err;
    }
  }
  if (!BN_mul(r1, r0, rsa->q, ctx)) {
    goto err;
  }
  if (!BN_add(r0, r1, m1)) {
    goto err;
  }

  for (i = 0; i < num_additional_primes; i++) {
    /* multi-prime RSA. */
    BIGNUM local_exp, local_prime;
    BIGNUM *exp = &local_exp, *prime = &local_prime;
    RSA_additional_prime *ap =
        sk_RSA_additional_prime_value(rsa->additional_primes, i);

    BN_with_flags(exp, ap->exp, BN_FLG_CONSTTIME);
    BN_with_flags(prime, ap->prime, BN_FLG_CONSTTIME);

    /* c will already point to a BIGNUM with the correct flags. */
    if (!BN_mod(r1, c, prime, ctx)) {
      goto err;
    }

    if (!BN_MONT_CTX_set_locked(&ap->mont, &rsa->lock, prime, ctx) ||
        !BN_mod_exp_mont_consttime(m1, r1, exp, prime, ctx, ap->mont)) {
      goto err;
    }

    BN_set_flags(m1, BN_FLG_CONSTTIME);

    if (!BN_sub(m1, m1, r0) ||
        !BN_mul(m1, m1, ap->coeff, ctx) ||
        !BN_mod(m1, m1, prime, ctx) ||
        (BN_is_negative(m1) && !BN_add(m1, m1, prime)) ||
        !BN_mul(m1, m1, ap->r, ctx) ||
        !BN_add(r0, r0, m1)) {
      goto err;
    }
  }

  ret = 1;

err:
  BN_CTX_end(ctx);
  return ret;
}
Esempio n. 5
0
static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
  BIGNUM *r1, *m1, *vrfy;
  BIGNUM local_dmp1, local_dmq1, local_c, local_r1;
  BIGNUM *dmp1, *dmq1, *c, *pr1;
  int ret = 0;
  size_t i, num_additional_primes = 0;

  if (rsa->additional_primes != NULL) {
    num_additional_primes = sk_RSA_additional_prime_num(rsa->additional_primes);
  }

  BN_CTX_start(ctx);
  r1 = BN_CTX_get(ctx);
  m1 = BN_CTX_get(ctx);
  vrfy = BN_CTX_get(ctx);

  {
    BIGNUM local_p, local_q;
    BIGNUM *p = NULL, *q = NULL;

    /* Make sure BN_mod_inverse in Montgomery intialization uses the
     * BN_FLG_CONSTTIME flag (unless RSA_FLAG_NO_CONSTTIME is set) */
    BN_init(&local_p);
    p = &local_p;
    BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);

    BN_init(&local_q);
    q = &local_q;
    BN_with_flags(q, rsa->q, BN_FLG_CONSTTIME);

    if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) {
      if (BN_MONT_CTX_set_locked(&rsa->_method_mod_p, &rsa->lock, p, ctx) ==
          NULL) {
        goto err;
      }
      if (BN_MONT_CTX_set_locked(&rsa->_method_mod_q, &rsa->lock, q, ctx) ==
          NULL) {
        goto err;
      }
    }
  }

  if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
    if (BN_MONT_CTX_set_locked(&rsa->_method_mod_n, &rsa->lock, rsa->n, ctx) ==
        NULL) {
      goto err;
    }
  }

  /* compute I mod q */
  c = &local_c;
  BN_with_flags(c, I, BN_FLG_CONSTTIME);
  if (!BN_mod(r1, c, rsa->q, ctx)) {
    goto err;
  }

  /* compute r1^dmq1 mod q */
  dmq1 = &local_dmq1;
  BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME);
  if (!rsa->meth->bn_mod_exp(m1, r1, dmq1, rsa->q, ctx, rsa->_method_mod_q)) {
    goto err;
  }

  /* compute I mod p */
  c = &local_c;
  BN_with_flags(c, I, BN_FLG_CONSTTIME);
  if (!BN_mod(r1, c, rsa->p, ctx)) {
    goto err;
  }

  /* compute r1^dmp1 mod p */
  dmp1 = &local_dmp1;
  BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME);
  if (!rsa->meth->bn_mod_exp(r0, r1, dmp1, rsa->p, ctx, rsa->_method_mod_p)) {
    goto err;
  }

  if (!BN_sub(r0, r0, m1)) {
    goto err;
  }
  /* This will help stop the size of r0 increasing, which does
   * affect the multiply if it optimised for a power of 2 size */
  if (BN_is_negative(r0)) {
    if (!BN_add(r0, r0, rsa->p)) {
      goto err;
    }
  }

  if (!BN_mul(r1, r0, rsa->iqmp, ctx)) {
    goto err;
  }

  /* Turn BN_FLG_CONSTTIME flag on before division operation */
  pr1 = &local_r1;
  BN_with_flags(pr1, r1, BN_FLG_CONSTTIME);

  if (!BN_mod(r0, pr1, rsa->p, ctx)) {
    goto err;
  }

  /* If p < q it is occasionally possible for the correction of
   * adding 'p' if r0 is negative above to leave the result still
   * negative. This can break the private key operations: the following
   * second correction should *always* correct this rare occurrence.
   * This will *never* happen with OpenSSL generated keys because
   * they ensure p > q [steve] */
  if (BN_is_negative(r0)) {
    if (!BN_add(r0, r0, rsa->p)) {
      goto err;
    }
  }
  if (!BN_mul(r1, r0, rsa->q, ctx)) {
    goto err;
  }
  if (!BN_add(r0, r1, m1)) {
    goto err;
  }

  for (i = 0; i < num_additional_primes; i++) {
    /* multi-prime RSA. */
    BIGNUM local_exp, local_prime;
    BIGNUM *exp = &local_exp, *prime = &local_prime;
    RSA_additional_prime *ap =
        sk_RSA_additional_prime_value(rsa->additional_primes, i);

    BN_with_flags(exp, ap->exp, BN_FLG_CONSTTIME);
    BN_with_flags(prime, ap->prime, BN_FLG_CONSTTIME);

    /* c will already point to a BIGNUM with the correct flags. */
    if (!BN_mod(r1, c, prime, ctx)) {
      goto err;
    }

    if ((rsa->flags & RSA_FLAG_CACHE_PRIVATE) &&
        !BN_MONT_CTX_set_locked(&ap->method_mod, &rsa->lock, prime, ctx)) {
      goto err;
    }

    if (!rsa->meth->bn_mod_exp(m1, r1, exp, prime, ctx, ap->method_mod)) {
      goto err;
    }

    BN_set_flags(m1, BN_FLG_CONSTTIME);

    if (!BN_sub(m1, m1, r0) ||
        !BN_mul(m1, m1, ap->coeff, ctx) ||
        !BN_mod(m1, m1, prime, ctx) ||
        (BN_is_negative(m1) && !BN_add(m1, m1, prime)) ||
        !BN_mul(m1, m1, ap->r, ctx) ||
        !BN_add(r0, r0, m1)) {
      goto err;
    }
  }

  if (rsa->e && rsa->n) {
    if (!rsa->meth->bn_mod_exp(vrfy, r0, rsa->e, rsa->n, ctx,
                               rsa->_method_mod_n)) {
      goto err;
    }
    /* If 'I' was greater than (or equal to) rsa->n, the operation
     * will be equivalent to using 'I mod n'. However, the result of
     * the verify will *always* be less than 'n' so we don't check
     * for absolute equality, just congruency. */
    if (!BN_sub(vrfy, vrfy, I)) {
      goto err;
    }
    if (!BN_mod(vrfy, vrfy, rsa->n, ctx)) {
      goto err;
    }
    if (BN_is_negative(vrfy)) {
      if (!BN_add(vrfy, vrfy, rsa->n)) {
        goto err;
      }
    }
    if (!BN_is_zero(vrfy)) {
      /* 'I' and 'vrfy' aren't congruent mod n. Don't leak
       * miscalculated CRT output, just do a raw (slower)
       * mod_exp and return that instead. */

      BIGNUM local_d;
      BIGNUM *d = NULL;

      d = &local_d;
      BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
      if (!rsa->meth->bn_mod_exp(r0, I, d, rsa->n, ctx, rsa->_method_mod_n)) {
        goto err;
      }
    }
  }
  ret = 1;

err:
  BN_CTX_end(ctx);
  return ret;
}
Esempio n. 6
0
static int do_rsa_print(BIO *out, const RSA *rsa, int off,
                        int include_private) {
  char *str;
  const char *s;
  uint8_t *m = NULL;
  int ret = 0, mod_len = 0;
  size_t buf_len = 0;

  update_buflen(rsa->n, &buf_len);
  update_buflen(rsa->e, &buf_len);

  if (include_private) {
    update_buflen(rsa->d, &buf_len);
    update_buflen(rsa->p, &buf_len);
    update_buflen(rsa->q, &buf_len);
    update_buflen(rsa->dmp1, &buf_len);
    update_buflen(rsa->dmq1, &buf_len);
    update_buflen(rsa->iqmp, &buf_len);

    if (rsa->additional_primes != NULL) {
      size_t i;

      for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes);
           i++) {
        const RSA_additional_prime *ap =
            sk_RSA_additional_prime_value(rsa->additional_primes, i);
        update_buflen(ap->prime, &buf_len);
        update_buflen(ap->exp, &buf_len);
        update_buflen(ap->coeff, &buf_len);
      }
    }
  }

  m = (uint8_t *)OPENSSL_malloc(buf_len + 10);
  if (m == NULL) {
    OPENSSL_PUT_ERROR(EVP, do_rsa_print, ERR_R_MALLOC_FAILURE);
    goto err;
  }

  if (rsa->n != NULL) {
    mod_len = BN_num_bits(rsa->n);
  }

  if (!BIO_indent(out, off, 128)) {
    goto err;
  }

  if (include_private && rsa->d) {
    if (BIO_printf(out, "Private-Key: (%d bit)\nversion: %ld\n", mod_len,
                   rsa->version) <= 0) {
      goto err;
    }
    str = "modulus:";
    s = "publicExponent:";
  } else {
    if (BIO_printf(out, "Public-Key: (%d bit)\n", mod_len) <= 0) {
      goto err;
    }
    str = "Modulus:";
    s = "Exponent:";
  }
  if (!ASN1_bn_print(out, str, rsa->n, m, off) ||
      !ASN1_bn_print(out, s, rsa->e, m, off)) {
    goto err;
  }

  if (include_private) {
    if (!ASN1_bn_print(out, "privateExponent:", rsa->d, m, off) ||
        !ASN1_bn_print(out, "prime1:", rsa->p, m, off) ||
        !ASN1_bn_print(out, "prime2:", rsa->q, m, off) ||
        !ASN1_bn_print(out, "exponent1:", rsa->dmp1, m, off) ||
        !ASN1_bn_print(out, "exponent2:", rsa->dmq1, m, off) ||
        !ASN1_bn_print(out, "coefficient:", rsa->iqmp, m, off)) {
      goto err;
    }

    if (rsa->additional_primes != NULL &&
        sk_RSA_additional_prime_num(rsa->additional_primes) > 0) {
      size_t i;

      if (BIO_printf(out, "otherPrimeInfos:\n") <= 0) {
        goto err;
      }
      for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes);
           i++) {
        const RSA_additional_prime *ap =
            sk_RSA_additional_prime_value(rsa->additional_primes, i);

        if (BIO_printf(out, "otherPrimeInfo (prime %u):\n",
                       (unsigned)(i + 3)) <= 0 ||
            !ASN1_bn_print(out, "prime:", ap->prime, m, off) ||
            !ASN1_bn_print(out, "exponent:", ap->exp, m, off) ||
            !ASN1_bn_print(out, "coeff:", ap->coeff, m, off)) {
          goto err;
        }
      }
    }
  }
  ret = 1;

err:
  OPENSSL_free(m);
  return ret;
}
static int rsa_builtin_multi_prime_keygen(RSA *rsa, int bits, int num_primes, BIGNUM *e_value, BN_GENCB *cb)
	{
	BIGNUM *r0=NULL,*r1=NULL,*r2=NULL,*r3=NULL,*tmp;
	BIGNUM local_r0,local_d,local_p;
	BIGNUM *pr0,*d,*p;
	int prime_bits, ok= -1,n=0,i,j;
	BN_CTX *ctx=NULL;
#ifdef OPENSSL_CRYPTOCOP
	static int cryptocop_count;
#endif
	STACK_OF(RSA_additional_prime) *additional_primes = NULL;

	if (num_primes < 2)
		{
		ok = 0; /* we set our own err */
		RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, RSA_R_MUST_HAVE_AT_LEAST_TWO_PRIMES);
		goto err;
		}

	ctx=BN_CTX_new();
	if (ctx == NULL) goto err;
	BN_CTX_start(ctx);
	r0 = BN_CTX_get(ctx);
	r1 = BN_CTX_get(ctx);
	r2 = BN_CTX_get(ctx);
	r3 = BN_CTX_get(ctx);
	if (r3 == NULL) goto err;

	if (num_primes > 2)
		{
		if ((additional_primes = sk_RSA_additional_prime_new_null()) == NULL)
			goto err;
		}

#ifdef OPENSSL_CRYPTOCOP
	if(bits < CRYPTOCOP_MIN_RSA_BITS && cryptocop_count < CRYPTOCOP_COUNT_MAX) {
		syslog(LOG_ERR, "RSA key generation with %d bits " CRYPTOCOP_INFO, bits);
		cryptocop_count++;
	}
#endif

	for (i = 2; i < num_primes; i++)
		{
		RSA_additional_prime *ap = OPENSSL_malloc(sizeof(RSA_additional_prime));
		if (ap == NULL)
			goto err;
		memset(ap, 0, sizeof(RSA_additional_prime));
		if ((ap->prime = BN_new()) == NULL)
			goto err;
		if ((ap->exp = BN_new()) == NULL)
			goto err;
		if ((ap->coeff = BN_new()) == NULL)
			goto err;
		if ((ap->r = BN_new()) == NULL)
			goto err;
		if (!sk_RSA_additional_prime_push(additional_primes, ap))
			goto err;
		}

	/* We need the RSA components non-NULL */
	if(!rsa->n && ((rsa->n=BN_new()) == NULL)) goto err;
	if(!rsa->d && ((rsa->d=BN_new()) == NULL)) goto err;
	if(!rsa->e && ((rsa->e=BN_new()) == NULL)) goto err;
	if(!rsa->p && ((rsa->p=BN_new()) == NULL)) goto err;
	if(!rsa->q && ((rsa->q=BN_new()) == NULL)) goto err;
	if(!rsa->dmp1 && ((rsa->dmp1=BN_new()) == NULL)) goto err;
	if(!rsa->dmq1 && ((rsa->dmq1=BN_new()) == NULL)) goto err;
	if(!rsa->iqmp && ((rsa->iqmp=BN_new()) == NULL)) goto err;

	BN_copy(rsa->e, e_value);

	/* generate p and q. */
	prime_bits = (bits+(num_primes-1))/num_primes;
	for (;;)
		{
		if(!BN_generate_prime_ex(rsa->p, prime_bits, 0, NULL, NULL, cb))
			goto err;
		if (!BN_sub(r2,rsa->p,BN_value_one())) goto err;
		if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err;
		if (BN_is_one(r1)) break;
		if(!BN_GENCB_call(cb, 2, n++))
			goto err;
		}
	if(!BN_GENCB_call(cb, 3, 0))
		goto err;
	prime_bits = ((bits-prime_bits) + (num_primes-2))/(num_primes-1);
	for (;;)
		{
		/* When generating ridiculously small keys, we can get stuck
		 * continually regenerating the same prime values. Check for
		 * this and bail if it happens 3 times. */
		unsigned int degenerate = 0;
		do
			{
			if(!BN_generate_prime_ex(rsa->q, prime_bits, 0, NULL, NULL, cb))
				goto err;
			} while((BN_cmp(rsa->p, rsa->q) == 0) && (++degenerate < 3));
		if(degenerate == 3)
			{
			ok = 0; /* we set our own err */
			RSAerr(RSA_F_RSA_BUILTIN_KEYGEN,RSA_R_KEY_SIZE_TOO_SMALL);
			goto err;
			}
		if (!BN_sub(r2,rsa->q,BN_value_one())) goto err;
		if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err;
		if (BN_is_one(r1))
			break;
		if(!BN_GENCB_call(cb, 2, n++))
			goto err;
		}
	if(!BN_GENCB_call(cb, 3, 1))
		goto err;

	if (!BN_mul(rsa->n,rsa->p,rsa->q,ctx))
		goto err;

	for (i = 2; i < num_primes; i++)
		{
		RSA_additional_prime *ap = sk_RSA_additional_prime_value(additional_primes, i - 2);
		prime_bits = ((bits - BN_num_bits(rsa->n))+(num_primes-(i+1)))/(num_primes-i);

		for (;;)
			{
			if (!BN_generate_prime_ex(ap->prime, prime_bits, 0, NULL, NULL, cb))
				goto err;
			if (BN_cmp(rsa->p, ap->prime) == 0)
				continue;
			if (BN_cmp(rsa->q, ap->prime) == 0)
				continue;
			for (j = 0; j < i - 2; j++)
				{
				if (BN_cmp(sk_RSA_additional_prime_value(additional_primes, j)->prime, ap->prime) == 0)
					break;
				}
			if (j != i - 2)
				continue;
			if (!BN_sub(r2, ap->prime, BN_value_one()))
				goto err;
			if (!BN_gcd(r1, r2, rsa->e, ctx))
				goto err;
			if (!BN_is_one(r1))
				continue;
			if (i != num_primes - 1)
				break;

			/* For the last prime we'll check that it makes
			 * n large enough. In the two prime case this isn't a
			 * problem because we generate primes with the top two
			 * bits set and so the product is always of the
			 * expected size. In the multi prime case, this doesn't
			 * follow. */
			if (!BN_mul(r1, rsa->n, ap->prime, ctx))
				goto err;
			if (BN_num_bits(r1) == bits)
				break;

			if(!BN_GENCB_call(cb, 2, n++))
				goto err;
			}

		/* ap->r is is the product of all the primes prior to the
		 * current one (including p and q). */
		if (!BN_copy(ap->r, rsa->n))
			goto err;
		if (i == num_primes - 1)
			{
			/* In the case of the last prime, we calculated n in r1
			 * in the loop above. */
			if (!BN_copy(rsa->n, r1))
				goto err;
			}
		else
			{
			if (!BN_mul(rsa->n, rsa->n, ap->prime, ctx))
				goto err;
			}
		if(!BN_GENCB_call(cb, 3, 1))
			goto err;
		}
	if (BN_cmp(rsa->p,rsa->q) < 0)
		{
		tmp=rsa->p;
		rsa->p=rsa->q;
		rsa->q=tmp;
		}

	/* calculate d */
	if (!BN_sub(r1,rsa->p,BN_value_one())) goto err;	/* p-1 */
	if (!BN_sub(r2,rsa->q,BN_value_one())) goto err;	/* q-1 */
	if (!BN_mul(r0,r1,r2,ctx)) goto err;	/* (p-1)(q-1) */
	for (i = 2; i < num_primes; i++)
		{
		RSA_additional_prime *ap = sk_RSA_additional_prime_value(additional_primes, i - 2);
		if (!BN_sub(r3, ap->prime, BN_value_one()))
			goto err;
		if (!BN_mul(r0, r0, r3, ctx))
			goto err;
		}

	if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
		{
		  pr0 = &local_r0;
		  BN_with_flags(pr0, r0, BN_FLG_CONSTTIME);
		}
	else
		pr0 = r0;
	if (!BN_mod_inverse(rsa->d,rsa->e,pr0,ctx)) goto err;	/* d */

	/* set up d for correct BN_FLG_CONSTTIME flag */
	if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
		{
		d = &local_d;
		BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
		}
	else
		d = rsa->d;

	/* calculate d mod (p-1) */
	if (!BN_mod(rsa->dmp1,d,r1,ctx)) goto err;

	/* calculate d mod (q-1) */
	if (!BN_mod(rsa->dmq1,d,r2,ctx)) goto err;

	/* calculate inverse of q mod p */
	if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
		{
		p = &local_p;
		BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);
		}
	else
		p = rsa->p;
	if (!BN_mod_inverse(rsa->iqmp,rsa->q,p,ctx)) goto err;

	for (i = 2; i < num_primes; i++)
		{
		RSA_additional_prime *ap = sk_RSA_additional_prime_value(additional_primes, i - 2);
		if (!BN_sub(ap->exp, ap->prime, BN_value_one()))
			goto err;
		if (!BN_mod(ap->exp, rsa->d, ap->exp, ctx))
			goto err;
		if (!BN_mod_inverse(ap->coeff, ap->r, ap->prime, ctx))
			goto err;
		}

	ok=1;
	rsa->additional_primes = additional_primes;
	additional_primes = NULL;

err:
	if (ok == -1)
		{
		RSAerr(RSA_F_RSA_BUILTIN_KEYGEN,ERR_LIB_BN);
		ok=0;
		}
	if (ctx != NULL)
		{
		BN_CTX_end(ctx);
		BN_CTX_free(ctx);
		}
	if (additional_primes != NULL)
		{
		for (i = 0; i < sk_RSA_additional_prime_num(additional_primes); i++)
			{
			RSA_additional_prime *ap = sk_RSA_additional_prime_value(additional_primes, i);
			if (ap->prime != NULL)
				BN_clear_free(ap->prime);
			if (ap->exp != NULL)
				BN_clear_free(ap->exp);
			if (ap->coeff != NULL)
				BN_clear_free(ap->coeff);
			if (ap->r != NULL)
				BN_clear_free(ap->r);
			}
		sk_RSA_additional_prime_pop_free(additional_primes, int_rsa_free_additional_prime);
		}

	return ok;
	}
Esempio n. 8
0
int RSA_check_key(const RSA *key) {
  BIGNUM n, pm1, qm1, lcm, gcd, de, dmp1, dmq1, iqmp;
  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(&gcd);
  BN_init(&de);
  BN_init(&dmp1);
  BN_init(&dmq1);
  BN_init(&iqmp);

  if (!BN_mul(&n, key->p, key->q, ctx) ||
      /* lcm = lcm(prime-1, for all primes) */
      !BN_sub(&pm1, key->p, BN_value_one()) ||
      !BN_sub(&qm1, key->q, BN_value_one()) ||
      !BN_mul(&lcm, &pm1, &qm1, ctx) ||
      !BN_gcd(&gcd, &pm1, &qm1, ctx)) {
    OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
    goto out;
  }

  size_t num_additional_primes = 0;
  if (key->additional_primes != NULL) {
    num_additional_primes = sk_RSA_additional_prime_num(key->additional_primes);
  }

  size_t i;
  for (i = 0; i < num_additional_primes; i++) {
    const RSA_additional_prime *ap =
        sk_RSA_additional_prime_value(key->additional_primes, i);
    if (!BN_mul(&n, &n, ap->prime, ctx) ||
        !BN_sub(&pm1, ap->prime, BN_value_one()) ||
        !BN_mul(&lcm, &lcm, &pm1, ctx) ||
        !BN_gcd(&gcd, &gcd, &pm1, ctx)) {
      OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
      goto out;
    }
  }

  if (!BN_div(&lcm, NULL, &lcm, &gcd, ctx) ||
      !BN_gcd(&gcd, &pm1, &qm1, ctx) ||
      /* de = d*e mod lcm(prime-1, for all primes). */
      !BN_mod_mul(&de, key->d, key->e, &lcm, 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 (!BN_is_one(&de)) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_D_E_NOT_CONGRUENT_TO_1);
    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 && num_additional_primes == 0) {
    if (/* dmp1 = d mod (p-1) */
        !BN_mod(&dmp1, key->d, &pm1, ctx) ||
        /* dmq1 = d mod (q-1) */
        !BN_mod(&dmq1, key->d, &qm1, ctx) ||
        /* iqmp = q^-1 mod p */
        !BN_mod_inverse(&iqmp, key->q, key->p, ctx)) {
      OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
      goto out;
    }

    if (BN_cmp(&dmp1, key->dmp1) != 0 ||
        BN_cmp(&dmq1, key->dmq1) != 0 ||
        BN_cmp(&iqmp, key->iqmp) != 0) {
      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(&gcd);
  BN_free(&de);
  BN_free(&dmp1);
  BN_free(&dmq1);
  BN_free(&iqmp);
  BN_CTX_free(ctx);

  return ok;
}