Exemple #1
0
/**
 * blinded_modexp(r, a, priv):
 * Compute ${r} = ${a}^(2^258 + ${priv}), where ${r} and ${priv} are treated
 * as big-endian integers; and avoid leaking timing data in this process.
 */
static int
blinded_modexp(uint8_t r[CRYPTO_DH_PUBLEN], BIGNUM * a,
    const uint8_t priv[CRYPTO_DH_PRIVLEN])
{
	BIGNUM * two_exp_256_bn;
	BIGNUM * priv_bn;
	uint8_t blinding[CRYPTO_DH_PRIVLEN];
	BIGNUM * blinding_bn;
	BIGNUM * priv_blinded;
	BIGNUM * m_bn;
	BN_CTX * ctx;
	BIGNUM * r1;
	BIGNUM * r2;
	size_t rlen;

	/* Construct 2^256 in BN representation. */
	if ((two_exp_256_bn = BN_bin2bn(two_exp_256, 33, NULL)) == NULL) {
		warn0("%s", ERR_error_string(ERR_get_error(), NULL));
		goto err0;
	}

	/* Construct 2^258 + ${priv} in BN representation. */
	if ((priv_bn = BN_bin2bn(priv, CRYPTO_DH_PRIVLEN, NULL)) == NULL) {
		warn0("%s", ERR_error_string(ERR_get_error(), NULL));
		goto err1;
	}
	if ((!BN_add(priv_bn, priv_bn, two_exp_256_bn)) ||
	    (!BN_add(priv_bn, priv_bn, two_exp_256_bn)) ||
	    (!BN_add(priv_bn, priv_bn, two_exp_256_bn)) ||
	    (!BN_add(priv_bn, priv_bn, two_exp_256_bn))) {
		warn0("%s", ERR_error_string(ERR_get_error(), NULL));
		goto err2;
	}

	/* Generate blinding exponent. */
	if (crypto_entropy_read(blinding, CRYPTO_DH_PRIVLEN))
		goto err2;
	if ((blinding_bn = BN_bin2bn(blinding,
	    CRYPTO_DH_PRIVLEN, NULL)) == NULL) {
		warn0("%s", ERR_error_string(ERR_get_error(), NULL));
		goto err2;
	}
	if (!BN_add(blinding_bn, blinding_bn, two_exp_256_bn)) {
		warn0("%s", ERR_error_string(ERR_get_error(), NULL));
		goto err3;
	}

	/* Generate blinded exponent. */
	if ((priv_blinded = BN_new()) == NULL) {
		warn0("%s", ERR_error_string(ERR_get_error(), NULL));
		goto err3;
	}
	if (!BN_sub(priv_blinded, priv_bn, blinding_bn)) {
		warn0("%s", ERR_error_string(ERR_get_error(), NULL));
		goto err4;
	}

	/* Construct group #14 modulus in BN representation. */
	if ((m_bn = BN_bin2bn(crypto_dh_group14, 256, NULL)) == NULL) {
		warn0("%s", ERR_error_string(ERR_get_error(), NULL));
		goto err4;
	}

	/* Allocate BN context. */
	if ((ctx = BN_CTX_new()) == NULL) {
		warn0("%s", ERR_error_string(ERR_get_error(), NULL));
		goto err5;
	}

	/* Allocate space for storing results of exponentiations. */
	if ((r1 = BN_new()) == NULL) {
		warn0("%s", ERR_error_string(ERR_get_error(), NULL));
		goto err6;
	}
	if ((r2 = BN_new()) == NULL) {
		warn0("%s", ERR_error_string(ERR_get_error(), NULL));
		goto err7;
	}

	/* Perform modular exponentiations. */
	if (!BN_mod_exp(r1, a, blinding_bn, m_bn, ctx)) {
		warn0("%s", ERR_error_string(ERR_get_error(), NULL));
		goto err8;
	}
	if (!BN_mod_exp(r2, a, priv_blinded, m_bn, ctx)) {
		warn0("%s", ERR_error_string(ERR_get_error(), NULL));
		goto err8;
	}

	/* Compute final result and export to big-endian integer format. */
	if (!BN_mod_mul(r1, r1, r2, m_bn, ctx)) {
		warn0("%s", ERR_error_string(ERR_get_error(), NULL));
		goto err8;
	}
	rlen = BN_num_bytes(r1);
	if (rlen > CRYPTO_DH_PUBLEN) {
		warn0("Exponent result too large!");
		goto err8;
	}
	memset(r, 0, CRYPTO_DH_PUBLEN - rlen);
	BN_bn2bin(r1, r + CRYPTO_DH_PUBLEN - rlen);

	/* Free space allocated by BN_new. */
	BN_clear_free(r2);
	BN_clear_free(r1);

	/* Free context allocated by BN_CTX_new. */
	BN_CTX_free(ctx);

	/* Free space allocated by BN_bin2bn. */
	BN_free(m_bn);

	/* Free space allocated by BN_new. */
	BN_clear_free(priv_blinded);

	/* Free space allocated by BN_bin2bn. */
	BN_clear_free(blinding_bn);
	BN_clear_free(priv_bn);
	BN_free(two_exp_256_bn);

	/* Success! */
	return (0);

err8:
	BN_clear_free(r2);
err7:
	BN_clear_free(r1);
err6:
	BN_CTX_free(ctx);
err5:
	BN_free(m_bn);
err4:
	BN_clear_free(priv_blinded);
err3:
	BN_clear_free(blinding_bn);
err2:
	BN_clear_free(priv_bn);
err1:
	BN_free(two_exp_256_bn);
err0:
	/* Failure! */
	return (-1);
}
Exemple #2
0
ECDSA_SIG *ECDSA_do_sign_ex(const uint8_t *digest, size_t digest_len,
                            const BIGNUM *in_kinv, const BIGNUM *in_r,
                            const EC_KEY *eckey) {
  int ok = 0;
  BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL;
  const BIGNUM *ckinv;
  BN_CTX *ctx = NULL;
  const EC_GROUP *group;
  ECDSA_SIG *ret;
  const BIGNUM *priv_key;

  if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) {
    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NOT_IMPLEMENTED);
    return NULL;
  }

  group = EC_KEY_get0_group(eckey);
  priv_key = EC_KEY_get0_private_key(eckey);

  if (group == NULL || priv_key == NULL) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER);
    return NULL;
  }

  ret = ECDSA_SIG_new();
  if (!ret) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
    return NULL;
  }
  s = ret->s;

  if ((ctx = BN_CTX_new()) == NULL ||
      (tmp = BN_new()) == NULL ||
      (m = BN_new()) == NULL) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
    goto err;
  }

  const BIGNUM *order = EC_GROUP_get0_order(group);

  if (!digest_to_bn(m, digest, digest_len, order)) {
    goto err;
  }
  for (;;) {
    if (in_kinv == NULL || in_r == NULL) {
      if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, digest, digest_len)) {
        OPENSSL_PUT_ERROR(ECDSA, ERR_R_ECDSA_LIB);
        goto err;
      }
      ckinv = kinv;
    } else {
      ckinv = in_kinv;
      if (BN_copy(ret->r, in_r) == NULL) {
        OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
        goto err;
      }
    }

    if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) {
      OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
      goto err;
    }
    if (!BN_mod_add_quick(s, tmp, m, order)) {
      OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
      goto err;
    }
    if (!BN_mod_mul(s, s, ckinv, order, ctx)) {
      OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
      goto err;
    }
    if (BN_is_zero(s)) {
      // if kinv and r have been supplied by the caller
      // don't to generate new kinv and r values
      if (in_kinv != NULL && in_r != NULL) {
        OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NEED_NEW_SETUP_VALUES);
        goto err;
      }
    } else {
      // s != 0 => we have a valid signature
      break;
    }
  }

  ok = 1;

err:
  if (!ok) {
    ECDSA_SIG_free(ret);
    ret = NULL;
  }
  BN_CTX_free(ctx);
  BN_clear_free(m);
  BN_clear_free(tmp);
  BN_clear_free(kinv);
  return ret;
}
Exemple #3
0
/* Shared parts of key derivation and confirmation calculation */
void
jpake_key_confirm(struct modp_group *grp, BIGNUM *s, BIGNUM *step2_val,
    BIGNUM *mypriv2, BIGNUM *mypub1, BIGNUM *mypub2,
    BIGNUM *theirpub1, BIGNUM *theirpub2,
    const u_char *my_id, u_int my_id_len,
    const u_char *their_id, u_int their_id_len,
    const u_char *sess_id, u_int sess_id_len,
    const u_char *theirpriv2_s_proof, u_int theirpriv2_s_proof_len,
    BIGNUM **k,
    u_char **confirm_hash, u_int *confirm_hash_len)
{
	BN_CTX *bn_ctx;
	BIGNUM *tmp;

	if ((bn_ctx = BN_CTX_new()) == NULL)
		fatal("%s: BN_CTX_new", __func__);
	if ((tmp = BN_new()) == NULL ||
	    (*k = BN_new()) == NULL)
		fatal("%s: BN_new", __func__);

	/* Validate step 2 values */
	if (BN_cmp(step2_val, BN_value_one()) <= 0)
		fatal("%s: step2_val <= 1", __func__);
	if (BN_cmp(step2_val, grp->p) >= 0)
		fatal("%s: step2_val >= p", __func__);

	/*
	 * theirpriv2_s_proof is calculated with a different generator:
	 * tmp = g^(mypriv1+mypriv2+theirpub1) = g^mypub1*g^mypub2*g^theirpub1
	 * Calculate it here so we can check the signature.
	 */
	if (BN_mod_mul(tmp, mypub1, mypub2, grp->p, bn_ctx) != 1)
		fatal("%s: BN_mod_mul (tmp = mypub1 * mypub2 mod p)", __func__);
	if (BN_mod_mul(tmp, tmp, theirpub1, grp->p, bn_ctx) != 1)
		fatal("%s: BN_mod_mul (tmp = tmp * theirpub1 mod p)", __func__);

	JPAKE_DEBUG_BN((tmp, "%s: tmp = ", __func__));

	if (schnorr_verify_buf(grp->p, grp->q, tmp, step2_val, 
	    their_id, their_id_len,
	    theirpriv2_s_proof, theirpriv2_s_proof_len) != 1)
		fatal("%s: schnorr_verify theirpriv2_s_proof failed", __func__);

	/*
	 * Derive shared key:
	 *     client: k = (b / g^(x2*x4*s))^x2 = g^((x1+x3)*x2*x4*s)
	 *     server: k = (a / g^(x2*x4*s))^x4 = g^((x1+x3)*x2*x4*s)
	 *
	 * Computed as:
	 *     client: k = (g_x4^(q - (x2 * s)) * b)^x2 mod p
	 *     server: k = (g_x2^(q - (x4 * s)) * b)^x4 mod p
	 */
	if (BN_mul(tmp, mypriv2, s, bn_ctx) != 1)
		fatal("%s: BN_mul (tmp = mypriv2 * s)", __func__);
	if (BN_mod_sub(tmp, grp->q, tmp, grp->q, bn_ctx) != 1)
		fatal("%s: BN_mod_sub (tmp = q - tmp mod q)", __func__);
	if (BN_mod_exp(tmp, theirpub2, tmp, grp->p, bn_ctx) != 1)
		fatal("%s: BN_mod_exp (tmp = theirpub2^tmp) mod p", __func__);
	if (BN_mod_mul(tmp, tmp, step2_val, grp->p, bn_ctx) != 1)
		fatal("%s: BN_mod_mul (tmp = tmp * step2_val) mod p", __func__);
	if (BN_mod_exp(*k, tmp, mypriv2, grp->p, bn_ctx) != 1)
		fatal("%s: BN_mod_exp (k = tmp^mypriv2) mod p", __func__);
	
	BN_CTX_free(bn_ctx);
	BN_clear_free(tmp);

	jpake_confirm_hash(*k, my_id, my_id_len, sess_id, sess_id_len,
	    confirm_hash, confirm_hash_len);
}
Exemple #4
0
static ECDSA_SIG *
ecdsa_do_sign(const unsigned char *dgst, int dgst_len,
    const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey)
{
	int     ok = 0, i;
	BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL, *order = NULL;
	const BIGNUM *ckinv;
	BN_CTX     *ctx = NULL;
	const EC_GROUP   *group;
	ECDSA_SIG  *ret;
	ECDSA_DATA *ecdsa;
	const BIGNUM *priv_key;

	ecdsa = ecdsa_check(eckey);
	group = EC_KEY_get0_group(eckey);
	priv_key = EC_KEY_get0_private_key(eckey);

	if (group == NULL || priv_key == NULL || ecdsa == NULL) {
		ECDSAerror(ERR_R_PASSED_NULL_PARAMETER);
		return NULL;
	}

	ret = ECDSA_SIG_new();
	if (!ret) {
		ECDSAerror(ERR_R_MALLOC_FAILURE);
		return NULL;
	}
	s = ret->s;

	if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL ||
	    (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) {
		ECDSAerror(ERR_R_MALLOC_FAILURE);
		goto err;
	}

	if (!EC_GROUP_get_order(group, order, ctx)) {
		ECDSAerror(ERR_R_EC_LIB);
		goto err;
	}
	i = BN_num_bits(order);
	/* Need to truncate digest if it is too long: first truncate whole
	 * bytes.
	 */
	if (8 * dgst_len > i)
		dgst_len = (i + 7)/8;
	if (!BN_bin2bn(dgst, dgst_len, m)) {
		ECDSAerror(ERR_R_BN_LIB);
		goto err;
	}
	/* If still too long truncate remaining bits with a shift */
	if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) {
		ECDSAerror(ERR_R_BN_LIB);
		goto err;
	}
	do {
		if (in_kinv == NULL || in_r == NULL) {
			if (!ECDSA_sign_setup(eckey, ctx, &kinv, &ret->r)) {
				ECDSAerror(ERR_R_ECDSA_LIB);
				goto err;
			}
			ckinv = kinv;
		} else {
			ckinv = in_kinv;
			if (BN_copy(ret->r, in_r) == NULL) {
				ECDSAerror(ERR_R_MALLOC_FAILURE);
				goto err;
			}
		}

		if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) {
			ECDSAerror(ERR_R_BN_LIB);
			goto err;
		}
		if (!BN_mod_add_quick(s, tmp, m, order)) {
			ECDSAerror(ERR_R_BN_LIB);
			goto err;
		}
		if (!BN_mod_mul(s, s, ckinv, order, ctx)) {
			ECDSAerror(ERR_R_BN_LIB);
			goto err;
		}
		if (BN_is_zero(s)) {
			/* if kinv and r have been supplied by the caller
			 * don't to generate new kinv and r values */
			if (in_kinv != NULL && in_r != NULL) {
				ECDSAerror(ECDSA_R_NEED_NEW_SETUP_VALUES);
				goto err;
			}
		} else
			/* s != 0 => we have a valid signature */
			break;
	} while (1);

	ok = 1;

err:
	if (!ok) {
		ECDSA_SIG_free(ret);
		ret = NULL;
	}
	BN_CTX_free(ctx);
	BN_clear_free(m);
	BN_clear_free(tmp);
	BN_free(order);
	BN_clear_free(kinv);
	return ret;
}
Exemple #5
0
int RSA_check_key(RSA *key)
	{
	BIGNUM *i, *j, *k, *l, *m;
	BN_CTX *ctx;
	int r;
	int ret=1;
	
	i = BN_new();
	j = BN_new();
	k = BN_new();
	l = BN_new();
	m = BN_new();
	ctx = BN_CTX_new();
	if (i == NULL || j == NULL || k == NULL || l == NULL ||
		m == NULL || ctx == NULL)
		{
		ret = -1;
		RSAerr(RSA_F_RSA_CHECK_KEY, ERR_R_MALLOC_FAILURE);
		goto err;
		}
	
	/* p prime? */
	r = BN_is_prime(key->p, BN_prime_checks, NULL, NULL, NULL);
	if (r != 1)
		{
		ret = r;
		if (r != 0)
			goto err;
		RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_P_NOT_PRIME);
		}
	
	/* q prime? */
	r = BN_is_prime(key->q, BN_prime_checks, NULL, NULL, NULL);
	if (r != 1)
		{
		ret = r;
		if (r != 0)
			goto err;
		RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_Q_NOT_PRIME);
		}
	
	/* n = p*q? */
	r = BN_mul(i, key->p, key->q, ctx);
	if (!r) { ret = -1; goto err; }
	
	if (BN_cmp(i, key->n) != 0)
		{
		ret = 0;
		RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_N_DOES_NOT_EQUAL_P_Q);
		}
	
	/* d*e = 1  mod lcm(p-1,q-1)? */

	r = BN_sub(i, key->p, BN_value_one());
	if (!r) { ret = -1; goto err; }
	r = BN_sub(j, key->q, BN_value_one());
	if (!r) { ret = -1; goto err; }

	/* now compute k = lcm(i,j) */
	r = BN_mul(l, i, j, ctx);
	if (!r) { ret = -1; goto err; }
	r = BN_gcd(m, i, j, ctx);
	if (!r) { ret = -1; goto err; }
	r = BN_div(k, NULL, l, m, ctx); /* remainder is 0 */
	if (!r) { ret = -1; goto err; }

	r = BN_mod_mul(i, key->d, key->e, k, ctx);
	if (!r) { ret = -1; goto err; }

	if (!BN_is_one(i))
		{
		ret = 0;
		RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_D_E_NOT_CONGRUENT_TO_1);
		}
	
	if (key->dmp1 != NULL && key->dmq1 != NULL && key->iqmp != NULL)
		{
		/* dmp1 = d mod (p-1)? */
		r = BN_sub(i, key->p, BN_value_one());
		if (!r) { ret = -1; goto err; }

		r = BN_mod(j, key->d, i, ctx);
		if (!r) { ret = -1; goto err; }

		if (BN_cmp(j, key->dmp1) != 0)
			{
			ret = 0;
			RSAerr(RSA_F_RSA_CHECK_KEY,
				RSA_R_DMP1_NOT_CONGRUENT_TO_D);
			}
	
		/* dmq1 = d mod (q-1)? */    
		r = BN_sub(i, key->q, BN_value_one());
		if (!r) { ret = -1; goto err; }
	
		r = BN_mod(j, key->d, i, ctx);
		if (!r) { ret = -1; goto err; }

		if (BN_cmp(j, key->dmq1) != 0)
			{
			ret = 0;
			RSAerr(RSA_F_RSA_CHECK_KEY,
				RSA_R_DMQ1_NOT_CONGRUENT_TO_D);
			}
	
		/* iqmp = q^-1 mod p? */
		if(!BN_mod_inverse(i, key->q, key->p, ctx))
			{
			ret = -1;
			goto err;
			}

		if (BN_cmp(i, key->iqmp) != 0)
			{
			ret = 0;
			RSAerr(RSA_F_RSA_CHECK_KEY,
				RSA_R_IQMP_NOT_INVERSE_OF_Q);
			}
		}

 err:
	if (i != NULL) BN_free(i);
	if (j != NULL) BN_free(j);
	if (k != NULL) BN_free(k);
	if (l != NULL) BN_free(l);
	if (m != NULL) BN_free(m);
	if (ctx != NULL) BN_CTX_free(ctx);
	return (ret);
	}
Exemple #6
0
/* Implementation of CryptoPro VKO 34.10-2001/2012 algorithm */
static int VKO_compute_key(unsigned char *shared_key, size_t shared_key_size,
                           const EC_POINT *pub_key, EC_KEY *priv_key,
                           const unsigned char *ukm, int dgst_nid)
{
    unsigned char *databuf = NULL, *hashbuf = NULL;
    BIGNUM *UKM = NULL, *p = NULL, *order = NULL, *X = NULL, *Y = NULL;
    const BIGNUM *key = EC_KEY_get0_private_key(priv_key);
    EC_POINT *pnt = EC_POINT_new(EC_KEY_get0_group(priv_key));
    int i;
    BN_CTX *ctx = BN_CTX_new();
    EVP_MD_CTX mdctx;
    const EVP_MD *md;
    int effective_dgst_nid = (dgst_nid == NID_id_GostR3411_2012_512) ?
        NID_id_GostR3411_2012_256 : dgst_nid;
    int buf_len = (dgst_nid == NID_id_GostR3411_2012_512) ? 128 : 64,
        half_len = buf_len >> 1;

    if (!ctx) {
        GOSTerr(GOST_F_VKO_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
        return 0;
    }
    BN_CTX_start(ctx);

    databuf = OPENSSL_malloc(buf_len);
    hashbuf = OPENSSL_malloc(buf_len);
    if (!databuf || !hashbuf) {
        GOSTerr(GOST_F_VKO_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    md = EVP_get_digestbynid(effective_dgst_nid);
    if (!md) {
        GOSTerr(GOST_F_VKO_COMPUTE_KEY, GOST_R_INVALID_DIGEST_TYPE);
        goto err;
    }

    UKM = hashsum2bn(ukm, 8);
    p = BN_CTX_get(ctx);
    order = BN_CTX_get(ctx);
    X = BN_CTX_get(ctx);
    Y = BN_CTX_get(ctx);
    EC_GROUP_get_order(EC_KEY_get0_group(priv_key), order, ctx);
    BN_mod_mul(p, key, UKM, order, ctx);
    if (!EC_POINT_mul
        (EC_KEY_get0_group(priv_key), pnt, NULL, pub_key, p, ctx)) {
        GOSTerr(GOST_F_VKO_COMPUTE_KEY, GOST_R_ERROR_POINT_MUL);
        goto err;
    }
    EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(priv_key),
                                        pnt, X, Y, ctx);
    /*
     * Serialize elliptic curve point same way as we do it when saving key
     */
    store_bignum(Y, databuf, half_len);
    store_bignum(X, databuf + half_len, half_len);
    /* And reverse byte order of whole buffer */
    for (i = 0; i < buf_len; i++) {
        hashbuf[buf_len - 1 - i] = databuf[i];
    }
    EVP_MD_CTX_init(&mdctx);
    EVP_DigestInit_ex(&mdctx, md, NULL);
    EVP_DigestUpdate(&mdctx, hashbuf, buf_len);
    EVP_DigestFinal_ex(&mdctx, shared_key, NULL);
    EVP_MD_CTX_cleanup(&mdctx);
 err:
    BN_free(UKM);
    BN_CTX_end(ctx);
    BN_CTX_free(ctx);
    EC_POINT_free(pnt);
    if (databuf)
        OPENSSL_free(databuf);
    if (hashbuf)
        OPENSSL_free(hashbuf);

    return 32;
}
Exemple #7
0
static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len,
                                const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey)
{
    int     ok = 0;
    BIGNUM *kinv=NULL, *s, *m=NULL,*tmp=NULL,*order=NULL;
    const BIGNUM *ckinv;
    BN_CTX     *ctx = NULL;
    const EC_GROUP   *group;
    ECDSA_SIG  *ret;
    ECDSA_DATA *ecdsa;
    const BIGNUM *priv_key;

    ecdsa    = ecdsa_check(eckey);
    group    = EC_KEY_get0_group(eckey);
    priv_key = EC_KEY_get0_private_key(eckey);

    if (group == NULL || priv_key == NULL || ecdsa == NULL)
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER);
        return NULL;
    }

    ret = ECDSA_SIG_new();
    if (!ret)
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
        return NULL;
    }
    s = ret->s;

    if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL ||
            (tmp = BN_new()) == NULL || (m = BN_new()) == NULL)
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    if (!EC_GROUP_get_order(group, order, ctx))
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
        goto err;
    }
    if (dgst_len > BN_num_bytes(order))
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_SIGN,
                 ECDSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
        goto err;
    }

    if (!BN_bin2bn(dgst, dgst_len, m))
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
        goto err;
    }
    do
    {
        if (in_kinv == NULL || in_r == NULL)
        {
            if (!ECDSA_sign_setup(eckey, ctx, &kinv, &ret->r))
            {
                ECDSAerr(ECDSA_F_ECDSA_DO_SIGN,ERR_R_ECDSA_LIB);
                goto err;
            }
            ckinv = kinv;
        }
        else
        {
            ckinv  = in_kinv;
            if (BN_copy(ret->r, in_r) == NULL)
            {
                ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
                goto err;
            }
        }

        if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx))
        {
            ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
            goto err;
        }
        if (!BN_mod_add_quick(s, tmp, m, order))
        {
            ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
            goto err;
        }
        if (!BN_mod_mul(s, s, ckinv, order, ctx))
        {
            ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
            goto err;
        }
    }
    while (BN_is_zero(s));

    ok = 1;
err:
    if (!ok)
    {
        ECDSA_SIG_free(ret);
        ret = NULL;
    }
    if (ctx)
        BN_CTX_free(ctx);
    if (m)
        BN_clear_free(m);
    if (tmp)
        BN_clear_free(tmp);
    if (order)
        BN_free(order);
    if (kinv)
        BN_clear_free(kinv);
    return ret;
}
Exemple #8
0
int test_mont(BIO *bp, BN_CTX *ctx)
	{
	BIGNUM a,b,c,d,A,B;
	BIGNUM n;
	int i;
	BN_MONT_CTX *mont;

	BN_init(&a);
	BN_init(&b);
	BN_init(&c);
	BN_init(&d);
	BN_init(&A);
	BN_init(&B);
	BN_init(&n);

	mont=BN_MONT_CTX_new();

	BN_bntest_rand(&a,100,0,0); /**/
	BN_bntest_rand(&b,100,0,0); /**/
	for (i=0; i<num2; i++)
		{
		int bits = (200*(i+1))/num2;

		if (bits == 0)
			continue;
		BN_bntest_rand(&n,bits,0,1);
		BN_MONT_CTX_set(mont,&n,ctx);

		BN_nnmod(&a,&a,&n,ctx);
		BN_nnmod(&b,&b,&n,ctx);

		BN_to_montgomery(&A,&a,mont,ctx);
		BN_to_montgomery(&B,&b,mont,ctx);

		BN_mod_mul_montgomery(&c,&A,&B,mont,ctx);/**/
		BN_from_montgomery(&A,&c,mont,ctx);/**/
		if (bp != NULL)
			{
			if (!results)
				{
#ifdef undef
fprintf(stderr,"%d * %d %% %d\n",
BN_num_bits(&a),
BN_num_bits(&b),
BN_num_bits(mont->N));
#endif
				BN_print(bp,&a);
				BIO_puts(bp," * ");
				BN_print(bp,&b);
				BIO_puts(bp," % ");
				BN_print(bp,&(mont->N));
				BIO_puts(bp," - ");
				}
			BN_print(bp,&A);
			BIO_puts(bp,"\n");
			}
		BN_mod_mul(&d,&a,&b,&n,ctx);
		BN_sub(&d,&d,&A);
		if(!BN_is_zero(&d))
		    {
		    fprintf(stderr,"Montgomery multiplication test failed!\n");
		    return 0;
		    }
		}
	BN_MONT_CTX_free(mont);
	BN_free(&a);
	BN_free(&b);
	BN_free(&c);
	BN_free(&d);
	BN_free(&A);
	BN_free(&B);
	BN_free(&n);
	return(1);
	}
Exemple #9
0
int test_mod_mul(BIO *bp, BN_CTX *ctx)
	{
	BIGNUM *a,*b,*c,*d,*e;
	int i,j;

	a=BN_new();
	b=BN_new();
	c=BN_new();
	d=BN_new();
	e=BN_new();

	for (j=0; j<3; j++) {
	BN_bntest_rand(c,1024,0,0); /**/
	for (i=0; i<num0; i++)
		{
		BN_bntest_rand(a,475+i*10,0,0); /**/
		BN_bntest_rand(b,425+i*11,0,0); /**/
		a->neg=rand_neg();
		b->neg=rand_neg();
		if (!BN_mod_mul(e,a,b,c,ctx))
			{
			unsigned long l;

			while ((l=ERR_get_error()))
				fprintf(stderr,"ERROR:%s\n",
					ERR_error_string(l,NULL));
			EXIT(1);
			}
		if (bp != NULL)
			{
			if (!results)
				{
				BN_print(bp,a);
				BIO_puts(bp," * ");
				BN_print(bp,b);
				BIO_puts(bp," % ");
				BN_print(bp,c);
				if ((a->neg ^ b->neg) && !BN_is_zero(e))
					{
					/* If  (a*b) % c  is negative,  c  must be added
					 * in order to obtain the normalized remainder
					 * (new with OpenSSL 0.9.7, previous versions of
					 * BN_mod_mul could generate negative results)
					 */
					BIO_puts(bp," + ");
					BN_print(bp,c);
					}
				BIO_puts(bp," - ");
				}
			BN_print(bp,e);
			BIO_puts(bp,"\n");
			}
		BN_mul(d,a,b,ctx);
		BN_sub(d,d,e);
		BN_div(a,b,d,c,ctx);
		if(!BN_is_zero(b))
		    {
		    fprintf(stderr,"Modulo multiply test failed!\n");
		    ERR_print_errors_fp(stderr);
		    return 0;
		    }
		}
	}
	BN_free(a);
	BN_free(b);
	BN_free(c);
	BN_free(d);
	BN_free(e);
	return(1);
	}
Exemple #10
0
BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) 
/* Returns 'ret' such that
 *      ret^2 == a (mod p),
 * using the Tonelli/Shanks algorithm (cf. Henri Cohen, "A Course
 * in Algebraic Computational Number Theory", algorithm 1.5.1).
 * 'p' must be prime!
 */
	{
	BIGNUM *ret = in;
	int err = 1;
	int r;
	BIGNUM *A, *b, *q, *t, *x, *y;
	int e, i, j;
	
	if (!BN_is_odd(p) || BN_abs_is_word(p, 1))
		{
		if (BN_abs_is_word(p, 2))
			{
			if (ret == NULL)
				ret = BN_new();
			if (ret == NULL)
				goto end;
			if (!BN_set_word(ret, BN_is_bit_set(a, 0)))
				{
				if (ret != in)
					BN_free(ret);
				return NULL;
				}
			bn_check_top(ret);
			return ret;
			}

		BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME);
		return(NULL);
		}

	if (BN_is_zero(a) || BN_is_one(a))
		{
		if (ret == NULL)
			ret = BN_new();
		if (ret == NULL)
			goto end;
		if (!BN_set_word(ret, BN_is_one(a)))
			{
			if (ret != in)
				BN_free(ret);
			return NULL;
			}
		bn_check_top(ret);
		return ret;
		}

	BN_CTX_start(ctx);
	A = BN_CTX_get(ctx);
	b = BN_CTX_get(ctx);
	q = BN_CTX_get(ctx);
	t = BN_CTX_get(ctx);
	x = BN_CTX_get(ctx);
	y = BN_CTX_get(ctx);
	if (y == NULL) goto end;
	
	if (ret == NULL)
		ret = BN_new();
	if (ret == NULL) goto end;

	/* A = a mod p */
	if (!BN_nnmod(A, a, p, ctx)) goto end;

	/* now write  |p| - 1  as  2^e*q  where  q  is odd */
	e = 1;
	while (!BN_is_bit_set(p, e))
		e++;
	/* we'll set  q  later (if needed) */

	if (e == 1)
		{
		/* The easy case:  (|p|-1)/2  is odd, so 2 has an inverse
		 * modulo  (|p|-1)/2,  and square roots can be computed
		 * directly by modular exponentiation.
		 * We have
		 *     2 * (|p|+1)/4 == 1   (mod (|p|-1)/2),
		 * so we can use exponent  (|p|+1)/4,  i.e.  (|p|-3)/4 + 1.
		 */
		if (!BN_rshift(q, p, 2)) goto end;
		q->neg = 0;
		if (!BN_add_word(q, 1)) goto end;
		if (!BN_mod_exp(ret, A, q, p, ctx)) goto end;
		err = 0;
		goto vrfy;
		}
	
	if (e == 2)
		{
		/* |p| == 5  (mod 8)
		 *
		 * In this case  2  is always a non-square since
		 * Legendre(2,p) = (-1)^((p^2-1)/8)  for any odd prime.
		 * So if  a  really is a square, then  2*a  is a non-square.
		 * Thus for
		 *      b := (2*a)^((|p|-5)/8),
		 *      i := (2*a)*b^2
		 * we have
		 *     i^2 = (2*a)^((1 + (|p|-5)/4)*2)
		 *         = (2*a)^((p-1)/2)
		 *         = -1;
		 * so if we set
		 *      x := a*b*(i-1),
		 * then
		 *     x^2 = a^2 * b^2 * (i^2 - 2*i + 1)
		 *         = a^2 * b^2 * (-2*i)
		 *         = a*(-i)*(2*a*b^2)
		 *         = a*(-i)*i
		 *         = a.
		 *
		 * (This is due to A.O.L. Atkin, 
		 * <URL: http://listserv.nodak.edu/scripts/wa.exe?A2=ind9211&L=nmbrthry&O=T&P=562>,
		 * November 1992.)
		 */

		/* t := 2*a */
		if (!BN_mod_lshift1_quick(t, A, p)) goto end;

		/* b := (2*a)^((|p|-5)/8) */
		if (!BN_rshift(q, p, 3)) goto end;
		q->neg = 0;
		if (!BN_mod_exp(b, t, q, p, ctx)) goto end;

		/* y := b^2 */
		if (!BN_mod_sqr(y, b, p, ctx)) goto end;

		/* t := (2*a)*b^2 - 1*/
		if (!BN_mod_mul(t, t, y, p, ctx)) goto end;
		if (!BN_sub_word(t, 1)) goto end;

		/* x = a*b*t */
		if (!BN_mod_mul(x, A, b, p, ctx)) goto end;
		if (!BN_mod_mul(x, x, t, p, ctx)) goto end;

		if (!BN_copy(ret, x)) goto end;
		err = 0;
		goto vrfy;
		}
	
	/* e > 2, so we really have to use the Tonelli/Shanks algorithm.
	 * First, find some  y  that is not a square. */
	if (!BN_copy(q, p)) goto end; /* use 'q' as temp */
	q->neg = 0;
	i = 2;
	do
		{
		/* For efficiency, try small numbers first;
		 * if this fails, try random numbers.
		 */
		if (i < 22)
			{
			if (!BN_set_word(y, i)) goto end;
			}
		else
			{
			if (!BN_pseudo_rand(y, BN_num_bits(p), 0, 0)) goto end;
			if (BN_ucmp(y, p) >= 0)
				{
				if (!(p->neg ? BN_add : BN_sub)(y, y, p)) goto end;
				}
			/* now 0 <= y < |p| */
			if (BN_is_zero(y))
				if (!BN_set_word(y, i)) goto end;
			}
		
		r = BN_kronecker(y, q, ctx); /* here 'q' is |p| */
		if (r < -1) goto end;
		if (r == 0)
			{
			/* m divides p */
			BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME);
			goto end;
			}
		}
	while (r == 1 && ++i < 82);
	
	if (r != -1)
		{
		/* Many rounds and still no non-square -- this is more likely
		 * a bug than just bad luck.
		 * Even if  p  is not prime, we should have found some  y
		 * such that r == -1.
		 */
		BNerr(BN_F_BN_MOD_SQRT, BN_R_TOO_MANY_ITERATIONS);
		goto end;
		}

	/* Here's our actual 'q': */
	if (!BN_rshift(q, q, e)) goto end;

	/* Now that we have some non-square, we can find an element
	 * of order  2^e  by computing its q'th power. */
	if (!BN_mod_exp(y, y, q, p, ctx)) goto end;
	if (BN_is_one(y))
		{
		BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME);
		goto end;
		}

	/* Now we know that (if  p  is indeed prime) there is an integer
	 * k,  0 <= k < 2^e,  such that
	 *
	 *      a^q * y^k == 1   (mod p).
	 *
	 * As  a^q  is a square and  y  is not,  k  must be even.
	 * q+1  is even, too, so there is an element
	 *
	 *     X := a^((q+1)/2) * y^(k/2),
	 *
	 * and it satisfies
	 *
	 *     X^2 = a^q * a     * y^k
	 *         = a,
	 *
	 * so it is the square root that we are looking for.
	 */
	
	/* t := (q-1)/2  (note that  q  is odd) */
	if (!BN_rshift1(t, q)) goto end;
	
	/* x := a^((q-1)/2) */
	if (BN_is_zero(t)) /* special case: p = 2^e + 1 */
		{
		if (!BN_nnmod(t, A, p, ctx)) goto end;
		if (BN_is_zero(t))
			{
			/* special case: a == 0  (mod p) */
			BN_zero(ret);
			err = 0;
			goto end;
			}
		else
			if (!BN_one(x)) goto end;
		}
	else
		{
		if (!BN_mod_exp(x, A, t, p, ctx)) goto end;
		if (BN_is_zero(x))
			{
			/* special case: a == 0  (mod p) */
			BN_zero(ret);
			err = 0;
			goto end;
			}
		}

	/* b := a*x^2  (= a^q) */
	if (!BN_mod_sqr(b, x, p, ctx)) goto end;
	if (!BN_mod_mul(b, b, A, p, ctx)) goto end;
	
	/* x := a*x    (= a^((q+1)/2)) */
	if (!BN_mod_mul(x, x, A, p, ctx)) goto end;

	while (1)
		{
		/* Now  b  is  a^q * y^k  for some even  k  (0 <= k < 2^E
		 * where  E  refers to the original value of  e,  which we
		 * don't keep in a variable),  and  x  is  a^((q+1)/2) * y^(k/2).
		 *
		 * We have  a*b = x^2,
		 *    y^2^(e-1) = -1,
		 *    b^2^(e-1) = 1.
		 */

		if (BN_is_one(b))
			{
			if (!BN_copy(ret, x)) goto end;
			err = 0;
			goto vrfy;
			}


		/* find smallest  i  such that  b^(2^i) = 1 */
		i = 1;
		if (!BN_mod_sqr(t, b, p, ctx)) goto end;
		while (!BN_is_one(t))
			{
			i++;
			if (i == e)
				{
				BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE);
				goto end;
				}
			if (!BN_mod_mul(t, t, t, p, ctx)) goto end;
			}
		

		/* t := y^2^(e - i - 1) */
		if (!BN_copy(t, y)) goto end;
		for (j = e - i - 1; j > 0; j--)
			{
			if (!BN_mod_sqr(t, t, p, ctx)) goto end;
			}
		if (!BN_mod_mul(y, t, t, p, ctx)) goto end;
		if (!BN_mod_mul(x, x, t, p, ctx)) goto end;
		if (!BN_mod_mul(b, b, y, p, ctx)) goto end;
		e = i;
		}

 vrfy:
	if (!err)
		{
		/* verify the result -- the input might have been not a square
		 * (test added in 0.9.8) */
		
		if (!BN_mod_sqr(x, ret, p, ctx))
			err = 1;
		
		if (!err && 0 != BN_cmp(x, A))
			{
			BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE);
			err = 1;
			}
		}

 end:
	if (err)
		{
		if (ret != NULL && ret != in)
			{
			BN_clear_free(ret);
			}
		ret = NULL;
		}
	BN_CTX_end(ctx);
	bn_check_top(ret);
	return ret;
	}
Exemple #11
0
int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
                                             EC_POINT *point,
                                             const BIGNUM *x_, int y_bit,
                                             BN_CTX *ctx)
{
    BN_CTX *new_ctx = NULL;
    BIGNUM *tmp1, *tmp2, *x, *y;
    int ret = 0;

    /* clear error queue */
    ERR_clear_error();

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

    y_bit = (y_bit != 0);

    BN_CTX_start(ctx);
    tmp1 = BN_CTX_get(ctx);
    tmp2 = BN_CTX_get(ctx);
    x = BN_CTX_get(ctx);
    y = BN_CTX_get(ctx);
    if (y == NULL)
        goto err;

    /*-
     * Recover y.  We have a Weierstrass equation
     *     y^2 = x^3 + a*x + b,
     * so  y  is one of the square roots of  x^3 + a*x + b.
     */

    /* tmp1 := x^3 */
    if (!BN_nnmod(x, x_, group->field, ctx))
        goto err;
    if (group->meth->field_decode == 0) {
        /* field_{sqr,mul} work on standard representation */
        if (!group->meth->field_sqr(group, tmp2, x_, ctx))
            goto err;
        if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx))
            goto err;
    } else {
        if (!BN_mod_sqr(tmp2, x_, group->field, ctx))
            goto err;
        if (!BN_mod_mul(tmp1, tmp2, x_, group->field, ctx))
            goto err;
    }

    /* tmp1 := tmp1 + a*x */
    if (group->a_is_minus3) {
        if (!BN_mod_lshift1_quick(tmp2, x, group->field))
            goto err;
        if (!BN_mod_add_quick(tmp2, tmp2, x, group->field))
            goto err;
        if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, group->field))
            goto err;
    } else {
        if (group->meth->field_decode) {
            if (!group->meth->field_decode(group, tmp2, group->a, ctx))
                goto err;
            if (!BN_mod_mul(tmp2, tmp2, x, group->field, ctx))
                goto err;
        } else {
            /* field_mul works on standard representation */
            if (!group->meth->field_mul(group, tmp2, group->a, x, ctx))
                goto err;
        }

        if (!BN_mod_add_quick(tmp1, tmp1, tmp2, group->field))
            goto err;
    }

    /* tmp1 := tmp1 + b */
    if (group->meth->field_decode) {
        if (!group->meth->field_decode(group, tmp2, group->b, ctx))
            goto err;
        if (!BN_mod_add_quick(tmp1, tmp1, tmp2, group->field))
            goto err;
    } else {
        if (!BN_mod_add_quick(tmp1, tmp1, group->b, group->field))
            goto err;
    }

    if (!BN_mod_sqrt(y, tmp1, group->field, ctx)) {
        unsigned long err = ERR_peek_last_error();

        if (ERR_GET_LIB(err) == ERR_LIB_BN
            && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) {
            ERR_clear_error();
            ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
                  EC_R_INVALID_COMPRESSED_POINT);
        } else
            ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
                  ERR_R_BN_LIB);
        goto err;
    }

    if (y_bit != BN_is_odd(y)) {
        if (BN_is_zero(y)) {
            int kron;

            kron = BN_kronecker(x, group->field, ctx);
            if (kron == -2)
                goto err;

            if (kron == 1)
                ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
                      EC_R_INVALID_COMPRESSION_BIT);
            else
                /*
                 * BN_mod_sqrt() should have cought this error (not a square)
                 */
                ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
                      EC_R_INVALID_COMPRESSED_POINT);
            goto err;
        }
        if (!BN_usub(y, group->field, y))
            goto err;
    }
    if (y_bit != BN_is_odd(y)) {
        ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
              ERR_R_INTERNAL_ERROR);
        goto err;
    }

    if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx))
        goto err;

    ret = 1;

 err:
    BN_CTX_end(ctx);
    BN_CTX_free(new_ctx);
    return ret;
}
Exemple #12
0
int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) {
  int ret = 0;
  BIGNUM *a, *b, *order, *tmp_1, *tmp_2;
  const BIGNUM *p = &group->field;
  BN_CTX *new_ctx = NULL;

  if (ctx == NULL) {
    ctx = new_ctx = BN_CTX_new();
    if (ctx == NULL) {
      OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
      goto err;
    }
  }
  BN_CTX_start(ctx);
  a = BN_CTX_get(ctx);
  b = BN_CTX_get(ctx);
  tmp_1 = BN_CTX_get(ctx);
  tmp_2 = BN_CTX_get(ctx);
  order = BN_CTX_get(ctx);
  if (order == NULL) {
    goto err;
  }

  if (group->meth->field_decode) {
    if (!group->meth->field_decode(group, a, &group->a, ctx) ||
        !group->meth->field_decode(group, b, &group->b, ctx)) {
      goto err;
    }
  } else {
    if (!BN_copy(a, &group->a) || !BN_copy(b, &group->b)) {
      goto err;
    }
  }

  /* check the discriminant:
   * y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p)
   * 0 =< a, b < p */
  if (BN_is_zero(a)) {
    if (BN_is_zero(b)) {
      goto err;
    }
  } else if (!BN_is_zero(b)) {
    if (!BN_mod_sqr(tmp_1, a, p, ctx) ||
        !BN_mod_mul(tmp_2, tmp_1, a, p, ctx) ||
        !BN_lshift(tmp_1, tmp_2, 2)) {
      goto err;
    }
    /* tmp_1 = 4*a^3 */

    if (!BN_mod_sqr(tmp_2, b, p, ctx) ||
        !BN_mul_word(tmp_2, 27)) {
      goto err;
    }
    /* tmp_2 = 27*b^2 */

    if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx) ||
        BN_is_zero(a)) {
      goto err;
    }
  }
  ret = 1;

err:
  if (ctx != NULL) {
    BN_CTX_end(ctx);
  }
  BN_CTX_free(new_ctx);
  return ret;
}
int
pgp_elgamal_encrypt(PGP_PubKey * pk, PGP_MPI * _m,
					PGP_MPI ** c1_p, PGP_MPI ** c2_p)
{
	int			res = PXE_PGP_MATH_FAILED;
	int			k_bits;
	BIGNUM	   *m = mpi_to_bn(_m);
	BIGNUM	   *p = mpi_to_bn(pk->pub.elg.p);
	BIGNUM	   *g = mpi_to_bn(pk->pub.elg.g);
	BIGNUM	   *y = mpi_to_bn(pk->pub.elg.y);
	BIGNUM	   *k = BN_new();
	BIGNUM	   *yk = BN_new();
	BIGNUM	   *c1 = BN_new();
	BIGNUM	   *c2 = BN_new();
	BN_CTX	   *tmp = BN_CTX_new();

	if (!m || !p || !g || !y || !k || !yk || !c1 || !c2 || !tmp)
		goto err;

	/*
	 * generate k
	 */
	k_bits = decide_k_bits(BN_num_bits(p));
	if (!BN_rand(k, k_bits, 0, 0))
		goto err;

	/*
	 * c1 = g^k c2 = m * y^k
	 */
	if (!BN_mod_exp(c1, g, k, p, tmp))
		goto err;
	if (!BN_mod_exp(yk, y, k, p, tmp))
		goto err;
	if (!BN_mod_mul(c2, m, yk, p, tmp))
		goto err;

	/* result */
	*c1_p = bn_to_mpi(c1);
	*c2_p = bn_to_mpi(c2);
	if (*c1_p && *c2_p)
		res = 0;
err:
	if (tmp)
		BN_CTX_free(tmp);
	if (c2)
		BN_clear_free(c2);
	if (c1)
		BN_clear_free(c1);
	if (yk)
		BN_clear_free(yk);
	if (k)
		BN_clear_free(k);
	if (y)
		BN_clear_free(y);
	if (g)
		BN_clear_free(g);
	if (p)
		BN_clear_free(p);
	if (m)
		BN_clear_free(m);
	return res;
}
Exemple #14
0
/*
 * Refer to FIPS 186-4 C.3.2 Enhanced Miller-Rabin Probabilistic Primality Test.
 * OR C.3.1 Miller-Rabin Probabilistic Primality Test (if enhanced is zero).
 * The Step numbers listed in the code refer to the enhanced case.
 *
 * if enhanced is set, then status returns one of the following:
 *     BN_PRIMETEST_PROBABLY_PRIME
 *     BN_PRIMETEST_COMPOSITE_WITH_FACTOR
 *     BN_PRIMETEST_COMPOSITE_NOT_POWER_OF_PRIME
 * if enhanced is zero, then status returns either
 *     BN_PRIMETEST_PROBABLY_PRIME or
 *     BN_PRIMETEST_COMPOSITE
 *
 * returns 0 if there was an error, otherwise it returns 1.
 */
int bn_miller_rabin_is_prime(const BIGNUM *w, int iterations, BN_CTX *ctx,
                             BN_GENCB *cb, int enhanced, int *status)
{
    int i, j, a, ret = 0;
    BIGNUM *g, *w1, *w3, *x, *m, *z, *b;
    BN_MONT_CTX *mont = NULL;

    /* w must be odd */
    if (!BN_is_odd(w))
        return 0;

    BN_CTX_start(ctx);
    g = BN_CTX_get(ctx);
    w1 = BN_CTX_get(ctx);
    w3 = BN_CTX_get(ctx);
    x = BN_CTX_get(ctx);
    m = BN_CTX_get(ctx);
    z = BN_CTX_get(ctx);
    b = BN_CTX_get(ctx);

    if (!(b != NULL
            /* w1 := w - 1 */
            && BN_copy(w1, w)
            && BN_sub_word(w1, 1)
            /* w3 := w - 3 */
            && BN_copy(w3, w)
            && BN_sub_word(w3, 3)))
        goto err;

    /* check w is larger than 3, otherwise the random b will be too small */
    if (BN_is_zero(w3) || BN_is_negative(w3))
        goto err;

    /* (Step 1) Calculate largest integer 'a' such that 2^a divides w-1 */
    a = 1;
    while (!BN_is_bit_set(w1, a))
        a++;
    /* (Step 2) m = (w-1) / 2^a */
    if (!BN_rshift(m, w1, a))
        goto err;

    /* Montgomery setup for computations mod a */
    mont = BN_MONT_CTX_new();
    if (mont == NULL || !BN_MONT_CTX_set(mont, w, ctx))
        goto err;

    if (iterations == BN_prime_checks)
        iterations = BN_prime_checks_for_size(BN_num_bits(w));

    /* (Step 4) */
    for (i = 0; i < iterations; ++i) {
        /* (Step 4.1) obtain a Random string of bits b where 1 < b < w-1 */
        if (!BN_priv_rand_range(b, w3) || !BN_add_word(b, 2)) /* 1 < b < w-1 */
            goto err;

        if (enhanced) {
            /* (Step 4.3) */
            if (!BN_gcd(g, b, w, ctx))
                goto err;
            /* (Step 4.4) */
            if (!BN_is_one(g)) {
                *status = BN_PRIMETEST_COMPOSITE_WITH_FACTOR;
                ret = 1;
                goto err;
            }
        }
        /* (Step 4.5) z = b^m mod w */
        if (!BN_mod_exp_mont(z, b, m, w, ctx, mont))
            goto err;
        /* (Step 4.6) if (z = 1 or z = w-1) */
        if (BN_is_one(z) || BN_cmp(z, w1) == 0)
            goto outer_loop;
        /* (Step 4.7) for j = 1 to a-1 */
        for (j = 1; j < a ; ++j) {
            /* (Step 4.7.1 - 4.7.2) x = z. z = x^2 mod w */
            if (!BN_copy(x, z) || !BN_mod_mul(z, x, x, w, ctx))
                goto err;
            /* (Step 4.7.3) */
            if (BN_cmp(z, w1) == 0)
                goto outer_loop;
            /* (Step 4.7.4) */
            if (BN_is_one(z))
                goto composite;
        }
        /* At this point z = b^((w-1)/2) mod w */
        /* (Steps 4.8 - 4.9) x = z, z = x^2 mod w */
        if (!BN_copy(x, z) || !BN_mod_mul(z, x, x, w, ctx))
            goto err;
        /* (Step 4.10) */
        if (BN_is_one(z))
            goto composite;
        /* (Step 4.11) x = b^(w-1) mod w */
        if (!BN_copy(x, z))
            goto err;
composite:
        if (enhanced) {
            /* (Step 4.1.2) g = GCD(x-1, w) */
            if (!BN_sub_word(x, 1) || !BN_gcd(g, x, w, ctx))
                goto err;
            /* (Steps 4.1.3 - 4.1.4) */
            if (BN_is_one(g))
                *status = BN_PRIMETEST_COMPOSITE_NOT_POWER_OF_PRIME;
            else
                *status = BN_PRIMETEST_COMPOSITE_WITH_FACTOR;
        } else {
            *status = BN_PRIMETEST_COMPOSITE;
        }
        ret = 1;
        goto err;
outer_loop: ;
        /* (Step 4.1.5) */
        if (!BN_GENCB_call(cb, 1, i))
            goto err;
    }
    /* (Step 5) */
    *status = BN_PRIMETEST_PROBABLY_PRIME;
    ret = 1;
err:
    BN_clear(g);
    BN_clear(w1);
    BN_clear(w3);
    BN_clear(x);
    BN_clear(m);
    BN_clear(z);
    BN_clear(b);
    BN_CTX_end(ctx);
    BN_MONT_CTX_free(mont);
    return ret;
}
Exemple #15
0
int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group,
                                               const EC_POINT *point, BIGNUM *x,
                                               BIGNUM *y, BN_CTX *ctx) {
  BN_CTX *new_ctx = NULL;
  BIGNUM *Z, *Z_1, *Z_2, *Z_3;
  const BIGNUM *Z_;
  int ret = 0;

  if (EC_POINT_is_at_infinity(group, point)) {
    OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
    return 0;
  }

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

  BN_CTX_start(ctx);
  Z = BN_CTX_get(ctx);
  Z_1 = BN_CTX_get(ctx);
  Z_2 = BN_CTX_get(ctx);
  Z_3 = BN_CTX_get(ctx);
  if (Z == NULL || Z_1 == NULL || Z_2 == NULL || Z_3 == NULL) {
    goto err;
  }

  /* transform  (X, Y, Z)  into  (x, y) := (X/Z^2, Y/Z^3) */

  if (group->meth->field_decode) {
    if (!group->meth->field_decode(group, Z, &point->Z, ctx)) {
      goto err;
    }
    Z_ = Z;
  } else {
    Z_ = &point->Z;
  }

  if (BN_is_one(Z_)) {
    if (group->meth->field_decode) {
      if (x != NULL && !group->meth->field_decode(group, x, &point->X, ctx)) {
        goto err;
      }
      if (y != NULL && !group->meth->field_decode(group, y, &point->Y, ctx)) {
        goto err;
      }
    } else {
      if (x != NULL && !BN_copy(x, &point->X)) {
        goto err;
      }
      if (y != NULL && !BN_copy(y, &point->Y)) {
        goto err;
      }
    }
  } else {
    if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx)) {
      OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
      goto err;
    }

    if (group->meth->field_encode == 0) {
      /* field_sqr works on standard representation */
      if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) {
        goto err;
      }
    } else if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) {
      goto err;
    }

    /* in the Montgomery case, field_mul will cancel out Montgomery factor in
     * X: */
    if (x != NULL && !group->meth->field_mul(group, x, &point->X, Z_2, ctx)) {
      goto err;
    }

    if (y != NULL) {
      if (group->meth->field_encode == 0) {
        /* field_mul works on standard representation */
        if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) {
          goto err;
        }
      } else if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) {
        goto err;
      }

      /* in the Montgomery case, field_mul will cancel out Montgomery factor in
       * Y: */
      if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx)) {
        goto err;
      }
    }
  }

  ret = 1;

err:
  BN_CTX_end(ctx);
  BN_CTX_free(new_ctx);
  return ret;
}
Exemple #16
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_check_key, RSA_R_ONLY_ONE_OF_P_Q_GIVEN);
    return 0;
  }

  if (!key->n || !key->e) {
    OPENSSL_PUT_ERROR(RSA, RSA_check_key, 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, RSA_check_key, 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 (/* n = pq */
      !BN_mul(&n, key->p, key->q, ctx) ||
      /* lcm = lcm(p-1, q-1) */
      !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) ||
      !BN_div(&lcm, NULL, &lcm, &gcd, ctx) ||
      /* de = d*e mod lcm(p-1, q-1) */
      !BN_mod_mul(&de, key->d, key->e, &lcm, ctx)) {
    OPENSSL_PUT_ERROR(RSA, RSA_check_key, ERR_LIB_BN);
    goto out;
  }

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

  if (!BN_is_one(&de)) {
    OPENSSL_PUT_ERROR(RSA, RSA_check_key, 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_check_key, RSA_R_INCONSISTENT_SET_OF_CRT_VALUES);
    goto out;
  }

  if (has_crt_values) {
    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, RSA_check_key, 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_check_key, 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;
}
Exemple #17
0
int BN_enhanced_miller_rabin_primality_test(
    enum bn_primality_result_t *out_result, const BIGNUM *w, int iterations,
    BN_CTX *ctx, BN_GENCB *cb) {
  /* Enhanced Miller-Rabin is only valid on odd integers greater than 3. */
  if (!BN_is_odd(w) || BN_cmp_word(w, 3) <= 0) {
    OPENSSL_PUT_ERROR(BN, BN_R_INVALID_INPUT);
    return 0;
  }

  if (iterations == BN_prime_checks) {
    iterations = BN_prime_checks_for_size(BN_num_bits(w));
  }

  int ret = 0;
  BN_MONT_CTX *mont = NULL;

  BN_CTX_start(ctx);

  BIGNUM *w1 = BN_CTX_get(ctx);
  if (w1 == NULL ||
      !BN_copy(w1, w) ||
      !BN_sub_word(w1, 1)) {
    goto err;
  }

  /* Write w1 as m*2^a (Steps 1 and 2). */
  int a = 0;
  while (!BN_is_bit_set(w1, a)) {
    a++;
  }
  BIGNUM *m = BN_CTX_get(ctx);
  if (m == NULL ||
      !BN_rshift(m, w1, a)) {
    goto err;
  }

  BIGNUM *b = BN_CTX_get(ctx);
  BIGNUM *g = BN_CTX_get(ctx);
  BIGNUM *z = BN_CTX_get(ctx);
  BIGNUM *x = BN_CTX_get(ctx);
  BIGNUM *x1 = BN_CTX_get(ctx);
  if (b == NULL ||
      g == NULL ||
      z == NULL ||
      x == NULL ||
      x1 == NULL) {
    goto err;
  }

  /* Montgomery setup for computations mod A */
  mont = BN_MONT_CTX_new();
  if (mont == NULL ||
      !BN_MONT_CTX_set(mont, w, ctx)) {
    goto err;
  }

  /* The following loop performs in inner iteration of the Enhanced Miller-Rabin
   * Primality test (Step 4). */
  for (int i = 1; i <= iterations; i++) {
    /* Step 4.1-4.2 */
    if (!BN_rand_range_ex(b, 2, w1)) {
      goto err;
    }

    /* Step 4.3-4.4 */
    if (!BN_gcd(g, b, w, ctx)) {
      goto err;
    }
    if (BN_cmp_word(g, 1) > 0) {
      *out_result = bn_composite;
      ret = 1;
      goto err;
    }

    /* Step 4.5 */
    if (!BN_mod_exp_mont(z, b, m, w, ctx, mont)) {
      goto err;
    }

    /* Step 4.6 */
    if (BN_is_one(z) || BN_cmp(z, w1) == 0) {
      goto loop;
    }

    /* Step 4.7 */
    for (int j = 1; j < a; j++) {
      if (!BN_copy(x, z) || !BN_mod_mul(z, x, x, w, ctx)) {
        goto err;
      }
      if (BN_cmp(z, w1) == 0) {
        goto loop;
      }
      if (BN_is_one(z)) {
        goto composite;
      }
    }

    /* Step 4.8-4.9 */
    if (!BN_copy(x, z) || !BN_mod_mul(z, x, x, w, ctx)) {
      goto err;
    }

    /* Step 4.10-4.11 */
    if (!BN_is_one(z) && !BN_copy(x, z)) {
      goto err;
    }

 composite:
    /* Step 4.12-4.14 */
    if (!BN_copy(x1, x) ||
        !BN_sub_word(x1, 1) ||
        !BN_gcd(g, x1, w, ctx)) {
      goto err;
    }
    if (BN_cmp_word(g, 1) > 0) {
      *out_result = bn_composite;
    } else {
      *out_result = bn_non_prime_power_composite;
    }

    ret = 1;
    goto err;

 loop:
    /* Step 4.15 */
    if (!BN_GENCB_call(cb, 1, i)) {
      goto err;
    }
  }

  *out_result = bn_probably_prime;
  ret = 1;

err:
  BN_MONT_CTX_free(mont);
  BN_CTX_end(ctx);

  return ret;
}
/*
 * Verifies gost 2001 signature
 *
 */ 
int gost2001_do_verify(const unsigned char *dgst,int dgst_len,
	DSA_SIG *sig, EC_KEY *ec)
	{
	BN_CTX *ctx=BN_CTX_new();
	const EC_GROUP *group = EC_KEY_get0_group(ec);
	BIGNUM *order;
	BIGNUM *md = NULL,*e=NULL,*R=NULL,*v=NULL,*z1=NULL,*z2=NULL;
	BIGNUM *X=NULL,*tmp=NULL;
	EC_POINT *C = NULL;
	const EC_POINT *pub_key=NULL;
	int ok=0;

	BN_CTX_start(ctx);
	order = BN_CTX_get(ctx);
	e = BN_CTX_get(ctx);
	z1 = BN_CTX_get(ctx);
	z2 = BN_CTX_get(ctx);
	tmp = BN_CTX_get(ctx);
	X= BN_CTX_get(ctx);	
	R=BN_CTX_get(ctx);
	v=BN_CTX_get(ctx);
	
	EC_GROUP_get_order(group,order,ctx);
	pub_key = EC_KEY_get0_public_key(ec);
	if (BN_is_zero(sig->s) || BN_is_zero(sig->r) ||
		(BN_cmp(sig->s,order)>=1) || (BN_cmp(sig->r,order)>=1)) 
		{
		GOSTerr(GOST_F_GOST2001_DO_VERIFY,GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
		goto err;

		}
	md = hashsum2bn(dgst);

	BN_mod(e,md,order,ctx);
#ifdef DEBUG_SIGN
	fprintf(stderr,"digest as bignum: ");
	BN_print_fp(stderr,md);
	fprintf(stderr,"\ndigest mod q: ");
	BN_print_fp(stderr,e);
#endif	
	if (BN_is_zero(e)) BN_one(e);
	v=BN_mod_inverse(v,e,order,ctx);
	BN_mod_mul(z1,sig->s,v,order,ctx);
	BN_sub(tmp,order,sig->r);
	BN_mod_mul(z2,tmp,v,order,ctx);
#ifdef DEBUG_SIGN
	fprintf(stderr,"\nInverted digest value: ");
	BN_print_fp(stderr,v);
	fprintf(stderr,"\nz1: ");
	BN_print_fp(stderr,z1);
	fprintf(stderr,"\nz2: ");
	BN_print_fp(stderr,z2);
#endif	
	C = EC_POINT_new(group);
	if (!EC_POINT_mul(group,C,z1,pub_key,z2,ctx)) 
		{	
		GOSTerr(GOST_F_GOST2001_DO_VERIFY,ERR_R_EC_LIB);
		goto err;
		}	
	if (!EC_POINT_get_affine_coordinates_GFp(group,C,X,NULL,ctx)) 
		{
		GOSTerr(GOST_F_GOST2001_DO_VERIFY,ERR_R_EC_LIB);
		goto err;
		}
	BN_mod(R,X,order,ctx);
#ifdef DEBUG_SIGN
	fprintf(stderr,"\nX=");
	BN_print_fp(stderr,X);
	fprintf(stderr,"\nX mod q=");
	BN_print_fp(stderr,R);
	fprintf(stderr,"\n");
#endif	
	if (BN_cmp(R,sig->r)!=0)
		{
		GOSTerr(GOST_F_GOST2001_DO_VERIFY,GOST_R_SIGNATURE_MISMATCH);
		}
	else
		{
		ok = 1;
		}
	err:
	EC_POINT_free(C);
	BN_CTX_end(ctx);
	BN_CTX_free(ctx);
	BN_free(md);
	return ok;
	}
// Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
// recid selects which key is recovered
// if check is non-zero, additional checks are performed
int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check)
{
    if (!eckey) return 0;

    int ret = 0;
    BN_CTX *ctx = NULL;

    BIGNUM *x = NULL;
    BIGNUM *e = NULL;
    BIGNUM *order = NULL;
    BIGNUM *sor = NULL;
    BIGNUM *eor = NULL;
    BIGNUM *field = NULL;
    EC_POINT *R = NULL;
    EC_POINT *O = NULL;
    EC_POINT *Q = NULL;
    BIGNUM *rr = NULL;
    BIGNUM *zero = NULL;
    int n = 0;
    int i = recid / 2;

    const EC_GROUP *group = EC_KEY_get0_group(eckey);
    if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; }
    BN_CTX_start(ctx);
    order = BN_CTX_get(ctx);
    if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; }
    x = BN_CTX_get(ctx);
    if (!BN_copy(x, order)) { ret=-1; goto err; }
    if (!BN_mul_word(x, i)) { ret=-1; goto err; }
    if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; }
    field = BN_CTX_get(ctx);
    if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; }
    if (BN_cmp(x, field) >= 0) { ret=0; goto err; }
    if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
    if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; }
    if (check)
    {
        if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
        if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; }
        if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; }
    }
    if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
    n = EC_GROUP_get_degree(group);
    e = BN_CTX_get(ctx);
    if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; }
    if (8*msglen > n) BN_rshift(e, e, 8-(n & 7));
    zero = BN_CTX_get(ctx);
    if (!BN_zero(zero)) { ret=-1; goto err; }
    if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; }
    rr = BN_CTX_get(ctx);
    if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; }
    sor = BN_CTX_get(ctx);
    if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; }
    eor = BN_CTX_get(ctx);
    if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; }
    if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; }
    if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; }

    ret = 1;

err:
    if (ctx) {
        BN_CTX_end(ctx);
        BN_CTX_free(ctx);
    }
    if (R != NULL) EC_POINT_free(R);
    if (O != NULL) EC_POINT_free(O);
    if (Q != NULL) EC_POINT_free(Q);
    return ret;
}
/*
 * Computes gost2001 signature as DSA_SIG structure 
 *
 *
 */ 
DSA_SIG *gost2001_do_sign(const unsigned char *dgst,int dlen, EC_KEY *eckey)
	{
	DSA_SIG *newsig = NULL;
	BIGNUM *md = hashsum2bn(dgst);
	BIGNUM *order = NULL;
	const EC_GROUP *group;
	const BIGNUM *priv_key;
	BIGNUM *r=NULL,*s=NULL,*X=NULL,*tmp=NULL,*tmp2=NULL, *k=NULL,*e=NULL;
	EC_POINT *C=NULL;
	BN_CTX *ctx = BN_CTX_new();	
	BN_CTX_start(ctx);
	OPENSSL_assert(dlen==32);
	newsig=DSA_SIG_new();
	if (!newsig) 
		{
		GOSTerr(GOST_F_GOST2001_DO_SIGN,GOST_R_NO_MEMORY);
		goto err;
		}	
	group = EC_KEY_get0_group(eckey);
	order=BN_CTX_get(ctx);
	EC_GROUP_get_order(group,order,ctx);
	priv_key = EC_KEY_get0_private_key(eckey);
	e = BN_CTX_get(ctx);
	BN_mod(e,md,order,ctx);
#ifdef DEBUG_SIGN
	fprintf(stderr,"digest as bignum=");
	BN_print_fp(stderr,md);
	fprintf(stderr,"\ndigest mod q=");
	BN_print_fp(stderr,e);
	fprintf(stderr,"\n");
#endif		
	if (BN_is_zero(e))
		{
		BN_one(e);
		}   
	k =BN_CTX_get(ctx);
	C=EC_POINT_new(group);
	do 
		{
		do 
			{
			if (!BN_rand_range(k,order)) 
				{
				GOSTerr(GOST_F_GOST2001_DO_SIGN,GOST_R_RANDOM_NUMBER_GENERATOR_FAILED);
				DSA_SIG_free(newsig);
				goto err;
				}	
			if (!EC_POINT_mul(group,C,k,NULL,NULL,ctx))
				{
				GOSTerr(GOST_F_GOST2001_DO_SIGN,ERR_R_EC_LIB);
				DSA_SIG_free(newsig);
				goto err;
				}	
			if (!X) X=BN_CTX_get(ctx);
			if (!EC_POINT_get_affine_coordinates_GFp(group,C,X,NULL,ctx))
				{
				GOSTerr(GOST_F_GOST2001_DO_SIGN,ERR_R_EC_LIB);
				DSA_SIG_free(newsig);
				goto err;
				}	
			if (!r) r=BN_CTX_get(ctx);
			BN_nnmod(r,X,order,ctx);
			}
		while (BN_is_zero(r));
		/* s =  (r*priv_key+k*e) mod order */
		if (!tmp) tmp = BN_CTX_get(ctx);
		BN_mod_mul(tmp,priv_key,r,order,ctx);
		if (!tmp2) tmp2 = BN_CTX_get(ctx);
		BN_mod_mul(tmp2,k,e,order,ctx);
		if (!s) s=BN_CTX_get(ctx);
		BN_mod_add(s,tmp,tmp2,order,ctx);
		}
	while (BN_is_zero(s));	

	newsig->s=BN_dup(s);
	newsig->r=BN_dup(r);
	err:			
	BN_CTX_end(ctx);
	BN_CTX_free(ctx);
	EC_POINT_free(C);
	BN_free(md);
	return newsig;
	}
Exemple #21
0
static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len,
                           const ECDSA_SIG *sig, EC_KEY *eckey)
{
    int ret = -1;
    BN_CTX   *ctx;
    BIGNUM   *order, *u1, *u2, *m, *X;
    EC_POINT *point = NULL;
    const EC_GROUP *group;
    const EC_POINT *pub_key;

    /* check input values */
    if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL ||
            (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL)
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_MISSING_PARAMETERS);
        return -1;
    }

    ctx = BN_CTX_new();
    if (!ctx)
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
        return -1;
    }
    BN_CTX_start(ctx);
    order = BN_CTX_get(ctx);
    u1    = BN_CTX_get(ctx);
    u2    = BN_CTX_get(ctx);
    m     = BN_CTX_get(ctx);
    X     = BN_CTX_get(ctx);
    if (!X)
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
        goto err;
    }

    if (!EC_GROUP_get_order(group, order, ctx))
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
        goto err;
    }

    if (BN_is_zero(sig->r)          || BN_is_negative(sig->r) ||
            BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s)  ||
            BN_is_negative(sig->s)      || BN_ucmp(sig->s, order) >= 0)
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE);
        ret = 0;	/* signature is invalid */
        goto err;
    }
    /* calculate tmp1 = inv(S) mod order */
    if (!BN_mod_inverse(u2, sig->s, order, ctx))
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
        goto err;
    }
    /* digest -> m */
    if (!BN_bin2bn(dgst, dgst_len, m))
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
        goto err;
    }
    /* u1 = m * tmp mod order */
    if (!BN_mod_mul(u1, m, u2, order, ctx))
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
        goto err;
    }
    /* u2 = r * w mod q */
    if (!BN_mod_mul(u2, sig->r, u2, order, ctx))
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
        goto err;
    }

    if ((point = EC_POINT_new(group)) == NULL)
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx))
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
        goto err;
    }
    if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field)
    {
        if (!EC_POINT_get_affine_coordinates_GFp(group,
                point, X, NULL, ctx))
        {
            ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
            goto err;
        }
    }
    else /* NID_X9_62_characteristic_two_field */
    {
        if (!EC_POINT_get_affine_coordinates_GF2m(group,
                point, X, NULL, ctx))
        {
            ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
            goto err;
        }
    }

    if (!BN_nnmod(u1, X, order, ctx))
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
        goto err;
    }
    /*  if the signature is correct u1 is equal to sig->r */
    ret = (BN_ucmp(u1, sig->r) == 0);
err:
    BN_CTX_end(ctx);
    BN_CTX_free(ctx);
    if (point)
        EC_POINT_free(point);
    return ret;
}
Exemple #22
0
/*
 * Computes gost_ec signature as DSA_SIG structure
 *
 */
DSA_SIG *gost_ec_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey)
{
    DSA_SIG *newsig = NULL, *ret = NULL;
    BIGNUM *md = NULL;
    BIGNUM *order = NULL;
    const EC_GROUP *group;
    const BIGNUM *priv_key;
    BIGNUM *r = NULL, *s = NULL, *X = NULL, *tmp = NULL, *tmp2 = NULL,
        *k = NULL, *e = NULL;
    EC_POINT *C = NULL;
    BN_CTX *ctx;

    OPENSSL_assert(dgst != NULL && eckey != NULL);

    if (!(ctx = BN_CTX_new())) {
        GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_MALLOC_FAILURE);
        return NULL;
    }

    BN_CTX_start(ctx);
    OPENSSL_assert(dlen == 32 || dlen == 64);
    md = hashsum2bn(dgst, dlen);
    newsig = DSA_SIG_new();
    if (!newsig || !md) {
        GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    group = EC_KEY_get0_group(eckey);
    if (!group) {
        GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_INTERNAL_ERROR);
        goto err;
    }
    order = BN_CTX_get(ctx);
    if (!order || !EC_GROUP_get_order(group, order, ctx)) {
        GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_INTERNAL_ERROR);
        goto err;
    }
    priv_key = EC_KEY_get0_private_key(eckey);
    if (!priv_key) {
        GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_INTERNAL_ERROR);
        goto err;
    }
    e = BN_CTX_get(ctx);
    if (!e || !BN_mod(e, md, order, ctx)) {
        GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_INTERNAL_ERROR);
        goto err;
    }
#ifdef DEBUG_SIGN
    fprintf(stderr, "digest as bignum=");
    BN_print_fp(stderr, md);
    fprintf(stderr, "\ndigest mod q=");
    BN_print_fp(stderr, e);
    fprintf(stderr, "\n");
#endif
    if (BN_is_zero(e)) {
        BN_one(e);
    }
    k = BN_CTX_get(ctx);
    C = EC_POINT_new(group);
    if (!k || !C) {
        GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    do {
        do {
            if (!BN_rand_range(k, order)) {
                GOSTerr(GOST_F_GOST_EC_SIGN, GOST_R_RNG_ERROR);
                goto err;
            }
            /*
             * To avoid timing information leaking the length of k,
             * compute C*k using an equivalent scalar of fixed bit-length */
            if (!BN_add(k, k, order)
                || (BN_num_bits(k) <= BN_num_bits(order)
                    && !BN_add(k, k, order))) {
                goto err;
            }
            if (!EC_POINT_mul(group, C, k, NULL, NULL, ctx)) {
                GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_EC_LIB);
                goto err;
            }
            if (!X)
                X = BN_CTX_get(ctx);
            if (!r)
                r = BN_CTX_get(ctx);
            if (!X || !r) {
                GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_MALLOC_FAILURE);
                goto err;
            }
            if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) {
                GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_EC_LIB);
                goto err;
            }

            if (!BN_nnmod(r, X, order, ctx)) {
                GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_INTERNAL_ERROR);
                goto err;
            }
        }
        while (BN_is_zero(r));
        /* s =  (r*priv_key+k*e) mod order */
        if (!tmp)
            tmp = BN_CTX_get(ctx);
        if (!tmp2)
            tmp2 = BN_CTX_get(ctx);
        if (!s)
            s = BN_CTX_get(ctx);
        if (!tmp || !tmp2 || !s) {
            GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_MALLOC_FAILURE);
            goto err;
        }

        if (!BN_mod_mul(tmp, priv_key, r, order, ctx)
            || !BN_mod_mul(tmp2, k, e, order, ctx)
            || !BN_mod_add(s, tmp, tmp2, order, ctx)) {
            GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_INTERNAL_ERROR);
            goto err;
        }
    }
    while (BN_is_zero(s));

    newsig->s = BN_dup(s);
    newsig->r = BN_dup(r);
    if (!newsig->s || !newsig->r) {
        GOSTerr(GOST_F_GOST_EC_SIGN, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    ret = newsig;
 err:
    BN_CTX_end(ctx);
    BN_CTX_free(ctx);
    if (C)
        EC_POINT_free(C);
    if (md)
        BN_free(md);
    if (!ret && newsig) {
        DSA_SIG_free(newsig);
    }
    return ret;
}
Exemple #23
0
static int
ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig,
    EC_KEY *eckey)
{
	int ret = -1, i;
	BN_CTX   *ctx;
	BIGNUM   *order, *u1, *u2, *m, *X;
	EC_POINT *point = NULL;
	const EC_GROUP *group;
	const EC_POINT *pub_key;

	/* check input values */
	if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL ||
	    (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL) {
		ECDSAerror(ECDSA_R_MISSING_PARAMETERS);
		return -1;
	}

	ctx = BN_CTX_new();
	if (!ctx) {
		ECDSAerror(ERR_R_MALLOC_FAILURE);
		return -1;
	}
	BN_CTX_start(ctx);
	order = BN_CTX_get(ctx);
	u1 = BN_CTX_get(ctx);
	u2 = BN_CTX_get(ctx);
	m = BN_CTX_get(ctx);
	X = BN_CTX_get(ctx);
	if (!X) {
		ECDSAerror(ERR_R_BN_LIB);
		goto err;
	}

	if (!EC_GROUP_get_order(group, order, ctx)) {
		ECDSAerror(ERR_R_EC_LIB);
		goto err;
	}

	if (BN_is_zero(sig->r)          || BN_is_negative(sig->r) ||
	    BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s)  ||
	    BN_is_negative(sig->s)      || BN_ucmp(sig->s, order) >= 0) {
		ECDSAerror(ECDSA_R_BAD_SIGNATURE);
		ret = 0;	/* signature is invalid */
		goto err;
	}
	/* calculate tmp1 = inv(S) mod order */
	if (!BN_mod_inverse_ct(u2, sig->s, order, ctx)) {
		ECDSAerror(ERR_R_BN_LIB);
		goto err;
	}
	/* digest -> m */
	i = BN_num_bits(order);
	/* Need to truncate digest if it is too long: first truncate whole
	 * bytes.
	 */
	if (8 * dgst_len > i)
		dgst_len = (i + 7)/8;
	if (!BN_bin2bn(dgst, dgst_len, m)) {
		ECDSAerror(ERR_R_BN_LIB);
		goto err;
	}
	/* If still too long truncate remaining bits with a shift */
	if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) {
		ECDSAerror(ERR_R_BN_LIB);
		goto err;
	}
	/* u1 = m * tmp mod order */
	if (!BN_mod_mul(u1, m, u2, order, ctx)) {
		ECDSAerror(ERR_R_BN_LIB);
		goto err;
	}
	/* u2 = r * w mod q */
	if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) {
		ECDSAerror(ERR_R_BN_LIB);
		goto err;
	}

	if ((point = EC_POINT_new(group)) == NULL) {
		ECDSAerror(ERR_R_MALLOC_FAILURE);
		goto err;
	}
	if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) {
		ECDSAerror(ERR_R_EC_LIB);
		goto err;
	}
	if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
	    NID_X9_62_prime_field) {
		if (!EC_POINT_get_affine_coordinates_GFp(group,
		    point, X, NULL, ctx)) {
			ECDSAerror(ERR_R_EC_LIB);
			goto err;
		}
	}
#ifndef OPENSSL_NO_EC2M
	else /* NID_X9_62_characteristic_two_field */
	{
		if (!EC_POINT_get_affine_coordinates_GF2m(group,
		    point, X, NULL, ctx)) {
			ECDSAerror(ERR_R_EC_LIB);
			goto err;
		}
	}
#endif
	if (!BN_nnmod(u1, X, order, ctx)) {
		ECDSAerror(ERR_R_BN_LIB);
		goto err;
	}
	/*  if the signature is correct u1 is equal to sig->r */
	ret = (BN_ucmp(u1, sig->r) == 0);

err:
	BN_CTX_end(ctx);
	BN_CTX_free(ctx);
	EC_POINT_free(point);
	return ret;
}
Exemple #24
0
/*
 * Verifies gost ec signature
 *
 */
int gost_ec_verify(const unsigned char *dgst, int dgst_len,
                   DSA_SIG *sig, EC_KEY *ec)
{
    BN_CTX *ctx;
    const EC_GROUP *group = (ec) ? EC_KEY_get0_group(ec) : NULL;
    BIGNUM *order;
    BIGNUM *md = NULL, *e = NULL, *R = NULL, *v = NULL,
        *z1 = NULL, *z2 = NULL;
    BIGNUM *X = NULL, *tmp = NULL;
    EC_POINT *C = NULL;
    const EC_POINT *pub_key = NULL;
    int ok = 0;

    OPENSSL_assert(dgst != NULL && sig != NULL && group != NULL);

    if (!(ctx = BN_CTX_new())) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, ERR_R_MALLOC_FAILURE);
        return 0;
    }

    BN_CTX_start(ctx);
    order = BN_CTX_get(ctx);
    e = BN_CTX_get(ctx);
    z1 = BN_CTX_get(ctx);
    z2 = BN_CTX_get(ctx);
    tmp = BN_CTX_get(ctx);
    X = BN_CTX_get(ctx);
    R = BN_CTX_get(ctx);
    v = BN_CTX_get(ctx);
    if (!order || !e || !z1 || !z2 || !tmp || !X || !R || !v) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    pub_key = EC_KEY_get0_public_key(ec);
    if (!pub_key || !EC_GROUP_get_order(group, order, ctx)) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, ERR_R_INTERNAL_ERROR);
        goto err;
    }

    if (BN_is_zero(sig->s) || BN_is_zero(sig->r) ||
        (BN_cmp(sig->s, order) >= 1) || (BN_cmp(sig->r, order) >= 1)) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
        goto err;

    }

    OPENSSL_assert(dgst_len == 32 || dgst_len == 64);
    md = hashsum2bn(dgst, dgst_len);
    if (!md || !BN_mod(e, md, order, ctx)) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, ERR_R_INTERNAL_ERROR);
        goto err;
    }
#ifdef DEBUG_SIGN
    fprintf(stderr, "digest as bignum: ");
    BN_print_fp(stderr, md);
    fprintf(stderr, "\ndigest mod q: ");
    BN_print_fp(stderr, e);
#endif
    if (BN_is_zero(e) && !BN_one(e)) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, ERR_R_INTERNAL_ERROR);
        goto err;
    }
    v = BN_mod_inverse(v, e, order, ctx);
    if (!v || !BN_mod_mul(z1, sig->s, v, order, ctx)
        || !BN_sub(tmp, order, sig->r)
        || !BN_mod_mul(z2, tmp, v, order, ctx)) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, ERR_R_INTERNAL_ERROR);
        goto err;
    }
#ifdef DEBUG_SIGN
    fprintf(stderr, "\nInverted digest value: ");
    BN_print_fp(stderr, v);
    fprintf(stderr, "\nz1: ");
    BN_print_fp(stderr, z1);
    fprintf(stderr, "\nz2: ");
    BN_print_fp(stderr, z2);
#endif
    C = EC_POINT_new(group);
    if (!C) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    if (!EC_POINT_mul(group, C, z1, pub_key, z2, ctx)) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, ERR_R_EC_LIB);
        goto err;
    }
    if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, ERR_R_EC_LIB);
        goto err;
    }
    if (!BN_mod(R, X, order, ctx)) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, ERR_R_INTERNAL_ERROR);
        goto err;
    }
#ifdef DEBUG_SIGN
    fprintf(stderr, "\nX=");
    BN_print_fp(stderr, X);
    fprintf(stderr, "\nX mod q=");
    BN_print_fp(stderr, R);
    fprintf(stderr, "\n");
#endif
    if (BN_cmp(R, sig->r) != 0) {
        GOSTerr(GOST_F_GOST_EC_VERIFY, GOST_R_SIGNATURE_MISMATCH);
    } else {
        ok = 1;
    }
 err:
    if (C)
        EC_POINT_free(C);
    BN_CTX_end(ctx);
    BN_CTX_free(ctx);
    if (md)
        BN_free(md);
    return ok;
}
Exemple #25
0
int ECDSA_do_verify(const uint8_t *digest, size_t digest_len,
                    const ECDSA_SIG *sig, const EC_KEY *eckey) {
  int ret = 0;
  BN_CTX *ctx;
  BIGNUM *u1, *u2, *m, *X;
  EC_POINT *point = NULL;
  const EC_GROUP *group;
  const EC_POINT *pub_key;

  // check input values
  if ((group = EC_KEY_get0_group(eckey)) == NULL ||
      (pub_key = EC_KEY_get0_public_key(eckey)) == NULL ||
      sig == NULL) {
    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_MISSING_PARAMETERS);
    return 0;
  }

  ctx = BN_CTX_new();
  if (!ctx) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
    return 0;
  }
  BN_CTX_start(ctx);
  u1 = BN_CTX_get(ctx);
  u2 = BN_CTX_get(ctx);
  m = BN_CTX_get(ctx);
  X = BN_CTX_get(ctx);
  if (u1 == NULL || u2 == NULL || m == NULL || X == NULL) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
    goto err;
  }

  const BIGNUM *order = EC_GROUP_get0_order(group);
  if (BN_is_zero(sig->r) || BN_is_negative(sig->r) ||
      BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) ||
      BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) {
    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE);
    goto err;
  }
  // calculate tmp1 = inv(S) mod order
  int no_inverse;
  if (!BN_mod_inverse_odd(u2, &no_inverse, sig->s, order, ctx)) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
    goto err;
  }
  if (!digest_to_bn(m, digest, digest_len, order)) {
    goto err;
  }
  // u1 = m * tmp mod order
  if (!BN_mod_mul(u1, m, u2, order, ctx)) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
    goto err;
  }
  // u2 = r * w mod q
  if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
    goto err;
  }

  point = EC_POINT_new(group);
  if (point == NULL) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
    goto err;
  }
  if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB);
    goto err;
  }
  if (!EC_POINT_get_affine_coordinates_GFp(group, point, X, NULL, ctx)) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB);
    goto err;
  }
  if (!BN_nnmod(u1, X, order, ctx)) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
    goto err;
  }
  // if the signature is correct u1 is equal to sig->r
  if (BN_ucmp(u1, sig->r) != 0) {
    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE);
    goto err;
  }

  ret = 1;

err:
  BN_CTX_end(ctx);
  BN_CTX_free(ctx);
  EC_POINT_free(point);
  return ret;
}
Exemple #26
0
/*
 * Generate Schnorr signature to prove knowledge of private value 'x' used
 * in public exponent g^x, under group defined by 'grp_p', 'grp_q' and 'grp_g'
 * using the hash function "evp_md".
 * 'idlen' bytes from 'id' will be included in the signature hash as an anti-
 * replay salt.
 *
 * On success, 0 is returned. The signature values are returned as *e_p
 * (g^v mod p) and *r_p (v - xh mod q). The caller must free these values.
 * On failure, -1 is returned.
 */
int
schnorr_sign(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
             const EVP_MD *evp_md, const BIGNUM *x, const BIGNUM *g_x,
             const u_char *id, u_int idlen, BIGNUM **r_p, BIGNUM **e_p)
{
    int success = -1;
    BIGNUM *h, *tmp, *v, *g_v, *r;
    BN_CTX *bn_ctx;

    SCHNORR_DEBUG_BN((x, "%s: x = ", __func__));
    SCHNORR_DEBUG_BN((g_x, "%s: g_x = ", __func__));

    /* Avoid degenerate cases: g^0 yields a spoofable signature */
    if (BN_cmp(g_x, BN_value_one()) <= 0) {
        error("%s: g_x < 1", __func__);
        return -1;
    }
    if (BN_cmp(g_x, grp_p) >= 0) {
        error("%s: g_x > g", __func__);
        return -1;
    }

    h = g_v = r = tmp = v = NULL;
    if ((bn_ctx = BN_CTX_new()) == NULL) {
        error("%s: BN_CTX_new", __func__);
        goto out;
    }
    if ((g_v = BN_new()) == NULL ||
            (r = BN_new()) == NULL ||
            (tmp = BN_new()) == NULL) {
        error("%s: BN_new", __func__);
        goto out;
    }

    /*
     * v must be a random element of Zq, so 1 <= v < q
     * we also exclude v = 1, since g^1 looks dangerous
     */
    if ((v = bn_rand_range_gt_one(grp_p)) == NULL) {
        error("%s: bn_rand_range2", __func__);
        goto out;
    }
    SCHNORR_DEBUG_BN((v, "%s: v = ", __func__));

    /* g_v = g^v mod p */
    if (BN_mod_exp(g_v, grp_g, v, grp_p, bn_ctx) == -1) {
        error("%s: BN_mod_exp (g^v mod p)", __func__);
        goto out;
    }
    SCHNORR_DEBUG_BN((g_v, "%s: g_v = ", __func__));

    /* h = H(g || g^v || g^x || id) */
    if ((h = schnorr_hash(grp_p, grp_q, grp_g, evp_md, g_v, g_x,
                          id, idlen)) == NULL) {
        error("%s: schnorr_hash failed", __func__);
        goto out;
    }

    /* r = v - xh mod q */
    if (BN_mod_mul(tmp, x, h, grp_q, bn_ctx) == -1) {
        error("%s: BN_mod_mul (tmp = xv mod q)", __func__);
        goto out;
    }
    if (BN_mod_sub(r, v, tmp, grp_q, bn_ctx) == -1) {
        error("%s: BN_mod_mul (r = v - tmp)", __func__);
        goto out;
    }
    SCHNORR_DEBUG_BN((g_v, "%s: e = ", __func__));
    SCHNORR_DEBUG_BN((r, "%s: r = ", __func__));

    *e_p = g_v;
    *r_p = r;

    success = 0;
out:
    BN_CTX_free(bn_ctx);
    if (h != NULL)
        BN_clear_free(h);
    if (v != NULL)
        BN_clear_free(v);
    BN_clear_free(tmp);

    return success;
}
Exemple #27
0
/* Shared parts of step 2 exchange calculation */
void
jpake_step2(struct modp_group *grp, BIGNUM *s,
    BIGNUM *mypub1, BIGNUM *theirpub1, BIGNUM *theirpub2, BIGNUM *mypriv2,
    const u_char *theirid, u_int theirid_len,
    const u_char *myid, u_int myid_len,
    const u_char *theirpub1_proof, u_int theirpub1_proof_len,
    const u_char *theirpub2_proof, u_int theirpub2_proof_len,
    BIGNUM **newpub,
    u_char **newpub_exponent_proof, u_int *newpub_exponent_proof_len)
{
	BN_CTX *bn_ctx;
	BIGNUM *tmp, *exponent;

	/* Validate peer's step 1 values */
	if (BN_cmp(theirpub1, BN_value_one()) <= 0)
		fatal("%s: theirpub1 <= 1", __func__);
	if (BN_cmp(theirpub1, grp->p) >= 0)
		fatal("%s: theirpub1 >= p", __func__);
	if (BN_cmp(theirpub2, BN_value_one()) <= 0)
		fatal("%s: theirpub2 <= 1", __func__);
	if (BN_cmp(theirpub2, grp->p) >= 0)
		fatal("%s: theirpub2 >= p", __func__);

	if (schnorr_verify_buf(grp->p, grp->q, grp->g, theirpub1,
	    theirid, theirid_len, theirpub1_proof, theirpub1_proof_len) != 1)
		fatal("%s: schnorr_verify theirpub1 failed", __func__);
	if (schnorr_verify_buf(grp->p, grp->q, grp->g, theirpub2,
	    theirid, theirid_len, theirpub2_proof, theirpub2_proof_len) != 1)
		fatal("%s: schnorr_verify theirpub2 failed", __func__);

	if ((bn_ctx = BN_CTX_new()) == NULL)
		fatal("%s: BN_CTX_new", __func__);

	if ((*newpub = BN_new()) == NULL ||
	    (tmp = BN_new()) == NULL ||
	    (exponent = BN_new()) == NULL)
		fatal("%s: BN_new", __func__);

	/*
	 * client: exponent = x2 * s mod p
	 * server: exponent = x4 * s mod p
	 */
	if (BN_mod_mul(exponent, mypriv2, s, grp->q, bn_ctx) != 1)
		fatal("%s: BN_mod_mul (exponent = mypriv2 * s mod p)",
		    __func__);

	/*
	 * client: tmp = g^(x1 + x3 + x4) mod p
	 * server: tmp = g^(x1 + x2 + x3) mod p
	 */
	if (BN_mod_mul(tmp, mypub1, theirpub1, grp->p, bn_ctx) != 1)
		fatal("%s: BN_mod_mul (tmp = mypub1 * theirpub1 mod p)",
		    __func__);
	if (BN_mod_mul(tmp, tmp, theirpub2, grp->p, bn_ctx) != 1)
		fatal("%s: BN_mod_mul (tmp = tmp * theirpub2 mod p)", __func__);

	/*
	 * client: a = tmp^exponent = g^((x1+x3+x4) * x2 * s) mod p
	 * server: b = tmp^exponent = g^((x1+x2+x3) * x4 * s) mod p
	 */
	if (BN_mod_exp(*newpub, tmp, exponent, grp->p, bn_ctx) != 1)
		fatal("%s: BN_mod_mul (newpub = tmp^exponent mod p)", __func__);

	JPAKE_DEBUG_BN((tmp, "%s: tmp = ", __func__));
	JPAKE_DEBUG_BN((exponent, "%s: exponent = ", __func__));

	/* Note the generator here is 'tmp', not g */
	if (schnorr_sign_buf(grp->p, grp->q, tmp, exponent, *newpub,
	    myid, myid_len,
	    newpub_exponent_proof, newpub_exponent_proof_len) != 0)
		fatal("%s: schnorr_sign newpub", __func__);

	BN_clear_free(tmp); /* XXX stash for later use? */
	BN_clear_free(exponent); /* XXX stash for later use? (yes, in conf) */

	BN_CTX_free(bn_ctx);
}
Exemple #28
0
/*
 * Verify Schnorr signature { r (v - xh mod q), e (g^v mod p) } against
 * public exponent g_x (g^x) under group defined by 'grp_p', 'grp_q' and
 * 'grp_g' using hash "evp_md".
 * Signature hash will be salted with 'idlen' bytes from 'id'.
 * Returns -1 on failure, 0 on incorrect signature or 1 on matching signature.
 */
int
schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
               const EVP_MD *evp_md, const BIGNUM *g_x, const u_char *id, u_int idlen,
               const BIGNUM *r, const BIGNUM *e)
{
    int success = -1;
    BIGNUM *h = NULL, *g_xh = NULL, *g_r = NULL, *gx_q = NULL;
    BIGNUM *expected = NULL;
    BN_CTX *bn_ctx;

    SCHNORR_DEBUG_BN((g_x, "%s: g_x = ", __func__));

    /* Avoid degenerate cases: g^0 yields a spoofable signature */
    if (BN_cmp(g_x, BN_value_one()) <= 0) {
        error("%s: g_x <= 1", __func__);
        return -1;
    }
    if (BN_cmp(g_x, grp_p) >= 0) {
        error("%s: g_x >= p", __func__);
        return -1;
    }

    h = g_xh = g_r = expected = NULL;
    if ((bn_ctx = BN_CTX_new()) == NULL) {
        error("%s: BN_CTX_new", __func__);
        goto out;
    }
    if ((g_xh = BN_new()) == NULL ||
            (g_r = BN_new()) == NULL ||
            (gx_q = BN_new()) == NULL ||
            (expected = BN_new()) == NULL) {
        error("%s: BN_new", __func__);
        goto out;
    }

    SCHNORR_DEBUG_BN((e, "%s: e = ", __func__));
    SCHNORR_DEBUG_BN((r, "%s: r = ", __func__));

    /* gx_q = (g^x)^q must === 1 mod p */
    if (BN_mod_exp(gx_q, g_x, grp_q, grp_p, bn_ctx) == -1) {
        error("%s: BN_mod_exp (g_x^q mod p)", __func__);
        goto out;
    }
    if (BN_cmp(gx_q, BN_value_one()) != 0) {
        error("%s: Invalid signature (g^x)^q != 1 mod p", __func__);
        goto out;
    }

    SCHNORR_DEBUG_BN((g_xh, "%s: g_xh = ", __func__));
    /* h = H(g || g^v || g^x || id) */
    if ((h = schnorr_hash(grp_p, grp_q, grp_g, evp_md, e, g_x,
                          id, idlen)) == NULL) {
        error("%s: schnorr_hash failed", __func__);
        goto out;
    }

    /* g_xh = (g^x)^h */
    if (BN_mod_exp(g_xh, g_x, h, grp_p, bn_ctx) == -1) {
        error("%s: BN_mod_exp (g_x^h mod p)", __func__);
        goto out;
    }
    SCHNORR_DEBUG_BN((g_xh, "%s: g_xh = ", __func__));

    /* g_r = g^r */
    if (BN_mod_exp(g_r, grp_g, r, grp_p, bn_ctx) == -1) {
        error("%s: BN_mod_exp (g_x^h mod p)", __func__);
        goto out;
    }
    SCHNORR_DEBUG_BN((g_r, "%s: g_r = ", __func__));

    /* expected = g^r * g_xh */
    if (BN_mod_mul(expected, g_r, g_xh, grp_p, bn_ctx) == -1) {
        error("%s: BN_mod_mul (expected = g_r mod p)", __func__);
        goto out;
    }
    SCHNORR_DEBUG_BN((expected, "%s: expected = ", __func__));

    /* Check e == expected */
    success = BN_cmp(expected, e) == 0;
out:
    BN_CTX_free(bn_ctx);
    if (h != NULL)
        BN_clear_free(h);
    if (gx_q != NULL)
        BN_clear_free(gx_q);
    if (g_xh != NULL)
        BN_clear_free(g_xh);
    if (g_r != NULL)
        BN_clear_free(g_r);
    if (expected != NULL)
        BN_clear_free(expected);
    return success;
}
int ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
{
    return BN_mod_mul(r, a, b, &group->field, ctx);
}
static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig,
      DSA *dsa)
  {
  BN_CTX *ctx;
  BIGNUM u1,u2,t1;
  BN_MONT_CTX *mont=NULL;
  int ret = -1;
  if (!dsa->p || !dsa->q || !dsa->g)
    {
    DSAerr(DSA_F_DSA_DO_VERIFY,DSA_R_MISSING_PARAMETERS);
    return -1;
    }

  BN_init(&u1);
  BN_init(&u2);
  BN_init(&t1);

  if ((ctx=BN_CTX_new()) == NULL) goto err;

  if (BN_is_zero(sig->r) || BN_is_negative(sig->r) ||
      BN_ucmp(sig->r, dsa->q) >= 0)
    {
    ret = 0;
    goto err;
    }
  if (BN_is_zero(sig->s) || BN_is_negative(sig->s) ||
      BN_ucmp(sig->s, dsa->q) >= 0)
    {
    ret = 0;
    goto err;
    }

  /* Calculate W = inv(S) mod Q
   * save W in u2 */
  if ((BN_mod_inverse(&u2,sig->s,dsa->q,ctx)) == NULL) goto err;

  /* save M in u1 */
  if (BN_bin2bn(dgst,dgst_len,&u1) == NULL) goto err;

  /* u1 = M * w mod q */
  if (!BN_mod_mul(&u1,&u1,&u2,dsa->q,ctx)) goto err;

  /* u2 = r * w mod q */
  if (!BN_mod_mul(&u2,sig->r,&u2,dsa->q,ctx)) goto err;


  if (dsa->flags & DSA_FLAG_CACHE_MONT_P)
    {
    mont = BN_MONT_CTX_set_locked(&dsa->method_mont_p,
          CRYPTO_LOCK_DSA, dsa->p, ctx);
    if (!mont)
      goto err;
    }


  DSA_MOD_EXP(goto err, dsa, &t1, dsa->g, &u1, dsa->pub_key, &u2, dsa->p, ctx, mont);
  /* BN_copy(&u1,&t1); */
  /* let u1 = u1 mod q */
  if (!BN_mod(&u1,&t1,dsa->q,ctx)) goto err;

  /* V is now in u1.  If the signature is correct, it will be
   * equal to R. */
  ret=(BN_ucmp(&u1, sig->r) == 0);

  err:
  /* XXX: surely this is wrong - if ret is 0, it just didn't verify;
     there is no error in BN. Test should be ret == -1 (Ben) */
  if (ret != 1) DSAerr(DSA_F_DSA_DO_VERIFY,ERR_R_BN_LIB);
  if (ctx != NULL) BN_CTX_free(ctx);
  BN_free(&u1);
  BN_free(&u2);
  BN_free(&t1);
  return(ret);
  }