16#include "FileHeader.h"
20#include "IllegalArgumentException.h"
21#include "IllegalStateException.h"
35using namespace calypsonet::terminal::calypso;
36using namespace keyple::core::util;
37using namespace keyple::core::util::cpp;
38using namespace keyple::core::util::cpp::exception;
40const std::string CalypsoCardAdapter::PATTERN_1_BYTE_HEX =
"%02Xh";
41const std::string CalypsoCardAdapter::PATTERN_2_BYTES_HEX =
"%04Xh";
43const int CalypsoCardAdapter::CARD_REV1_ATR_LENGTH = 20;
44const int CalypsoCardAdapter::REV1_CARD_DEFAULT_WRITE_OPERATIONS_NUMBER_SUPPORTED_PER_SESSION = 3;
45const int CalypsoCardAdapter::REV2_CARD_DEFAULT_WRITE_OPERATIONS_NUMBER_SUPPORTED_PER_SESSION = 6;
46const int CalypsoCardAdapter::SI_BUFFER_SIZE_INDICATOR = 0;
47const int CalypsoCardAdapter::SI_PLATFORM = 1;
48const int CalypsoCardAdapter::SI_APPLICATION_TYPE = 2;
49const int CalypsoCardAdapter::SI_APPLICATION_SUBTYPE = 3;
50const int CalypsoCardAdapter::SI_SOFTWARE_ISSUER = 4;
51const int CalypsoCardAdapter::SI_SOFTWARE_VERSION = 5;
52const int CalypsoCardAdapter::SI_SOFTWARE_REVISION = 6;
53const uint8_t CalypsoCardAdapter::PAY_LOAD_CAPACITY = 250;
55const uint8_t CalypsoCardAdapter::APP_TYPE_WITH_CALYPSO_PIN = 0x01;
56const uint8_t CalypsoCardAdapter::APP_TYPE_WITH_CALYPSO_SV = 0x02;
57const uint8_t CalypsoCardAdapter::APP_TYPE_RATIFICATION_COMMAND_REQUIRED = 0x04;
58const uint8_t CalypsoCardAdapter::APP_TYPE_CALYPSO_REV_32_MODE = 0x08;
59const uint8_t CalypsoCardAdapter::APP_TYPE_WITH_PUBLIC_AUTHENTICATION = 0x10;
61const std::vector<int> CalypsoCardAdapter::BUFFER_SIZE_INDICATOR_TO_BUFFER_SIZE = {
62 0, 0, 0, 0, 0, 0, 215, 256, 304, 362, 430, 512, 608, 724, 861, 1024, 1217, 1448, 1722, 2048,
63 2435, 2896, 3444, 4096, 4870, 5792, 6888, 8192, 9741, 11585, 13777, 16384, 19483, 23170,
64 27554, 32768, 38967, 46340, 55108, 65536, 77935, 92681, 110217, 131072, 155871, 185363,
65 220435, 262144, 311743, 370727, 440871, 524288, 623487, 741455, 881743, 1048576
69: mIsExtendedModeSupported(false),
70 mIsRatificationOnDeselectSupported(false),
71 mIsSvFeatureAvailable(false),
72 mIsPinFeatureAvailable(false),
73 mIsPkiModeSupported(false),
74 mIsDfInvalidated(false),
77 mModificationsCounterMax(0),
78 mIsModificationCounterInBytes(true),
84 mApplicationSubType(0),
86 mSessionModification(0) {}
90 mPowerOnData = powerOnData;
96 const std::vector<uint8_t> atr = HexUtil::toByteArray(powerOnData);
99 if (atr.size() != CARD_REV1_ATR_LENGTH) {
100 throw IllegalArgumentException(
"Unexpected ATR length: " + powerOnData);
104 mCalypsoSerialNumber = std::vector<uint8_t>(8);
110 System::arraycopy(atr, 12, mCalypsoSerialNumber, 4, 4);
111 mModificationsCounterMax = REV1_CARD_DEFAULT_WRITE_OPERATIONS_NUMBER_SUPPORTED_PER_SESSION;
113 mStartupInfo = std::vector<uint8_t>(7);
116 mStartupInfo[0] =
static_cast<uint8_t
>(mModificationsCounterMax);
119 System::arraycopy(atr, 6, mStartupInfo, 1, 6);
121 mIsRatificationOnDeselectSupported =
true;
123 mProductType = ProductType::PRIME_REVISION_1;
128 const std::shared_ptr<ApduResponseApi> selectApplicationResponse)
130 mSelectApplicationResponse = selectApplicationResponse;
132 if (selectApplicationResponse->getDataOut().size() == 0) {
141 auto cardGetDataFci = std::make_shared<CmdCardGetDataFci>();
142 const auto& cmdCardGetDataFci = cardGetDataFci->setApduResponse(selectApplicationResponse);
144 if (!cmdCardGetDataFci.isValidCalypsoFCI()) {
145 throw IllegalArgumentException(
"Bad FCI format.");
148 mIsDfInvalidated = cmdCardGetDataFci.isDfInvalidated();
151 mDfName = cmdCardGetDataFci.getDfName();
152 mCalypsoSerialNumber = cmdCardGetDataFci.getApplicationSerialNumber();
155 mStartupInfo = cmdCardGetDataFci.getDiscretionaryData();
164 mApplicationType = mStartupInfo[SI_APPLICATION_TYPE];
165 mProductType = computeProductType(mApplicationType & 0xFF);
168 mApplicationSubType = mStartupInfo[SI_APPLICATION_SUBTYPE];
169 if (mApplicationSubType == 0x00 || mApplicationSubType == 0xFF) {
170 throw IllegalArgumentException(
"Unexpected application subtype: " +
171 std::to_string(mApplicationSubType));
174 mSessionModification = mStartupInfo[SI_BUFFER_SIZE_INDICATOR];
176 if (mProductType == ProductType::PRIME_REVISION_2) {
180 mIsModificationCounterInBytes =
false;
181 mModificationsCounterMax = REV2_CARD_DEFAULT_WRITE_OPERATIONS_NUMBER_SUPPORTED_PER_SESSION;
183 }
else if (mProductType == ProductType::BASIC) {
185 if (mSessionModification < 0x04 || mSessionModification > 0x37) {
186 throw IllegalArgumentException(
"Wrong session modification value for a Basic type " \
187 "(should be between 04h and 37h): " +
188 std::to_string(mSessionModification));
192 mIsModificationCounterInBytes =
false;
193 mModificationsCounterMax = 3;
201 if (mSessionModification < 0x06 || mSessionModification > 0x37) {
202 throw IllegalArgumentException(
"Session modifications byte should be in range 06h to" \
204 std::to_string(mSessionModification));
207 mModificationsCounterMax = BUFFER_SIZE_INDICATOR_TO_BUFFER_SIZE[mSessionModification];
211 if (mProductType == ProductType::PRIME_REVISION_3) {
212 mIsExtendedModeSupported = (mApplicationType & APP_TYPE_CALYPSO_REV_32_MODE) != 0;
213 mIsRatificationOnDeselectSupported =
214 (mApplicationType & APP_TYPE_RATIFICATION_COMMAND_REQUIRED) == 0;
215 mIsPkiModeSupported = (mApplicationType & APP_TYPE_WITH_PUBLIC_AUTHENTICATION) != 0;
218 if (mProductType == ProductType::PRIME_REVISION_3 ||
219 mProductType == ProductType::PRIME_REVISION_2) {
220 mIsSvFeatureAvailable = (mApplicationType & APP_TYPE_WITH_CALYPSO_SV) != 0;
221 mIsPinFeatureAvailable = (mApplicationType & APP_TYPE_WITH_CALYPSO_PIN) != 0;
224 mIsHce = (mCalypsoSerialNumber[3] & 0x80) == 0x80;
229 if (applicationType == 0) {
230 throw IllegalArgumentException(
"Invalid application type 00h");
231 }
else if (applicationType == 0xFF) {
232 return ProductType::UNKNOWN;
233 }
else if (applicationType <= 0x1F) {
234 return ProductType::PRIME_REVISION_2;
235 }
else if (applicationType >= 0x90 && applicationType <= 0x97) {
236 return ProductType::LIGHT;
237 }
else if (applicationType >= 0x98 && applicationType <= 0x9F) {
238 return ProductType::BASIC;
241 return ProductType::PRIME_REVISION_3;
261 return mCalypsoSerialNumber;
266 std::vector<uint8_t> applicationSerialNumber = mCalypsoSerialNumber;
267 applicationSerialNumber[0] = 0;
268 applicationSerialNumber[1] = 0;
270 return applicationSerialNumber;
281 return PAY_LOAD_CAPACITY;
286 return mIsModificationCounterInBytes;
291 return mModificationsCounterMax;
296 return mStartupInfo[SI_PLATFORM];
301 return mApplicationType;
306 return mIsExtendedModeSupported;
311 return mIsRatificationOnDeselectSupported;
316 return mIsSvFeatureAvailable;
321 return mIsPinFeatureAvailable;
326 return mIsPkiModeSupported;
331 return mApplicationSubType;
336 return mStartupInfo[SI_SOFTWARE_ISSUER];
341 return mStartupInfo[SI_SOFTWARE_VERSION];
346 return mStartupInfo[SI_SOFTWARE_REVISION];
351 return mSessionModification;
357 return mTraceabilityInformation;
362 return mIsDfInvalidated;
367 if (mIsDfRatified !=
nullptr) {
368 return *mIsDfRatified.get();
371 throw IllegalStateException(
"Unable to determine the ratification status. No session was " \
377 if (mTransactionCounter ==
nullptr) {
378 throw IllegalStateException(
"Unable to determine the transaction counter. No session was " \
382 return *mTransactionCounter.get();
387 mTransactionCounter = std::make_shared<int>(transactionCounter);
391 const std::vector<uint8_t>& svGetHeader,
392 const std::vector<uint8_t>& svGetData,
394 const int svLastTNum,
395 const std::shared_ptr<SvLoadLogRecord> svLoadLogRecord,
396 const std::shared_ptr<SvDebitLogRecord> svDebitLogRecord)
399 mSvGetHeader = svGetHeader;
400 mSvGetData = svGetData;
401 mSvBalance = std::make_shared<int>(svBalance);
402 mSvLastTNum = svLastTNum;
405 if (mSvLoadLogRecord ==
nullptr) {
406 mSvLoadLogRecord = svLoadLogRecord;
409 if (mSvDebitLogRecord ==
nullptr) {
410 mSvDebitLogRecord = svDebitLogRecord;
416 if (mSvBalance ==
nullptr) {
417 throw IllegalStateException(
"No SV Get command has been executed.");
420 return *mSvBalance.get();
425 if (mSvBalance ==
nullptr) {
426 new IllegalStateException(
"No SV Get command has been executed.");
434 if (mSvLoadLogRecord ==
nullptr) {
436 const std::shared_ptr<ElementaryFile> ef =
439 const std::vector<uint8_t> logRecord = ef->getData()->getContent();
440 mSvLoadLogRecord = std::make_shared<SvLoadLogRecordAdapter>(logRecord, 0);
444 return mSvLoadLogRecord;
449 if (mSvDebitLogRecord ==
nullptr) {
451 const std::vector<std::shared_ptr<SvDebitLogRecord>> svDebitLogRecords =
453 mSvDebitLogRecord = svDebitLogRecords[0];
456 return mSvDebitLogRecord;
462 std::vector<std::shared_ptr<SvDebitLogRecord>> svDebitLogRecords;
465 const std::shared_ptr<ElementaryFile> ef =
468 return svDebitLogRecords;
471 const std::map<const uint8_t, std::vector<uint8_t>>& logRecords =
472 ef->getData()->getAllRecordsContent();
473 for (
const auto& entry : logRecords) {
474 svDebitLogRecords.push_back(std::make_shared<SvDebitLogRecordAdapter>(entry.second, 0));
477 return svDebitLogRecords;
482 mIsDfRatified = std::make_shared<bool>(dfRatified);
487 return mCalypsoCardClass;
492 return mDirectoryHeader;
496 const std::shared_ptr<DirectoryHeader> directoryHeader)
498 mDirectoryHeader = directoryHeader;
499 mIsDfInvalidated = (directoryHeader->getDfStatus() & 0x01) != 0;
510 for (
const auto& ef : mFiles) {
511 if (ef->getSfi() == sfi) {
516 mLogger->warn(
"EF with SFI % is not found\n", sfi);
523 for (
const auto& ef : mFiles) {
524 if (ef->getHeader() !=
nullptr && ef->getHeader()->getLid() == lid) {
529 mLogger->warn(
"EF with LID % is not found\n", lid);
534const std::map<const uint8_t, const std::shared_ptr<ElementaryFile>>
537 std::map<const uint8_t, const std::shared_ptr<ElementaryFile>> res;
538 for (
const auto& ef : mFiles) {
539 if (ef->getSfi() != 0) {
540 res.insert({ef->getSfi(), ef});
552void CalypsoCardAdapter::updateCurrentSfi(
const uint8_t sfi)
559void CalypsoCardAdapter::updateCurrentLid(
const uint16_t lid)
566const std::shared_ptr<ElementaryFileAdapter> CalypsoCardAdapter::getOrCreateFile()
568 if (mCurrentSfi != 0) {
570 for (
const auto& ef : mFiles) {
571 if (ef->getSfi() == mCurrentSfi) {
572 return std::dynamic_pointer_cast<ElementaryFileAdapter>(ef);
575 }
else if (mCurrentLid != 0) {
577 for (
const auto& ef : mFiles) {
578 if (ef->getHeader() !=
nullptr && ef->getHeader()->getLid() == mCurrentLid) {
579 return std::dynamic_pointer_cast<ElementaryFileAdapter>(ef);
585 const auto ef = std::make_shared<ElementaryFileAdapter>(mCurrentSfi);
586 mFiles.push_back(ef);
598 if (mPinAttemptCounter ==
nullptr) {
599 throw IllegalStateException(
"PIN status has not been checked.");
602 return *mPinAttemptCounter.get();
607 mPinAttemptCounter = std::make_shared<int>(pinAttemptCounter);
611 const std::shared_ptr<FileHeaderAdapter> header)
613 updateCurrentSfi(sfi);
614 updateCurrentLid(header->getLid());
616 std::shared_ptr<ElementaryFileAdapter> ef = getOrCreateFile();
617 if (ef->getHeader() ==
nullptr) {
618 ef->setHeader(header);
620 std::dynamic_pointer_cast<FileHeaderAdapter>(ef->getHeader())
621 ->updateMissingInfoFrom(header);
626 const uint8_t numRecord,
627 const std::vector<uint8_t>& content)
629 updateCurrentSfi(sfi);
630 std::shared_ptr<ElementaryFileAdapter> ef = getOrCreateFile();
631 std::dynamic_pointer_cast<FileDataAdapter>(ef->getData())->setContent(numRecord, content);
635 const uint8_t numCounter,
636 const std::vector<uint8_t>& content)
638 updateCurrentSfi(sfi);
639 std::shared_ptr<ElementaryFileAdapter> ef = getOrCreateFile();
640 std::dynamic_pointer_cast<FileDataAdapter>(ef->getData())->setCounter(numCounter, content);
644 const uint8_t numRecord,
645 const std::vector<uint8_t>& content,
646 const uint8_t offset)
648 updateCurrentSfi(sfi);
649 std::shared_ptr<ElementaryFileAdapter> ef = getOrCreateFile();
650 std::dynamic_pointer_cast<FileDataAdapter>(ef->getData())
651 ->setContent(numRecord, content, offset);
655 const uint8_t numRecord,
656 const std::vector<uint8_t>& content,
657 const uint8_t offset)
659 updateCurrentSfi(sfi);
660 std::shared_ptr<ElementaryFileAdapter> ef = getOrCreateFile();
661 std::dynamic_pointer_cast<FileDataAdapter>(ef->getData())
662 ->fillContent(numRecord, content, offset);
667 updateCurrentSfi(sfi);
668 std::shared_ptr<ElementaryFileAdapter> ef = getOrCreateFile();
669 std::dynamic_pointer_cast<FileDataAdapter>(ef->getData())->addCyclicContent(content);
674 copyFiles(mFiles, mFilesBackup);
679 copyFiles(mFilesBackup, mFiles);
682void CalypsoCardAdapter::copyFiles(
const std::vector<std::shared_ptr<ElementaryFile>>& src,
683 std::vector<std::shared_ptr<ElementaryFile>>& dest)
686 for (
const auto& file : src) {
687 dest.push_back(std::make_shared<ElementaryFileAdapter>(file));
698 if (mSelectApplicationResponse ==
nullptr) {
699 return std::vector<uint8_t>();
702 return mSelectApplicationResponse->getApdu();
707 mCardChallenge = cardChallenge;
711 const std::vector<uint8_t>& traceabilityInformation)
713 mTraceabilityInformation = traceabilityInformation;
718 mSvOperationSignature = svOperationSignature;
723 return mCardChallenge;
733 if (mSvGetHeader.empty()) {
734 throw IllegalStateException(
"SV Get Header not available.");
742 if (mSvGetData.empty()) {
743 throw new IllegalStateException(
"SV Get Data not available.");
751 return mSvOperationSignature;
756 os <<
"CALYPSO_CARD_ADAPTER: {"
757 <<
"SELECT_APPLICATION_RESPONSE: " << cca.mSelectApplicationResponse <<
", "
758 <<
"POWER_ON_DATA: " << cca.mPowerOnData <<
", "
759 <<
"IS_EXTENDED_MODE_SUPPORTED: " << cca.mIsExtendedModeSupported <<
", "
760 <<
"IS_RATIFICATION_ON_DESELECT_SUPPORTED: " << cca.mIsRatificationOnDeselectSupported <<
", "
761 <<
"IS_SV_FEATURE_AVAILABLE: " << cca.mIsSvFeatureAvailable <<
", "
762 <<
"IS_PIN_FEATURE_AVAILABLE: " << cca.mIsPinFeatureAvailable <<
", "
763 <<
"IS_PKI_MODE_SUPPORTED:" << cca.mIsPkiModeSupported <<
", "
764 <<
"IS_DF_INVALIDATED:" << cca.mIsDfInvalidated <<
", "
765 <<
"CALYPSO_CARD_CLASS: " << cca.mCalypsoCardClass <<
", "
766 <<
"CALYPSO_SERIAL_NUMBER: " << cca.mCalypsoSerialNumber <<
", "
767 <<
"STARTUP_INFO:" << cca.mStartupInfo <<
", "
768 <<
"PRODUCT_TYPE: " << cca.mProductType <<
", "
769 <<
"DF_NAME: " << cca.mDfName <<
", "
770 <<
"MODIFICATIONS_COUNTER_MAX: " << cca.mModificationsCounterMax <<
", "
771 <<
"IS_MODIFICATION_COUNTER_IN_BYTES: " << cca.mIsModificationCounterInBytes <<
", "
772 <<
"DIRECTORY_HEADER: " << cca.mDirectoryHeader <<
", "
773 <<
"FILES: " << cca.mFiles <<
", "
774 <<
"FILES_BACKUP: " << cca.mFilesBackup <<
", "
775 <<
"CURRENT_SFI: " << cca.mCurrentSfi <<
", "
776 <<
"CURRENT_LID: " << cca.mCurrentLid <<
", "
777 <<
"ID_DF_RATIFIED: " << cca.mIsDfRatified <<
", "
778 <<
"PIN_ATTEMPT_COUNTER: " << cca.mPinAttemptCounter <<
", "
779 <<
"SV_BALANCE: " << cca.mSvBalance <<
", "
780 <<
"SV_LAST_T_NUM: " << cca.mSvLastTNum <<
", "
781 <<
"SV_LOAD_LOG_RECORD: " << cca.mSvLoadLogRecord <<
", "
782 <<
"SV_DEBIT_LOG_RECORD: " << cca.mSvDebitLogRecord <<
", "
783 <<
"IS_HCE: " << cca.mIsHce <<
", "
784 <<
"CARD_CHALLENGE: " << cca.mCardChallenge <<
", "
785 <<
"TRACEABILITY_INFORMATION: " << cca.mTraceabilityInformation <<
", "
786 <<
"SV_KVC: " << cca.mSvKvc <<
", "
787 <<
"SV_GET_HEADER: " << cca.mSvGetHeader <<
", "
788 <<
"SV_GET_DATA: " << cca.mSvGetData <<
", "
789 <<
"SV_OPERATION_SIGNATURE: " << cca.mSvOperationSignature <<
", "
790 <<
"APPLICATION_SUB_TYPE: " << cca.mApplicationSubType <<
", "
791 <<
"APPLICATION_TYPE: " << cca.mApplicationType <<
", "
792 <<
"SESSION_MODIFICATION: " << cca.mSessionModification
798std::ostream&
operator<<(std::ostream& os,
const std::shared_ptr<CalypsoCardAdapter> cca)
800 if (cca ==
nullptr) {
801 os <<
"CALYPSO_CARD_ADAPTER: null";
CalypsoCard & setDirectoryHeader(const std::shared_ptr< DirectoryHeader > directoryHeader)
const std::vector< uint8_t > & getStartupInfoRawData() const override
const std::shared_ptr< SvDebitLogRecord > getSvDebitLogLastRecord() override
uint8_t getSessionModification() const override
bool isPinBlocked() const override
bool isDfInvalidated() const override
const std::vector< std::shared_ptr< ElementaryFile > > & getFiles() const override
bool isHce() const override
const std::shared_ptr< ElementaryFile > getFileBySfi(const uint8_t sfi) const override
uint8_t getPlatform() const override
const CalypsoCard::ProductType & getProductType() const override
const std::map< const uint8_t, const std::shared_ptr< ElementaryFile > > getAllFiles() const override
const std::vector< uint8_t > getApplicationSerialNumber() const override
uint8_t getSoftwareVersion() const override
const std::string & getPowerOnData() const override
void setTraceabilityInformation(const std::vector< uint8_t > &traceabilityInformation)
uint8_t getApplicationType() const override
void fillContent(const uint8_t sfi, const uint8_t numRecord, const std::vector< uint8_t > &content, const uint8_t offset)
const std::vector< uint8_t > & getDfName() const override
void setPinAttemptRemaining(const int pinAttemptCounter)
uint8_t getSoftwareIssuer() const override
bool isPinFeatureAvailable() const override
const std::shared_ptr< DirectoryHeader > getDirectoryHeader() const override
int getPinAttemptRemaining() const override
const std::shared_ptr< ElementaryFile > getFileByLid(const uint16_t lid) const override
const std::vector< uint8_t > & getSvGetData() const
int getTransactionCounter() const override
bool isSvFeatureAvailable() const override
void setSvOperationSignature(const std::vector< uint8_t > &svOperationSignature)
const std::shared_ptr< SvLoadLogRecord > getSvLoadLogRecord() override
void addCyclicContent(const uint8_t sfi, const std::vector< uint8_t > content)
uint8_t getApplicationSubtype() const override
void setContent(const uint8_t sfi, const uint8_t numRecord, const std::vector< uint8_t > &content)
const std::vector< uint8_t > & getSvOperationSignature() const
uint8_t getPayloadCapacity() const
CalypsoCardClass getCardClass() const
bool isRatificationOnDeselectSupported() const override
const std::vector< std::shared_ptr< SvDebitLogRecord > > getSvDebitLogAllRecords() const override
void setCardChallenge(const std::vector< uint8_t > &cardChallenge)
int getSvBalance() const override
const std::vector< uint8_t > & getSvGetHeader() const
int getSvLastTNum() const override
const std::vector< uint8_t > getSelectApplicationResponse() const override
int getModificationsCounter() const
void initializeWithFci(const std::shared_ptr< ApduResponseApi > selectApplicationResponse)
void setSvData(const uint8_t svKvc, const std::vector< uint8_t > &svGetHeader, const std::vector< uint8_t > &svGetData, const int svBalance, const int svLastTNum, const std::shared_ptr< SvLoadLogRecord > svLoadLogRecord, const std::shared_ptr< SvDebitLogRecord > svDebitLogRecord)
void setDfRatified(const bool dfRatified)
void setFileHeader(const uint8_t sfi, const std::shared_ptr< FileHeaderAdapter > header)
bool isPkiModeSupported() const override
bool isExtendedModeSupported() const override
void initializeWithPowerOnData(const std::string &powerOnData)
uint8_t getSoftwareRevision() const override
const std::vector< uint8_t > & getCardChallenge() const
bool isModificationsCounterInBytes() const
void setTransactionCounter(const int transactionCounter)
const std::vector< uint8_t > & getCalypsoSerialNumberFull() const
bool isDfRatified() const override
void setCounter(const uint8_t sfi, const uint8_t numCounter, const std::vector< uint8_t > &content)
const std::vector< uint8_t > getTraceabilityInformation() const override
static const CalypsoCardClass LEGACY
static const CalypsoCardClass ISO
static const uint8_t SV_DEBIT_LOG_FILE_SFI
static const uint8_t SV_RELOAD_LOG_FILE_SFI
CalypsoSam::ProductType ProductType
std::ostream & operator<<(std::ostream &os, const std::shared_ptr< ApduRequestAdapter > ara)