@@ -9,6 +9,7 @@ use log::{debug, error, info, LevelFilter};
99use std:: {
1010 collections:: HashMap ,
1111 env, fs,
12+ ops:: { Deref , DerefMut } ,
1213 path:: { Path , PathBuf } ,
1314 str:: FromStr ,
1415} ;
@@ -21,15 +22,18 @@ use oks::{
2122 self , CsrSpec , DcsrSpec , KeySpec , Transport , CSRSPEC_EXT , DCSRSPEC_EXT ,
2223 ENV_NEW_PASSWORD , ENV_PASSWORD , KEYSPEC_EXT ,
2324 } ,
24- hsm:: { Hsm , LIMIT , VERIFIER_FILE } ,
25+ hsm:: { Hsm , Share , Verifier , LIMIT , THRESHOLD } ,
26+ secret_reader:: { StdioPasswordReader , StdioShareReader } ,
2527 secret_writer:: { PrinterSecretWriter , DEFAULT_PRINT_DEV } ,
2628 util,
2729} ;
2830
29- const PASSWD_PROMPT : & str = "Enter new password: " ;
30- const PASSWD_PROMPT2 : & str = "Enter password again to confirm: " ;
31+ const PASSWD_PROMPT : & str = "Enter YubiHSM Password: " ;
32+ const PASSWD_NEW : & str = "Enter new password: " ;
33+ const PASSWD_NEW_2 : & str = "Enter password again to confirm: " ;
3134
3235const GEN_PASSWD_LENGTH : usize = 16 ;
36+ const VERIFIER_FILE : & str = "verifier.json" ;
3337
3438// when we write out signed certs to the file system this suffix is appended
3539const CERT_SUFFIX : & str = "cert.pem" ;
@@ -163,7 +167,13 @@ enum HsmCommand {
163167 } ,
164168
165169 /// Restore a previously split aes256-ccm-wrap key
166- Restore ,
170+ Restore {
171+ #[ clap( long, env, default_value = "input" ) ]
172+ backups : PathBuf ,
173+
174+ #[ clap( long, env, default_value = "input/verifier.json" ) ]
175+ verifier : PathBuf ,
176+ } ,
167177
168178 /// Get serial number from YubiHSM and dump to console.
169179 SerialNumber ,
@@ -200,7 +210,7 @@ fn get_auth_id(auth_id: Option<Id>, command: &HsmCommand) -> Id {
200210 print_dev : _,
201211 passwd_challenge : _,
202212 }
203- | HsmCommand :: Restore
213+ | HsmCommand :: Restore { .. }
204214 | HsmCommand :: SerialNumber => 1 ,
205215 // otherwise we assume the auth key that we create is
206216 // present: auth_id 2
@@ -211,14 +221,18 @@ fn get_auth_id(auth_id: Option<Id>, command: &HsmCommand) -> Id {
211221
212222/// Get password either from environment, the YubiHSM2 default, or challenge
213223/// the user with a password prompt.
214- fn get_passwd ( auth_id : Option < Id > , command : & HsmCommand ) -> Result < String > {
215- match env:: var ( ENV_PASSWORD ) . ok ( ) {
216- Some ( s) => Ok ( s) ,
224+ fn get_passwd (
225+ auth_id : Option < Id > ,
226+ command : & HsmCommand ,
227+ ) -> Result < Zeroizing < String > > {
228+ let passwd = match env:: var ( ENV_PASSWORD ) . ok ( ) {
229+ Some ( s) => Zeroizing :: new ( s) ,
217230 None => {
231+ let passwd_reader = StdioPasswordReader :: default ( ) ;
218232 if auth_id. is_some ( ) {
219233 // if auth_id was set by the caller but not the password we
220234 // prompt for the password
221- Ok ( rpassword :: prompt_password ( "Enter YubiHSM Password: " ) ? )
235+ passwd_reader . read ( PASSWD_PROMPT ) ?
222236 } else {
223237 match command {
224238 // if password isn't set, auth_id isn't set, and
@@ -229,47 +243,52 @@ fn get_passwd(auth_id: Option<Id>, command: &HsmCommand) -> Result<String> {
229243 print_dev : _,
230244 passwd_challenge : _,
231245 }
232- | HsmCommand :: Restore
233- | HsmCommand :: SerialNumber => Ok ( "password" . to_string ( ) ) ,
246+ | HsmCommand :: Restore { .. }
247+ | HsmCommand :: SerialNumber => {
248+ Zeroizing :: new ( "password" . to_string ( ) )
249+ }
234250 // otherwise prompt the user for the password
235- _ => Ok ( rpassword:: prompt_password (
236- "Enter YubiHSM Password: " ,
237- ) ?) ,
251+ _ => passwd_reader. read ( PASSWD_PROMPT ) ?,
238252 }
239253 }
240254 }
241- }
255+ } ;
256+
257+ Ok ( passwd)
242258}
243259
244260/// get a new password from the environment or by issuing a challenge the user
245261fn get_new_passwd ( hsm : Option < & Hsm > ) -> Result < Zeroizing < String > > {
246- match env:: var ( ENV_NEW_PASSWORD ) . ok ( ) {
262+ let passwd = match env:: var ( ENV_NEW_PASSWORD ) . ok ( ) {
247263 // prefer new password from env above all else
248264 Some ( s) => {
249265 info ! ( "got password from env" ) ;
250- Ok ( Zeroizing :: new ( s) )
266+ Zeroizing :: new ( s)
251267 }
252268 None => match hsm {
253269 // use the HSM otherwise if available
254270 Some ( hsm) => {
255271 info ! ( "Generating random password" ) ;
256- Ok ( Zeroizing :: new ( hsm. rand_string ( GEN_PASSWD_LENGTH ) ?) )
272+ Zeroizing :: new ( hsm. rand_string ( GEN_PASSWD_LENGTH ) ?)
257273 }
258274 // last option: challenge the caller
259- None => loop {
260- let password =
261- Zeroizing :: new ( rpassword:: prompt_password ( PASSWD_PROMPT ) ?) ;
262- let password2 =
263- Zeroizing :: new ( rpassword:: prompt_password ( PASSWD_PROMPT2 ) ?) ;
264- if password != password2 {
265- error ! ( "the passwords entered do not match" ) ;
266- } else {
267- debug ! ( "got the same password twice" ) ;
268- return Ok ( password) ;
275+ None => {
276+ let passwd_reader = StdioPasswordReader :: default ( ) ;
277+ loop {
278+ let password = passwd_reader. read ( PASSWD_NEW ) ?;
279+ let password2 = passwd_reader. read ( PASSWD_NEW_2 ) ?;
280+ if password != password2 {
281+ error ! ( "the passwords entered do not match" ) ;
282+ } else {
283+ debug ! ( "got the same password twice" ) ;
284+ break password;
285+ }
269286 }
270- } ,
287+ }
271288 } ,
272- }
289+ } ;
290+
291+ Ok ( passwd)
273292}
274293
275294/// Perform all operations that make up the ceremony for provisioning an
@@ -746,9 +765,22 @@ fn main() -> Result<()> {
746765 hsm. replace_default_auth ( & passwd_new)
747766 }
748767 HsmCommand :: Generate { key_spec } => hsm. generate ( & key_spec) ,
749- HsmCommand :: Restore => {
750- hsm. restore_wrap ( ) ?;
751- oks:: hsm:: restore ( & hsm. client , & hsm. state_dir ) ?;
768+ HsmCommand :: Restore { backups, verifier } => {
769+ let verifier = fs:: read_to_string ( verifier) ?;
770+ let verifier: Verifier = serde_json:: from_str ( & verifier) ?;
771+ let share_itr = StdioShareReader :: new ( verifier) ;
772+
773+ let mut shares: Zeroizing < Vec < Share > > =
774+ Zeroizing :: new ( Vec :: new ( ) ) ;
775+ for share in share_itr {
776+ shares. deref_mut ( ) . push ( * share?. deref ( ) ) ;
777+ if shares. len ( ) >= THRESHOLD {
778+ break ;
779+ }
780+ }
781+
782+ hsm. restore_wrap ( shares) ?;
783+ oks:: hsm:: restore ( & hsm. client , backups) ?;
752784 info ! ( "Deleting default authentication key" ) ;
753785 oks:: hsm:: delete ( & hsm. client , 1 , Type :: AuthenticationKey )
754786 }
0 commit comments