static void
eap_pwd_perform_confirm_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)
{
	BIGNUM *x = NULL, *y = NULL;
	struct crypto_hash *hash;
	u32 cs;
	u16 grp;
	u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr;
	int offset;

	/*
	 * first build up the ciphersuite which is group | random_function |
	 *	prf
	 */
	grp = htons(data->group_num);
	ptr = (u8 *) &cs;
	os_memcpy(ptr, &grp, sizeof(u16));
	ptr += sizeof(u16);
	*ptr = EAP_PWD_DEFAULT_RAND_FUNC;
	ptr += sizeof(u8);
	*ptr = EAP_PWD_DEFAULT_PRF;

	/* each component of the cruft will be at most as big as the prime */
	if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) ||
	    ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) {
		wpa_printf(MSG_INFO, "EAP-PWD (server): confirm allocation "
			   "fail");
		goto fin;
	}

	/*
	 * server's commit is H(k | server_element | server_scalar |
	 *			peer_element | peer_scalar | ciphersuite)
	 */
	hash = eap_pwd_h_init();
	if (hash == NULL)
		goto fin;

	/*
	 * zero the memory each time because this is mod prime math and some
	 * value may start with a few zeros and the previous one did not.
	 */
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k);
	BN_bn2bin(data->k, cruft + offset);
	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));

	/* server element: x, y */
	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
						 data->server_element, x, y,
						 data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
			   "assignment fail");
		goto fin;
	}
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
	BN_bn2bin(x, cruft + offset);
	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
	BN_bn2bin(y, cruft + offset);
	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));

	/* server scalar */
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	offset = BN_num_bytes(data->grp->order) -
		BN_num_bytes(data->server_scalar);
	BN_bn2bin(data->server_scalar, cruft + offset);
	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));

	/* my element: x, y */
	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
						 data->my_element, x, y,
						 data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
			   "assignment fail");
		goto fin;
	}

	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
	BN_bn2bin(x, cruft + offset);
	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
	BN_bn2bin(y, cruft + offset);
	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));

	/* my scalar */
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	offset = BN_num_bytes(data->grp->order) -
		BN_num_bytes(data->my_scalar);
	BN_bn2bin(data->my_scalar, cruft + offset);
	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));

	/* the ciphersuite */
	eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32));

	/* random function fin */
	eap_pwd_h_final(hash, conf);

	ptr = (u8 *) payload;
	if (os_memcmp(conf, ptr, SHA256_MAC_LEN)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm did not verify");
		goto fin;
	}

	wpa_printf(MSG_DEBUG, "EAP-pwd (peer): confirm verified");

	/*
	 * compute confirm:
	 *  H(k | peer_element | peer_scalar | server_element | server_scalar |
	 *    ciphersuite)
	 */
	hash = eap_pwd_h_init();
	if (hash == NULL)
		goto fin;

	/* k */
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k);
	BN_bn2bin(data->k, cruft + offset);
	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));

	/* my element */
	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
						 data->my_element, x, y,
						 data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm point "
			   "assignment fail");
		goto fin;
	}
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
	BN_bn2bin(x, cruft + offset);
	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
	BN_bn2bin(y, cruft + offset);
	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));

	/* my scalar */
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	offset = BN_num_bytes(data->grp->order) -
		BN_num_bytes(data->my_scalar);
	BN_bn2bin(data->my_scalar, cruft + offset);
	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));

	/* server element: x, y */
	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
						 data->server_element, x, y,
						 data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm point "
			   "assignment fail");
		goto fin;
	}
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
	BN_bn2bin(x, cruft + offset);
	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
	BN_bn2bin(y, cruft + offset);
	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));

	/* server scalar */
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	offset = BN_num_bytes(data->grp->order) -
		BN_num_bytes(data->server_scalar);
	BN_bn2bin(data->server_scalar, cruft + offset);
	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));

	/* the ciphersuite */
	eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32));

	/* all done */
	eap_pwd_h_final(hash, conf);

	if (compute_keys(data->grp, data->bnctx, data->k,
			 data->my_scalar, data->server_scalar, conf, ptr,
			 &cs, data->msk, data->emsk) < 0) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to compute MSK | "
			   "EMSK");
		goto fin;
	}

	data->outbuf = wpabuf_alloc(SHA256_MAC_LEN);
	if (data->outbuf == NULL)
		goto fin;

	wpabuf_put_data(data->outbuf, conf, SHA256_MAC_LEN);

fin:
	os_free(cruft);
	BN_free(x);
	BN_free(y);
	ret->methodState = METHOD_DONE;
	if (data->outbuf == NULL) {
		ret->decision = DECISION_FAIL;
		eap_pwd_state(data, FAILURE);
	} else {
		ret->decision = DECISION_UNCOND_SUCC;
		eap_pwd_state(data, SUCCESS);
	}
}
Пример #2
0
static void
eap_pwd_process_confirm_resp(struct eap_sm *sm, struct eap_pwd_data *data,
			     const u8 *payload, size_t payload_len)
{
	BIGNUM *x = NULL, *y = NULL;
	HMAC_CTX ctx;
	u32 cs;
	u16 grp;
	u8 conf[SHA256_DIGEST_LENGTH], *cruft = NULL, *ptr;

	/* build up the ciphersuite: group | random_function | prf */
	grp = htons(data->group_num);
	ptr = (u8 *) &cs;
	os_memcpy(ptr, &grp, sizeof(u16));
	ptr += sizeof(u16);
	*ptr = EAP_PWD_DEFAULT_RAND_FUNC;
	ptr += sizeof(u8);
	*ptr = EAP_PWD_DEFAULT_PRF;

	/* each component of the cruft will be at most as big as the prime */
	if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) ||
	    ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): allocation fail");
		goto fin;
	}

	/*
	 * commit is H(k | peer_element | peer_scalar | server_element |
	 *	       server_scalar | ciphersuite)
	 */
	H_Init(&ctx);

	/* k */
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	BN_bn2bin(data->k, cruft);
	H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime));

	/* peer element: x, y */
	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
						 data->peer_element, x, y,
						 data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
			   "assignment fail");
		goto fin;
	}
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	BN_bn2bin(x, cruft);
	H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime));
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	BN_bn2bin(y, cruft);
	H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime));

	/* peer scalar */
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	BN_bn2bin(data->peer_scalar, cruft);
	H_Update(&ctx, cruft, BN_num_bytes(data->grp->order));

	/* server element: x, y */
	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
						 data->my_element, x, y,
						 data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
			   "assignment fail");
		goto fin;
	}

	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	BN_bn2bin(x, cruft);
	H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime));
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	BN_bn2bin(y, cruft);
	H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime));

	/* server scalar */
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	BN_bn2bin(data->my_scalar, cruft);
	H_Update(&ctx, cruft, BN_num_bytes(data->grp->order));

	/* ciphersuite */
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	H_Update(&ctx, (u8 *)&cs, sizeof(u32));

	/* all done */
	H_Final(&ctx, conf);

	ptr = (u8 *) payload;
	if (os_memcmp(conf, ptr, SHA256_DIGEST_LENGTH)) {
		wpa_printf(MSG_INFO, "EAP-PWD (server): confirm did not "
			   "verify");
		goto fin;
	}

	wpa_printf(MSG_DEBUG, "EAP-pwd (server): confirm verified");
	if (compute_keys(data->grp, data->bnctx, data->k,
			 data->peer_scalar, data->my_scalar, conf,
			 data->my_confirm, &cs, data->msk, data->emsk) < 0)
		eap_pwd_state(data, FAILURE);
	else
		eap_pwd_state(data, SUCCESS);

fin:
	os_free(cruft);
	BN_free(x);
	BN_free(y);
}
Пример #3
0
static void
eap_pwd_process_confirm_resp(struct eap_sm *sm, struct eap_pwd_data *data,
			     const u8 *payload, size_t payload_len)
{
	BIGNUM *x = NULL, *y = NULL;
	struct crypto_hash *hash;
	u32 cs;
	u16 grp;
	u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr;
	int offset;

	if (payload_len != SHA256_MAC_LEN) {
		wpa_printf(MSG_INFO,
			   "EAP-pwd: Unexpected Confirm payload length %u (expected %u)",
			   (unsigned int) payload_len, SHA256_MAC_LEN);
		goto fin;
	}

	/* build up the ciphersuite: group | random_function | prf */
	grp = htons(data->group_num);
	ptr = (u8 *) &cs;
	os_memcpy(ptr, &grp, sizeof(u16));
	ptr += sizeof(u16);
	*ptr = EAP_PWD_DEFAULT_RAND_FUNC;
	ptr += sizeof(u8);
	*ptr = EAP_PWD_DEFAULT_PRF;

	/* each component of the cruft will be at most as big as the prime */
	if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) ||
	    ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): allocation fail");
		goto fin;
	}

	/*
	 * commit is H(k | peer_element | peer_scalar | server_element |
	 *	       server_scalar | ciphersuite)
	 */
	hash = eap_pwd_h_init();
	if (hash == NULL)
		goto fin;

	/* k */
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k);
	BN_bn2bin(data->k, cruft + offset);
	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));

	/* peer element: x, y */
	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
						 data->peer_element, x, y,
						 data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
			   "assignment fail");
		goto fin;
	}
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
	BN_bn2bin(x, cruft + offset);
	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
	BN_bn2bin(y, cruft + offset);
	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));

	/* peer scalar */
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	offset = BN_num_bytes(data->grp->order) -
		BN_num_bytes(data->peer_scalar);
	BN_bn2bin(data->peer_scalar, cruft + offset);
	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));

	/* server element: x, y */
	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
						 data->my_element, x, y,
						 data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
			   "assignment fail");
		goto fin;
	}

	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
	BN_bn2bin(x, cruft + offset);
	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
	BN_bn2bin(y, cruft + offset);
	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));

	/* server scalar */
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	offset = BN_num_bytes(data->grp->order) -
		BN_num_bytes(data->my_scalar);
	BN_bn2bin(data->my_scalar, cruft + offset);
	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));

	/* ciphersuite */
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32));

	/* all done */
	eap_pwd_h_final(hash, conf);

	ptr = (u8 *) payload;
	if (os_memcmp_const(conf, ptr, SHA256_MAC_LEN)) {
		wpa_printf(MSG_INFO, "EAP-PWD (server): confirm did not "
			   "verify");
		goto fin;
	}

	wpa_printf(MSG_DEBUG, "EAP-pwd (server): confirm verified");
	if (compute_keys(data->grp, data->bnctx, data->k,
			 data->peer_scalar, data->my_scalar, conf,
			 data->my_confirm, &cs, data->msk, data->emsk,
			 data->session_id) < 0)
		eap_pwd_state(data, FAILURE);
	else
		eap_pwd_state(data, SUCCESS);

fin:
	bin_clear_free(cruft, BN_num_bytes(data->grp->prime));
	BN_clear_free(x);
	BN_clear_free(y);
}
Пример #4
0
static int
mod_authenticate (void *arg, eap_handler_t *handler)
{
    pwd_session_t *pwd_session;
    pwd_hdr *hdr;
    pwd_id_packet *id;
    eap_packet_t *response;
    REQUEST *request, *fake;
    VALUE_PAIR *pw, *vp;
    EAP_DS *eap_ds;
    int len, ret = 0;
    eap_pwd_t *inst = (eap_pwd_t *)arg;
    uint16_t offset;
    uint8_t exch, *buf, *ptr, msk[MSK_EMSK_LEN], emsk[MSK_EMSK_LEN];
    uint8_t peer_confirm[SHA256_DIGEST_LENGTH];
    BIGNUM *x = NULL, *y = NULL;

    if ((!handler) ||
	((eap_ds = handler->eap_ds) == NULL) ||
	(!inst)) {
	return 0;
    }
    pwd_session = (pwd_session_t *)handler->opaque;
    request = handler->request;
    response = handler->eap_ds->response;
    hdr = (pwd_hdr *)response->type.data;

    buf = hdr->data;
    len = response->type.length - sizeof(pwd_hdr);

    /*
     * see if we're fragmenting, if so continue until we're done
     */
    if (pwd_session->out_buf_pos) {
	if (len) {
	    RDEBUG2("pwd got something more than an ACK for a fragment");
	}
	return send_pwd_request(pwd_session, eap_ds);
    }

    /*
     * the first fragment will have a total length, make a
     * buffer to hold all the fragments
     */
    if (EAP_PWD_GET_LENGTH_BIT(hdr)) {
	if (pwd_session->in_buf) {
	    RDEBUG2("pwd already alloced buffer for fragments");
	    return 0;
	}
	pwd_session->in_buf_len = ntohs(buf[0] * 256 | buf[1]);
	if ((pwd_session->in_buf = talloc_zero_array(pwd_session, uint8_t,
						     pwd_session->in_buf_len)) == NULL) {
	    RDEBUG2("pwd cannot allocate %d buffer to hold fragments",
		    pwd_session->in_buf_len);
	    return 0;
	}
	memset(pwd_session->in_buf, 0, pwd_session->in_buf_len);
	pwd_session->in_buf_pos = 0;
	buf += sizeof(uint16_t);
	len -= sizeof(uint16_t);
    }

    /*
     * all fragments, including the 1st will have the M(ore) bit set,
     * buffer those fragments!
     */
    if (EAP_PWD_GET_MORE_BIT(hdr)) {
	rad_assert(pwd_session->in_buf != NULL);
	if ((pwd_session->in_buf_pos + len) > pwd_session->in_buf_len) {
	    RDEBUG2("pwd will not overflow a fragment buffer. Nope, not prudent.");
	    return 0;
	}
	memcpy(pwd_session->in_buf + pwd_session->in_buf_pos, buf, len);
	pwd_session->in_buf_pos += len;

	/*
	 * send back an ACK for this fragment
	 */
	exch = EAP_PWD_GET_EXCHANGE(hdr);
	eap_ds->request->code = PW_EAP_REQUEST;
	eap_ds->request->type.num = PW_EAP_PWD;
	eap_ds->request->type.length = sizeof(pwd_hdr);
	if ((eap_ds->request->type.data = talloc_array(eap_ds->request,
						       uint8_t, sizeof(pwd_hdr))) == NULL) {
	    return 0;
	}
	hdr = (pwd_hdr *)eap_ds->request->type.data;
	EAP_PWD_SET_EXCHANGE(hdr, exch);
	return 1;

    }

    if (pwd_session->in_buf) {
	/*
	 * the last fragment...
	 */
	if ((pwd_session->in_buf_pos + len) > pwd_session->in_buf_len) {
	    RDEBUG2("pwd will not overflow a fragment buffer. Nope, not prudent.");
	    return 0;
	}
	memcpy(pwd_session->in_buf + pwd_session->in_buf_pos, buf, len);
	buf = pwd_session->in_buf;
	len = pwd_session->in_buf_len;
    }

    switch (pwd_session->state) {
	case PWD_STATE_ID_REQ:
	    if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_ID) {
		RDEBUG2("pwd exchange is incorrect: not ID");
		return 0;
	    }
	    id = (pwd_id_packet *)buf;
	    if ((id->prf != EAP_PWD_DEF_PRF) ||
		(id->random_function != EAP_PWD_DEF_RAND_FUN) ||
		(id->prep != EAP_PWD_PREP_NONE) ||
		(memcmp(id->token, (char *)&pwd_session->token, 4)) ||
		(id->group_num != ntohs(pwd_session->group_num))) {
		RDEBUG2("pwd id response is invalid");
		return 0;
	    }
	    /*
	     * we've agreed on the ciphersuite, record it...
	     */
	    ptr = (uint8_t *)&pwd_session->ciphersuite;
	    memcpy(ptr, (char *)&id->group_num, sizeof(uint16_t));
	    ptr += sizeof(uint16_t);
	    *ptr = EAP_PWD_DEF_RAND_FUN;
	    ptr += sizeof(uint8_t);
	    *ptr = EAP_PWD_DEF_PRF;

	    pwd_session->peer_id_len = len - sizeof(pwd_id_packet);
	    if (pwd_session->peer_id_len >= sizeof(pwd_session->peer_id)) {
		RDEBUG2("pwd id response is malformed");
		return 0;
	    }
	    memcpy(pwd_session->peer_id, id->identity,
		    pwd_session->peer_id_len);
	    pwd_session->peer_id[pwd_session->peer_id_len] = '\0';

	    /*
	     * make fake request to get the password for the usable ID
	     */
	    if ((fake = request_alloc_fake(handler->request)) == NULL) {
		RDEBUG("pwd unable to create fake request!");
		return 0;
	    }
	    fake->username = pairmake_packet("User-Name", "", T_OP_EQ);
	    if (!fake->username) {
		RDEBUG("pwd unanable to create value pair for username!");
		request_free(&fake);
		return 0;
	    }
	    memcpy(fake->username->vp_strvalue, pwd_session->peer_id,
		   pwd_session->peer_id_len);
	    fake->username->length = pwd_session->peer_id_len;
	    fake->username->vp_strvalue[fake->username->length] = 0;

	    if ((vp = pairfind(request->config_items, PW_VIRTUAL_SERVER, 0, TAG_ANY)) != NULL) {
		    fake->server = vp->vp_strvalue;
		
	    } else if (inst->conf->virtual_server) {
		    fake->server = inst->conf->virtual_server;
		
	    } /* else fake->server == request->server */
	
	    if ((debug_flag > 0) && fr_log_fp) {
		    RDEBUG("Sending tunneled request");
		
		    debug_pair_list(fake->packet->vps);
		
		    fprintf(fr_log_fp, "server %s {\n",
			    (!fake->server) ? "" : fake->server);
	    }
	
	    /*
	     *	Call authorization recursively, which will
	     *	get the password.
	     */
	    process_authorize(0, fake);
	
	    /*
	     *	Note that we don't do *anything* with the reply
	     *	attributes.
	     */
	    if ((debug_flag > 0) && fr_log_fp) {
		    fprintf(fr_log_fp, "} # server %s\n",
			    (!fake->server) ? "" : fake->server);
		
		    RDEBUG("Got tunneled reply code %d", fake->reply->code);
		
		    debug_pair_list(fake->reply->vps);
	    }

	    if ((pw = pairfind(fake->config_items, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) == NULL) {
		DEBUG2("failed to find password for %s to do pwd authentication",
		       pwd_session->peer_id);
		request_free(&fake);
		return 0;
	    }

	    if (compute_password_element(pwd_session, pwd_session->group_num,
					 pw->data.strvalue, strlen(pw->data.strvalue),
					 inst->conf->server_id, strlen(inst->conf->server_id),
					 pwd_session->peer_id, strlen(pwd_session->peer_id),
					 &pwd_session->token)) {
		DEBUG2("failed to obtain password element :-(");
		request_free(&fake);
		return 0;
	    }
	    request_free(&fake);

	    /*
	     * compute our scalar and element
	     */
	    if (compute_scalar_element(pwd_session, inst->bnctx)) {
		DEBUG2("failed to compute server's scalar and element");
		return 0;
	    }
	    if (((x = BN_new()) == NULL) ||
		((y = BN_new()) == NULL)) {
		DEBUG2("server point allocation failed");
		return 0;
	    }
	    /*
	     * element is a point, get both coordinates: x and y
	     */
	    if (!EC_POINT_get_affine_coordinates_GFp(pwd_session->group,
						     pwd_session->my_element, x, y,
						     inst->bnctx)) {
		DEBUG2("server point assignment failed");
		BN_free(x);
		BN_free(y);
		return 0;
	    }
	    /*
	     * construct request
	     */
	    pwd_session->out_buf_len = BN_num_bytes(pwd_session->order) +
		(2 * BN_num_bytes(pwd_session->prime));
	    if ((pwd_session->out_buf = talloc_array(pwd_session, uint8_t,
						     pwd_session->out_buf_len)) == NULL) {
		return 0;
	    }
	    memset(pwd_session->out_buf, 0, pwd_session->out_buf_len);

	    ptr = pwd_session->out_buf;
	    offset = BN_num_bytes(pwd_session->prime) - BN_num_bytes(x);
	    BN_bn2bin(x, ptr + offset);

	    ptr += BN_num_bytes(pwd_session->prime);
	    offset = BN_num_bytes(pwd_session->prime) - BN_num_bytes(y);
	    BN_bn2bin(y, ptr + offset);

	    ptr += BN_num_bytes(pwd_session->prime);
	    offset = BN_num_bytes(pwd_session->order) - BN_num_bytes(pwd_session->my_scalar);
	    BN_bn2bin(pwd_session->my_scalar, ptr + offset);

	    pwd_session->state = PWD_STATE_COMMIT;
	    ret = send_pwd_request(pwd_session, eap_ds);
	    break;
	case PWD_STATE_COMMIT:
	    if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_COMMIT) {
		RDEBUG2("pwd exchange is incorrect: not commit!");
		return 0;
	    }
	    /*
	     * process the peer's commit and generate the shared key, k
	     */
	    if (process_peer_commit(pwd_session, buf, inst->bnctx)) {
		RDEBUG2("failed to process peer's commit");
		return 0;
	    }

	    /*
	     * compute our confirm blob
	     */
	    if (compute_server_confirm(pwd_session, pwd_session->my_confirm, inst->bnctx)) {
		ERROR("rlm_eap_pwd: failed to compute confirm!");
		return 0;
	    }
	    /*
	     * construct a response...which is just our confirm blob
	     */
	    pwd_session->out_buf_len = SHA256_DIGEST_LENGTH;
	    if ((pwd_session->out_buf = talloc_array(pwd_session, uint8_t,
						     pwd_session->out_buf_len)) == NULL) {
		return 0;
	    }
	    memset(pwd_session->out_buf, 0, pwd_session->out_buf_len);
	    memcpy(pwd_session->out_buf, pwd_session->my_confirm, SHA256_DIGEST_LENGTH);

	    pwd_session->state = PWD_STATE_CONFIRM;
	    ret = send_pwd_request(pwd_session, eap_ds);
	    break;
	case PWD_STATE_CONFIRM:
	    if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_CONFIRM) {
		RDEBUG2("pwd exchange is incorrect: not commit!");
		return 0;
	    }
	    if (compute_peer_confirm(pwd_session, peer_confirm, inst->bnctx)) {
		RDEBUG2("pwd exchange cannot compute peer's confirm");
		return 0;
	    }
	    if (memcmp(peer_confirm, buf, SHA256_DIGEST_LENGTH)) {
		RDEBUG2("pwd exchange fails: peer confirm is incorrect!");
		return 0;
	    }
	    if (compute_keys(pwd_session, peer_confirm, msk, emsk)) {
		RDEBUG2("pwd exchange cannot generate (E)MSK!");
		return 0;
	    }
	    eap_ds->request->code = PW_EAP_SUCCESS;
	    /*
	     * return the MSK (in halves)
	     */
	    eap_add_reply(handler->request,
			  "MS-MPPE-Recv-Key", msk, MPPE_KEY_LEN);
	    eap_add_reply(handler->request,
			  "MS-MPPE-Send-Key", msk+MPPE_KEY_LEN, MPPE_KEY_LEN);
	    ret = 1;
	    break;
	default:
	    RDEBUG2("unknown PWD state");
	    return 0;
    }

    /*
     * we processed the buffered fragments, get rid of them
     */
    if (pwd_session->in_buf) {
	    talloc_free(pwd_session->in_buf);
	    pwd_session->in_buf = NULL;
    }

    return ret;
}
Пример #5
0
static int mod_process(void *arg, eap_handler_t *handler)
{
	pwd_session_t *session;
	pwd_hdr *hdr;
	pwd_id_packet_t *packet;
	eap_packet_t *response;
	REQUEST *request, *fake;
	VALUE_PAIR *pw, *vp;
	EAP_DS *eap_ds;
	size_t in_len;
	int ret = 0;
	eap_pwd_t *inst = (eap_pwd_t *)arg;
	uint16_t offset;
	uint8_t exch, *in, *ptr, msk[MSK_EMSK_LEN], emsk[MSK_EMSK_LEN];
	uint8_t peer_confirm[SHA256_DIGEST_LENGTH];

	if (((eap_ds = handler->eap_ds) == NULL) || !inst) return 0;

	session = (pwd_session_t *)handler->opaque;
	request = handler->request;
	response = handler->eap_ds->response;
	hdr = (pwd_hdr *)response->type.data;

	/*
	 *	The header must be at least one byte.
	 */
	if (!hdr || (response->type.length < sizeof(pwd_hdr))) {
		RDEBUG("Packet with insufficient data");
		return 0;
	}

	in = hdr->data;
	in_len = response->type.length - sizeof(pwd_hdr);

	/*
	* see if we're fragmenting, if so continue until we're done
	*/
	if (session->out_pos) {
		if (in_len) RDEBUG2("pwd got something more than an ACK for a fragment");

		return send_pwd_request(session, eap_ds);
	}

	/*
	* the first fragment will have a total length, make a
	* buffer to hold all the fragments
	*/
	if (EAP_PWD_GET_LENGTH_BIT(hdr)) {
		if (session->in) {
			RDEBUG2("pwd already alloced buffer for fragments");
			return 0;
		}

		if (in_len < 2) {
			RDEBUG("Invalid packet: length bit set, but no length field");
			return 0;
		}

		session->in_len = ntohs(in[0] * 256 | in[1]);
		if ((session->in = talloc_zero_array(session, uint8_t, session->in_len)) == NULL) {
			RDEBUG2("pwd cannot allocate %zd buffer to hold fragments",
				session->in_len);
			return 0;
		}
		memset(session->in, 0, session->in_len);
		session->in_pos = 0;
		in += sizeof(uint16_t);
		in_len -= sizeof(uint16_t);
	}

	/*
	 * all fragments, including the 1st will have the M(ore) bit set,
	 * buffer those fragments!
	 */
	if (EAP_PWD_GET_MORE_BIT(hdr)) {
		rad_assert(session->in != NULL);

		if ((session->in_pos + in_len) > session->in_len) {
			RDEBUG2("Fragment overflows packet.");
			return 0;
		}

		memcpy(session->in + session->in_pos, in, in_len);
		session->in_pos += in_len;

		/*
		 * send back an ACK for this fragment
		 */
		exch = EAP_PWD_GET_EXCHANGE(hdr);
		eap_ds->request->code = PW_EAP_REQUEST;
		eap_ds->request->type.num = PW_EAP_PWD;
		eap_ds->request->type.length = sizeof(pwd_hdr);
		if ((eap_ds->request->type.data = talloc_array(eap_ds->request, uint8_t, sizeof(pwd_hdr))) == NULL) {
			return 0;
		}
		hdr = (pwd_hdr *)eap_ds->request->type.data;
		EAP_PWD_SET_EXCHANGE(hdr, exch);
		return 1;
	}


	if (session->in) {
		/*
		 * the last fragment...
		 */
		if ((session->in_pos + in_len) > session->in_len) {
			RDEBUG2("pwd will not overflow a fragment buffer. Nope, not prudent");
			return 0;
		}
		memcpy(session->in + session->in_pos, in, in_len);
		in = session->in;
		in_len = session->in_len;
	}

	switch (session->state) {
	case PWD_STATE_ID_REQ:
	{
		BIGNUM	*x = NULL, *y = NULL;

		if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_ID) {
			RDEBUG2("pwd exchange is incorrect: not ID");
			return 0;
		}

		packet = (pwd_id_packet_t *) in;
		if (in_len < sizeof(*packet)) {
			RDEBUG("Packet is too small (%zd < %zd).", in_len, sizeof(*packet));
			return 0;
		}

		if ((packet->prf != EAP_PWD_DEF_PRF) ||
		    (packet->random_function != EAP_PWD_DEF_RAND_FUN) ||
		    (packet->prep != EAP_PWD_PREP_NONE) ||
		    (CRYPTO_memcmp(packet->token, &session->token, 4)) ||
		    (packet->group_num != ntohs(session->group_num))) {
			RDEBUG2("pwd id response is invalid");
			return 0;
		}
		/*
		 * we've agreed on the ciphersuite, record it...
		 */
		ptr = (uint8_t *)&session->ciphersuite;
		memcpy(ptr, (char *)&packet->group_num, sizeof(uint16_t));
		ptr += sizeof(uint16_t);
		*ptr = EAP_PWD_DEF_RAND_FUN;
		ptr += sizeof(uint8_t);
		*ptr = EAP_PWD_DEF_PRF;

		session->peer_id_len = in_len - sizeof(pwd_id_packet_t);
		if (session->peer_id_len >= sizeof(session->peer_id)) {
			RDEBUG2("pwd id response is malformed");
			return 0;
		}

		memcpy(session->peer_id, packet->identity, session->peer_id_len);
		session->peer_id[session->peer_id_len] = '\0';

		/*
		 * make fake request to get the password for the usable ID
		 */
		if ((fake = request_alloc_fake(handler->request)) == NULL) {
			RDEBUG("pwd unable to create fake request!");
			return 0;
		}
		fake->username = fr_pair_afrom_num(fake->packet, PW_USER_NAME, 0);
		if (!fake->username) {
			RDEBUG("Failed creating pair for peer id");
			talloc_free(fake);
			return 0;
		}
		fr_pair_value_bstrncpy(fake->username, session->peer_id, session->peer_id_len);
		fr_pair_add(&fake->packet->vps, fake->username);

		if ((vp = fr_pair_find_by_num(request->config, PW_VIRTUAL_SERVER, 0, TAG_ANY)) != NULL) {
			fake->server = vp->vp_strvalue;
		} else if (inst->virtual_server) {
			fake->server = inst->virtual_server;
		} /* else fake->server == request->server */

		RDEBUG("Sending tunneled request");
		rdebug_pair_list(L_DBG_LVL_1, request, fake->packet->vps, NULL);

		if (fake->server) {
			RDEBUG("server %s {", fake->server);
		} else {
			RDEBUG("server {");
		}

		/*
		 *	Call authorization recursively, which will
		 *	get the password.
		 */
		RINDENT();
		process_authorize(0, fake);
		REXDENT();

		/*
		 *	Note that we don't do *anything* with the reply
		 *	attributes.
		 */
		if (fake->server) {
			RDEBUG("} # server %s", fake->server);
		} else {
			RDEBUG("}");
		}

		RDEBUG("Got tunneled reply code %d", fake->reply->code);
		rdebug_pair_list(L_DBG_LVL_1, request, fake->reply->vps, NULL);

		if ((pw = fr_pair_find_by_num(fake->config, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) == NULL) {
			DEBUG2("failed to find password for %s to do pwd authentication",
			session->peer_id);
			talloc_free(fake);
			return 0;
		}

		if (compute_password_element(session, session->group_num,
			     		     pw->data.strvalue, strlen(pw->data.strvalue),
					     inst->server_id, strlen(inst->server_id),
					     session->peer_id, strlen(session->peer_id),
					     &session->token)) {
			DEBUG2("failed to obtain password element");
			talloc_free(fake);
			return 0;
		}
		TALLOC_FREE(fake);

		/*
		 * compute our scalar and element
		 */
		if (compute_scalar_element(session, inst->bnctx)) {
			DEBUG2("failed to compute server's scalar and element");
			return 0;
		}

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

		/*
		 * element is a point, get both coordinates: x and y
		 */
		if (!EC_POINT_get_affine_coordinates_GFp(session->group, session->my_element, x, y,
							 inst->bnctx)) {
			DEBUG2("server point assignment failed");
			BN_clear_free(x);
			BN_clear_free(y);
			return 0;
		}

		/*
		 * construct request
		 */
		session->out_len = BN_num_bytes(session->order) + (2 * BN_num_bytes(session->prime));
		if ((session->out = talloc_array(session, uint8_t, session->out_len)) == NULL) {
			return 0;
		}
		memset(session->out, 0, session->out_len);

		ptr = session->out;
		offset = BN_num_bytes(session->prime) - BN_num_bytes(x);
		BN_bn2bin(x, ptr + offset);
		BN_clear_free(x);

		ptr += BN_num_bytes(session->prime);
		offset = BN_num_bytes(session->prime) - BN_num_bytes(y);
		BN_bn2bin(y, ptr + offset);
		BN_clear_free(y);

		ptr += BN_num_bytes(session->prime);
		offset = BN_num_bytes(session->order) - BN_num_bytes(session->my_scalar);
		BN_bn2bin(session->my_scalar, ptr + offset);

		session->state = PWD_STATE_COMMIT;
		ret = send_pwd_request(session, eap_ds);
	}
		break;

		case PWD_STATE_COMMIT:
		if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_COMMIT) {
			RDEBUG2("pwd exchange is incorrect: not commit!");
			return 0;
		}

		/*
		 * process the peer's commit and generate the shared key, k
		 */
		if (process_peer_commit(session, in, in_len, inst->bnctx)) {
			RDEBUG2("failed to process peer's commit");
			return 0;
		}

		/*
		 * compute our confirm blob
		 */
		if (compute_server_confirm(session, session->my_confirm, inst->bnctx)) {
			ERROR("rlm_eap_pwd: failed to compute confirm!");
			return 0;
		}

		/*
		 * construct a response...which is just our confirm blob
		 */
		session->out_len = SHA256_DIGEST_LENGTH;
		if ((session->out = talloc_array(session, uint8_t, session->out_len)) == NULL) {
			return 0;
		}

		memset(session->out, 0, session->out_len);
		memcpy(session->out, session->my_confirm, SHA256_DIGEST_LENGTH);

		session->state = PWD_STATE_CONFIRM;
		ret = send_pwd_request(session, eap_ds);
		break;

	case PWD_STATE_CONFIRM:
		if (in_len < SHA256_DIGEST_LENGTH) {
			RDEBUG("Peer confirm is too short (%zd < %d)",
			       in_len, SHA256_DIGEST_LENGTH);
			return 0;
		}

		if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_CONFIRM) {
			RDEBUG2("pwd exchange is incorrect: not commit!");
			return 0;
		}
		if (compute_peer_confirm(session, peer_confirm, inst->bnctx)) {
			RDEBUG2("pwd exchange cannot compute peer's confirm");
			return 0;
		}
		if (CRYPTO_memcmp(peer_confirm, in, SHA256_DIGEST_LENGTH)) {
			RDEBUG2("pwd exchange fails: peer confirm is incorrect!");
			return 0;
		}
		if (compute_keys(session, peer_confirm, msk, emsk)) {
			RDEBUG2("pwd exchange cannot generate (E)MSK!");
			return 0;
		}
		eap_ds->request->code = PW_EAP_SUCCESS;
		/*
		 * return the MSK (in halves)
		 */
		eap_add_reply(handler->request, "MS-MPPE-Recv-Key", msk, MPPE_KEY_LEN);
		eap_add_reply(handler->request, "MS-MPPE-Send-Key", msk + MPPE_KEY_LEN, MPPE_KEY_LEN);

		ret = 1;
		break;

	default:
		RDEBUG2("unknown PWD state");
		return 0;
	}

	/*
	 * we processed the buffered fragments, get rid of them
	 */
	if (session->in) {
		talloc_free(session->in);
		session->in = NULL;
	}

	return ret;
}
Пример #6
0
int main(int argc, char **argv) {
    mpz_t x;            /* witness */
    unsigned int e;     /* random boolean vector (challenge) */
    mpz_t y;            /* response */
    int proof;
    int sockfd;         /* socket file descriptor */
    int index;
    int j;

    char buf[MAXDATASIZE];

    printf("Feige-Fiat-Shamir ZKP implementation\n");

    if (argc != 2) {
        fprintf(stderr, "ZKP Server Usage: %s hostname\n", argv[0]);
        exit(1);
    } else {
        fastseed = TRUE;
        // printf("Warning: fastseed enabled, using a bad random seed value!\n");
    }

    printf("\n");

    mpz_init(rndseed);

    mpz_init(n);
    mpz_set_str(n, N, 10);

    /* Connect to server, T times */
    for (j=0; j < T; j++) {
        printf("Iteration %d: ", j);
        timestamp(stdout);
        printf("\n");

        mpz_init(x);
        mpz_init(y);
        e     = 0;
        proof = 0;
        index = 0;

        // gmp_printf("n = %Zd\n", n);
        // printf("Computing keys.\n");
        compute_keys();                /* Prover chooses public/private keys    */

        sockfd = zkp_connect(argv[1]);

        if (sockfd == 2) {
            return(0);
        }

        /* Prover sends public key, i[K] */
        itoa(K, buf, 10);
        zkp_send(buf, sockfd); // 5 = K
        printf("Sent 1.\n");

        for (index = 0; index < K; index++) {
            // gmp_printf("Sending: %i %Zd\n", index, i[index]);
            mpz_get_str(buf, 10, i[index]);
            zkp_send(buf, sockfd);
            sleep(1);
        }

        /* Prover sends the witness */
        witness(x);
        mpz_get_str(buf, 10, x);
        zkp_send(buf, sockfd);
        /* end, Prover sends the witness */

        /* Verifier/server sends the challenge, we receive */
        zkp_recv(sockfd, buf);
        e = atoi(buf);
        printf("Client: got e: %i\n", e);
        /* End server sends the challenge */

        /* Send the response to the server */
        response(y, e);                /* Prover sends the response             */
        mpz_get_str(buf, 10, y);
        zkp_send(buf, sockfd);

        /* Verifier/server sends the authentication response */
        if (!zkp_recv(sockfd, buf)) {
            printf("Client ZKP: Error receiving client data.\n");
            return(0);
        }
        proof = atoi(buf);

        zkp_disconnect(sockfd);

        if (proof) {
            printf("Authentication successful!\n");
        } else {
            printf("Authentication failed!\n");
        }

        mpz_clear(x);
        mpz_clear(y);

        printf("Iteration %d finished at: ", j);
        timestamp(stdout);
        printf("\n\n");

    }

    mpz_clear(n);
    mpz_clear(rndseed);
    return (1);
}
Пример #7
0
void octree::sort_bodies(tree_structure &tree, my_dev::dev_mem<float4>  &bodies_pos, 
                         my_dev::dev_mem<uint>  &sortPermutation, int n_bodies) {

  //We assume the bodies are already onthe GPU
  devContext.startTiming();
  
  this->allocateParticleSpecificBuffers(n_bodies);

  
  //Call the GPUSort function, since we made it general 
  //into a uint4 so we can extend the tree to 96bit key
  //we have to convert to 64bit key to a 96bit for sorting
  //and back from 96 to 64    
  my_dev::dev_mem<uint4>  srcValues(devContext);
  my_dev::dev_mem<uint4>  output(devContext);
  my_dev::dev_mem<uint4>  bodies_key(devContext);
  
  
  //Allocate memory for the generalBuffer
  
  //The generalBuffer1 has size uint*4*N*3
  //this buffer gets part: 0-uint*4*N
  srcValues.cmalloc_copy(tree.generalBuffer1.get_pinned(), 
                         tree.generalBuffer1.get_flags(), 
                         tree.generalBuffer1.get_devMem(),
                         &tree.generalBuffer1[0], 0,  
                         n_bodies, getAllignmentOffset(0));  
 
  //this buffer gets part: uint*4*N-uint*4*N*2
  output.cmalloc_copy(tree.generalBuffer1.get_pinned(), 
		      tree.generalBuffer1.get_flags(), 
		      tree.generalBuffer1.get_devMem(),
		      &tree.generalBuffer1[4*n_bodies], 4*n_bodies,
		      n_bodies, getAllignmentOffset(4*n_bodies));
  
  int prevOffset = getAllignmentOffset(4*n_bodies);
  
  bodies_key.cmalloc_copy(tree.generalBuffer1.get_pinned(), 
			  tree.generalBuffer1.get_flags(), 
			  tree.generalBuffer1.get_devMem(),
			  &tree.generalBuffer1[8*n_bodies], 8*n_bodies,
			  n_bodies, prevOffset + getAllignmentOffset(8*n_bodies + prevOffset));
  
  
  //This function computes the keys, seperate since we compute keys also before 
  //buidling the tree-structure
  //Corner and size are not stored, since we can use sorting without building a tree
  float4 corner;
  float domain_fac;
  compute_keys(bodies_pos, bodies_key, n_bodies, corner, domain_fac);
  
  
  
  
   //Extract the keys
  convertKey64to96.set_arg<cl_mem>(0,   bodies_key.p());
  convertKey64to96.set_arg<cl_mem>(1,   srcValues.p());
  convertKey64to96.set_arg<int>(2,      &n_bodies);  
  convertKey64to96.setWork(n_bodies, 256);
  convertKey64to96.execute();
  
 
  //Sort the keys  
  
  // If srcValues (2nd argument) and buffer (4th argument) are different, then the original values
  // are preserved, if they are the same srcValues will be overwritten  
  gpuSort(devContext, srcValues, output, srcValues, n_bodies, 32, 3, tree);
 

  //Extract the keys and get the permuation required to sort the other
  //properties of the particles
  //Extract the sorted keys
  extractKeyAndPerm.set_arg<cl_mem>(0,   output.p());
  extractKeyAndPerm.set_arg<cl_mem>(1,   bodies_key.p());
  extractKeyAndPerm.set_arg<cl_mem>(2,   sortPermutation.p());  
  extractKeyAndPerm.set_arg<int>(3,      &n_bodies);
  extractKeyAndPerm.setWork(n_bodies, 256);
  extractKeyAndPerm.execute();  
  
  devContext.stopTiming("Sorting", 0);  
}
Пример #8
0
static struct wpabuf *
eap_pwd_perform_confirm_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)
{
	struct wpabuf *resp = NULL;
	BIGNUM *x = NULL, *y = NULL;
	HMAC_CTX ctx;
	u32 cs;
	u16 grp;
	u8 conf[SHA256_DIGEST_LENGTH], *cruft = NULL, *ptr;

	/*
	 * first build up the ciphersuite which is group | random_function |
	 *	prf
	 */
	grp = htons(data->group_num);
	ptr = (u8 *) &cs;
	os_memcpy(ptr, &grp, sizeof(u16));
	ptr += sizeof(u16);
	*ptr = EAP_PWD_DEFAULT_RAND_FUNC;
	ptr += sizeof(u8);
	*ptr = EAP_PWD_DEFAULT_PRF;

	/* each component of the cruft will be at most as big as the prime */
	if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) ||
	    ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) {
		wpa_printf(MSG_INFO, "EAP-PWD (server): debug allocation "
			   "fail");
		goto fin;
	}

	/*
	 * server's commit is H(k | server_element | server_scalar |
	 *			peer_element | peer_scalar | ciphersuite)
	 */
	H_Init(&ctx);

	/*
	 * zero the memory each time because this is mod prime math and some
	 * value may start with a few zeros and the previous one did not.
	 */
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	BN_bn2bin(data->k, cruft);
	H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime));

	/* server element: x, y */
	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
						 data->server_element, x, y,
						 data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
			   "assignment fail");
		goto fin;
	}
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	BN_bn2bin(x, cruft);
	H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime));
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	BN_bn2bin(y, cruft);
	H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime));

	/* server scalar */
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	BN_bn2bin(data->server_scalar, cruft);
	H_Update(&ctx, cruft, BN_num_bytes(data->grp->order));

	/* my element: x, y */
	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
						 data->my_element, x, y,
						 data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
			   "assignment fail");
		goto fin;
	}

	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	BN_bn2bin(x, cruft);
	H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime));
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	BN_bn2bin(y, cruft);
	H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime));

	/* my scalar */
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	BN_bn2bin(data->my_scalar, cruft);
	H_Update(&ctx, cruft, BN_num_bytes(data->grp->order));

	/* the ciphersuite */
	H_Update(&ctx, (u8 *) &cs, sizeof(u32));

	/* random function fin */
	H_Final(&ctx, conf);

	ptr = (u8 *) payload;
	if (os_memcmp(conf, ptr, SHA256_DIGEST_LENGTH)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm did not verify");
		goto fin;
	}

	wpa_printf(MSG_DEBUG, "EAP-pwd (peer): confirm verified");

	/*
	 * compute confirm:
	 *  H(k | peer_element | peer_scalar | server_element | server_scalar |
	 *    ciphersuite)
	 */
	H_Init(&ctx);

	/* k */
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	BN_bn2bin(data->k, cruft);
	H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime));

	/* my element */
	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
						 data->my_element, x, y,
						 data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm point "
			   "assignment fail");
		goto fin;
	}
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	BN_bn2bin(x, cruft);
	H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime));
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	BN_bn2bin(y, cruft);
	H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime));

	/* my scalar */
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	BN_bn2bin(data->my_scalar, cruft);
	H_Update(&ctx, cruft, BN_num_bytes(data->grp->order));

	/* server element: x, y */
	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
						 data->server_element, x, y,
						 data->bnctx)) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm point "
			   "assignment fail");
		goto fin;
	}
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	BN_bn2bin(x, cruft);
	H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime));
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	BN_bn2bin(y, cruft);
	H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime));

	/* server scalar */
	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
	BN_bn2bin(data->server_scalar, cruft);
	H_Update(&ctx, cruft, BN_num_bytes(data->grp->order));

	/* the ciphersuite */
	H_Update(&ctx, (u8 *) &cs, sizeof(u32));

	/* all done */
	H_Final(&ctx, conf);

	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD,
			     sizeof(struct eap_pwd_hdr) + SHA256_DIGEST_LENGTH,
			     EAP_CODE_RESPONSE, eap_get_id(reqData));
	if (resp == NULL)
		goto fin;

	wpabuf_put_u8(resp, EAP_PWD_OPCODE_CONFIRM_EXCH);
	wpabuf_put_data(resp, conf, SHA256_DIGEST_LENGTH);

	if (compute_keys(data->grp, data->bnctx, data->k,
			 data->my_scalar, data->server_scalar, conf, ptr,
			 &cs, data->msk, data->emsk) < 0) {
		wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to compute MSK | "
			   "EMSK");
		goto fin;
	}

fin:
	os_free(cruft);
	BN_free(x);
	BN_free(y);
	ret->methodState = METHOD_DONE;
	if (resp == NULL) {
		ret->decision = DECISION_FAIL;
		eap_pwd_state(data, FAILURE);
	} else {
		ret->decision = DECISION_UNCOND_SUCC;
		eap_pwd_state(data, SUCCESS);
	}

	return resp;
}
Пример #9
0
int main(int argc, char **argv) {
    unsigned char reg;

    unsigned int num;
    int i;
    unsigned int mode;

    unsigned long long source_ksv = 0LL;
    unsigned long long sink_ksv = 0LL;
    unsigned long long ksv_temp = 0LL;
    unsigned long long Km = 0LL;
    unsigned long long Kmp = 0LL;
    
    unsigned long long old_Km = 0LL;
    
    unsigned long long source_pkey[40];
    unsigned long long sink_pkey[40];

    unsigned char compctl;
    unsigned char snoopctl;

    FILE *km_file;

    if(argc != 1) {
        fprintf(stderr, "Usage: %s\n", argv[0]);
        return 1;
    }

    // km sense changed to be a "semaphore" bit, use it here accordingly.

    /////////////
    // this region should be atomic
    compctl = read_byte(0x3);
    printf( "Checking semaphore...\n" );
    if( (compctl & 0x80) ) {
      // semaphore is set
      printf( "Semaphore set, someone else is running: exiting.\n" );
      return 1;
    }
    // however, atomicity can be broken here: on the other hand, structurally,
    // we guarantee nobody can steal the lock here by never triggering the HPD
    // event between the read and the modify-write

    // if we have atomicity problems, the solution is to implement the RMW operation
    // in the FPGA (i.e., a command that can read and grab the semaphore in one operation)
    compctl |= 0x80; // set the semaphore
    write_byte( 0x3, compctl );
    printf( "Grabbed semaphore!\n" );
    // this region should be atomic
    //////////////
    fflush(stdout);
    
    for( i = 6; i >= 0; i-- ) {
      old_Km <<= 8;
      old_Km |= read_byte( i + 0x19 ) & 0xff;
    }

    for( i = 0; i < 5; i++ ) {
      sink_ksv <<= 8;
      sink_ksv |= (snoop_hdcp_byte(4 - i) & 0xff);
    }

    for( i = 0; i < 5; i++ ) {
      source_ksv <<= 8;
      source_ksv |= (snoop_hdcp_byte(4 - i + 0x10) & 0xff);
    }

    printf( "source public ksv: %010llx\n", source_ksv );
    printf( "sink public ksv: %010llx\n", sink_ksv );
    compute_keys( source_ksv, SOURCE, source_pkey );
    compute_keys( sink_ksv, SINK, sink_pkey );


    ksv_temp = source_ksv; // source Ksv
    num = 0;
    for( i = 0; i < 40; i++ ) {
      if( ksv_temp & 1LL ) {
	num++;
	Km += sink_pkey[i]; // used to select sink's keys
	Km %=  72057594037927936LL;
	//	printf( "Km %014llx\n", Km );
      }
      ksv_temp >>= 1LL;
    }
    //    printf( "num 1's: %d\n", num );
    // km is the sink km

    ksv_temp = sink_ksv; // sink Ksv
    num = 0;
    for( i = 0; i < 40; i++ ) {
      if( ksv_temp & 1LL ) {
	num++;
	Kmp += source_pkey[i]; // used to select source's keys
	Kmp %=  72057594037927936LL;
	//	printf( "Kmp %014llx\n", Kmp );
      }
      ksv_temp >>= 1LL;
    }
    //    printf( "num 1's: %d\n", num );
    // Kmp is the source Km
  
    Km &= 0xFFFFFFFFFFFFFFLL;
    Kmp &= 0xFFFFFFFFFFFFFFLL;
  
    printf( "\n" );
    printf( "Km : %014llx\n", Km );
    printf( "Km': %014llx\n", Kmp );

    fflush(stdout);

    if( Km != Kmp ) {
      printf( "Km is not equal to Km', can't encrypt this stream.\n" );
      printf( "Releasing semaphore.\n" );
      compctl = read_byte(0x3); // refresh compctl in case other bits changed

      compctl &= 0x7F; // release semaphore
      write_byte( 0x3, compctl );
      exit(0);
    }

    if( Km == old_Km ) {
      printf( "Km is same as cached value, doing nothing.\n" );
      printf( "Releasing semaphore.\n" );
      compctl = read_byte(0x3); // refresh compctl in case other bits changed

      compctl &= 0x7F; // release semaphore
      write_byte( 0x3, compctl );
      
      // don't need to do anything, Km is correct
      return 0;
    } else if( Km == 0 ) {
      printf( "Km is zero. This probably means derive_km was fired spuriously on disconnect.\n" );
      printf( "Aborting without doing anything, since Km = 0 is never a correct condition\n" );
      printf( "Releasing semaphore.\n" );
      compctl = read_byte(0x3); // refresh compctl in case other bits changed

      compctl &= 0x7F; // release semaphore
      write_byte( 0x3, compctl );
      
      return 0;
    } else {
      
      km_file = fopen( "/psp/km_cache", "wb" );
      if( km_file == NULL ) {
	printf( "can't open km_file to write cache...but letting life go on.\n" );
      } else {
	// write out the Km to the cache file

	// this is a totally-device and compiler-dependent way to do this
	// but it's fast and easy and it's just cache data so who cares
	fwrite(&Km, sizeof(unsigned long long), 1, km_file);
	fflush(km_file);
	fclose(km_file);
      }
      
      // now commit Km to the fpga
      for( i = 0; i < 7; i++ ) {
	write_byte( i + 0x19, Km & 0xFF );
	Km >>= 8;
      }
      
      // invoke HPD to re-load the stream
      snoopctl = read_byte(0x0);
      snoopctl |= 0x08;  // force HPD, leave all other bits intact
      write_byte( 0x0, snoopctl ); // hpd is now forcing

      printf( "Km has changed since last value, initiating HPD reset of stream and updating cache. This will take 3 seconds.");
      fflush(stdout);
      // wait
      sleep(2);
      printf( "." );
      fflush(stdout);
      snoopctl &= 0xF7;
      write_byte( 0x0, snoopctl ); // hpd is now releasing

      // wait
      for( i = 0; i < 2; i ++ ) {
	printf( "." );
	fflush(stdout);
	sleep(1); // this is the dead-zone where we try to keep the semaphore locked down
	// to prevent a recursive derive_km/HPD loop nightmare
	// if someone is just jamming cables in and out really fast, it could cause
	// problems
      }
      
      printf( "\nDone. Releasing semaphore.\n" );
      // then release semaphore
      compctl = read_byte(0x3); // refresh compctl in case other bits changed

      compctl &= 0x7F; // release semaphore
      write_byte( 0x3, compctl );
    }

    return 0;
}