Keyple Card Calypso C++ Library 2.2.5.6
Reference Terminal Reader API for C++
CmdCardSelectFile.cpp
Go to the documentation of this file.
1/**************************************************************************************************
2 * Copyright (c) 2023 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
13#include "CmdCardSelectFile.h"
14
15/* Keyple Card Calypso */
16#include "CalypsoCardConstant.h"
20#include "FileHeaderAdapter.h"
21
22/* Keyple Core Util */
23#include "ApduUtil.h"
24#include "Arrays.h"
25#include "BerTlvUtil.h"
26#include "ByteArrayUtil.h"
27#include "HexUtil.h"
28#include "IllegalStateException.h"
29#include "KeypleAssert.h"
30#include "StringUtils.h"
31#include "System.h"
32
33namespace keyple {
34namespace card {
35namespace calypso {
36
37using namespace calypsonet::terminal::calypso;
38using namespace keyple::core::util;
39using namespace keyple::core::util::cpp::exception;
40
41const int CmdCardSelectFile::TAG_PROPRIETARY_INFORMATION = 0x85;
42const CalypsoCardCommand CmdCardSelectFile::mCommand = CalypsoCardCommand::SELECT_FILE;
43const std::map<const int, const std::shared_ptr<StatusProperties>>
44 CmdCardSelectFile::STATUS_TABLE = initStatusTable();
45
46CmdCardSelectFile::CmdCardSelectFile(const std::shared_ptr<CalypsoCardAdapter> calypsoCard,
47 const SelectFileControl selectFileControl)
48: AbstractCardCommand(mCommand, 25, calypsoCard)
49{
50 buildCommand(calypsoCard->getCardClass(), selectFileControl);
51}
52
54 const SelectFileControl selectFileControl)
55: AbstractCardCommand(mCommand, 25, nullptr)
56{
57 buildCommand(calypsoCardClass, selectFileControl);
58}
59
60CmdCardSelectFile::CmdCardSelectFile(const std::shared_ptr<CalypsoCardAdapter> calypsoCard,
61 const uint16_t lid)
62: AbstractCardCommand(mCommand, 25, calypsoCard)
63{
64 buildCommand(calypsoCard->getCardClass(), calypsoCard->getProductType(), lid);
65}
66
68 const CalypsoCard::ProductType productType,
69 const uint16_t lid)
70: AbstractCardCommand(mCommand, 25, nullptr)
71{
72 buildCommand(calypsoCardClass, productType, lid);
73}
74
75void CmdCardSelectFile::buildCommand(const CalypsoCardClass calypsoCardClass,
76 const SelectFileControl selectFileControl)
77{
78 const uint8_t cla = calypsoCardClass.getValue();
79 uint8_t p1;
80 uint8_t p2;
81 const std::vector<uint8_t> selectData = {0x00, 0x00};
82
83 switch (selectFileControl) {
84
85 case SelectFileControl::FIRST_EF:
86 p1 = 0x02;
87 p2 = 0x00;
88 break;
89
90 case SelectFileControl::NEXT_EF:
91 p1 = 0x02;
92 p2 = 0x02;
93 break;
94
95 case SelectFileControl::CURRENT_DF:
96 /* CL-KEY-KIFSF.1 */
97 p1 = 0x09;
98 p2 = 0x00;
99 break;
100
101 default:
102 throw IllegalStateException("Unsupported selectFileControl parameter " \
103 "FIXME: selectFileControl.name()");
104 }
105
106 // APDU Case 4
108 std::make_shared<ApduRequestAdapter>(
109 ApduUtil::build(cla, mCommand.getInstructionByte(), p1, p2, selectData, 0x00)));
110
111
112 addSubName("SELECTIONCONTROL FIXME: selectFileControl");
113}
114
115void CmdCardSelectFile::buildCommand(const CalypsoCardClass calypsoCardClass,
116 const CalypsoCard::ProductType productType,
117 const uint16_t lid)
118{
119 /*
120 * Handle the REV1 case
121 * CL-KEY-KIFSF.1
122 * If legacy and rev2 then 02h else if legacy then 08h else 09h
123 */
124 uint8_t p1;
125
126 if (calypsoCardClass == CalypsoCardClass::LEGACY &&
127 productType == CalypsoCard::ProductType::PRIME_REVISION_2) {
128
129 p1 = 0x02;
130
131 } else if (calypsoCardClass == CalypsoCardClass::LEGACY) {
132
133 p1 = 0x08;
134
135 } else {
136
137 p1 = 0x09;
138 }
139
140 const std::vector<uint8_t> dataIn = ByteArrayUtil::extractBytes(lid, 2);
141
143 std::make_shared<ApduRequestAdapter>(
144 ApduUtil::build(calypsoCardClass.getValue(),
145 mCommand.getInstructionByte(),
146 p1,
147 0x00,
148 dataIn,
149 0x00)));
150
151 addSubName("LID=" + HexUtil::toHex(dataIn));
152}
153
154void CmdCardSelectFile::parseApduResponse(const std::shared_ptr<ApduResponseApi> apduResponse)
155{
157
158 parseProprietaryInformation(apduResponse->getDataOut(), getCalypsoCard());
159}
160
162 const std::vector<uint8_t>& dataOut,
163 const std::shared_ptr<CalypsoCardAdapter> calypsoCard)
164{
165 const std::vector<uint8_t>& proprietaryInformation = getProprietaryInformation(dataOut);
166 const uint8_t sfi = proprietaryInformation[CalypsoCardConstant::SEL_SFI_OFFSET];
167 const uint8_t fileType = proprietaryInformation[CalypsoCardConstant::SEL_TYPE_OFFSET];
168
169 if (fileType == CalypsoCardConstant::FILE_TYPE_MF ||
171
172 std::shared_ptr<DirectoryHeader> directoryHeader =
173 createDirectoryHeader(proprietaryInformation, calypsoCard);
174 calypsoCard->setDirectoryHeader(directoryHeader);
175
176 } else if (fileType == CalypsoCardConstant::FILE_TYPE_EF) {
177
178 std::shared_ptr<FileHeaderAdapter> fileHeader =
179 createFileHeader(proprietaryInformation, calypsoCard);
180 calypsoCard->setFileHeader(sfi, fileHeader);
181
182 } else {
183
184 throw IllegalStateException(StringUtils::format("Unknown file type: %02Xh", fileType));
185 }
186}
187
189{
190 return false;
191}
192
194 const std::vector<uint8_t>& dataOut)
195{
196 std::vector<uint8_t> proprietaryInformation;
197 const std::map<const int, const std::vector<uint8_t>> tags =
198 BerTlvUtil::parseSimple(dataOut, true);
199
200 const auto& it = tags.find(TAG_PROPRIETARY_INFORMATION);
201
202 if (it == tags.end()) {
203
204 throw IllegalStateException("Proprietary information: tag not found.");
205 }
206
207 proprietaryInformation = it->second;
208
209 Assert::getInstance().isEqual(proprietaryInformation.size(), 23, "proprietaryInformation");
210
211 return proprietaryInformation;
212}
213
214const std::shared_ptr<DirectoryHeader> CmdCardSelectFile::createDirectoryHeader(
215 const std::vector<uint8_t>& proprietaryInformation,
216 const std::shared_ptr<CalypsoCardAdapter> calypsoCard)
217
218{
219 std::vector<uint8_t> accessConditions(CalypsoCardConstant::SEL_AC_LENGTH);
220 System::arraycopy(proprietaryInformation,
222 accessConditions,
223 0,
225
226 std::vector<uint8_t> keyIndexes(CalypsoCardConstant::SEL_NKEY_LENGTH);
227 System::arraycopy(proprietaryInformation,
229 keyIndexes,
230 0,
232
233 const uint8_t dfStatus = proprietaryInformation[CalypsoCardConstant::SEL_DF_STATUS_OFFSET];
234
235 const int lidOffset =
236 calypsoCard->getProductType() == CalypsoCard::ProductType::PRIME_REVISION_2 ?
238
239 const uint8_t lid = ByteArrayUtil::extractShort(proprietaryInformation, lidOffset);
240
242 ->lid(lid)
243 .accessConditions(accessConditions)
244 .keyIndexes(keyIndexes)
245 .dfStatus(dfStatus)
246 .kvc(WriteAccessLevel::PERSONALIZATION,
247 proprietaryInformation[CalypsoCardConstant::SEL_KVCS_OFFSET])
248 .kvc(WriteAccessLevel::LOAD,
249 proprietaryInformation[CalypsoCardConstant::SEL_KVCS_OFFSET + 1])
250 .kvc(WriteAccessLevel::DEBIT,
251 proprietaryInformation[CalypsoCardConstant::SEL_KVCS_OFFSET + 2])
252 .kif(WriteAccessLevel::PERSONALIZATION,
253 proprietaryInformation[CalypsoCardConstant::SEL_KIFS_OFFSET])
254 .kif(WriteAccessLevel::LOAD,
255 proprietaryInformation[CalypsoCardConstant::SEL_KIFS_OFFSET + 1])
256 .kif(WriteAccessLevel::DEBIT,
257 proprietaryInformation[CalypsoCardConstant::SEL_KIFS_OFFSET + 2])
258 .build();
259}
260
261const std::shared_ptr<FileHeaderAdapter> CmdCardSelectFile::createFileHeader(
262 const std::vector<uint8_t>& proprietaryInformation,
263 const std::shared_ptr<CalypsoCardAdapter> calypsoCard)
264{
265 const ElementaryFile::Type fileType =
266 getEfTypeFromCardValue(proprietaryInformation[CalypsoCardConstant::SEL_EF_TYPE_OFFSET]);
267
268 int recordSize;
269 int recordsNumber;
270
271 if (fileType == ElementaryFile::Type::BINARY) {
272
273 recordSize = ByteArrayUtil::extractInt(proprietaryInformation,
275 2,
276 false);
277 recordsNumber = 1;
278
279 } else {
280
281 recordSize = proprietaryInformation[CalypsoCardConstant::SEL_REC_SIZE_OFFSET];
282 recordsNumber = proprietaryInformation[CalypsoCardConstant::SEL_NUM_REC_OFFSET];
283 }
284
285 std::vector<uint8_t> accessConditions(CalypsoCardConstant::SEL_AC_LENGTH);
286 System::arraycopy(proprietaryInformation,
288 accessConditions,
289 0,
291
292 std::vector<uint8_t> keyIndexes(CalypsoCardConstant::SEL_NKEY_LENGTH);
293 System::arraycopy(proprietaryInformation,
295 keyIndexes,
296 0,
298
299 const uint8_t dfStatus = proprietaryInformation[CalypsoCardConstant::SEL_DF_STATUS_OFFSET];
300
301 const uint16_t sharedReference =
302 ByteArrayUtil::extractShort(proprietaryInformation,
304
305 const int lidOffset =
306 calypsoCard->getProductType() == CalypsoCard::ProductType::PRIME_REVISION_2 ?
308
309 const uint16_t lid = ByteArrayUtil::extractShort(proprietaryInformation, lidOffset);
310
312 ->lid(lid)
313 .recordsNumber(recordsNumber)
314 .recordSize(recordSize)
315 .type(fileType)
316 .accessConditions(Arrays::copyOf(accessConditions, accessConditions.size()))
317 .keyIndexes(Arrays::copyOf(keyIndexes, keyIndexes.size()))
318 .dfStatus(dfStatus)
319 .sharedReference(sharedReference)
320 .build();
321}
322
323ElementaryFile::Type CmdCardSelectFile::getEfTypeFromCardValue(const uint8_t efType)
324{
326
327 return ElementaryFile::Type::BINARY;
328
329 } else if (efType == CalypsoCardConstant::EF_TYPE_LINEAR) {
330
331 return ElementaryFile::Type::LINEAR;
332
333 } else if (efType == CalypsoCardConstant::EF_TYPE_CYCLIC) {
334
335 return ElementaryFile::Type::CYCLIC;
336
338
339 return ElementaryFile::Type::SIMULATED_COUNTERS;
340
341 } else if (efType == CalypsoCardConstant::EF_TYPE_COUNTERS) {
342
343 return ElementaryFile::Type::COUNTERS;
344
345 } else {
346
347 throw IllegalStateException("Unknown EF Type: " + std::to_string(efType));
348 }
349}
350
351const std::map<const int, const std::shared_ptr<StatusProperties>>
352 CmdCardSelectFile::initStatusTable()
353{
354 std::map<const int, const std::shared_ptr<StatusProperties>> m =
356
357 m.insert({0x6700,
358 std::make_shared<StatusProperties>("Lc value not supported.",
359 typeid(CardIllegalParameterException))});
360 m.insert({0x6A82,
361 std::make_shared<StatusProperties>("File not found.",
362 typeid(CardDataAccessException))});
363 m.insert({0x6119,
364 std::make_shared<StatusProperties>("Correct execution (ISO7816 T=0).",
365 typeid(nullptr))});
366
367 return m;
368}
369
370const std::map<const int, const std::shared_ptr<StatusProperties>>&
372{
373 return STATUS_TABLE;
374}
375
376}
377}
378}
static const std::map< const int, const std::shared_ptr< StatusProperties > > STATUS_TABLE
virtual void addSubName(const std::string &subName) final
virtual void setApduRequest(const std::shared_ptr< ApduRequestAdapter > apduRequest) final
void parseApduResponse(const std::shared_ptr< ApduResponseApi > apduResponse) override
std::shared_ptr< CalypsoCardAdapter > getCalypsoCard() const
static const CalypsoCardClass LEGACY
static const CalypsoCardCommand SELECT_FILE
CmdCardSelectFile(const std::shared_ptr< CalypsoCardAdapter > calypsoCard, const SelectFileControl selectFileControl)
const std::map< const int, const std::shared_ptr< StatusProperties > > & getStatusTable() const override
static void parseProprietaryInformation(const std::vector< uint8_t > &dataOut, const std::shared_ptr< CalypsoCardAdapter > calypsoCard)
static const std::vector< uint8_t > getProprietaryInformation(const std::vector< uint8_t > &dataOut)
void parseApduResponse(const std::shared_ptr< ApduResponseApi > apduResponse) override
static std::shared_ptr< DirectoryHeaderBuilder > builder()
static std::shared_ptr< FileHeaderBuilder > builder()
CalypsoSam::ProductType ProductType