void _check_success(int rc, YKP_CONFIG *cfg, unsigned char expected[], int caller_line)
{
	struct config_st *ycfg;
	bool config_matches_expected = false;

	if (rc != 1) {
		fprintf(stderr, "TEST FAILED (line %i of %s)\n", caller_line, __FILE__);
		fprintf(stderr, "Error returned : %i/%i (%s)\n", rc, ykp_errno, ykp_strerror(ykp_errno));
	}
	assert(rc == 1);

	ycfg = (struct config_st *) ykp_core_config(cfg);
	/* insert CRC */
	ycfg->crc = ~yubikey_crc16 ((unsigned char *) ycfg,
				    offsetof(struct config_st, crc));
	ycfg->crc = yk_endian_swap_16(ycfg->crc);

	config_matches_expected = ! memcmp(expected, ycfg, sizeof(*ycfg));
	if (! config_matches_expected) {
		fprintf(stderr, "TEST FAILED (line %i of %s)\n", caller_line, __FILE__);
		_yktest_hexdump ("BAD MATCH :\n", ycfg, sizeof(*ycfg), 7);
		_yktest_hexdump ("EXPECTED :\n", expected, sizeof(*ycfg), 7);
	}
	assert(config_matches_expected == true);
}
示例#2
0
int yk_get_status(YK_KEY *k, YK_STATUS *status)
{
	unsigned int status_count = 0;

	if (!yk_read_from_key(k, 0, status, sizeof(YK_STATUS), &status_count))
		return 0;

	if (status_count != sizeof(YK_STATUS)) {
		yk_errno = YK_EWRONGSIZ;
		return 0;
	}

	status->touchLevel = yk_endian_swap_16(status->touchLevel);

	return 1;
}
示例#3
0
int yk_write_command(YK_KEY *yk, YK_CONFIG *cfg, uint8_t command,
		    unsigned char *acc_code)
{
	unsigned char buf[sizeof(YK_CONFIG) + ACC_CODE_SIZE];

	/* Update checksum and insert config block in buffer if present */

	memset(buf, 0, sizeof(buf));

	if (cfg) {
		cfg->crc = ~yubikey_crc16 ((unsigned char *) cfg,
					   sizeof(YK_CONFIG) - sizeof(cfg->crc));
		cfg->crc = yk_endian_swap_16(cfg->crc);
		memcpy(buf, cfg, sizeof(YK_CONFIG));
	}

	/* Append current access code if present */

	if (acc_code)
		memcpy(buf + sizeof(YK_CONFIG), acc_code, ACC_CODE_SIZE);

	return _yk_write(yk, command, buf, sizeof(buf));

}
示例#4
0
/*
 * Send something to the YubiKey. The command, as well as the slot, is
 * given in the 'slot' parameter (e.g. SLOT_CHAL_HMAC2 to send a HMAC-SHA1
 * challenge to slot 2).
 */
int yk_write_to_key(YK_KEY *yk, uint8_t slot, const void *buf, int bufcount)
{
	YK_FRAME frame;
	unsigned char repbuf[FEATURE_RPT_SIZE];
	int i, seq;
	unsigned char *ptr, *end;

	if (bufcount > sizeof(frame.payload)) {
		yk_errno = YK_EWRONGSIZ;
		return 0;
	}

	/* Insert data and set slot # */

	memset(&frame, 0, sizeof(frame));
	memcpy(frame.payload, buf, bufcount);
	frame.slot = slot;

	/* Append slot checksum */

	i = yubikey_crc16 (frame.payload, sizeof(frame.payload));
	frame.crc = yk_endian_swap_16(i);

	/* Chop up the data into parts that fits into the payload of a
	   feature report. Set the sequence number | 0x80 in the end
	   of the feature report. When the Yubikey has processed it,
	   it will clear this byte, signaling that the next part can be
	   sent */

	ptr = (unsigned char *) &frame;
	end = (unsigned char *) &frame + sizeof(frame);

#ifdef YK_DEBUG
	fprintf(stderr, "YK_DEBUG: Write %i bytes to YubiKey :\n", bufcount);
#endif
	for (seq = 0; ptr < end; seq++) {
		int all_zeros = 1;
		/* Ignore parts that are all zeroes except first and last
		   to speed up the transfer */

		for (i = 0; i < (FEATURE_RPT_SIZE - 1); i++) {
			if ((repbuf[i] = *ptr++)) all_zeros = 0;
		}
		if (all_zeros && (seq > 0) && (ptr < end))
			continue;

		/* sequence number goes into lower bits of last byte */
		repbuf[i] = seq | SLOT_WRITE_FLAG;

		/* When the Yubikey clears the SLOT_WRITE_FLAG, the
		 * next part can be sent.
		 */
		if (! yk_wait_for_key_status(yk, slot, 0, WAIT_FOR_WRITE_FLAG,
					     false, SLOT_WRITE_FLAG, NULL))
			return 0;
#ifdef YK_DEBUG
		_yk_hexdump(repbuf, FEATURE_RPT_SIZE);
#endif
		if (!_ykusb_write(yk, REPORT_TYPE_FEATURE, 0,
				  (char *)repbuf, FEATURE_RPT_SIZE))
			return 0;
	}

	return 1;
}
int yk_write_config(YK_KEY *yk, YK_CONFIG *cfg, int confnum,
		    unsigned char *acc_code)
{
	unsigned char buf[sizeof(YK_CONFIG) + ACC_CODE_SIZE];
	YK_STATUS stat;
	int seq;
	uint8_t slot;

	/* Get current sequence # from status block */

	if (!yk_get_status(yk, &stat /*, 0*/))
		return 0;

	seq = stat.pgmSeq;

	/* Update checksum and insert config block in buffer if present */

	memset(buf, 0, sizeof(buf));

	if (cfg) {
		cfg->crc = ~yubikey_crc16 ((unsigned char *) cfg,
					   sizeof(YK_CONFIG) - sizeof(cfg->crc));
		cfg->crc = yk_endian_swap_16(cfg->crc);
		memcpy(buf, cfg, sizeof(YK_CONFIG));
	}

	/* Append current access code if present */

	if (acc_code)
		memcpy(buf + sizeof(YK_CONFIG), acc_code, ACC_CODE_SIZE);

	/* Write to Yubikey */

	switch(confnum) {
	case 1:
		slot = SLOT_CONFIG;
		break;
	case 2:
		slot = SLOT_CONFIG2;
		break;
	}

	if (!yk_write_to_key(yk, slot, buf, sizeof(buf)))
		return 0;

	/* When the Yubikey clears the SLOT_WRITE_FLAG, it has processed the last write.
	 * This wait can't be done in yk_write_to_key since some users of that function
	 * want to get the bytes in the status message, but when writing configuration
	 * we don't expect any data back.
	 */
	yk_wait_for_key_status(yk, slot, 0, WAIT_FOR_WRITE_FLAG, false, SLOT_WRITE_FLAG, NULL);

	/* Verify update */

	if (!yk_get_status(yk, &stat /*, 0*/))
		return 0;

	yk_errno = YK_EWRITEERR;
	if (cfg) {
		return stat.pgmSeq != seq;
	}

	return stat.pgmSeq == 0;

}