Exemplo n.º 1
0
static void eap_pwd_reset(struct eap_sm *sm, void *priv)
{
	struct eap_pwd_data *data = priv;

	BN_clear_free(data->private_value);
	BN_clear_free(data->peer_scalar);
	BN_clear_free(data->my_scalar);
	BN_clear_free(data->k);
	BN_CTX_free(data->bnctx);
	EC_POINT_clear_free(data->my_element);
	EC_POINT_clear_free(data->peer_element);
	bin_clear_free(data->id_peer, data->id_peer_len);
	bin_clear_free(data->id_server, data->id_server_len);
	bin_clear_free(data->password, data->password_len);
	if (data->grp) {
		EC_GROUP_free(data->grp->group);
		EC_POINT_clear_free(data->grp->pwe);
		BN_clear_free(data->grp->order);
		BN_clear_free(data->grp->prime);
		os_free(data->grp);
	}
	wpabuf_free(data->inbuf);
	wpabuf_free(data->outbuf);
	bin_clear_free(data, sizeof(*data));
}
Exemplo n.º 2
0
int
MKEM_decode_message(const MKEM *kp, uint8_t *secret, const uint8_t *message)
{
  int use_curve0 = !(message[0] & kp->params->curve_bit);
  const EC_GROUP *ca = use_curve0 ? kp->params->c0 : kp->params->c1;
  const BIGNUM *sa = use_curve0 ? kp->s0 : kp->s1;
  EC_POINT *q = 0, *r = 0;
  uint8_t *unpadded = 0;
  BIGNUM x, y;
  size_t mlen = kp->params->msgsize;
  int rv;

  if (!kp->s0 || !kp->s1) /* secret key not available */
    return -1;

  BN_init(&x);
  BN_init(&y);
  FAILZ(q = EC_POINT_new(ca));
  FAILZ(r = EC_POINT_new(ca));
  FAILZ(unpadded = malloc(mlen + 1));

  /* Copy the message, erase the padding bits, and put an 0x02 byte on
     the front so we can use EC_POINT_oct2point to recover the
     y-coordinate. */
  unpadded[0] = 0x02;
  unpadded[1] = (message[0] & ~(kp->params->pad_mask|kp->params->curve_bit));
  memcpy(&unpadded[2], &message[1], mlen - 1);

  FAILZ(EC_POINT_oct2point(ca, q, unpadded, mlen + 1,
                           kp->params->ctx));
  FAILZ(EC_POINT_mul(ca, r, 0, q, sa, kp->params->ctx));

  FAILZ(EC_POINT_get_affine_coordinates_GF2m(ca, q, &x, &y, kp->params->ctx));
  if (bn2bin_padhi(&x, secret, mlen) != mlen)
    goto fail;

  FAILZ(EC_POINT_get_affine_coordinates_GF2m(ca, r, &x, &y, kp->params->ctx));
  if (bn2bin_padhi(&x, secret + mlen, mlen) != mlen)
    goto fail;

  rv = 0;
 done:
  if (unpadded) {
    memset(unpadded, 0, mlen + 1);
    free(unpadded);
  }
  if (q) EC_POINT_clear_free(q);
  if (r) EC_POINT_clear_free(r);
  BN_clear(&x);
  BN_clear(&y);
  return rv;

 fail:
  rv = -1;
  memset(secret, 0, mlen * 2);
  goto done;
}
Exemplo n.º 3
0
void
MKEM_teardown(MKEM *kp)
{
  /* s0 and s1 are secret. p0 and p1 are not secret, but clear them
     anyway. */
  if (kp->s0) BN_clear_free((BIGNUM *)kp->s0);
  if (kp->s1) BN_clear_free((BIGNUM *)kp->s1);

  if (kp->p0) EC_POINT_clear_free((EC_POINT *)kp->p0);
  if (kp->p1) EC_POINT_clear_free((EC_POINT *)kp->p1);

  memset(kp, 0, sizeof(MKEM));
}
Exemplo n.º 4
0
static int _free_pwd_session (pwd_session_t *session)
{
	BN_clear_free(session->private_value);
	BN_clear_free(session->peer_scalar);
	BN_clear_free(session->my_scalar);
	BN_clear_free(session->k);
	EC_POINT_clear_free(session->my_element);
	EC_POINT_clear_free(session->peer_element);
	EC_GROUP_free(session->group);
	EC_POINT_clear_free(session->pwe);
	BN_clear_free(session->order);
	BN_clear_free(session->prime);

	return 0;
}
Exemplo n.º 5
0
static void ec_pre_comp_clear_free(void *pre_)
{
    int i;
    EC_PRE_COMP *pre = pre_;

    if (!pre)
        return;

    CRYPTO_atomic_add(&pre->references, -1, &i, pre->lock);
    if (i > 0)
        return;

    CRYPTO_thread_cleanup(pre->lock);
    if (pre->points) {
        EC_POINT **p;

        for (p = pre->points; *p != NULL; p++) {
            EC_POINT_clear_free(*p);
            vigortls_zeroize(p, sizeof *p);
        }
        free(pre->points);
    }
    vigortls_zeroize(pre, sizeof *pre);
    free(pre);
}
Exemplo n.º 6
0
void EC_GROUP_clear_free(EC_GROUP *group)
	{
	if (!group) return;

	if (group->meth->group_clear_finish != 0)
		group->meth->group_clear_finish(group);
	else if (group->meth->group_finish != 0)
		group->meth->group_finish(group);

	EC_EX_DATA_clear_free_all_data(&group->extra_data);

	if (group->generator != NULL)
		EC_POINT_clear_free(group->generator);
	BN_clear_free(&group->order);
	BN_clear_free(&group->cofactor);

	if (group->seed)
		{
		OPENSSL_cleanse(group->seed, group->seed_len);
		OPENSSL_free(group->seed);
		}

	OPENSSL_cleanse(group, sizeof *group);
	OPENSSL_free(group);
	}
Exemplo n.º 7
0
/***************************************************************************//**
 * Delete all Mikey Sakke parameter set data.
 ******************************************************************************/
void ms_deleteParameterSets() {

    int c = 0;
    for (c = 0; c <  MAX_ES_PARAMETER_SETS; c++) {
        if (NULL != ms_parameter_sets[c].p) {
            BN_clear_free(ms_parameter_sets[c].p);
        }
        if (NULL != ms_parameter_sets[c].q) {
            BN_clear_free(ms_parameter_sets[c].q);
        }
        if (NULL != ms_parameter_sets[c].Px) {
            BN_clear_free(ms_parameter_sets[c].Px);
        }
        if (NULL != ms_parameter_sets[c].Py) {
            BN_clear_free(ms_parameter_sets[c].Py);
        }
        if (NULL != ms_parameter_sets[c].g) {
            BN_clear_free(ms_parameter_sets[c].g);
        }
        if (NULL != ms_parameter_sets[c].E) {
            EC_GROUP_clear_free(ms_parameter_sets[c].E);
        }
        if (NULL != ms_parameter_sets[c].P) {
            EC_POINT_clear_free(ms_parameter_sets[c].P);
        }
        memset(&ms_parameter_sets[c], 0, sizeof(struct msParameterSet_t));
    }
    ms_parameter_sets_initialised = ES_FALSE;

} /* ms_deleteParameterSets */
Exemplo n.º 8
0
EC_POINT *
EC_POINT_bn2point(const EC_GROUP * group,
    const BIGNUM * bn, EC_POINT * point, BN_CTX * ctx)
{
	size_t buf_len = 0;
	unsigned char *buf;
	EC_POINT *ret;

	if ((buf_len = BN_num_bytes(bn)) == 0)
		return NULL;
	buf = malloc(buf_len);
	if (buf == NULL)
		return NULL;

	if (!BN_bn2bin(bn, buf)) {
		free(buf);
		return NULL;
	}
	if (point == NULL) {
		if ((ret = EC_POINT_new(group)) == NULL) {
			free(buf);
			return NULL;
		}
	} else
		ret = point;

	if (!EC_POINT_oct2point(group, ret, buf, buf_len, ctx)) {
		if (point == NULL)
			EC_POINT_clear_free(ret);
		free(buf);
		return NULL;
	}
	free(buf);
	return ret;
}
Exemplo n.º 9
0
static void ec_pre_comp_clear_free(void *pre_)
	{
	int i;
	EC_PRE_COMP *pre = pre_;

	if (!pre)
		return;

	i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
	if (i > 0)
		return;

	if (pre->points)
		{
		EC_POINT **p;

		for (p = pre->points; *p != NULL; p++)
			{
			EC_POINT_clear_free(*p);
			OPENSSL_cleanse(p, sizeof *p);
			}
		OPENSSL_free(pre->points);
		}
	OPENSSL_cleanse(pre, sizeof *pre);
	OPENSSL_free(pre);
	}
Exemplo n.º 10
0
int
MKEM_init_pk_vec(MKEM *kp,
                 const MKEMParams *params,
                 const uint8_t *p0, size_t p0l,
                 const uint8_t *p1, size_t p1l)
{
  EC_POINT *pp0 = EC_POINT_new(params->c0);
  EC_POINT *pp1 = EC_POINT_new(params->c1);

  FAILZ(pp0); FAILZ(pp1);
  FAILZ(EC_POINT_oct2point(params->c0, pp0, p0, p0l, params->ctx));
  FAILZ(EC_POINT_oct2point(params->c1, pp1, p1, p1l, params->ctx));

  return MKEM_init_pk_point(kp, params, pp0, pp1);

 fail:
  if (pp0) EC_POINT_clear_free(pp0);
  if (pp1) EC_POINT_clear_free(pp1);
  return -1;
}
Exemplo n.º 11
0
void EC_GROUP_clear_free(EC_GROUP *group)
{
    if (!group)
        return;

    if (group->meth->group_clear_finish != 0)
        group->meth->group_clear_finish(group);
    else if (group->meth->group_finish != 0)
        group->meth->group_finish(group);

    EC_pre_comp_free(group);
    BN_MONT_CTX_free(group->mont_data);
    EC_POINT_clear_free(group->generator);
    BN_clear_free(group->order);
    BN_clear_free(group->cofactor);
    OPENSSL_clear_free(group->seed, group->seed_len);
    OPENSSL_clear_free(group, sizeof(*group));
}
Exemplo n.º 12
0
int ec_group_copy(EC_GROUP *dest, const EC_GROUP *src) {
  if (dest->meth->group_copy == 0) {
    OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
    return 0;
  }
  if (dest->meth != src->meth) {
    OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
    return 0;
  }
  if (dest == src) {
    return 1;
  }

  ec_pre_comp_free(dest->pre_comp);
  dest->pre_comp = ec_pre_comp_dup(src->pre_comp);

  if (src->generator != NULL) {
    if (dest->generator == NULL) {
      dest->generator = EC_POINT_new(dest);
      if (dest->generator == NULL) {
        return 0;
      }
    }
    if (!EC_POINT_copy(dest->generator, src->generator)) {
      return 0;
    }
  } else {
    /* src->generator == NULL */
    if (dest->generator != NULL) {
      EC_POINT_clear_free(dest->generator);
      dest->generator = NULL;
    }
  }

  if (!BN_copy(&dest->order, &src->order) ||
      !BN_copy(&dest->cofactor, &src->cofactor)) {
    return 0;
  }

  dest->curve_name = src->curve_name;

  return dest->meth->group_copy(dest, src);
}
Exemplo n.º 13
0
void 
EC_GROUP_clear_free(EC_GROUP * group)
{
	if (!group)
		return;

	if (group->meth->group_clear_finish != 0)
		group->meth->group_clear_finish(group);
	else if (group->meth->group_finish != 0)
		group->meth->group_finish(group);

	EC_EX_DATA_clear_free_all_data(&group->extra_data);

	EC_POINT_clear_free(group->generator);
	BN_clear_free(&group->order);
	BN_clear_free(&group->cofactor);

	if (group->seed) {
		explicit_bzero(group->seed, group->seed_len);
		free(group->seed);
	}
	explicit_bzero(group, sizeof *group);
	free(group);
}
Exemplo n.º 14
0
int
EVP_PKEY_set_keys(EVP_PKEY *evp_pkey,
        const unsigned char *privkey, size_t privkey_len,
           const unsigned char *pubkey, size_t pubkey_len,
           BN_CTX *bn_ctx)
{
    EC_KEY *ec_key = NULL;
    DH *dh = NULL;
    EC_POINT *ec_point = NULL;
    BIGNUM *bn = NULL, *dh_pub_key, *dh_priv_key;
    int ok = 0;
    const EC_GROUP *group;

    check(evp_pkey, "Invalid arguments");

    switch (EVP_PKEY_base_id(evp_pkey)) {
        case EVP_PKEY_EC:
            ec_key = EVP_PKEY_get1_EC_KEY(evp_pkey);
            if (!ec_key)
                goto err;
            group = EC_KEY_get0_group(ec_key);

            if (pubkey) {
                ec_point = EC_POINT_new(group);
                if (!ec_point
                        || !EC_POINT_oct2point(group, ec_point, pubkey,
                            pubkey_len, bn_ctx)
                        || !EC_KEY_set_public_key(ec_key, ec_point))
                    goto err;
            }
            if (privkey) {
                bn = BN_bin2bn(privkey, privkey_len, bn);
                if (!bn || !EC_KEY_set_private_key(ec_key, bn))
                    goto err;
            }

            if (!EVP_PKEY_set1_EC_KEY(evp_pkey, ec_key))
                goto err;
            break;

        case EVP_PKEY_DH:
            dh = EVP_PKEY_get1_DH(evp_pkey);
            if (!dh)
                goto err;

            if (pubkey) {
                dh_pub_key = BN_bin2bn(pubkey, pubkey_len, NULL);
                if (!dh_pub_key || !DH_set0_key(dh, dh_pub_key, NULL))
                    goto err;
            }
            if (privkey) {
                dh_priv_key = BN_bin2bn(privkey, privkey_len, NULL);
                if (!dh_priv_key || !DH_set0_key(dh, NULL, dh_priv_key))
                    goto err;
            }

            if (!EVP_PKEY_set1_DH(evp_pkey, dh))
                goto err;
            break;

        default:
            log_err("Unknown type of key");
            goto err;
            break;
    }

    ok = 1;

err:
    if (bn)
        BN_clear_free(bn);
    if (ec_key)
        EC_KEY_free(ec_key);
    if (dh)
        DH_free(dh);
    if (ec_point)
        EC_POINT_clear_free(ec_point);

    return ok;
}
Exemplo n.º 15
0
static int
input_kex_ecdh_reply(int type, u_int32_t seq, void *ctxt)
{
	struct ssh *ssh = ctxt;
	struct kex *kex = ssh->kex;
	const EC_GROUP *group;
	EC_POINT *server_public = NULL;
	EC_KEY *client_key;
	BIGNUM *shared_secret = NULL;
	struct sshkey *server_host_key = NULL;
	u_char *server_host_key_blob = NULL, *signature = NULL;
	u_char *kbuf = NULL;
	u_char hash[SSH_DIGEST_MAX_LENGTH];
	size_t slen, sbloblen;
	size_t klen = 0, hashlen;
	int r;

	if (kex->verify_host_key == NULL) {
		r = SSH_ERR_INVALID_ARGUMENT;
		goto out;
	}
	group = kex->ec_group;
	client_key = kex->ec_client_key;

	/* hostkey */
	if ((r = sshpkt_get_string(ssh, &server_host_key_blob,
	    &sbloblen)) != 0 ||
	    (r = sshkey_from_blob(server_host_key_blob, sbloblen,
	    &server_host_key)) != 0)
		goto out;
	if (server_host_key->type != kex->hostkey_type ||
	    (kex->hostkey_type == KEY_ECDSA &&
	    server_host_key->ecdsa_nid != kex->hostkey_nid)) {
		r = SSH_ERR_KEY_TYPE_MISMATCH;
		goto out;
	}
	if (kex->verify_host_key(server_host_key, ssh) == -1) {
		r = SSH_ERR_SIGNATURE_INVALID;
		goto out;
	}

	/* Q_S, server public key */
	/* signed H */
	if ((server_public = EC_POINT_new(group)) == NULL) {
		r = SSH_ERR_ALLOC_FAIL;
		goto out;
	}
	if ((r = sshpkt_get_ec(ssh, server_public, group)) != 0 ||
	    (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
	    (r = sshpkt_get_end(ssh)) != 0)
		goto out;

#ifdef DEBUG_KEXECDH
	fputs("server public key:\n", stderr);
	sshkey_dump_ec_point(group, server_public);
#endif
	if (sshkey_ec_validate_public(group, server_public) != 0) {
		sshpkt_disconnect(ssh, "invalid server public key");
		r = SSH_ERR_MESSAGE_INCOMPLETE;
		goto out;
	}

	klen = (EC_GROUP_get_degree(group) + 7) / 8;
	if ((kbuf = malloc(klen)) == NULL ||
	    (shared_secret = BN_new()) == NULL) {
		r = SSH_ERR_ALLOC_FAIL;
		goto out;
	}
	if (ECDH_compute_key(kbuf, klen, server_public,
	    client_key, NULL) != (int)klen ||
	    BN_bin2bn(kbuf, klen, shared_secret) == NULL) {
		r = SSH_ERR_LIBCRYPTO_ERROR;
		goto out;
	}

#ifdef DEBUG_KEXECDH
	dump_digest("shared secret", kbuf, klen);
#endif
	/* calc and verify H */
	hashlen = sizeof(hash);
	if ((r = kex_ecdh_hash(
	    kex->hash_alg,
	    group,
	    kex->client_version_string,
	    kex->server_version_string,
	    sshbuf_ptr(kex->my), sshbuf_len(kex->my),
	    sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
	    server_host_key_blob, sbloblen,
	    EC_KEY_get0_public_key(client_key),
	    server_public,
	    shared_secret,
	    hash, &hashlen)) != 0)
		goto out;

	if ((r = sshkey_verify(server_host_key, signature, slen, hash,
	    hashlen, ssh->compat)) != 0)
		goto out;

	/* save session id */
	if (kex->session_id == NULL) {
		kex->session_id_len = hashlen;
		kex->session_id = malloc(kex->session_id_len);
		if (kex->session_id == NULL) {
			r = SSH_ERR_ALLOC_FAIL;
			goto out;
		}
		memcpy(kex->session_id, hash, kex->session_id_len);
	}

	if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
		r = kex_send_newkeys(ssh);
 out:
	explicit_bzero(hash, sizeof(hash));
	if (kex->ec_client_key) {
		EC_KEY_free(kex->ec_client_key);
		kex->ec_client_key = NULL;
	}
	if (server_public)
		EC_POINT_clear_free(server_public);
	if (kbuf) {
		explicit_bzero(kbuf, klen);
		free(kbuf);
	}
	if (shared_secret)
		BN_clear_free(shared_secret);
	sshkey_free(server_host_key);
	free(server_host_key_blob);
	free(signature);
	return r;
}
Exemplo n.º 16
0
void
kexecdh_client(Kex *kex)
{
	EC_KEY *client_key;
	EC_POINT *server_public;
	const EC_GROUP *group;
	BIGNUM *shared_secret;
	Key *server_host_key;
	u_char *server_host_key_blob = NULL, *signature = NULL;
	u_char *kbuf, *hash;
	u_int klen, slen, sbloblen, hashlen;

	if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL)
		fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
	if (EC_KEY_generate_key(client_key) != 1)
		fatal("%s: EC_KEY_generate_key failed", __func__);
	group = EC_KEY_get0_group(client_key);

	packet_start(SSH2_MSG_KEX_ECDH_INIT);
	packet_put_ecpoint(group, EC_KEY_get0_public_key(client_key));
	packet_send();
	debug("sending SSH2_MSG_KEX_ECDH_INIT");

#ifdef DEBUG_KEXECDH
	fputs("client private key:\n", stderr);
	key_dump_ec_key(client_key);
#endif

	debug("expecting SSH2_MSG_KEX_ECDH_REPLY");
	packet_read_expect(SSH2_MSG_KEX_ECDH_REPLY);

	/* hostkey */
	server_host_key_blob = packet_get_string(&sbloblen);
	server_host_key = key_from_blob(server_host_key_blob, sbloblen);
	if (server_host_key == NULL)
		fatal("cannot decode server_host_key_blob");
	if (server_host_key->type != kex->hostkey_type)
		fatal("type mismatch for decoded server_host_key_blob");
	if (kex->verify_host_key == NULL)
		fatal("cannot verify server_host_key");
	if (kex->verify_host_key(server_host_key) == -1)
		fatal("server_host_key verification failed");

	/* Q_S, server public key */
	if ((server_public = EC_POINT_new(group)) == NULL)
		fatal("%s: EC_POINT_new failed", __func__);
	packet_get_ecpoint(group, server_public);

	if (key_ec_validate_public(group, server_public) != 0)
		fatal("%s: invalid server public key", __func__);

#ifdef DEBUG_KEXECDH
	fputs("server public key:\n", stderr);
	key_dump_ec_point(group, server_public);
#endif

	/* signed H */
	signature = packet_get_string(&slen);
	packet_check_eom();

	klen = (EC_GROUP_get_degree(group) + 7) / 8;
	kbuf = xmalloc(klen);
	if (ECDH_compute_key(kbuf, klen, server_public,
	    client_key, NULL) != (int)klen)
		fatal("%s: ECDH_compute_key failed", __func__);

#ifdef DEBUG_KEXECDH
	dump_digest("shared secret", kbuf, klen);
#endif
	if ((shared_secret = BN_new()) == NULL)
		fatal("%s: BN_new failed", __func__);
	if (BN_bin2bn(kbuf, klen, shared_secret) == NULL)
		fatal("%s: BN_bin2bn failed", __func__);
	memset(kbuf, 0, klen);
	free(kbuf);

	/* calc and verify H */
	kex_ecdh_hash(
	    kex->evp_md,
	    group,
	    kex->client_version_string,
	    kex->server_version_string,
	    buffer_ptr(&kex->my), buffer_len(&kex->my),
	    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
	    server_host_key_blob, sbloblen,
	    EC_KEY_get0_public_key(client_key),
	    server_public,
	    shared_secret,
	    &hash, &hashlen
	);
	free(server_host_key_blob);
	EC_POINT_clear_free(server_public);
	EC_KEY_free(client_key);

	if (key_verify(server_host_key, signature, slen, hash, hashlen) != 1)
		fatal("key_verify failed for server_host_key");
	key_free(server_host_key);
	free(signature);

	/* save session id */
	if (kex->session_id == NULL) {
		kex->session_id_len = hashlen;
		kex->session_id = xmalloc(kex->session_id_len);
		memcpy(kex->session_id, hash, kex->session_id_len);
	}

	kex_derive_keys(kex, hash, hashlen, shared_secret);
	BN_clear_free(shared_secret);
	kex_finish(kex);
}
Exemplo n.º 17
0
int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
{
    if (dest->meth->group_copy == 0) {
        ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
        return 0;
    }
    if (dest->meth != src->meth) {
        ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
        return 0;
    }
    if (dest == src)
        return 1;

    /* Copy precomputed */
    dest->pre_comp_type = src->pre_comp_type;
    switch (src->pre_comp_type) {
    case PCT_none:
        dest->pre_comp.ec = NULL;
        break;
    case PCT_nistz256:
#ifdef ECP_NISTZ256_ASM
        dest->pre_comp.nistz256 = EC_nistz256_pre_comp_dup(src->pre_comp.nistz256);
#endif
        break;
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
    case PCT_nistp224:
        dest->pre_comp.nistp224 = EC_nistp224_pre_comp_dup(src->pre_comp.nistp224);
        break;
    case PCT_nistp256:
        dest->pre_comp.nistp256 = EC_nistp256_pre_comp_dup(src->pre_comp.nistp256);
        break;
    case PCT_nistp521:
        dest->pre_comp.nistp521 = EC_nistp521_pre_comp_dup(src->pre_comp.nistp521);
        break;
#else
    case PCT_nistp224:
    case PCT_nistp256:
    case PCT_nistp521:
        break;
#endif
    case PCT_ec:
        dest->pre_comp.ec = EC_ec_pre_comp_dup(src->pre_comp.ec);
        break;
    }

    if (src->mont_data != NULL) {
        if (dest->mont_data == NULL) {
            dest->mont_data = BN_MONT_CTX_new();
            if (dest->mont_data == NULL)
                return 0;
        }
        if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data))
            return 0;
    } else {
        /* src->generator == NULL */
        BN_MONT_CTX_free(dest->mont_data);
        dest->mont_data = NULL;
    }

    if (src->generator != NULL) {
        if (dest->generator == NULL) {
            dest->generator = EC_POINT_new(dest);
            if (dest->generator == NULL)
                return 0;
        }
        if (!EC_POINT_copy(dest->generator, src->generator))
            return 0;
    } else {
        /* src->generator == NULL */
        EC_POINT_clear_free(dest->generator);
        dest->generator = NULL;
    }

    if ((src->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) {
        if (!BN_copy(dest->order, src->order))
            return 0;
        if (!BN_copy(dest->cofactor, src->cofactor))
            return 0;
    }

    dest->curve_name = src->curve_name;
    dest->asn1_flag = src->asn1_flag;
    dest->asn1_form = src->asn1_form;

    if (src->seed) {
        OPENSSL_free(dest->seed);
        dest->seed = OPENSSL_malloc(src->seed_len);
        if (dest->seed == NULL)
            return 0;
        if (!memcpy(dest->seed, src->seed, src->seed_len))
            return 0;
        dest->seed_len = src->seed_len;
    } else {
        OPENSSL_free(dest->seed);
        dest->seed = NULL;
        dest->seed_len = 0;
    }

    return dest->meth->group_copy(dest, src);
}
Exemplo n.º 18
0
/*
 * compute a "random" secret point on an elliptic curve based
 * on the password and identities.
 */
int compute_password_element(EAP_PWD_group *grp, u16 num,
                             const u8 *password, size_t password_len,
                             const u8 *id_server, size_t id_server_len,
                             const u8 *id_peer, size_t id_peer_len,
                             const u8 *token)
{
    BIGNUM *x_candidate = NULL, *rnd = NULL, *cofactor = NULL;
    struct crypto_hash *hash;
    unsigned char pwe_digest[SHA256_MAC_LEN], *prfbuf = NULL, ctr;
    int nid, is_odd, ret = 0;
    size_t primebytelen, primebitlen;

    switch (num) { /* from IANA registry for IKE D-H groups */
    case 19:
        nid = NID_X9_62_prime256v1;
        break;
    case 20:
        nid = NID_secp384r1;
        break;
    case 21:
        nid = NID_secp521r1;
        break;
#ifndef OPENSSL_IS_BORINGSSL
    case 25:
        nid = NID_X9_62_prime192v1;
        break;
#endif /* OPENSSL_IS_BORINGSSL */
    case 26:
        nid = NID_secp224r1;
        break;
    default:
        wpa_printf(MSG_INFO, "EAP-pwd: unsupported group %d", num);
        return -1;
    }

    grp->pwe = NULL;
    grp->order = NULL;
    grp->prime = NULL;

    if ((grp->group = EC_GROUP_new_by_curve_name(nid)) == NULL) {
        wpa_printf(MSG_INFO, "EAP-pwd: unable to create EC_GROUP");
        goto fail;
    }

    if (((rnd = BN_new()) == NULL) ||
            ((cofactor = BN_new()) == NULL) ||
            ((grp->pwe = EC_POINT_new(grp->group)) == NULL) ||
            ((grp->order = BN_new()) == NULL) ||
            ((grp->prime = BN_new()) == NULL) ||
            ((x_candidate = BN_new()) == NULL)) {
        wpa_printf(MSG_INFO, "EAP-pwd: unable to create bignums");
        goto fail;
    }

    if (!EC_GROUP_get_curve_GFp(grp->group, grp->prime, NULL, NULL, NULL))
    {
        wpa_printf(MSG_INFO, "EAP-pwd: unable to get prime for GFp "
                   "curve");
        goto fail;
    }
    if (!EC_GROUP_get_order(grp->group, grp->order, NULL)) {
        wpa_printf(MSG_INFO, "EAP-pwd: unable to get order for curve");
        goto fail;
    }
    if (!EC_GROUP_get_cofactor(grp->group, cofactor, NULL)) {
        wpa_printf(MSG_INFO, "EAP-pwd: unable to get cofactor for "
                   "curve");
        goto fail;
    }
    primebitlen = BN_num_bits(grp->prime);
    primebytelen = BN_num_bytes(grp->prime);
    if ((prfbuf = os_malloc(primebytelen)) == NULL) {
        wpa_printf(MSG_INFO, "EAP-pwd: unable to malloc space for prf "
                   "buffer");
        goto fail;
    }
    os_memset(prfbuf, 0, primebytelen);
    ctr = 0;
    while (1) {
        if (ctr > 30) {
            wpa_printf(MSG_INFO, "EAP-pwd: unable to find random "
                       "point on curve for group %d, something's "
                       "fishy", num);
            goto fail;
        }
        ctr++;

        /*
         * compute counter-mode password value and stretch to prime
         *    pwd-seed = H(token | peer-id | server-id | password |
         *		   counter)
         */
        hash = eap_pwd_h_init();
        if (hash == NULL)
            goto fail;
        eap_pwd_h_update(hash, token, sizeof(u32));
        eap_pwd_h_update(hash, id_peer, id_peer_len);
        eap_pwd_h_update(hash, id_server, id_server_len);
        eap_pwd_h_update(hash, password, password_len);
        eap_pwd_h_update(hash, &ctr, sizeof(ctr));
        eap_pwd_h_final(hash, pwe_digest);

        BN_bin2bn(pwe_digest, SHA256_MAC_LEN, rnd);

        if (eap_pwd_kdf(pwe_digest, SHA256_MAC_LEN,
                        (u8 *) "EAP-pwd Hunting And Pecking",
                        os_strlen("EAP-pwd Hunting And Pecking"),
                        prfbuf, primebitlen) < 0)
            goto fail;

        BN_bin2bn(prfbuf, primebytelen, x_candidate);

        /*
         * eap_pwd_kdf() returns a string of bits 0..primebitlen but
         * BN_bin2bn will treat that string of bits as a big endian
         * number. If the primebitlen is not an even multiple of 8
         * then excessive bits-- those _after_ primebitlen-- so now
         * we have to shift right the amount we masked off.
         */
        if (primebitlen % 8)
            BN_rshift(x_candidate, x_candidate,
                      (8 - (primebitlen % 8)));

        if (BN_ucmp(x_candidate, grp->prime) >= 0)
            continue;

        wpa_hexdump(MSG_DEBUG, "EAP-pwd: x_candidate",
                    prfbuf, primebytelen);

        /*
         * need to unambiguously identify the solution, if there is
         * one...
         */
        if (BN_is_odd(rnd))
            is_odd = 1;
        else
            is_odd = 0;

        /*
         * solve the quadratic equation, if it's not solvable then we
         * don't have a point
         */
        if (!EC_POINT_set_compressed_coordinates_GFp(grp->group,
                grp->pwe,
                x_candidate,
                is_odd, NULL))
            continue;
        /*
         * If there's a solution to the equation then the point must be
         * on the curve so why check again explicitly? OpenSSL code
         * says this is required by X9.62. We're not X9.62 but it can't
         * hurt just to be sure.
         */
        if (!EC_POINT_is_on_curve(grp->group, grp->pwe, NULL)) {
            wpa_printf(MSG_INFO, "EAP-pwd: point is not on curve");
            continue;
        }

        if (BN_cmp(cofactor, BN_value_one())) {
            /* make sure the point is not in a small sub-group */
            if (!EC_POINT_mul(grp->group, grp->pwe, NULL, grp->pwe,
                              cofactor, NULL)) {
                wpa_printf(MSG_INFO, "EAP-pwd: cannot "
                           "multiply generator by order");
                continue;
            }
            if (EC_POINT_is_at_infinity(grp->group, grp->pwe)) {
                wpa_printf(MSG_INFO, "EAP-pwd: point is at "
                           "infinity");
                continue;
            }
        }
        /* if we got here then we have a new generator. */
        break;
    }
    wpa_printf(MSG_DEBUG, "EAP-pwd: found a PWE in %d tries", ctr);
    grp->group_num = num;
    if (0) {
fail:
        EC_GROUP_free(grp->group);
        grp->group = NULL;
        EC_POINT_clear_free(grp->pwe);
        grp->pwe = NULL;
        BN_clear_free(grp->order);
        grp->order = NULL;
        BN_clear_free(grp->prime);
        grp->prime = NULL;
        ret = 1;
    }
    /* cleanliness and order.... */
    BN_clear_free(cofactor);
    BN_clear_free(x_candidate);
    BN_clear_free(rnd);
    os_free(prfbuf);

    return ret;
}
Exemplo n.º 19
0
int process_peer_commit(REQUEST *request, pwd_session_t *session, uint8_t *in, size_t in_len, BN_CTX *bn_ctx)
{
	uint8_t		*ptr;
	size_t		data_len;
	BIGNUM		*x = NULL, *y = NULL, *cofactor = NULL;
	EC_POINT	*K = NULL, *point = NULL;
	int		ret = 1;

	MEM(session->peer_scalar = BN_new());
	MEM(session->k = BN_new());
	MEM(session->peer_element = EC_POINT_new(session->group));
	MEM(point = EC_POINT_new(session->group));
	MEM(K = EC_POINT_new(session->group));

	MEM(cofactor = BN_new());
	MEM(x = BN_new());
	MEM(y = BN_new());

	if (!EC_GROUP_get_cofactor(session->group, cofactor, NULL)) {
		REDEBUG("Unable to get group co-factor");
		goto finish;
	}

	/* element, x then y, followed by scalar */
	ptr = (uint8_t *)in;
	data_len = BN_num_bytes(session->prime);

	/*
	 *	Did the peer send enough data?
	 */
	if (in_len < (2 * data_len + BN_num_bytes(session->order))) {
		REDEBUG("Invalid commit packet");
		goto finish;
	}

	BN_bin2bn(ptr, data_len, x);
	ptr += data_len;
	BN_bin2bn(ptr, data_len, y);
	ptr += data_len;

	data_len = BN_num_bytes(session->order);
	BN_bin2bn(ptr, data_len, session->peer_scalar);

	/* validate received scalar */
	if (BN_is_zero(session->peer_scalar) ||
	    BN_is_one(session->peer_scalar) ||
	    BN_cmp(session->peer_scalar, session->order) >= 0) {
		REDEBUG("Peer's scalar is not within the allowed range");
		goto finish;
	}

	if (!EC_POINT_set_affine_coordinates_GFp(session->group, session->peer_element, x, y, bn_ctx)) {
		REDEBUG("Unable to get coordinates of peer's element");
		goto finish;
	}

	/* validate received element */
	if (!EC_POINT_is_on_curve(session->group, session->peer_element, bn_ctx) ||
	    EC_POINT_is_at_infinity(session->group, session->peer_element)) {
		REDEBUG("Peer's element is not a point on the elliptic curve");
		goto finish;
	}

	/* check to ensure peer's element is not in a small sub-group */
	if (BN_cmp(cofactor, BN_value_one())) {
		if (!EC_POINT_mul(session->group, point, NULL, session->peer_element, cofactor, NULL)) {
			REDEBUG("Unable to multiply element by co-factor");
			goto finish;
		}

		if (EC_POINT_is_at_infinity(session->group, point)) {
			REDEBUG("Peer's element is in small sub-group");
			goto finish;
		}
	}

	/* detect reflection attacks */
	if (BN_cmp(session->peer_scalar, session->my_scalar) == 0 ||
	    EC_POINT_cmp(session->group, session->peer_element, session->my_element, bn_ctx) == 0) {
		REDEBUG("Reflection attack detected");
		goto finish;
	}

	/* compute the shared key, k */
	if ((!EC_POINT_mul(session->group, K, NULL, session->pwe, session->peer_scalar, bn_ctx)) ||
	    (!EC_POINT_add(session->group, K, K, session->peer_element, bn_ctx)) ||
	    (!EC_POINT_mul(session->group, K, NULL, K, session->private_value, bn_ctx))) {
		REDEBUG("Unable to compute shared key, k");
		goto finish;
	}

	/* ensure that the shared key isn't in a small sub-group */
	if (BN_cmp(cofactor, BN_value_one())) {
		if (!EC_POINT_mul(session->group, K, NULL, K, cofactor, NULL)) {
			REDEBUG("Unable to multiply k by co-factor");
			goto finish;
		}
	}

	/*
	 * This check is strictly speaking just for the case above where
	 * co-factor > 1 but it was suggested that even though this is probably
	 * never going to happen it is a simple and safe check "just to be
	 * sure" so let's be safe.
	 */
	if (EC_POINT_is_at_infinity(session->group, K)) {
		REDEBUG("K is point-at-infinity");
		goto finish;
	}

	if (!EC_POINT_get_affine_coordinates_GFp(session->group, K, session->k, NULL, bn_ctx)) {
		REDEBUG("Unable to get shared secret from K");
		goto finish;
	}
	ret = 0;

finish:
	EC_POINT_clear_free(K);
	EC_POINT_clear_free(point);
	BN_clear_free(cofactor);
	BN_clear_free(x);
	BN_clear_free(y);

	return ret;
}
Exemplo n.º 20
0
int
MKEM_generate_message_u(const MKEM *kp, const BIGNUM *uraw, uint8_t pad,
                        uint8_t *secret, uint8_t *message)
{
  BIGNUM u, x, y;
  int use_curve0 = (BN_cmp(uraw, kp->params->n0) < 0);
  const EC_GROUP *ca;
  const EC_POINT *ga;
  const EC_POINT *pa;
  EC_POINT *q = 0, *r = 0;
  size_t mlen = kp->params->msgsize;
  int rv;

  BN_init(&u);
  BN_init(&x);
  BN_init(&y);

  if (use_curve0) {
    ca = kp->params->c0;
    ga = kp->params->g0;
    pa = kp->p0;
    FAILZ(BN_copy(&u, uraw));
  } else {
    ca = kp->params->c1;
    ga = kp->params->g1;
    pa = kp->p1;
    FAILZ(BN_sub(&u, uraw, kp->params->n0));
    FAILZ(BN_add(&u, &u, BN_value_one()));
  }

  FAILZ(q = EC_POINT_new(ca));
  FAILZ(r = EC_POINT_new(ca));
  FAILZ(EC_POINT_mul(ca, q, 0, ga, &u, kp->params->ctx));
  FAILZ(EC_POINT_mul(ca, r, 0, pa, &u, kp->params->ctx));

  FAILZ(EC_POINT_get_affine_coordinates_GF2m(ca, q, &x, &y, kp->params->ctx));
  if (bn2bin_padhi(&x, message, mlen) != mlen)
    goto fail;
  if (message[0] & (kp->params->pad_mask|kp->params->curve_bit)) /* see below */
    goto fail;
  memcpy(secret, message, mlen);

  FAILZ(EC_POINT_get_affine_coordinates_GF2m(ca, r, &x, &y, kp->params->ctx));
  if (bn2bin_padhi(&x, secret + mlen, mlen) != mlen)
    goto fail;

  /* K high bits of the message will be zero.  Fill in the high K-1
     of them with random bits from the pad, and use the lowest bit
     to identify the curve in use.  That bit will have a bias on the
     order of 2^{-d/2} where d is the bit-degree of the curve; 2^{-81}
     for the only curve presently implemented.  This is acceptably
     small since an elliptic curve of d bits gives only about d/2 bits
     of security anyway, and is much better than allowing a timing
     attack via the recipient having to attempt point decompression
     twice for curve 1 but only once for curve 0 (or, alternatively,
     doubling the time required for all decryptions).  */

  pad &= kp->params->pad_mask;
  pad |= (use_curve0 ? 0 : kp->params->curve_bit);
  message[0] |= pad;

  rv = 0;
 done:
  BN_clear(&u);
  BN_clear(&x);
  BN_clear(&y);
  if (q) EC_POINT_clear_free(q);
  if (r) EC_POINT_clear_free(r);
  return rv;

 fail:
  memset(message, 0, mlen);
  memset(secret, 0, mlen * 2);
  rv = -1;
  goto done;
}
Exemplo n.º 21
0
static void
eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
				struct eap_method_ret *ret,
				const struct wpabuf *reqData,
				const u8 *payload, size_t payload_len)
{
	EC_POINT *K = NULL, *point = NULL;
	BIGNUM *mask = NULL, *x = NULL, *y = NULL, *cofactor = NULL;
	u16 offset;
	u8 *ptr, *scalar = NULL, *element = NULL;
	size_t prime_len, order_len;

	if (data->state != PWD_Commit_Req) {
		ret->ignore = TRUE;
		goto fin;
	}

	prime_len = BN_num_bytes(data->grp->prime);
	order_len = BN_num_bytes(data->grp->order);

	if (payload_len != 2 * prime_len + order_len) {
		wpa_printf(MSG_INFO,
			   "EAP-pwd: Unexpected Commit payload length %u (expected %u)",
			   (unsigned int) payload_len,
			   (unsigned int) (2 * prime_len + order_len));
		goto fin;
	}

	if (((data->private_value = BN_new()) == NULL) ||
	    ((data->my_element = EC_POINT_new(data->grp->group)) == NULL) ||
	    ((cofactor = BN_new()) == NULL) ||
	    ((data->my_scalar = BN_new()) == NULL) ||
	    ((mask = BN_new()) == NULL)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): scalar allocation fail");
		goto fin;
	}

	if (!EC_GROUP_get_cofactor(data->grp->group, cofactor, NULL)) {
		wpa_printf(MSG_INFO, "EAP-pwd (peer): unable to get cofactor "
			   "for curve");
		goto fin;
	}

	if (BN_rand_range(data->private_value, data->grp->order) != 1 ||
	    BN_rand_range(mask, data->grp->order) != 1 ||
	    BN_add(data->my_scalar, data->private_value, mask) != 1 ||
	    BN_mod(data->my_scalar, data->my_scalar, data->grp->order,
		   data->bnctx) != 1) {
		wpa_printf(MSG_INFO,
			   "EAP-pwd (peer): unable to get randomness");
		goto fin;
	}

	if (!EC_POINT_mul(data->grp->group, data->my_element, NULL,
			  data->grp->pwe, mask, data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): element allocation "
			   "fail");
		eap_pwd_state(data, FAILURE);
		goto fin;
	}

	if (!EC_POINT_invert(data->grp->group, data->my_element, data->bnctx))
	{
		wpa_printf(MSG_INFO, "EAP-PWD (peer): element inversion fail");
		goto fin;
	}
	BN_clear_free(mask);

	if (((x = BN_new()) == NULL) ||
	    ((y = BN_new()) == NULL)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): point allocation fail");
		goto fin;
	}

	/* process the request */
	if (((data->server_scalar = BN_new()) == NULL) ||
	    ((data->k = BN_new()) == NULL) ||
	    ((K = EC_POINT_new(data->grp->group)) == NULL) ||
	    ((point = EC_POINT_new(data->grp->group)) == NULL) ||
	    ((data->server_element = EC_POINT_new(data->grp->group)) == NULL))
	{
		wpa_printf(MSG_INFO, "EAP-PWD (peer): peer data allocation "
			   "fail");
		goto fin;
	}

	/* element, x then y, followed by scalar */
	ptr = (u8 *) payload;
	BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), x);
	ptr += BN_num_bytes(data->grp->prime);
	BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), y);
	ptr += BN_num_bytes(data->grp->prime);
	BN_bin2bn(ptr, BN_num_bytes(data->grp->order), data->server_scalar);
	if (!EC_POINT_set_affine_coordinates_GFp(data->grp->group,
						 data->server_element, x, y,
						 data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): setting peer element "
			   "fail");
		goto fin;
	}

	/* check to ensure server's element is not in a small sub-group */
	if (BN_cmp(cofactor, BN_value_one())) {
		if (!EC_POINT_mul(data->grp->group, point, NULL,
				  data->server_element, cofactor, NULL)) {
			wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply "
				   "server element by order!\n");
			goto fin;
		}
		if (EC_POINT_is_at_infinity(data->grp->group, point)) {
			wpa_printf(MSG_INFO, "EAP-PWD (peer): server element "
				   "is at infinity!\n");
			goto fin;
		}
	}

	/* compute the shared key, k */
	if ((!EC_POINT_mul(data->grp->group, K, NULL, data->grp->pwe,
			   data->server_scalar, data->bnctx)) ||
	    (!EC_POINT_add(data->grp->group, K, K, data->server_element,
			   data->bnctx)) ||
	    (!EC_POINT_mul(data->grp->group, K, NULL, K, data->private_value,
			   data->bnctx))) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): computing shared key "
			   "fail");
		goto fin;
	}

	/* ensure that the shared key isn't in a small sub-group */
	if (BN_cmp(cofactor, BN_value_one())) {
		if (!EC_POINT_mul(data->grp->group, K, NULL, K, cofactor,
				  NULL)) {
			wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply "
				   "shared key point by order");
			goto fin;
		}
	}

	/*
	 * This check is strictly speaking just for the case above where
	 * co-factor > 1 but it was suggested that even though this is probably
	 * never going to happen it is a simple and safe check "just to be
	 * sure" so let's be safe.
	 */
	if (EC_POINT_is_at_infinity(data->grp->group, K)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): shared key point is at "
			   "infinity!\n");
		goto fin;
	}

	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, K, data->k,
						 NULL, data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to extract "
			   "shared secret from point");
		goto fin;
	}

	/* now do the response */
	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
						 data->my_element, x, y,
						 data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): point assignment fail");
		goto fin;
	}

	if (((scalar = os_malloc(BN_num_bytes(data->grp->order))) == NULL) ||
	    ((element = os_malloc(BN_num_bytes(data->grp->prime) * 2)) ==
	     NULL)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): data allocation fail");
		goto fin;
	}

	/*
	 * bignums occupy as little memory as possible so one that is
	 * sufficiently smaller than the prime or order might need pre-pending
	 * with zeros.
	 */
	os_memset(scalar, 0, BN_num_bytes(data->grp->order));
	os_memset(element, 0, BN_num_bytes(data->grp->prime) * 2);
	offset = BN_num_bytes(data->grp->order) -
		BN_num_bytes(data->my_scalar);
	BN_bn2bin(data->my_scalar, scalar + offset);

	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
	BN_bn2bin(x, element + offset);
	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
	BN_bn2bin(y, element + BN_num_bytes(data->grp->prime) + offset);

	data->outbuf = wpabuf_alloc(BN_num_bytes(data->grp->order) +
				    2 * BN_num_bytes(data->grp->prime));
	if (data->outbuf == NULL)
		goto fin;

	/* we send the element as (x,y) follwed by the scalar */
	wpabuf_put_data(data->outbuf, element,
			2 * BN_num_bytes(data->grp->prime));
	wpabuf_put_data(data->outbuf, scalar, BN_num_bytes(data->grp->order));

fin:
	os_free(scalar);
	os_free(element);
	BN_clear_free(x);
	BN_clear_free(y);
	BN_clear_free(cofactor);
	EC_POINT_clear_free(K);
	EC_POINT_clear_free(point);
	if (data->outbuf == NULL)
		eap_pwd_state(data, FAILURE);
	else
		eap_pwd_state(data, PWD_Confirm_Req);
}
Exemplo n.º 22
0
jbyteArray
Java_ru_ivanovpv_gorets_psm_nativelib_NativeLib_getECSharedKey( JNIEnv* env, jobject thiz,
                                                    jbyteArray privKey, jbyteArray pubKey, jint ecGroup)
{
    EC_GROUP * ec_group = NULL;
    EC_POINT * ec_pub = NULL;
    EC_POINT * ec_res = NULL;
    BN_CTX * bn_ctx = NULL;
    BIGNUM * bn_priv = NULL;
    jbyte * privKeyArr = NULL;
    jbyte * pubKeyArr = NULL;
    jbyteArray resKey = NULL;
    jbyte resKeyArr[MAX_EC_KEY_SIZE];
    jint privKeySize = 0;
    jint pubKeySize = 0;
    size_t resKeySize = 0;

    if (  ((ecGroup != 1) && (ecGroup != 2) && (ecGroup != 3)) || (privKey == NULL) || (pubKey == NULL) )
    {
        goto cleanup;
    }

    privKeySize = (*env)->GetArrayLength(env, privKey);
    pubKeySize = (*env)->GetArrayLength(env, pubKey);
    if ( (privKeySize <= 0) || (pubKeySize <= 0) )
    {
        goto cleanup;
    }

    switch(ecGroup)
    {
    case 1:
        if ( ( privKeySize < (112/8) ) || ( pubKeySize < (112/8+1) ) )
            goto cleanup;
        ec_group = EC_GROUP_new_by_curve_name(NID_secp112r1);
        break;
    case 2:
        if ( ( privKeySize < (256/8) ) || ( pubKeySize < (256/8+1) ) )
            goto cleanup;
        ec_group = EC_GROUP_new_by_curve_name(NID_secp256k1);
        break;
    case 3:
        if ( ( privKeySize < (384/8) ) || ( pubKeySize < (384/8+1) ) )
            goto cleanup;
        ec_group = EC_GROUP_new_by_curve_name(NID_secp384r1);
        break;
    default:
        goto cleanup;
    }

    if (!ec_group)
    {
        goto cleanup;
    }

    if( (bn_priv = BN_new()) == NULL)
    {
        goto cleanup;
    }

    if( (privKeyArr = (*env)->GetByteArrayElements(env, privKey, NULL)) == NULL )
    {
        goto cleanup;
    }

    if ( BN_bin2bn((const unsigned char *)privKeyArr, (int) privKeySize, bn_priv) == NULL )
    {
        goto cleanup;
    }

    if ( (bn_ctx = BN_CTX_new()) == NULL )
    {
        goto cleanup;
    }

    if ( (ec_pub = EC_POINT_new(ec_group)) == NULL)
    {
        goto cleanup;
    }

    if( (pubKeyArr = (*env)->GetByteArrayElements(env, pubKey, NULL)) == NULL )
    {
            goto cleanup;
    }

    if ( EC_POINT_oct2point((const EC_GROUP *) ec_group, (EC_POINT *) ec_pub,
        (unsigned char *) pubKeyArr, (size_t) pubKeySize, bn_ctx) == 0 )
    {
        goto cleanup;
    }

    if ( (ec_res = EC_POINT_new(ec_group)) == NULL)
    {
            goto cleanup;
    }


    if (!EC_POINT_mul((const EC_GROUP *) ec_group, ec_res, (const BIGNUM *)NULL, ec_pub, bn_priv, bn_ctx))
    {
        goto cleanup;
    }


    if ( (resKeySize = EC_POINT_point2oct((const EC_GROUP *) ec_group, (const EC_POINT *) ec_res,
        	POINT_CONVERSION_COMPRESSED, (unsigned char *) resKeyArr, (size_t) MAX_EC_KEY_SIZE, bn_ctx)) == 0 )
    {
        goto cleanup;
    }

    resKey  =  (*env)->NewByteArray(env, resKeySize);
    if (resKey == NULL)
    {
        goto cleanup;
    }

    (*env)->SetByteArrayRegion(env, resKey,
                0, resKeySize, (const jbyte*)resKeyArr);

    memset (resKeyArr, 0, resKeySize);


cleanup:

    if ( ec_group )
        EC_GROUP_clear_free( ec_group );

    if ( ec_pub )
        EC_POINT_clear_free( ec_pub );

    if ( ec_res )
        EC_POINT_clear_free( ec_res );

    if ( bn_priv )
        BN_clear_free( bn_priv );

    if ( privKeyArr )
        (*env)->ReleaseByteArrayElements(env, privKey, privKeyArr, JNI_ABORT);

    if ( pubKeyArr )
        (*env)->ReleaseByteArrayElements(env, pubKey, pubKeyArr, JNI_ABORT);

    return resKey;
}
Exemplo n.º 23
0
void
kexecdh_server(Kex *kex)
{
	EC_POINT *client_public;
	EC_KEY *server_key;
	const EC_GROUP *group;
	BIGNUM *shared_secret;
	Key *server_host_private, *server_host_public;
	u_char *server_host_key_blob = NULL, *signature = NULL;
	u_char *kbuf, *hash;
	u_int klen, slen, sbloblen, hashlen;
	int curve_nid;

	if ((curve_nid = kex_ecdh_name_to_nid(kex->name)) == -1)
		fatal("%s: unsupported ECDH curve \"%s\"", __func__, kex->name);
	if ((server_key = EC_KEY_new_by_curve_name(curve_nid)) == NULL)
		fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
	if (EC_KEY_generate_key(server_key) != 1)
		fatal("%s: EC_KEY_generate_key failed", __func__);
	group = EC_KEY_get0_group(server_key);

#ifdef DEBUG_KEXECDH
	fputs("server private key:\n", stderr);
	key_dump_ec_key(server_key);
#endif

	if (kex->load_host_public_key == NULL ||
	    kex->load_host_private_key == NULL)
		fatal("Cannot load hostkey");
	server_host_public = kex->load_host_public_key(kex->hostkey_type);
	if (server_host_public == NULL)
		fatal("Unsupported hostkey type %d", kex->hostkey_type);
	server_host_private = kex->load_host_private_key(kex->hostkey_type);
	if (server_host_private == NULL)
		fatal("Missing private key for hostkey type %d",
		    kex->hostkey_type);

	debug("expecting SSH2_MSG_KEX_ECDH_INIT");
	packet_read_expect(SSH2_MSG_KEX_ECDH_INIT);
	if ((client_public = EC_POINT_new(group)) == NULL)
		fatal("%s: EC_POINT_new failed", __func__);
	packet_get_ecpoint(group, client_public);
	packet_check_eom();

	if (key_ec_validate_public(group, client_public) != 0)
		fatal("%s: invalid client public key", __func__);

#ifdef DEBUG_KEXECDH
	fputs("client public key:\n", stderr);
	key_dump_ec_point(group, client_public);
#endif

	/* Calculate shared_secret */
	klen = (EC_GROUP_get_degree(group) + 7) / 8;
	kbuf = xmalloc(klen);
	if (ECDH_compute_key(kbuf, klen, client_public,
	    server_key, NULL) != (int)klen)
		fatal("%s: ECDH_compute_key failed", __func__);

#ifdef DEBUG_KEXDH
	dump_digest("shared secret", kbuf, klen);
#endif
	if ((shared_secret = BN_new()) == NULL)
		fatal("%s: BN_new failed", __func__);
	if (BN_bin2bn(kbuf, klen, shared_secret) == NULL)
		fatal("%s: BN_bin2bn failed", __func__);
	memset(kbuf, 0, klen);
	xfree(kbuf);

	/* calc H */
	key_to_blob(server_host_public, &server_host_key_blob, &sbloblen);
	kex_ecdh_hash(
	    kex->evp_md,
	    group,
	    kex->client_version_string,
	    kex->server_version_string,
	    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
	    buffer_ptr(&kex->my), buffer_len(&kex->my),
	    server_host_key_blob, sbloblen,
	    client_public,
	    EC_KEY_get0_public_key(server_key),
	    shared_secret,
	    &hash, &hashlen
	);
	EC_POINT_clear_free(client_public);

	/* save session id := H */
	if (kex->session_id == NULL) {
		kex->session_id_len = hashlen;
		kex->session_id = xmalloc(kex->session_id_len);
		memcpy(kex->session_id, hash, kex->session_id_len);
	}

	/* sign H */
	if (PRIVSEP(key_sign(server_host_private, &signature, &slen,
	    hash, hashlen)) < 0)
		fatal("kexdh_server: key_sign failed");

	/* destroy_sensitive_data(); */

	/* send server hostkey, ECDH pubkey 'Q_S' and signed H */
	packet_start(SSH2_MSG_KEX_ECDH_REPLY);
	packet_put_string(server_host_key_blob, sbloblen);
	packet_put_ecpoint(group, EC_KEY_get0_public_key(server_key));
	packet_put_string(signature, slen);
	packet_send();

	xfree(signature);
	xfree(server_host_key_blob);
	/* have keys, free server key */
	EC_KEY_free(server_key);

	kex_derive_keys(kex, hash, hashlen, shared_secret);
	BN_clear_free(shared_secret);
	kex_finish(kex);
}
Exemplo n.º 24
0
static void
eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
			    const u8 *payload, size_t payload_len)
{
	u8 *ptr;
	BIGNUM *x = NULL, *y = NULL, *cofactor = NULL;
	EC_POINT *K = NULL, *point = NULL;
	int res = 0;

	wpa_printf(MSG_DEBUG, "EAP-pwd: Received commit response");

	if (((data->peer_scalar = BN_new()) == NULL) ||
	    ((data->k = BN_new()) == NULL) ||
	    ((cofactor = BN_new()) == NULL) ||
	    ((x = BN_new()) == NULL) ||
	    ((y = BN_new()) == NULL) ||
	    ((point = EC_POINT_new(data->grp->group)) == NULL) ||
	    ((K = EC_POINT_new(data->grp->group)) == NULL) ||
	    ((data->peer_element = EC_POINT_new(data->grp->group)) == NULL)) {
		wpa_printf(MSG_INFO, "EAP-PWD (server): peer data allocation "
			   "fail");
		goto fin;
	}

	if (!EC_GROUP_get_cofactor(data->grp->group, cofactor, NULL)) {
		wpa_printf(MSG_INFO, "EAP-PWD (server): unable to get "
			   "cofactor for curve");
		goto fin;
	}

	/* element, x then y, followed by scalar */
	ptr = (u8 *) payload;
	BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), x);
	ptr += BN_num_bytes(data->grp->prime);
	BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), y);
	ptr += BN_num_bytes(data->grp->prime);
	BN_bin2bn(ptr, BN_num_bytes(data->grp->order), data->peer_scalar);
	if (!EC_POINT_set_affine_coordinates_GFp(data->grp->group,
						 data->peer_element, x, y,
						 data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (server): setting peer element "
			   "fail");
		goto fin;
	}

	/* check to ensure peer's element is not in a small sub-group */
	if (BN_cmp(cofactor, BN_value_one())) {
		if (!EC_POINT_mul(data->grp->group, point, NULL,
				  data->peer_element, cofactor, NULL)) {
			wpa_printf(MSG_INFO, "EAP-PWD (server): cannot "
				   "multiply peer element by order");
			goto fin;
		}
		if (EC_POINT_is_at_infinity(data->grp->group, point)) {
			wpa_printf(MSG_INFO, "EAP-PWD (server): peer element "
				   "is at infinity!\n");
			goto fin;
		}
	}

	/* compute the shared key, k */
	if ((!EC_POINT_mul(data->grp->group, K, NULL, data->grp->pwe,
			   data->peer_scalar, data->bnctx)) ||
	    (!EC_POINT_add(data->grp->group, K, K, data->peer_element,
			   data->bnctx)) ||
	    (!EC_POINT_mul(data->grp->group, K, NULL, K, data->private_value,
			   data->bnctx))) {
		wpa_printf(MSG_INFO, "EAP-PWD (server): computing shared key "
			   "fail");
		goto fin;
	}

	/* ensure that the shared key isn't in a small sub-group */
	if (BN_cmp(cofactor, BN_value_one())) {
		if (!EC_POINT_mul(data->grp->group, K, NULL, K, cofactor,
				  NULL)) {
			wpa_printf(MSG_INFO, "EAP-PWD (server): cannot "
				   "multiply shared key point by order!\n");
			goto fin;
		}
	}

	/*
	 * This check is strictly speaking just for the case above where
	 * co-factor > 1 but it was suggested that even though this is probably
	 * never going to happen it is a simple and safe check "just to be
	 * sure" so let's be safe.
	 */
	if (EC_POINT_is_at_infinity(data->grp->group, K)) {
		wpa_printf(MSG_INFO, "EAP-PWD (server): shared key point is "
			   "at infinity");
		goto fin;
	}
	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, K, data->k,
						 NULL, data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (server): unable to extract "
			   "shared secret from secret point");
		goto fin;
	}
	res = 1;

fin:
	EC_POINT_clear_free(K);
	EC_POINT_clear_free(point);
	BN_clear_free(cofactor);
	BN_clear_free(x);
	BN_clear_free(y);

	if (res)
		eap_pwd_state(data, PWD_Confirm_Req);
	else
		eap_pwd_state(data, FAILURE);
}
Exemplo n.º 25
0
int
ecdh_gm_compute_key(PACE_CTX * ctx, const BUF_MEM * s, const BUF_MEM * in,
        BN_CTX *bn_ctx)
{
    int ret = 0;
    BUF_MEM * mem_h = NULL;
    BIGNUM * bn_s = NULL, *order = NULL, *cofactor = NULL;
    EC_POINT * ecp_h = NULL, *ecp_g = NULL;
    const ECDH_METHOD *default_method;
    EC_GROUP *group = NULL;
    EC_KEY *static_key = NULL, *ephemeral_key = NULL;

    BN_CTX_start(bn_ctx);

    check((ctx && ctx->static_key && s && ctx->ka_ctx), "Invalid arguments");

    static_key = EVP_PKEY_get1_EC_KEY(ctx->static_key);
    check(static_key, "could not get key object");

    /* Extract group parameters */
    group = EC_GROUP_dup(EC_KEY_get0_group(static_key));
    order = BN_CTX_get(bn_ctx);
    cofactor = BN_CTX_get(bn_ctx);
    check(group && cofactor, "internal error");
    if (!EC_GROUP_get_order(group, order, bn_ctx)
            || !EC_GROUP_get_cofactor(group, cofactor, bn_ctx))
        goto err;

    /* Convert nonce to BIGNUM */
    bn_s = BN_bin2bn((unsigned char *) s->data, s->length, bn_s);
    if (!bn_s)
        goto err;

    default_method = ECDH_get_default_method();
    ECDH_set_default_method(ECDH_OpenSSL_Point());
    /* complete the ECDH and get the resulting point h */
    mem_h = ecdh_compute_key(ctx->static_key, in, bn_ctx);
    ECDH_set_default_method(default_method);
    ecp_h = EC_POINT_new(group);
    if (!mem_h || !ecp_h || !EC_POINT_oct2point(group, ecp_h,
            (unsigned char *) mem_h->data, mem_h->length, bn_ctx))
        goto err;

    /* map to new generator */
    ecp_g = EC_POINT_new(group);
    /* g' = g*s + h*1 */
    if (!EC_POINT_mul(group, ecp_g, bn_s, ecp_h, BN_value_one(), bn_ctx))
        goto err;

    /* Initialize ephemeral parameters with parameters from the static key */
    ephemeral_key = EC_KEY_dup(static_key);
    if (!ephemeral_key)
        goto err;
    EVP_PKEY_set1_EC_KEY(ctx->ka_ctx->key, ephemeral_key);

    /* configure the new EC_KEY */
    if (!EC_GROUP_set_generator(group, ecp_g, order, cofactor)
            || !EC_GROUP_check(group, bn_ctx)
            || !EC_KEY_set_group(ephemeral_key, group))
        goto err;

    ret = 1;

err:
    if (ecp_g)
        EC_POINT_clear_free(ecp_g);
    if (ecp_h)
        EC_POINT_clear_free(ecp_h);
    if (mem_h)
        BUF_MEM_free(mem_h);
    if (bn_s)
        BN_clear_free(bn_s);
    BN_CTX_end(bn_ctx);
    /* Decrement reference count, keys are still available via PACE_CTX */
    if (static_key)
        EC_KEY_free(static_key);
    if (ephemeral_key)
        EC_KEY_free(ephemeral_key);
    if (group)
        EC_GROUP_clear_free(group);

    return ret;
}
Exemplo n.º 26
0
BitcoinResult Bitcoin_MakePublicKeyFromPrivateKey(
	struct BitcoinPublicKey *public_key,
	const struct BitcoinPrivateKey *private_key
)
{
	BN_CTX *ctx = NULL;
	EC_KEY *key = NULL;
	EC_POINT *ec_public = NULL;
	unsigned char *public_key_ptr = public_key->data;
	BIGNUM *private_key_bn;
	const EC_GROUP *group = NULL;
	int size, size2;
	unsigned compression = private_key->public_key_compression;
	size_t expected_public_key_size = 0;
	enum BitcoinPublicKeyCompression public_key_compression;

	switch (compression) {
		case BITCOIN_PUBLIC_KEY_COMPRESSED :
		case BITCOIN_PUBLIC_KEY_UNCOMPRESSED :
			break;
		default :
			applog(APPLOG_ERROR, __func__,
				"public key compression is not specified, please set using"
				" --public-key-compression compressed/uncompressed"
			);
			EC_KEY_free(key);
			return BITCOIN_ERROR_PRIVATE_KEY_INVALID_FORMAT;
			break;
	}

	key = EC_KEY_new_by_curve_name_NID_secp256k1();
	if (!key) {
		applog(APPLOG_ERROR, __func__,
			"EC_KEY_new_by_curve_name failed: %s",
			ERR_error_string(ERR_get_error(), NULL)
		);
		return BITCOIN_ERROR_LIBRARY_FAILURE;
	}

	group = EC_KEY_get0_group(key);
	if (!group) {
		applog(APPLOG_ERROR, __func__,
			"EC_KEY_get0_group failed: %s",
			ERR_error_string(ERR_get_error(), NULL)
		);
		EC_KEY_free(key);
		return BITCOIN_ERROR_LIBRARY_FAILURE;
	}

	private_key_bn = BN_new();
	BN_bin2bn(private_key->data, BITCOIN_PRIVATE_KEY_SIZE, private_key_bn);
	ec_public = EC_POINT_new(group);

	ctx = BN_CTX_new();
	if (!ctx) {
		applog(APPLOG_ERROR, __func__,
			"BN_CTX_new failed: %s",
			ERR_error_string(ERR_get_error(), NULL)
		);
		EC_KEY_free(key);
		return BITCOIN_ERROR_LIBRARY_FAILURE;
	}

	if (!EC_POINT_mul(group, ec_public, private_key_bn, NULL, NULL, ctx)) {
		applog(APPLOG_ERROR, __func__,
			"EC_POINT_mul failed: %s",
			ERR_error_string(ERR_get_error(), NULL)
		);
		EC_KEY_free(key);
		return BITCOIN_ERROR_LIBRARY_FAILURE;
	}

	EC_KEY_set_private_key(key, private_key_bn);
	EC_KEY_set_public_key(key, ec_public);

	if (compression == BITCOIN_PUBLIC_KEY_COMPRESSED) {
		EC_KEY_set_conv_form(key, POINT_CONVERSION_COMPRESSED);
		expected_public_key_size = BITCOIN_PUBLIC_KEY_COMPRESSED_SIZE;
		public_key_compression = BITCOIN_PUBLIC_KEY_COMPRESSED;
	} else {
		EC_KEY_set_conv_form(key, POINT_CONVERSION_UNCOMPRESSED);
		expected_public_key_size = BITCOIN_PUBLIC_KEY_UNCOMPRESSED_SIZE;
		public_key_compression = BITCOIN_PUBLIC_KEY_UNCOMPRESSED;
	}

	size = i2o_ECPublicKey(key, NULL);

	if (size != expected_public_key_size) {
		fprintf(stderr, "%s: invalid public key size (%u), should be %u\n",
			__func__,
			(unsigned)size,
			(unsigned)expected_public_key_size
		);
		BN_free(private_key_bn);
		EC_KEY_free(key);
		return BITCOIN_ERROR_PUBLIC_KEY_INVALID_FORMAT;
	}

	size2 = i2o_ECPublicKey(key, &public_key_ptr);
	if (size2 != expected_public_key_size) {
		fprintf(stderr, "%s: invalid public key size (%u), should be %u\n",
			__func__,
			(unsigned)size,
			(unsigned)expected_public_key_size
		);
		BN_free(private_key_bn);
		EC_KEY_free(key);
		return BITCOIN_ERROR_PUBLIC_KEY_INVALID_FORMAT;
	}

	/* public key appears to be valid by now, set the compression type */
	public_key->compression = public_key_compression;
	public_key->network_type = private_key->network_type;

	/* free resources */
	EC_POINT_clear_free(ec_public);
	BN_free(private_key_bn);
	BN_CTX_free(ctx);
	EC_KEY_free(key);

	return BITCOIN_SUCCESS;
}
Exemplo n.º 27
0
static int ecdh_build_k(ssh_session session) {
  const EC_GROUP *group = EC_KEY_get0_group(session->next_crypto->ecdh_privkey);
  EC_POINT *pubkey;
  void *buffer;
  int rc;
  int len = (EC_GROUP_get_degree(group) + 7) / 8;
  bignum_CTX ctx = bignum_ctx_new();
  if (ctx == NULL) {
    return -1;
  }

  session->next_crypto->k = bignum_new();
  if (session->next_crypto->k == NULL) {
    bignum_ctx_free(ctx);
    return -1;
  }

  pubkey = EC_POINT_new(group);
  if (pubkey == NULL) {
    bignum_ctx_free(ctx);
    return -1;
  }

  if (session->server) {
      rc = EC_POINT_oct2point(group,
                              pubkey,
                              ssh_string_data(session->next_crypto->ecdh_client_pubkey),
                              ssh_string_len(session->next_crypto->ecdh_client_pubkey),
                              ctx);
  } else {
      rc = EC_POINT_oct2point(group,
                              pubkey,
                              ssh_string_data(session->next_crypto->ecdh_server_pubkey),
                              ssh_string_len(session->next_crypto->ecdh_server_pubkey),
                              ctx);
  }
  bignum_ctx_free(ctx);
  if (rc <= 0) {
      EC_POINT_clear_free(pubkey);
      return -1;
  }

  buffer = malloc(len);
  if (buffer == NULL) {
      EC_POINT_clear_free(pubkey);
      return -1;
  }

  rc = ECDH_compute_key(buffer,
                        len,
                        pubkey,
                        session->next_crypto->ecdh_privkey,
                        NULL);
  EC_POINT_clear_free(pubkey);
  if (rc <= 0) {
      free(buffer);
      return -1;
  }

  bignum_bin2bn(buffer, len, session->next_crypto->k);
  free(buffer);

  EC_KEY_free(session->next_crypto->ecdh_privkey);
  session->next_crypto->ecdh_privkey = NULL;

#ifdef DEBUG_CRYPTO
    ssh_print_hexa("Session server cookie",
                   session->next_crypto->server_kex.cookie, 16);
    ssh_print_hexa("Session client cookie",
                   session->next_crypto->client_kex.cookie, 16);
    ssh_print_bignum("Shared secret key", session->next_crypto->k);
#endif

  return 0;
}
Exemplo n.º 28
0
int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
	{
	EC_EXTRA_DATA *d;

	if (dest->meth->group_copy == 0)
		{
		ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
		return 0;
		}
	if (dest->meth != src->meth)
		{
		ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
		return 0;
		}
	if (dest == src)
		return 1;
	
	EC_EX_DATA_free_all_data(&dest->extra_data);

	for (d = src->extra_data; d != NULL; d = d->next)
		{
		void *t = d->dup_func(d->data);
		
		if (t == NULL)
			return 0;
		if (!EC_EX_DATA_set_data(&dest->extra_data, t, d->dup_func, d->free_func, d->clear_free_func))
			return 0;
		}

	if (src->generator != NULL)
		{
		if (dest->generator == NULL)
			{
			dest->generator = EC_POINT_new(dest);
			if (dest->generator == NULL) return 0;
			}
		if (!EC_POINT_copy(dest->generator, src->generator)) return 0;
		}
	else
		{
		/* src->generator == NULL */
		if (dest->generator != NULL)
			{
			EC_POINT_clear_free(dest->generator);
			dest->generator = NULL;
			}
		}

	if (!BN_copy(&dest->order, &src->order)) return 0;
	if (!BN_copy(&dest->cofactor, &src->cofactor)) return 0;

	dest->curve_name = src->curve_name;
	dest->asn1_flag  = src->asn1_flag;
	dest->asn1_form  = src->asn1_form;

	if (src->seed)
		{
		if (dest->seed)
			OPENSSL_free(dest->seed);
		dest->seed = OPENSSL_malloc(src->seed_len);
		if (dest->seed == NULL)
			return 0;
		if (!memcpy(dest->seed, src->seed, src->seed_len))
			return 0;
		dest->seed_len = src->seed_len;
		}
	else
		{
		if (dest->seed)
			OPENSSL_free(dest->seed);
		dest->seed = NULL;
		dest->seed_len = 0;
		}
	

	return dest->meth->group_copy(dest, src);
	}
Exemplo n.º 29
0
int
ecdh_im_compute_key(PACE_CTX * ctx, const BUF_MEM * s, const BUF_MEM * in,
        BN_CTX *bn_ctx)
{
    int ret = 0;
    BUF_MEM * x_mem = NULL;
    BIGNUM * a = NULL, *b = NULL, *p = NULL;
    BIGNUM * x = NULL, *y = NULL, *v = NULL, *u = NULL;
    BIGNUM * tmp = NULL, *tmp2 = NULL, *bn_inv = NULL;
    BIGNUM * two = NULL, *three = NULL, *four = NULL, *six = NULL;
    BIGNUM * twentyseven = NULL;
    EC_KEY *static_key = NULL, *ephemeral_key = NULL;
    EC_POINT *g = NULL;

    BN_CTX_start(bn_ctx);

    check((ctx && ctx->static_key && s && ctx->ka_ctx), "Invalid arguments"); 

    static_key = EVP_PKEY_get1_EC_KEY(ctx->static_key);
    if (!static_key)
        goto err;

    /* Setup all the variables*/
    a = BN_CTX_get(bn_ctx);
    b = BN_CTX_get(bn_ctx);
    p = BN_CTX_get(bn_ctx);
    x = BN_CTX_get(bn_ctx);
    y = BN_CTX_get(bn_ctx);
    v = BN_CTX_get(bn_ctx);
    two = BN_CTX_get(bn_ctx);
    three = BN_CTX_get(bn_ctx);
    four = BN_CTX_get(bn_ctx);
    six = BN_CTX_get(bn_ctx);
    twentyseven = BN_CTX_get(bn_ctx);
    tmp = BN_CTX_get(bn_ctx);
    tmp2 = BN_CTX_get(bn_ctx);
    bn_inv = BN_CTX_get(bn_ctx);
    if (!bn_inv)
        goto err;

    /* Encrypt the Nonce using the symmetric key in */
    x_mem = cipher_no_pad(ctx->ka_ctx, NULL, in, s, 1);
    if (!x_mem)
        goto err;

    /* Fetch the curve parameters */
    if (!EC_GROUP_get_curve_GFp(EC_KEY_get0_group(static_key), p, a, b, bn_ctx))
        goto err;

    /* Assign constants */
    if (    !BN_set_word(two,2)||
            !BN_set_word(three,3)||
            !BN_set_word(four,4)||
            !BN_set_word(six,6)||
            !BN_set_word(twentyseven,27)
            ) goto err;

    /* Check prerequisites for curve parameters */
    check(
            /* p > 3;*/
           (BN_cmp(p, three) == 1) &&
           /* p mod 3 = 2; (p has the form p=q^n, q prime) */
           BN_nnmod(tmp, p, three, bn_ctx) &&
           (BN_cmp(tmp, two) == 0),
        "Unsuited curve");

    /* Convert encrypted nonce to BIGNUM */
    u = BN_bin2bn((unsigned char *) x_mem->data, x_mem->length, u);
    if (!u)
        goto err;

    if ( /* v = (3a - u^4) / 6u mod p */
            !BN_mod_mul(tmp, three, a, p, bn_ctx) ||
            !BN_mod_exp(tmp2, u, four, p, bn_ctx) ||
            !BN_mod_sub(v, tmp, tmp2, p, bn_ctx) ||
            !BN_mod_mul(tmp, u, six, p, bn_ctx) ||
            /* For division within a galois field we need to compute
             * the multiplicative inverse of a number */
            !BN_mod_inverse(bn_inv, tmp, p, bn_ctx) ||
            !BN_mod_mul(v, v, bn_inv, p, bn_ctx) ||

            /* x = (v^2 - b - ((u^6)/27)) */
            !BN_mod_sqr(tmp, v, p, bn_ctx) ||
            !BN_mod_sub(tmp2, tmp, b, p, bn_ctx) ||
            !BN_mod_exp(tmp, u, six, p, bn_ctx) ||
            !BN_mod_inverse(bn_inv, twentyseven, p, bn_ctx) ||
            !BN_mod_mul(tmp, tmp, bn_inv, p, bn_ctx) ||
            !BN_mod_sub(x, tmp2, tmp, p, bn_ctx) ||

            /* x -> x^(1/3) = x^((2p^n -1)/3) */
            !BN_mul(tmp, two, p, bn_ctx) ||
            !BN_sub(tmp, tmp, BN_value_one()) ||

            /* Division is defined, because p^n = 2 mod 3 */
            !BN_div(tmp, y, tmp, three, bn_ctx) ||
            !BN_mod_exp(tmp2, x, tmp, p, bn_ctx) ||
            !BN_copy(x, tmp2) ||

            /* x += (u^2)/3 */
            !BN_mod_sqr(tmp, u, p, bn_ctx) ||
            !BN_mod_inverse(bn_inv, three, p, bn_ctx) ||
            !BN_mod_mul(tmp2, tmp, bn_inv, p, bn_ctx) ||
            !BN_mod_add(tmp, x, tmp2, p, bn_ctx) ||
            !BN_copy(x, tmp) ||

            /* y = ux + v */
            !BN_mod_mul(y, u, x, p, bn_ctx) ||
            !BN_mod_add(tmp, y, v, p, bn_ctx) ||
            !BN_copy(y, tmp)
            )
        goto err;

    /* Initialize ephemeral parameters with parameters from the static key */
    ephemeral_key = EC_KEY_dup(static_key);
    if (!ephemeral_key)
        goto err;
    EVP_PKEY_set1_EC_KEY(ctx->ka_ctx->key, ephemeral_key);

    /* configure the new EC_KEY */
    g = EC_POINT_new(EC_KEY_get0_group(ephemeral_key));
    if (!g)
        goto err;
    if (!EC_POINT_set_affine_coordinates_GFp(EC_KEY_get0_group(ephemeral_key), g,
            x, y, bn_ctx))
        goto err;

    ret = 1;

err:
    if (x_mem)
        BUF_MEM_free(x_mem);
    if (u)
        BN_free(u);
    BN_CTX_end(bn_ctx);
    if (g)
        EC_POINT_clear_free(g);
    /* Decrement reference count, keys are still available via PACE_CTX */
    if (static_key)
        EC_KEY_free(static_key);
    if (ephemeral_key)
        EC_KEY_free(ephemeral_key);

    return ret;
}