16#include "FileHeader.h"
19#include "ByteArrayUtil.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 = ByteArrayUtil::fromHex(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 " \
376 const std::vector<uint8_t>& svGetHeader,
377 const std::vector<uint8_t>& svGetData,
379 const int svLastTNum,
380 const std::shared_ptr<SvLoadLogRecord> svLoadLogRecord,
381 const std::shared_ptr<SvDebitLogRecord> svDebitLogRecord)
384 mSvGetHeader = svGetHeader;
385 mSvGetData = svGetData;
386 mSvBalance = std::make_shared<int>(svBalance);
387 mSvLastTNum = svLastTNum;
390 if (mSvLoadLogRecord ==
nullptr) {
391 mSvLoadLogRecord = svLoadLogRecord;
394 if (mSvDebitLogRecord ==
nullptr) {
395 mSvDebitLogRecord = svDebitLogRecord;
401 if (mSvBalance ==
nullptr) {
402 throw IllegalStateException(
"No SV Get command has been executed.");
405 return *mSvBalance.get();
410 if (mSvBalance ==
nullptr) {
411 new IllegalStateException(
"No SV Get command has been executed.");
419 if (mSvLoadLogRecord ==
nullptr) {
421 const std::shared_ptr<ElementaryFile> ef =
424 const std::vector<uint8_t> logRecord = ef->getData()->getContent();
425 mSvLoadLogRecord = std::make_shared<SvLoadLogRecordAdapter>(logRecord, 0);
429 return mSvLoadLogRecord;
434 if (mSvDebitLogRecord ==
nullptr) {
436 const std::vector<std::shared_ptr<SvDebitLogRecord>> svDebitLogRecords =
438 mSvDebitLogRecord = svDebitLogRecords[0];
441 return mSvDebitLogRecord;
447 std::vector<std::shared_ptr<SvDebitLogRecord>> svDebitLogRecords;
450 const std::shared_ptr<ElementaryFile> ef =
453 return svDebitLogRecords;
456 const std::map<const uint8_t, std::vector<uint8_t>>& logRecords =
457 ef->getData()->getAllRecordsContent();
458 for (
const auto& entry : logRecords) {
459 svDebitLogRecords.push_back(std::make_shared<SvDebitLogRecordAdapter>(entry.second, 0));
462 return svDebitLogRecords;
467 mIsDfRatified = std::make_shared<bool>(dfRatified);
472 return mCalypsoCardClass;
477 return mDirectoryHeader;
481 const std::shared_ptr<DirectoryHeader> directoryHeader)
483 mDirectoryHeader = directoryHeader;
484 mIsDfInvalidated = (directoryHeader->getDfStatus() & 0x01) != 0;
495 for (
const auto& ef : mFiles) {
496 if (ef->getSfi() == sfi) {
501 mLogger->warn(
"EF with SFI % is not found\n", sfi);
508 for (
const auto& ef : mFiles) {
509 if (ef->getHeader() !=
nullptr && ef->getHeader()->getLid() == lid) {
514 mLogger->warn(
"EF with LID % is not found\n", lid);
519const std::map<const uint8_t, const std::shared_ptr<ElementaryFile>>
522 std::map<const uint8_t, const std::shared_ptr<ElementaryFile>> res;
523 for (
const auto& ef : mFiles) {
524 if (ef->getSfi() != 0) {
525 res.insert({ef->getSfi(), ef});
537void CalypsoCardAdapter::updateCurrentSfi(
const uint8_t sfi)
544void CalypsoCardAdapter::updateCurrentLid(
const uint16_t lid)
551const std::shared_ptr<ElementaryFileAdapter> CalypsoCardAdapter::getOrCreateFile()
553 if (mCurrentSfi != 0) {
555 for (
const auto& ef : mFiles) {
556 if (ef->getSfi() == mCurrentSfi) {
557 return std::dynamic_pointer_cast<ElementaryFileAdapter>(ef);
560 }
else if (mCurrentLid != 0) {
562 for (
const auto& ef : mFiles) {
563 if (ef->getHeader() !=
nullptr && ef->getHeader()->getLid() == mCurrentLid) {
564 return std::dynamic_pointer_cast<ElementaryFileAdapter>(ef);
570 const auto ef = std::make_shared<ElementaryFileAdapter>(mCurrentSfi);
571 mFiles.push_back(ef);
583 if (mPinAttemptCounter ==
nullptr) {
584 throw IllegalStateException(
"PIN status has not been checked.");
587 return *mPinAttemptCounter.get();
592 mPinAttemptCounter = std::make_shared<int>(pinAttemptCounter);
596 const std::shared_ptr<FileHeaderAdapter> header)
598 updateCurrentSfi(sfi);
599 updateCurrentLid(header->getLid());
601 std::shared_ptr<ElementaryFileAdapter> ef = getOrCreateFile();
602 if (ef->getHeader() ==
nullptr) {
603 ef->setHeader(header);
605 std::dynamic_pointer_cast<FileHeaderAdapter>(ef->getHeader())
606 ->updateMissingInfoFrom(header);
611 const uint8_t numRecord,
612 const std::vector<uint8_t>& content)
614 updateCurrentSfi(sfi);
615 std::shared_ptr<ElementaryFileAdapter> ef = getOrCreateFile();
616 std::dynamic_pointer_cast<FileDataAdapter>(ef->getData())->setContent(numRecord, content);
620 const uint8_t numCounter,
621 const std::vector<uint8_t>& content)
623 updateCurrentSfi(sfi);
624 std::shared_ptr<ElementaryFileAdapter> ef = getOrCreateFile();
625 std::dynamic_pointer_cast<FileDataAdapter>(ef->getData())->setCounter(numCounter, content);
629 const uint8_t numRecord,
630 const std::vector<uint8_t>& content,
631 const uint8_t offset)
633 updateCurrentSfi(sfi);
634 std::shared_ptr<ElementaryFileAdapter> ef = getOrCreateFile();
635 std::dynamic_pointer_cast<FileDataAdapter>(ef->getData())
636 ->setContent(numRecord, content, offset);
640 const uint8_t numRecord,
641 const std::vector<uint8_t>& content,
642 const uint8_t offset)
644 updateCurrentSfi(sfi);
645 std::shared_ptr<ElementaryFileAdapter> ef = getOrCreateFile();
646 std::dynamic_pointer_cast<FileDataAdapter>(ef->getData())
647 ->fillContent(numRecord, content, offset);
652 updateCurrentSfi(sfi);
653 std::shared_ptr<ElementaryFileAdapter> ef = getOrCreateFile();
654 std::dynamic_pointer_cast<FileDataAdapter>(ef->getData())->addCyclicContent(content);
659 copyFiles(mFiles, mFilesBackup);
664 copyFiles(mFilesBackup, mFiles);
667void CalypsoCardAdapter::copyFiles(
const std::vector<std::shared_ptr<ElementaryFile>>& src,
668 std::vector<std::shared_ptr<ElementaryFile>>& dest)
671 for (
const auto& file : src) {
672 dest.push_back(std::make_shared<ElementaryFileAdapter>(file));
683 if (mSelectApplicationResponse ==
nullptr) {
684 return std::vector<uint8_t>();
687 return mSelectApplicationResponse->getApdu();
692 mCardChallenge = cardChallenge;
696 const std::vector<uint8_t>& traceabilityInformation)
698 mTraceabilityInformation = traceabilityInformation;
703 mSvOperationSignature = svOperationSignature;
708 return mCardChallenge;
718 if (mSvGetHeader.empty()) {
719 throw IllegalStateException(
"SV Get Header not available.");
727 if (mSvGetData.empty()) {
728 throw new IllegalStateException(
"SV Get Data not available.");
736 return mSvOperationSignature;
741 os <<
"CALYPSO_CARD_ADAPTER: {"
742 <<
"SELECT_APPLICATION_RESPONSE: " << cca.mSelectApplicationResponse <<
", "
743 <<
"POWER_ON_DATA: " << cca.mPowerOnData <<
", "
744 <<
"IS_EXTENDED_MODE_SUPPORTED: " << cca.mIsExtendedModeSupported <<
", "
745 <<
"IS_RATIFICATION_ON_DESELECT_SUPPORTED: " << cca.mIsRatificationOnDeselectSupported <<
", "
746 <<
"IS_SV_FEATURE_AVAILABLE: " << cca.mIsSvFeatureAvailable <<
", "
747 <<
"IS_PIN_FEATURE_AVAILABLE: " << cca.mIsPinFeatureAvailable <<
", "
748 <<
"IS_PKI_MODE_SUPPORTED:" << cca.mIsPkiModeSupported <<
", "
749 <<
"IS_DF_INVALIDATED:" << cca.mIsDfInvalidated <<
", "
750 <<
"CALYPSO_CARD_CLASS: " << cca.mCalypsoCardClass <<
", "
751 <<
"CALYPSO_SERIAL_NUMBER: " << cca.mCalypsoSerialNumber <<
", "
752 <<
"STARTUP_INFO:" << cca.mStartupInfo <<
", "
753 <<
"PRODUCT_TYPE: " << cca.mProductType <<
", "
754 <<
"DF_NAME: " << cca.mDfName <<
", "
755 <<
"MODIFICATIONS_COUNTER_MAX: " << cca.mModificationsCounterMax <<
", "
756 <<
"IS_MODIFICATION_COUNTER_IN_BYTES: " << cca.mIsModificationCounterInBytes <<
", "
757 <<
"DIRECTORY_HEADER: " << cca.mDirectoryHeader <<
", "
758 <<
"FILES: " << cca.mFiles <<
", "
759 <<
"FILES_BACKUP: " << cca.mFilesBackup <<
", "
760 <<
"CURRENT_SFI: " << cca.mCurrentSfi <<
", "
761 <<
"CURRENT_LID: " << cca.mCurrentLid <<
", "
762 <<
"ID_DF_RATIFIED: " << cca.mIsDfRatified <<
", "
763 <<
"PIN_ATTEMPT_COUNTER: " << cca.mPinAttemptCounter <<
", "
764 <<
"SV_BALANCE: " << cca.mSvBalance <<
", "
765 <<
"SV_LAST_T_NUM: " << cca.mSvLastTNum <<
", "
766 <<
"SV_LOAD_LOG_RECORD: " << cca.mSvLoadLogRecord <<
", "
767 <<
"SV_DEBIT_LOG_RECORD: " << cca.mSvDebitLogRecord <<
", "
768 <<
"IS_HCE: " << cca.mIsHce <<
", "
769 <<
"CARD_CHALLENGE: " << cca.mCardChallenge <<
", "
770 <<
"TRACEABILITY_INFORMATION: " << cca.mTraceabilityInformation <<
", "
771 <<
"SV_KVC: " << cca.mSvKvc <<
", "
772 <<
"SV_GET_HEADER: " << cca.mSvGetHeader <<
", "
773 <<
"SV_GET_DATA: " << cca.mSvGetData <<
", "
774 <<
"SV_OPERATION_SIGNATURE: " << cca.mSvOperationSignature <<
", "
775 <<
"APPLICATION_SUB_TYPE: " << cca.mApplicationSubType <<
", "
776 <<
"APPLICATION_TYPE: " << cca.mApplicationType <<
", "
777 <<
"SESSION_MODIFICATION: " << cca.mSessionModification
783std::ostream&
operator<<(std::ostream& os,
const std::shared_ptr<CalypsoCardAdapter> cca)
785 if (cca ==
nullptr) {
786 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
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
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)