@@ -32,15 +32,16 @@ pub use ledger_zondax_generic::LedgerAppError;
32
32
mod params;
33
33
use params:: SALT_LEN ;
34
34
pub use params:: {
35
- InstructionCode , ADDRESS_LEN , CLA , ED25519_PUBKEY_LEN , PK_LEN_PLUS_TAG , SIG_LEN_PLUS_TAG ,
35
+ InstructionCode , ADDRESS_LEN , CLA , ED25519_PUBKEY_LEN , KEY_LENGTH , PK_LEN_PLUS_TAG , SIG_LEN_PLUS_TAG ,
36
36
} ;
37
- use utils:: { ResponseAddress , ResponseSignature } ;
37
+ use utils:: { P1Values , ResponseAddress , ResponseSignature } ;
38
38
39
39
use std:: convert:: TryInto ;
40
40
use std:: str;
41
41
42
42
mod utils;
43
43
pub use utils:: BIP44Path ;
44
+ pub use utils:: { KeyResponse , NamadaKeys } ;
44
45
45
46
/// Ledger App Error
46
47
#[ derive( Debug , thiserror:: Error ) ]
@@ -137,11 +138,11 @@ where
137
138
let ( _public_key, rest) = rest. split_at ( ( * public_key_len) . into ( ) ) ;
138
139
let ( address_len, rest) = rest. split_first ( ) . expect ( "response too short" ) ;
139
140
let ( address_bytes, rest) = rest. split_at ( ( * address_len) . into ( ) ) ;
140
- if rest. len ( ) > 0 {
141
+ if ! rest. is_empty ( ) {
141
142
panic ! ( "response too long" ) ;
142
143
}
143
144
144
- let address_str = str:: from_utf8 ( & address_bytes)
145
+ let address_str = str:: from_utf8 ( address_bytes)
145
146
. map_err ( |_| LedgerAppError :: Utf8 ) ?
146
147
. to_owned ( ) ;
147
148
@@ -152,6 +153,91 @@ where
152
153
} )
153
154
}
154
155
156
+ /// Retrieves the public key and address
157
+ pub async fn retrieve_keys (
158
+ & self ,
159
+ path : & BIP44Path ,
160
+ key_type : NamadaKeys ,
161
+ show_in_device : bool ,
162
+ ) -> Result < KeyResponse , NamError < E :: Error > > {
163
+ let serialized_path = path. serialize_path ( ) . unwrap ( ) ;
164
+ let p1: u8 = if show_in_device {
165
+ P1Values :: ShowAddressInDevice
166
+ } else {
167
+ P1Values :: OnlyRetrieve
168
+ } as _ ;
169
+ let command = APDUCommand {
170
+ cla : CLA ,
171
+ ins : InstructionCode :: GetKeys as _ ,
172
+ p1,
173
+ p2 : key_type as _ ,
174
+ data : serialized_path,
175
+ } ;
176
+
177
+ let response = self
178
+ . apdu_transport
179
+ . exchange ( & command)
180
+ . await
181
+ . map_err ( LedgerAppError :: TransportError ) ?;
182
+
183
+ match response. error_code ( ) {
184
+ Ok ( APDUErrorCode :: NoError ) => { }
185
+ Ok ( err) => {
186
+ return Err ( NamError :: Ledger ( LedgerAppError :: AppSpecific (
187
+ err as _ ,
188
+ err. description ( ) ,
189
+ ) ) )
190
+ }
191
+ Err ( err) => {
192
+ return Err ( NamError :: Ledger ( LedgerAppError :: AppSpecific (
193
+ err,
194
+ "[APDU_ERROR] Unknown" . to_string ( ) ,
195
+ ) ) )
196
+ }
197
+ }
198
+
199
+ let response_data = response. data ( ) ;
200
+
201
+ match key_type {
202
+ NamadaKeys :: PublicAddress => {
203
+ let ( public_address, rest) = response_data. split_at ( KEY_LENGTH ) ;
204
+ if !rest. is_empty ( ) {
205
+ panic ! ( "response too long" ) ;
206
+ }
207
+
208
+ Ok ( KeyResponse :: Address {
209
+ public_address : public_address. try_into ( ) . unwrap ( ) ,
210
+ } )
211
+ } ,
212
+ NamadaKeys :: ViewKey => {
213
+ let ( view_key, rest) = response_data. split_at ( 2 * KEY_LENGTH ) ;
214
+ let ( ovk, rest) = rest. split_at ( KEY_LENGTH ) ;
215
+ let ( ivk, rest) = rest. split_at ( KEY_LENGTH ) ;
216
+ if !rest. is_empty ( ) {
217
+ panic ! ( "response too long" ) ;
218
+ }
219
+
220
+ Ok ( KeyResponse :: ViewKey {
221
+ view_key : view_key. try_into ( ) . unwrap ( ) ,
222
+ ovk : ovk. try_into ( ) . unwrap ( ) ,
223
+ ivk : ivk. try_into ( ) . unwrap ( ) ,
224
+ } )
225
+ } ,
226
+ NamadaKeys :: ProofGenerationKey => {
227
+ let ( ak, rest) = response_data. split_at ( KEY_LENGTH ) ;
228
+ let ( nsk, rest) = rest. split_at ( KEY_LENGTH ) ;
229
+ if !rest. is_empty ( ) {
230
+ panic ! ( "response too long" ) ;
231
+ }
232
+
233
+ Ok ( KeyResponse :: ProofGenKey {
234
+ ak : ak. try_into ( ) . unwrap ( ) ,
235
+ nsk : nsk. try_into ( ) . unwrap ( ) ,
236
+ } )
237
+ } ,
238
+ }
239
+ }
240
+
155
241
/// Sign wrapper transaction
156
242
pub async fn sign (
157
243
& self ,
@@ -232,7 +318,7 @@ where
232
318
233
319
hasher. update ( [ 0x01 ] ) ;
234
320
235
- hasher. update ( & [ pubkeys. len ( ) as u8 , 0 , 0 , 0 ] ) ;
321
+ hasher. update ( [ pubkeys. len ( ) as u8 , 0 , 0 , 0 ] ) ;
236
322
for pubkey in pubkeys {
237
323
hasher. update ( pubkey) ;
238
324
}
@@ -260,7 +346,7 @@ where
260
346
) -> bool {
261
347
use ed25519_dalek:: { Signature , VerifyingKey } ;
262
348
263
- if pubkey != & signature. pubkey {
349
+ if pubkey != signature. pubkey {
264
350
return false ;
265
351
}
266
352
0 commit comments