diff --git a/APDU.hpp b/APDU.hpp index c489b06..7229dbc 100644 --- a/APDU.hpp +++ b/APDU.hpp @@ -9,10 +9,9 @@ enum APDU : uint8_t enum APDU_STATUS : uint16_t { - SW_NO_ERROR = 0x9000, + SW_NO_ERROR = 0x9000, + SW_WRONG_DATA = 0x6A80, SW_CONDITIONS_NOT_SATISFIED = 0x6985, - SW_WRONG_DATA = 0x6A80, - SW_WRONG_LENGTH = 0x6700, - SW_CLA_NOT_SUPPORTED = 0x6E00, - SW_INS_NOT_SUPPORTED = 0x6D00 + SW_COMMAND_NOT_ALLOWED = 0x6986, + SW_INS_NOT_SUPPORTED = 0x6D00 }; diff --git a/U2F_Authenticate_APDU.cpp b/U2F_Authenticate_APDU.cpp index ba1f9d6..3a66f41 100644 --- a/U2F_Authenticate_APDU.cpp +++ b/U2F_Authenticate_APDU.cpp @@ -14,8 +14,16 @@ using namespace std; U2F_Authenticate_APDU::U2F_Authenticate_APDU(const U2F_Msg_CMD &msg, const vector &data) : U2F_Msg_CMD{ msg } { - if (data.size() < 66) - throw runtime_error{ "Invalid authentication request" }; + if (p2 != 0) + { + //Invalid U2F (APDU) parameter detected + throw APDU_STATUS::SW_COMMAND_NOT_ALLOWED; + } + else if (data.size() < 66) + { + //Invalid authentication request + throw APDU_STATUS::SW_WRONG_LENGTH; + } copy(data.begin() + 0, data.begin() + 32, challengeP.begin()); copy(data.begin() + 32, data.begin() + 64, appParam.begin()); @@ -27,20 +35,11 @@ U2F_Authenticate_APDU::U2F_Authenticate_APDU(const U2F_Msg_CMD &msg, const vecto void U2F_Authenticate_APDU::respond(const uint32_t channelID) const { - U2FMessage msg{}; - msg.cid = channelID; - msg.cmd = U2FHID_MSG; - auto statusCode = APDU_STATUS::SW_NO_ERROR; - - auto &response = msg.data; - if (keyH.size() != sizeof(Storage::KeyHandle)) { //Respond with error code - key handle is of wrong size cerr << "Invalid key handle length" << endl; - statusCode = APDU_STATUS::SW_WRONG_DATA; - response.insert(response.end(), FIELD_BE(statusCode)); - msg.write(); + this->error(channelID, APDU_STATUS::SW_WRONG_DATA); return; } @@ -50,14 +49,19 @@ void U2F_Authenticate_APDU::respond(const uint32_t channelID) const { //Respond with error code - key handle doesn't exist in storage cerr << "Invalid key handle" << endl; - statusCode = APDU_STATUS::SW_WRONG_DATA; - response.insert(response.end(), FIELD_BE(statusCode)); - msg.write(); + this->error(channelID, SW_WRONG_DATA); return; } auto appMatches = (Storage::appParams.at(keyHB) == appParam); + U2FMessage msg{}; + msg.cid = channelID; + msg.cmd = U2FHID_MSG; + + auto &response = msg.data; + APDU_STATUS statusCode = APDU_STATUS::SW_NO_ERROR; + switch (p1) { case ControlCode::CheckOnly: @@ -76,10 +80,8 @@ void U2F_Authenticate_APDU::respond(const uint32_t channelID) const break; default: - cerr << "Unknown APDU command" << endl; - statusCode = APDU_STATUS::SW_WRONG_DATA; - response.insert(response.end(), FIELD_BE(statusCode)); - msg.write(); + cerr << "Unknown APDU authentication command" << endl; + this->error(channelID, APDU_STATUS::SW_COMMAND_NOT_ALLOWED); return; } diff --git a/U2F_CMD.cpp b/U2F_CMD.cpp index b50ca80..75c2a59 100644 --- a/U2F_CMD.cpp +++ b/U2F_CMD.cpp @@ -10,7 +10,14 @@ shared_ptr U2F_CMD::get(const shared_ptr uMsg) switch (uMsg->cmd) { case U2FHID_MSG: - return U2F_Msg_CMD::generate(uMsg); + try + { + return U2F_Msg_CMD::generate(uMsg); + } + catch (runtime_error) + { + return {}; + } case U2FHID_INIT: return make_shared(uMsg); default: diff --git a/U2F_Msg_CMD.cpp b/U2F_Msg_CMD.cpp index 68bc375..19084da 100644 --- a/U2F_Msg_CMD.cpp +++ b/U2F_Msg_CMD.cpp @@ -47,12 +47,22 @@ shared_ptr U2F_Msg_CMD::generate(const shared_ptr uMsg) if (uMsg->cmd != U2FHID_MSG) throw runtime_error{ "Failed to get U2F Msg uMsg" }; else if (uMsg->data.size() < 4) + { + U2F_Msg_CMD::error(uMsg->cid, APDU_STATUS::SW_WRONG_LENGTH); throw runtime_error{ "Msg data is incorrect size" }; + } U2F_Msg_CMD cmd; auto &dat = uMsg->data; cmd.cla = dat[0]; + + if (cmd.cla != 0) + { + U2F_Msg_CMD::error(uMsg->cid, APDU_STATUS::SW_COMMAND_NOT_ALLOWED); + throw runtime_error{ "Invalid CLA value in U2F Message" }; + } + cmd.ins = dat[1]; cmd.p1 = dat[2]; cmd.p2 = dat[3]; @@ -64,7 +74,10 @@ shared_ptr U2F_Msg_CMD::generate(const shared_ptr uMsg) if (usesData.at(cmd.ins) || data.size() > 3) { if (cBCount == 0) + { + U2F_Msg_CMD::error(uMsg->cid, APDU_STATUS::SW_WRONG_LENGTH); throw runtime_error{ "Invalid command - should have attached data" }; + } if (data[0] != 0) //1 byte length { @@ -79,14 +92,30 @@ shared_ptr U2F_Msg_CMD::generate(const shared_ptr uMsg) endPtr = startPtr + cmd.lc; - cmd.le = getLe(data.end() - endPtr, vector(endPtr, data.end())); + try + { + cmd.le = getLe(data.end() - endPtr, vector(endPtr, data.end())); + } + catch (runtime_error) + { + U2F_Msg_CMD::error(uMsg->cid, APDU_STATUS::SW_WRONG_LENGTH); + throw; + } } else { cmd.lc = 0; endPtr = startPtr; - cmd.le = getLe(cBCount, data); + try + { + cmd.le = getLe(cBCount, data); + } + catch (runtime_error) + { + U2F_Msg_CMD::error(uMsg->cid, APDU_STATUS::SW_WRONG_LENGTH); + throw; + } } const auto dBytes = vector(startPtr, endPtr); @@ -124,16 +153,25 @@ shared_ptr U2F_Msg_CMD::generate(const shared_ptr uMsg) "\t\t\n" "\t\t
", cmd.le); - switch (cmd.ins) + try { - case APDU::U2F_REG: - return make_shared(cmd, dBytes); - case APDU::U2F_AUTH: - return make_shared(cmd, dBytes); - case APDU::U2F_VER: - return make_shared(cmd); - default: - throw runtime_error{ "Unknown APDU command issued" }; + switch (cmd.ins) + { + case APDU::U2F_REG: + return make_shared(cmd, dBytes); + case APDU::U2F_AUTH: + return make_shared(cmd, dBytes); + case APDU::U2F_VER: + return make_shared(cmd); + default: + cerr << "Invalid command used" << endl; + throw APDU_STATUS::SW_INS_NOT_SUPPORTED; + } + } + catch (const APDU_STATUS e) + { + U2F_Msg_CMD::error(uMsg->cid, e); + throw runtime_error{ "APDU construction error" }; } } diff --git a/U2F_Register_APDU.cpp b/U2F_Register_APDU.cpp index 63d7308..dd095fb 100644 --- a/U2F_Register_APDU.cpp +++ b/U2F_Register_APDU.cpp @@ -16,11 +16,14 @@ U2F_Register_APDU::U2F_Register_APDU(const U2F_Msg_CMD &msg, const vector(ins) << ", p1: " << static_cast(p1) << ", p2: " << static_cast(p2) << endl; - cerr << "Invalid APDU parameters detected" << endl; + //Invalid U2F Message (APDU) parameters detected + throw APDU_STATUS::SW_COMMAND_NOT_ALLOWED; } copy(data.data() + 0, data.data() + 32, challengeP.begin()); @@ -30,7 +33,7 @@ U2F_Register_APDU::U2F_Register_APDU(const U2F_Msg_CMD &msg, const vector