예제 #1
0
파일: u2f_hid.c 프로젝트: alitalia/u2f-zero
// writes what has been buffered and clears memory
void u2f_hid_flush()
{
	if (_hid_offset)
	{
		usb_write(_hid_pkt, HID_PACKET_SIZE);
	}
	u2f_hid_reset_packet();
}
예제 #2
0
파일: u2f_hid.c 프로젝트: ad-m/u2f-zero
void u2f_hid_check_timeouts()
{
	uint8_t i;
	for(i = 0; i < CID_MAX; i++)
	{
		if (CIDS[i].busy && ((get_ms() - CIDS[i].last_used) >= 750))
		{
			u2f_printlx("timeout cid ",2,CIDS[i].cid,get_ms());
			stamp_error(CIDS[i].cid, ERR_MSG_TIMEOUT);
			del_cid(CIDS[i].cid);
			u2f_hid_reset_packet();
		}
	}

}
예제 #3
0
파일: u2f_hid.c 프로젝트: alitalia/u2f-zero
void u2f_hid_request(struct u2f_hid_msg* req)
{
	uint8_t* payload = req->pkt.init.payload;
	static int8_t last_seq = -1;
	struct CID* cid = get_cid(req->cid);


	if (cid != NULL)
	{
		refresh_cid(cid);
	}
	else if (req->cid == U2FHID_BROADCAST)
	{

	}
	else
	{
		// Ignore CID's we did not allocate.
		//u2f_printlx("ignoring pkt ",1,req->cid);
		return;
	}

	// ignore if we locked to a different cid
	if(hid_is_locked())
	{
		if (!hid_is_lock_cid(cid))
		{
			stamp_error(hid_layer.current_cid, ERR_CHANNEL_BUSY);
			return;
		}
	}

	hid_layer.state = (u2f_hid_busy()) ? HID_BUSY : HID_READY;

	switch(hid_layer.state)
	{
		case HID_READY:
			if (req->pkt.init.cmd & TYPE_INIT)
			{
				if (U2FHID_LEN(req) > U2FHID_MAX_PAYLOAD_SIZE)
				{
					//u2f_prints("length too big\r\n");
					stamp_error(req->cid, ERR_INVALID_LEN);
					return;
				}
				u2f_hid_reset_packet();
				hid_layer.current_cid = req->cid;
				hid_layer.current_cmd = req->pkt.init.cmd;
				hid_layer.last_buffered = get_ms();
				last_seq = -1;

			}
			else
			{
				stamp_error(req->cid, ERR_INVALID_CMD);
				u2f_prints("ERR_INVALID_CMD\r\n");
				return;
			}

			break;
		case HID_BUSY:
			// buffer long requests
			if (req->cid == hid_layer.current_cid)
			{
				if (req->pkt.init.cmd & TYPE_INIT)
				{
					u2f_hid_reset_packet();
					u2f_hid_request(req);
					return;
				}

				hid_layer.last_buffered = get_ms();

				// verify packets arrive in ascending order
				if (last_seq + 1 != req->pkt.cont.seq)
				{
					u2f_hid_reset_packet();
					stamp_error(hid_layer.current_cid, ERR_INVALID_SEQ);
					return;
				}
				last_seq = req->pkt.cont.seq;

			}
			else if (U2FHID_TIMEOUT(&hid_layer))
			{
				// return timeout error for old channel and run again for new channel
				//u2f_prints("timeout, switching\r\n");
				hid_layer.state = HID_READY;
				u2f_hid_reset_packet();
				stamp_error(hid_layer.current_cid, ERR_MSG_TIMEOUT);
				u2f_hid_request(req);
				return;
			}
			else
			{
				// Current application may not be interrupted
				stamp_error(req->cid, ERR_CHANNEL_BUSY);
				return;
			}
			break;

	}

	hid_u2f_parse(req);
	return;
}
예제 #4
0
파일: u2f_hid.c 프로젝트: ad-m/u2f-zero
void u2f_hid_request(struct u2f_hid_msg* req)
{
	static int8_t last_seq;
	struct CID* cid = NULL;

	cid = get_cid(req->cid);

	// Error checking
	if ((U2FHID_IS_INIT(req->pkt.init.cmd)))
	{
		if (U2FHID_LEN(req) > 7609)
		{
			stamp_error(req->cid, ERR_INVALID_LEN);
			return;
		}
		if (req->pkt.init.cmd != U2FHID_INIT && req->cid != hid_layer.current_cid && u2f_hid_busy())
		{
			stamp_error(req->cid, ERR_CHANNEL_BUSY);
			return;
		}
	}
	else if (cid == NULL || !cid->busy)
	{
		// ignore random cont packets
		return;
	}

	if (!req->cid)
	{
		stamp_error(req->cid, ERR_SYNC_FAIL);
		return;
	}



	if (req->cid == U2FHID_BROADCAST)
	{
		if (!(req->pkt.init.cmd == U2FHID_INIT))
		{
			stamp_error(req->cid, ERR_SYNC_FAIL);
			return;
		}
		cid = &BROADCAST_CID;
		BROADCAST_CID.cid = U2FHID_BROADCAST;
	}
	else if (U2FHID_IS_INIT(req->pkt.init.cmd) && cid == NULL)
	{
		add_new_cid(req->cid);
		cid = get_cid(req->cid);
		if (cid == NULL)
		{
			return;
		}
		cid->busy = 0;
	}




	// Reset init packets
	if (req->pkt.init.cmd == U2FHID_INIT)
	{
		cid->busy = 0;
	}

	hid_layer.current_cid = req->cid;
	hid_layer.last_buffered = get_ms();

	cid->last_used = get_ms();


	// ignore if we locked to a different cid
#ifdef U2F_SUPPORT_HID_LOCK
	if(hid_is_locked() && req->pkt.init.cmd != U2FHID_INIT)
	{
		if (!hid_is_lock_cid(req->cid))
		{
			stamp_error(req->cid, ERR_CHANNEL_BUSY);
			return;
		}
	}
#endif

	if ((req->pkt.init.cmd & TYPE_INIT) && !cid->busy)
	{
		cid->last_cmd = req->pkt.init.cmd;
		hid_layer.current_cmd = req->pkt.init.cmd;
		last_seq = -1;

	}
	else
	{


		// verify packets arrive in ascending order
		hid_layer.last_buffered = get_ms();
		if (last_seq + 1 != req->pkt.cont.seq)
		{
			stamp_error(hid_layer.current_cid, ERR_INVALID_SEQ);
			u2f_hid_reset_packet();
			return;
		}
		last_seq = req->pkt.cont.seq;

		hid_layer.current_cmd = cid->last_cmd;

	}

	cid->busy = hid_u2f_parse(req);

}