Keyple Card Calypso C++ Library - 3.2.2
Component of the Keyple C++ middleware
CommandGetDataEfList.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
5 * regarding * copyright ownership.
6 * *
7 * *
8 * This program and the accompanying materials are made available under the
9 * terms of the Eclipse *
10 * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 *
11 * *
12 * SPDX-License-Identifier: EPL-2.0 *
13 **************************************************************************************************/
14
15#include "keyple/card/calypso/CommandGetDataEfList.hpp"
16
17#include <map>
18#include <memory>
19#include <vector>
20
21#include "keyple/card/calypso/CalypsoCardAdapter.hpp"
22#include "keyple/card/calypso/CalypsoCardConstant.hpp"
23#include "keyple/card/calypso/CardDataAccessException.hpp"
24#include "keyple/core/util/ApduUtil.hpp"
25#include "keyple/core/util/ByteArrayUtil.hpp"
26#include "keyple/core/util/cpp/Arrays.hpp"
27#include "keyple/core/util/cpp/exception/IllegalStateException.hpp"
28
29namespace keyple {
30namespace card {
31namespace calypso {
32
33using keyple::core::util::ApduUtil;
34using keyple::core::util::ByteArrayUtil;
35using keyple::core::util::cpp::Arrays;
36using keyple::core::util::cpp::exception::IllegalStateException;
37
38const int CommandGetDataEfList::DESCRIPTORS_OFFSET = 2;
39const int CommandGetDataEfList::DESCRIPTOR_DATA_OFFSET = 2;
40const int CommandGetDataEfList::DESCRIPTOR_DATA_SFI_OFFSET = 2;
41const int CommandGetDataEfList::DESCRIPTOR_TAG_LENGTH = 8;
42const int CommandGetDataEfList::DESCRIPTOR_DATA_LENGTH = 6;
43
44const std::map<int, const std::shared_ptr<Command::StatusProperties>>
45 CommandGetDataEfList::STATUS_TABLE = [] {
46 std::map<int, const std::shared_ptr<Command::StatusProperties>> m(
47 Command::STATUS_TABLE);
48
49 m.insert(
50 {{0x6A88,
51 std::make_shared<StatusProperties>(
52 "Data object not found (optional mode not available)",
53 typeid(CardDataAccessException))},
54 {0x6B00,
55 std::make_shared<StatusProperties>(
56 "P1 or P2 value not supported",
57 typeid(CardDataAccessException))}});
58 return m;
59 }();
60
61CommandGetDataEfList::CommandGetDataEfList(
62 const std::shared_ptr<DtoAdapters::TransactionContextDto>&
63 transactionContext,
64 const std::shared_ptr<DtoAdapters::CommandContextDto>& commandContext)
65: Command(CardCommandRef::GET_DATA, nullptr, transactionContext, commandContext)
66{
67 const std::uint8_t cardClass
68 = transactionContext->getCard() != nullptr
69 ? transactionContext->getCard()->getCardClass().getValue()
70 : CalypsoCardClass::ISO.getValue();
71
72 /* APDU Case 2 - always outside secure session */
73 setApduRequest(
74 std::make_shared<DtoAdapters::ApduRequestAdapter>(ApduUtil::build(
75 cardClass,
76 getCommandRef().getInstructionByte(),
77 CalypsoCardConstant::TAG_EF_LIST_MSB,
78 CalypsoCardConstant::TAG_EF_LIST_LSB,
79 0)));
80
81 addSubName("EF_LIST");
82}
83
84void
85CommandGetDataEfList::finalizeRequest()
86{
87 /* NOP */
88}
89
90bool
91CommandGetDataEfList::isCryptoServiceRequiredToFinalizeRequest() const
92{
93 return false;
94}
95
96bool
97CommandGetDataEfList::synchronizeCryptoServiceBeforeCardProcessing()
98{
99 return true;
100}
101
102void
103CommandGetDataEfList::parseResponse(
104 std::shared_ptr<ApduResponseApi> apduResponse)
105{
106 Command::setApduResponseAndCheckStatus(apduResponse);
107
108 const std::map<std::shared_ptr<FileHeaderAdapter>, std::uint8_t>
109 fileHeaderToSfiMap = getEfHeaders();
110
111 for (const auto& entry : fileHeaderToSfiMap) {
112 getTransactionContext()->getCard()->setFileHeader(
113 entry.second, entry.first);
114 }
115}
116
117const std::map<int, const std::shared_ptr<Command::StatusProperties>>&
118CommandGetDataEfList::getStatusTable() const
119{
120 return STATUS_TABLE;
121}
122
123std::map<std::shared_ptr<FileHeaderAdapter>, std::uint8_t>
124CommandGetDataEfList::getEfHeaders()
125{
126 const std::vector<std::uint8_t> rawList = getApduResponse()->getDataOut();
127 std::map<std::shared_ptr<FileHeaderAdapter>, std::uint8_t>
128 fileHeaderToSfiMap;
129 int nbFiles = rawList[1] / DESCRIPTOR_TAG_LENGTH;
130
131 for (int i = 0; i < nbFiles; i++) {
132 fileHeaderToSfiMap.insert(
133 {createFileHeader(
134 Arrays::copyOfRange(
135 rawList,
136 DESCRIPTORS_OFFSET + (i * DESCRIPTOR_TAG_LENGTH)
137 + DESCRIPTOR_DATA_OFFSET,
138 DESCRIPTORS_OFFSET + (i * DESCRIPTOR_TAG_LENGTH)
139 + DESCRIPTOR_DATA_OFFSET + DESCRIPTOR_DATA_LENGTH)),
140 rawList
141 [DESCRIPTORS_OFFSET + (i * DESCRIPTOR_TAG_LENGTH)
142 + DESCRIPTOR_DATA_OFFSET + DESCRIPTOR_DATA_SFI_OFFSET]});
143 }
144
145 return fileHeaderToSfiMap;
146}
147
148std::shared_ptr<FileHeaderAdapter>
149CommandGetDataEfList::createFileHeader(
150 const std::vector<std::uint8_t>& efDescriptorByteArray)
151{
152 ElementaryFile::Type efType;
153
154 switch (efDescriptorByteArray[3]) {
155 case CalypsoCardConstant::EF_TYPE_LINEAR:
156 efType = ElementaryFile::Type::LINEAR;
157 break;
158 case CalypsoCardConstant::EF_TYPE_CYCLIC:
159 efType = ElementaryFile::Type::CYCLIC;
160 break;
161 case CalypsoCardConstant::EF_TYPE_COUNTERS:
162 efType = ElementaryFile::Type::COUNTERS;
163 break;
164 case CalypsoCardConstant::EF_TYPE_BINARY:
165 efType = ElementaryFile::Type::BINARY;
166 break;
167 case CalypsoCardConstant::EF_TYPE_SIMULATED_COUNTERS:
168 efType = ElementaryFile::Type::SIMULATED_COUNTERS;
169 break;
170 default:
171 throw IllegalStateException(
172 "Unexpected EF type: " + std::to_string(efDescriptorByteArray[3]));
173 }
174
175 return FileHeaderAdapter::builder()
176 ->lid(ByteArrayUtil::extractShort(efDescriptorByteArray, 0))
177 .type(efType)
178 .recordSize(efDescriptorByteArray[4])
179 .recordsNumber(efDescriptorByteArray[5])
180 .build();
181}
182
183} /* namespace calypso */
184} /* namespace card */
185} /* namespace keyple */