1 /*! 2 * \copyright Copyright (c) 2014-2021 Governikus GmbH & Co. KG, Germany 3 */ 4 5 #include "ResponseApdu.h" 6 7 #include <QLoggingCategory> 8 #include <QtEndian> 9 10 using namespace governikus; 11 Q_DECLARE_LOGGING_CATEGORY(card)12Q_DECLARE_LOGGING_CATEGORY(card) 13 14 ResponseApdu::ResponseApdu(StatusCode pStatusCode) 15 : Apdu(QByteArray()) 16 { 17 char buffer[2]; 18 qToBigEndian<quint16>(Enum<StatusCode>::getValue(pStatusCode), buffer); 19 ResponseApdu::setBuffer(QByteArray(buffer, 2)); 20 } 21 22 ResponseApdu(const QByteArray & pBuffer)23ResponseApdu::ResponseApdu(const QByteArray& pBuffer) 24 : Apdu(pBuffer) 25 { 26 } 27 28 setBuffer(const QByteArray & pBuffer)29void ResponseApdu::setBuffer(const QByteArray& pBuffer) 30 { 31 mBuffer = pBuffer; 32 } 33 34 getData() const35QByteArray ResponseApdu::getData() const 36 { 37 if (length() < RETURN_CODE_LENGTH) 38 { 39 return QByteArray(); 40 } 41 42 return mBuffer.left(getDataLength()); 43 } 44 45 getDataLength() const46int ResponseApdu::getDataLength() const 47 { 48 return length() - RETURN_CODE_LENGTH; 49 } 50 51 getReturnCode() const52StatusCode ResponseApdu::getReturnCode() const 53 { 54 if (mBuffer.isEmpty()) 55 { 56 return StatusCode::EMPTY; 57 } 58 59 const int returnCodeAsInt = getReturnCodeAsHex().toInt(nullptr, 16); 60 return Enum<StatusCode>::isValue(returnCodeAsInt) ? StatusCode(returnCodeAsInt) : StatusCode::INVALID; 61 } 62 63 getReturnCodeAsHex() const64QByteArray ResponseApdu::getReturnCodeAsHex() const 65 { 66 return mBuffer.right(RETURN_CODE_LENGTH).toHex(); 67 } 68 69 getRetryCounter() const70int ResponseApdu::getRetryCounter() const 71 { 72 StatusCode statusCode = getReturnCode(); 73 if (statusCode == StatusCode::SUCCESS) 74 { 75 return 3; 76 } 77 if (statusCode == StatusCode::PIN_RETRY_COUNT_2) 78 { 79 return 2; 80 } 81 if (statusCode == StatusCode::PIN_SUSPENDED) 82 { 83 return 1; 84 } 85 if (statusCode == StatusCode::PIN_BLOCKED || statusCode == StatusCode::PIN_DEACTIVATED) 86 { 87 return 0; 88 } 89 return -1; 90 } 91 92 getSW1() const93SW1 ResponseApdu::getSW1() const 94 { 95 if (length() < RETURN_CODE_LENGTH) 96 { 97 qCCritical(card) << "Buffer too short, returning 0"; 98 return SW1::INVALID; 99 } 100 const char value = mBuffer.at(length() - RETURN_CODE_LENGTH); 101 if (!Enum<SW1>::isValue(value)) 102 { 103 qCCritical(card) << "Unknown SW1 value, returning INVALID, value:" << QString::number(value, 16); 104 return SW1::INVALID; 105 } 106 return SW1(value); 107 } 108 109 getSW2() const110char ResponseApdu::getSW2() const 111 { 112 if (length() < 1) 113 { 114 qCCritical(card) << "Buffer too short, returning 0"; 115 116 return 0; 117 } 118 return mBuffer.at(length() - 1); 119 } 120 121 getCardReturnCode() const122CardReturnCode ResponseApdu::getCardReturnCode() const 123 { 124 switch (getReturnCode()) 125 { 126 case StatusCode::SUCCESS: 127 return CardReturnCode::OK; 128 129 case StatusCode::INPUT_TIMEOUT: 130 return CardReturnCode::INPUT_TIME_OUT; 131 132 case StatusCode::INPUT_CANCELLED: 133 return CardReturnCode::CANCELLATION_BY_USER; 134 135 case StatusCode::PASSWORDS_DIFFER: 136 return CardReturnCode::NEW_PIN_MISMATCH; 137 138 case StatusCode::PASSWORD_OUTOF_RANGE: 139 return CardReturnCode::NEW_PIN_INVALID_LENGTH; 140 141 case StatusCode::PIN_BLOCKED: 142 return CardReturnCode::PIN_BLOCKED; 143 144 default: 145 return CardReturnCode::PROTOCOL_ERROR; 146 } 147 148 Q_UNREACHABLE(); 149 return CardReturnCode::UNDEFINED; 150 } 151 152 153 #include "moc_ResponseApdu.cpp" 154