История изменений
Исправление ncrmnt, (текущая версия) :
Это что-то новое. Последняя реализация, которую я имплементил выглядела как-то так:
#include <arch/antares.h>
#include <avr/eeprom.h>
#include <string.h>
#include <util/crc16.h>
#include <skeleton.h>
#include "aes.h"
/* 8hz timer is recommended */
uint16_t g_timestamp_low;
uint8_t g_timestamp_high;
static uint8_t otps_generated;
#define YUBIKEY_MODHEX_MAP "cbdefghijklnrtuv"
const char trans[] = YUBIKEY_MODHEX_MAP;
void yubikey_modhex_encode (char *dst, const char *src, size_t srcSize)
{
while (srcSize--)
{
*dst++ = trans[(*src >> 4) & 0xf];
*dst++ = trans[*src++ & 0xf];
}
*dst = '\0';
}
inline uint16_t yubi_crc16_update(uint16_t crc, uint8_t a)
{
int i;
crc ^= a;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0x8408;
else
crc = (crc >> 1);
}
return crc;
}
void skeleton_send_yubi_token(struct key_yubikey *conf)
{
int len, i;
char buf[64];
struct yubikey_secret_token tok;
char *ptr;
uint16_t crc = 0x5af0;
aes128_ctx_t ctx;
len = min_t(int, 2 * YUBIKEY_ID_LEN, strlen(conf->pub_string));
memcpy(buf, conf->pub_string, len);
memcpy(tok.secret, conf->secret, YUBIKEY_ID_LEN);
cli();
tok.timestamp_high = g_timestamp_high;
tok.timestamp_low = g_timestamp_low;
sei();
tok.insert_count = g_eeprom_conf.insertcount;
tok.otps = otps_generated++;
tok.random = rand(); //Fair dice roll
ptr = (char *) &tok;
for (i=0; i < sizeof(struct yubikey_secret_token) - sizeof(uint16_t); i++) {
crc = yubi_crc16_update(crc, ptr[i]);
}
tok.crc = crc;
aes128_init(conf->aes_key, &ctx);
aes128_enc(&tok, &ctx);
yubikey_modhex_encode(&buf[len], &tok, sizeof(tok));
skeleton_type_message(buf);
}
void update_rgb();
ISR(TIMER1_OVF_vect)
{
if (++g_timestamp_low == 0) {
g_timestamp_high++;
}
//update_rgb();
}
ANTARES_INIT_LOW(timer_init)
{
TCCR1A = 0;
TCCR1B = 0;
ICR1 = 1470; /* ~8Hz at 12Mhz clock */
TCCR1A = (1<<WGM11);
TCCR1B = (1 << WGM13) | (1<<WGM12) | 0x5; // /1024
#ifdef TIMSK
TIMSK = 1<<TOIE1;
#else
TIMSK1 = 1<<TOIE1;
#endif
}
По сути берем секретную строку, количество втыканий, значение таймера, шифруем AES одним блоком, потом транслируем в modhex и печатаем имитируя клавиатуру.
Кому надо, вот моя старая реализация этих токенов: https://git.ncrmnt.org/firmwares/SkeletonKey/
Исправление ncrmnt, :
Это что-то новое. Последняя реализация, которую я имплементил выглядела как-то так:
#include <arch/antares.h>
#include <avr/eeprom.h>
#include <string.h>
#include <util/crc16.h>
#include <skeleton.h>
#include "aes.h"
/* 8hz timer is recommended */
uint16_t g_timestamp_low;
uint8_t g_timestamp_high;
static uint8_t otps_generated;
#define YUBIKEY_MODHEX_MAP "cbdefghijklnrtuv"
const char trans[] = YUBIKEY_MODHEX_MAP;
void yubikey_modhex_encode (char *dst, const char *src, size_t srcSize)
{
while (srcSize--)
{
*dst++ = trans[(*src >> 4) & 0xf];
*dst++ = trans[*src++ & 0xf];
}
*dst = '\0';
}
inline uint16_t yubi_crc16_update(uint16_t crc, uint8_t a)
{
int i;
crc ^= a;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0x8408;
else
crc = (crc >> 1);
}
return crc;
}
void skeleton_send_yubi_token(struct key_yubikey *conf)
{
int len, i;
char buf[64];
struct yubikey_secret_token tok;
char *ptr;
uint16_t crc = 0x5af0;
aes128_ctx_t ctx;
len = min_t(int, 2 * YUBIKEY_ID_LEN, strlen(conf->pub_string));
memcpy(buf, conf->pub_string, len);
memcpy(tok.secret, conf->secret, YUBIKEY_ID_LEN);
cli();
tok.timestamp_high = g_timestamp_high;
tok.timestamp_low = g_timestamp_low;
sei();
tok.insert_count = g_eeprom_conf.insertcount;
tok.otps = otps_generated++;
tok.random = rand(); //Fair dice roll
ptr = (char *) &tok;
for (i=0; i < sizeof(struct yubikey_secret_token) - sizeof(uint16_t); i++) {
crc = yubi_crc16_update(crc, ptr[i]);
}
tok.crc = crc;
aes128_init(conf->aes_key, &ctx);
aes128_enc(&tok, &ctx);
yubikey_modhex_encode(&buf[len], &tok, sizeof(tok));
skeleton_type_message(buf);
}
void update_rgb();
ISR(TIMER1_OVF_vect)
{
if (++g_timestamp_low == 0) {
g_timestamp_high++;
}
//update_rgb();
}
ANTARES_INIT_LOW(timer_init)
{
TCCR1A = 0;
TCCR1B = 0;
ICR1 = 1470; /* ~8Hz at 12Mhz clock */
TCCR1A = (1<<WGM11);
TCCR1B = (1 << WGM13) | (1<<WGM12) | 0x5; // /1024
#ifdef TIMSK
TIMSK = 1<<TOIE1;
#else
TIMSK1 = 1<<TOIE1;
#endif
}
По сути берем секретную строку, количество втыканий, значение таймера, шифруем AES одним блоком, потом транслируем в modhex и печатаем имитируя клавиатуру.
Кому надо, вот моя старая реализация этих токенов: https://git.ncrmnt.org/firmwares/SkeletonKey/
Исходная версия ncrmnt, :
Это что-то новое. Последняя реализация, которую я имплементил выглядела как-то так:
#include <arch/antares.h>
#include <avr/eeprom.h>
#include <string.h>
#include <util/crc16.h>
#include <skeleton.h>
#include "aes.h"
/* 8hz timer is recommended */
uint16_t g_timestamp_low;
uint8_t g_timestamp_high;
static uint8_t otps_generated;
#define YUBIKEY_MODHEX_MAP "cbdefghijklnrtuv"
const char trans[] = YUBIKEY_MODHEX_MAP;
void yubikey_modhex_encode (char *dst, const char *src, size_t srcSize)
{
while (srcSize--)
{
*dst++ = trans[(*src >> 4) & 0xf];
*dst++ = trans[*src++ & 0xf];
}
*dst = '\0';
}
inline uint16_t yubi_crc16_update(uint16_t crc, uint8_t a)
{
int i;
crc ^= a;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0x8408;
else
crc = (crc >> 1);
}
return crc;
}
void skeleton_send_yubi_token(struct key_yubikey *conf)
{
int len, i;
char buf[64];
struct yubikey_secret_token tok;
char *ptr;
uint16_t crc = 0x5af0;
aes128_ctx_t ctx;
len = min_t(int, 2 * YUBIKEY_ID_LEN, strlen(conf->pub_string));
memcpy(buf, conf->pub_string, len);
memcpy(tok.secret, conf->secret, YUBIKEY_ID_LEN);
cli();
tok.timestamp_high = g_timestamp_high;
tok.timestamp_low = g_timestamp_low;
sei();
tok.insert_count = g_eeprom_conf.insertcount;
tok.otps = otps_generated++;
tok.random = rand(); //Fair dice roll
ptr = (char *) &tok;
for (i=0; i < sizeof(struct yubikey_secret_token) - sizeof(uint16_t); i++) {
crc = yubi_crc16_update(crc, ptr[i]);
}
tok.crc = crc;
aes128_init(conf->aes_key, &ctx);
aes128_enc(&tok, &ctx);
yubikey_modhex_encode(&buf[len], &tok, sizeof(tok));
skeleton_type_message(buf);
}
void update_rgb();
ISR(TIMER1_OVF_vect)
{
if (++g_timestamp_low == 0) {
g_timestamp_high++;
}
//update_rgb();
}
ANTARES_INIT_LOW(timer_init)
{
TCCR1A = 0;
TCCR1B = 0;
ICR1 = 1470; /* ~8Hz at 12Mhz clock */
TCCR1A = (1<<WGM11);
TCCR1B = (1 << WGM13) | (1<<WGM12) | 0x5; // /1024
#ifdef TIMSK
TIMSK = 1<<TOIE1;
#else
TIMSK1 = 1<<TOIE1;
#endif
}