SE050 Driver
API reference
Loading...
Searching...
No Matches
se050_device.hpp
Go to the documentation of this file.
1
7#pragma once
8
9#include "se050_applet.hpp"
10#include "se050_commands.hpp"
11#include "se050_rfc3394.hpp"
12#include "se050_scp03.hpp"
13#include "se050_session.hpp"
14#include "se050_t1_session.hpp"
15#include "se050_types.hpp"
16
17#include <cstddef>
18#include <cstdint>
19
20namespace se050 {
21
22template <typename TransportT>
23class Device {
24public:
25 explicit Device(TransportT& transport) noexcept : session_(transport), t1_(transport) {}
26
27 [[nodiscard]] bool EnsureInitialized() noexcept { return session_.EnsureReady(); }
28
30 [[nodiscard]] Error TransceiveRaw(const std::uint8_t* tx, std::size_t tx_len,
31 std::uint8_t* rx, std::size_t rx_cap,
32 std::size_t* rx_len_out,
33 std::uint32_t timeout_ms) noexcept {
34 return session_.TransceiveRaw(tx, tx_len, rx, rx_cap, rx_len_out, timeout_ms);
35 }
36
37 [[nodiscard]] Error HardwareReset() noexcept { return session_.PulseReset(); }
38
40 [[nodiscard]] T1Session<TransportT>& T1() noexcept { return t1_; }
41 [[nodiscard]] const T1Session<TransportT>& T1() const noexcept { return t1_; }
42
44 [[nodiscard]] scp03::Session<TransportT>& Scp03() noexcept { return scp03_; }
45 [[nodiscard]] const scp03::Session<TransportT>& Scp03() const noexcept { return scp03_; }
46
51 void BindScp03WrapScratch(std::uint8_t* buf, std::size_t cap) noexcept {
52 scp03_wrap_ = buf;
53 scp03_wrap_cap_ = cap;
54 }
55
70 [[nodiscard]] Error TransmitApdu(const std::uint8_t* capdu, std::size_t capdu_len, std::uint8_t* rapdu_buf,
71 std::size_t rapdu_cap, std::size_t* rapdu_len,
72 std::uint32_t timeout_ms) noexcept {
73 if (rapdu_len == nullptr) {
75 }
76 *rapdu_len = 0;
77 if (!EnsureInitialized()) {
79 }
80 if (scp03_.Failed()) {
81 return Error::Authentication; /* never fall back to plaintext after a lost channel */
82 }
83 if (!scp03_.IsOpen()) {
84 return t1_.ExchangeInformation(capdu, capdu_len, rapdu_buf, rapdu_cap, rapdu_len, timeout_ms);
85 }
86 if (scp03_wrap_ == nullptr || scp03_wrap_cap_ < scp03::kWrapScratchBytes) {
88 }
89 std::size_t wrapped_len = 0;
90 Error e = scp03_.WrapCommand(capdu, capdu_len, scp03_wrap_, scp03_wrap_cap_, &wrapped_len);
91 if (e != Error::Ok) {
92 return e; /* nothing sent; the channel is unchanged */
93 }
94 e = t1_.ExchangeInformation(scp03_wrap_, wrapped_len, rapdu_buf, rapdu_cap, rapdu_len, timeout_ms);
95 if (e != Error::Ok) {
96 /* The MAC chaining value moved on but the answer is lost: host and card are out of step. */
97 scp03_.Abort();
98 *rapdu_len = 0;
99 return e;
100 }
101 return scp03_.UnwrapResponse(rapdu_buf, *rapdu_len, rapdu_buf, rapdu_cap, rapdu_len);
102 }
103
110 [[nodiscard]] Error SelectDefaultIoTApplet(std::uint8_t* rapdu_buf, std::size_t rapdu_cap, std::size_t* rapdu_len,
111 std::uint32_t timeout_ms) noexcept {
112 std::uint8_t capdu[5U + sizeof(applet::kDefaultIoTAppletAid) + 1U]{};
113 std::size_t capdu_len = 0;
114 const Error be = applet::BuildSelectDefaultIot(capdu, sizeof(capdu), &capdu_len);
115 if (be != Error::Ok) {
116 return be;
117 }
118 return TransmitApdu(capdu, capdu_len, rapdu_buf, rapdu_cap, rapdu_len, timeout_ms);
119 }
120
126 [[nodiscard]] Error SelectCardManager(std::uint8_t* rapdu_buf, std::size_t rapdu_cap, std::size_t* rapdu_len,
127 std::uint32_t timeout_ms) noexcept {
128 std::uint8_t capdu[5U + sizeof(applet::kCardManagerAid) + 1U]{};
129 std::size_t capdu_len = 0;
130 const Error be = applet::BuildSelectCardManager(capdu, sizeof(capdu), &capdu_len);
131 if (be != Error::Ok) {
132 return be;
133 }
134 return TransmitApdu(capdu, capdu_len, rapdu_buf, rapdu_cap, rapdu_len, timeout_ms);
135 }
136
137 [[nodiscard]] Error GetVersion(cmd::VersionInfo* out, std::uint32_t timeout_ms) noexcept {
138 if (out == nullptr) {
140 }
141 std::uint8_t capdu[32]{};
142 std::size_t capdu_len = 0;
143 Error e = cmd::BuildGetVersion(capdu, sizeof(capdu), &capdu_len);
144 if (e != Error::Ok) {
145 return e;
146 }
147 std::uint8_t rapdu[64]{};
148 std::size_t rapdu_len = 0;
149 e = TransmitApdu(capdu, capdu_len, rapdu, sizeof(rapdu), &rapdu_len, timeout_ms);
150 if (e != Error::Ok) {
151 return e;
152 }
153 return cmd::ParseVersionInfo(rapdu, rapdu_len, out);
154 }
155
156 [[nodiscard]] Error GetRandom(std::uint16_t bytes_requested, std::uint8_t* out, std::size_t out_cap,
157 std::size_t* out_len, std::uint32_t timeout_ms) noexcept {
158 if (out_len == nullptr) {
160 }
161 *out_len = 0;
162 std::uint8_t capdu[32]{};
163 std::size_t capdu_len = 0;
164 Error e = cmd::BuildGetRandom(bytes_requested, capdu, sizeof(capdu), &capdu_len);
165 if (e != Error::Ok) {
166 return e;
167 }
168 std::uint8_t rapdu[kMaxApduResponseBytes]{};
169 std::size_t rapdu_len = 0;
170 e = TransmitApdu(capdu, capdu_len, rapdu, sizeof(rapdu), &rapdu_len, timeout_ms);
171 if (e != Error::Ok) {
172 return e;
173 }
174 return cmd::ParseDataTag1(rapdu, rapdu_len, out, out_cap, out_len);
175 }
176
177 [[nodiscard]] Error GetFreeMemory(cmd::MemoryType memory_type, std::uint16_t* free_bytes,
178 std::uint32_t timeout_ms) noexcept {
179 if (free_bytes == nullptr) {
181 }
182 std::uint8_t capdu[32]{};
183 std::size_t capdu_len = 0;
184 Error e = cmd::BuildGetFreeMemory(memory_type, capdu, sizeof(capdu), &capdu_len);
185 if (e != Error::Ok) {
186 return e;
187 }
188 std::uint8_t rapdu[64]{};
189 std::size_t rapdu_len = 0;
190 e = TransmitApdu(capdu, capdu_len, rapdu, sizeof(rapdu), &rapdu_len, timeout_ms);
191 if (e != Error::Ok) {
192 return e;
193 }
194 return cmd::ParseFreeMemory(rapdu, rapdu_len, free_bytes);
195 }
196
197 [[nodiscard]] Error WriteBinary(const cmd::ObjectId& object_id, const std::uint8_t* data, std::size_t data_len,
198 bool has_offset, std::uint16_t offset, bool has_file_length,
199 std::uint16_t file_length, std::uint32_t timeout_ms) noexcept {
200 std::uint8_t capdu[kMaxApduCommandBytes]{};
201 std::size_t capdu_len = 0;
202 Error e = cmd::BuildWriteBinary(object_id, data, data_len, has_offset, offset, has_file_length, file_length,
203 capdu, sizeof(capdu), &capdu_len);
204 if (e != Error::Ok) {
205 return e;
206 }
207 std::uint8_t rapdu[64]{};
208 std::size_t rapdu_len = 0;
209 e = TransmitApdu(capdu, capdu_len, rapdu, sizeof(rapdu), &rapdu_len, timeout_ms);
210 if (e != Error::Ok) {
211 return e;
212 }
213 const std::uint8_t* payload = nullptr;
214 std::size_t payload_len = 0;
216 e = apdu::ParseResponse(rapdu, rapdu_len, &payload, &payload_len, &sw);
217 if (e != Error::Ok) {
218 return e;
219 }
221 }
222
223 [[nodiscard]] Error ReadObject(const cmd::ObjectId& object_id, bool has_offset, std::uint16_t offset,
224 bool has_length, std::uint16_t length, std::uint8_t* out, std::size_t out_cap,
225 std::size_t* out_len, std::uint32_t timeout_ms) noexcept {
226 if (out_len == nullptr) {
228 }
229 *out_len = 0;
230 std::uint8_t capdu[64]{};
231 std::size_t capdu_len = 0;
232 Error e = cmd::BuildReadObject(object_id, has_offset, offset, has_length, length, capdu, sizeof(capdu),
233 &capdu_len);
234 if (e != Error::Ok) {
235 return e;
236 }
237 std::uint8_t rapdu[kMaxApduResponseBytes]{};
238 std::size_t rapdu_len = 0;
239 e = TransmitApdu(capdu, capdu_len, rapdu, sizeof(rapdu), &rapdu_len, timeout_ms);
240 if (e != Error::Ok) {
241 return e;
242 }
243 return cmd::ParseDataTag1(rapdu, rapdu_len, out, out_cap, out_len);
244 }
245
246 [[nodiscard]] Error DeleteSecureObject(const cmd::ObjectId& object_id, std::uint32_t timeout_ms) noexcept {
247 std::uint8_t capdu[32]{};
248 std::size_t capdu_len = 0;
249 Error e = cmd::BuildDeleteSecureObject(object_id, capdu, sizeof(capdu), &capdu_len);
250 if (e != Error::Ok) {
251 return e;
252 }
253 std::uint8_t rapdu[64]{};
254 std::size_t rapdu_len = 0;
255 e = TransmitApdu(capdu, capdu_len, rapdu, sizeof(rapdu), &rapdu_len, timeout_ms);
256 if (e != Error::Ok) {
257 return e;
258 }
259 const std::uint8_t* payload = nullptr;
260 std::size_t payload_len = 0;
262 e = apdu::ParseResponse(rapdu, rapdu_len, &payload, &payload_len, &sw);
263 if (e != Error::Ok) {
264 return e;
265 }
267 }
268
269 [[nodiscard]] Error CheckObjectExists(const cmd::ObjectId& object_id, bool* exists,
270 std::uint32_t timeout_ms) noexcept {
271 if (exists == nullptr) {
273 }
274 *exists = false;
275 std::uint8_t capdu[32]{};
276 std::size_t capdu_len = 0;
277 Error e = cmd::BuildCheckObjectExists(object_id, capdu, sizeof(capdu), &capdu_len);
278 if (e != Error::Ok) {
279 return e;
280 }
281 std::uint8_t rapdu[96]{};
282 std::size_t rapdu_len = 0;
283 e = TransmitApdu(capdu, capdu_len, rapdu, sizeof(rapdu), &rapdu_len, timeout_ms);
284 if (e != Error::Ok) {
285 return e;
286 }
287 return cmd::ParseObjectExistsResult(rapdu, rapdu_len, exists);
288 }
289
290 [[nodiscard]] Error ReadPublicEcKey(const cmd::ObjectId& key_id, std::uint8_t* out, std::size_t out_cap,
291 std::size_t* out_len, std::uint32_t timeout_ms) noexcept {
292 return ReadObject(key_id, false, 0U, false, 0U, out, out_cap, out_len, timeout_ms);
293 }
294
295 [[nodiscard]] Error GenerateEcKeyPair(const cmd::ObjectId& object_id, cmd::EcCurve curve,
296 std::uint32_t timeout_ms) noexcept {
297 std::uint8_t capdu[64]{};
298 std::size_t capdu_len = 0;
299 Error e = cmd::BuildGenerateEcKeyPair(object_id, curve, capdu, sizeof(capdu), &capdu_len);
300 if (e != Error::Ok) {
301 return e;
302 }
303 std::uint8_t rapdu[64]{};
304 std::size_t rapdu_len = 0;
305 e = TransmitApdu(capdu, capdu_len, rapdu, sizeof(rapdu), &rapdu_len, timeout_ms);
306 if (e != Error::Ok) {
307 return e;
308 }
309 const std::uint8_t* payload = nullptr;
310 std::size_t payload_len = 0;
312 e = apdu::ParseResponse(rapdu, rapdu_len, &payload, &payload_len, &sw);
313 if (e != Error::Ok) {
314 return e;
315 }
317 }
318
319 [[nodiscard]] Error EcdsaSign(const cmd::ObjectId& key_id, cmd::EcdsaAlgo algo,
320 const std::uint8_t* digest, std::size_t digest_len,
321 std::uint8_t* signature_out, std::size_t signature_cap,
322 std::size_t* signature_len, std::uint32_t timeout_ms) noexcept {
323 if (signature_len == nullptr) {
325 }
326 *signature_len = 0;
327 std::uint8_t capdu[256]{};
328 std::size_t capdu_len = 0;
329 Error e = cmd::BuildEcdsaSign(key_id, algo, digest, digest_len, capdu, sizeof(capdu), &capdu_len);
330 if (e != Error::Ok) {
331 return e;
332 }
333 std::uint8_t rapdu[kMaxApduResponseBytes]{};
334 std::size_t rapdu_len = 0;
335 e = TransmitApdu(capdu, capdu_len, rapdu, sizeof(rapdu), &rapdu_len, timeout_ms);
336 if (e != Error::Ok) {
337 return e;
338 }
339 return cmd::ParseDataTag1(rapdu, rapdu_len, signature_out, signature_cap, signature_len);
340 }
341
342 [[nodiscard]] Error EcdsaVerify(const cmd::ObjectId& key_id, cmd::EcdsaAlgo algo,
343 const std::uint8_t* digest, std::size_t digest_len,
344 const std::uint8_t* signature, std::size_t signature_len,
345 bool* verified, std::uint32_t timeout_ms) noexcept {
346 if (verified == nullptr) {
348 }
349 *verified = false;
350 std::uint8_t capdu[384]{};
351 std::size_t capdu_len = 0;
352 Error e = cmd::BuildEcdsaVerify(key_id, algo, digest, digest_len, signature, signature_len, capdu,
353 sizeof(capdu), &capdu_len);
354 if (e != Error::Ok) {
355 return e;
356 }
357 std::uint8_t rapdu[96]{};
358 std::size_t rapdu_len = 0;
359 e = TransmitApdu(capdu, capdu_len, rapdu, sizeof(rapdu), &rapdu_len, timeout_ms);
360 if (e != Error::Ok) {
361 return e;
362 }
363 return cmd::ParseVerifyResult(rapdu, rapdu_len, verified);
364 }
365
371 [[nodiscard]] Error WriteAesKey(const cmd::ObjectId& object_id, const std::uint8_t* key, std::size_t key_len,
372 std::uint32_t timeout_ms) noexcept {
373 std::uint8_t capdu[80]{};
374 std::size_t capdu_len = 0;
375 Error e = cmd::BuildWriteAesKey(object_id, key, key_len, capdu, sizeof(capdu), &capdu_len);
376 if (e != Error::Ok) {
377 return e;
378 }
379 std::uint8_t rapdu[32]{};
380 std::size_t rapdu_len = 0;
381 e = TransmitApdu(capdu, capdu_len, rapdu, sizeof(rapdu), &rapdu_len, timeout_ms);
382 if (e != Error::Ok) {
383 return e;
384 }
385 const std::uint8_t* payload = nullptr;
386 std::size_t payload_len = 0;
388 e = apdu::ParseResponse(rapdu, rapdu_len, &payload, &payload_len, &sw);
389 if (e != Error::Ok) {
390 return e;
391 }
393 }
394
400 [[nodiscard]] Error CipherAesEcb(const cmd::ObjectId& key_id, bool decrypt, const std::uint8_t* in,
401 std::size_t in_len, std::uint8_t* out, std::size_t out_cap, std::size_t* out_len,
402 std::uint32_t timeout_ms) noexcept {
403 if (out_len == nullptr) {
405 }
406 *out_len = 0;
407 if (in == nullptr || out == nullptr || in_len == 0U || (in_len % 16U) != 0U) {
409 }
410 std::uint8_t capdu[80]{};
411 std::size_t capdu_len = 0;
412 Error e = cmd::BuildCipherOneShot(key_id, decrypt, in, in_len, capdu, sizeof(capdu), &capdu_len);
413 if (e != Error::Ok) {
414 return e;
415 }
416 std::uint8_t rapdu[48]{};
417 std::size_t rapdu_len = 0;
418 e = TransmitApdu(capdu, capdu_len, rapdu, sizeof(rapdu), &rapdu_len, timeout_ms);
419 if (e != Error::Ok) {
420 return e;
421 }
422 return cmd::ParseDataTag1(rapdu, rapdu_len, out, out_cap, out_len);
423 }
424
429 [[nodiscard]] Error UnwrapAes256Rfc3394(const cmd::ObjectId& kek_id, const std::uint8_t* wrapped,
430 std::size_t wrapped_len, std::uint8_t* out, std::size_t out_cap,
431 std::size_t* out_len, std::uint32_t timeout_ms) noexcept {
432 struct Ctx {
433 Device* self;
434 cmd::ObjectId id;
435 std::uint32_t timeout_ms;
436 };
437 Ctx ctx{this, kek_id, timeout_ms};
438 auto decrypt = [](const std::uint8_t in[16], std::uint8_t outb[16], void* v) -> Error {
439 auto* c = static_cast<Ctx*>(v);
440 std::size_t n = 0;
441 const Error e = c->self->CipherAesEcb(c->id, true, in, 16U, outb, 16U, &n, c->timeout_ms);
442 if (e != Error::Ok) {
443 return e;
444 }
445 return (n == 16U) ? Error::Ok : Error::Protocol;
446 };
447 return rfc3394::Unwrap(wrapped, wrapped_len, out, out_cap, out_len, decrypt, &ctx);
448 }
449
450 Session<TransportT>& SessionRef() noexcept { return session_; }
451 const Session<TransportT>& SessionRef() const noexcept { return session_; }
452
453private:
454 Session<TransportT> session_;
457 std::uint8_t* scp03_wrap_{nullptr};
458 std::size_t scp03_wrap_cap_{0};
459};
460
461} // namespace se050
Definition se050_device.hpp:23
Error SelectDefaultIoTApplet(std::uint8_t *rapdu_buf, std::size_t rapdu_cap, std::size_t *rapdu_len, std::uint32_t timeout_ms) noexcept
SELECT the default IoT applet (applet::kDefaultIoTAppletAid, short Le).
Definition se050_device.hpp:110
Error WriteAesKey(const cmd::ObjectId &object_id, const std::uint8_t *key, std::size_t key_len, std::uint32_t timeout_ms) noexcept
Write a persistent AESKey (AN12413 WriteSymmKey, P1_AES).
Definition se050_device.hpp:371
Device(TransportT &transport) noexcept
Definition se050_device.hpp:25
Error ReadPublicEcKey(const cmd::ObjectId &key_id, std::uint8_t *out, std::size_t out_cap, std::size_t *out_len, std::uint32_t timeout_ms) noexcept
Definition se050_device.hpp:290
T1Session< TransportT > & T1() noexcept
ISO 7816-3 T=1 session bound to the same transport as SessionRef.
Definition se050_device.hpp:40
Error TransmitApdu(const std::uint8_t *capdu, std::size_t capdu_len, std::uint8_t *rapdu_buf, std::size_t rapdu_cap, std::size_t *rapdu_len, std::uint32_t timeout_ms) noexcept
Transmit a C-APDU (already serialized) and receive the R-APDU INF bytes.
Definition se050_device.hpp:70
const scp03::Session< TransportT > & Scp03() const noexcept
Definition se050_device.hpp:45
Error CipherAesEcb(const cmd::ObjectId &key_id, bool decrypt, const std::uint8_t *in, std::size_t in_len, std::uint8_t *out, std::size_t out_cap, std::size_t *out_len, std::uint32_t timeout_ms) noexcept
One-shot AES-ECB (AN12413 CipherOneShot, AES_ECB_NOPAD).
Definition se050_device.hpp:400
Error GetVersion(cmd::VersionInfo *out, std::uint32_t timeout_ms) noexcept
Definition se050_device.hpp:137
Error GetRandom(std::uint16_t bytes_requested, std::uint8_t *out, std::size_t out_cap, std::size_t *out_len, std::uint32_t timeout_ms) noexcept
Definition se050_device.hpp:156
Session< TransportT > & SessionRef() noexcept
Definition se050_device.hpp:450
scp03::Session< TransportT > & Scp03() noexcept
SCP03 session. Handshake uses T=1 directly; wrapped APDUs go through TransmitApdu.
Definition se050_device.hpp:44
Error UnwrapAes256Rfc3394(const cmd::ObjectId &kek_id, const std::uint8_t *wrapped, std::size_t wrapped_len, std::uint8_t *out, std::size_t out_cap, std::size_t *out_len, std::uint32_t timeout_ms) noexcept
RFC 3394 unwrap of an AES-256 CEK using kek_id as the wrapping key.
Definition se050_device.hpp:429
const Session< TransportT > & SessionRef() const noexcept
Definition se050_device.hpp:451
Error EcdsaVerify(const cmd::ObjectId &key_id, cmd::EcdsaAlgo algo, const std::uint8_t *digest, std::size_t digest_len, const std::uint8_t *signature, std::size_t signature_len, bool *verified, std::uint32_t timeout_ms) noexcept
Definition se050_device.hpp:342
bool EnsureInitialized() noexcept
Definition se050_device.hpp:27
Error TransceiveRaw(const std::uint8_t *tx, std::size_t tx_len, std::uint8_t *rx, std::size_t rx_cap, std::size_t *rx_len_out, std::uint32_t timeout_ms) noexcept
Raw I²C exchange (legacy / bring-up); prefer T1 for SE050 T=1 blocks.
Definition se050_device.hpp:30
void BindScp03WrapScratch(std::uint8_t *buf, std::size_t cap) noexcept
Bind caller-owned wrap workspace (CM4: D2 .se_apdu_scratch, not a task stack).
Definition se050_device.hpp:51
Error CheckObjectExists(const cmd::ObjectId &object_id, bool *exists, std::uint32_t timeout_ms) noexcept
Definition se050_device.hpp:269
Error WriteBinary(const cmd::ObjectId &object_id, const std::uint8_t *data, std::size_t data_len, bool has_offset, std::uint16_t offset, bool has_file_length, std::uint16_t file_length, std::uint32_t timeout_ms) noexcept
Definition se050_device.hpp:197
const T1Session< TransportT > & T1() const noexcept
Definition se050_device.hpp:41
Error DeleteSecureObject(const cmd::ObjectId &object_id, std::uint32_t timeout_ms) noexcept
Definition se050_device.hpp:246
Error HardwareReset() noexcept
Definition se050_device.hpp:37
Error GenerateEcKeyPair(const cmd::ObjectId &object_id, cmd::EcCurve curve, std::uint32_t timeout_ms) noexcept
Definition se050_device.hpp:295
Error ReadObject(const cmd::ObjectId &object_id, bool has_offset, std::uint16_t offset, bool has_length, std::uint16_t length, std::uint8_t *out, std::size_t out_cap, std::size_t *out_len, std::uint32_t timeout_ms) noexcept
Definition se050_device.hpp:223
Error GetFreeMemory(cmd::MemoryType memory_type, std::uint16_t *free_bytes, std::uint32_t timeout_ms) noexcept
Definition se050_device.hpp:177
Error EcdsaSign(const cmd::ObjectId &key_id, cmd::EcdsaAlgo algo, const std::uint8_t *digest, std::size_t digest_len, std::uint8_t *signature_out, std::size_t signature_cap, std::size_t *signature_len, std::uint32_t timeout_ms) noexcept
Definition se050_device.hpp:319
Error SelectCardManager(std::uint8_t *rapdu_buf, std::size_t rapdu_cap, std::size_t *rapdu_len, std::uint32_t timeout_ms) noexcept
SELECT the GlobalPlatform Card Manager (ISD) for PUT KEY.
Definition se050_device.hpp:126
Transport-facing session (no owned buffers).
Definition se050_session.hpp:25
Stateful T=1 session bound to a concrete I²C transport.
Definition se050_t1_session.hpp:101
SCP03 session bound to a T=1 transport.
Definition se050_scp03.hpp:398
bool IsSuccess(const StatusWords &sw) noexcept
Return true when SW1 == 0x90 and SW2 == 0x00.
Definition se050_apdu.hpp:161
Error ParseResponse(const std::uint8_t *rsp, std::size_t rsp_len, const std::uint8_t **data_out, std::size_t *data_len_out, StatusWords *sw_out) noexcept
Parse a simple R-APDU: optional response data followed by SW1 SW2.
Definition se050_apdu.hpp:144
constexpr std::uint8_t kCardManagerAid[]
GlobalPlatform Card Manager / ISD AID (8 bytes).
Definition se050_applet.hpp:40
constexpr std::uint8_t kDefaultIoTAppletAid[]
NXP Plug & Trust SE05x IoT applet AID (16 bytes).
Definition se050_applet.hpp:27
Error BuildSelectDefaultIot(std::uint8_t *out, std::size_t cap, std::size_t *out_len) noexcept
Build SELECT (CLA=0x00, INS=0xA4, P1=0x04, P2=0x00) for kDefaultIoTAppletAid.
Definition se050_applet.hpp:51
Error BuildSelectCardManager(std::uint8_t *out, std::size_t cap, std::size_t *out_len) noexcept
Build SELECT for the Card Manager / ISD (kCardManagerAid).
Definition se050_applet.hpp:60
Error BuildEcdsaSign(const ObjectId &key_id, EcdsaAlgo algo, const std::uint8_t *digest, std::size_t digest_len, std::uint8_t *out, std::size_t out_cap, std::size_t *out_len) noexcept
Definition se050_commands.hpp:282
Error ParseDataTag1(const std::uint8_t *rapdu, std::size_t rapdu_len, std::uint8_t *out, std::size_t out_cap, std::size_t *out_len) noexcept
Definition se050_commands.hpp:399
Error BuildCipherOneShot(const ObjectId &key_id, bool decrypt, const std::uint8_t *data, std::size_t data_len, std::uint8_t *out, std::size_t out_cap, std::size_t *out_len) noexcept
Definition se050_commands.hpp:230
Error BuildGetRandom(std::uint16_t random_len, std::uint8_t *out, std::size_t out_cap, std::size_t *out_len) noexcept
Definition se050_commands.hpp:93
Error BuildGetFreeMemory(MemoryType memory_type, std::uint8_t *out, std::size_t out_cap, std::size_t *out_len) noexcept
Definition se050_commands.hpp:108
Error ParseFreeMemory(const std::uint8_t *rapdu, std::size_t rapdu_len, std::uint16_t *free_bytes) noexcept
Definition se050_commands.hpp:380
Error ParseVerifyResult(const std::uint8_t *rapdu, std::size_t rapdu_len, bool *verified) noexcept
Definition se050_commands.hpp:422
Error BuildReadObject(const ObjectId &object_id, bool has_offset, std::uint16_t offset, bool has_length, std::uint16_t length, std::uint8_t *out, std::size_t out_cap, std::size_t *out_len) noexcept
Definition se050_commands.hpp:254
MemoryType
Definition se050_commands.hpp:57
Error BuildWriteBinary(const ObjectId &object_id, const std::uint8_t *data, std::size_t data_len, bool has_offset, std::uint16_t offset, bool has_file_length, std::uint16_t file_length, std::uint8_t *out, std::size_t out_cap, std::size_t *out_len) noexcept
Definition se050_commands.hpp:177
EcCurve
Definition se050_commands.hpp:63
Error ParseVersionInfo(const std::uint8_t *rapdu, std::size_t rapdu_len, VersionInfo *out) noexcept
Definition se050_commands.hpp:357
std::array< std::uint8_t, 4 > ObjectId
Definition se050_commands.hpp:55
Error BuildGetVersion(std::uint8_t *out, std::size_t out_cap, std::size_t *out_len) noexcept
Definition se050_commands.hpp:87
Error ParseObjectExistsResult(const std::uint8_t *rapdu, std::size_t rapdu_len, bool *exists) noexcept
Definition se050_commands.hpp:442
EcdsaAlgo
Definition se050_commands.hpp:71
Error BuildWriteAesKey(const ObjectId &object_id, const std::uint8_t *key, std::size_t key_len, std::uint8_t *out, std::size_t out_cap, std::size_t *out_len) noexcept
Definition se050_commands.hpp:211
Error BuildGenerateEcKeyPair(const ObjectId &object_id, EcCurve curve, std::uint8_t *out, std::size_t out_cap, std::size_t *out_len) noexcept
Definition se050_commands.hpp:158
Error BuildDeleteSecureObject(const ObjectId &object_id, std::uint8_t *out, std::size_t out_cap, std::size_t *out_len) noexcept
Definition se050_commands.hpp:124
Error BuildCheckObjectExists(const ObjectId &object_id, std::uint8_t *out, std::size_t out_cap, std::size_t *out_len) noexcept
Definition se050_commands.hpp:139
Error BuildEcdsaVerify(const ObjectId &key_id, EcdsaAlgo algo, const std::uint8_t *digest, std::size_t digest_len, const std::uint8_t *signature, std::size_t signature_len, std::uint8_t *out, std::size_t out_cap, std::size_t *out_len) noexcept
Definition se050_commands.hpp:306
Error Unwrap(const std::uint8_t *wrapped, std::size_t wrapped_len, std::uint8_t *out, std::size_t out_cap, std::size_t *out_len, AesBlockFn decrypt, void *ctx) noexcept
RFC 3394 unwrap. wrapped_len must be 8*(n+1) with n >= 2.
Definition se050_rfc3394.hpp:52
constexpr std::size_t kWrapScratchBytes
Minimum wrap workspace, enough for short APDUs (CM4: D2 .se_apdu_scratch, not task stack).
Definition se050_scp03.hpp:40
Definition se050_apdu.hpp:15
Error
Definition se050_types.hpp:14
constexpr std::size_t kMaxApduCommandBytes
Definition se050_types.hpp:40
constexpr std::size_t kMaxApduResponseBytes
Definition se050_types.hpp:42
SE050 applet selection helpers (ISO 7816-4 SELECT by DF name / AID).
Typed SE050 command builders/parsers for a core management/object subset.
RFC 3394 AES Key Wrap / Unwrap with a caller-supplied AES-128 block.
GlobalPlatform SCP03 session over an existing T=1 I²C link.
Low-level session: owns no buffers; forwards transceive to transport.
ISO/IEC 7816-3 T=1 block protocol for NXP SE050 T=1 over I²C (EDC = CRC-16).
Shared types, limits, and error codes for the HF-SE050 driver.
Parsed status words from a response APDU.
Definition se050_apdu.hpp:18
Definition se050_commands.hpp:79