1
+ use crate :: error:: ApduError as Error ;
2
+ use crate :: utils:: { check_password, check_pin, make_apdu} ;
1
3
use alloc:: vec:: Vec ;
2
4
use der_parser:: der:: der_read_element_header;
3
- use crate :: error:: ApduError as Error ;
4
- use crate :: utils:: { make_apdu, check_pin} ;
5
+
5
6
type Request = Vec < u8 > ;
6
7
type Response = Vec < u8 > ;
7
8
type BinaryData = Vec < u8 > ;
8
9
type Hash < ' a > = & ' a [ u8 ] ;
9
10
type FileId < ' a > = & ' a [ u8 ] ;
10
11
11
- pub trait Apdu {
12
+ #[ derive( Clone , Copy , Debug ) ]
13
+ pub enum KeyType {
14
+ UserAuth ,
15
+ DigitalSign ,
16
+ }
12
17
18
+ pub trait Apdu {
13
19
/// (Required) Error type that transmit() returns when failed to read card
14
20
type TransErr ;
15
21
/// (Required) Implement card communication here.
@@ -20,7 +26,10 @@ pub trait Apdu {
20
26
match self . transmit ( data) {
21
27
Ok ( apdu) => {
22
28
let len = apdu. len ( ) ;
23
- let sw1 = apdu[ len - 2 ] ;
29
+ if len < 2 {
30
+ return Err ( Error :: Fatal ( "No response" ) ) ;
31
+ }
32
+ let sw1 = apdu[ len - 2 ] ; // overflow
24
33
let sw2 = apdu[ len - 1 ] ;
25
34
if ( sw1 == 0x90 || sw1 == 0x91 ) && sw2 == 0x00 {
26
35
return Ok ( apdu[ 0 ..( len - 2 ) ] . to_vec ( ) ) ;
@@ -30,51 +39,70 @@ pub trait Apdu {
30
39
Err ( e) => Err ( Error :: Transmission ( e) ) ,
31
40
}
32
41
}
33
-
42
+ /// SELECT DF
34
43
fn select_df ( & self , dfid : FileId ) -> Result < ( ) , Error < Self :: TransErr > > {
35
44
match self . transmit_checked ( make_apdu ( 0x00 , 0xa4 , ( 0x04 , 0x0c ) , dfid, None ) ) {
36
45
Ok ( _) => Ok ( ( ) ) ,
37
- _ => Err ( Error :: Execution ( "Failed to SELECT DF" ) ) ,
46
+ Err ( e ) => Err ( e . check_err ( "Failed to SELECT DF" ) ) ,
38
47
}
39
48
}
49
+ /// SELECT EF
50
+ ///
51
+ /// Call it with DF selected
40
52
fn select_ef ( & self , efid : FileId ) -> Result < ( ) , Error < Self :: TransErr > > {
41
53
match self . transmit_checked ( make_apdu ( 0x00 , 0xa4 , ( 0x02 , 0x0c ) , efid, None ) ) {
42
54
Ok ( _) => Ok ( ( ) ) ,
43
- _ => Err ( Error :: Execution ( "Failed to SELECT EF" ) ) ,
55
+ Err ( e ) => Err ( e . check_err ( "Failed to SELECT EF" ) ) ,
44
56
}
45
57
}
46
- fn select_jpki_ap ( & self ) -> Result < ( ) , Error < Self :: TransErr > > {
47
- self . select_df ( b"\xD3 \x92 \xf0 \x00 \x26 \x01 \x00 \x00 \x00 \x01 " )
48
- }
49
- fn select_jpki_token ( & self ) -> Result < ( ) , Error < Self :: TransErr > > {
50
- self . select_ef ( b"\x00 \x06 " )
51
- }
52
- fn select_jpki_cert_auth ( & self ) -> Result < ( ) , Error < Self :: TransErr > > {
53
- self . select_ef ( b"\x00 \x0a " )
54
- }
55
58
56
- fn select_jpki_auth_pin ( & self ) -> Result < ( ) , Error < Self :: TransErr > > {
57
- self . select_ef ( b"\x00 \x18 " )
58
- }
59
- fn select_jpki_auth_key ( & self ) -> Result < ( ) , Error < Self :: TransErr > > {
60
- self . select_ef ( b"\x00 \x17 " )
61
- }
59
+ /// GET CHALLENGE
62
60
fn get_challenge ( & self , size : u8 ) -> Result < Response , Error < Self :: TransErr > > {
63
61
match self . transmit_checked ( make_apdu ( 0x00 , 0x84 , ( 0 , 0 ) , & [ ] , Some ( size) ) ) {
64
62
Ok ( s) => Ok ( s) ,
65
- _ => Err ( Error :: Execution ( "GET CHALLENGE failed" ) ) ,
63
+ Err ( e ) => Err ( e . check_err ( "GET CHALLENGE failed" ) ) ,
66
64
}
67
65
}
68
- fn verify_pin ( & self , pin : & str ) -> Result < ( ) , Error < Self :: TransErr > > {
69
- if !check_pin ( pin) {
70
- return Err ( Error :: Execution ( "PIN is invalid" ) )
71
- }
66
+
67
+ /// VERIFY PIN
68
+ ///
69
+ /// Call it with PIN EF selected
70
+ fn verify_pin ( & self , pin : & str , key_type : KeyType ) -> Result < ( ) , Error < Self :: TransErr > > {
71
+ match key_type {
72
+ KeyType :: UserAuth => {
73
+ if !check_pin ( pin) {
74
+ return Err ( Error :: Execution ( "PIN is invalid" ) ) ;
75
+ }
76
+ }
77
+ KeyType :: DigitalSign => {
78
+ if !check_password ( pin) {
79
+ return Err ( Error :: Execution ( "PIN is invalid" ) ) ;
80
+ }
81
+ }
82
+ } ;
83
+
72
84
match self . transmit_checked ( make_apdu ( 0x00 , 0x20 , ( 0x00 , 0x80 ) , pin. as_bytes ( ) , None ) ) {
73
85
Ok ( _) => Ok ( ( ) ) ,
74
- _ => Err ( Error :: Execution ( "VERIFY PIN failed" ) ) ,
86
+ Err ( e) => Err ( e. pin_err ( ) ) ,
87
+ }
88
+ }
89
+
90
+ /// VERIFY PIN without PIN
91
+ ///
92
+ /// check PIN retry counter
93
+ fn lookup_pin ( & self ) -> Result < u8 , Error < Self :: TransErr > > {
94
+ if let Err ( e) = self . transmit_checked ( make_apdu ( 0x00 , 0x20 , ( 0x00 , 0x80 ) , & [ ] , None ) ) {
95
+ if let Error :: PinIncorrect ( remaining) = e. pin_err ( ) {
96
+ return Ok ( remaining) ;
97
+ }
75
98
}
99
+ return Err ( Error :: Fatal ( "Unexpected Error" ) ) ;
76
100
}
77
- fn compute_sig ( & self , hash_pkcs1 : Hash ) -> Result < Response , Error < Self :: TransErr > > {
101
+
102
+ /// COMPUTE DIGITAL SIGNATURE
103
+ ///
104
+ /// Call it with Private Key EF selected
105
+ fn compute_digital_signature ( & self , hash_pkcs1 : Hash ) -> Result < Response , Error < Self :: TransErr > > {
78
106
match self . transmit_checked ( make_apdu (
79
107
0x80 ,
80
108
0x2a ,
@@ -84,19 +112,13 @@ pub trait Apdu {
84
112
) ) {
85
113
// zero, the value of Le probably means 256. it overflowed.
86
114
Ok ( sig) => Ok ( sig) ,
87
- _ => Err ( Error :: Execution ( "COMPUTE DIGITAL SIGNATURE failed" ) ) ,
115
+ Err ( e ) => Err ( e . check_err ( "COMPUTE DIGITAL SIGNATURE failed" ) ) ,
88
116
}
89
117
}
90
-
91
- fn read_binary ( & self ) -> Result < BinaryData , Error < Self :: TransErr > > {
92
- let header = match self . transmit_checked ( make_apdu ( 0x00 , 0xb0 , ( 0u8 , 0u8 ) , & [ ] , Some ( 7u8 ) ) ) {
93
- Ok ( s) => s,
94
- _ => return Err ( Error :: Execution ( "READ BINARY failed" ) ) ,
95
- } ;
96
-
97
- let parsed = der_read_element_header ( & header[ ..] ) . unwrap ( ) ;
98
- let length = parsed. 1 . len as usize + header. len ( ) - parsed. 0 . len ( ) ;
99
-
118
+ /// READ BINARY
119
+ ///
120
+ /// Call it with readable object selected
121
+ fn read_binary ( & self , length : usize ) -> Result < BinaryData , Error < Self :: TransErr > > {
100
122
let mut data: Vec < u8 > = Vec :: with_capacity ( length) ;
101
123
loop {
102
124
let current_size = data. len ( ) ;
@@ -115,10 +137,89 @@ pub trait Apdu {
115
137
return Ok ( data) ;
116
138
}
117
139
}
118
- _ => return Err ( Error :: Execution ( "READ BINARY failed" ) ) ,
140
+ Err ( e ) => return Err ( e . check_err ( "READ BINARY failed" ) ) ,
119
141
}
120
142
}
121
143
}
122
- }
144
+
145
+ /// Read binary as X.509 Certificate
146
+ fn read_cert ( & self ) -> Result < BinaryData , Error < Self :: TransErr > > {
147
+ let header = self . read_binary ( 8 ) ?;
148
+
149
+ let parsed = der_read_element_header ( & header[ ..] )
150
+ . map_err ( |_| Error :: Execution ( "Failed to parse Certificate header" ) ) ?;
151
+ let length = parsed. 1 . len as usize + header. len ( ) - parsed. 0 . len ( ) ;
152
+
153
+ return self . read_binary ( length) ;
154
+ }
155
+
156
+ /// Selects JPKI AP DF
157
+ fn select_jpki_ap ( & self ) -> Result < ( ) , Error < Self :: TransErr > > {
158
+ self . select_df ( b"\xD3 \x92 \xf0 \x00 \x26 \x01 \x00 \x00 \x00 \x01 " )
159
+ }
160
+
161
+ /// Selects JPKI Token EF
162
+ fn select_jpki_token ( & self ) -> Result < ( ) , Error < Self :: TransErr > > {
163
+ self . select_ef ( b"\x00 \x06 " )
164
+ }
123
165
166
+ /// Selects JPKI Certificate EF
167
+ fn select_jpki_cert ( & self , key_type : KeyType ) -> Result < ( ) , Error < Self :: TransErr > > {
168
+ match key_type {
169
+ KeyType :: UserAuth => self . select_ef ( b"\x00 \x0a " ) ,
170
+ KeyType :: DigitalSign => self . select_ef ( b"\x00 \x01 " ) ,
171
+ }
172
+ }
124
173
174
+ /// Selects JPKI PIN EF
175
+ fn select_jpki_pin ( & self , key_type : KeyType ) -> Result < ( ) , Error < Self :: TransErr > > {
176
+ match key_type {
177
+ KeyType :: UserAuth => self . select_ef ( b"\x00 \x18 " ) ,
178
+ KeyType :: DigitalSign => self . select_ef ( b"\x00 \x1B " ) ,
179
+ }
180
+ }
181
+
182
+ /// Selects JPKI Private Key EF
183
+ fn select_jpki_key ( & self , key_type : KeyType ) -> Result < ( ) , Error < Self :: TransErr > > {
184
+ match key_type {
185
+ KeyType :: UserAuth => self . select_ef ( b"\x00 \x17 " ) ,
186
+ _ => unimplemented ! ( ) ,
187
+ }
188
+ }
189
+
190
+ /// Checks if it is mynumber card
191
+ fn is_mynumber_card ( & self ) -> Result < bool , Error < Self :: TransErr > > {
192
+ self . select_jpki_ap ( ) ?;
193
+ self . select_jpki_token ( ) ?;
194
+ let jpki_token = self . read_binary ( 32 ) ?;
195
+ Ok ( & jpki_token[ ..] == b"JPKIAPICCTOKEN2 " )
196
+ }
197
+
198
+ /// Gets Certificate
199
+ fn get_cert ( & self , key_type : KeyType ) -> Result < BinaryData , Error < Self :: TransErr > > {
200
+ self . select_jpki_ap ( ) ?;
201
+ self . select_jpki_key ( key_type) ?;
202
+ self . select_jpki_cert ( key_type) ?;
203
+
204
+ let cert = self . read_cert ( ) ?;
205
+ Ok ( cert)
206
+ }
207
+
208
+ /// Computes signature
209
+ fn compute_sig ( & self , pin : & str , hash : Hash , key_type : KeyType ) -> Result < Response , Error < Self :: TransErr > > {
210
+ self . select_jpki_ap ( ) ?;
211
+ self . select_jpki_pin ( key_type) ?;
212
+ self . verify_pin ( pin, key_type) ?;
213
+ self . select_jpki_key ( key_type) ?;
214
+ let sig = self . compute_digital_signature ( hash) ?;
215
+ Ok ( sig)
216
+ }
217
+
218
+ /// Gets PIN retry counter
219
+ fn get_retry_counter ( & self , key_type : KeyType ) -> Result < u8 , Error < Self :: TransErr > > {
220
+ self . select_jpki_ap ( ) ?;
221
+ self . select_jpki_pin ( key_type) ?;
222
+ let count = self . lookup_pin ( ) ?;
223
+ Ok ( count)
224
+ }
225
+ }
0 commit comments