1 /*!
2  * \copyright Copyright (c) 2017-2021 Governikus GmbH & Co. KG, Germany
3  */
4 
5 
6 #include "IfdStatus.h"
7 
8 #include "AppSettings.h"
9 
10 #include <QLoggingCategory>
11 
12 
13 Q_DECLARE_LOGGING_CATEGORY(remote_device)
14 
15 
16 using namespace governikus;
17 
18 
19 namespace
20 {
21 VALUE_NAME(SLOT_NAME, "SlotName")
22 VALUE_NAME(PIN_CAPABILITIES, "PINCapabilities")
23 VALUE_NAME(PIN_CAP_PACE, "PACE")
24 VALUE_NAME(PIN_CAP_EID, "eID")
25 VALUE_NAME(PIN_CAP_ESIGN, "eSign")
26 VALUE_NAME(PIN_CAP_DESTROY, "Destroy")
27 VALUE_NAME(PIN_PAD, "PINPad")
28 VALUE_NAME(MAX_APDU_LENGTH, "MaxAPDULength")
29 VALUE_NAME(CONNECTED_READER, "ConnectedReader")
30 VALUE_NAME(CARD_AVAILABLE, "CardAvailable")
31 VALUE_NAME(EF_ATR, "EFATR")
32 VALUE_NAME(EF_DIR, "EFDIR")
33 } // namespace
34 
35 
createPaceCapabilities() const36 QJsonValue IfdStatus::createPaceCapabilities() const
37 {
38 	QJsonObject result;
39 	result[PIN_CAP_PACE()] = mHasPinPad;
40 	result[PIN_CAP_EID()] = false;
41 	result[PIN_CAP_ESIGN()] = false;
42 	result[PIN_CAP_DESTROY()] = false;
43 	return result;
44 }
45 
46 
parsePinPad(const QJsonObject & pMessageObject)47 void IfdStatus::parsePinPad(const QJsonObject& pMessageObject)
48 {
49 	const bool v0Supported = IfdVersion(IfdVersion::Version::v0).isSupported();
50 
51 	bool pinPadFound = false;
52 	if (v0Supported && pMessageObject.contains(PIN_CAPABILITIES()))
53 	{
54 		pinPadFound = true;
55 		QJsonValue value = pMessageObject.value(PIN_CAPABILITIES());
56 		if (value.isObject())
57 		{
58 			QJsonObject object = value.toObject();
59 			mHasPinPad = getBoolValue(object, PIN_CAP_PACE());
60 			Q_UNUSED(getBoolValue(object, PIN_CAP_EID()))
61 			Q_UNUSED(getBoolValue(object, PIN_CAP_ESIGN()))
62 			Q_UNUSED(getBoolValue(object, PIN_CAP_DESTROY()))
63 		}
64 		else
65 		{
66 			invalidType(PIN_CAPABILITIES(), QLatin1String("object"));
67 		}
68 	}
69 
70 	if (!v0Supported || pMessageObject.contains(PIN_PAD()))
71 	{
72 		pinPadFound = true;
73 		mHasPinPad = getBoolValue(pMessageObject, PIN_PAD());
74 	}
75 
76 	if (!pinPadFound)
77 	{
78 		missingValue(PIN_CAPABILITIES());
79 		missingValue(PIN_PAD());
80 	}
81 }
82 
83 
IfdStatus(const ReaderInfo & pReaderInfo)84 IfdStatus::IfdStatus(const ReaderInfo& pReaderInfo)
85 	: RemoteMessage(RemoteCardMessageType::IFDStatus)
86 	, mSlotName(pReaderInfo.getName())
87 	, mHasPinPad(pReaderInfo.isBasicReader() ? Env::getSingleton<AppSettings>()->getRemoteServiceSettings().getPinPadMode() : true)
88 	, mMaxApduLength(pReaderInfo.getMaxApduLength())
89 	, mConnectedReader(pReaderInfo.isConnected())
90 	, mCardAvailable(pReaderInfo.hasCard())
91 {
92 }
93 
94 
IfdStatus(const QJsonObject & pMessageObject)95 IfdStatus::IfdStatus(const QJsonObject& pMessageObject)
96 	: RemoteMessage(pMessageObject)
97 	, mSlotName()
98 	, mHasPinPad(false)
99 	, mMaxApduLength(0)
100 	, mConnectedReader(false)
101 	, mCardAvailable(false)
102 {
103 	mSlotName = getStringValue(pMessageObject, SLOT_NAME());
104 	parsePinPad(pMessageObject);
105 
106 	mMaxApduLength = getIntValue(pMessageObject, MAX_APDU_LENGTH(), -1);
107 	// Support SaC with AusweisApp2 < 1.22.0
108 	if (IfdVersion(IfdVersion::Version::v0).isSupported() && mMaxApduLength == 0)
109 	{
110 		mMaxApduLength = -1;
111 	}
112 
113 	mConnectedReader = getBoolValue(pMessageObject, CONNECTED_READER());
114 	mCardAvailable = getBoolValue(pMessageObject, CARD_AVAILABLE());
115 
116 	if (getType() != RemoteCardMessageType::IFDStatus)
117 	{
118 		markIncomplete(QStringLiteral("The value of msg should be IFDStatus"));
119 	}
120 }
121 
122 
getSlotName() const123 const QString& IfdStatus::getSlotName() const
124 {
125 	return mSlotName;
126 }
127 
128 
hasPinPad() const129 bool IfdStatus::hasPinPad() const
130 {
131 	return mHasPinPad;
132 }
133 
134 
getMaxApduLength() const135 int IfdStatus::getMaxApduLength() const
136 {
137 	return mMaxApduLength;
138 }
139 
140 
getConnectedReader() const141 bool IfdStatus::getConnectedReader() const
142 {
143 	return mConnectedReader;
144 }
145 
146 
getCardAvailable() const147 bool IfdStatus::getCardAvailable() const
148 {
149 	return mCardAvailable;
150 }
151 
152 
toByteArray(const IfdVersion & pIfdVersion,const QString & pContextHandle) const153 QByteArray IfdStatus::toByteArray(const IfdVersion& pIfdVersion, const QString& pContextHandle) const
154 {
155 	QJsonObject result = createMessageBody(pContextHandle);
156 
157 	result[SLOT_NAME()] = mSlotName;
158 	if (pIfdVersion.getVersion() >= IfdVersion::Version::v2)
159 	{
160 		result[PIN_PAD()] = mHasPinPad;
161 	}
162 	else
163 	{
164 		result[PIN_CAPABILITIES()] = createPaceCapabilities();
165 	}
166 	result[MAX_APDU_LENGTH()] = mMaxApduLength;
167 	result[CONNECTED_READER()] = mConnectedReader;
168 	result[CARD_AVAILABLE()] = mCardAvailable;
169 	result[EF_ATR()] = QJsonValue();
170 	result[EF_DIR()] = QJsonValue();
171 
172 	return RemoteMessage::toByteArray(result);
173 }
174