Keyple Card Calypso C++ Library - 3.2.2
Component of the Keyple C++ middleware
CommandAppendRecord.cpp
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ *
3 * *
4 * See the NOTICE file(s) distributed with this work for additional *
5 * information regarding copyright ownership. *
6 * *
7 * This program and the accompanying materials are made available under the *
8 * terms of the Eclipse Public License 2.0 which is available at *
9 * http://www.eclipse.org/legal/epl-2.0 *
10 * *
11 * SPDX-License-Identifier: EPL-2.0 *
12 ******************************************************************************/
13
14#include "keyple/card/calypso/CommandAppendRecord.hpp"
15
16#include <map>
17#include <memory>
18#include <string>
19#include <vector>
20
21#include "keyple/card/calypso/CalypsoCardAdapter.hpp"
22#include "keyple/card/calypso/CalypsoCardClass.hpp"
23#include "keyple/card/calypso/CardAccessForbiddenException.hpp"
24#include "keyple/card/calypso/CardCommandRef.hpp"
25#include "keyple/card/calypso/CardDataAccessException.hpp"
26#include "keyple/card/calypso/CardIllegalParameterException.hpp"
27#include "keyple/card/calypso/CardSecurityContextException.hpp"
28#include "keyple/card/calypso/CardSessionBufferOverflowException.hpp"
29#include "keyple/core/util/ApduUtil.hpp"
30#include "keyple/core/util/HexUtil.hpp"
31#include "keyple/core/util/cpp/Arrays.hpp"
32#include "keyple/core/util/cpp/System.hpp"
33
34namespace keyple {
35namespace card {
36namespace calypso {
37
38using keyple::core::util::ApduUtil;
39using keyple::core::util::HexUtil;
40using keyple::core::util::cpp::Arrays;
41using keyple::core::util::cpp::System;
42
43const std::map<int, const std::shared_ptr<Command::StatusProperties>>
44 CommandAppendRecord::STATUS_TABLE = [] {
45 std::map<int, const std::shared_ptr<Command::StatusProperties>> m(
46 Command::STATUS_TABLE);
47
48 m.insert(
49 {{0x6B00,
50 std::make_shared<Command::StatusProperties>(
51 "P1 or P2 value not supported",
52 typeid(CardIllegalParameterException))},
53 {0x6700,
54 std::make_shared<Command::StatusProperties>(
55 "Lc value not supported", typeid(CardDataAccessException))},
56 {0x6400,
57 std::make_shared<Command::StatusProperties>(
58 "Too many modifications in session",
59 typeid(CardSessionBufferOverflowException))},
60 {0x6981,
61 std::make_shared<Command::StatusProperties>(
62 "The current EF is not a Cyclic EF",
63 typeid(CardDataAccessException))},
64 {0x6982,
65 std::make_shared<Command::StatusProperties>(
66 "Security conditions not fulfilled (no session, wrong key)",
67 typeid(CardSecurityContextException))},
68 {0x6985,
69 std::make_shared<Command::StatusProperties>(
70 "Access forbidden (Never access mode, DF is invalidated, "
71 "etc..)",
72 typeid(CardAccessForbiddenException))},
73 {0x6986,
74 std::make_shared<Command::StatusProperties>(
75 "Command not allowed (no current EF)",
76 typeid(CardDataAccessException))},
77 {0x6A82,
78 std::make_shared<Command::StatusProperties>(
79 "File not found", typeid(CardDataAccessException))}});
80 return m;
81 }();
82
83CommandAppendRecord::CommandAppendRecord(
84 const std::shared_ptr<DtoAdapters::TransactionContextDto>&
85 transactionContext,
86 const std::shared_ptr<DtoAdapters::CommandContextDto>& commandContext,
87 int sfi,
88 const std::vector<std::uint8_t>& data)
89: Command(
90 CardCommandRef::APPEND_RECORD,
91 std::unique_ptr<int>(new int(0)),
92 transactionContext,
93 commandContext)
94, mSfi(sfi)
95, mData(data)
96{
97 const std::uint8_t p1 = 0x00;
98 const std::uint8_t p2
99 = static_cast<std::uint8_t>((sfi == 0) ? 0x00 : (sfi * 8));
100
101 /* APDU Case 3 */
102 setApduRequest(
103 std::make_shared<DtoAdapters::ApduRequestAdapter>(ApduUtil::build(
104 transactionContext->getCard()->getCardClass().getValue(),
105 getCommandRef().getInstructionByte(),
106 p1,
107 p2,
108 data)));
109
110 addSubName(
111 std::string("SFI: ") + HexUtil::toHex(static_cast<std::uint8_t>(sfi))
112 + "h");
113}
114
115void
116CommandAppendRecord::finalizeRequest()
117{
118 encryptRequestAndUpdateTerminalSessionMacIfNeeded();
119}
120
121bool
122CommandAppendRecord::isCryptoServiceRequiredToFinalizeRequest() const
123{
124 return getCommandContext()->isEncryptionActive();
125}
126
127bool
128CommandAppendRecord::synchronizeCryptoServiceBeforeCardProcessing()
129{
130 if (getCommandContext()->isEncryptionActive()) {
131 return false;
132 }
133
134 updateTerminalSessionIfNeeded(APDU_RESPONSE_9000);
135
136 return true;
137}
138
139void
140CommandAppendRecord::parseResponse(
141 std::shared_ptr<ApduResponseApi> apduResponse)
142{
143 decryptResponseAndUpdateTerminalSessionMacIfNeeded(apduResponse);
144 Command::setApduResponseAndCheckStatus(apduResponse);
145 getTransactionContext()->getCard()->addCyclicContent(
146 static_cast<std::uint8_t>(mSfi), mData);
147 updateTerminalSessionIfNeeded();
148}
149
150const std::map<int, const std::shared_ptr<Command::StatusProperties>>&
151CommandAppendRecord::getStatusTable() const
152{
153 return STATUS_TABLE;
154}
155
156} /* namespace calypso */
157} /* namespace card */
158} /* namespace keyple */