14#include "keyple/card/calypso/TransactionManagerAdapter.hpp"
24#include "keyple/card/calypso/CalypsoCardConstant.hpp"
25#include "keyple/card/calypso/CommandAppendRecord.hpp"
26#include "keyple/card/calypso/CommandGenerateAsymmetricKeyPair.hpp"
27#include "keyple/card/calypso/CommandGetDataCardPublicKey.hpp"
28#include "keyple/card/calypso/CommandGetDataCertificate.hpp"
29#include "keyple/card/calypso/CommandGetDataEfList.hpp"
30#include "keyple/card/calypso/CommandGetDataFcp.hpp"
31#include "keyple/card/calypso/CommandGetDataTraceabilityInformation.hpp"
32#include "keyple/card/calypso/CommandIncreaseOrDecrease.hpp"
33#include "keyple/card/calypso/CommandIncreaseOrDecreaseMultiple.hpp"
34#include "keyple/card/calypso/CommandOpenSecureSession.hpp"
35#include "keyple/card/calypso/CommandPutData.hpp"
36#include "keyple/card/calypso/CommandReadBinary.hpp"
37#include "keyple/card/calypso/CommandReadRecordMultiple.hpp"
38#include "keyple/card/calypso/CommandReadRecords.hpp"
39#include "keyple/card/calypso/CommandSearchRecordMultiple.hpp"
40#include "keyple/card/calypso/CommandSelectFile.hpp"
41#include "keyple/card/calypso/CommandUpdateOrWriteBinary.hpp"
42#include "keyple/card/calypso/CommandUpdateRecord.hpp"
43#include "keyple/card/calypso/CommandVerifyPin.hpp"
44#include "keyple/card/calypso/CommandWriteRecord.hpp"
45#include "keyple/core/util/HexUtil.hpp"
46#include "keyple/core/util/KeypleAssert.hpp"
47#include "keyple/core/util/cpp/Arrays.hpp"
48#include "keyple/core/util/cpp/exception/IllegalArgumentException.hpp"
49#include "keyple/core/util/cpp/exception/IllegalStateException.hpp"
50#include "keyple/core/util/cpp/exception/RuntimeException.hpp"
51#include "keyple/core/util/cpp/exception/UnsupportedOperationException.hpp"
52#include "keypop/calypso/card/transaction/InconsistentDataException.hpp"
53#include "keypop/card/CardBrokenCommunicationException.hpp"
54#include "keypop/card/ReaderBrokenCommunicationException.hpp"
55#include "keypop/card/UnexpectedStatusWordException.hpp"
56#include "keypop/reader/CardCommunicationException.hpp"
57#include "keypop/reader/ReaderCommunicationException.hpp"
58#include "keypop/reader/selection/InvalidCardResponseException.hpp"
64using keyple::core::util::Assert;
65using keyple::core::util::HexUtil;
66using keyple::core::util::cpp::Arrays;
67using keyple::core::util::cpp::exception::IllegalArgumentException;
68using keyple::core::util::cpp::exception::IllegalStateException;
69using keyple::core::util::cpp::exception::RuntimeException;
70using keyple::core::util::cpp::exception::UnsupportedOperationException;
71using keypop::calypso::card::transaction::InconsistentDataException;
72using keypop::card::CardBrokenCommunicationException;
73using keypop::card::ReaderBrokenCommunicationException;
74using keypop::card::UnexpectedStatusWordException;
75using keypop::reader::CardCommunicationException;
76using keypop::reader::ReaderCommunicationException;
77using keypop::reader::selection::InvalidCardResponseException;
80const std::string TransactionManagerAdapter<
81 T>::MSG_THE_NUMBER_OF_COMMANDS_RESPONSES_DOES_NOT_MATCH_EXPECTED
82 =
"The number of commands/responses does not match. Expected ";
84const std::string TransactionManagerAdapter<T>::MSG_RESPONSES_GOT
88 TransactionManagerAdapter<T>::MSG_CARD_READER_COMMUNICATION_ERROR
89 =
"Failed to communicate with card reader";
91const std::string TransactionManagerAdapter<T>::MSG_CARD_COMMUNICATION_ERROR
92 =
"Failed to communicate with card";
94const std::string TransactionManagerAdapter<T>::MSG_WHILE_TRANSMITTING_COMMANDS
95 =
" while transmitting commands.";
97const std::string TransactionManagerAdapter<T>::MSG_PIN_NOT_AVAILABLE
98 =
"PIN is not available for this card";
100const std::string TransactionManagerAdapter<T>::MSG_RECORD_NUMBER
103const std::string TransactionManagerAdapter<T>::MSG_OFFSET =
"offset";
105const std::string TransactionManagerAdapter<T>::MSG_RECORD_DATA =
"record data";
107const std::string TransactionManagerAdapter<T>::MSG_RECORD_DATA_LENGTH
108 =
"record data length";
110const std::string TransactionManagerAdapter<T>::MSG_SECURE_SESSION_OPEN
111 =
"Secure session is open";
114 TransactionManagerAdapter<T>::MSG_PKI_MODE_IS_NOT_AVAILABLE_FOR_THIS_CARD
115 =
"PKI mode is not available for this card";
117const std::string TransactionManagerAdapter<T>::MSG_DATA_LENGTH =
"data length";
120TransactionManagerAdapter<T>::TransactionManagerAdapter(
121 std::shared_ptr<ProxyReaderApi> cardReader,
122 std::shared_ptr<CalypsoCardAdapter> card)
124, mCardReader(cardReader)
130TransactionManagerAdapter<T>::executeCardCommands(
131 const std::vector<std::shared_ptr<Command>>& commands,
132 ChannelControl channelControl)
135 std::vector<std::shared_ptr<ApduRequestSpi>> apduRequests
136 = getApduRequests(commands);
140 = std::make_shared<DtoAdapters::CardRequestAdapter>(apduRequests,
true);
143 std::shared_ptr<CardResponseApi> cardResponse
144 = transmitCardRequest(cardRequest, channelControl);
147 std::vector<std::shared_ptr<ApduResponseApi>> apduResponses
148 = cardResponse->getApduResponses();
155 if (apduResponses.size() > commands.size()) {
156 throw InconsistentDataException(
157 MSG_THE_NUMBER_OF_COMMANDS_RESPONSES_DOES_NOT_MATCH_EXPECTED
158 + std::to_string(commands.size()) + MSG_RESPONSES_GOT
159 + std::to_string(apduResponses.size())
160 + getTransactionAuditDataAsString());
168 for (
int i = 0; i < static_cast<int>(apduResponses.size()); i++) {
169 std::shared_ptr<Command> command = commands[i];
171 std::cout <<
"apdu cmd: " << command->getName() << std::endl;
172 std::cout <<
"apdu resp: "
173 << HexUtil::toHex(apduResponses[i]->getDataOut())
176 parseCommandResponse(command, apduResponses[i]);
177 handleCommandPostProcessing(i, commands);
178 }
catch (
const CardCommandException& e) {
180 = command->getApduResponse() !=
nullptr
182 static_cast<std::uint16_t
>(
183 command->getApduResponse()->getStatusWord()))
185 throw InvalidCardResponseException(
186 "Failed to process card response. Command: "
187 + command->getCommandRef().getName() +
", SW: " + sw
188 + getTransactionAuditDataAsString(),
197 if (apduResponses.size() < commands.size()) {
198 throw InconsistentDataException(
199 MSG_THE_NUMBER_OF_COMMANDS_RESPONSES_DOES_NOT_MATCH_EXPECTED
200 + std::to_string(commands.size()) + MSG_RESPONSES_GOT
201 + std::to_string(apduResponses.size())
202 + getTransactionAuditDataAsString());
208TransactionManagerAdapter<T>::parseCommandResponse(
209 const std::shared_ptr<Command>& command,
210 const std::shared_ptr<ApduResponseApi>& apduResponse)
212 command->parseResponse(apduResponse);
217TransactionManagerAdapter<T>::handleCommandPostProcessing(
219 const std::vector<std::shared_ptr<Command>>& )
224std::vector<std::shared_ptr<ApduRequestSpi>>
225TransactionManagerAdapter<T>::getApduRequests(
226 const std::vector<std::shared_ptr<Command>>& commands)
228 std::vector<std::shared_ptr<ApduRequestSpi>> apduRequests;
229 if (!commands.empty()) {
230 for (
const auto& command : commands) {
231 apduRequests.push_back(command->getApduRequest());
239std::shared_ptr<CardResponseApi>
240TransactionManagerAdapter<T>::transmitCardRequest(
241 std::shared_ptr<CardRequestSpi> cardRequest, ChannelControl channelControl)
243 std::shared_ptr<CardResponseApi> cardResponse;
246 cardResponse = mCardReader->transmitCardRequest(
247 cardRequest, mapToInternalChannelControl(channelControl));
249 }
catch (
const ReaderBrokenCommunicationException& e) {
250 saveTransactionAuditData(cardRequest, e.getCardResponse());
251 throw ReaderCommunicationException(
252 MSG_CARD_READER_COMMUNICATION_ERROR
253 + MSG_WHILE_TRANSMITTING_COMMANDS
254 + getTransactionAuditDataAsString(),
257 }
catch (
const CardBrokenCommunicationException& e) {
258 saveTransactionAuditData(cardRequest, e.getCardResponse());
259 throw CardCommunicationException(
260 MSG_CARD_COMMUNICATION_ERROR + MSG_WHILE_TRANSMITTING_COMMANDS
261 + getTransactionAuditDataAsString(),
264 }
catch (
const UnexpectedStatusWordException& e) {
265 cardResponse = e.getCardResponse();
268 saveTransactionAuditData(cardRequest, cardResponse);
275TransactionManagerAdapter<T>::getTransactionAuditDataAsString()
const
277 return std::string(
"\nTransaction audit JSON data: {")
278 +
"\"targetSmartCard\":" +
"FIXME"
280 +
"\"apdus\":" +
" FIXME"
285keypop::card::ChannelControl
286TransactionManagerAdapter<T>::mapToInternalChannelControl(
287 ChannelControl channelControl)
const
289 return keypop::card::valueOf(
static_cast<int>(channelControl));
294TransactionManagerAdapter<T>::saveTransactionAuditData(
295 const std::shared_ptr<CardRequestSpi>& cardRequest,
296 const std::shared_ptr<CardResponseApi>& cardResponse)
298 if (cardResponse !=
nullptr) {
299 std::vector<std::shared_ptr<ApduRequestSpi>> requests
300 = cardRequest->getApduRequests();
301 std::vector<std::shared_ptr<ApduResponseApi>> responses
302 = cardResponse->getApduResponses();
304 int responsesSize =
static_cast<int>(responses.size());
306 for (
int i = 0; i < static_cast<int>(requests.size()); i++) {
307 const std::vector<std::uint8_t> empty;
308 mTransactionAuditData.push_back(requests[i]->getApdu());
309 mTransactionAuditData.push_back(
310 (i < responsesSize) ? responses[i]->getApdu() : empty);
317TransactionManagerAdapter<T>::prepareSelectFile(std::uint16_t lid)
321 std::unique_ptr<CommandSelectFile>(
new CommandSelectFile(
322 getTransactionContext(), getCommandContext(), lid)));
329 return dynamic_cast<T&
>(*this);
334TransactionManagerAdapter<T>::prepareSelectFile(
335 SelectFileControl selectFileControl)
339 std::unique_ptr<CommandSelectFile>(
new CommandSelectFile(
340 getTransactionContext(),
342 selectFileControl)));
349 return dynamic_cast<T&
>(*this);
354TransactionManagerAdapter<T>::prepareGetData(GetDataTag tag)
357 if (getCommandContext()->isSecureSessionOpen()) {
358 throw IllegalStateException(MSG_SECURE_SESSION_OPEN);
362 case GetDataTag::FCI_FOR_CURRENT_DF:
364 std::make_shared<CommandGetDataFci>(
365 getTransactionContext(), getCommandContext()));
367 case GetDataTag::FCP_FOR_CURRENT_FILE:
369 std::make_shared<CommandGetDataFcp>(
370 getTransactionContext(), getCommandContext()));
372 case GetDataTag::EF_LIST:
374 std::make_shared<CommandGetDataEfList>(
375 getTransactionContext(), getCommandContext()));
377 case GetDataTag::TRACEABILITY_INFORMATION:
379 std::make_shared<CommandGetDataTraceabilityInformation>(
380 getTransactionContext(), getCommandContext()));
382 case GetDataTag::CARD_PUBLIC_KEY:
384 std::make_shared<CommandGetDataCardPublicKey>(
385 getTransactionContext(), getCommandContext()));
387 case GetDataTag::CARD_CERTIFICATE:
389 std::make_shared<CommandGetDataCertificate>(
390 getTransactionContext(), getCommandContext(),
true,
true));
392 std::make_shared<CommandGetDataCertificate>(
393 getTransactionContext(), getCommandContext(),
true,
false));
395 case GetDataTag::CA_CERTIFICATE:
397 std::make_shared<CommandGetDataCertificate>(
398 getTransactionContext(), getCommandContext(),
false,
true));
400 std::make_shared<CommandGetDataCertificate>(
401 getTransactionContext(),
407 throw UnsupportedOperationException(
408 "Unsupported GetDataTag: "
409 + std::to_string(
static_cast<int>(tag)));
417 return dynamic_cast<T&
>(*this);
422TransactionManagerAdapter<T>::preparePutData(
423 PutDataTag putDataTag,
const std::vector<std::uint8_t>& data)
425 if (getCommandContext()->isSecureSessionOpen()) {
426 throw IllegalStateException(MSG_SECURE_SESSION_OPEN);
429 switch (putDataTag) {
430 case PutDataTag::CARD_KEY_PAIR:
431 preparePutDataCardKeyPair(putDataTag, data);
433 case PutDataTag::CARD_CERTIFICATE:
434 preparePutDataCertificate(
435 putDataTag, data, CalypsoCardConstant::CARD_CERTIFICATE_SIZE);
437 case PutDataTag::CA_CERTIFICATE:
438 preparePutDataCertificate(
439 putDataTag, data, CalypsoCardConstant::CA_CERTIFICATE_SIZE);
442 throw UnsupportedOperationException(
443 "Unsupported PutDataTag: "
444 + std::to_string(
static_cast<int>(putDataTag)));
447 return dynamic_cast<T&
>(*this);
452TransactionManagerAdapter<T>::preparePutDataCardKeyPair(
453 PutDataTag putDataTag,
const std::vector<std::uint8_t>& data)
455 if (!mCard->isPkiModeSupported()) {
456 throw UnsupportedOperationException(
457 MSG_PKI_MODE_IS_NOT_AVAILABLE_FOR_THIS_CARD);
460 Assert::getInstance().isEqual(
461 data.size(), CalypsoCardConstant::CARD_KEY_PAIR_SIZE, MSG_DATA_LENGTH);
464 std::make_shared<CommandPutData>(
465 getTransactionContext(),
474TransactionManagerAdapter<T>::preparePutDataCertificate(
475 PutDataTag putDataTag,
476 const std::vector<std::uint8_t>& data,
479 std::shared_ptr<DtoAdapters::TransactionContextDto> transactionContext
480 = getTransactionContext();
481 std::shared_ptr<DtoAdapters::CommandContextDto> commandContext
482 = getCommandContext();
485 = getTransactionContext()->getCard()->getPayloadCapacity();
487 if (!mCard->isPkiModeSupported()) {
488 throw UnsupportedOperationException(
489 MSG_PKI_MODE_IS_NOT_AVAILABLE_FOR_THIS_CARD);
492 Assert::getInstance().isEqual(
493 data.size(), certificateSize, MSG_DATA_LENGTH);
496 std::make_shared<CommandPutData>(
504 - CalypsoCardConstant::TAG_CERTIFICATE_HEADER_SIZE)));
506 std::make_shared<CommandPutData>(
514 - CalypsoCardConstant::TAG_CERTIFICATE_HEADER_SIZE,
520TransactionManagerAdapter<T>::prepareReadRecord(
521 std::uint8_t sfi,
int recordNumber)
524 if (getCommandContext()->isSecureSessionOpen()) {
525 throw IllegalStateException(MSG_SECURE_SESSION_OPEN);
528 Assert::getInstance()
530 static_cast<int>(sfi),
531 CalypsoCardConstant::SFI_MIN,
532 CalypsoCardConstant::SFI_MAX,
536 CalypsoCardConstant::NB_REC_MIN,
537 CalypsoCardConstant::NB_REC_MAX,
544 std::unique_ptr<int> recordSize
545 = mCard->isLegacyCase1()
546 ? std::unique_ptr<int>(
547 new int(CalypsoCardConstant::LEGACY_REC_LENGTH))
551 std::make_shared<CommandReadRecords>(
552 getTransactionContext(),
556 CommandReadRecords::ReadMode::ONE_RECORD,
557 std::move(recordSize),
558 recordSize !=
nullptr ? *recordSize : 0));
565 return dynamic_cast<T&
>(*this);
570TransactionManagerAdapter<T>::prepareReadRecords(
571 std::uint8_t sfi,
int fromRecordNumber,
int toRecordNumber,
int recordSize)
574 Assert::getInstance()
576 static_cast<int>(sfi),
577 CalypsoCardConstant::SFI_MIN,
578 CalypsoCardConstant::SFI_MAX,
582 CalypsoCardConstant::NB_REC_MIN,
583 CalypsoCardConstant::NB_REC_MAX,
588 CalypsoCardConstant::NB_REC_MAX,
590 .isInRange(recordSize, 0, getPayloadCapacity(),
"recordSize");
592 if (toRecordNumber == fromRecordNumber
593 || (mCard->getProductType()
594 != CalypsoCard::ProductType::PRIME_REVISION_3
595 && mCard->getProductType()
596 != CalypsoCard::ProductType::LIGHT)) {
602 if (canConfigureReadOnOpenSecureSession()) {
604 = std::dynamic_pointer_cast<CommandOpenSecureSession>(
605 mCommands[mCommands.size() - 1]);
606 session->configureReadMode(sfi, fromRecordNumber, recordSize);
610 for (
int i = fromRecordNumber; i <= toRecordNumber; i++) {
612 std::make_shared<CommandReadRecords>(
613 getTransactionContext(),
617 CommandReadRecords::ReadMode::ONE_RECORD,
618 std::unique_ptr<int>(
new int(recordSize)),
629 const int nbBytesPerRecord = recordSize + 2;
630 const int nbRecordsPerApdu
631 = getPayloadCapacity() / nbBytesPerRecord;
632 const int dataSizeMaxPerApdu = nbRecordsPerApdu * nbBytesPerRecord;
634 int currentRecordNumber = fromRecordNumber;
635 int nbRecordsRemainingToRead
636 = toRecordNumber - fromRecordNumber + 1;
638 while (currentRecordNumber < toRecordNumber) {
640 = nbRecordsRemainingToRead <= nbRecordsPerApdu
641 ? nbRecordsRemainingToRead * nbBytesPerRecord
642 : dataSizeMaxPerApdu;
645 std::make_shared<CommandReadRecords>(
646 getTransactionContext(),
650 CommandReadRecords::ReadMode::MULTIPLE_RECORD,
651 std::unique_ptr<int>(
new int(currentLength)),
653 currentRecordNumber += (currentLength / nbBytesPerRecord);
654 nbRecordsRemainingToRead -= (currentLength / nbBytesPerRecord);
661 if (currentRecordNumber == toRecordNumber) {
663 std::make_shared<CommandReadRecords>(
664 getTransactionContext(),
668 CommandReadRecords::ReadMode::ONE_RECORD,
669 std::unique_ptr<int>(
new int(recordSize)),
679 return dynamic_cast<T&
>(*this);
684TransactionManagerAdapter<T>::prepareReadRecordsPartially(
686 int fromRecordNumber,
692 if (mCard->getProductType()
693 != CalypsoCard::ProductType::PRIME_REVISION_3
694 && mCard->getProductType() != CalypsoCard::ProductType::LIGHT) {
695 throw UnsupportedOperationException(
696 std::string(
"'Read Record Multiple' command is not available ")
700 if (getCommandContext()->isSecureSessionOpen()) {
701 throw IllegalStateException(MSG_SECURE_SESSION_OPEN);
704 Assert::getInstance()
706 static_cast<int>(sfi),
707 CalypsoCardConstant::SFI_MIN,
708 CalypsoCardConstant::SFI_MAX,
712 CalypsoCardConstant::NB_REC_MIN,
713 CalypsoCardConstant::NB_REC_MAX,
718 CalypsoCardConstant::NB_REC_MAX,
722 CalypsoCardConstant::OFFSET_MIN,
723 CalypsoCardConstant::OFFSET_MAX,
727 CalypsoCardConstant::DATA_LENGTH_MIN,
728 getPayloadCapacity(),
731 const int nbRecordsPerApdu = getPayloadCapacity() / nbBytesToRead;
733 int currentRecordNumber = fromRecordNumber;
735 while (currentRecordNumber <= toRecordNumber) {
737 std::make_shared<CommandReadRecordMultiple>(
738 getTransactionContext(),
741 static_cast<std::uint8_t
>(currentRecordNumber),
742 static_cast<std::uint8_t
>(offset),
743 static_cast<std::uint8_t
>(nbBytesToRead)));
744 currentRecordNumber += nbRecordsPerApdu;
752 return dynamic_cast<T&
>(*this);
757TransactionManagerAdapter<T>::prepareReadBinary(
758 std::uint8_t sfi,
int offset,
int nbBytesToRead)
761 if (mCard->getProductType()
762 != CalypsoCard::ProductType::PRIME_REVISION_3) {
763 if (mCard->getProductType()
764 == CalypsoCard::ProductType::PRIME_REVISION_2) {
766 std::string(
"Command may not be supported for ")
767 +
"PRIME_REVISION_2 card: Read Binary");
769 throw UnsupportedOperationException(
770 "'Read Binary' command is not available for this card");
774 Assert::getInstance()
776 static_cast<int>(sfi),
777 CalypsoCardConstant::SFI_MIN,
778 CalypsoCardConstant::SFI_MAX,
782 CalypsoCardConstant::OFFSET_MIN,
783 CalypsoCardConstant::OFFSET_BINARY_MAX,
785 .greaterOrEqual(nbBytesToRead, 1,
"nbBytesToRead");
787 if (sfi > 0 && offset > 255) {
793 std::make_shared<CommandReadBinary>(
794 getTransactionContext(), getCommandContext(), sfi, 0, 1));
797 int currentOffset = offset;
798 int nbBytesRemainingToRead = nbBytesToRead;
802 = std::min(nbBytesRemainingToRead, getPayloadCapacity());
805 std::make_shared<CommandReadBinary>(
806 getTransactionContext(),
812 currentOffset += currentLength;
813 nbBytesRemainingToRead -= currentLength;
815 }
while (nbBytesRemainingToRead > 0);
817 }
catch (
const RuntimeException&) {
822 return dynamic_cast<T&
>(*this);
827TransactionManagerAdapter<T>::prepareReadCounter(
828 std::uint8_t sfi,
int nbCountersToRead)
830 return prepareReadRecords(sfi, 1, 1, nbCountersToRead * 3);
835TransactionManagerAdapter<T>::prepareSearchRecords(
836 std::shared_ptr<SearchCommandData> data)
839 if (mCard->getProductType()
840 != CalypsoCard::ProductType::PRIME_REVISION_3) {
841 throw UnsupportedOperationException(
842 std::string(
"'Search Record Multiple' command is not available")
846 Assert::getInstance().notNull(data,
"data");
849 = std::dynamic_pointer_cast<DtoAdapters::SearchCommandDataAdapter>(
852 throw IllegalArgumentException(
853 "Cannot cast 'data' to SearchCommandDataAdapter. Actual type: "
857 if (getCommandContext()->isSecureSessionOpen()) {
858 throw IllegalStateException(MSG_SECURE_SESSION_OPEN);
861 Assert::getInstance()
863 static_cast<int>(dataAdapter->getSfi()),
864 CalypsoCardConstant::SFI_MIN,
865 CalypsoCardConstant::SFI_MAX,
868 dataAdapter->getRecordNumber(),
869 CalypsoCardConstant::NB_REC_MIN,
870 CalypsoCardConstant::NB_REC_MAX,
873 dataAdapter->getOffset(),
874 CalypsoCardConstant::OFFSET_MIN,
875 CalypsoCardConstant::OFFSET_MAX,
878 dataAdapter->getSearchData().size(),
879 CalypsoCardConstant::DATA_LENGTH_MIN,
880 getPayloadCapacity(),
882 if (dataAdapter->getMask().size() != 0) {
883 Assert::getInstance().isInRange(
884 dataAdapter->getMask().size(),
885 CalypsoCardConstant::DATA_LENGTH_MIN,
886 dataAdapter->getSearchData().size(),
891 std::make_shared<CommandSearchRecordMultiple>(
892 getTransactionContext(), getCommandContext(), dataAdapter));
899 return dynamic_cast<T&
>(*this);
904TransactionManagerAdapter<T>::prepareCheckPinStatus()
907 if (!mCard->isPinFeatureAvailable()) {
908 throw UnsupportedOperationException(MSG_PIN_NOT_AVAILABLE);
912 std::make_shared<CommandVerifyPin>(
913 getTransactionContext(), getCommandContext()));
920 return dynamic_cast<T&
>(*this);
925TransactionManagerAdapter<T>::prepareAppendRecord(
926 std::uint8_t sfi,
const std::vector<std::uint8_t>& recordData)
929 Assert::getInstance()
931 static_cast<int>(sfi),
932 CalypsoCardConstant::SFI_MIN,
933 CalypsoCardConstant::SFI_MAX,
938 getPayloadCapacity(),
939 MSG_RECORD_DATA_LENGTH);
941 auto command = std::make_shared<CommandAppendRecord>(
942 getTransactionContext(), getCommandContext(), sfi, recordData);
943 prepareNewSecureSessionIfNeeded(command);
944 mCommands.push_back(command);
951 return dynamic_cast<T&
>(*this);
956TransactionManagerAdapter<T>::prepareUpdateRecord(
959 const std::vector<std::uint8_t>& recordData)
962 Assert::getInstance()
964 static_cast<int>(sfi),
965 CalypsoCardConstant::SFI_MIN,
966 CalypsoCardConstant::SFI_MAX,
970 CalypsoCardConstant::NB_REC_MIN,
971 CalypsoCardConstant::NB_REC_MAX,
976 getPayloadCapacity(),
977 MSG_RECORD_DATA_LENGTH);
979 auto command = std::make_shared<CommandUpdateRecord>(
980 getTransactionContext(),
983 static_cast<std::uint8_t
>(recordNumber),
985 prepareNewSecureSessionIfNeeded(command);
986 mCommands.push_back(command);
993 return dynamic_cast<T&
>(*this);
998TransactionManagerAdapter<T>::prepareWriteRecord(
1001 const std::vector<std::uint8_t>& recordData)
1004 Assert::getInstance()
1006 static_cast<int>(sfi),
1007 CalypsoCardConstant::SFI_MIN,
1008 CalypsoCardConstant::SFI_MAX,
1012 CalypsoCardConstant::NB_REC_MIN,
1013 CalypsoCardConstant::NB_REC_MAX,
1018 getPayloadCapacity(),
1019 MSG_RECORD_DATA_LENGTH);
1020 auto command = std::make_shared<CommandWriteRecord>(
1021 getTransactionContext(),
1022 getCommandContext(),
1024 static_cast<std::uint8_t
>(recordNumber),
1026 prepareNewSecureSessionIfNeeded(command);
1027 mCommands.push_back(command);
1034 return dynamic_cast<T&
>(*this);
1037template <
typename T>
1039TransactionManagerAdapter<T>::prepareUpdateBinary(
1040 std::uint8_t sfi,
int offset,
const std::vector<std::uint8_t>& data)
1042 return prepareUpdateOrWriteBinary(
true, sfi, offset, data);
1045template <
typename T>
1047TransactionManagerAdapter<T>::prepareWriteBinary(
1048 std::uint8_t sfi,
int offset,
const std::vector<std::uint8_t>& data)
1050 return prepareUpdateOrWriteBinary(
false, sfi, offset, data);
1053template <
typename T>
1055TransactionManagerAdapter<T>::prepareUpdateOrWriteBinary(
1056 bool isUpdateCommand,
1059 const std::vector<std::uint8_t>& data)
1062 if (mCard->getProductType()
1063 != CalypsoCard::ProductType::PRIME_REVISION_3) {
1064 if (mCard->getProductType()
1065 == CalypsoCard::ProductType::PRIME_REVISION_2) {
1067 std::string(
"Command may not be supported for ")
1068 +
"PRIME_REVISION_2 card: Update/Write Binary");
1070 throw UnsupportedOperationException(
1071 std::string(
"'Update/Write Binary' command is not ")
1072 +
"available for this card");
1076 Assert::getInstance()
1078 static_cast<int>(sfi),
1079 CalypsoCardConstant::SFI_MIN,
1080 CalypsoCardConstant::SFI_MAX,
1084 CalypsoCardConstant::OFFSET_MIN,
1085 CalypsoCardConstant::OFFSET_BINARY_MAX,
1087 .notEmpty(data,
"data");
1089 if (sfi > 0 && offset > 255) {
1094 mCommands.push_back(
1095 std::make_shared<CommandReadBinary>(
1096 getTransactionContext(), getCommandContext(), sfi, 0, 1));
1099 const int dataLength =
static_cast<int>(data.size());
1100 int currentOffset = offset;
1101 int currentIndex = 0;
1105 = std::min(dataLength - currentIndex, getPayloadCapacity());
1107 auto command = std::make_shared<CommandUpdateOrWriteBinary>(
1109 getTransactionContext(),
1110 getCommandContext(),
1113 Arrays::copyOfRange(
1114 data, currentIndex, currentIndex + currentLength));
1115 prepareNewSecureSessionIfNeeded(command);
1116 mCommands.push_back(command);
1118 currentOffset += currentLength;
1119 currentIndex += currentLength;
1121 }
while (currentIndex < dataLength);
1128 return dynamic_cast<T&
>(*this);
1131template <
typename T>
1133TransactionManagerAdapter<T>::prepareIncreaseCounter(
1134 std::uint8_t sfi,
int counterNumber,
int incValue)
1136 return prepareIncreaseOrDecreaseCounter(
1137 false, sfi, counterNumber, incValue);
1140template <
typename T>
1142TransactionManagerAdapter<T>::prepareIncreaseCounters(
1143 std::uint8_t sfi,
const std::map<int, int>& counterNumberToIncValueMap)
1145 return prepareIncreaseOrDecreaseCounters(
1146 false, sfi, counterNumberToIncValueMap);
1149template <
typename T>
1151TransactionManagerAdapter<T>::prepareDecreaseCounter(
1152 std::uint8_t sfi,
int counterNumber,
int decValue)
1154 return prepareIncreaseOrDecreaseCounter(
true, sfi, counterNumber, decValue);
1157template <
typename T>
1159TransactionManagerAdapter<T>::prepareDecreaseCounters(
1160 std::uint8_t sfi,
const std::map<int, int>& counterNumberToDecValueMap)
1162 return prepareIncreaseOrDecreaseCounters(
1163 true, sfi, counterNumberToDecValueMap);
1166template <
typename T>
1168TransactionManagerAdapter<T>::prepareSetCounter(
1169 std::uint8_t sfi,
int counterNumber,
int newValue)
1172 std::shared_ptr<int> oldValue =
nullptr;
1173 std::shared_ptr<ElementaryFile> ef = mCard->getFileBySfi(sfi);
1174 if (ef !=
nullptr) {
1175 oldValue = ef->getData()->getContentAsCounterValue(
1176 counterNumber != 0 ? counterNumber : 1);
1178 if (oldValue ==
nullptr) {
1179 throw IllegalStateException(
1180 std::string(
"The counter value is not available. SFI: ")
1181 + std::to_string(sfi)
1182 +
", Counter: " + std::to_string(counterNumber));
1185 int delta = newValue - *oldValue.get();
1188 "Increment counter #% (file %h) from % to %\n",
1190 HexUtil::toHex(sfi),
1193 prepareIncreaseCounter(sfi, counterNumber, delta);
1195 }
else if (delta < 0) {
1197 "Decrement counter #% (file %h) from % to %",
1199 HexUtil::toHex(sfi),
1202 prepareDecreaseCounter(sfi, counterNumber, -delta);
1206 "Counter #% (sfi %h) already set to the desired value %\n",
1208 HexUtil::toHex(sfi),
1217 return dynamic_cast<T&
>(*this);
1220template <
typename T>
1222TransactionManagerAdapter<T>::prepareIncreaseOrDecreaseCounter(
1223 bool isDecreaseCommand,
1229 Assert::getInstance()
1231 static_cast<int>(sfi),
1232 CalypsoCardConstant::SFI_MIN,
1233 CalypsoCardConstant::SFI_MAX,
1238 getPayloadCapacity() / 3,
1242 CalypsoCardConstant::CNT_VALUE_MIN,
1243 CalypsoCardConstant::CNT_VALUE_MAX,
1246 auto command = std::make_shared<CommandIncreaseOrDecrease>(
1248 getTransactionContext(),
1249 getCommandContext(),
1253 prepareNewSecureSessionIfNeeded(command);
1254 mCommands.push_back(command);
1261 return dynamic_cast<T&
>(*this);
1264template <
typename T>
1266TransactionManagerAdapter<T>::prepareIncreaseOrDecreaseCounters(
1267 bool isDecreaseCommand,
1269 const std::map<int, int>& counterNumberToIncDecValueMap)
1272 Assert::getInstance()
1274 static_cast<int>(sfi),
1275 CalypsoCardConstant::SFI_MIN,
1276 CalypsoCardConstant::SFI_MAX,
1279 counterNumberToIncDecValueMap.size(),
1281 getPayloadCapacity() / 3,
1282 "counterNumberToIncDecValueMap");
1284 for (
const auto& entry : counterNumberToIncDecValueMap) {
1285 Assert::getInstance()
1288 CalypsoCardConstant::NUM_CNT_MIN,
1289 getPayloadCapacity() / 3,
1290 "counterNumberToIncDecValueMapKey")
1293 CalypsoCardConstant::CNT_VALUE_MIN,
1294 CalypsoCardConstant::CNT_VALUE_MAX,
1295 "counterNumberToIncDecValueMapValue");
1298 if (mCard->getProductType()
1299 != CalypsoCard::ProductType::PRIME_REVISION_3
1300 && mCard->getProductType()
1301 != CalypsoCard::ProductType::PRIME_REVISION_2) {
1302 for (
const auto& entry : counterNumberToIncDecValueMap) {
1303 if (isDecreaseCommand) {
1304 prepareDecreaseCounter(sfi, entry.first, entry.second);
1307 prepareIncreaseCounter(sfi, entry.first, entry.second);
1312 const int nbCountersPerApdu = getPayloadCapacity() / 4;
1313 if (
static_cast<int>(counterNumberToIncDecValueMap.size())
1314 <= nbCountersPerApdu) {
1316 = std::make_shared<CommandIncreaseOrDecreaseMultiple>(
1318 getTransactionContext(),
1319 getCommandContext(),
1321 counterNumberToIncDecValueMap);
1323 prepareNewSecureSessionIfNeeded(command);
1324 mCommands.push_back(command);
1332 std::map<int, int> map;
1333 for (
const auto& entry : counterNumberToIncDecValueMap) {
1335 map[entry.first] = entry.second;
1336 if (i == nbCountersPerApdu) {
1337 auto command = std::make_shared<
1338 CommandIncreaseOrDecreaseMultiple>(
1340 getTransactionContext(),
1341 getCommandContext(),
1345 prepareNewSecureSessionIfNeeded(command);
1346 mCommands.push_back(command);
1353 = std::make_shared<CommandIncreaseOrDecreaseMultiple>(
1355 getTransactionContext(),
1356 getCommandContext(),
1360 prepareNewSecureSessionIfNeeded(command);
1361 mCommands.push_back(command);
1371 return dynamic_cast<T&
>(*this);
1374template <
typename T>
1376TransactionManagerAdapter<T>::prepareSvReadAllLogs()
1379 if (!mCard->isSvFeatureAvailable()) {
1380 throw UnsupportedOperationException(
1381 "Stored Value is not available for this card");
1384 if (mCard->getApplicationSubtype()
1385 != CalypsoCardConstant::STORED_VALUE_FILE_STRUCTURE_ID) {
1386 throw UnsupportedOperationException(
1387 "The currently selected application is not an SV application");
1391 const std::vector<std::uint8_t> empty;
1392 mCard->setSvData((std::uint8_t)0, empty, empty, 0, 0);
1394 CalypsoCardConstant::SV_RELOAD_LOG_FILE_SFI,
1396 CalypsoCardConstant::SV_RELOAD_LOG_FILE_NB_REC,
1397 CalypsoCardConstant::SV_LOG_FILE_REC_LENGTH);
1399 CalypsoCardConstant::SV_DEBIT_LOG_FILE_SFI,
1401 CalypsoCardConstant::SV_DEBIT_LOG_FILE_NB_REC,
1402 CalypsoCardConstant::SV_LOG_FILE_REC_LENGTH);
1409 return dynamic_cast<T&
>(*this);
1412template <
typename T>
1414TransactionManagerAdapter<T>::prepareGenerateAsymmetricKeyPair()
1416 if (!mCard->isPkiModeSupported()) {
1417 throw UnsupportedOperationException(
1418 MSG_PKI_MODE_IS_NOT_AVAILABLE_FOR_THIS_CARD);
1421 if (getTransactionContext()->isSecureSessionOpen()) {
1422 throw IllegalStateException(MSG_SECURE_SESSION_OPEN);
1425 mCommands.push_back(
1426 std::unique_ptr<CommandGenerateAsymmetricKeyPair>(
1427 new CommandGenerateAsymmetricKeyPair(
1428 getTransactionContext(), getCommandContext())));
1430 return dynamic_cast<T&
>(*this);
1433template <
typename T>
1434const std::vector<std::vector<std::uint8_t>>&
1435TransactionManagerAdapter<T>::getTransactionAuditData()
const
1438 return mTransactionAuditData;
1446#include "keypop/calypso/card/cpp/SecureExtendedModeTransactionManagerBase.hpp"
1447#include "keypop/calypso/card/cpp/SecureRegularModeTransactionManagerBase.hpp"
1448#include "keypop/calypso/card/transaction/FreeTransactionManager.hpp"
1449#include "keypop/calypso/card/transaction/SecurePkiModeTransactionManager.hpp"
1451template class keyple::card::calypso::TransactionManagerAdapter<
1452 keypop::calypso::card::transaction::FreeTransactionManager>;
1454template class keyple::card::calypso::TransactionManagerAdapter<
1455 keypop::calypso::card::cpp::SecureExtendedModeTransactionManagerBase>;
1457template class keyple::card::calypso::TransactionManagerAdapter<
1458 keypop::calypso::card::cpp::SecureRegularModeTransactionManagerBase>;
1460template class keyple::card::calypso::TransactionManagerAdapter<
1461 keypop::calypso::card::transaction::SecurePkiModeTransactionManager>;