This commit is contained in:
2019-08-23 13:32:41 +01:00
parent 55d1fd738f
commit f7dea03132
42 changed files with 850 additions and 985 deletions

View File

@@ -18,15 +18,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once #pragma once
enum APDU : uint8_t enum APDU : uint8_t { U2F_REG = 0x01, U2F_AUTH = 0x02, U2F_VER = 0x03 };
{
U2F_REG = 0x01,
U2F_AUTH = 0x02,
U2F_VER = 0x03
};
enum APDU_STATUS : uint16_t enum APDU_STATUS : uint16_t {
{
SW_NO_ERROR = 0x9000, SW_NO_ERROR = 0x9000,
SW_WRONG_LENGTH = 0x6700, SW_WRONG_LENGTH = 0x6700,
SW_CONDITIONS_NOT_SATISFIED = 0x6985, SW_CONDITIONS_NOT_SATISFIED = 0x6985,

View File

@@ -31,7 +31,9 @@ template <typename InContainer, typename Elem, size_t count>
void b64decode(const InContainer& iContainer, std::array<Elem, count>& oArr); void b64decode(const InContainer& iContainer, std::array<Elem, count>& oArr);
template <typename InContainerIter, typename OutContainerIter> template <typename InContainerIter, typename OutContainerIter>
void b64encode(const InContainerIter beginIter, const InContainerIter endIter, OutContainerIter oBeginIter); void b64encode(const InContainerIter beginIter, const InContainerIter endIter,
OutContainerIter oBeginIter);
template <typename InContainerIter, typename OutContainerIter> template <typename InContainerIter, typename OutContainerIter>
void b64decode(const InContainerIter beginIter, const InContainerIter endIter, OutContainerIter oBeginIter); void b64decode(const InContainerIter beginIter, const InContainerIter endIter,
OutContainerIter oBeginIter);

View File

@@ -25,66 +25,50 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
// You can generate your own using the method detailed in the README. // You can generate your own using the method detailed in the README.
uint8_t attestCert[] = { uint8_t attestCert[] = {
0x30, 0x82, 0x02, 0x29, 0x30, 0x82, 0x01, 0xd0, 0xa0, 0x03, 0x02, 0x01, 0x30, 0x82, 0x02, 0x29, 0x30, 0x82, 0x01, 0xd0, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00,
0x02, 0x02, 0x09, 0x00, 0x8a, 0xe2, 0x21, 0x3f, 0x2f, 0x8b, 0x72, 0x52, 0x8a, 0xe2, 0x21, 0x3f, 0x2f, 0x8b, 0x72, 0x52, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x70, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x30, 0x70, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x4b, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f,
0x02, 0x55, 0x4b, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x0a, 0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x49, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x29, 0x30, 0x27, 0x06,
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x20, 0x55, 0x32, 0x46, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x74, 0x50,
0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x46, 0x53, 0x71, 0x54, 0x71, 0x6f, 0x5a, 0x6d, 0x62, 0x37, 0x38, 0x61, 0x6a, 0x6f, 0x2f, 0x75,
0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x20, 0x55, 0x32, 0x58, 0x50, 0x73, 0x51, 0x3d, 0x3d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x36, 0x33, 0x30,
0x46, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x74, 0x50, 0x46, 0x53, 0x71, 0x54, 0x31, 0x39, 0x30, 0x37, 0x35, 0x31, 0x5a, 0x17, 0x0d, 0x32, 0x38, 0x30, 0x36, 0x32, 0x37, 0x31,
0x71, 0x6f, 0x5a, 0x6d, 0x62, 0x37, 0x38, 0x61, 0x6a, 0x6f, 0x2f, 0x75, 0x39, 0x30, 0x37, 0x35, 0x31, 0x5a, 0x30, 0x70, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
0x58, 0x50, 0x73, 0x51, 0x3d, 0x3d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x06, 0x13, 0x02, 0x55, 0x4b, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a,
0x30, 0x36, 0x33, 0x30, 0x31, 0x39, 0x30, 0x37, 0x35, 0x31, 0x5a, 0x17, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03,
0x0d, 0x32, 0x38, 0x30, 0x36, 0x32, 0x37, 0x31, 0x39, 0x30, 0x37, 0x35, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69,
0x31, 0x5a, 0x30, 0x70, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x29, 0x30,
0x06, 0x13, 0x02, 0x55, 0x4b, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x20, 0x55, 0x32, 0x46, 0x20, 0x4b, 0x65, 0x79, 0x20,
0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x50, 0x46, 0x53, 0x71, 0x54, 0x71, 0x6f, 0x5a, 0x6d, 0x62, 0x37, 0x38, 0x61, 0x6a, 0x6f,
0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x2f, 0x75, 0x58, 0x50, 0x73, 0x51, 0x3d, 0x3d, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x42, 0x00, 0x04, 0x32, 0x41, 0xc3, 0xb8, 0x96, 0x97, 0xd8, 0x90, 0x66, 0x41, 0x88, 0x96, 0xd4,
0x64, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x20, 0x73, 0xb6, 0x37, 0xf7, 0x85, 0x29, 0xaf, 0x3b, 0x15, 0x0f, 0x83, 0x61, 0x67, 0xea, 0xc9, 0xb2,
0x55, 0x32, 0x46, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x74, 0x50, 0x46, 0x53, 0xdb, 0x82, 0xb3, 0x2c, 0x99, 0x60, 0x8a, 0x98, 0x7c, 0xd4, 0x04, 0xa0, 0x92, 0x22, 0x05, 0xaa,
0x71, 0x54, 0x71, 0x6f, 0x5a, 0x6d, 0x62, 0x37, 0x38, 0x61, 0x6a, 0x6f, 0xf7, 0x7a, 0x91, 0x02, 0x03, 0xdd, 0x15, 0x88, 0x87, 0x6a, 0x26, 0xe9, 0xee, 0xcf, 0x99, 0xb1,
0x2f, 0x75, 0x58, 0x50, 0x73, 0x51, 0x3d, 0x3d, 0x30, 0x59, 0x30, 0x13, 0x66, 0xc0, 0x01, 0xa3, 0x53, 0x30, 0x51, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16,
0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x04, 0x14, 0xcf, 0x7f, 0xfa, 0x7d, 0xc4, 0x8d, 0xba, 0x60, 0x52, 0x4c, 0xb6, 0x16, 0x2e, 0x88,
0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x32, 0x62, 0xc7, 0x8c, 0xfc, 0xe0, 0x63, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30,
0x41, 0xc3, 0xb8, 0x96, 0x97, 0xd8, 0x90, 0x66, 0x41, 0x88, 0x96, 0xd4, 0x16, 0x80, 0x14, 0xcf, 0x7f, 0xfa, 0x7d, 0xc4, 0x8d, 0xba, 0x60, 0x52, 0x4c, 0xb6, 0x16, 0x2e,
0x73, 0xb6, 0x37, 0xf7, 0x85, 0x29, 0xaf, 0x3b, 0x15, 0x0f, 0x83, 0x61, 0x88, 0x62, 0xc7, 0x8c, 0xfc, 0xe0, 0x63, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01,
0x67, 0xea, 0xc9, 0xb2, 0xdb, 0x82, 0xb3, 0x2c, 0x99, 0x60, 0x8a, 0x98, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
0x7c, 0xd4, 0x04, 0xa0, 0x92, 0x22, 0x05, 0xaa, 0xf7, 0x7a, 0x91, 0x02, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x72, 0x25, 0x89, 0xc1, 0x32,
0x03, 0xdd, 0x15, 0x88, 0x87, 0x6a, 0x26, 0xe9, 0xee, 0xcf, 0x99, 0xb1, 0x54, 0x66, 0xf8, 0x0e, 0x58, 0x77, 0xe3, 0xb5, 0x62, 0x47, 0x33, 0x18, 0x5a, 0xdc, 0x28, 0x6a,
0x66, 0xc0, 0x01, 0xa3, 0x53, 0x30, 0x51, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x4a, 0x56, 0xcb, 0x58, 0x63, 0xe3, 0xa1, 0x02, 0x6a, 0xf0, 0xd8, 0x02, 0x20, 0x65, 0x26, 0x84,
0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xcf, 0x7f, 0xfa, 0x7d, 0xc4, 0x8d, 0x7c, 0xc3, 0x3b, 0x7d, 0x6a, 0x22, 0x0c, 0x22, 0x3d, 0xc8, 0x43, 0xb7, 0x84, 0x8b, 0x7b, 0x48,
0xba, 0x60, 0x52, 0x4c, 0xb6, 0x16, 0x2e, 0x88, 0x62, 0xc7, 0x8c, 0xfc, 0x23, 0xb0, 0x1e, 0x13, 0x35, 0x1d, 0x1a, 0x90, 0x44, 0x62, 0x6c, 0xab, 0x9b
0xe0, 0x63, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30,
0x16, 0x80, 0x14, 0xcf, 0x7f, 0xfa, 0x7d, 0xc4, 0x8d, 0xba, 0x60, 0x52,
0x4c, 0xb6, 0x16, 0x2e, 0x88, 0x62, 0xc7, 0x8c, 0xfc, 0xe0, 0x63, 0x30,
0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30,
0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x72,
0x25, 0x89, 0xc1, 0x32, 0x54, 0x66, 0xf8, 0x0e, 0x58, 0x77, 0xe3, 0xb5,
0x62, 0x47, 0x33, 0x18, 0x5a, 0xdc, 0x28, 0x6a, 0x4a, 0x56, 0xcb, 0x58,
0x63, 0xe3, 0xa1, 0x02, 0x6a, 0xf0, 0xd8, 0x02, 0x20, 0x65, 0x26, 0x84,
0x7c, 0xc3, 0x3b, 0x7d, 0x6a, 0x22, 0x0c, 0x22, 0x3d, 0xc8, 0x43, 0xb7,
0x84, 0x8b, 0x7b, 0x48, 0x23, 0xb0, 0x1e, 0x13, 0x35, 0x1d, 0x1a, 0x90,
0x44, 0x62, 0x6c, 0xab, 0x9b
}; };
uint8_t attestPrivKey[] = { uint8_t attestPrivKey[] = { 0x7e, 0xbd, 0x91, 0x05, 0x5a, 0x80, 0x9f, 0x36, 0xe5, 0x2f, 0xe0,
0x7e, 0xbd, 0x91, 0x05, 0x5a, 0x80, 0x9f, 0x36, 0xe5, 0x2f, 0xe0, 0xd0, 0xd0, 0xa9, 0x63, 0x0c, 0x86, 0x04, 0xb1, 0x04, 0xe3, 0xd1, 0xfb,
0xa9, 0x63, 0x0c, 0x86, 0x04, 0xb1, 0x04, 0xe3, 0xd1, 0xfb, 0xd0, 0x83, 0xd0, 0x83, 0xc7, 0x2e, 0x2f, 0x34, 0xb6, 0xd6, 0xa4, 0xb2 };
0xc7, 0x2e, 0x2f, 0x34, 0xb6, 0xd6, 0xa4, 0xb2
};
uint8_t attestPubKey[] = { uint8_t attestPubKey[] = { 0x04, 0x32, 0x41, 0xc3, 0xb8, 0x96, 0x97, 0xd8, 0x90, 0x66, 0x41,
0x04, 0x32, 0x41, 0xc3, 0xb8, 0x96, 0x97, 0xd8, 0x90, 0x66, 0x41, 0x88, 0x88, 0x96, 0xd4, 0x73, 0xb6, 0x37, 0xf7, 0x85, 0x29, 0xaf, 0x3b,
0x96, 0xd4, 0x73, 0xb6, 0x37, 0xf7, 0x85, 0x29, 0xaf, 0x3b, 0x15, 0x0f, 0x15, 0x0f, 0x83, 0x61, 0x67, 0xea, 0xc9, 0xb2, 0xdb, 0x82, 0xb3,
0x83, 0x61, 0x67, 0xea, 0xc9, 0xb2, 0xdb, 0x82, 0xb3, 0x2c, 0x99, 0x60, 0x2c, 0x99, 0x60, 0x8a, 0x98, 0x7c, 0xd4, 0x04, 0xa0, 0x92, 0x22,
0x8a, 0x98, 0x7c, 0xd4, 0x04, 0xa0, 0x92, 0x22, 0x05, 0xaa, 0xf7, 0x7a, 0x05, 0xaa, 0xf7, 0x7a, 0x91, 0x02, 0x03, 0xdd, 0x15, 0x88, 0x87,
0x91, 0x02, 0x03, 0xdd, 0x15, 0x88, 0x87, 0x6a, 0x26, 0xe9, 0xee, 0xcf, 0x6a, 0x26, 0xe9, 0xee, 0xcf, 0x99, 0xb1, 0x66, 0xc0, 0x01 };
0x99, 0xb1, 0x66, 0xc0, 0x01
};

View File

@@ -17,24 +17,23 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include "Channel.hpp" #include "Channel.hpp"
#include <stdexcept>
#include "u2f.hpp"
#include "U2F_CMD.hpp" #include "U2F_CMD.hpp"
#include "u2f.hpp"
#include <iostream> #include <iostream>
#include <stdexcept>
using namespace std; using namespace std;
Channel::Channel(const uint32_t channelID) Channel::Channel(const uint32_t channelID)
: cid{ channelID }, initState{ ChannelInitState::Unitialised }, lockedState{ ChannelLockedState::Unlocked } : cid{ channelID }, initState{ ChannelInitState::Unitialised }, lockedState{
{} ChannelLockedState::Unlocked
} {}
uint32_t Channel::getCID() const uint32_t Channel::getCID() const {
{
return cid; return cid;
} }
void Channel::handle(const shared_ptr<U2FMessage> uMsg) void Channel::handle(const shared_ptr<U2FMessage> uMsg) {
{
if (uMsg->cmd == U2FHID_INIT) if (uMsg->cmd == U2FHID_INIT)
this->initState = ChannelInitState::Initialised; this->initState = ChannelInitState::Initialised;
else if (uMsg->cid != this->cid) else if (uMsg->cid != this->cid)
@@ -51,12 +50,10 @@ void Channel::handle(const shared_ptr<U2FMessage> uMsg)
return cmd->respond(this->cid); return cmd->respond(this->cid);
} }
void Channel::init(const ChannelInitState newInitState) void Channel::init(const ChannelInitState newInitState) {
{
this->initState = newInitState; this->initState = newInitState;
} }
void Channel::lock(const ChannelLockedState newLockedState) void Channel::lock(const ChannelLockedState newLockedState) {
{
this->lockedState = newLockedState; this->lockedState = newLockedState;
} }

View File

@@ -17,24 +17,15 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "U2FMessage.hpp"
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include "U2FMessage.hpp"
enum class ChannelInitState enum class ChannelInitState { Unitialised, Initialised };
{
Unitialised,
Initialised
};
enum class ChannelLockedState enum class ChannelLockedState { Locked, Unlocked };
{
Locked,
Unlocked
};
class Channel class Channel {
{
protected: protected:
uint32_t cid; uint32_t cid;
ChannelInitState initState; ChannelInitState initState;

View File

@@ -17,28 +17,25 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include "Controller.hpp" #include "Controller.hpp"
#include "u2f.hpp"
#include <iostream>
#include "IO.hpp" #include "IO.hpp"
#include "LED.hpp" #include "LED.hpp"
#include "u2f.hpp"
#include <iostream>
using namespace std; using namespace std;
Controller::Controller(const uint32_t startChannel) Controller::Controller(const uint32_t startChannel) : channels{}, currChannel{ startChannel } {}
: channels{}, currChannel{ startChannel }
{}
void Controller::handleTransaction() void Controller::handleTransaction() {
{ try {
try if (channels.size() != 0 &&
{ chrono::duration_cast<chrono::seconds>(chrono::system_clock::now() - lastMessage) <
if (channels.size() != 0 && chrono::duration_cast<chrono::seconds>(chrono::system_clock::now() - lastMessage) < chrono::seconds(5)) chrono::seconds(5))
toggleACTLED(); toggleACTLED();
else else
enableACTLED(false); enableACTLED(false);
} catch (runtime_error& ignored) {
} }
catch (runtime_error& ignored)
{}
auto msg = U2FMessage::readNonBlock(); auto msg = U2FMessage::readNonBlock();
@@ -49,17 +46,13 @@ void Controller::handleTransaction()
auto opChannel = msg->cid; auto opChannel = msg->cid;
if (msg->cmd == U2FHID_INIT) if (msg->cmd == U2FHID_INIT) {
{
opChannel = nextChannel(); opChannel = nextChannel();
auto channel = Channel{ opChannel }; auto channel = Channel{ opChannel };
try try {
{
channels.emplace(opChannel, channel); // In case of wrap-around replace existing one channels.emplace(opChannel, channel); // In case of wrap-around replace existing one
} } catch (...) {
catch (...)
{
channels.insert(make_pair(opChannel, channel)); channels.insert(make_pair(opChannel, channel));
} }
} }
@@ -72,8 +65,7 @@ void Controller::handleTransaction()
channels.at(opChannel).handle(msg); channels.at(opChannel).handle(msg);
} }
uint32_t Controller::nextChannel() uint32_t Controller::nextChannel() {
{
do do
currChannel++; currChannel++;
while (currChannel == 0xFFFFFFFF || currChannel == 0); while (currChannel == 0xFFFFFFFF || currChannel == 0);

View File

@@ -17,12 +17,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include <map>
#include <chrono>
#include "Channel.hpp" #include "Channel.hpp"
#include <chrono>
#include <map>
class Controller class Controller {
{
protected: protected:
std::map<uint32_t, Channel> channels; std::map<uint32_t, Channel> channels;
uint32_t currChannel; uint32_t currChannel;

View File

@@ -20,7 +20,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
using namespace std; using namespace std;
vector<uint8_t> beEncode(const uint8_t* val, const size_t byteCount) vector<uint8_t> beEncode(const uint8_t* val, const size_t byteCount) {
{ return { reverse_iterator<const uint8_t*>(val + byteCount),
return { reverse_iterator<const uint8_t *>(val + byteCount), reverse_iterator<const uint8_t *>(val) }; reverse_iterator<const uint8_t*>(val) };
} }

View File

@@ -17,13 +17,17 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include <vector>
#include <cstdint> #include <cstdint>
#include <vector>
template <typename Type> template <typename Type>
std::vector<uint8_t> beEncode(const Type val); std::vector<uint8_t> beEncode(const Type val);
std::vector<uint8_t> beEncode(const uint8_t* val, const std::size_t byteCount); std::vector<uint8_t> beEncode(const uint8_t* val, const std::size_t byteCount);
#define FIELD(name) reinterpret_cast<const uint8_t*>(&name), (reinterpret_cast<const uint8_t*>(&name) + sizeof(name)) #define FIELD(name) \
#define FIELD_BE(name) reverse_iterator<const uint8_t*>(reinterpret_cast<const uint8_t*>(&name) + sizeof(name)), reverse_iterator<const uint8_t*>(reinterpret_cast<const uint8_t*>(&name)) reinterpret_cast<const uint8_t*>(&name), \
(reinterpret_cast<const uint8_t*>(&name) + sizeof(name))
#define FIELD_BE(name) \
reverse_iterator<const uint8_t*>(reinterpret_cast<const uint8_t*>(&name) + sizeof(name)), \
reverse_iterator<const uint8_t*>(reinterpret_cast<const uint8_t*>(&name))

62
IO.cpp
View File

@@ -21,26 +21,24 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <iostream> #include <iostream>
#include <unistd.h> #include <unistd.h>
//#include <sys/ioctl.h> //#include <sys/ioctl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <chrono>
#include <ratio>
#include "u2f.hpp"
#include "Macro.hpp" #include "Macro.hpp"
#include "U2FDevice.hpp" #include "U2FDevice.hpp"
#include "u2f.hpp"
#include <chrono>
#include <fcntl.h>
#include <ratio>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
using namespace std; using namespace std;
bool bytesAvailable(const size_t count); bool bytesAvailable(const size_t count);
vector<uint8_t>& getBuffer(); vector<uint8_t>& getBuffer();
vector<uint8_t> readNonBlock(const size_t count) vector<uint8_t> readNonBlock(const size_t count) {
{ if (!bytesAvailable(count)) {
if (!bytesAvailable(count))
{
return vector<uint8_t>{}; return vector<uint8_t>{};
} }
@@ -54,32 +52,29 @@ vector<uint8_t> readNonBlock(const size_t count)
return bytes; return bytes;
} }
void write(const uint8_t* bytes, const size_t count) void write(const uint8_t* bytes, const size_t count) {
{
size_t totalBytes = 0; size_t totalBytes = 0;
auto hostDescriptor = *getHostDescriptor(); auto hostDescriptor = *getHostDescriptor();
while (totalBytes < count) while (totalBytes < count) {
{
auto writtenBytes = write(hostDescriptor, bytes + totalBytes, count - totalBytes); auto writtenBytes = write(hostDescriptor, bytes + totalBytes, count - totalBytes);
if (writtenBytes > 0) if (writtenBytes > 0)
totalBytes += writtenBytes; totalBytes += writtenBytes;
else if (errno != 0 && errno != EAGAIN && errno != EWOULDBLOCK) //Expect file blocking behaviour else if (errno != 0 && errno != EAGAIN &&
errno != EWOULDBLOCK) // Expect file blocking behaviour
ERR(); ERR();
} }
errno = 0; errno = 0;
} }
bool bytesAvailable(const size_t count) bool bytesAvailable(const size_t count) {
{
auto startTime = std::chrono::high_resolution_clock::now(); auto startTime = std::chrono::high_resolution_clock::now();
const timespec iterDelay{ 0, 1000 }; const timespec iterDelay{ 0, 1000 };
chrono::duration<double, milli> delay{ 0 }; chrono::duration<double, milli> delay{ 0 };
while (delay.count() < U2FHID_TRANS_TIMEOUT && contProc) while (delay.count() < U2FHID_TRANS_TIMEOUT && contProc) {
{
delay = chrono::high_resolution_clock::now() - startTime; delay = chrono::high_resolution_clock::now() - startTime;
if (getBuffer().size() >= count) { if (getBuffer().size() >= count) {
#ifdef DEBUG_MSGS #ifdef DEBUG_MSGS
@@ -97,49 +92,42 @@ bool bytesAvailable(const size_t count)
return false; return false;
} }
vector<uint8_t>& bufferVar() vector<uint8_t>& bufferVar() {
{
static vector<uint8_t> buffer{}; static vector<uint8_t> buffer{};
return buffer; return buffer;
} }
vector<uint8_t>& getBuffer() vector<uint8_t>& getBuffer() {
{
auto& buff = bufferVar(); auto& buff = bufferVar();
array<uint8_t, HID_RPT_SIZE> bytes{}; array<uint8_t, HID_RPT_SIZE> bytes{};
auto hostDescriptor = *getHostDescriptor(); auto hostDescriptor = *getHostDescriptor();
while (true) while (true) {
{
auto readByteCount = read(hostDescriptor, bytes.data(), HID_RPT_SIZE); auto readByteCount = read(hostDescriptor, bytes.data(), HID_RPT_SIZE);
if (readByteCount > 0 && readByteCount != HID_RPT_SIZE) if (readByteCount > 0 && readByteCount != HID_RPT_SIZE) {
{
// Failed to copy an entire packet in, so log this packet // Failed to copy an entire packet in, so log this packet
#ifdef DEBUG_MSGS #ifdef DEBUG_MSGS
cerr << "Only retrieved " << readByteCount << " bytes from expected full packet." << endl; cerr << "Only retrieved " << readByteCount << " bytes from expected full packet."
<< endl;
#endif #endif
} }
if (readByteCount > 0) if (readByteCount > 0) {
{
copy(bytes.begin(), bytes.begin() + readByteCount, back_inserter(buff)); copy(bytes.begin(), bytes.begin() + readByteCount, back_inserter(buff));
#ifdef DEBUG_STREAMS #ifdef DEBUG_STREAMS
fwrite(bytes.data(), 1, readByteCount, getComHostStream().get()); fwrite(bytes.data(), 1, readByteCount, getComHostStream().get());
#endif #endif
} } else if (errno != EAGAIN && errno != EWOULDBLOCK) // Expect read would block
else if (errno != EAGAIN && errno != EWOULDBLOCK) //Expect read would block
{ {
ERR(); ERR();
#ifdef DEBUG_MSGS #ifdef DEBUG_MSGS
cerr << "Unknown stream error: " << errno << endl; cerr << "Unknown stream error: " << errno << endl;
#endif #endif
break; break;
} } else {
else
{
errno = 0; errno = 0;
break; // Escape loop if blocking would occur break; // Escape loop if blocking would occur
} }

15
LED.cpp
View File

@@ -24,19 +24,16 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
using namespace std; using namespace std;
bool& ledState() bool& ledState() {
{
static bool state = true; static bool state = true;
return state; return state;
} }
bool getLEDState() bool getLEDState() {
{
return ledState(); return ledState();
} }
void disableACTTrigger([[maybe_unused]] bool nowDisabled) void disableACTTrigger([[maybe_unused]] bool nowDisabled) {
{
#ifdef LEDS #ifdef LEDS
ofstream trigFile{ "/sys/class/leds/led0/trigger", ofstream::out | ofstream::trunc }; ofstream trigFile{ "/sys/class/leds/led0/trigger", ofstream::out | ofstream::trunc };
@@ -48,8 +45,7 @@ void disableACTTrigger([[maybe_unused]] bool nowDisabled)
#endif #endif
} }
void enableACTLED([[maybe_unused]] bool nowOn) void enableACTLED([[maybe_unused]] bool nowOn) {
{
#ifdef LEDS #ifdef LEDS
if (nowOn == getLEDState()) if (nowOn == getLEDState())
return; return;
@@ -66,7 +62,6 @@ void enableACTLED([[maybe_unused]] bool nowOn)
#endif #endif
} }
void toggleACTLED() void toggleACTLED() {
{
enableACTLED(!getLEDState()); enableACTLED(!getLEDState());
} }

View File

@@ -17,7 +17,12 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include <unistd.h>
#include <string> #include <string>
#include <unistd.h>
#define ERR() if (errno != 0) perror((string{ "(" } + __FILE__ + ":" + to_string(__LINE__) + ")" + " " + __PRETTY_FUNCTION__).c_str()), errno = 0 #define ERR() \
if (errno != 0) \
perror( \
(string{ "(" } + __FILE__ + ":" + to_string(__LINE__) + ")" + " " + __PRETTY_FUNCTION__) \
.c_str()), \
errno = 0

View File

@@ -18,24 +18,22 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "Packet.hpp" #include "Packet.hpp"
#include "IO.hpp" #include "IO.hpp"
#include "Streams.hpp"
#include "u2f.hpp" #include "u2f.hpp"
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
#include <unistd.h> #include <unistd.h>
#include "Streams.hpp"
using namespace std; using namespace std;
shared_ptr<InitPacket> InitPacket::getPacket(const uint32_t rCID, const uint8_t rCMD) shared_ptr<InitPacket> InitPacket::getPacket(const uint32_t rCID, const uint8_t rCMD) {
{
static size_t bytesRead = 0; static size_t bytesRead = 0;
static uint8_t bcnth; static uint8_t bcnth;
static uint8_t bcntl; static uint8_t bcntl;
static decltype(InitPacket::data) dataBytes; static decltype(InitPacket::data) dataBytes;
vector<uint8_t> bytes{}; vector<uint8_t> bytes{};
switch (bytesRead) switch (bytesRead) {
{
case 0: case 0:
bytes = readNonBlock(1); bytes = readNonBlock(1);
@@ -62,7 +60,8 @@ shared_ptr<InitPacket> InitPacket::getPacket(const uint32_t rCID, const uint8_t
if (bytes.size() == 0) if (bytes.size() == 0)
return {}; return {};
copy(bytes.begin(), bytes.end(), dataBytes.begin());; copy(bytes.begin(), bytes.end(), dataBytes.begin());
;
bytesRead += bytes.size(); bytesRead += bytes.size();
[[fallthrough]]; [[fallthrough]];
@@ -82,7 +81,8 @@ shared_ptr<InitPacket> InitPacket::getPacket(const uint32_t rCID, const uint8_t
#ifdef DEBUG_STREAMS #ifdef DEBUG_STREAMS
auto hPStream = getHostPacketStream().get(); auto hPStream = getHostPacketStream().get();
fprintf(hPStream, "\t\t<table>\n" fprintf(hPStream,
"\t\t<table>\n"
"\t\t\t<thead>\n" "\t\t\t<thead>\n"
"\t\t\t\t<tr>\n" "\t\t\t\t<tr>\n"
"\t\t\t\t\t<th>CID</th>\n" "\t\t\t\t\t<th>CID</th>\n"
@@ -98,7 +98,8 @@ shared_ptr<InitPacket> InitPacket::getPacket(const uint32_t rCID, const uint8_t
"\t\t\t\t\t<td>%u</td>\n" "\t\t\t\t\t<td>%u</td>\n"
"\t\t\t\t\t<td>%u</td>\n" "\t\t\t\t\t<td>%u</td>\n"
"\t\t\t\t\t<td>%u</td>\n" "\t\t\t\t\t<td>%u</td>\n"
"\t\t\t\t\t<td class=\"data\">", p->cid, p->cmd, p->bcnth, p->bcntl); "\t\t\t\t\t<td class=\"data\">",
p->cid, p->cmd, p->bcnth, p->bcntl);
for (auto elem : dataBytes) for (auto elem : dataBytes)
fprintf(hPStream, "%3u ", elem); fprintf(hPStream, "%3u ", elem);
@@ -114,16 +115,14 @@ shared_ptr<InitPacket> InitPacket::getPacket(const uint32_t rCID, const uint8_t
return p; return p;
} }
shared_ptr<ContPacket> ContPacket::getPacket(const uint32_t rCID, const uint8_t rSeq) shared_ptr<ContPacket> ContPacket::getPacket(const uint32_t rCID, const uint8_t rSeq) {
{
static size_t readBytes = 0; static size_t readBytes = 0;
static decltype(ContPacket::data) dataBytes; static decltype(ContPacket::data) dataBytes;
vector<uint8_t> bytes{}; vector<uint8_t> bytes{};
auto p = make_shared<ContPacket>(); auto p = make_shared<ContPacket>();
if (readBytes != dataBytes.size()) if (readBytes != dataBytes.size()) {
{
dataBytes = {}; dataBytes = {};
bytes = readNonBlock(dataBytes.size()); bytes = readNonBlock(dataBytes.size());
@@ -140,7 +139,8 @@ shared_ptr<ContPacket> ContPacket::getPacket(const uint32_t rCID, const uint8_t
#ifdef DEBUG_STREAMS #ifdef DEBUG_STREAMS
auto hPStream = getHostPacketStream().get(); auto hPStream = getHostPacketStream().get();
fprintf(hPStream, "\t\t<table>\n" fprintf(hPStream,
"\t\t<table>\n"
"\t\t\t<thead>\n" "\t\t\t<thead>\n"
"\t\t\t\t<tr>\n" "\t\t\t\t<tr>\n"
"\t\t\t\t\t<th>CID</th>\n" "\t\t\t\t\t<th>CID</th>\n"
@@ -152,7 +152,8 @@ shared_ptr<ContPacket> ContPacket::getPacket(const uint32_t rCID, const uint8_t
"\t\t\t\t<tr>\n" "\t\t\t\t<tr>\n"
"\t\t\t\t\t<td>0x%08X</td>\n" "\t\t\t\t\t<td>0x%08X</td>\n"
"\t\t\t\t\t<td>%u</td>\n" "\t\t\t\t\t<td>%u</td>\n"
"\t\t\t\t\t<td class=\"data\">", p->cid, p->seq); "\t\t\t\t\t<td class=\"data\">",
p->cid, p->seq);
for (auto elem : dataBytes) for (auto elem : dataBytes)
fprintf(hPStream, "%3u ", elem); fprintf(hPStream, "%3u ", elem);
@@ -168,8 +169,7 @@ shared_ptr<ContPacket> ContPacket::getPacket(const uint32_t rCID, const uint8_t
return p; return p;
} }
shared_ptr<Packet> Packet::getPacket() shared_ptr<Packet> Packet::getPacket() {
{
static size_t bytesRead = 0; static size_t bytesRead = 0;
vector<uint8_t> bytes{}; vector<uint8_t> bytes{};
@@ -177,8 +177,7 @@ shared_ptr<Packet> Packet::getPacket()
static uint8_t b; static uint8_t b;
shared_ptr<Packet> packet{}; shared_ptr<Packet> packet{};
switch (bytesRead) switch (bytesRead) {
{
case 0: case 0:
bytes = readNonBlock(4); bytes = readNonBlock(4);
@@ -200,8 +199,7 @@ shared_ptr<Packet> Packet::getPacket()
[[fallthrough]]; [[fallthrough]];
case 5: case 5:
if (b & TYPE_MASK) if (b & TYPE_MASK) {
{
// Init packet // Init packet
packet = InitPacket::getPacket(cid, b); packet = InitPacket::getPacket(cid, b);
@@ -209,9 +207,7 @@ shared_ptr<Packet> Packet::getPacket()
bytesRead = 0; bytesRead = 0;
return packet; return packet;
} } else {
else
{
// Cont packet // Cont packet
packet = ContPacket::getPacket(cid, b); packet = ContPacket::getPacket(cid, b);
@@ -225,14 +221,12 @@ shared_ptr<Packet> Packet::getPacket()
} }
} }
void Packet::writePacket() void Packet::writePacket() {
{
memset(this->buf, 0, HID_RPT_SIZE); memset(this->buf, 0, HID_RPT_SIZE);
memcpy(this->buf, &cid, 4); memcpy(this->buf, &cid, 4);
} }
void InitPacket::writePacket() void InitPacket::writePacket() {
{
Packet::writePacket(); Packet::writePacket();
#ifdef DEBUG_STREAMS #ifdef DEBUG_STREAMS
@@ -249,7 +243,8 @@ void InitPacket::writePacket()
fwrite(this->buf, 1, sizeof(this->buf), devStream); fwrite(this->buf, 1, sizeof(this->buf), devStream);
auto dPStream = getDevPacketStream().get(); auto dPStream = getDevPacketStream().get();
fprintf(dPStream, "\t\t<table>\n" fprintf(dPStream,
"\t\t<table>\n"
"\t\t\t<thead>\n" "\t\t\t<thead>\n"
"\t\t\t\t<tr>\n" "\t\t\t\t<tr>\n"
"\t\t\t\t\t<th>CID</th>\n" "\t\t\t\t\t<th>CID</th>\n"
@@ -265,7 +260,8 @@ void InitPacket::writePacket()
"\t\t\t\t\t<td>%u</td>\n" "\t\t\t\t\t<td>%u</td>\n"
"\t\t\t\t\t<td>%u</td>\n" "\t\t\t\t\t<td>%u</td>\n"
"\t\t\t\t\t<td>%u</td>\n" "\t\t\t\t\t<td>%u</td>\n"
"\t\t\t\t\t<td class=\"data\">", cid, cmd, bcnth, bcntl); "\t\t\t\t\t<td class=\"data\">",
cid, cmd, bcnth, bcntl);
for (auto elem : data) for (auto elem : data)
fprintf(dPStream, "%3u ", elem); fprintf(dPStream, "%3u ", elem);
@@ -278,8 +274,7 @@ void InitPacket::writePacket()
#endif #endif
} }
void ContPacket::writePacket() void ContPacket::writePacket() {
{
Packet::writePacket(); Packet::writePacket();
#ifdef DEBUG_STREAMS #ifdef DEBUG_STREAMS
@@ -295,7 +290,8 @@ void ContPacket::writePacket()
auto dPStream = getDevPacketStream().get(); auto dPStream = getDevPacketStream().get();
fprintf(dPStream, "\t\t<table>\n" fprintf(dPStream,
"\t\t<table>\n"
"\t\t\t<thead>\n" "\t\t\t<thead>\n"
"\t\t\t\t<tr>\n" "\t\t\t\t<tr>\n"
"\t\t\t\t\t<th>CID</th>\n" "\t\t\t\t\t<th>CID</th>\n"
@@ -307,7 +303,8 @@ void ContPacket::writePacket()
"\t\t\t\t<tr>\n" "\t\t\t\t<tr>\n"
"\t\t\t\t\t<td>0x%08X</td>\n" "\t\t\t\t\t<td>0x%08X</td>\n"
"\t\t\t\t\t<td>%u</td>\n" "\t\t\t\t\t<td>%u</td>\n"
"\t\t\t\t\t<td class=\"data\">", cid, seq); "\t\t\t\t\t<td class=\"data\">",
cid, seq);
for (auto elem : data) for (auto elem : data)
fprintf(dPStream, "%3u ", elem); fprintf(dPStream, "%3u ", elem);

View File

@@ -17,13 +17,12 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "u2f.hpp"
#include <array>
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include <array>
#include "u2f.hpp"
struct Packet struct Packet {
{
public: public:
uint32_t cid; uint32_t cid;
uint8_t buf[HID_RPT_SIZE]; uint8_t buf[HID_RPT_SIZE];
@@ -37,8 +36,7 @@ struct Packet
virtual ~Packet() = default; virtual ~Packet() = default;
}; };
struct InitPacket : Packet struct InitPacket : Packet {
{
public: public:
uint8_t cmd; uint8_t cmd;
uint8_t bcnth; uint8_t bcnth;
@@ -51,8 +49,7 @@ struct InitPacket : Packet
void writePacket() override; void writePacket() override;
}; };
struct ContPacket : Packet struct ContPacket : Packet {
{
public: public:
uint8_t seq; uint8_t seq;
std::array<uint8_t, HID_RPT_SIZE - 5> data{}; std::array<uint8_t, HID_RPT_SIZE - 5> data{};

View File

@@ -22,21 +22,18 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
using namespace std; using namespace std;
// Ripped from https://github.com/pratikd650/Teensy_U2F/blob/master/Teensy_U2F.cpp // Ripped from https://github.com/pratikd650/Teensy_U2F/blob/master/Teensy_U2F.cpp
void appendSignatureAsDER(vector<uint8_t> &response, const array<uint8_t, 64> &signature) void appendSignatureAsDER(vector<uint8_t>& response, const array<uint8_t, 64>& signature) {
{
response.push_back(0x30); // Start of ASN.1 SEQUENCE response.push_back(0x30); // Start of ASN.1 SEQUENCE
response.push_back(68); // total length from (2 * (32 + 2)) to (2 * (33 + 2)) response.push_back(68); // total length from (2 * (32 + 2)) to (2 * (33 + 2))
size_t countByte = response.size() - 1; size_t countByte = response.size() - 1;
// Loop twice - for R and S // Loop twice - for R and S
for(unsigned int i = 0; i < 2; i++) for (unsigned int i = 0; i < 2; i++) {
{
unsigned int sigOffs = i * 32; unsigned int sigOffs = i * 32;
auto offset = signature.begin() + sigOffs; auto offset = signature.begin() + sigOffs;
response.push_back(0x02); // header: integer response.push_back(0x02); // header: integer
response.push_back(32); // 32 byte response.push_back(32); // 32 byte
if (signature[sigOffs] > 0x7f) if (signature[sigOffs] > 0x7f) {
{
// Integer needs to be represented in 2's completement notion // Integer needs to be represented in 2's completement notion
response.back()++; response.back()++;
response.push_back(0); // add leading 0, to indicate it is a positive number response.push_back(0); // add leading 0, to indicate it is a positive number

View File

@@ -17,8 +17,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include <vector>
#include <array> #include <array>
#include <vector>
using Digest = std::array<uint8_t, 32>; using Digest = std::array<uint8_t, 32>;
using Signature = std::array<uint8_t, 64>; using Signature = std::array<uint8_t, 64>;

View File

@@ -17,10 +17,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include "Storage.hpp" #include "Storage.hpp"
#include <exception>
#include <sstream>
#include "Base64.tpp" #include "Base64.tpp"
#include <exception>
#include <iostream> #include <iostream>
#include <sstream>
using namespace std; using namespace std;
@@ -30,15 +30,13 @@ std::map<Storage::KeyHandle, Storage::PrivKey> Storage::privKeys{};
std::map<Storage::KeyHandle, Storage::PubKey> Storage::pubKeys{}; std::map<Storage::KeyHandle, Storage::PubKey> Storage::pubKeys{};
std::map<Storage::KeyHandle, Storage::KeyCount> Storage::keyCounts{}; std::map<Storage::KeyHandle, Storage::KeyCount> Storage::keyCounts{};
void Storage::init(const string &dirPrefix) void Storage::init(const string& dirPrefix) {
{
Storage::filename = dirPrefix + "U2F_Priv_Keys.txt"; Storage::filename = dirPrefix + "U2F_Priv_Keys.txt";
ifstream file{ Storage::filename }; ifstream file{ Storage::filename };
string line; string line;
size_t lineNumber = 0; size_t lineNumber = 0;
while (getline(file, line)) while (getline(file, line)) {
{
auto strLineNum = to_string(lineNumber); auto strLineNum = to_string(lineNumber);
stringstream ss{ line }; stringstream ss{ line };
string keyHStr, appStr, privStr, pubStr, keyCStr; string keyHStr, appStr, privStr, pubStr, keyCStr;
@@ -48,13 +46,15 @@ void Storage::init(const string &dirPrefix)
throw runtime_error{ string{ "Invalid syntax of line " } + strLineNum }; throw runtime_error{ string{ "Invalid syntax of line " } + strLineNum };
char* endP = nullptr; char* endP = nullptr;
Storage::KeyHandle keyH{ static_cast<Storage::KeyHandle>(strtoull(keyHStr.c_str(), &endP, 10)) }; Storage::KeyHandle keyH{ static_cast<Storage::KeyHandle>(
strtoull(keyHStr.c_str(), &endP, 10)) };
if (!endP) if (!endP)
throw runtime_error{ "Invalid keyhandle format on line " + strLineNum }; throw runtime_error{ "Invalid keyhandle format on line " + strLineNum };
endP = nullptr; endP = nullptr;
Storage::KeyCount keyC{ static_cast<Storage::KeyCount>(strtoull(keyCStr.c_str(), &endP, 10)) }; Storage::KeyCount keyC{ static_cast<Storage::KeyCount>(
strtoull(keyCStr.c_str(), &endP, 10)) };
if (!endP) if (!endP)
throw runtime_error{ "Invalid key count format on line " + strLineNum }; throw runtime_error{ "Invalid key count format on line " + strLineNum };
@@ -77,12 +77,10 @@ void Storage::init(const string &dirPrefix)
} }
} }
void Storage::save() void Storage::save() {
{
ofstream file{ Storage::filename }; ofstream file{ Storage::filename };
for (auto &keypair : Storage::appParams) for (auto& keypair : Storage::appParams) {
{
const auto& keyID = keypair.first; const auto& keyID = keypair.first;
const auto& appParam = keypair.second; const auto& appParam = keypair.second;
const auto& privKey = Storage::privKeys[keyID]; const auto& privKey = Storage::privKeys[keyID];

View File

@@ -17,13 +17,12 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include <map>
#include <array> #include <array>
#include <string>
#include <fstream> #include <fstream>
#include <map>
#include <string>
class Storage class Storage {
{
public: public:
using KeyHandle = uint32_t; using KeyHandle = uint32_t;
using KeyCount = uint32_t; using KeyCount = uint32_t;

View File

@@ -17,11 +17,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include "Streams.hpp" #include "Streams.hpp"
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cstdio> #include <cstdio>
#include <fcntl.h>
#include <iostream>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h> #include <unistd.h>
using namespace std; using namespace std;
@@ -31,8 +31,7 @@ FILE* initHTML(FILE *fPtr, const string &title);
void closeHTML(FILE* fPtr); void closeHTML(FILE* fPtr);
#endif #endif
shared_ptr<int> getHostDescriptor() shared_ptr<int> getHostDescriptor() {
{
static shared_ptr<int> descriptor{}; static shared_ptr<int> descriptor{};
descriptor.reset(new int{ open(HID_DEV, O_RDWR | O_NONBLOCK | O_APPEND) }, [](int* fd) { descriptor.reset(new int{ open(HID_DEV, O_RDWR | O_NONBLOCK | O_APPEND) }, [](int* fd) {
@@ -47,8 +46,7 @@ shared_ptr<int> getHostDescriptor()
} }
#ifdef DEBUG_STREAMS #ifdef DEBUG_STREAMS
shared_ptr<FILE> getComHostStream() shared_ptr<FILE> getComHostStream() {
{
static shared_ptr<FILE> stream{ fopen(DEBUG_STREAMS "comhost.txt", "wb"), [](FILE* f) { static shared_ptr<FILE> stream{ fopen(DEBUG_STREAMS "comhost.txt", "wb"), [](FILE* f) {
clog << "Closing comhost stream" << endl; clog << "Closing comhost stream" << endl;
fclose(f); fclose(f);
@@ -60,9 +58,10 @@ shared_ptr<FILE> getComHostStream()
return stream; return stream;
} }
shared_ptr<FILE> getHostPacketStream() shared_ptr<FILE> getHostPacketStream() {
{ static shared_ptr<FILE> stream{ initHTML(fopen(DEBUG_STREAMS "hostpackets.html", "wb"),
static shared_ptr<FILE> stream{ initHTML(fopen(DEBUG_STREAMS "hostpackets.html", "wb"), "Host Packets"), [](FILE *f){ "Host Packets"),
[](FILE* f) {
clog << "Closing hostPackets stream" << endl; clog << "Closing hostPackets stream" << endl;
closeHTML(f); closeHTML(f);
} }; } };
@@ -73,9 +72,10 @@ shared_ptr<FILE> getHostPacketStream()
return stream; return stream;
} }
shared_ptr<FILE> getHostAPDUStream() shared_ptr<FILE> getHostAPDUStream() {
{ static shared_ptr<FILE> stream{ initHTML(fopen(DEBUG_STREAMS "hostAPDU.html", "wb"),
static shared_ptr<FILE> stream{ initHTML(fopen(DEBUG_STREAMS "hostAPDU.html", "wb"), "Host APDU"), [](FILE *f){ "Host APDU"),
[](FILE* f) {
clog << "Closing host APDU stream" << endl; clog << "Closing host APDU stream" << endl;
closeHTML(f); closeHTML(f);
} }; } };
@@ -86,8 +86,7 @@ shared_ptr<FILE> getHostAPDUStream()
return stream; return stream;
} }
shared_ptr<FILE> getComDevStream() shared_ptr<FILE> getComDevStream() {
{
static shared_ptr<FILE> stream{ fopen(DEBUG_STREAMS "comdev.txt", "wb"), [](FILE* f) { static shared_ptr<FILE> stream{ fopen(DEBUG_STREAMS "comdev.txt", "wb"), [](FILE* f) {
clog << "Closing comdev stream" << endl; clog << "Closing comdev stream" << endl;
fclose(f); fclose(f);
@@ -99,9 +98,10 @@ shared_ptr<FILE> getComDevStream()
return stream; return stream;
} }
shared_ptr<FILE> getDevPacketStream() shared_ptr<FILE> getDevPacketStream() {
{ static shared_ptr<FILE> stream{ initHTML(fopen(DEBUG_STREAMS "devpackets.html", "wb"),
static shared_ptr<FILE> stream{ initHTML(fopen(DEBUG_STREAMS "devpackets.html", "wb"), "Dev Packets"), [](FILE *f){ "Dev Packets"),
[](FILE* f) {
clog << "Closing devPackets stream" << endl; clog << "Closing devPackets stream" << endl;
closeHTML(f); closeHTML(f);
} }; } };
@@ -112,9 +112,9 @@ shared_ptr<FILE> getDevPacketStream()
return stream; return stream;
} }
shared_ptr<FILE> getDevAPDUStream() shared_ptr<FILE> getDevAPDUStream() {
{ static shared_ptr<FILE> stream{ initHTML(fopen(DEBUG_STREAMS "devAPDU.html", "wb"), "Dev APDU"),
static shared_ptr<FILE> stream{ initHTML(fopen(DEBUG_STREAMS "devAPDU.html", "wb"), "Dev APDU"), [](FILE *f){ [](FILE* f) {
clog << "Closing dev APDU stream" << endl; clog << "Closing dev APDU stream" << endl;
closeHTML(f); closeHTML(f);
} }; } };
@@ -125,9 +125,9 @@ shared_ptr<FILE> getDevAPDUStream()
return stream; return stream;
} }
FILE* initHTML(FILE *fPtr, const string &title) FILE* initHTML(FILE* fPtr, const string& title) {
{ fprintf(fPtr,
fprintf(fPtr, "<html>\n" "<html>\n"
"\t<head>\n" "\t<head>\n"
"\t\t<title>%s</title>\n" "\t\t<title>%s</title>\n"
"\t\t<style>\n" "\t\t<style>\n"
@@ -164,13 +164,13 @@ FILE* initHTML(FILE *fPtr, const string &title)
"\t\t</style>\n" "\t\t</style>\n"
"\t</head>\n" "\t</head>\n"
"\n" "\n"
"\t<body>", title.c_str()); "\t<body>",
title.c_str());
return fPtr; return fPtr;
} }
void closeHTML(FILE *fPtr) void closeHTML(FILE* fPtr) {
{
fprintf(fPtr, "\t</body>\n" fprintf(fPtr, "\t</body>\n"
"</html>"); "</html>");
fclose(fPtr); fclose(fPtr);

View File

@@ -17,9 +17,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "Architecture.hpp"
#include <cstdio> #include <cstdio>
#include <memory> #include <memory>
#include "Architecture.hpp"
std::shared_ptr<int> getHostDescriptor(); std::shared_ptr<int> getHostDescriptor();

View File

@@ -17,10 +17,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include "Architecture.hpp" #include "Architecture.hpp"
#include <iostream>
#include "Storage.hpp"
#include "Controller.hpp" #include "Controller.hpp"
#include "LED.hpp" #include "LED.hpp"
#include "Storage.hpp"
#include <iostream>
#include <signal.h> #include <signal.h>
#include <unistd.h> #include <unistd.h>
@@ -31,13 +31,10 @@ void signalCallback(int signum);
volatile bool contProc = true; volatile bool contProc = true;
bool initialiseLights(const string& prog) { bool initialiseLights(const string& prog) {
try try {
{
disableACTTrigger(true); disableACTTrigger(true);
enableACTLED(false); enableACTLED(false);
} } catch (runtime_error& e) {
catch (runtime_error &e)
{
cerr << e.what() << endl; cerr << e.what() << endl;
if (getuid() != 0) if (getuid() != 0)
@@ -49,20 +46,15 @@ bool initialiseLights(const string& prog) {
return true; return true;
} }
int handleTransactions(const string& prog, const string& privKeyDir) int handleTransactions(const string& prog, const string& privKeyDir) {
{
signal(SIGINT, signalCallback); signal(SIGINT, signalCallback);
Storage::init(privKeyDir); Storage::init(privKeyDir);
Controller ch{ 0xF1D00000 }; Controller ch{ 0xF1D00000 };
while (contProc) while (contProc) {
{ try {
try
{
ch.handleTransaction(); ch.handleTransaction();
} } catch (const runtime_error& e) {
catch (const runtime_error &e)
{
cerr << e.what() << endl; cerr << e.what() << endl;
if (getuid() != 0) if (getuid() != 0)
@@ -79,13 +71,10 @@ int handleTransactions(const string& prog, const string& privKeyDir)
} }
bool deinitialiseLights(const string& prog) { bool deinitialiseLights(const string& prog) {
try try {
{
disableACTTrigger(false); disableACTTrigger(false);
enableACTLED(true); enableACTLED(true);
} } catch (runtime_error& e) {
catch (runtime_error &e)
{
cerr << e.what() << endl; cerr << e.what() << endl;
if (getuid() != 0) if (getuid() != 0)
@@ -97,8 +86,7 @@ bool deinitialiseLights(const string& prog) {
return true; return true;
} }
void signalCallback([[maybe_unused]] int signum) void signalCallback([[maybe_unused]] int signum) {
{
contProc = false; contProc = false;
clog << "\nClosing" << endl; clog << "\nClosing" << endl;
} }

View File

@@ -24,4 +24,3 @@ extern volatile bool contProc;
bool initialiseLights(const std::string& prog); bool initialiseLights(const std::string& prog);
bool deinitialiseLights(const std::string& prog); bool deinitialiseLights(const std::string& prog);
int handleTransactions(const std::string& prog, const std::string& privKeyDir); int handleTransactions(const std::string& prog, const std::string& privKeyDir);

View File

@@ -17,18 +17,17 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include "U2FMessage.hpp" #include "U2FMessage.hpp"
#include "IO.hpp"
#include "Packet.hpp" #include "Packet.hpp"
#include <stdexcept>
#include <iostream>
#include <iomanip>
#include "Streams.hpp" #include "Streams.hpp"
#include "u2f.hpp" #include "u2f.hpp"
#include "IO.hpp" #include <iomanip>
#include <iostream>
#include <stdexcept>
using namespace std; using namespace std;
shared_ptr<U2FMessage> U2FMessage::readNonBlock() shared_ptr<U2FMessage> U2FMessage::readNonBlock() {
{
const static size_t startSeq = (size_t)-1ull; const static size_t startSeq = (size_t)-1ull;
static size_t currSeq = startSeq; static size_t currSeq = startSeq;
static uint16_t messageSize; static uint16_t messageSize;
@@ -38,16 +37,14 @@ shared_ptr<U2FMessage> U2FMessage::readNonBlock()
shared_ptr<Packet> p{}; shared_ptr<Packet> p{};
if (currSeq == startSeq) if (currSeq == startSeq) {
{
cid = 0; cid = 0;
cmd = 0; cmd = 0;
messageSize = 0; messageSize = 0;
dataBytes = {}; dataBytes = {};
shared_ptr<InitPacket> initPack{}; shared_ptr<InitPacket> initPack{};
do do {
{
p = Packet::getPacket(); p = Packet::getPacket();
if (!p) if (!p)
@@ -62,16 +59,19 @@ shared_ptr<U2FMessage> U2FMessage::readNonBlock()
} while (!initPack); // Spurious cont. packet - spec states ignore } while (!initPack); // Spurious cont. packet - spec states ignore
messageSize = ((static_cast<uint16_t>(initPack->bcnth) << 8u) + initPack->bcntl); messageSize = ((static_cast<uint16_t>(initPack->bcnth) << 8u) + initPack->bcntl);
const uint16_t copyByteCount = min(static_cast<uint16_t>(initPack->data.size()), messageSize); const uint16_t copyByteCount =
min(static_cast<uint16_t>(initPack->data.size()), messageSize);
cid = initPack->cid; cid = initPack->cid;
cmd = initPack->cmd; cmd = initPack->cmd;
copy(initPack->data.begin(), initPack->data.begin() + copyByteCount, back_inserter(dataBytes)); copy(initPack->data.begin(), initPack->data.begin() + copyByteCount,
back_inserter(dataBytes));
currSeq = 0; currSeq = 0;
} }
while (messageSize > dataBytes.size() && static_cast<bool>(p = Packet::getPacket())) //While there is a packet while (messageSize > dataBytes.size() &&
static_cast<bool>(p = Packet::getPacket())) // While there is a packet
{ {
auto contPack = dynamic_pointer_cast<ContPacket>(p); auto contPack = dynamic_pointer_cast<ContPacket>(p);
@@ -87,15 +87,15 @@ shared_ptr<U2FMessage> U2FMessage::readNonBlock()
if (contPack->cid != cid) // Cont. packet of different CID if (contPack->cid != cid) // Cont. packet of different CID
{ {
#ifdef DEBUG_MSGS #ifdef DEBUG_MSGS
cerr << "Invalid CID: was handling channel 0x" << hex << cid << " and received packet from channel 0x" << contPack->cid << dec << endl; cerr << "Invalid CID: was handling channel 0x" << hex << cid
<< " and received packet from channel 0x" << contPack->cid << dec << endl;
#endif #endif
U2FMessage::error(contPack->cid, ERR_CHANNEL_BUSY); U2FMessage::error(contPack->cid, ERR_CHANNEL_BUSY);
currSeq = startSeq; currSeq = startSeq;
return {}; return {};
} }
if (contPack->seq != currSeq) if (contPack->seq != currSeq) {
{
#ifdef DEBUG_MSGS #ifdef DEBUG_MSGS
cerr << "Invalid packet seq. value" << endl; cerr << "Invalid packet seq. value" << endl;
#endif #endif
@@ -105,15 +105,18 @@ shared_ptr<U2FMessage> U2FMessage::readNonBlock()
} }
const uint16_t remainingBytes = messageSize - dataBytes.size(); const uint16_t remainingBytes = messageSize - dataBytes.size();
const uint16_t copyBytes = min(static_cast<uint16_t>(contPack->data.size()), remainingBytes); const uint16_t copyBytes =
min(static_cast<uint16_t>(contPack->data.size()), remainingBytes);
dataBytes.insert(dataBytes.end(), contPack->data.begin(), contPack->data.begin() + copyBytes); dataBytes.insert(dataBytes.end(), contPack->data.begin(),
contPack->data.begin() + copyBytes);
currSeq++; currSeq++;
} }
if (messageSize != dataBytes.size()) { if (messageSize != dataBytes.size()) {
#ifdef DEBUG_MSGS #ifdef DEBUG_MSGS
cerr << "Invalid message size: " << messageSize << " when received " << dataBytes.size() << endl; cerr << "Invalid message size: " << messageSize << " when received " << dataBytes.size()
<< endl;
#endif #endif
return {}; return {};
} }
@@ -125,8 +128,7 @@ shared_ptr<U2FMessage> U2FMessage::readNonBlock()
return message; return message;
} }
void U2FMessage::write() void U2FMessage::write() {
{
const uint16_t bytesToWrite = this->data.size(); const uint16_t bytesToWrite = this->data.size();
uint16_t bytesWritten = 0; uint16_t bytesWritten = 0;
@@ -141,7 +143,8 @@ void U2FMessage::write()
p.bcntl = bcntl; p.bcntl = bcntl;
{ {
uint16_t initialByteCount = min(static_cast<uint16_t>(p.data.size()), static_cast<uint16_t>(bytesToWrite - bytesWritten)); uint16_t initialByteCount = min(static_cast<uint16_t>(p.data.size()),
static_cast<uint16_t>(bytesToWrite - bytesWritten));
copy(data.begin(), data.begin() + initialByteCount, p.data.begin()); copy(data.begin(), data.begin() + initialByteCount, p.data.begin());
bytesWritten += initialByteCount; bytesWritten += initialByteCount;
} }
@@ -151,20 +154,20 @@ void U2FMessage::write()
uint8_t seq = 0; uint8_t seq = 0;
while (bytesWritten != bytesToWrite) while (bytesWritten != bytesToWrite) {
{
ContPacket p{}; ContPacket p{};
p.cid = cid; p.cid = cid;
p.seq = seq; p.seq = seq;
uint16_t newByteCount = min(static_cast<uint16_t>(p.data.size()), static_cast<uint16_t>(bytesToWrite - bytesWritten)); uint16_t newByteCount = min(static_cast<uint16_t>(p.data.size()),
copy(data.begin() + bytesWritten, data.begin() + bytesWritten + newByteCount, p.data.begin()); static_cast<uint16_t>(bytesToWrite - bytesWritten));
copy(data.begin() + bytesWritten, data.begin() + bytesWritten + newByteCount,
p.data.begin());
p.writePacket(); p.writePacket();
seq++; seq++;
bytesWritten += newByteCount; bytesWritten += newByteCount;
} }
if (cmd == U2FHID_MSG) if (cmd == U2FHID_MSG) {
{
#ifdef DEBUG_STREAMS #ifdef DEBUG_STREAMS
auto dAS = getDevAPDUStream().get(); auto dAS = getDevAPDUStream().get();
@@ -187,22 +190,21 @@ void U2FMessage::write()
err |= data.back(); err |= data.back();
#ifdef DEBUG_STREAMS #ifdef DEBUG_STREAMS
fprintf(dAS, "</td>\n" fprintf(dAS,
"</td>\n"
"\t\t\t\t\t<td>0x%04X</td>\n" "\t\t\t\t\t<td>0x%04X</td>\n"
"\t\t\t\t</tr>\n" "\t\t\t\t</tr>\n"
"\t\t\t</tbody>\n" "\t\t\t</tbody>\n"
"\t\t</table>\n" "\t\t</table>\n"
"\t\t<br />", err); "\t\t<br />",
err);
#endif #endif
} }
} }
U2FMessage::U2FMessage(const uint32_t nCID, const uint8_t nCMD) U2FMessage::U2FMessage(const uint32_t nCID, const uint8_t nCMD) : cid{ nCID }, cmd{ nCMD } {}
: cid{ nCID }, cmd{ nCMD }
{}
void U2FMessage::error(const uint32_t tCID, const uint8_t tErr) void U2FMessage::error(const uint32_t tCID, const uint8_t tErr) {
{
U2FMessage msg{}; U2FMessage msg{};
msg.cid = tCID; msg.cid = tCID;
msg.cmd = U2FHID_ERROR; msg.cmd = U2FHID_ERROR;

View File

@@ -18,12 +18,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <vector>
#include <memory> #include <memory>
#include <cstdint> #include <vector>
struct U2FMessage struct U2FMessage {
{
public: public:
uint32_t cid; uint32_t cid;
uint8_t cmd; uint8_t cmd;

View File

@@ -17,28 +17,24 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include "U2F_Authenticate_APDU.hpp" #include "U2F_Authenticate_APDU.hpp"
#include "Field.hpp"
#include "U2FMessage.hpp"
#include "u2f.hpp"
#include "Field.tpp"
#include "APDU.hpp" #include "APDU.hpp"
#include <iostream> #include "Field.hpp"
#include "Field.tpp"
#include "Signature.hpp" #include "Signature.hpp"
#include "U2FMessage.hpp"
#include "micro-ecc/uECC.h" #include "micro-ecc/uECC.h"
#include "u2f.hpp"
#include <iostream>
#include <mbedtls/sha256.h> #include <mbedtls/sha256.h>
using namespace std; using namespace std;
U2F_Authenticate_APDU::U2F_Authenticate_APDU(const U2F_Msg_CMD& msg, const vector<uint8_t>& data) U2F_Authenticate_APDU::U2F_Authenticate_APDU(const U2F_Msg_CMD& msg, const vector<uint8_t>& data)
: U2F_Msg_CMD{ msg } : U2F_Msg_CMD{ msg } {
{ if (p2 != 0) {
if (p2 != 0)
{
// Invalid U2F (APDU) parameter detected // Invalid U2F (APDU) parameter detected
throw APDU_STATUS::SW_CONDITIONS_NOT_SATISFIED; throw APDU_STATUS::SW_CONDITIONS_NOT_SATISFIED;
} } else if (data.size() < 66) {
else if (data.size() < 66)
{
// Invalid authentication request // Invalid authentication request
throw APDU_STATUS::SW_WRONG_LENGTH; throw APDU_STATUS::SW_WRONG_LENGTH;
} }
@@ -51,10 +47,8 @@ U2F_Authenticate_APDU::U2F_Authenticate_APDU(const U2F_Msg_CMD &msg, const vecto
copy(data.begin() + 65, data.begin() + 65 + keyHLen, back_inserter(keyH)); copy(data.begin() + 65, data.begin() + 65 + keyHLen, back_inserter(keyH));
} }
void U2F_Authenticate_APDU::respond(const uint32_t channelID) const void U2F_Authenticate_APDU::respond(const uint32_t channelID) const {
{ if (keyH.size() != sizeof(Storage::KeyHandle)) {
if (keyH.size() != sizeof(Storage::KeyHandle))
{
// Respond with error code - key handle is of wrong size // Respond with error code - key handle is of wrong size
cerr << "Invalid key handle length" << endl; cerr << "Invalid key handle length" << endl;
this->error(channelID, APDU_STATUS::SW_WRONG_DATA); this->error(channelID, APDU_STATUS::SW_WRONG_DATA);
@@ -63,8 +57,7 @@ void U2F_Authenticate_APDU::respond(const uint32_t channelID) const
auto keyHB = *reinterpret_cast<const Storage::KeyHandle*>(keyH.data()); auto keyHB = *reinterpret_cast<const Storage::KeyHandle*>(keyH.data());
if (Storage::appParams.find(keyHB) == Storage::appParams.end()) if (Storage::appParams.find(keyHB) == Storage::appParams.end()) {
{
// Respond with error code - key handle doesn't exist in storage // Respond with error code - key handle doesn't exist in storage
cerr << "Invalid key handle" << endl; cerr << "Invalid key handle" << endl;
this->error(channelID, SW_WRONG_DATA); this->error(channelID, SW_WRONG_DATA);
@@ -80,8 +73,7 @@ void U2F_Authenticate_APDU::respond(const uint32_t channelID) const
auto& response = msg.data; auto& response = msg.data;
APDU_STATUS statusCode = APDU_STATUS::SW_NO_ERROR; APDU_STATUS statusCode = APDU_STATUS::SW_NO_ERROR;
switch (p1) switch (p1) {
{
case ControlCode::CheckOnly: case ControlCode::CheckOnly:
if (appMatches) if (appMatches)
statusCode = APDU_STATUS::SW_CONDITIONS_NOT_SATISFIED; statusCode = APDU_STATUS::SW_CONDITIONS_NOT_SATISFIED;
@@ -117,7 +109,8 @@ void U2F_Authenticate_APDU::respond(const uint32_t channelID) const
mbedtls_sha256_init(&shaContext); mbedtls_sha256_init(&shaContext);
mbedtls_sha256_starts(&shaContext, 0); mbedtls_sha256_starts(&shaContext, 0);
mbedtls_sha256_update(&shaContext, reinterpret_cast<const uint8_t *>(appParam.data()), sizeof(appParam)); mbedtls_sha256_update(&shaContext, reinterpret_cast<const uint8_t*>(appParam.data()),
sizeof(appParam));
uint8_t userPresence{ 1u }; uint8_t userPresence{ 1u };
mbedtls_sha256_update(&shaContext, &userPresence, 1); mbedtls_sha256_update(&shaContext, &userPresence, 1);
const auto beCounter = beEncode(keyCount); const auto beCounter = beEncode(keyCount);

View File

@@ -17,11 +17,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "U2F_Msg_CMD.hpp"
#include "Storage.hpp" #include "Storage.hpp"
#include "U2F_Msg_CMD.hpp"
struct U2F_Authenticate_APDU : U2F_Msg_CMD struct U2F_Authenticate_APDU : U2F_Msg_CMD {
{
uint8_t controlByte; uint8_t controlByte;
std::array<uint8_t, 32> challengeP; std::array<uint8_t, 32> challengeP;
Storage::AppParam appParam; Storage::AppParam appParam;
@@ -32,8 +31,7 @@ struct U2F_Authenticate_APDU : U2F_Msg_CMD
virtual void respond(const uint32_t channelID) const override; virtual void respond(const uint32_t channelID) const override;
enum ControlCode enum ControlCode {
{
CheckOnly = 0x07, CheckOnly = 0x07,
EnforcePresenceSign = 0x03, EnforcePresenceSign = 0x03,
DontEnforcePresenceSign = 0x08 DontEnforcePresenceSign = 0x08

View File

@@ -17,19 +17,16 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include "U2F_CMD.hpp" #include "U2F_CMD.hpp"
#include "u2f.hpp"
#include "U2F_Msg_CMD.hpp"
#include "U2F_Init_CMD.hpp" #include "U2F_Init_CMD.hpp"
#include "U2F_Msg_CMD.hpp"
#include "U2F_Ping_CMD.hpp" #include "U2F_Ping_CMD.hpp"
#include "u2f.hpp"
using namespace std; using namespace std;
shared_ptr<U2F_CMD> U2F_CMD::get(const shared_ptr<U2FMessage> uMsg) shared_ptr<U2F_CMD> U2F_CMD::get(const shared_ptr<U2FMessage> uMsg) {
{ try {
try switch (uMsg->cmd) {
{
switch (uMsg->cmd)
{
case U2FHID_PING: case U2FHID_PING:
return make_shared<U2F_Ping_CMD>(uMsg); return make_shared<U2F_Ping_CMD>(uMsg);
case U2FHID_MSG: case U2FHID_MSG:
@@ -40,9 +37,7 @@ shared_ptr<U2F_CMD> U2F_CMD::get(const shared_ptr<U2FMessage> uMsg)
U2FMessage::error(uMsg->cid, ERR_INVALID_CMD); U2FMessage::error(uMsg->cid, ERR_INVALID_CMD);
return {}; return {};
} }
} } catch (runtime_error& ignored) {
catch (runtime_error& ignored)
{
U2FMessage::error(uMsg->cid, ERR_OTHER); U2FMessage::error(uMsg->cid, ERR_OTHER);
return {}; return {};
} }

View File

@@ -17,11 +17,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include <memory>
#include "U2FMessage.hpp" #include "U2FMessage.hpp"
#include <memory>
struct U2F_CMD struct U2F_CMD {
{
protected: protected:
U2F_CMD() = default; U2F_CMD() = default;

View File

@@ -17,23 +17,19 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include "U2F_Init_CMD.hpp" #include "U2F_Init_CMD.hpp"
#include <stdexcept>
#include "u2f.hpp"
#include "Field.hpp" #include "Field.hpp"
#include "u2f.hpp"
#include <stdexcept>
using namespace std; using namespace std;
U2F_Init_CMD::U2F_Init_CMD(const shared_ptr<U2FMessage> uMsg) U2F_Init_CMD::U2F_Init_CMD(const shared_ptr<U2FMessage> uMsg) {
{
if (uMsg->cmd != U2FHID_INIT) if (uMsg->cmd != U2FHID_INIT)
throw runtime_error{ "Failed to get U2F Init message" }; throw runtime_error{ "Failed to get U2F Init message" };
else if (uMsg->cid != CID_BROADCAST) else if (uMsg->cid != CID_BROADCAST) {
{
U2FMessage::error(uMsg->cid, ERR_OTHER); U2FMessage::error(uMsg->cid, ERR_OTHER);
throw runtime_error{ "Invalid CID for init command" }; throw runtime_error{ "Invalid CID for init command" };
} } else if (uMsg->data.size() != INIT_NONCE_SIZE) {
else if (uMsg->data.size() != INIT_NONCE_SIZE)
{
U2FMessage::error(uMsg->cid, ERR_INVALID_LEN); U2FMessage::error(uMsg->cid, ERR_INVALID_LEN);
throw runtime_error{ "Init nonce is incorrect size" }; throw runtime_error{ "Init nonce is incorrect size" };
} }
@@ -41,8 +37,7 @@ U2F_Init_CMD::U2F_Init_CMD(const shared_ptr<U2FMessage> uMsg)
this->nonce = *reinterpret_cast<const uint64_t*>(uMsg->data.data()); this->nonce = *reinterpret_cast<const uint64_t*>(uMsg->data.data());
} }
void U2F_Init_CMD::respond(const uint32_t channelID) const void U2F_Init_CMD::respond(const uint32_t channelID) const {
{
U2FMessage msg{}; U2FMessage msg{};
msg.cid = CID_BROADCAST; msg.cid = CID_BROADCAST;
msg.cmd = U2FHID_INIT; msg.cmd = U2FHID_INIT;

View File

@@ -17,13 +17,12 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "U2FMessage.hpp"
#include "U2F_CMD.hpp"
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include "U2F_CMD.hpp"
#include "U2FMessage.hpp"
struct U2F_Init_CMD : U2F_CMD struct U2F_Init_CMD : U2F_CMD {
{
uint64_t nonce; uint64_t nonce;
public: public:

View File

@@ -18,26 +18,22 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "U2F_Msg_CMD.hpp" #include "U2F_Msg_CMD.hpp"
#include "APDU.hpp" #include "APDU.hpp"
#include "Field.hpp"
#include "Streams.hpp"
#include "U2FMessage.hpp"
#include "U2F_Authenticate_APDU.hpp"
#include "U2F_Register_APDU.hpp" #include "U2F_Register_APDU.hpp"
#include "U2F_Version_APDU.hpp" #include "U2F_Version_APDU.hpp"
#include "U2F_Authenticate_APDU.hpp"
#include "U2FMessage.hpp"
#include "u2f.hpp" #include "u2f.hpp"
#include "APDU.hpp"
#include <iostream> #include <iostream>
#include "Streams.hpp"
#include "Field.hpp"
using namespace std; using namespace std;
uint32_t U2F_Msg_CMD::getLe(const uint32_t byteCount, vector<uint8_t> bytes) uint32_t U2F_Msg_CMD::getLe(const uint32_t byteCount, vector<uint8_t> bytes) {
{ if (byteCount != 0) {
if (byteCount != 0)
{
// Le must be length of data in bytes // Le must be length of data in bytes
switch (byteCount) switch (byteCount) {
{
case 1: case 1:
return (bytes[0] == 0 ? 256 : bytes[0]); return (bytes[0] == 0 ? 256 : bytes[0]);
case 2: case 2:
@@ -55,17 +51,14 @@ uint32_t U2F_Msg_CMD::getLe(const uint32_t byteCount, vector<uint8_t> bytes)
default: default:
throw runtime_error{ "Too much data for command" }; throw runtime_error{ "Too much data for command" };
} }
} } else
else
return 0; return 0;
} }
shared_ptr<U2F_Msg_CMD> U2F_Msg_CMD::generate(const shared_ptr<U2FMessage> uMsg) shared_ptr<U2F_Msg_CMD> U2F_Msg_CMD::generate(const shared_ptr<U2FMessage> uMsg) {
{
if (uMsg->cmd != U2FHID_MSG) if (uMsg->cmd != U2FHID_MSG)
throw runtime_error{ "Failed to get U2F Msg uMsg" }; throw runtime_error{ "Failed to get U2F Msg uMsg" };
else if (uMsg->data.size() < 4) else if (uMsg->data.size() < 4) {
{
U2F_Msg_CMD::error(uMsg->cid, APDU_STATUS::SW_WRONG_LENGTH); U2F_Msg_CMD::error(uMsg->cid, APDU_STATUS::SW_WRONG_LENGTH);
throw runtime_error{ "Msg data is incorrect size" }; throw runtime_error{ "Msg data is incorrect size" };
} }
@@ -75,8 +68,7 @@ shared_ptr<U2F_Msg_CMD> U2F_Msg_CMD::generate(const shared_ptr<U2FMessage> uMsg)
cmd.cla = dat[0]; cmd.cla = dat[0];
if (cmd.cla != 0) if (cmd.cla != 0) {
{
U2F_Msg_CMD::error(uMsg->cid, APDU_STATUS::SW_COMMAND_NOT_ALLOWED); U2F_Msg_CMD::error(uMsg->cid, APDU_STATUS::SW_COMMAND_NOT_ALLOWED);
throw runtime_error{ "Invalid CLA value in U2F Message" }; throw runtime_error{ "Invalid CLA value in U2F Message" };
} }
@@ -89,10 +81,8 @@ shared_ptr<U2F_Msg_CMD> U2F_Msg_CMD::generate(const shared_ptr<U2FMessage> uMsg)
const uint32_t cBCount = data.size(); const uint32_t cBCount = data.size();
auto startPtr = data.begin(), endPtr = data.end(); auto startPtr = data.begin(), endPtr = data.end();
if (usesData.at(cmd.ins) || data.size() > 3) if (usesData.at(cmd.ins) || data.size() > 3) {
{ if (cBCount == 0) {
if (cBCount == 0)
{
U2F_Msg_CMD::error(uMsg->cid, APDU_STATUS::SW_WRONG_LENGTH); U2F_Msg_CMD::error(uMsg->cid, APDU_STATUS::SW_WRONG_LENGTH);
throw runtime_error{ "Invalid command - should have attached data" }; throw runtime_error{ "Invalid command - should have attached data" };
} }
@@ -101,36 +91,26 @@ shared_ptr<U2F_Msg_CMD> U2F_Msg_CMD::generate(const shared_ptr<U2FMessage> uMsg)
{ {
cmd.lc = data[0]; cmd.lc = data[0];
startPtr++; startPtr++;
} } else {
else
{
cmd.lc = (data[1] << 8) + data[2]; cmd.lc = (data[1] << 8) + data[2];
startPtr += 3; startPtr += 3;
} }
endPtr = startPtr + cmd.lc; endPtr = startPtr + cmd.lc;
try try {
{
cmd.le = getLe(data.end() - endPtr, vector<uint8_t>(endPtr, data.end())); cmd.le = getLe(data.end() - endPtr, vector<uint8_t>(endPtr, data.end()));
} } catch (runtime_error& ignored) {
catch (runtime_error& ignored)
{
U2F_Msg_CMD::error(uMsg->cid, APDU_STATUS::SW_WRONG_LENGTH); U2F_Msg_CMD::error(uMsg->cid, APDU_STATUS::SW_WRONG_LENGTH);
throw; throw;
} }
} } else {
else
{
cmd.lc = 0; cmd.lc = 0;
endPtr = startPtr; endPtr = startPtr;
try try {
{
cmd.le = getLe(cBCount, data); cmd.le = getLe(cBCount, data);
} } catch (runtime_error& ignored) {
catch (runtime_error& ignored)
{
U2F_Msg_CMD::error(uMsg->cid, APDU_STATUS::SW_WRONG_LENGTH); U2F_Msg_CMD::error(uMsg->cid, APDU_STATUS::SW_WRONG_LENGTH);
throw; throw;
} }
@@ -141,7 +121,8 @@ shared_ptr<U2F_Msg_CMD> U2F_Msg_CMD::generate(const shared_ptr<U2FMessage> uMsg)
#ifdef DEBUG_STREAMS #ifdef DEBUG_STREAMS
auto hAS = getHostAPDUStream().get(); auto hAS = getHostAPDUStream().get();
fprintf(hAS, "<table>\n" fprintf(hAS,
"<table>\n"
"\t\t\t<thead>\n" "\t\t\t<thead>\n"
"\t\t\t\t<tr>\n" "\t\t\t\t<tr>\n"
"\t\t\t\t\t<th>CLA</th>\n" "\t\t\t\t\t<th>CLA</th>\n"
@@ -160,23 +141,24 @@ shared_ptr<U2F_Msg_CMD> U2F_Msg_CMD::generate(const shared_ptr<U2FMessage> uMsg)
"\t\t\t\t\t<td>%u</td>\n" "\t\t\t\t\t<td>%u</td>\n"
"\t\t\t\t\t<td>%u</td>\n" "\t\t\t\t\t<td>%u</td>\n"
"\t\t\t\t\t<td>%3u</td>\n" "\t\t\t\t\t<td>%3u</td>\n"
"\t\t\t\t\t<td class=\"data\">", cmd.cla, cmd.ins, cmd.p1, cmd.p2, cmd.lc); "\t\t\t\t\t<td class=\"data\">",
cmd.cla, cmd.ins, cmd.p1, cmd.p2, cmd.lc);
for (auto b : dBytes) for (auto b : dBytes)
fprintf(hAS, "%3u ", b); fprintf(hAS, "%3u ", b);
fprintf(hAS, "</td>\n" fprintf(hAS,
"</td>\n"
"\t\t\t\t\t<td>%5u</td>\n" "\t\t\t\t\t<td>%5u</td>\n"
"\t\t\t\t</tr>\n" "\t\t\t\t</tr>\n"
"\t\t\t</tbody>\n" "\t\t\t</tbody>\n"
"\t\t</table>\n" "\t\t</table>\n"
"\t\t<br />", cmd.le); "\t\t<br />",
cmd.le);
#endif #endif
try try {
{ switch (cmd.ins) {
switch (cmd.ins)
{
case APDU::U2F_REG: case APDU::U2F_REG:
return make_shared<U2F_Register_APDU>(cmd, dBytes); return make_shared<U2F_Register_APDU>(cmd, dBytes);
case APDU::U2F_AUTH: case APDU::U2F_AUTH:
@@ -187,17 +169,14 @@ shared_ptr<U2F_Msg_CMD> U2F_Msg_CMD::generate(const shared_ptr<U2FMessage> uMsg)
cerr << "Invalid command used" << endl; cerr << "Invalid command used" << endl;
throw APDU_STATUS::SW_INS_NOT_SUPPORTED; throw APDU_STATUS::SW_INS_NOT_SUPPORTED;
} }
} } catch (const APDU_STATUS e) {
catch (const APDU_STATUS e)
{
U2F_Msg_CMD::error(uMsg->cid, e); U2F_Msg_CMD::error(uMsg->cid, e);
throw runtime_error{ "APDU construction error" }; throw runtime_error{ "APDU construction error" };
return {}; return {};
} }
} }
void U2F_Msg_CMD::error(const uint32_t channelID, const uint16_t errCode) void U2F_Msg_CMD::error(const uint32_t channelID, const uint16_t errCode) {
{
clog << "U2F_Msg_CMD::error " << errCode << endl; clog << "U2F_Msg_CMD::error " << errCode << endl;
U2FMessage msg{}; U2FMessage msg{};
msg.cid = channelID; msg.cid = channelID;
@@ -206,13 +185,10 @@ void U2F_Msg_CMD::error(const uint32_t channelID, const uint16_t errCode)
msg.write(); msg.write();
} }
const map<uint8_t, bool> U2F_Msg_CMD::usesData = { const map<uint8_t, bool> U2F_Msg_CMD::usesData = { { U2F_REG, true },
{ U2F_REG, true },
{ U2F_AUTH, true }, { U2F_AUTH, true },
{ U2F_VER, false } { U2F_VER, false } };
};
void U2F_Msg_CMD::respond(const uint32_t channelID) const void U2F_Msg_CMD::respond(const uint32_t channelID) const {
{
U2F_Msg_CMD::error(channelID, static_cast<uint16_t>(APDU_STATUS::SW_INS_NOT_SUPPORTED)); U2F_Msg_CMD::error(channelID, static_cast<uint16_t>(APDU_STATUS::SW_INS_NOT_SUPPORTED));
} }

View File

@@ -20,11 +20,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "U2F_CMD.hpp" #include "U2F_CMD.hpp"
#include <cstdint> #include <cstdint>
#include <map> #include <map>
#include <vector>
#include <memory> #include <memory>
#include <vector>
struct U2F_Msg_CMD : U2F_CMD struct U2F_Msg_CMD : U2F_CMD {
{
uint8_t cla; uint8_t cla;
uint8_t ins; uint8_t ins;
uint8_t p1; uint8_t p1;
@@ -43,4 +42,3 @@ struct U2F_Msg_CMD : U2F_CMD
static void error(const uint32_t channelID, const uint16_t errCode); static void error(const uint32_t channelID, const uint16_t errCode);
void respond(const uint32_t channelID) const; void respond(const uint32_t channelID) const;
}; };

View File

@@ -21,15 +21,12 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
using namespace std; using namespace std;
U2F_Ping_CMD::U2F_Ping_CMD(const shared_ptr<U2FMessage> uMsg) U2F_Ping_CMD::U2F_Ping_CMD(const shared_ptr<U2FMessage> uMsg) : nonce{ uMsg->data } {
: nonce{ uMsg->data }
{
if (uMsg->cmd != U2FHID_PING) if (uMsg->cmd != U2FHID_PING)
throw runtime_error{ "Failed to get U2F ping message" }; throw runtime_error{ "Failed to get U2F ping message" };
} }
void U2F_Ping_CMD::respond(const uint32_t channelID) const void U2F_Ping_CMD::respond(const uint32_t channelID) const {
{
U2FMessage msg{}; U2FMessage msg{};
msg.cid = channelID; msg.cid = channelID;
msg.cmd = U2FHID_PING; msg.cmd = U2FHID_PING;

View File

@@ -17,13 +17,12 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "U2FMessage.hpp"
#include "U2F_CMD.hpp"
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include "U2F_CMD.hpp"
#include "U2FMessage.hpp"
struct U2F_Ping_CMD : U2F_CMD struct U2F_Ping_CMD : U2F_CMD {
{
std::vector<uint8_t> nonce; std::vector<uint8_t> nonce;
public: public:

View File

@@ -17,28 +17,25 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include "U2F_Register_APDU.hpp" #include "U2F_Register_APDU.hpp"
#include <exception>
#include <cstring>
#include "micro-ecc/uECC.h"
#include "Certificates.hpp"
#include <mbedtls/sha256.h>
#include <iostream>
#include "APDU.hpp" #include "APDU.hpp"
#include "U2FMessage.hpp" #include "Certificates.hpp"
#include "u2f.hpp"
#include "Signature.hpp" #include "Signature.hpp"
#include "U2FMessage.hpp"
#include "micro-ecc/uECC.h"
#include "u2f.hpp"
#include <cstring>
#include <exception>
#include <iostream>
#include <mbedtls/sha256.h>
using namespace std; using namespace std;
U2F_Register_APDU::U2F_Register_APDU(const U2F_Msg_CMD& msg, const vector<uint8_t>& data) U2F_Register_APDU::U2F_Register_APDU(const U2F_Msg_CMD& msg, const vector<uint8_t>& data)
: U2F_Msg_CMD{ msg } : U2F_Msg_CMD{ msg } {
{ if (data.size() != 64) {
if (data.size() != 64)
{
// Incorrect registration size // Incorrect registration size
throw APDU_STATUS::SW_WRONG_LENGTH; throw APDU_STATUS::SW_WRONG_LENGTH;
} } else if ((p1 != 0x00 && p1 != 0x03) || p2 != 0x00) // According to spec, 0x03 not allowed here
else if ((p1 != 0x00 && p1 != 0x03) || p2 != 0x00) //According to spec, 0x03 not allowed here
// However, browsers seem to do it, so... // However, browsers seem to do it, so...
{ {
// Invalid U2F Message (APDU) parameters detected // Invalid U2F Message (APDU) parameters detected
@@ -64,8 +61,7 @@ U2F_Register_APDU::U2F_Register_APDU(const U2F_Msg_CMD &msg, const vector<uint8_
Storage::keyCounts[this->keyH] = 0; Storage::keyCounts[this->keyH] = 0;
} }
void U2F_Register_APDU::respond(const uint32_t channelID) const void U2F_Register_APDU::respond(const uint32_t channelID) const {
{
U2FMessage m{}; U2FMessage m{};
m.cid = channelID; m.cid = channelID;
m.cmd = U2FHID_MSG; m.cmd = U2FHID_MSG;
@@ -94,13 +90,18 @@ void U2F_Register_APDU::respond(const uint32_t channelID) const
uint8_t byteReserved = 0; uint8_t byteReserved = 0;
mbedtls_sha256_update(&shaContext, reinterpret_cast<unsigned char*>(&byteReserved), 1); mbedtls_sha256_update(&shaContext, reinterpret_cast<unsigned char*>(&byteReserved), 1);
mbedtls_sha256_update(&shaContext, reinterpret_cast<const unsigned char*>(appParam.data()), appParam.size()); mbedtls_sha256_update(&shaContext, reinterpret_cast<const unsigned char*>(appParam.data()),
appParam.size());
mbedtls_sha256_update(&shaContext, reinterpret_cast<const unsigned char*>(challengeP.data()), challengeP.size()); mbedtls_sha256_update(&shaContext,
reinterpret_cast<const unsigned char*>(challengeP.data()),
challengeP.size());
mbedtls_sha256_update(&shaContext, reinterpret_cast<const unsigned char*>(&keyH), sizeof(keyH)); mbedtls_sha256_update(&shaContext, reinterpret_cast<const unsigned char*>(&keyH),
sizeof(keyH));
mbedtls_sha256_update(&shaContext, reinterpret_cast<const unsigned char*>(pubKey.data()), pubKey.size()); mbedtls_sha256_update(&shaContext, reinterpret_cast<const unsigned char*>(pubKey.data()),
pubKey.size());
mbedtls_sha256_finish(&shaContext, digest.data()); mbedtls_sha256_finish(&shaContext, digest.data());
mbedtls_sha256_free(&shaContext); mbedtls_sha256_free(&shaContext);

View File

@@ -17,11 +17,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "U2F_Msg_CMD.hpp"
#include "Storage.hpp" #include "Storage.hpp"
#include "U2F_Msg_CMD.hpp"
struct U2F_Register_APDU : U2F_Msg_CMD struct U2F_Register_APDU : U2F_Msg_CMD {
{
std::array<uint8_t, 32> challengeP; std::array<uint8_t, 32> challengeP;
Storage::AppParam appP; Storage::AppParam appP;
Storage::KeyHandle keyH; Storage::KeyHandle keyH;
@@ -31,4 +30,3 @@ struct U2F_Register_APDU : U2F_Msg_CMD
void respond(const uint32_t channelID) const override; void respond(const uint32_t channelID) const override;
}; };

View File

@@ -17,16 +17,15 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include "U2F_Version_APDU.hpp" #include "U2F_Version_APDU.hpp"
#include <iostream> #include "APDU.hpp"
#include "Field.hpp"
#include "U2FMessage.hpp" #include "U2FMessage.hpp"
#include "u2f.hpp" #include "u2f.hpp"
#include "Field.hpp" #include <iostream>
#include "APDU.hpp"
using namespace std; using namespace std;
U2F_Version_APDU::U2F_Version_APDU(const U2F_Msg_CMD &msg, const std::vector<uint8_t> &data) U2F_Version_APDU::U2F_Version_APDU(const U2F_Msg_CMD& msg, const std::vector<uint8_t>& data) {
{
// Don't actually respond yet unless invalid // Don't actually respond yet unless invalid
if (msg.p1 != 0 || msg.p2 != 0) if (msg.p1 != 0 || msg.p2 != 0)
throw APDU_STATUS::SW_INS_NOT_SUPPORTED; throw APDU_STATUS::SW_INS_NOT_SUPPORTED;
@@ -34,8 +33,7 @@ U2F_Version_APDU::U2F_Version_APDU(const U2F_Msg_CMD &msg, const std::vector<uin
throw APDU_STATUS::SW_WRONG_LENGTH; throw APDU_STATUS::SW_WRONG_LENGTH;
} }
void U2F_Version_APDU::respond(const uint32_t channelID) const void U2F_Version_APDU::respond(const uint32_t channelID) const {
{
char ver[]{ 'U', '2', 'F', '_', 'V', '2' }; char ver[]{ 'U', '2', 'F', '_', 'V', '2' };
U2FMessage m{}; U2FMessage m{};

View File

@@ -19,8 +19,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once #pragma once
#include "U2F_Msg_CMD.hpp" #include "U2F_Msg_CMD.hpp"
struct U2F_Version_APDU : U2F_Msg_CMD struct U2F_Version_APDU : U2F_Msg_CMD {
{
public: public:
U2F_Version_APDU(const U2F_Msg_CMD& msg, const std::vector<uint8_t>& data); U2F_Version_APDU(const U2F_Msg_CMD& msg, const std::vector<uint8_t>& data);
void respond(const uint32_t channelID) const override; void respond(const uint32_t channelID) const override;

View File

@@ -1,17 +1,15 @@
#include "U2FDevice.hpp"
#include "Architecture.hpp" #include "Architecture.hpp"
#include "U2FDevice.hpp"
#include <execinfo.h> #include <execinfo.h>
#include <iostream> #include <iostream>
#ifdef DEBUG_MSGS #ifdef DEBUG_MSGS
// Courtesy StackOverflow answer https://stackoverflow.com/a/3356421 // Courtesy StackOverflow answer https://stackoverflow.com/a/3356421
void terminateHandler() void terminateHandler() {
{
void* trace_elems[20]; void* trace_elems[20];
int trace_elem_count(backtrace(trace_elems, 20)); int trace_elem_count(backtrace(trace_elems, 20));
char** stack_syms(backtrace_symbols(trace_elems, trace_elem_count)); char** stack_syms(backtrace_symbols(trace_elems, trace_elem_count));
for (int i = 0; i < trace_elem_count; ++i) for (int i = 0; i < trace_elem_count; ++i) {
{
std::cout << stack_syms[i] << "\n"; std::cout << stack_syms[i] << "\n";
} }
free(stack_syms); free(stack_syms);
@@ -26,13 +24,10 @@ int main(int argc, char **argv) {
#endif #endif
int retCode = handleTransactions(argv[0], argc == 2 ? argv[1] : STORAGE_PREFIX); int retCode = handleTransactions(argv[0], argc == 2 ? argv[1] : STORAGE_PREFIX);
try try {
{
initialiseLights(argv[0]); initialiseLights(argv[0]);
deinitialiseLights(argv[0]); deinitialiseLights(argv[0]);
} } catch (std::exception& e) {
catch (std::exception &e)
{
std::cerr << "Exception in code: " << e.what() << std::endl; std::cerr << "Exception in code: " << e.what() << std::endl;
throw; throw;
} }

View File

@@ -124,4 +124,3 @@ typedef struct {
#endif #endif
#endif // __U2FHID_H_INCLUDED__ #endif // __U2FHID_H_INCLUDED__