25 #include "os_io_seproxyhal.h"
30 #define INIT_U2F_VERSION 0x02
31 #define INIT_DEVICE_VERSION_MAJOR 0
32 #define INIT_DEVICE_VERSION_MINOR 1
33 #define INIT_BUILD_VERSION 0
36 #define INIT_CAPABILITIES 0x04
38 #define INIT_CAPABILITIES 0x00
47 #define APDU_MIN_HEADER 4
48 #define LC_FIRST_BYTE_OFFSET 4
49 #define LONG_ENC_LC_SIZE 3
50 #define LONG_ENC_LE_SIZE 2
53 #define FIDO_INS_ENROLL 0x01
54 #define FIDO_INS_SIGN 0x02
55 #define U2F_HANDLE_SIGN_HEADER_SIZE (32 + 32 + 1)
56 #define FIDO_INS_GET_VERSION 0x03
58 #define FIDO_INS_PROP_GET_COUNTER 0xC0
59 #define FIDO_INS_PROP_GET_INFO 0xC1
61 #define P1_SIGN_CHECK_ONLY 0x07
62 #define P1_SIGN_SIGN 0x03
64 #define SIGN_USER_PRESENCE_MASK 0x01
66 #ifndef U2F_PROXY_MAGIC
68 static const uint8_t SW_WRONG_LENGTH[] = {0x67, 0x00};
72 static const uint8_t SW_BUSY[] = {0x90, 0x01};
73 static const uint8_t SW_PROOF_OF_PRESENCE_REQUIRED[] = {0x69, 0x85};
74 static const uint8_t SW_BAD_KEY_HANDLE[] = {0x6A, 0x80};
76 static const uint8_t SW_UNKNOWN_INSTRUCTION[] = {0x6d, 0x00};
77 static const uint8_t SW_UNKNOWN_CLASS[] = {0x6e, 0x00};
78 static const uint8_t SW_WRONG_LENGTH[] = {0x67, 0x00};
79 static const uint8_t SW_INTERNAL[] = {0x6F, 0x00};
81 static const uint8_t U2F_VERSION[] = {
'U',
'2',
'F',
'_',
'V',
'2', 0x90, 0x00};
84 static const uint8_t INFO[] = {1 ,
85 (char) (IO_APDU_BUFFER_SIZE - U2F_HANDLE_SIGN_HEADER_SIZE - 3 - 4),
111 if (G_io_app.apdu_state != APDU_IDLE) {
116 if (length < U2F_HANDLE_SIGN_HEADER_SIZE + 5 ) {
123 if (p1 == P1_SIGN_CHECK_ONLY) {
126 (
uint8_t *) SW_PROOF_OF_PRESENCE_REQUIRED,
127 sizeof(SW_PROOF_OF_PRESENCE_REQUIRED));
132 keyHandleLength = buffer[U2F_HANDLE_SIGN_HEADER_SIZE - 1];
133 if (U2F_HANDLE_SIGN_HEADER_SIZE + keyHandleLength != length) {
140 if (keyHandleLength == 5) {
145 if (memcmp(buffer + U2F_HANDLE_SIGN_HEADER_SIZE,
"\xF1\xD0\x00\x00\x00", 5) == 0) {
147 G_io_apdu_buffer[0] =
sizeof(U2F_PROXY_MAGIC) - 1;
148 memcpy(G_io_apdu_buffer + 1, U2F_PROXY_MAGIC,
sizeof(U2F_PROXY_MAGIC) - 1);
149 memcpy(G_io_apdu_buffer + 1 +
sizeof(U2F_PROXY_MAGIC) - 1,
"\x90\x00\x90\x00", 4);
153 G_io_apdu_buffer[0] + 1 + 2 + 2);
159 for (i = 0; i < keyHandleLength; i++) {
160 buffer[U2F_HANDLE_SIGN_HEADER_SIZE + i]
161 ^= U2F_PROXY_MAGIC[i % (
sizeof(U2F_PROXY_MAGIC) - 1)];
164 if (length != U2F_HANDLE_SIGN_HEADER_SIZE + 5 + buffer[U2F_HANDLE_SIGN_HEADER_SIZE + 4]) {
171 memmove(G_io_apdu_buffer, buffer + U2F_HANDLE_SIGN_HEADER_SIZE, keyHandleLength);
172 G_io_app.apdu_length = keyHandleLength;
173 G_io_app.apdu_media = IO_APDU_MEDIA_U2F;
174 G_io_app.apdu_state = APDU_U2F;
233 memcpy(channel, channelInit, 4);
235 memmove(G_io_apdu_buffer, buffer, 8);
236 memcpy(G_io_apdu_buffer + 8, channel, 4);
237 G_io_apdu_buffer[12] = INIT_U2F_VERSION;
238 G_io_apdu_buffer[13] = INIT_DEVICE_VERSION_MAJOR;
239 G_io_apdu_buffer[14] = INIT_DEVICE_VERSION_MINOR;
240 G_io_apdu_buffer[15] = INIT_BUILD_VERSION;
241 G_io_apdu_buffer[16] = INIT_CAPABILITIES;
244 memset(service->
channel, 0xff, 4);
247 memcpy(service->
channel, channel, 4);
263 if (length < APDU_MIN_HEADER) {
267 if (length == APDU_MIN_HEADER) {
272 if (length == APDU_MIN_HEADER + 1) {
283 if (length < APDU_MIN_HEADER + 3) {
289 if (length == APDU_MIN_HEADER + 3) {
290 if (buffer[4] != 0) {
304 if (buffer[LC_FIRST_BYTE_OFFSET] != 0) {
313 = (buffer[LC_FIRST_BYTE_OFFSET + 1] << 8) | (buffer[LC_FIRST_BYTE_OFFSET + 2]);
316 if ((APDU_MIN_HEADER + LONG_ENC_LC_SIZE + dataLength != length)
317 && (APDU_MIN_HEADER + LONG_ENC_LC_SIZE + dataLength + LONG_ENC_LE_SIZE != length)) {
328 #ifdef U2F_PROXY_MAGIC
336 if (dataLength < 0) {
343 #ifndef U2F_PROXY_MAGIC
346 memmove(G_io_apdu_buffer, buffer, length);
347 G_io_app.apdu_length = length;
348 G_io_app.apdu_media = IO_APDU_MEDIA_U2F;
349 G_io_app.apdu_state = APDU_U2F;
353 if (cla != FIDO_CLA) {
359 case FIDO_INS_ENROLL:
361 u2f_apdu_enroll(service, p1, p2, buffer + OFFSET_DATA, dataLength);
365 u2f_apdu_sign(service, p1, p2, buffer + OFFSET_DATA, dataLength);
367 case FIDO_INS_GET_VERSION:
369 u2f_apdu_get_version(service, p1, p2, buffer + OFFSET_DATA, dataLength);
373 case FIDO_INS_PROP_GET_INFO:
374 u2f_apdu_get_info(service, p1, p2, buffer + OFFSET_DATA, dataLength);
381 (
uint8_t *) SW_UNKNOWN_INSTRUCTION,
382 sizeof(SW_UNKNOWN_INSTRUCTION));
uint8_t * transportBuffer
uint8_t channel[U2F_CHANNEL_ID_SIZE]
int u2f_get_cmd_msg_data_length(const uint8_t *buffer, uint16_t length)
void u2f_message_set_autoreply_wait_user_presence(u2f_service_t *service, bool enabled)
void u2f_message_complete(u2f_service_t *service)
void u2f_message_reply(u2f_service_t *service, uint8_t cmd, uint8_t *buffer, uint16_t length)
void ctap2_handle_cmd_cancel(u2f_service_t *service, uint8_t *buffer, uint16_t length)
void ctap2_handle_cmd_cbor(u2f_service_t *service, uint8_t *buffer, uint16_t length)
bool u2f_is_channel_broadcast(uint8_t *channel)