14#include "keyple/card/calypso/CommandSvGet.hpp"
20#include "keyple/card/calypso/CalypsoCardAdapter.hpp"
21#include "keyple/card/calypso/CalypsoCardConstant.hpp"
22#include "keyple/card/calypso/CardAccessForbiddenException.hpp"
23#include "keyple/card/calypso/CardIllegalParameterException.hpp"
24#include "keyple/card/calypso/CardSecurityContextException.hpp"
25#include "keyple/core/util/ApduUtil.hpp"
26#include "keyple/core/util/ByteArrayUtil.hpp"
27#include "keyple/core/util/cpp/Arrays.hpp"
28#include "keyple/core/util/cpp/exception/IllegalStateException.hpp"
34using keyple::core::util::ApduUtil;
35using keyple::core::util::ByteArrayUtil;
36using keyple::core::util::cpp::Arrays;
37using keyple::core::util::cpp::exception::IllegalStateException;
39const std::map<int, const std::shared_ptr<Command::StatusProperties>>
40 CommandSvGet::STATUS_TABLE = [] {
41 std::map<int, const std::shared_ptr<Command::StatusProperties>> m(
42 Command::STATUS_TABLE);
46 std::make_shared<StatusProperties>(
47 "Security conditions not fulfilled",
48 typeid(CardSecurityContextException))},
50 std::make_shared<StatusProperties>(
51 "Preconditions not satisfied (a store value operation was "
52 "already done in the current session)",
53 typeid(CardAccessForbiddenException))},
55 std::make_shared<StatusProperties>(
56 "Incorrect P1 or P2",
typeid(CardIllegalParameterException))},
58 std::make_shared<StatusProperties>(
59 "Le inconsistent with P2",
60 typeid(CardIllegalParameterException))},
62 std::make_shared<StatusProperties>(
63 "SV function not present",
64 typeid(CardIllegalParameterException))}});
68CommandSvGet::CommandSvGet(
69 const std::shared_ptr<DtoAdapters::TransactionContextDto>&
71 const std::shared_ptr<DtoAdapters::CommandContextDto>& commandContext,
72 SvOperation svOperation,
75 CardCommandRef::SV_GET,
77 new int(computeExpectedResponseLength(svOperation, useExtendedMode))),
81 const std::uint8_t cla
82 = transactionContext->getCard()->getCardClass()
83 == CalypsoCardClass::LEGACY
84 ? CalypsoCardClass::LEGACY_STORED_VALUE.getValue()
85 : CalypsoCardClass::ISO.getValue();
87 const std::uint8_t p1 = useExtendedMode ? 0x01 : 0x00;
88 const std::uint8_t p2 = svOperation == SvOperation::RELOAD ? 0x07 : 0x09;
91 const int* le = getExpectedResponseLength();
94 std::make_shared<DtoAdapters::ApduRequestAdapter>(ApduUtil::build(
95 cla, getCommandRef().getInstructionByte(), p1, p2)));
98 std::make_shared<DtoAdapters::ApduRequestAdapter>(ApduUtil::build(
100 getCommandRef().getInstructionByte(),
103 static_cast<uint8_t
>(*le))));
106 addSubName(
"Operation: " + std::to_string(
static_cast<int>(svOperation)));
109 mHeader[0] = getCommandRef().getInstructionByte();
112 mHeader[3] =
static_cast<uint8_t
>(le ==
nullptr ? 0 : *le);
116CommandSvGet::finalizeRequest()
118 encryptRequestAndUpdateTerminalSessionMacIfNeeded();
122CommandSvGet::isCryptoServiceRequiredToFinalizeRequest()
const
124 return getCommandContext()->isEncryptionActive();
128CommandSvGet::synchronizeCryptoServiceBeforeCardProcessing()
134CommandSvGet::parseResponse(std::shared_ptr<ApduResponseApi> apduResponse)
136 decryptResponseAndUpdateTerminalSessionMacIfNeeded(apduResponse);
137 Command::setApduResponseAndCheckStatus(apduResponse);
139 const std::vector<std::uint8_t> cardResponse = apduResponse->getDataOut();
140 std::uint8_t currentKvc;
141 int transactionNumber;
143 std::vector<std::uint8_t> loadLog;
144 std::vector<std::uint8_t> debitLog;
146 switch (cardResponse.size()) {
149 currentKvc = cardResponse[0];
151 = ByteArrayUtil::extractInt(cardResponse, 1, 2,
false);
152 balance = ByteArrayUtil::extractInt(cardResponse, 8, 3,
true);
154 if (cardResponse.size() == 0x21) {
157 = Arrays::copyOfRange(cardResponse, 11, cardResponse.size());
163 = Arrays::copyOfRange(cardResponse, 11, cardResponse.size());
167 currentKvc = cardResponse[8];
169 = ByteArrayUtil::extractInt(cardResponse, 9, 2,
false);
170 balance = ByteArrayUtil::extractInt(cardResponse, 17, 3,
true);
171 loadLog = Arrays::copyOfRange(cardResponse, 20, 42);
172 debitLog = Arrays::copyOfRange(cardResponse, 42, cardResponse.size());
175 throw IllegalStateException(
176 "SV Get response is not the correct length. Expected: 30/33/61, "
178 + std::to_string(cardResponse.size()));
181 std::shared_ptr<CalypsoCardAdapter> calypsoCard
182 = getTransactionContext()->getCard();
183 calypsoCard->setSvData(
186 apduResponse->getApdu(),
190 if (!loadLog.empty()) {
191 calypsoCard->addCyclicContent(
192 CalypsoCardConstant::SV_RELOAD_LOG_FILE_SFI, loadLog);
195 if (!debitLog.empty()) {
196 calypsoCard->addCyclicContent(
197 CalypsoCardConstant::SV_DEBIT_LOG_FILE_SFI, debitLog);
200 updateTerminalSessionIfNeeded();
203const std::map<int, const std::shared_ptr<Command::StatusProperties>>&
204CommandSvGet::getStatusTable()
const
210CommandSvGet::computeExpectedResponseLength(
211 SvOperation svOperation,
bool useExtendedMode)
213 if (useExtendedMode) {
217 return svOperation == SvOperation::RELOAD ? 0x21 : 0x1E;