@@ -19,10 +19,10 @@ use rtnetlink::{
1919 link:: { LinkAttribute , LinkExtentMask } ,
2020 } ,
2121} ;
22+ use serde:: { Deserialize , Serialize } ;
2223use std:: {
2324 collections:: BTreeMap ,
24- ffi:: CStr ,
25- ffi:: CString ,
25+ ffi:: { CStr , CString } ,
2626 fs,
2727 net:: { IpAddr , Ipv4Addr , Ipv6Addr } ,
2828 os:: unix:: fs:: chown,
@@ -40,6 +40,7 @@ const MANGLE_CHAIN_NAME: &CStr = c"mangle";
4040const MANGLE_CHAIN_PRIORITY : i32 = libc:: NF_IP_PRI_MANGLE ;
4141const NAT_CHAIN_NAME : & CStr = c"nat" ;
4242pub const TOR_INSTANCE_LIB_DIR : & str = "/var/lib/tor-instances" ;
43+ const TOR_MASTER_KEY_NAME : & str = "ed25519_master_id_secret_key" ;
4344
4445pub fn collect_specs ( ) -> anyhow:: Result < HwSpecs > {
4546 let sys = System :: new_all ( ) ;
@@ -420,92 +421,68 @@ fn send_and_process(batch: &FinalizedBatch) -> anyhow::Result<()> {
420421 Ok ( ( ) )
421422}
422423
423- // Tor keys are stored in TPM NV storage
424- // Serialization format: <instance-name>\0<key-bytes>\0<instance-name>\0<key-bytes>...
425- fn serialize_relay_keys ( relays : & [ ResolvedRelayRecord ] ) -> anyhow:: Result < Vec < u8 > > {
426- let mut buffer = Vec :: new ( ) ;
424+ #[ derive( Debug , Serialize , Deserialize ) ]
425+ pub struct RelayKeyData {
426+ pub instance_name : String ,
427+ #[ serde( with = "serde_bytes" ) ]
428+ pub ed25519_master_id_secret_key : Vec < u8 > ,
429+ }
430+
431+ pub fn serialize_relay_keys ( relays : & [ ResolvedRelayRecord ] ) -> anyhow:: Result < Vec < u8 > > {
432+ let mut relay_keys = Vec :: new ( ) ;
427433
428434 for relay in relays {
429435 let keys_dir = Path :: new ( & TOR_INSTANCE_LIB_DIR )
430436 . join ( & relay. name )
431437 . join ( "keys" ) ;
432438
433- let key_path = keys_dir. join ( "ed25519_master_id_secret_key" ) ;
439+ let key_path = keys_dir. join ( TOR_MASTER_KEY_NAME ) ;
434440 let key_data = fs:: read ( & key_path)
435441 . map_err ( |e| anyhow:: anyhow!( "Failed to read key for relay {}: {}" , relay. name, e) ) ?;
436442
437- buffer. extend_from_slice ( relay. name . as_bytes ( ) ) ;
438- buffer. push ( 0 ) ;
439-
440- buffer. extend_from_slice ( & key_data) ;
441- buffer. push ( 0 ) ;
443+ relay_keys. push ( RelayKeyData {
444+ instance_name : relay. name . clone ( ) ,
445+ ed25519_master_id_secret_key : key_data,
446+ } ) ;
442447 }
448+ let json = serde_json:: to_string ( & relay_keys)
449+ . map_err ( |e| anyhow:: anyhow!( "Failed to serialize backup to JSON: {}" , e) ) ?;
443450
444- // Pad to NV_SIZE if needed
445- if buffer. len ( ) > NV_SIZE {
446- anyhow:: bail!(
447- "Serialized keys exceed NV_SIZE: {} > {}" ,
448- buffer. len( ) ,
449- NV_SIZE
450- ) ;
451- }
452- buffer. resize ( NV_SIZE , 0 ) ;
451+ let bytes = json. into_bytes ( ) ;
453452
454- Ok ( buffer )
453+ Ok ( bytes )
455454}
456455
457- fn deserialize_relay_keys ( data : & [ u8 ] ) -> anyhow:: Result < Vec < ( String , Vec < u8 > ) > > {
458- let mut result = Vec :: new ( ) ;
459- let mut pos = 0 ;
460-
461- while pos < data. len ( ) {
462- // Skip padding zeros at the end
463- if data[ pos] == 0 {
464- break ;
465- }
466-
467- // Read instance name until null terminator
468- let name_end = data[ pos..]
469- . iter ( )
470- . position ( |& b| b == 0 )
471- . ok_or_else ( || anyhow:: anyhow!( "Missing null terminator for instance name" ) ) ?;
472-
473- let name = String :: from_utf8 ( data[ pos..pos + name_end] . to_vec ( ) )
474- . map_err ( |e| anyhow:: anyhow!( "Invalid UTF-8 in instance name: {}" , e) ) ?;
475- pos += name_end + 1 ; // Skip null terminator
456+ pub fn deserialize_relay_keys ( data : & [ u8 ] ) -> anyhow:: Result < Vec < RelayKeyData > > {
457+ let trimmed = data
458+ . iter ( )
459+ . rposition ( |& b| b != 0 )
460+ . map ( |pos| & data[ ..=pos] )
461+ . unwrap_or ( data) ;
476462
477- if pos >= data. len ( ) {
478- anyhow:: bail!( "Truncated key data for instance {}" , name) ;
479- }
463+ let json_str = std:: str:: from_utf8 ( trimmed)
464+ . map_err ( |e| anyhow:: anyhow!( "Invalid UTF-8 in backup data: {}" , e) ) ?;
480465
481- // Read key data until null terminator
482- let key_end = data[ pos..]
483- . iter ( )
484- . position ( |& b| b == 0 )
485- . ok_or_else ( || anyhow:: anyhow!( "Missing null terminator for key data" ) ) ?;
486-
487- let key_data = data[ pos..pos + key_end] . to_vec ( ) ;
488- pos += key_end + 1 ; // Skip null terminator
489-
490- result. push ( ( name, key_data) ) ;
491- }
466+ let backup: Vec < RelayKeyData > = serde_json:: from_str ( json_str)
467+ . map_err ( |e| anyhow:: anyhow!( "Failed to deserialize backup data: {}" , e) ) ?;
492468
493- Ok ( result )
469+ Ok ( backup )
494470}
495471
496472pub fn backup_tor_keys_to_tpm (
497473 ctx : & mut TpmContext ,
498474 nv_handle : NvIndexHandle ,
475+ nv_size : usize ,
499476 relays : & [ ResolvedRelayRecord ] ,
500477) -> anyhow:: Result < ( ) > {
501478 println ! ( "Backing up Tor relay keys to TPM..." ) ;
502479
503480 let serialized = serialize_relay_keys ( relays) ?;
504- let key_array : [ u8 ; NV_SIZE ] = serialized
505- . try_into ( )
506- . map_err ( |_| anyhow :: anyhow! ( "Failed to convert to array" ) ) ? ;
481+ // Pad data to nv_size
482+ let mut padded_data = serialized ;
483+ padded_data . resize ( nv_size , 0 ) ;
507484
508- nv_write_key ( ctx, nv_handle, & key_array ) ?;
485+ nv_write_data ( ctx, nv_handle, & padded_data ) ?;
509486
510487 println ! ( "Successfully backed up {} relay keys to TPM" , relays. len( ) ) ;
511488 Ok ( ( ) )
@@ -514,18 +491,19 @@ pub fn backup_tor_keys_to_tpm(
514491pub fn restore_tor_keys_from_tpm (
515492 ctx : & mut TpmContext ,
516493 nv_handle : NvIndexHandle ,
494+ _nv_size : usize ,
517495 relays : & [ ResolvedRelayRecord ] ,
518496) -> anyhow:: Result < ( ) > {
519497 println ! ( "Restoring Tor relay keys from TPM" ) ;
520498
521- let data = nv_read_key ( ctx, nv_handle) ?;
499+ let data = nv_read_data ( ctx, nv_handle) ?;
522500 let restored_keys = deserialize_relay_keys ( & data) ?;
523501
524502 for relay in relays {
525503 let key_data = restored_keys
526504 . iter ( )
527- . find ( |( name , _ ) | name == & relay. name )
528- . map ( |( _ , key ) | key )
505+ . find ( |rk| rk . instance_name == relay. name )
506+ . map ( |rk| rk . ed25519_master_id_secret_key . clone ( ) )
529507 . ok_or_else ( || anyhow:: anyhow!( "No backup found for relay {}" , relay. name) ) ?;
530508
531509 let keys_dir = Path :: new ( & TOR_INSTANCE_LIB_DIR )
@@ -534,7 +512,7 @@ pub fn restore_tor_keys_from_tpm(
534512
535513 fs:: create_dir_all ( & keys_dir) ?;
536514
537- let key_path = keys_dir. join ( "ed25519_master_id_secret_key" ) ;
515+ let key_path = keys_dir. join ( TOR_MASTER_KEY_NAME ) ;
538516 fs:: write ( & key_path, key_data)
539517 . map_err ( |e| anyhow:: anyhow!( "Failed to write key for relay {}: {}" , relay. name, e) ) ?;
540518
0 commit comments