@@ -3,46 +3,17 @@ use nfc1::target_info::TargetInfo;
3
3
use nfc1:: BaudRate :: Baud106 ;
4
4
use nfc1:: Error :: Timeout as TimeoutError ;
5
5
use nfc1:: ModulationType :: Iso14443a ;
6
+ use nfc1:: Property :: EasyFraming ;
6
7
use nfc1:: { Modulation , Property , Timeout } ;
7
8
8
9
use crate :: nfc:: ndef:: { parse_ndef_text_record, NdefMessageParser } ;
9
10
10
- pub type Uid = [ u8 ; 4 ] ;
11
-
12
- #[ derive( Copy , Clone ) ]
13
- struct AuthOption {
14
- key_type : u8 ,
15
- key : [ u8 ; 6 ] ,
16
- }
11
+ pub type Uid = [ u8 ; 7 ] ;
17
12
18
13
pub struct NfcReader < ' a > {
19
14
device : nfc1:: Device < ' a > ,
20
15
}
21
16
22
- const KEY_TYPE_A : u8 = 0x60 ;
23
- const KEY_TYPE_B : u8 = 0x61 ;
24
- const DEFAULT_KEY_A : [ u8 ; 6 ] = [ 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ] ;
25
- const DEFAULT_KEY_B : [ u8 ; 6 ] = [ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ] ;
26
-
27
- const AUTH_OPTIONS : [ AuthOption ; 4 ] = [
28
- AuthOption {
29
- key_type : KEY_TYPE_A ,
30
- key : DEFAULT_KEY_A ,
31
- } ,
32
- AuthOption {
33
- key_type : KEY_TYPE_A ,
34
- key : DEFAULT_KEY_B ,
35
- } ,
36
- AuthOption {
37
- key_type : KEY_TYPE_B ,
38
- key : DEFAULT_KEY_A ,
39
- } ,
40
- AuthOption {
41
- key_type : KEY_TYPE_B ,
42
- key : DEFAULT_KEY_B ,
43
- } ,
44
- ] ;
45
-
46
17
impl < ' a > NfcReader < ' a > {
47
18
pub fn new ( device : nfc1:: Device < ' a > ) -> Self {
48
19
Self { device }
@@ -70,43 +41,33 @@ impl<'a> NfcReader<'a> {
70
41
return None ;
71
42
}
72
43
73
- Some ( info. uid [ 0 ..4 ] . try_into ( ) . unwrap ( ) )
44
+ Some ( info. uid [ 0 ..7 ] . try_into ( ) . unwrap ( ) )
74
45
}
75
46
76
47
pub fn check_for_release ( & mut self ) -> bool {
77
48
self . device . initiator_target_is_present_any ( ) . is_err ( )
78
49
}
79
50
80
- pub fn read_first_plain_text_ndef_record ( & mut self , uid : & Uid ) -> Result < String > {
51
+ pub fn read_first_plain_text_ndef_record ( & mut self ) -> Result < String > {
81
52
let mut ndef_message_parser = NdefMessageParser :: new ( ) ;
82
- let mut maybe_auth_option: Option < AuthOption > = None ;
83
-
84
- ' sector: for sector in 1 ..16 {
85
- match maybe_auth_option {
86
- Some ( auth_option) => {
87
- self . authenticate_block (
88
- sector * 4 + 3 ,
89
- auth_option. key_type ,
90
- & auth_option. key ,
91
- uid,
92
- ) ?;
93
- }
94
- None => {
95
- let auth_option = self . try_authenticate_block ( sector * 4 + 3 , uid) ?;
96
- maybe_auth_option = Some ( auth_option) ;
97
- }
98
- }
99
53
100
- for block in 0 .. 3 {
101
- let block_data = self . read_block ( sector * 4 + block ) ?;
102
- ndef_message_parser . add_data ( & block_data ) ;
54
+ self . check_version ( ) ? ;
55
+ self . device . set_property_bool ( EasyFraming , true ) ?;
56
+ let capabilities = self . read_block ( 3 ) ? ;
103
57
104
- if ndef_message_parser. is_done ( ) {
105
- break ' sector;
106
- }
58
+ let total_bytes = ( capabilities[ 2 ] as u32 ) * 8 ;
59
+ let total_pages = total_bytes / 4 ;
60
+ let total_quads = ( total_pages / 4 ) as u8 ;
61
+
62
+ for quad in 1 ..total_quads + 1 {
63
+ let quad_data = self . read_block ( 4 * quad) ?;
64
+ ndef_message_parser. add_data ( & quad_data) ;
65
+
66
+ if ndef_message_parser. is_done ( ) {
67
+ break ;
107
68
}
108
69
109
- if !ndef_message_parser. has_started ( ) {
70
+ if quad == 2 && !ndef_message_parser. has_started ( ) {
110
71
return Err ( anyhow ! ( "No NDEF message found in first sector" ) ) ;
111
72
}
112
73
}
@@ -119,61 +80,33 @@ impl<'a> NfcReader<'a> {
119
80
record. text ( )
120
81
}
121
82
122
- fn read_block ( & mut self , block_number : u8 ) -> Result < [ u8 ; 16 ] > {
123
- let packet: [ u8 ; 2 ] = [ 0x30 , block_number] ;
124
-
125
- let response = self
83
+ fn check_version ( & mut self ) -> Result < ( ) > {
84
+ self . device . set_property_bool ( EasyFraming , false ) ?;
85
+ let version = self
126
86
. device
127
- . initiator_transceive_bytes ( & packet, 16 , Timeout :: Default ) ?;
128
- Ok ( response[ ..] . try_into ( ) ?)
129
- }
87
+ . initiator_transceive_bytes ( & [ 0x60 ] , 8 , Timeout :: Default ) ?;
130
88
131
- fn try_authenticate_block ( & mut self , block_number : u8 , uid : & [ u8 ; 4 ] ) -> Result < AuthOption > {
132
- for auth_option in AUTH_OPTIONS {
133
- let auth_result =
134
- self . authenticate_block ( block_number, auth_option. key_type , & auth_option. key , uid) ;
135
-
136
- match auth_result {
137
- Ok ( ( ) ) => {
138
- return Ok ( auth_option) ;
139
- }
140
- Err ( _) => {
141
- self . device . initiator_select_passive_target ( & Modulation {
142
- modulation_type : Iso14443a ,
143
- baud_rate : Baud106 ,
144
- } ) ?;
145
- }
146
- }
89
+ if version[ 0 ..6 ] != [ 0x00 , 0x04 , 0x04 , 0x02 , 0x01 , 0x00 ] {
90
+ return Err ( anyhow ! ( "Version mismatch, unsupported tag" ) ) ;
147
91
}
148
92
149
- Err ( anyhow ! ( "No key matched sector" ) )
150
- }
151
-
152
- fn authenticate_block (
153
- & mut self ,
154
- block_number : u8 ,
155
- key_type : u8 ,
156
- key : & [ u8 ; 6 ] ,
157
- uid : & [ u8 ; 4 ] ,
158
- ) -> Result < ( ) > {
159
- let packet: [ u8 ; 12 ] = [
160
- key_type,
161
- block_number,
162
- key[ 0 ] ,
163
- key[ 1 ] ,
164
- key[ 2 ] ,
165
- key[ 3 ] ,
166
- key[ 4 ] ,
167
- key[ 5 ] ,
168
- uid[ 0 ] ,
169
- uid[ 1 ] ,
170
- uid[ 2 ] ,
171
- uid[ 3 ] ,
172
- ] ;
93
+ if ![ 0x0f , 0x11 , 0x13 ] . contains ( & version[ 6 ] ) {
94
+ return Err ( anyhow ! ( "Version mismatch, unsupported subtype of tag" ) ) ;
95
+ }
173
96
174
- self . device
175
- . initiator_transceive_bytes ( & packet, 0 , Timeout :: Default ) ?;
97
+ if version[ 7 ] != 0x03 {
98
+ return Err ( anyhow ! ( "Version mismatch, unsupported protocol" ) ) ;
99
+ }
176
100
177
101
Ok ( ( ) )
178
102
}
103
+
104
+ fn read_block ( & mut self , block_number : u8 ) -> Result < [ u8 ; 16 ] > {
105
+ let packet: [ u8 ; 2 ] = [ 0x30 , block_number] ;
106
+
107
+ let response = self
108
+ . device
109
+ . initiator_transceive_bytes ( & packet, 16 , Timeout :: Default ) ?;
110
+ Ok ( response[ ..] . try_into ( ) ?)
111
+ }
179
112
}
0 commit comments