Keyple Card Calypso C++ Library - 3.2.2
Component of the Keyple C++ middleware
CommandUpdateRecord.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/CommandUpdateRecord.hpp"
15
16#include <map>
17#include <memory>
18#include <sstream>
19#include <string>
20#include <vector>
21
22#include "keyple/card/calypso/CalypsoCardAdapter.hpp"
23#include "keyple/card/calypso/CalypsoCardClass.hpp"
24#include "keyple/card/calypso/CardAccessForbiddenException.hpp"
25#include "keyple/card/calypso/CardCommandRef.hpp"
26#include "keyple/card/calypso/CardDataAccessException.hpp"
27#include "keyple/card/calypso/CardIllegalParameterException.hpp"
28#include "keyple/card/calypso/CardSecurityContextException.hpp"
29#include "keyple/card/calypso/CardSessionBufferOverflowException.hpp"
30#include "keyple/core/util/ApduUtil.hpp"
31#include "keyple/core/util/HexUtil.hpp"
32#include "keyple/core/util/cpp/Arrays.hpp"
33#include "keyple/core/util/cpp/System.hpp"
34
35namespace keyple {
36namespace card {
37namespace calypso {
38
39using keyple::core::util::ApduUtil;
40using keyple::core::util::HexUtil;
41using keyple::core::util::cpp::Arrays;
42using keyple::core::util::cpp::System;
43
44const std::map<int, const std::shared_ptr<Command::StatusProperties>>
45 CommandUpdateRecord::STATUS_TABLE = [] {
46 std::map<int, const std::shared_ptr<Command::StatusProperties>> m(
47 Command::STATUS_TABLE);
48
49 m.insert(
50 {{0x6400,
51 std::make_shared<Command::StatusProperties>(
52 "Too many modifications in session",
53 typeid(CardSessionBufferOverflowException))},
54 {0x6700,
55 std::make_shared<Command::StatusProperties>(
56 "Lc value not supported", typeid(CardDataAccessException))},
57 {0x6981,
58 std::make_shared<Command::StatusProperties>(
59 "Command forbidden on cyclic files when the record exists "
60 "and "
61 "is not record 01h and on binary files",
62 typeid(CardDataAccessException))},
63 {0x6982,
64 std::make_shared<Command::StatusProperties>(
65 "Security conditions not fulfilled (no session, wrong key, "
66 "encryption required)",
67 typeid(CardSecurityContextException))},
68 {0x6985,
69 std::make_shared<Command::StatusProperties>(
70 "Access forbidden (Never access mode, DF is invalidated, "
71 "etc..)",
72 typeid(CardSecurityContextException))},
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 {0x6A83,
81 std::make_shared<Command::StatusProperties>(
82 "Record is not found (record index is 0 or above NumRec)",
83 typeid(CardDataAccessException))},
84 {0x6B00,
85 std::make_shared<Command::StatusProperties>(
86 "P2 value not supported",
87 typeid(CardIllegalParameterException))}});
88 return m;
89 }();
90
91CommandUpdateRecord::CommandUpdateRecord(
92 const std::shared_ptr<DtoAdapters::TransactionContextDto>&
93 transactionContext,
94 const std::shared_ptr<DtoAdapters::CommandContextDto>& commandContext,
95 std::uint8_t sfi,
96 std::uint8_t recordNumber,
97 const std::vector<uint8_t>& newRecordData)
98: Command(
99 CardCommandRef::UPDATE_RECORD,
100 std::unique_ptr<int>(new int(0)),
101 transactionContext,
102 commandContext)
103, mSfi(sfi)
104, mRecordNumber(recordNumber)
105, mData(newRecordData)
106{
107 const std::uint8_t p2 = (sfi == 0) ? 0x04 : sfi * 8 + 4;
108
109 // APDU Case 3
110 setApduRequest(
111 std::make_shared<DtoAdapters::ApduRequestAdapter>(ApduUtil::build(
112 transactionContext->getCard()->getCardClass().getValue(),
113 getCommandRef().getInstructionByte(),
114 recordNumber,
115 p2,
116 newRecordData)));
117
118 std::stringstream extraInfo;
119 extraInfo << "SFI:" << sfi << "h, "
120 << "REC:" << recordNumber;
121
122 addSubName(extraInfo.str());
123}
124
125void
126CommandUpdateRecord::finalizeRequest()
127{
128 encryptRequestAndUpdateTerminalSessionMacIfNeeded();
129}
130
131bool
132CommandUpdateRecord::isCryptoServiceRequiredToFinalizeRequest() const
133{
134 return getCommandContext()->isEncryptionActive();
135}
136
137bool
138CommandUpdateRecord::synchronizeCryptoServiceBeforeCardProcessing()
139{
140 if (getCommandContext()->isEncryptionActive()) {
141 return false;
142 }
143
144 updateTerminalSessionIfNeeded(APDU_RESPONSE_9000);
145
146 return true;
147}
148
149void
150CommandUpdateRecord::parseResponse(
151 std::shared_ptr<ApduResponseApi> apduResponse)
152{
153 decryptResponseAndUpdateTerminalSessionMacIfNeeded(apduResponse);
154 Command::setApduResponseAndCheckStatus(apduResponse);
155 getTransactionContext()->getCard()->setContent(mSfi, mRecordNumber, mData);
156 updateTerminalSessionIfNeeded();
157}
158
159const std::map<int, const std::shared_ptr<Command::StatusProperties>>&
160CommandUpdateRecord::getStatusTable() const
161{
162 return STATUS_TABLE;
163}
164
165} /* namespace calypso */
166} /* namespace card */
167} /* namespace keyple */