14#include "keyple/card/calypso/SecurePkiModeTransactionManagerAdapter.hpp"
21#include "keyple/card/calypso/CalypsoCardAdapter.hpp"
22#include "keyple/card/calypso/CalypsoCardConstant.hpp"
23#include "keyple/card/calypso/CommandChangePin.hpp"
24#include "keyple/card/calypso/CommandCloseSecureSession.hpp"
25#include "keyple/card/calypso/CommandGetDataCertificate.hpp"
26#include "keyple/card/calypso/CommandOpenSecureSession.hpp"
27#include "keyple/card/calypso/CommandVerifyPin.hpp"
28#include "keyple/core/plugin/CardIOException.hpp"
29#include "keyple/core/plugin/ReaderIOException.hpp"
30#include "keyple/core/util/HexUtil.hpp"
31#include "keyple/core/util/KeypleAssert.hpp"
32#include "keyple/core/util/cpp/Arrays.hpp"
33#include "keyple/core/util/cpp/exception/IllegalStateException.hpp"
34#include "keyple/core/util/cpp/exception/RuntimeException.hpp"
35#include "keyple/core/util/cpp/exception/UnsupportedOperationException.hpp"
36#include "keypop/calypso/card/transaction/InvalidCertificateException.hpp"
37#include "keypop/calypso/card/transaction/UnexpectedCommandStatusException.hpp"
38#include "keypop/calypso/crypto/asymmetric/AsymmetricCryptoException.hpp"
39#include "keypop/calypso/crypto/asymmetric/certificate/CertificateValidationException.hpp"
40#include "keypop/reader/CardCommunicationException.hpp"
41#include "keypop/reader/ReaderCommunicationException.hpp"
42#include "keypop/reader/selection/InvalidCardResponseException.hpp"
48using keyple::core::plugin::CardIOException;
49using keyple::core::plugin::ReaderIOException;
50using keyple::core::util::Assert;
51using keyple::core::util::HexUtil;
52using keyple::core::util::cpp::Arrays;
53using keyple::core::util::cpp::exception::IllegalStateException;
54using keyple::core::util::cpp::exception::RuntimeException;
55using keyple::core::util::cpp::exception::UnsupportedOperationException;
56using keypop::calypso::card::transaction::InvalidCertificateException;
57using keypop::calypso::card::transaction::UnexpectedCommandStatusException;
58using keypop::calypso::crypto::asymmetric::AsymmetricCryptoException;
59using keypop::calypso::crypto::asymmetric::certificate::
60 CertificateValidationException;
61using keypop::reader::CardCommunicationException;
62using keypop::reader::ReaderCommunicationException;
63using keypop::reader::selection::InvalidCardResponseException;
65const std::string SecurePkiModeTransactionManagerAdapter::MSG_PIN_NOT_AVAILABLE
66 =
"PIN is not available for this card";
68 SecurePkiModeTransactionManagerAdapter ::MSG_INVALID_CARD_CERTIFICATE
69 =
"Invalid card certificate";
71 SecurePkiModeTransactionManagerAdapter ::MSG_INVALID_CA_CERTIFICATE
72 =
"Invalid CA certificate";
74SecurePkiModeTransactionManagerAdapter::SecurePkiModeTransactionManagerAdapter(
75 std::shared_ptr<ProxyReaderApi> cardReader,
76 std::shared_ptr<CalypsoCardAdapter> card,
77 std::shared_ptr<AsymmetricCryptoSecuritySettingAdapter>
78 asymmetricCryptoSecuritySetting)
79: TransactionManagerAdapter<SecurePkiModeTransactionManager>(cardReader, card)
80, SecureTransactionManagerAdapter<SecurePkiModeTransactionManager>(
82, mAsymmetricCryptoSecuritySetting(asymmetricCryptoSecuritySetting)
83, mPayloadCapacity(card->getPayloadCapacity())
85 std::shared_ptr<AsymmetricCryptoCardTransactionManagerSpi>
86 asymmetricCryptoCardTransactionManagerSpi
87 = asymmetricCryptoSecuritySetting
88 ->getCryptoCardTransactionManagerFactorySpi()
89 ->createCardTransactionManager();
92 = std::dynamic_pointer_cast<CardTransactionCryptoExtension>(
93 asymmetricCryptoCardTransactionManagerSpi);
95 mTransactionContext = std::make_shared<DtoAdapters::TransactionContextDto>(
96 card, asymmetricCryptoCardTransactionManagerSpi);
99 std::random_device rd;
100 std::mt19937 gen(rd());
104SecurePkiModeTransactionManagerAdapter::resetCommandContext()
106 mIsSecureSessionOpen =
false;
109std::shared_ptr<DtoAdapters::TransactionContextDto>
110SecurePkiModeTransactionManagerAdapter::getTransactionContext()
const
112 return mTransactionContext;
115std::shared_ptr<DtoAdapters::CommandContextDto>
116SecurePkiModeTransactionManagerAdapter::getCommandContext()
const
118 return std::make_shared<DtoAdapters::CommandContextDto>(
119 mIsSecureSessionOpen,
false);
123SecurePkiModeTransactionManagerAdapter::getPayloadCapacity()
const
125 return mPayloadCapacity;
129SecurePkiModeTransactionManagerAdapter::resetTransaction()
131 resetCommandContext();
133 mIsGetDataCardCertificatePrepared =
false;
134 mIsGetDataCaCertificatePrepared =
false;
136 disablePreOpenMode();
140 if (mTransactionContext->isSecureSessionOpen()) {
142 auto cancelSecureSessionCommand
143 = std::make_shared<CommandCloseSecureSession>(
144 mTransactionContext, getCommandContext(),
true);
146 cancelSecureSessionCommand->finalizeRequest();
147 std::vector<std::shared_ptr<Command>> commands(1);
148 commands.push_back(cancelSecureSessionCommand);
149 executeCardCommands(commands, ChannelControl::KEEP_OPEN);
151 }
catch (
const RuntimeException& e) {
153 "Failed to abort secure session [reason=%]\n", e.what());
157 mCard->restoreFiles();
158 mTransactionContext->setSecureSessionOpen(
false);
163SecurePkiModeTransactionManagerAdapter::prepareNewSecureSessionIfNeeded(
164 const std::shared_ptr<Command>& )
170SecurePkiModeTransactionManagerAdapter::canConfigureReadOnOpenSecureSession()
173 return mIsSecureSessionOpen && !mCommands.empty()
174 && mCommands[mCommands.size() - 1]->getCommandRef()
175 == CardCommandRef::OPEN_SECURE_SESSION
176 && !std::dynamic_pointer_cast<CommandOpenSecureSession>(
177 mCommands[mCommands.size() - 1])
178 ->isReadModeConfigured();
181SecurePkiModeTransactionManager&
182SecurePkiModeTransactionManagerAdapter::prepareVerifyPin(
183 const std::vector<std::uint8_t>& pin)
186 Assert::getInstance().isEqual(
187 pin.size(), CalypsoCardConstant::PIN_LENGTH,
"PIN length");
188 if (!mCard->isPinFeatureAvailable()) {
189 throw UnsupportedOperationException(MSG_PIN_NOT_AVAILABLE);
193 std::make_shared<CommandVerifyPin>(
194 mTransactionContext, getCommandContext(), pin));
204SecurePkiModeTransactionManager&
205SecurePkiModeTransactionManagerAdapter::prepareChangePin(
206 const std::vector<std::uint8_t>& newPin)
209 Assert::getInstance().isEqual(
210 newPin.size(), CalypsoCardConstant::PIN_LENGTH,
"PIN length");
211 if (!mCard->isPinFeatureAvailable()) {
212 throw UnsupportedOperationException(MSG_PIN_NOT_AVAILABLE);
217 std::make_shared<CommandChangePin>(
218 mTransactionContext, getCommandContext(), newPin));
228SecurePkiModeTransactionManager&
229SecurePkiModeTransactionManagerAdapter::prepareGetData(GetDataTag tag)
231 SecureTransactionManagerAdapter<
232 SecurePkiModeTransactionManager>::prepareGetData(tag);
234 if (tag == GetDataTag::CARD_CERTIFICATE) {
235 mIsGetDataCardCertificatePrepared =
true;
237 }
else if (tag == GetDataTag::CA_CERTIFICATE) {
238 mIsGetDataCaCertificatePrepared =
true;
263SecurePkiModeTransactionManager&
264SecurePkiModeTransactionManagerAdapter::processCommands(
265 ChannelControl channelControl)
267 if (mCommands.empty()) {
281 mOriginalChannelControl = channelControl;
282 if (mCard->getCaCertificate().size() == 0
283 && !mIsGetDataCaCertificatePrepared) {
284 executeCardCommands(mCommands, ChannelControl::KEEP_OPEN);
286 executeCardCommands(mCommands, channelControl);
305SecurePkiModeTransactionManagerAdapter::parseCommandResponse(
306 const std::shared_ptr<Command>& command,
307 const std::shared_ptr<ApduResponseApi>& apduResponse)
309 if (command->getCommandRef() == CardCommandRef::OPEN_SECURE_SESSION) {
310 checkCardCertificateAndGetCardPublicKey();
313 command->parseResponse(apduResponse);
317SecurePkiModeTransactionManagerAdapter ::
318 checkCardCertificateAndGetCardPublicKey()
321 std::shared_ptr<CardCertificateSpi> cardCertificateSpi
322 = parseCardCertificate();
325 mCard->getApplicationSerialNumber(),
326 cardCertificateSpi->getCardSerialNumber())) {
327 throw InvalidCertificateException(
328 "Card serial number and certificate card serial number mismatch");
332 std::shared_ptr<CaCertificateContentSpi> caCertificateContentSpi
333 = mAsymmetricCryptoSecuritySetting->getCaCertificate(
334 cardCertificateSpi->getIssuerPublicKeyReference());
340 if (caCertificateContentSpi ==
nullptr) {
348 std::shared_ptr<CaCertificateSpi> caCertificateSpi
349 = parseCaCertificate();
352 mAsymmetricCryptoSecuritySetting->addCaCertificate(
353 std::dynamic_pointer_cast<CaCertificate>(caCertificateSpi));
356 caCertificateContentSpi
357 = mAsymmetricCryptoSecuritySetting->getCaCertificate(
358 cardCertificateSpi->getIssuerPublicKeyReference());
362 if (mOriginalChannelControl == ChannelControl::CLOSE_AFTER) {
363 executeCardCommands({}, ChannelControl::CLOSE_AFTER);
371 std::shared_ptr<CardPublicKeySpi> cardPublicKeySpi;
374 cardPublicKeySpi = cardCertificateSpi->checkCertificateAndGetPublicKey(
375 caCertificateContentSpi);
377 }
catch (
const CertificateValidationException& e) {
378 throw InvalidCertificateException(MSG_INVALID_CARD_CERTIFICATE, e);
380 }
catch (
const AsymmetricCryptoException& e) {
381 throw CryptoException(
"Failed to check the card certificate", e);
385 mCard->setCardPublicKeySpi(cardPublicKeySpi);
388std::shared_ptr<CardCertificateSpi>
389SecurePkiModeTransactionManagerAdapter::parseCardCertificate()
391 const std::vector<std::uint8_t> cardCertificateBytes
392 = mCard->getCardCertificate();
394 std::shared_ptr<CardCertificateParserSpi> cardCertificateParser
395 = mAsymmetricCryptoSecuritySetting->getCardCertificateParser(
396 cardCertificateBytes[0]);
398 if (cardCertificateParser ==
nullptr) {
399 throw IllegalStateException(
400 "No certificate parser registered for type "
401 + HexUtil::toHex(cardCertificateBytes[0]));
405 return cardCertificateParser->parseCertificate(cardCertificateBytes);
407 }
catch (
const CertificateValidationException& e) {
408 throw InvalidCertificateException(MSG_INVALID_CARD_CERTIFICATE, e);
412std::shared_ptr<CaCertificateSpi>
413SecurePkiModeTransactionManagerAdapter::parseCaCertificate()
415 const std::vector<std::uint8_t> caCertificateBytes
416 = mCard->getCaCertificate();
418 std::shared_ptr<CaCertificateParserSpi> caCertificateParser
419 = mAsymmetricCryptoSecuritySetting->getCaCertificateParser(
420 caCertificateBytes[0]);
422 if (caCertificateParser ==
nullptr) {
423 throw IllegalStateException(
424 "No certificate parser registered for type "
425 + HexUtil::toHex(caCertificateBytes[0]));
429 return caCertificateParser->parseCertificate(caCertificateBytes);
431 }
catch (
const CertificateValidationException& e) {
432 throw InvalidCertificateException(MSG_INVALID_CA_CERTIFICATE, e);
437SecurePkiModeTransactionManagerAdapter::readCaCertificate()
439 std::vector<std::shared_ptr<Command>> commands(2);
442 std::make_shared<CommandGetDataCertificate>(
443 mTransactionContext, getCommandContext(),
false,
true));
445 std::make_shared<CommandGetDataCertificate>(
446 mTransactionContext, getCommandContext(),
false,
false));
448 executeCardCommands(commands, mOriginalChannelControl);
451std::shared_ptr<CardTransactionCryptoExtension>
452SecurePkiModeTransactionManagerAdapter::getCryptoExtension()
454 return mCryptoExtension;
457SecurePkiModeTransactionManager&
458SecurePkiModeTransactionManagerAdapter::prepareOpenSecureSession()
460 checkNoSecureSession();
462 if (mCard->getCardCertificate().size() == 0
463 && !mIsGetDataCardCertificatePrepared) {
464 prepareGetData(GetDataTag::CARD_CERTIFICATE);
467 std::vector<std::uint8_t> terminalChallenge(8);
468 mSecureRandom->nextBytes(terminalChallenge);
471 std::make_shared<CommandOpenSecureSession>(
472 mTransactionContext, getCommandContext(), terminalChallenge));
474 mIsSecureSessionOpen =
true;
479SecurePkiModeTransactionManager&
480SecurePkiModeTransactionManagerAdapter::prepareCloseSecureSession()
483 checkSecureSession();
485 std::make_shared<CommandCloseSecureSession>(
486 mTransactionContext, getCommandContext(),
false));
488 }
catch (
const std::exception&) {
492 resetCommandContext();
493 disablePreOpenMode();
499 resetCommandContext();
500 disablePreOpenMode();