14#include "keyple/card/calypso/CommandSvReload.hpp"
21#include "keyple/card/calypso/CalypsoCardAdapter.hpp"
22#include "keyple/card/calypso/CalypsoCardConstant.hpp"
23#include "keyple/card/calypso/CardAccessForbiddenException.hpp"
24#include "keyple/card/calypso/CardIllegalParameterException.hpp"
25#include "keyple/card/calypso/CardSecurityDataException.hpp"
26#include "keyple/card/calypso/CardSessionBufferOverflowException.hpp"
27#include "keyple/card/calypso/CardTerminatedException.hpp"
28#include "keyple/core/util/ApduUtil.hpp"
29#include "keyple/core/util/ByteArrayUtil.hpp"
30#include "keyple/core/util/cpp/Arrays.hpp"
31#include "keyple/core/util/cpp/System.hpp"
32#include "keyple/core/util/cpp/exception/IllegalStateException.hpp"
33#include "keypop/calypso/card/transaction/CardSignatureNotVerifiableException.hpp"
34#include "keypop/calypso/card/transaction/CryptoException.hpp"
35#include "keypop/calypso/card/transaction/CryptoIOException.hpp"
36#include "keypop/calypso/card/transaction/InvalidCardSignatureException.hpp"
37#include "keypop/calypso/crypto/symmetric/SymmetricCryptoException.hpp"
38#include "keypop/calypso/crypto/symmetric/SymmetricCryptoIOException.hpp"
44using keyple::core::util::ApduUtil;
45using keyple::core::util::ByteArrayUtil;
46using keyple::core::util::cpp::Arrays;
47using keyple::core::util::cpp::System;
48using keyple::core::util::cpp::exception::IllegalStateException;
49using keypop::calypso::card::transaction::CardSignatureNotVerifiableException;
50using keypop::calypso::card::transaction::CryptoException;
51using keypop::calypso::card::transaction::CryptoIOException;
52using keypop::calypso::card::transaction::InvalidCardSignatureException;
53using keypop::calypso::crypto::symmetric::SymmetricCryptoException;
54using keypop::calypso::crypto::symmetric::SymmetricCryptoIOException;
56const std::string CommandSvReload::MSG_CARD_SV_MAC_NOT_VERIFIABLE
57 =
"Unable to verify the card SV MAC associated to the SV operation";
58const std::string CommandSvReload::MSG_INVALID_CARD_SESSION_MAC
59 =
"Invalid card session MAC";
60const int CommandSvReload::SW_POSTPONED_DATA = 0x6200;
62const std::map<int, const std::shared_ptr<Command::StatusProperties>>
63 CommandSvReload::STATUS_TABLE = [] {
64 std::map<int, const std::shared_ptr<Command::StatusProperties>> m(
65 Command::STATUS_TABLE);
69 std::make_shared<StatusProperties>(
70 "Too many modifications in session",
71 typeid(CardSessionBufferOverflowException))},
73 std::make_shared<StatusProperties>(
74 "Lc value not supported",
75 typeid(CardIllegalParameterException))},
77 std::make_shared<StatusProperties>(
78 "Transaction counter is 0 or SV TNum is FFFEh or FFFFh",
79 typeid(CardTerminatedException))},
81 std::make_shared<StatusProperties>(
82 "Preconditions not satisfied",
83 typeid(CardAccessForbiddenException))},
85 std::make_shared<StatusProperties>(
86 "Incorrect signatureHi",
typeid(CardSecurityDataException))},
88 std::make_shared<StatusProperties>(
89 "Successful execution, response data postponed until session "
94CommandSvReload::CommandSvReload(
95 const std::shared_ptr<DtoAdapters::TransactionContextDto>&
97 const std::shared_ptr<DtoAdapters::CommandContextDto>& commandContext,
99 const std::vector<std::uint8_t>& date,
100 const std::vector<std::uint8_t>& time,
101 const std::vector<std::uint8_t>& free,
102 bool isExtendedModeAllowed)
104 CardCommandRef::SV_RELOAD,
105 std::unique_ptr<int>(new int(computeExpectedResponseLength(
106 commandContext, isExtendedModeAllowed))),
111, mIsExtendedModeAllowed(isExtendedModeAllowed)
117 mDataIn = std::vector<std::uint8_t>(18 + (isExtendedModeAllowed ? 10 : 5));
120 mDataIn[1] = date[0];
121 mDataIn[2] = date[1];
122 mDataIn[3] = free[0];
123 mDataIn[4] = transactionContext->getCard()->getSvKvc();
124 mDataIn[5] = free[1];
125 ByteArrayUtil::copyBytes(amount, mDataIn, 6, 3);
126 mDataIn[9] = time[0];
127 mDataIn[10] = time[1];
135 std::unique_ptr<std::uint8_t> le(
136 computeLe(commandContext, isExtendedModeAllowed));
138 std::vector<std::uint8_t> apdu;
140 apdu = ApduUtil::build(0, 0, 0, 0, mDataIn);
143 apdu = ApduUtil::build(0, 0, 0, 0, mDataIn, *le.get());
146 setApduRequest(std::make_shared<DtoAdapters::ApduRequestAdapter>(apdu));
150CommandSvReload::finalizeRequest()
152 auto svCommandSecurityData(
153 std::make_shared<DtoAdapters::SvCommandSecurityDataApiAdapter>());
154 svCommandSecurityData->setSvGetRequest(
155 getTransactionContext()->getCard()->getSvGetHeader());
156 svCommandSecurityData->setSvGetResponse(
157 getTransactionContext()->getCard()->getSvGetData());
158 svCommandSecurityData->setSvCommandPartialRequest(getSvReloadData());
161 getTransactionContext()
162 ->getSymmetricCryptoCardTransactionManagerSpi()
163 ->computeSvCommandSecurityData(svCommandSecurityData);
165 }
catch (
const SymmetricCryptoException& e) {
166 throw CryptoException(e.what(), e);
168 }
catch (
const SymmetricCryptoIOException& e) {
169 throw CryptoIOException(e.what(), e);
172 finalizeCommand(svCommandSecurityData);
173 encryptRequestAndUpdateTerminalSessionMacIfNeeded();
177CommandSvReload::isCryptoServiceRequiredToFinalizeRequest()
const
183CommandSvReload::synchronizeCryptoServiceBeforeCardProcessing()
189CommandSvReload::parseResponse(std::shared_ptr<ApduResponseApi> apduResponse)
191 decryptResponseAndUpdateTerminalSessionMacIfNeeded(apduResponse);
192 Command::setApduResponseAndCheckStatus(apduResponse);
194 if (apduResponse->getDataOut().size() != 0
195 && apduResponse->getDataOut().size() != 3
196 && apduResponse->getDataOut().size() != 6) {
197 throw IllegalStateException(
198 "SV Reload response is not the correct length. Expected: 0/3/6, "
200 + std::to_string(apduResponse->getDataOut().size()));
203 std::shared_ptr<CalypsoCardAdapter> calypsoCard
204 = getTransactionContext()->getCard();
205 calypsoCard->setSvOperationSignature(apduResponse->getDataOut());
206 updateCalypsoCardSvHistory(calypsoCard);
207 updateTerminalSessionIfNeeded();
209 if (!getCommandContext()->isSecureSessionOpen()) {
211 if (!getTransactionContext()
212 ->getSymmetricCryptoCardTransactionManagerSpi()
214 getTransactionContext()
216 ->getSvOperationSignature())) {
217 throw InvalidCardSignatureException(
218 MSG_INVALID_CARD_SESSION_MAC);
221 }
catch (
const SymmetricCryptoIOException& e) {
222 throw CardSignatureNotVerifiableException(
223 MSG_CARD_SV_MAC_NOT_VERIFIABLE, e);
225 }
catch (
const SymmetricCryptoException& e) {
226 throw CryptoIOException(e.what(), e);
231const std::map<int, const std::shared_ptr<Command::StatusProperties>>&
232CommandSvReload::getStatusTable()
const
238CommandSvReload::computeExpectedResponseLength(
239 const std::shared_ptr<DtoAdapters::CommandContextDto>& commandContext,
240 bool isExtendedModeAllowed)
242 if (commandContext->isSecureSessionOpen()) {
245 return isExtendedModeAllowed ? 6 : 3;
249std::unique_ptr<std::uint8_t>
250CommandSvReload::computeLe(
251 const std::shared_ptr<DtoAdapters::CommandContextDto>& commandContext,
252 bool isExtendedModeAllowed)
254 if (commandContext->isSecureSessionOpen()) {
257 return std::unique_ptr<std::uint8_t>(
258 new std::uint8_t(isExtendedModeAllowed ? 6 : 3));
263CommandSvReload::finalizeCommand(
264 std::shared_ptr<DtoAdapters::SvCommandSecurityDataApiAdapter>
265 svCommandSecurityData)
267 const std::uint8_t p1 = svCommandSecurityData->getTerminalChallenge()[0];
268 std::uint8_t p2 = svCommandSecurityData->getTerminalChallenge()[1];
269 mDataIn[0] = svCommandSecurityData->getTerminalChallenge()[2];
271 svCommandSecurityData->getSerialNumber(), 0, mDataIn, 11, 4);
273 svCommandSecurityData->getTransactionNumber(), 0, mDataIn, 15, 3);
275 svCommandSecurityData->getTerminalSvMac(),
279 svCommandSecurityData->getTerminalSvMac().size());
282 const std::unique_ptr<std::uint8_t> le(
283 computeLe(getCommandContext(), mIsExtendedModeAllowed));
285 std::vector<std::uint8_t> _apdu;
288 _apdu = ApduUtil::build(
289 getTransactionContext()->getCard()->getCardClass()
290 == CalypsoCardClass::LEGACY
291 ? CalypsoCardClass::LEGACY_STORED_VALUE.getValue()
292 : CalypsoCardClass::ISO.getValue(),
293 getCommandRef().getInstructionByte(),
300 _apdu = ApduUtil::build(
301 getTransactionContext()->getCard()->getCardClass()
302 == CalypsoCardClass::LEGACY
303 ? CalypsoCardClass::LEGACY_STORED_VALUE.getValue()
304 : CalypsoCardClass::ISO.getValue(),
305 getCommandRef().getInstructionByte(),
312 auto apdu(std::make_shared<DtoAdapters::ApduRequestAdapter>(_apdu));
313 apdu->addSuccessfulStatusWord(SW_POSTPONED_DATA);
314 setApduRequest(apdu);
317std::vector<std::uint8_t>
318CommandSvReload::getSvReloadData()
320 std::vector<std::uint8_t> svReloadData(15);
321 svReloadData[0] = getCommandRef().getInstructionByte();
327 svReloadData[3] = mIsExtendedModeAllowed ? 0x1C : 0x17;
330 System::arraycopy(mDataIn, 0, svReloadData, 4, 11);
336CommandSvReload::updateCalypsoCardSvHistory(
337 std::shared_ptr<CalypsoCardAdapter> calypsoCard)
339 const int balance = calypsoCard->getSvBalance() + mAmount;
340 calypsoCard->updateSvData(balance, calypsoCard->getSvLastTNum() + 1);
342 std::vector<std::uint8_t> reloadLog(22);
343 System::arraycopy(getApduRequest()->getApdu(), 6, reloadLog, 0, 5);
344 ByteArrayUtil::copyBytes(balance, reloadLog, 5, 3);
345 ByteArrayUtil::copyBytes(mAmount, reloadLog, 8, 3);
346 System::arraycopy(getApduRequest()->getApdu(), 14, reloadLog, 11, 9);
347 ByteArrayUtil::copyBytes(calypsoCard->getSvLastTNum(), reloadLog, 20, 2);
348 calypsoCard->addCyclicContent(
349 CalypsoCardConstant::SV_RELOAD_LOG_FILE_SFI, reloadLog);