1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//! High-level API for APDU commands and responses.
//!
//! ## Features
//! ### Low-level APDU types
//! [apdu-core](https://docs.rs/apdu-core/) crate declares types for APDU command and response in low-level.
//! It is fully cross-platform since this crate contains only type declarations.
//! ```rust
//! let command = apdu_core::Command::new_with_payload(0x00, 0xA4, 0x12, 0x34, &[0x56, 0x78]);
//! let bytes: Vec<u8> = command.into();
//!
//! assert_eq!(
//! vec![
//! 0x00, 0xA4, 0x12, 0x34, // CLA + INS + P1 + P2 (required),
//! 0x02, // Lc, automatically calculated from Vec,
//! 0x56, 0x78, // ...and the command payload.
//! ],
//! bytes,
//! );
//! ```
//!
//! ### High-level APIs
//! This apdu crate declares some high-level APIs to compose APDU commands or parse their responses easily.
//! It is cross-platform now, but some os-specific features can be added in the future.
//! ```rust
//! let command = apdu::command::select_file(0x12, 0x34, &[0x56, 0x78]);
//! let bytes: Vec<u8> = command.into();
//!
//! assert_eq!(vec![0x00, 0xA4, 0x12, 0x34, 0x02, 0x56, 0x78], bytes);
//! ```
//!
//! Collection of APDU commands are incomplete and still in development.
//! We are welcome for your contribution at any time :)
//!
//! ### Abstraction
//! Among crates that supports communicating using APDU, it can use apdu-core crate for abstraction.
//! For example:
//! ```rust
//! /// You have an command that can be transmitted as APDU:
//! struct DoSomethingCommand {
//! parameters: Vec<String>,
//! }
//!
//! /// Now implement `From<YourType>` for `apdu_core::Command`:
//! impl<'a> From<DoSomethingCommand> for apdu_core::Command<'a> {
//! fn from(cmd: DoSomethingCommand) -> Self {
//! Self::new(0x12, 0x34, 0x56, 0x78)
//! }
//! }
//!
//! /// ... then dependents of your library can be used with other crate that has an APDU implementation:
//! fn handle_apdu_command<'a>(cmd: impl Into<apdu_core::Command<'a>>) {
//! // connect to your card ...
//! // transmit the command ...
//! // ... and wait for the response
//! }
//! ```
//!
//! For advance, this crate also supports abstraction of APDU transmitter (called Handler in apdu_core).
//! `handle_apdu_command` from the above example can be transformed to:
//! ```rust
//! struct NfcReader;
//!
//! impl apdu_core::HandlerInCtx<()> for NfcReader {
//! fn handle_in_ctx(&self, _ctx: (), command: &[u8], response: &mut [u8]) -> apdu_core::Result {
//! // connect to your card ...
//! // transmit the command ...
//! // ... and wait for the response
//! # let len = 0;
//!
//! Ok(len) // return the length of response
//! }
//! }
//! ```
//!
//! Thanks to this abstraction, application developer can choose how the APDU command is transmitted
//! to the card independently to their payload. This enables you to implement your libraries
//! that uses APDU in cross-platform easily!
//!
//! ## Examples
//! [jpki-rs](https://github.com/siketyan/jpki-rs) is implemented using this apdu crate.
//! Take a look for catch example usages for this crate.
pub use apdu_core as core;
/// Procedural macro to derive APDU response. See [apdu-derive](https://docs.rs/apdu-derive/) for details.
pub use Response;
pub use crate;
pub use crateError;