Keyple Card Calypso C++ Library 2.2.2
Reference Terminal Reader API for C++
CalypsoCardSelectionAdapter.cpp
Go to the documentation of this file.
1/**************************************************************************************************
2 * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ *
3 * *
4 * See the NOTICE file(s) distributed with this work for additional information regarding *
5 * copyright ownership. *
6 * *
7 * This program and the accompanying materials are made available under the terms of the Eclipse *
8 * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 *
9 * *
10 * SPDX-License-Identifier: EPL-2.0 *
11 **************************************************************************************************/
12
14
15/* Calypsonet Terminal Card */
16#include "ParseException.h"
17
18/* Keyple Card Calypso */
19#include "CalypsoCardAdapter.h"
20#include "CalypsoCardClass.h"
21#include "CalypsoCardConstant.h"
24#include "CmdCardGetDataFci.h"
25#include "CmdCardGetDataFcp.h"
28#include "CmdCardReadRecords.h"
29#include "CmdCardSelectFile.h"
30#include "UnsupportedOperationException.h"
31
32/* Keyple Card Generic */
33#include "CardRequestAdapter.h"
34
35/* Keyple Core Util */
36#include "ByteArrayUtil.h"
37#include "HexUtil.h"
38#include "IllegalArgumentException.h"
39#include "KeypleAssert.h"
40#include "Pattern.h"
41#include "PatternSyntaxException.h"
42
43namespace keyple {
44namespace card {
45namespace calypso {
46
47using namespace calypsonet::terminal::card::spi;
48using namespace keyple::core::util;
49using namespace keyple::core::util::cpp;
50using namespace keyple::core::util::cpp::exception;
51
52const int CalypsoCardSelectionAdapter::AID_MIN_LENGTH = 5;
53const int CalypsoCardSelectionAdapter::AID_MAX_LENGTH = 16;
54const int CalypsoCardSelectionAdapter::SW_CARD_INVALIDATED = 0x6283;
55
57: mCardSelector(std::make_shared<CardSelectorAdapter>()) {}
58
60 const std::string& cardProtocol)
61{
62 Assert::getInstance().notEmpty(cardProtocol, "cardProtocol");
63
64 mCardSelector->filterByCardProtocol(cardProtocol);
65
66 return *this;
67}
68
70 const std::string& powerOnDataRegex)
71{
72 Assert::getInstance().notEmpty(powerOnDataRegex, "powerOnDataRegex");
73
74 try {
75 Pattern::compile(powerOnDataRegex);
76 } catch (const PatternSyntaxException& exception) {
77 (void)exception;
78 throw IllegalArgumentException("Invalid regular expression: '" +
79 powerOnDataRegex +
80 "'.");
81 }
82
83 mCardSelector->filterByPowerOnData(powerOnDataRegex);
84
85 return *this;
86}
87
88CalypsoCardSelection& CalypsoCardSelectionAdapter::filterByDfName(const std::vector<uint8_t>& aid)
89{
90 Assert::getInstance().notEmpty(aid, "aid")
91 .isInRange(aid.size(), AID_MIN_LENGTH, AID_MAX_LENGTH, "aid");
92
93 mCardSelector->filterByDfName(aid);
94
95 return *this;
96}
97
98CalypsoCardSelection& CalypsoCardSelectionAdapter::filterByDfName(const std::string& aid)
99{
100 Assert::getInstance().isHexString(aid, "aid format");
101
102 filterByDfName(HexUtil::toByteArray(aid));
103
104 return *this;
105}
106
108 const FileOccurrence fileOccurrence)
109{
110 switch (fileOccurrence) {
111 case FileOccurrence::FIRST:
112 mCardSelector->setFileOccurrence(CardSelectorSpi::FileOccurrence::FIRST);
113 break;
114 case FileOccurrence::LAST:
115 mCardSelector->setFileOccurrence(CardSelectorSpi::FileOccurrence::LAST);
116 break;
117 case FileOccurrence::NEXT:
118 mCardSelector->setFileOccurrence(CardSelectorSpi::FileOccurrence::NEXT);
119 break;
120 case FileOccurrence::PREVIOUS:
121 mCardSelector->setFileOccurrence(CardSelectorSpi::FileOccurrence::PREVIOUS);
122 break;
123 }
124
125 return *this;
126}
127
129 const FileControlInformation fileControlInformation)
130{
131 if (fileControlInformation == FileControlInformation::FCI) {
132 mCardSelector->setFileControlInformation(CardSelectorSpi::FileControlInformation::FCI);
133 } else if (fileControlInformation == FileControlInformation::NO_RESPONSE) {
134 mCardSelector->setFileControlInformation(
135 CardSelectorSpi::FileControlInformation::NO_RESPONSE);
136 }
137
138 return *this;
139}
140
141CalypsoCardSelection& CalypsoCardSelectionAdapter::addSuccessfulStatusWord(const int statusWord)
142{
143 Assert::getInstance().isInRange(statusWord, 0, 0xFFFF, "statusWord");
144
145 mCardSelector->addSuccessfulStatusWord(statusWord);
146
147 return *this;
148}
149
151{
152 mCardSelector->addSuccessfulStatusWord(SW_CARD_INVALIDATED);
153
154 return *this;
155}
156
158 const uint8_t sfi, const uint8_t recordNumber)
159{
160 return prepareReadRecord(sfi, recordNumber);
161}
162
163CalypsoCardSelection& CalypsoCardSelectionAdapter::prepareReadRecord(const uint8_t sfi,
164 const uint8_t recordNumber)
165{
166 Assert::getInstance().isInRange(sfi,
169 "sfi")
170 .isInRange(recordNumber,
173 "recordNumber");
174
175 mCommands.push_back(
176 std::make_shared<CmdCardReadRecords>(CalypsoCardClass::ISO,
177 sfi,
178 recordNumber,
180 static_cast<uint8_t>(0)));
181
182 return *this;
183}
184
185CalypsoCardSelection& CalypsoCardSelectionAdapter::prepareGetData(const GetDataTag tag)
186{
187 /* Create the command and add it to the list of commands */
188 switch (tag) {
189 case GetDataTag::FCI_FOR_CURRENT_DF:
190 mCommands.push_back(std::make_shared<CmdCardGetDataFci>(CalypsoCardClass::ISO));
191 break;
192 case GetDataTag::FCP_FOR_CURRENT_FILE:
193 mCommands.push_back(std::make_shared<CmdCardGetDataFcp>(CalypsoCardClass::ISO));
194 break;
195 case GetDataTag::EF_LIST:
196 mCommands.push_back(std::make_shared<CmdCardGetDataEfList>(CalypsoCardClass::ISO));
197 break;
198 case GetDataTag::TRACEABILITY_INFORMATION:
199 mCommands.push_back(
200 std::make_shared<CmdCardGetDataTraceabilityInformation>(CalypsoCardClass::ISO));
201 break;
202 default:
203 throw UnsupportedOperationException("Unsupported Get Data tag: "); // FIXME: + tag.name());
204 }
205
206 return *this;
207}
208
210 const std::vector<uint8_t>& lid)
211{
212 Assert::getInstance().isEqual(lid.size(), 2, "lid length");
213
214 return prepareSelectFile(static_cast<uint16_t>(ByteArrayUtil::extractInt(lid, 0, 2, false)));
215}
216
217CalypsoCardSelection& CalypsoCardSelectionAdapter::prepareSelectFile(const uint16_t lid)
218{
219 mCommands.push_back(
220 std::make_shared<CmdCardSelectFile>(CalypsoCardClass::ISO,
221 CalypsoCard::ProductType::PRIME_REVISION_3, lid));
222
223 return *this;
224}
225
227 const SelectFileControl selectControl)
228{
229 mCommands.push_back(std::make_shared<CmdCardSelectFile>(CalypsoCardClass::ISO, selectControl));
230
231 return *this;
232}
233
234const std::shared_ptr<CardSelectionRequestSpi>
236{
237 std::vector<std::shared_ptr<ApduRequestSpi>> cardSelectionApduRequests;
238
239 if (!mCommands.empty()) {
240 for (const auto& command : mCommands) {
241 cardSelectionApduRequests.push_back(command->getApduRequest());
242 }
243
244 return std::make_shared<CardSelectionRequestAdapter>(
245 mCardSelector,
246 std::make_shared<CardRequestAdapter>(cardSelectionApduRequests, false));
247 } else {
248 return std::make_shared<CardSelectionRequestAdapter>(mCardSelector, nullptr);
249 }
250}
251
252const std::shared_ptr<SmartCardSpi> CalypsoCardSelectionAdapter::parse(
253 const std::shared_ptr<CardSelectionResponseApi> cardSelectionResponse)
254{
255 const std::shared_ptr<CardResponseApi> cardResponse = cardSelectionResponse->getCardResponse();
256 std::vector<std::shared_ptr<ApduResponseApi>> apduResponses;
257
258 if (cardResponse != nullptr) {
259 apduResponses = cardResponse->getApduResponses();
260 } else {
261 apduResponses = {};
262 }
263
264 if (mCommands.size() != apduResponses.size()) {
265 throw ParseException("Mismatch in the number of requests/responses.");
266 }
267
268 std::shared_ptr<CalypsoCardAdapter> calypsoCard;
269 try {
270 calypsoCard = std::make_shared<CalypsoCardAdapter>();
271 if (cardSelectionResponse->getSelectApplicationResponse() != nullptr) {
272 calypsoCard->initializeWithFci(cardSelectionResponse->getSelectApplicationResponse());
273 } else if (cardSelectionResponse->getPowerOnData() != "") {
274 calypsoCard->initializeWithPowerOnData(cardSelectionResponse->getPowerOnData());
275 }
276
277 if (!mCommands.empty()) {
278 CalypsoCardUtilAdapter::updateCalypsoCard(calypsoCard, mCommands, apduResponses, false);
279 }
280
281 } catch (const Exception& e) {
282 throw ParseException("Invalid card response: " + e.getMessage(),
283 std::make_shared<Exception>(e));
284 }
285
286 if (calypsoCard->getProductType() == CalypsoCard::ProductType::UNKNOWN &&
287 cardSelectionResponse->getSelectApplicationResponse() == nullptr &&
288 cardSelectionResponse->getPowerOnData() == "") {
289 throw ParseException("Unable to create a CalypsoCard: no power-on data and no FCI " \
290 "provided.");
291 }
292
293 return calypsoCard;
294}
295
296}
297}
298}
static const CalypsoCardClass ISO
CalypsoCardSelection & filterByPowerOnData(const std::string &powerOnDataRegex) override
CalypsoCardSelection & addSuccessfulStatusWord(const int statusWord) override
CalypsoCardSelection & prepareGetData(const GetDataTag tag) override
CalypsoCardSelection & prepareReadRecordFile(const uint8_t sfi, const uint8_t recordNumber) override
CalypsoCardSelection & setFileOccurrence(const FileOccurrence fileOccurrence) override
CalypsoCardSelection & setFileControlInformation(const FileControlInformation fileControlInformation) override
const std::shared_ptr< SmartCardSpi > parse(const std::shared_ptr< CardSelectionResponseApi > cardSelectionResponse) override
const std::shared_ptr< CardSelectionRequestSpi > getCardSelectionRequest() override
CalypsoCardSelection & prepareReadRecord(const uint8_t sfi, const uint8_t recordNumber) override
CalypsoCardSelection & filterByDfName(const std::vector< uint8_t > &aid) override
CalypsoCardSelection & filterByCardProtocol(const std::string &cardProtocol) override
CalypsoCardSelection & prepareSelectFile(const std::vector< uint8_t > &lid) override
static void updateCalypsoCard(std::shared_ptr< CalypsoCardAdapter > calypsoCard, const std::shared_ptr< AbstractCardCommand > command, const std::shared_ptr< ApduResponseApi > apduResponse, const bool isSessionOpen)
CardSelectorSpi::FileOccurrence FileOccurrence
CardSelectorSpi::FileControlInformation FileControlInformation