Keyple Util C++ Library - 2.4.0
Component of the Keyple C++ middleware
ApduUtil.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/core/util/ApduUtil.hpp"
15
16#include <vector>
17
18#include "keyple/core/util/cpp/System.hpp"
19
20namespace keyple {
21namespace core {
22namespace util {
23
24using keyple::core::util::cpp::System;
25
26ApduUtil::ApduUtil()
27{
28}
29
30const std::vector<uint8_t>
31ApduUtil::build(
32 const uint8_t cla,
33 const uint8_t ins,
34 const uint8_t p1,
35 const uint8_t p2,
36 const std::vector<uint8_t>& dataIn,
37 const uint8_t le)
38{
39 std::vector<uint8_t> apduCommand;
40
41 /* Buffer allocation */
42 apduCommand = allocateBuffer(dataIn, le);
43
44 /* Build APDU buffer from provided arguments */
45 apduCommand[0] = cla;
46 apduCommand[1] = ins;
47 apduCommand[2] = p1;
48 apduCommand[3] = p2;
49
50 /* ISO7618 case determination and Le management */
51 if (dataIn.size() != 0) {
52 /* Append Lc and ingoing data */
53 apduCommand[4] = static_cast<uint8_t>(dataIn.size());
54 System::arraycopy(
55 dataIn, 0, apduCommand, 5, static_cast<int>(dataIn.size()));
56 apduCommand[apduCommand.size() - 1] = le;
57 } else {
58 /* Case2: outgoing data only */
59 apduCommand[4] = le;
60 }
61
62 return apduCommand;
63}
64
65const std::vector<uint8_t>
66ApduUtil::build(
67 const uint8_t cla,
68 const uint8_t ins,
69 const uint8_t p1,
70 const uint8_t p2,
71 const std::vector<uint8_t>& dataIn)
72{
73 std::vector<uint8_t> apduCommand;
74
75 /* Buffer allocation */
76 apduCommand = allocateBuffer(dataIn);
77
78 /* Build APDU buffer from provided arguments */
79 apduCommand[0] = cla;
80 apduCommand[1] = ins;
81 apduCommand[2] = p1;
82 apduCommand[3] = p2;
83
84 /* ISO7618 case determination and Le management */
85 if (dataIn.size() != 0) {
86 /* append Lc and ingoing data */
87 apduCommand[4] = static_cast<uint8_t>(dataIn.size());
88 System::arraycopy(
89 dataIn, 0, apduCommand, 5, static_cast<int>(dataIn.size()));
90 /* Case3: ingoing data only, no Le */
91 } else {
92 /* Case1: no ingoing, no outgoing data, P3/Le = 0 */
93 apduCommand[4] = 0x00;
94 }
95 return apduCommand;
96}
97
98const std::vector<uint8_t>
99ApduUtil::build(
100 const uint8_t cla,
101 const uint8_t ins,
102 const uint8_t p1,
103 const uint8_t p2,
104 const uint8_t le)
105{
106 std::vector<uint8_t> apduCommand;
107
108 /* Buffer allocation */
109 apduCommand = allocateBuffer(le);
110
111 /* Build APDU buffer from provided arguments */
112 apduCommand[0] = cla;
113 apduCommand[1] = ins;
114 apduCommand[2] = p1;
115 apduCommand[3] = p2;
116
117 /* ISO7618 case determination and Le management */
118 /* Case2: outgoing data only */
119 apduCommand[4] = le;
120
121 return apduCommand;
122}
123
124const std::vector<uint8_t>
125ApduUtil::build(
126 const uint8_t cla, const uint8_t ins, const uint8_t p1, const uint8_t p2)
127{
128 std::vector<uint8_t> apduCommand;
129
130 /* Buffer allocation */
131 apduCommand = allocateBuffer();
132
133 /* Build APDU buffer from provided arguments */
134 apduCommand[0] = cla;
135 apduCommand[1] = ins;
136 apduCommand[2] = p1;
137 apduCommand[3] = p2;
138
139 /* ISO7618 case determination and Le management */
140 /* Case1: no ingoing, no outgoing data, P3/Le = 0 */
141 apduCommand[4] = 0x00;
142
143 return apduCommand;
144}
145
146std::vector<uint8_t>
147ApduUtil::allocateBuffer(const std::vector<uint8_t>& data, const uint8_t le)
148{
149 (void)le;
150
151 int length = 4; // Header
152
153 length += static_cast<int>(data.size() + 1); // Lc + data
154 length += 1; // Le
155
156 return std::vector<uint8_t>(length);
157}
158
159std::vector<uint8_t>
160ApduUtil::allocateBuffer(const std::vector<uint8_t>& data)
161{
162 int length = 4; // Header
163
164 length += static_cast<int>(data.size() + 1); // Lc + data
165
166 return std::vector<uint8_t>(length);
167}
168
169std::vector<uint8_t>
170ApduUtil::allocateBuffer(const uint8_t le)
171{
172 (void)le;
173
174 int length = 4; // Header
175
176 length += 1; // Le
177
178 return std::vector<uint8_t>(length);
179}
180
181std::vector<uint8_t>
182ApduUtil::allocateBuffer()
183{
184 int length = 4; // Header
185
186 /* Case 1: 5-byte apdu, le=0 */
187 length += 1; // Le
188
189 return std::vector<uint8_t>(length);
190}
191
192bool
193ApduUtil::isCase4(const std::vector<uint8_t>& apduCommand)
194{
195 if (apduCommand.size() > 4) {
196 return apduCommand[4] == apduCommand.size() - 6;
197 }
198
199 return false;
200}
201
202} /* namespace util */
203} /* namespace core */
204} /* namespace keyple */