Keyple Card Calypso C++ Library 2.2.5.6
Reference Terminal Reader API for C++
CalypsoCardAdapter.cpp
Go to the documentation of this file.
1/**************************************************************************************************
2 * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ *
3 * *
4 * See the NOTICE file(s) distributed with this work for additional information regarding *
5 * copyright ownership. *
6 * *
7 * This program and the accompanying materials are made available under the terms of the Eclipse *
8 * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 *
9 * *
10 * SPDX-License-Identifier: EPL-2.0 *
11 **************************************************************************************************/
12
13#include "CalypsoCardAdapter.h"
14
15/* Calypsonet Terminal Calypso */
16#include "FileHeader.h"
17
18/* Keyple Core Util */
19#include "ByteArrayUtil.h"
20#include "HexUtil.h"
21#include "IllegalArgumentException.h"
22#include "IllegalStateException.h"
23#include "KeypleStd.h"
24#include "System.h"
25
26/* Keyple Core Calypso */
27#include "CalypsoCardConstant.h"
28#include "CmdCardGetDataFci.h"
31
32namespace keyple {
33namespace card {
34namespace calypso {
35
36using namespace calypsonet::terminal::calypso;
37using namespace keyple::core::util;
38using namespace keyple::core::util::cpp;
39using namespace keyple::core::util::cpp::exception;
40
41/* CALYPSO CARD ADAPTER ------------------------------------------------------------------------- */
42
43const std::string CalypsoCardAdapter::PATTERN_1_BYTE_HEX = "%02Xh";
44const std::string CalypsoCardAdapter::PATTERN_2_BYTES_HEX = "%04Xh";
45
46const int CalypsoCardAdapter::CARD_REV1_ATR_LENGTH = 20;
47const int CalypsoCardAdapter::REV1_CARD_DEFAULT_WRITE_OPERATIONS_NUMBER_SUPPORTED_PER_SESSION = 3;
48const int CalypsoCardAdapter::REV2_CARD_DEFAULT_WRITE_OPERATIONS_NUMBER_SUPPORTED_PER_SESSION = 6;
49const int CalypsoCardAdapter::SI_BUFFER_SIZE_INDICATOR = 0;
50const int CalypsoCardAdapter::SI_PLATFORM = 1;
51const int CalypsoCardAdapter::SI_APPLICATION_TYPE = 2;
52const int CalypsoCardAdapter::SI_APPLICATION_SUBTYPE = 3;
53const int CalypsoCardAdapter::SI_SOFTWARE_ISSUER = 4;
54const int CalypsoCardAdapter::SI_SOFTWARE_VERSION = 5;
55const int CalypsoCardAdapter::SI_SOFTWARE_REVISION = 6;
56const int CalypsoCardAdapter::DEFAULT_PAYLOAD_CAPACITY = 250;
57
58const uint8_t CalypsoCardAdapter::APP_TYPE_WITH_CALYPSO_PIN = 0x01;
59const uint8_t CalypsoCardAdapter::APP_TYPE_WITH_CALYPSO_SV = 0x02;
60const uint8_t CalypsoCardAdapter::APP_TYPE_RATIFICATION_COMMAND_REQUIRED = 0x04;
61const uint8_t CalypsoCardAdapter::APP_TYPE_CALYPSO_REV_32_MODE = 0x08;
62const uint8_t CalypsoCardAdapter::APP_TYPE_WITH_PUBLIC_AUTHENTICATION = 0x10;
63
64const std::vector<int> CalypsoCardAdapter::BUFFER_SIZE_INDICATOR_TO_BUFFER_SIZE = {
65 0, 0, 0, 0, 0, 0, 215, 256, 304, 362, 430, 512, 608, 724, 861, 1024, 1217, 1448, 1722, 2048,
66 2435, 2896, 3444, 4096, 4870, 5792, 6888, 8192, 9741, 11585, 13777, 16384, 19483, 23170,
67 27554, 32768, 38967, 46340, 55108, 65536, 77935, 92681, 110217, 131072, 155871, 185363,
68 220435, 262144, 311743, 370727, 440871, 524288, 623487, 741455, 881743, 1048576
69};
70
71const std::vector<std::shared_ptr<CalypsoCardAdapter::PatchRev3>>
72 CalypsoCardAdapter::mPatchesRev3 = initPatchRev3();
73const std::vector<std::shared_ptr<CalypsoCardAdapter::PatchRev12>>
74 CalypsoCardAdapter::mPatchesRev12 = initPatchRev12();
75
77
79 const std::shared_ptr<CardSelectionResponseApi> cardSelectionResponse)
80{
81 if (cardSelectionResponse != nullptr) {
82
83 if (cardSelectionResponse->getSelectApplicationResponse() != nullptr) {
84
85 initializeWithFci(cardSelectionResponse->getSelectApplicationResponse());
86
87 } else if (cardSelectionResponse->getPowerOnData() != "") {
88
89 initializeWithPowerOnData(cardSelectionResponse->getPowerOnData());
90 }
91 }
92}
93
94const std::vector<std::shared_ptr<CalypsoCardAdapter::PatchRev12>>
95 CalypsoCardAdapter::initPatchRev12()
96{
97 std::shared_ptr<PatchRev12> p = nullptr;
98 std::vector<std::shared_ptr<PatchRev12>> v;
99
100 /* Patches for revision 1 & 2 */
101
102 /* 06 XX 01 03 XX XX XX */
103 p = std::shared_ptr<PatchRev12>(new PatchRev12("06000103000000", "FF00FFFF000000"));
104 p->setCounterValuePostponed();
105 v.push_back(p);
106
107 /* 06 0A 01 02 XX XX XX */
108 p = std::shared_ptr<PatchRev12>(new PatchRev12("060A0102000000", "FFFFFFFF000000"));
109 p->setCounterValuePostponed();
110 v.push_back(p);
111
112 /* XX XX 0X XX 15 XX XX */
113 p = std::shared_ptr<PatchRev12>(new PatchRev12("00000000150000", "0000F000FF0000"));
114 p->setCounterValuePostponed();
115 v.push_back(p);
116
117 /* XX XX 1X XX 15 XX XX */
118 p = std::shared_ptr<PatchRev12>(new PatchRev12("00001000150000", "0000F000FF0000"));
119 p->setCounterValuePostponed();
120 v.push_back(p);
121
122 return v;
123}
124
125const std::vector<std::shared_ptr<CalypsoCardAdapter::PatchRev3>>
126 CalypsoCardAdapter::initPatchRev3()
127{
128 std::shared_ptr<PatchRev3> p = nullptr;
129 std::vector<std::shared_ptr<PatchRev3>> v;
130
131 /* Patches for revision 3 */
132
133 /* XX 3C XX XX XX 10 XX */
134 p = std::shared_ptr<PatchRev3>(new PatchRev3("003C0000001000", "00FF000000FF00"));
135 p->setPayloadCapacity(235);
136 v.push_back(p);
137
138 return v;
139}
140
141void CalypsoCardAdapter::initializeWithPowerOnData(const std::string& powerOnData)
142{
143 mProductType = ProductType::PRIME_REVISION_1;
144 mCalypsoCardClass = CalypsoCardClass::LEGACY;
145
146 mPowerOnData = powerOnData;
147
148 /*
149 * FCI is not provided: we consider it is Calypso card rev 1, it's serial number is provided in
150 * the ATR.
151 */
152 const std::vector<uint8_t> atr = HexUtil::toByteArray(powerOnData);
153
154 /* Basic check: we expect to be here following a selection based on the ATR */
155 if (atr.size() != CARD_REV1_ATR_LENGTH) {
156
157 throw IllegalArgumentException("Unexpected ATR length: " + powerOnData);
158 }
159
160 mDfName.clear();
161 mCalypsoSerialNumber = std::vector<uint8_t>(8);
162
163 /*
164 * Old cards have their modification counter expressed in number of commands the array is
165 * initialized with 0 (cf. default value for primitive types).
166 */
167 System::arraycopy(atr, 12, mCalypsoSerialNumber, 4, 4);
168 mModificationsCounterMax = REV1_CARD_DEFAULT_WRITE_OPERATIONS_NUMBER_SUPPORTED_PER_SESSION;
169
170 mStartupInfo = std::vector<uint8_t>(7);
171
172 /* Create buffer size indicator */
173 mStartupInfo[0] = static_cast<uint8_t>(mModificationsCounterMax);
174
175 /* Create the startup info with the 6 bytes of the ATR from position 6 */
176 System::arraycopy(atr, 6, mStartupInfo, 1, 6);
177
178 mIsRatificationOnDeselectSupported = true;
179}
180
182 const std::shared_ptr<ApduResponseApi> selectApplicationResponse)
183{
184 mSelectApplicationResponse = selectApplicationResponse;
185
186 if (selectApplicationResponse->getDataOut().size() == 0) {
187
188 /* No FCI provided. May be filled later with a Get Data response */
189 return;
190 }
191
192 /*
193 * Parse card FCI - to retrieve DF Name (AID), Serial Number, &amp; StartupInfo
194 * CL-SEL-TLVSTRUC.1
195 */
196 auto cardGetDataFci = std::make_shared<CmdCardGetDataFci>(CalypsoCardClass::ISO);
197 cardGetDataFci->AbstractCardCommand::parseApduResponse(selectApplicationResponse,
198 shared_from_this());
199
200 if (!cardGetDataFci->isValidCalypsoFCI()) {
201 throw IllegalArgumentException("Bad FCI format.");
202 }
203
204}
205
207 const std::shared_ptr<CmdCardGetDataFci> cmdCardGetDataFci)
208{
209 mIsDfInvalidated = cmdCardGetDataFci->isDfInvalidated();
210
211 /* CL-SEL-DATA.1 */
212 mDfName = cmdCardGetDataFci->getDfName();
213 mCalypsoSerialNumber = cmdCardGetDataFci->getApplicationSerialNumber();
214
215 /* CL-SI-OTHER.1 */
216 mStartupInfo = cmdCardGetDataFci->getDiscretionaryData();
217
218 /*
219 * CL-SI-ATRFU.1
220 * CL-SI-ATPRIME.1
221 * CL-SI-ATB6B5.1
222 * CL-SI-ATLIGHT.1
223 * CL-SI-ATBASIC.1
224 */
225 mApplicationType = mStartupInfo[SI_APPLICATION_TYPE];
226 mProductType = computeProductType(mApplicationType & 0xFF);
227
228 /* CL-SI-ASRFU.1 */
229 mApplicationSubType = mStartupInfo[SI_APPLICATION_SUBTYPE];
230 if (mApplicationSubType == 0x00 || mApplicationSubType == 0xFF) {
231 throw IllegalArgumentException("Unexpected application subtype: " +
232 std::to_string(mApplicationSubType));
233 }
234
235 mSessionModification = mStartupInfo[SI_BUFFER_SIZE_INDICATOR];
236
237 if (mProductType == ProductType::PRIME_REVISION_2) {
238 mCalypsoCardClass = CalypsoCardClass::LEGACY;
239
240 /* Old cards have their modification counter expressed in number of commands */
241 mIsModificationCounterInBytes = false;
242 mModificationsCounterMax = REV2_CARD_DEFAULT_WRITE_OPERATIONS_NUMBER_SUPPORTED_PER_SESSION;
243
244 } else if (mProductType == ProductType::BASIC) {
245 /* CL-SI-SMBASIC.1 */
246 if (mSessionModification < 0x04 || mSessionModification > 0x37) {
247 throw IllegalArgumentException("Wrong session modification value for a Basic type " \
248 "(should be between 04h and 37h): " +
249 std::to_string(mSessionModification));
250 }
251
252 mCalypsoCardClass = CalypsoCardClass::ISO;
253 mIsModificationCounterInBytes = false;
254 mModificationsCounterMax = 3; // TODO Verify this
255 } else {
256 mCalypsoCardClass = CalypsoCardClass::ISO;
257
258 /*
259 * Session buffer size
260 * CL-SI-SM.1
261 */
262 if (mSessionModification < 0x06 || mSessionModification > 0x37) {
263 throw IllegalArgumentException("Session modifications byte should be in range 06h to" \
264 " 47h. Was: " +
265 std::to_string(mSessionModification));
266 }
267
268 mModificationsCounterMax = BUFFER_SIZE_INDICATOR_TO_BUFFER_SIZE[mSessionModification];
269 }
270
271 /* CL-SI-ATOPT.1 */
272 if (mProductType == ProductType::PRIME_REVISION_3) {
273 mIsExtendedModeSupported = (mApplicationType & APP_TYPE_CALYPSO_REV_32_MODE) != 0;
274 mIsRatificationOnDeselectSupported =
275 (mApplicationType & APP_TYPE_RATIFICATION_COMMAND_REQUIRED) == 0;
276 mIsPkiModeSupported = (mApplicationType & APP_TYPE_WITH_PUBLIC_AUTHENTICATION) != 0;
277 }
278
279 if (mProductType == ProductType::PRIME_REVISION_3 ||
280 mProductType == ProductType::PRIME_REVISION_2) {
281 mIsSvFeatureAvailable = (mApplicationType & APP_TYPE_WITH_CALYPSO_SV) != 0;
282 mIsPinFeatureAvailable = (mApplicationType & APP_TYPE_WITH_CALYPSO_PIN) != 0;
283 }
284
285 mIsHce = (mCalypsoSerialNumber[3] & 0x80) == 0x80;
286
287 applyPatchIfNeeded();
288}
289
290CalypsoCard::ProductType CalypsoCardAdapter::computeProductType(const int applicationType) const
291{
292 if (applicationType == 0) {
293 throw IllegalArgumentException("Invalid application type 00h");
294 } else if (applicationType == 0xFF) {
295 return ProductType::UNKNOWN;
296 } else if (applicationType <= 0x1F) {
297 return ProductType::PRIME_REVISION_2;
298 } else if (applicationType >= 0x90 && applicationType <= 0x97) {
299 return ProductType::LIGHT;
300 } else if (applicationType >= 0x98 && applicationType <= 0x9F) {
301 return ProductType::BASIC;
302 }
303
304 return ProductType::PRIME_REVISION_3;
305}
306
308{
309 return mProductType;
310}
311
313{
314 return mIsHce;
315}
316
317const std::vector<uint8_t>& CalypsoCardAdapter::getDfName() const
318{
319 return mDfName;
320}
321
322const std::vector<uint8_t>& CalypsoCardAdapter::getCalypsoSerialNumberFull() const
323{
324 return mCalypsoSerialNumber;
325}
326
327const std::vector<uint8_t> CalypsoCardAdapter::getApplicationSerialNumber() const
328{
329 std::vector<uint8_t> applicationSerialNumber = mCalypsoSerialNumber;
330 applicationSerialNumber[0] = 0;
331 applicationSerialNumber[1] = 0;
332
333 return applicationSerialNumber;
334}
335
336const std::vector<uint8_t>& CalypsoCardAdapter::getStartupInfoRawData() const
337{
338 return mStartupInfo;
339}
340
342{
343 return mPayloadCapacity;
344}
345
347{
348 return mIsModificationCounterInBytes;
349}
350
352{
353 return mModificationsCounterMax;
354}
355
357{
358 return mStartupInfo[SI_PLATFORM];
359}
360
362{
363 return mApplicationType;
364}
365
367{
368 return mIsExtendedModeSupported;
369}
370
372{
373 return mIsRatificationOnDeselectSupported;
374}
375
377{
378 return mIsSvFeatureAvailable;
379}
380
382{
383 return mIsPinFeatureAvailable;
384}
385
387{
388 return mIsPkiModeSupported;
389}
390
392{
393 return mApplicationSubType;
394}
395
397{
398 return mStartupInfo[SI_SOFTWARE_ISSUER];
399}
400
402{
403 return mStartupInfo[SI_SOFTWARE_VERSION];
404}
405
407{
408 return mStartupInfo[SI_SOFTWARE_REVISION];
409}
410
412{
413 return mSessionModification;
414}
415
416const std::vector<uint8_t> CalypsoCardAdapter::getTraceabilityInformation() const
417{
418 /* Java code: return traceabilityInformation != null ? traceabilityInformation : new byte[0]; */
419 return mTraceabilityInformation;
420}
421
423{
424 return mIsDfInvalidated;
425}
426
428{
429 if (mIsDfRatified != nullptr) {
430 return *mIsDfRatified.get();
431 }
432
433 throw IllegalStateException("Unable to determine the ratification status. No session was " \
434 "opened.");
435}
436
438{
439 if (mTransactionCounter == nullptr) {
440 throw IllegalStateException("Unable to determine the transaction counter. No session was " \
441 "opened.");
442 }
443
444 return *mTransactionCounter.get();
445}
446
447void CalypsoCardAdapter::setTransactionCounter(const int transactionCounter)
448{
449 mTransactionCounter = std::make_shared<int>(transactionCounter);
450}
451
452void CalypsoCardAdapter::setSvData(const uint8_t svKvc,
453 const std::vector<uint8_t>& svGetHeader,
454 const std::vector<uint8_t>& svGetData,
455 const int svBalance,
456 const int svLastTNum,
457 const std::shared_ptr<SvLoadLogRecord> svLoadLogRecord,
458 const std::shared_ptr<SvDebitLogRecord> svDebitLogRecord)
459{
460 mSvKvc = svKvc;
461 mSvGetHeader = svGetHeader;
462 mSvGetData = svGetData;
463 mSvBalance = std::make_shared<int>(svBalance);
464 mSvLastTNum = svLastTNum;
465
466 /* Update logs, do not overwrite existing values (case of double reading) */
467 if (mSvLoadLogRecord == nullptr) {
468 mSvLoadLogRecord = svLoadLogRecord;
469 }
470
471 if (mSvDebitLogRecord == nullptr) {
472 mSvDebitLogRecord = svDebitLogRecord;
473 }
474}
475
477{
478 if (mSvBalance == nullptr) {
479 throw IllegalStateException("No SV Get command has been executed.");
480 }
481
482 return *mSvBalance.get();
483}
484
486{
487 if (mSvBalance == nullptr) {
488 new IllegalStateException("No SV Get command has been executed.");
489 }
490
491 return mSvLastTNum;
492}
493
494const std::shared_ptr<SvLoadLogRecord> CalypsoCardAdapter::getSvLoadLogRecord()
495{
496 if (mSvLoadLogRecord == nullptr) {
497 /* Try to get it from the file data */
498 const std::shared_ptr<ElementaryFile> ef =
500 if (ef != nullptr) {
501 const std::vector<uint8_t> logRecord = ef->getData()->getContent();
502 mSvLoadLogRecord = std::make_shared<SvLoadLogRecordAdapter>(logRecord, 0);
503 }
504 }
505
506 return mSvLoadLogRecord;
507}
508
509const std::shared_ptr<SvDebitLogRecord> CalypsoCardAdapter::getSvDebitLogLastRecord()
510{
511 if (mSvDebitLogRecord == nullptr) {
512 /* Try to get it from the file data */
513 const std::vector<std::shared_ptr<SvDebitLogRecord>> svDebitLogRecords =
515 mSvDebitLogRecord = svDebitLogRecords[0];
516 }
517
518 return mSvDebitLogRecord;
519}
520
521const std::vector<std::shared_ptr<SvDebitLogRecord>> CalypsoCardAdapter::getSvDebitLogAllRecords()
522 const
523{
524 std::vector<std::shared_ptr<SvDebitLogRecord>> svDebitLogRecords;
525
526 /* Get the logs from the file data */
527 const std::shared_ptr<ElementaryFile> ef =
529 if (ef == nullptr) {
530 return svDebitLogRecords;
531 }
532
533 const std::map<const uint8_t, std::vector<uint8_t>>& logRecords =
534 ef->getData()->getAllRecordsContent();
535 for (const auto& entry : logRecords) {
536 svDebitLogRecords.push_back(std::make_shared<SvDebitLogRecordAdapter>(entry.second, 0));
537 }
538
539 return svDebitLogRecords;
540}
541
542void CalypsoCardAdapter::setDfRatified(const bool dfRatified)
543{
544 mIsDfRatified = std::make_shared<bool>(dfRatified);
545}
546
548{
549 return mCalypsoCardClass;
550}
551
552const std::shared_ptr<DirectoryHeader> CalypsoCardAdapter::getDirectoryHeader() const
553{
554 return mDirectoryHeader;
555}
556
558 const std::shared_ptr<DirectoryHeader> directoryHeader)
559{
560 mDirectoryHeader = directoryHeader;
561 mIsDfInvalidated = (directoryHeader->getDfStatus() & 0x01) != 0;
562
563 return *this;
564}
565
566const std::shared_ptr<ElementaryFile> CalypsoCardAdapter::getFileBySfi(const uint8_t sfi) const
567{
568 if (sfi == 0) {
569 return nullptr;
570 }
571
572 for (const auto& ef : mFiles) {
573 if (ef->getSfi() == sfi) {
574 return ef;
575 }
576 }
577
578 mLogger->warn("EF with SFI % is not found\n", sfi);
579
580 return nullptr;
581}
582
583const std::shared_ptr<ElementaryFile> CalypsoCardAdapter::getFileByLid(const uint16_t lid) const
584{
585 for (const auto& ef : mFiles) {
586 if (ef->getHeader() != nullptr && ef->getHeader()->getLid() == lid) {
587 return ef;
588 }
589 }
590
591 mLogger->warn("EF with LID % is not found\n", lid);
592
593 return nullptr;
594}
595
596const std::map<const uint8_t, const std::shared_ptr<ElementaryFile>>
598{
599 std::map<const uint8_t, const std::shared_ptr<ElementaryFile>> res;
600 for (const auto& ef : mFiles) {
601 if (ef->getSfi() != 0) {
602 res.insert({ef->getSfi(), ef});
603 }
604 }
605
606 return res;
607}
608
609const std::vector<std::shared_ptr<ElementaryFile>>& CalypsoCardAdapter::getFiles() const
610{
611 return mFiles;
612}
613
614const std::shared_ptr<ElementaryFileAdapter> CalypsoCardAdapter::getOrCreateFile(const uint8_t sfi,
615 const uint16_t lid)
616{
617 if (sfi == 0 && lid == 0 && mCurrentEf != nullptr) {
618
619 return mCurrentEf;
620 }
621
622 if (sfi != 0) {
623
624 /* Search by SFI */
625 for (const auto& ef : mFiles) {
626
627 if (ef->getSfi() == sfi) {
628
629 mCurrentEf = std::dynamic_pointer_cast<ElementaryFileAdapter>(ef);
630 return mCurrentEf;
631 }
632 }
633
634 } else if (lid != 0) {
635
636 /* Search by LID */
637 for (const auto& ef : mFiles) {
638
639 if (ef->getHeader() != nullptr && ef->getHeader()->getLid() == lid) {
640
641 mCurrentEf = std::dynamic_pointer_cast<ElementaryFileAdapter>(ef);
642 return mCurrentEf;
643 }
644 }
645 }
646
647 /* Create a new EF with the provided SFI */
648 mCurrentEf = std::make_shared<ElementaryFileAdapter>(sfi);
649 mFiles.push_back(mCurrentEf);
650
651 return mCurrentEf;
652}
653
655{
656 return getPinAttemptRemaining() == 0;
657}
658
660{
661 if (mPinAttemptCounter == nullptr) {
662 throw IllegalStateException("PIN status has not been checked.");
663 }
664
665 return *mPinAttemptCounter.get();
666}
667
668void CalypsoCardAdapter::setPinAttemptRemaining(const int pinAttemptCounter)
669{
670 mPinAttemptCounter = std::make_shared<int>(pinAttemptCounter);
671}
672
674 const std::shared_ptr<FileHeaderAdapter> header)
675{
676 std::shared_ptr<ElementaryFileAdapter> ef = getOrCreateFile(sfi, header->getLid());
677 if (ef->getHeader() == nullptr) {
678
679 ef->setHeader(header);
680
681 } else {
682
683 std::dynamic_pointer_cast<FileHeaderAdapter>(ef->getHeader())
684 ->updateMissingInfoFrom(header);
685 }
686}
687
688void CalypsoCardAdapter::setContent(const uint8_t sfi,
689 const uint8_t numRecord,
690 const std::vector<uint8_t>& content)
691{
692 std::shared_ptr<ElementaryFileAdapter> ef = getOrCreateFile(sfi, 0);
693 std::dynamic_pointer_cast<FileDataAdapter>(ef->getData())->setContent(numRecord, content);
694}
695
696void CalypsoCardAdapter::setCounter(const uint8_t sfi,
697 const uint8_t numCounter,
698 const std::vector<uint8_t>& content)
699{
700 std::shared_ptr<ElementaryFileAdapter> ef = getOrCreateFile(sfi, 0);
701 std::dynamic_pointer_cast<FileDataAdapter>(ef->getData())->setCounter(numCounter, content);
702}
703
704void CalypsoCardAdapter::setContent(const uint8_t sfi,
705 const uint8_t numRecord,
706 const std::vector<uint8_t>& content,
707 const int offset)
708{
709 std::shared_ptr<ElementaryFileAdapter> ef = getOrCreateFile(sfi, 0);
710 std::dynamic_pointer_cast<FileDataAdapter>(ef->getData())
711 ->setContent(numRecord, content, offset);
712}
713
714void CalypsoCardAdapter::fillContent(const uint8_t sfi,
715 const uint8_t numRecord,
716 const std::vector<uint8_t>& content,
717 const int offset)
718{
719 std::shared_ptr<ElementaryFileAdapter> ef = getOrCreateFile(sfi, 0);
720 std::dynamic_pointer_cast<FileDataAdapter>(ef->getData())
721 ->fillContent(numRecord, content, offset);
722}
723
724void CalypsoCardAdapter::addCyclicContent(const uint8_t sfi, const std::vector<uint8_t> content)
725{
726 std::shared_ptr<ElementaryFileAdapter> ef = getOrCreateFile(sfi, 0);
727 std::dynamic_pointer_cast<FileDataAdapter>(ef->getData())->addCyclicContent(content);
728}
729
731{
732 copyFiles(mFiles, mFilesBackup);
733}
734
736{
737 copyFiles(mFilesBackup, mFiles);
738}
739
740void CalypsoCardAdapter::copyFiles(const std::vector<std::shared_ptr<ElementaryFile>>& src,
741 std::vector<std::shared_ptr<ElementaryFile>>& dest)
742{
743 dest.clear();
744 for (const auto& file : src) {
745 dest.push_back(std::make_shared<ElementaryFileAdapter>(file));
746 }
747}
748
749const std::string& CalypsoCardAdapter::getPowerOnData() const
750{
751 return mPowerOnData;
752}
753
754const std::vector<uint8_t> CalypsoCardAdapter::getSelectApplicationResponse() const
755{
756 if (mSelectApplicationResponse == nullptr) {
757 return std::vector<uint8_t>();
758 }
759
760 return mSelectApplicationResponse->getApdu();
761}
762
763void CalypsoCardAdapter::setCardChallenge(const std::vector<uint8_t>& cardChallenge)
764{
765 mCardChallenge = cardChallenge;
766}
767
769 const std::vector<uint8_t>& traceabilityInformation)
770{
771 mTraceabilityInformation = traceabilityInformation;
772}
773
774void CalypsoCardAdapter::setSvOperationSignature(const std::vector<uint8_t>& svOperationSignature)
775{
776 mSvOperationSignature = svOperationSignature;
777}
778
779const std::vector<uint8_t>& CalypsoCardAdapter::getCardChallenge() const
780{
781 return mCardChallenge;
782}
783
785{
786 return mSvKvc;
787}
788
789const std::vector<uint8_t>& CalypsoCardAdapter::getSvGetHeader() const
790{
791 if (mSvGetHeader.empty()) {
792
793 throw IllegalStateException("SV Get Header not available.");
794 }
795
796 return mSvGetHeader;
797}
798
799const std::vector<uint8_t>& CalypsoCardAdapter::getSvGetData() const
800{
801 if (mSvGetData.empty()) {
802
803 throw new IllegalStateException("SV Get Data not available.");
804 }
805
806 return mSvGetData;
807}
808
809const std::vector<uint8_t>& CalypsoCardAdapter::getSvOperationSignature() const
810{
811 return mSvOperationSignature;
812}
813
814void CalypsoCardAdapter::applyPatchIfNeeded()
815{
816 uint64_t startupInfoLong =
817 ByteArrayUtil::extractLong(mStartupInfo, 0, mStartupInfo.size(), false);
818
819 if (mProductType == ProductType::PRIME_REVISION_3) {
820
821 std::vector<std::shared_ptr<CalypsoCardAdapter::Patch>> v;
822 for (const auto& p : mPatchesRev3) {
823
824 v.push_back(std::dynamic_pointer_cast<CalypsoCardAdapter::Patch>(p));
825 }
826
827 applyPatchIfNeededForRevision(v, startupInfoLong);
828
829 } else if (mProductType == ProductType::PRIME_REVISION_2 ||
830 mProductType == ProductType::PRIME_REVISION_1) {
831
832 mPayloadCapacity = 128;
833
834 std::vector<std::shared_ptr<CalypsoCardAdapter::Patch>> v;
835 for (const auto& p : mPatchesRev12) {
836
837 v.push_back(std::dynamic_pointer_cast<CalypsoCardAdapter::Patch>(p));
838 }
839
840 applyPatchIfNeededForRevision(v, startupInfoLong);
841 }
842}
843
844void CalypsoCardAdapter::applyPatchIfNeededForRevision(
845 const std::vector<std::shared_ptr<CalypsoCardAdapter::Patch>>& patches,
846 const uint64_t startupInfoLong)
847{
848 for (const auto& patch : patches) {
849
850 if (patch->isApplicableTo(startupInfoLong)) {
851
852 patch->apply(this);
853 return;
854 }
855 }
856}
857
859{
860 return mIsCounterValuePostponed;
861}
862
863/* PATCH ---------------------------------------------------------------------------------------- */
864
865CalypsoCardAdapter::Patch::Patch(const std::string& startupInfo)
866: mStartupInfo(HexUtil::toLong(startupInfo)) {}
867
868CalypsoCardAdapter::Patch::Patch(const std::string& startupInfo, const std::string& mask)
869: mStartupInfo(HexUtil::toLong(startupInfo)),
870 mMask(HexUtil::toLong(mask)) {}
871
872bool CalypsoCardAdapter::Patch::isApplicableTo(const uint64_t startupInfo) const
873{
874 return mStartupInfo == (startupInfo & mMask);
875}
876
877/* PATCH REV 3 ---------------------------------------------------------------------------------- */
878
879CalypsoCardAdapter::PatchRev3::PatchRev3(const std::string& startupInfo)
880: CalypsoCardAdapter::Patch(startupInfo) {}
881
882CalypsoCardAdapter::PatchRev3::PatchRev3(const std::string& startupInfo, const std::string& mask)
883: CalypsoCardAdapter::Patch(startupInfo, mask) {}
884
885CalypsoCardAdapter::PatchRev3& CalypsoCardAdapter::PatchRev3::setPayloadCapacity(
886 const int payloadCapacity)
887{
888 mPayloadCapacity = std::make_shared<int>(payloadCapacity);
889
890 return *this;
891}
892
893void CalypsoCardAdapter::PatchRev3::apply(CalypsoCardAdapter* calypsoCard)
894{
895 if (mPayloadCapacity != nullptr) {
896
897 calypsoCard->mPayloadCapacity = *mPayloadCapacity;
898 }
899}
900
901/* PATCH REV 12 --------------------------------------------------------------------------------- */
902
903CalypsoCardAdapter::PatchRev12::PatchRev12(const std::string& startupInfo)
904: CalypsoCardAdapter::Patch(startupInfo) {}
905
906CalypsoCardAdapter::PatchRev12::PatchRev12(const std::string& startupInfo, const std::string& mask)
907: CalypsoCardAdapter::Patch(startupInfo, mask) {}
908
909CalypsoCardAdapter::PatchRev12& CalypsoCardAdapter::PatchRev12::setCounterValuePostponed()
910{
911 mIsCounterValuePostponed = std::make_shared<bool>(true);
912
913 return *this;
914}
915
916void CalypsoCardAdapter::PatchRev12::apply(CalypsoCardAdapter* calypsoCard)
917{
918 if (mIsCounterValuePostponed != nullptr) {
919
920 calypsoCard->mIsCounterValuePostponed = *mIsCounterValuePostponed;
921 }
922}
923
924/* ---------------------------------------------------------------------------------------------- */
925
926std::ostream& operator<<(std::ostream& os, const CalypsoCardAdapter& cca)
927{
928 os << "CALYPSO_CARD_ADAPTER: {"
929 << "SELECT_APPLICATION_RESPONSE: " << cca.mSelectApplicationResponse << ", "
930 << "POWER_ON_DATA: " << cca.mPowerOnData << ", "
931 << "IS_EXTENDED_MODE_SUPPORTED: " << cca.mIsExtendedModeSupported << ", "
932 << "IS_RATIFICATION_ON_DESELECT_SUPPORTED: " << cca.mIsRatificationOnDeselectSupported <<", "
933 << "IS_SV_FEATURE_AVAILABLE: " << cca.mIsSvFeatureAvailable << ", "
934 << "IS_PIN_FEATURE_AVAILABLE: " << cca.mIsPinFeatureAvailable << ", "
935 << "IS_PKI_MODE_SUPPORTED:" << cca.mIsPkiModeSupported << ", "
936 << "IS_DF_INVALIDATED:" << cca.mIsDfInvalidated << ", "
937 << "CALYPSO_CARD_CLASS: " << cca.mCalypsoCardClass << ", "
938 << "CALYPSO_SERIAL_NUMBER: " << cca.mCalypsoSerialNumber << ", "
939 << "STARTUP_INFO:" << cca.mStartupInfo << ", "
940 << "PRODUCT_TYPE: " << cca.mProductType << ", "
941 << "DF_NAME: " << cca.mDfName << ", "
942 << "MODIFICATIONS_COUNTER_MAX: " << cca.mModificationsCounterMax << ", "
943 << "IS_MODIFICATION_COUNTER_IN_BYTES: " << cca.mIsModificationCounterInBytes << ", "
944 << "DIRECTORY_HEADER: " << cca.mDirectoryHeader << ", "
945 << "FILES: " << cca.mFiles << ", "
946 << "FILES_BACKUP: " << cca.mFilesBackup << ", "
947 << "ID_DF_RATIFIED: " << cca.mIsDfRatified << ", "
948 << "PIN_ATTEMPT_COUNTER: " << cca.mPinAttemptCounter << ", "
949 << "SV_BALANCE: " << cca.mSvBalance << ", "
950 << "SV_LAST_T_NUM: " << cca.mSvLastTNum << ", "
951 << "SV_LOAD_LOG_RECORD: " << cca.mSvLoadLogRecord << ", "
952 << "SV_DEBIT_LOG_RECORD: " << cca.mSvDebitLogRecord << ", "
953 << "IS_HCE: " << cca.mIsHce << ", "
954 << "CARD_CHALLENGE: " << cca.mCardChallenge << ", "
955 << "TRACEABILITY_INFORMATION: " << cca.mTraceabilityInformation << ", "
956 << "SV_KVC: " << cca.mSvKvc << ", "
957 << "SV_GET_HEADER: " << cca.mSvGetHeader << ", "
958 << "SV_GET_DATA: " << cca.mSvGetData << ", "
959 << "SV_OPERATION_SIGNATURE: " << cca.mSvOperationSignature << ", "
960 << "APPLICATION_SUB_TYPE: " << cca.mApplicationSubType << ", "
961 << "APPLICATION_TYPE: " << cca.mApplicationType << ", "
962 << "SESSION_MODIFICATION: " << cca.mSessionModification
963 << "}";
964
965 return os;
966}
967
968std::ostream& operator<<(std::ostream& os, const std::shared_ptr<CalypsoCardAdapter> cca)
969{
970 if (cca == nullptr) {
971
972 os << "CALYPSO_CARD_ADAPTER: null";
973
974 } else {
975
976 os << *cca.get();
977 }
978
979 return os;
980}
981
982}
983}
984}
CalypsoCard & setDirectoryHeader(const std::shared_ptr< DirectoryHeader > directoryHeader)
const std::vector< uint8_t > & getStartupInfoRawData() const override
const std::shared_ptr< SvDebitLogRecord > getSvDebitLogLastRecord() override
const std::vector< std::shared_ptr< ElementaryFile > > & getFiles() const override
const std::shared_ptr< ElementaryFile > getFileBySfi(const uint8_t sfi) 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
const std::string & getPowerOnData() const override
void setTraceabilityInformation(const std::vector< uint8_t > &traceabilityInformation)
const std::vector< uint8_t > & getDfName() const override
void setPinAttemptRemaining(const int pinAttemptCounter)
void initialize(const std::shared_ptr< CardSelectionResponseApi > cardSelectionResponse)
const std::shared_ptr< DirectoryHeader > getDirectoryHeader() const override
const std::shared_ptr< ElementaryFile > getFileByLid(const uint16_t lid) const override
const std::vector< uint8_t > & getSvGetData() const
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)
void setContent(const uint8_t sfi, const uint8_t numRecord, const std::vector< uint8_t > &content)
const std::vector< uint8_t > & getSvOperationSignature() const
const std::vector< std::shared_ptr< SvDebitLogRecord > > getSvDebitLogAllRecords() const override
void setCardChallenge(const std::vector< uint8_t > &cardChallenge)
void fillContent(const uint8_t sfi, const uint8_t numRecord, const std::vector< uint8_t > &content, const int offset)
void initializeWithFci(const std::shared_ptr< CmdCardGetDataFci > cmdCardGetDataFci)
const std::vector< uint8_t > & getSvGetHeader() const
const std::vector< uint8_t > getSelectApplicationResponse() const override
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 setFileHeader(const uint8_t sfi, const std::shared_ptr< FileHeaderAdapter > header)
const std::vector< uint8_t > & getCardChallenge() const
void setTransactionCounter(const int transactionCounter)
const std::vector< uint8_t > & getCalypsoSerialNumberFull() const
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
CalypsoSam::ProductType ProductType
std::ostream & operator<<(std::ostream &os, const std::shared_ptr< ApduRequestAdapter > ara)