14#include "keyple/card/calypso/CommandVerifyPin.hpp"
21#include "keyple/card/calypso/CardAccessForbiddenException.hpp"
22#include "keyple/card/calypso/CardIllegalParameterException.hpp"
23#include "keyple/card/calypso/CardPinException.hpp"
24#include "keyple/card/calypso/CardSecurityContextException.hpp"
25#include "keyple/card/calypso/CardTerminatedException.hpp"
26#include "keyple/core/util/ApduUtil.hpp"
27#include "keypop/calypso/card/transaction/CryptoException.hpp"
28#include "keypop/calypso/card/transaction/CryptoIOException.hpp"
29#include "keypop/calypso/card/transaction/InvalidPinException.hpp"
30#include "keypop/calypso/crypto/symmetric/SymmetricCryptoException.hpp"
31#include "keypop/calypso/crypto/symmetric/SymmetricCryptoIOException.hpp"
37using keyple::core::util::ApduUtil;
38using keypop::calypso::card::transaction::CryptoException;
39using keypop::calypso::card::transaction::CryptoIOException;
40using keypop::calypso::card::transaction::InvalidPinException;
41using keypop::calypso::crypto::symmetric::SymmetricCryptoException;
42using keypop::calypso::crypto::symmetric::SymmetricCryptoIOException;
44const CardCommandRef CommandVerifyPin::mCommandRef = CardCommandRef::VERIFY_PIN;
46const std::map<int, const std::shared_ptr<Command::StatusProperties>>
47 CommandVerifyPin::STATUS_TABLE = [] {
48 std::map<int, const std::shared_ptr<Command::StatusProperties>> m(
49 Command::STATUS_TABLE);
53 std::make_shared<StatusProperties>(
54 "Lc value not supported (only 00h, 04h or 08h are supported)",
55 typeid(CardIllegalParameterException))},
57 std::make_shared<StatusProperties>(
58 "Transaction Counter is 0",
typeid(CardTerminatedException))},
60 std::make_shared<StatusProperties>(
61 std::string(
"Security conditions not fulfilled (Get ")
62 +
"Challenge not done: challenge unavailable)",
63 typeid(CardSecurityContextException))},
65 std::make_shared<StatusProperties>(
66 "Access forbidden (a session is open or DF is invalidated)",
67 typeid(CardAccessForbiddenException))},
69 std::make_shared<StatusProperties>(
70 "Incorrect PIN (1 attempt remaining)",
71 typeid(CardPinException))},
73 std::make_shared<StatusProperties>(
74 "Incorrect PIN (2 attempt remaining)",
75 typeid(CardPinException))},
77 std::make_shared<StatusProperties>(
78 "Presentation rejected (PIN is blocked)",
79 typeid(CardPinException))},
81 std::make_shared<StatusProperties>(
82 "PIN function not present",
83 typeid(CardIllegalParameterException))}});
87CommandVerifyPin::CommandVerifyPin(
88 const std::shared_ptr<DtoAdapters::TransactionContextDto>&
90 const std::shared_ptr<DtoAdapters::CommandContextDto>& commandContext,
91 const std::vector<std::uint8_t>& pin,
92 std::uint8_t cipheringKif,
93 std::uint8_t cipheringKvc)
95: Command(mCommandRef, 0, transactionContext, commandContext)
97, mIsReadCounterMode(false)
98, mIsPinEncryptedMode(true)
99, mCipheringKif(cipheringKif)
100, mCipheringKvc(cipheringKvc)
104CommandVerifyPin::CommandVerifyPin(
105 const std::shared_ptr<DtoAdapters::TransactionContextDto>&
107 const std::shared_ptr<DtoAdapters::CommandContextDto>& commandContext,
108 const std::vector<std::uint8_t>& pin)
109: Command(mCommandRef, 0, transactionContext, commandContext)
111, mIsReadCounterMode(false)
112, mIsPinEncryptedMode(false)
118CommandVerifyPin::CommandVerifyPin(
119 const std::shared_ptr<DtoAdapters::TransactionContextDto>&
121 const std::shared_ptr<DtoAdapters::CommandContextDto>& commandContext)
122: Command(mCommandRef, 0, transactionContext, commandContext)
124, mIsReadCounterMode(
true)
125, mIsPinEncryptedMode(
false)
132CommandVerifyPin::finalizeRequest()
134 if (mIsPinEncryptedMode) {
136 mPin = getTransactionContext()
137 ->getSymmetricCryptoCardTransactionManagerSpi()
138 ->cipherPinForPresentation(
139 getTransactionContext()->getCard()->getChallenge(),
141 std::make_shared<std::uint8_t>(mCipheringKif),
142 std::make_shared<std::uint8_t>(mCipheringKvc));
144 }
catch (
const SymmetricCryptoException& e) {
145 throw CryptoException(e.what(), e);
147 }
catch (
const SymmetricCryptoIOException& e) {
148 throw CryptoIOException(e.what(), e);
153 std::vector<std::uint8_t> apdu;
156 apdu = ApduUtil::build(
157 getTransactionContext()->getCard()->getCardClass().getValue(),
158 mCommandRef.getInstructionByte(),
163 apdu = ApduUtil::build(
164 getTransactionContext()->getCard()->getCardClass().getValue(),
165 mCommandRef.getInstructionByte(),
170 setApduRequest(std::make_shared<DtoAdapters::ApduRequestAdapter>(apdu));
173 mIsReadCounterMode ?
"Read presentation counter"
174 : mIsPinEncryptedMode ?
"Encrypted"
177 encryptRequestAndUpdateTerminalSessionMacIfNeeded();
181CommandVerifyPin::isCryptoServiceRequiredToFinalizeRequest()
const
183 return mIsPinEncryptedMode || getCommandContext()->isEncryptionActive();
187CommandVerifyPin::synchronizeCryptoServiceBeforeCardProcessing()
189 if (getCommandContext()->isEncryptionActive()) {
193 updateTerminalSessionIfNeeded(APDU_RESPONSE_9000);
199CommandVerifyPin::parseResponse(std::shared_ptr<ApduResponseApi> apduResponse)
201 decryptResponseAndUpdateTerminalSessionMacIfNeeded(apduResponse);
204 Command::setApduResponseAndCheckStatus(apduResponse);
205 getTransactionContext()->getCard()->setPinAttemptRemaining(3);
207 }
catch (
const CardPinException&) {
208 switch (apduResponse->getStatusWord()) {
210 getTransactionContext()->getCard()->setPinAttemptRemaining(2);
213 getTransactionContext()->getCard()->setPinAttemptRemaining(1);
216 getTransactionContext()->getCard()->setPinAttemptRemaining(0);
227 if (!mIsReadCounterMode) {
228 throw InvalidPinException(
229 std::string(
"Invalid PIN. Remaining ")
231 getTransactionContext()
233 ->getPinAttemptRemaining())
238 updateTerminalSessionIfNeeded();
241const std::map<int, const std::shared_ptr<Command::StatusProperties>>&
242CommandVerifyPin::getStatusTable()
const