@@ -18,7 +18,60 @@ pub mod ed25519;
18
18
use alloc:: vec:: Vec ;
19
19
20
20
use crate :: bip32;
21
- use bitbox02:: keystore;
21
+ use bitbox02:: { keystore, memory, securechip} ;
22
+
23
+ #[ derive( Debug ) ]
24
+ pub enum Error {
25
+ AlreadyInitialized ,
26
+ Memory ,
27
+ SeedSize ,
28
+ SecureChip ,
29
+ IncorrectPassword ,
30
+ }
31
+
32
+ fn validate_seed_length ( len : usize ) -> Result < ( ) , Error > {
33
+ match len {
34
+ 16 | 24 | 32 => Ok ( ( ) ) ,
35
+ _ => Err ( Error :: SeedSize ) ,
36
+ }
37
+ }
38
+
39
+ fn get_and_decrypt_seed ( password : & str ) -> Result < zeroize:: Zeroizing < Vec < u8 > > , Error > {
40
+ let encrypted_seed_and_hmac =
41
+ memory:: get_encrypted_seed_and_hmac ( ) . map_err ( |_| Error :: Memory ) ?;
42
+
43
+ // TODO check actual SC result
44
+ let secret: zeroize:: Zeroizing < Vec < u8 > > =
45
+ securechip:: stretch_password ( password) . map_err ( |_| Error :: SecureChip ) ?;
46
+ let seed = bitbox_aes:: decrypt_with_hmac ( & secret, & encrypted_seed_and_hmac)
47
+ . map_err ( |_| Error :: IncorrectPassword ) ?;
48
+ validate_seed_length ( seed. len ( ) ) ?;
49
+ Ok ( seed)
50
+ }
51
+
52
+ pub fn encrypt_and_store_seed ( seed : & [ u8 ] , password : & str ) -> Result < ( ) , Error > {
53
+ if memory:: is_initialized ( ) {
54
+ return Err ( Error :: AlreadyInitialized ) ;
55
+ }
56
+ keystore:: lock ( ) ;
57
+ validate_seed_length ( seed. len ( ) ) ?;
58
+ securechip:: init_new_password ( password) . map_err ( |_| Error :: SecureChip ) ?;
59
+ let secret: zeroize:: Zeroizing < Vec < u8 > > =
60
+ securechip:: stretch_password ( password) . map_err ( |_| Error :: SecureChip ) ?;
61
+ // TODO: set IV randomly using random_32_bytes().
62
+ let iv = & [ 0u8 ; 16 ] ;
63
+ let encrypted_seed: Vec < u8 > =
64
+ bitbox_aes:: encrypt_with_hmac ( iv, secret. as_slice ( ) . try_into ( ) . unwrap ( ) , seed) ;
65
+ memory:: set_encrypted_seed_and_hmac ( & encrypted_seed) . map_err ( |_| Error :: Memory ) ?;
66
+
67
+ // Verify seed.
68
+ if get_and_decrypt_seed ( password) ?. as_slice ( ) != seed {
69
+ // TODO: reset hww
70
+ return Err ( Error :: Memory ) ;
71
+ }
72
+
73
+ Ok ( ( ) )
74
+ }
22
75
23
76
/// Derives an xpub from the keystore seed at the given keypath.
24
77
pub fn get_xpub ( keypath : & [ u32 ] ) -> Result < bip32:: Xpub , ( ) > {
0 commit comments