-
Notifications
You must be signed in to change notification settings - Fork 95
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
405 additions
and
200 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
// Copyright 2019 Shift Cryptosecurity AG | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#include "u2f_packet.h" | ||
#include "err_codes.h" | ||
#include "queue.h" | ||
#include "screen.h" | ||
#include "usb/usb_processing.h" | ||
#include <stdbool.h> | ||
#include <stdlib.h> | ||
|
||
// We can handle up to NUM_TIMEOUT_COUNTERS missing continuation frames | ||
#define NUM_TIMEOUT_COUNTERS 3 | ||
|
||
struct frame_counter { | ||
uint32_t cid; | ||
uint8_t counter; | ||
}; | ||
|
||
// cid == 0 indicates that there isn't any active timer for that slot | ||
static volatile struct frame_counter _timeout_counters[NUM_TIMEOUT_COUNTERS]; | ||
|
||
static void _reset_timeout(uint32_t cid) | ||
{ | ||
for (int i = 0; i < NUM_TIMEOUT_COUNTERS; ++i) { | ||
if (_timeout_counters[i].cid == cid) { | ||
_timeout_counters[i].counter = 0; | ||
} | ||
} | ||
} | ||
|
||
static void _timeout_disable(uint32_t cid) | ||
{ | ||
for (int i = 0; i < NUM_TIMEOUT_COUNTERS; ++i) { | ||
if (_timeout_counters[i].cid == cid) { | ||
_timeout_counters[i].cid = 0; | ||
_timeout_counters[i].counter = 0; | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Keeps a state for the frame processing of incoming frames. | ||
*/ | ||
static State _in_state; | ||
|
||
/** | ||
* Resets the current state. | ||
*/ | ||
static void _reset_state(void) | ||
{ | ||
queue_clear(queue_u2f_queue()); | ||
_timeout_disable(_in_state.cid); | ||
memset(&_in_state, 0, sizeof(_in_state)); | ||
} | ||
|
||
static queue_error_t _queue_push(const uint8_t* data) | ||
{ | ||
return queue_push(queue_u2f_queue(), data); | ||
} | ||
|
||
/** | ||
* Responds with an error. | ||
* @param[in] err The error. | ||
* @param[in] cid The channel identifier. | ||
* No return value needed as long as _reset_state clears the queue. | ||
*/ | ||
static void _queue_err(const uint8_t err, uint32_t cid) | ||
{ | ||
usb_frame_prepare_err(err, cid, _queue_push); | ||
} | ||
|
||
static bool _need_more_data(void) | ||
{ | ||
return (_in_state.buf_ptr - _in_state.data) < (signed)_in_state.len; | ||
} | ||
|
||
void u2f_packet_timeout_enable(uint32_t cid) | ||
{ | ||
for (int i = 0; i < NUM_TIMEOUT_COUNTERS; ++i) { | ||
if (_timeout_counters[i].cid == 0) { | ||
_timeout_counters[i].cid = cid; | ||
_timeout_counters[i].counter = 0; | ||
return; | ||
} | ||
} | ||
} | ||
|
||
bool u2f_packet_timeout_get(uint32_t* cid) | ||
{ | ||
for (int i = 0; i < NUM_TIMEOUT_COUNTERS; ++i) { | ||
*cid = _timeout_counters[i].cid; | ||
if (_timeout_counters[i].cid != 0 && _timeout_counters[i].counter >= 5) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
void u2f_packet_timeout_tick(void) | ||
{ | ||
for (int i = 0; i < NUM_TIMEOUT_COUNTERS; ++i) { | ||
if (_timeout_counters[i].cid != 0) { | ||
_timeout_counters[i].counter += 1; | ||
} | ||
} | ||
} | ||
|
||
void u2f_packet_timeout(uint32_t cid) | ||
{ | ||
_timeout_disable(cid); | ||
if (cid == _in_state.cid) { | ||
_reset_state(); | ||
} | ||
usb_frame_prepare_err(FRAME_ERR_MSG_TIMEOUT, cid, _queue_push); | ||
} | ||
|
||
bool u2f_packet_process(const USB_FRAME* frame, void (*send_packet)(void)) | ||
{ | ||
struct usb_processing* ctx = usb_processing_u2f(); | ||
switch (usb_frame_process(frame, &_in_state)) { | ||
case FRAME_ERR_IGNORE: | ||
// Ignore this frame, i.e. no response. | ||
break; | ||
case FRAME_ERR_INVALID_SEQ: | ||
// Reset the state becuase this error indicates that there is a host application bug | ||
_reset_state(); | ||
_queue_err(FRAME_ERR_INVALID_SEQ, frame->cid); | ||
break; | ||
case FRAME_ERR_CHANNEL_BUSY: | ||
// We don't reset the state because this error doesn't indicate something wrong with the | ||
// "current" connection. | ||
_queue_err(FRAME_ERR_CHANNEL_BUSY, frame->cid); | ||
break; | ||
case FRAME_ERR_INVALID_LEN: | ||
// Reset the state becuase this error indicates that there is a host application bug | ||
_reset_state(); | ||
_queue_err(FRAME_ERR_INVALID_LEN, frame->cid); | ||
break; | ||
case ERR_NONE: | ||
_reset_timeout(frame->cid); | ||
if (_need_more_data()) { | ||
// Do not send a message yet | ||
return true; | ||
} | ||
if (usb_processing_enqueue(ctx, &_in_state)) { | ||
// Queue filled and will be sent during usb processing | ||
_reset_state(); | ||
return false; | ||
} | ||
// Else: Currently processing a message, reset the state and forget about this packet | ||
_timeout_disable(frame->cid); | ||
_reset_state(); | ||
_queue_err(FRAME_ERR_CHANNEL_BUSY, frame->cid); | ||
break; | ||
default: | ||
// other errors | ||
_reset_state(); | ||
_queue_err(FRAME_ERR_OTHER, frame->cid); | ||
break; | ||
} | ||
send_packet(); | ||
return false; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// Copyright 2019 Shift Cryptosecurity AG | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#ifndef _U2F_PACKET_H_ | ||
#define _U2F_PACKET_H_ | ||
|
||
#include "usb/usb_frame.h" | ||
#include "usb/usb_packet.h" | ||
#include <stdbool.h> | ||
#include <stddef.h> | ||
#include <stdint.h> | ||
|
||
/** | ||
* Processes an incoming USB packet. | ||
* @param[in] frame The frame that is to be processed. | ||
* @param[in] send_packet The function to be called to send the response packet. | ||
* @return true if we are waiting for more frames to complete a packet, false otherwise. | ||
*/ | ||
bool u2f_packet_process(const USB_FRAME* frame, void (*send_packet)(void)); | ||
|
||
/** | ||
* Checks if there has been a timeout | ||
*/ | ||
bool u2f_packet_timeout_get(uint32_t* cid); | ||
|
||
/** | ||
* Queue a timeout packet for cid | ||
*/ | ||
void u2f_packet_timeout(uint32_t cid); | ||
|
||
/** | ||
* Increase the timout timers with 1 step (steps in 100ms) | ||
*/ | ||
void u2f_packet_timeout_tick(void); | ||
|
||
/** | ||
* Enable timer for this cid | ||
*/ | ||
void u2f_packet_timeout_enable(uint32_t cid); | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.