From 7fa43282702cbfb6383f13a613f19f7bfce0e97f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Wed, 14 Feb 2024 16:34:50 +0100 Subject: [PATCH] Add tests for migration --- src/migrate.rs | 209 +++++++++++++++++++++++++++++++++- test_fs/fido-trussed-auth.lfs | Bin 0 -> 65536 bytes test_fs/fido-trussed.lfs | Bin 0 -> 65536 bytes 3 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 test_fs/fido-trussed-auth.lfs create mode 100644 test_fs/fido-trussed.lfs diff --git a/src/migrate.rs b/src/migrate.rs index e10dd74..d874f80 100644 --- a/src/migrate.rs +++ b/src/migrate.rs @@ -1,3 +1,7 @@ +//! Helper to migrate from trussed-auth's legacy data layout to the new layout +//! +//! See [migrate]() + use core::iter::once; use littlefs2::{io::Error, object_safe::DynFilesystem, path, path::Path}; @@ -6,7 +10,7 @@ fn migrate_single(fs: &dyn DynFilesystem, path: &Path) -> Result<(), Error> { let path = path.join(path!("backend-auth")); let path_dat = path.join(path!("dat")); let dir_res = fs.read_dir_and_then(&path_dat, &mut |dir| { - for f in dir { + for f in dir.skip(2) { let f = f?; let new_path = path.join(f.file_name()); fs.rename(f.path(), &new_path)?; @@ -31,3 +35,206 @@ pub fn migrate(fs: &dyn DynFilesystem, apps: &[&Path]) -> Result<(), Error> { } Ok(()) } + +#[cfg(test)] +mod tests { + use littlefs2::{fs::Filesystem, ram_storage}; + + use super::*; + + type Result = core::result::Result; + + ram_storage!( + name=NoBackendStorage, + backend=RamDirect, + trait=littlefs2::driver::Storage, + erase_value=0xff, + read_size=16, + write_size=16, + cache_size_ty=littlefs2::consts::U512, + block_size=512, + block_count=128, + lookahead_size_ty=littlefs2::consts::U8, + filename_max_plus_one_ty=littlefs2::consts::U256, + path_max_plus_one_ty=littlefs2::consts::U256, + result=Result, + ); + + enum FsValues { + Dir(&'static [(&'static Path, FsValues)]), + File(usize), + } + + fn test_fs_equality(fs: &dyn DynFilesystem, value: &FsValues, path: &Path) { + match value { + FsValues::Dir(d) => { + let mut expected_iter = d.into_iter(); + fs.read_dir_and_then(path, &mut |dir| { + // skip . and .. + dir.next().unwrap().unwrap(); + dir.next().unwrap().unwrap(); + while let Some((expected_path, expected_values)) = expected_iter.next() { + let entry = dir.next().unwrap().unwrap(); + assert_eq!(entry.file_name(), *expected_path); + test_fs_equality(fs, expected_values, &path.join(expected_path)); + } + assert!(dir.next().is_none()); + Ok(()) + }) + .unwrap(); + } + FsValues::File(f_data_len) => { + fs.open_file_and_then(path, &mut |f| { + let mut buf = [0; 512]; + let data = f.read(&mut buf).unwrap(); + assert_eq!(data, *f_data_len); + Ok(()) + }) + .unwrap(); + } + } + } + + const FIDO_DAT_DIR: FsValues = FsValues::Dir(&[ + (path!("persistent-state.cbor"), FsValues::File(137)), + ( + path!("rk"), + FsValues::Dir(&[( + path!("74a6ea9213c99c2f"), + FsValues::Dir(&[ + (path!("038dfc6165b78be9"), FsValues::File(128)), + (path!("1ecbbfbed8992287"), FsValues::File(122)), + (path!("7c24db95312eac56"), FsValues::File(122)), + (path!("978cba44dfe39871"), FsValues::File(155)), + (path!("ac889a0433749726"), FsValues::File(138)), + ]), + )]), + ), + ]); + + const FIDO_SEC_DIR: FsValues = FsValues::Dir(&[ + ( + path!("069386c3c735689061ac51b8bca9f160"), + FsValues::File(48), + ), + ( + path!("233d86bfc2f196ff7c108cf23a282bd5"), + FsValues::File(36), + ), + ( + path!("2bdef14a0e18d28191162f8c1599d598"), + FsValues::File(36), + ), + ( + path!("3efe6394c20aa8128e27b376e226a58b"), + FsValues::File(36), + ), + ( + path!("4711aa79b4834ef8e551f80e523ba8d2"), + FsValues::File(36), + ), + ( + path!("b43bf8b7897087b7195b8ac53dcb5f11"), + FsValues::File(36), + ), + ]); + + #[test] + fn migration_nothing() { + let mut storage = RamDirect { + buf: *include_bytes!("../test_fs/fido-trussed.lfs"), + }; + + const TEST_VALUES: FsValues = FsValues::Dir(&[ + ( + path!("fido"), + FsValues::Dir(&[(path!("dat"), FIDO_DAT_DIR), (path!("sec"), FIDO_SEC_DIR)]), + ), + ( + path!("trussed"), + FsValues::Dir(&[( + path!("dat"), + FsValues::Dir(&[(path!("rng-state.bin"), FsValues::File(32))]), + )]), + ), + ]); + + Filesystem::mount_and_then(&mut NoBackendStorage::new(&mut storage), |fs| { + test_fs_equality(fs, &TEST_VALUES, path!("/")); + migrate(fs, &[path!("fido")]).unwrap(); + test_fs_equality(fs, &TEST_VALUES, path!("/")); + Ok(()) + }) + .unwrap(); + } + + #[test] + fn migration_full() { + let mut storage = RamDirect { + buf: *include_bytes!("../test_fs/fido-trussed-auth.lfs"), + }; + + const AUTH_SECRETS_DIR: FsValues = FsValues::Dir(&[ + (path!("application_salt"), FsValues::File(16)), + (path!("pin.00"), FsValues::File(118)), + ]); + + const TEST_BEFORE: FsValues = FsValues::Dir(&[ + ( + path!("backend-auth"), + FsValues::Dir(&[( + path!("dat"), + FsValues::Dir(&[(path!("salt"), FsValues::File(16))]), + )]), + ), + ( + path!("fido"), + FsValues::Dir(&[(path!("dat"), FIDO_DAT_DIR), (path!("sec"), FIDO_SEC_DIR)]), + ), + ( + path!("secrets"), + FsValues::Dir(&[( + path!("backend-auth"), + FsValues::Dir(&[(path!("dat"), AUTH_SECRETS_DIR)]), + )]), + ), + ( + path!("trussed"), + FsValues::Dir(&[( + path!("dat"), + FsValues::Dir(&[(path!("rng-state.bin"), FsValues::File(32))]), + )]), + ), + ]); + + const TEST_AFTER: FsValues = FsValues::Dir(&[ + ( + path!("backend-auth"), + FsValues::Dir(&[(path!("salt"), FsValues::File(16))]), + ), + ( + path!("fido"), + FsValues::Dir(&[(path!("dat"), FIDO_DAT_DIR), (path!("sec"), FIDO_SEC_DIR)]), + ), + ( + path!("secrets"), + FsValues::Dir(&[(path!("backend-auth"), AUTH_SECRETS_DIR)]), + ), + ( + path!("trussed"), + FsValues::Dir(&[( + path!("dat"), + FsValues::Dir(&[(path!("rng-state.bin"), FsValues::File(32))]), + )]), + ), + ]); + + Filesystem::mount_and_then(&mut NoBackendStorage::new(&mut storage), |fs| { + test_fs_equality(fs, &TEST_BEFORE, path!("/")); + migrate(fs, &[path!("secrets"), path!("opcard")]).unwrap(); + test_fs_equality(fs, &TEST_AFTER, path!("/")); + Ok(()) + }) + .unwrap(); + } +} diff --git a/test_fs/fido-trussed-auth.lfs b/test_fs/fido-trussed-auth.lfs new file mode 100644 index 0000000000000000000000000000000000000000..f3e16fd975468e2a9f9fd279406aef3b4546d729 GIT binary patch literal 65536 zcmZQ%U|{&b|NnbVW=Tm-YFe@W0|o&G1|~3SU|?YQ55oWd*Z*T?U?`CP!x6?jf&c#~ z7&almL}L6KnK^kPdtN~Phk%0t15Z+7a&~H7if&?QNrr*~1B(#@1A{RG1A_zq4+a?9 zfPq0`*@6jAQ1yQS>1QuaO)g3;DOONm;5TDnU@!-3{lWla8!#~Nn$}FX_g_H%1FM4p z1A9qPX>oCC3P`;z0|SE{Sp5eE7#pPi>FP-z{|m@}0jXz6%S_2vP+;J3WME)$0xSN) z0Am|4FfbHvJ#YirT_c6fFbYOPU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU z1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0q zLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$( zGz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!n zMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1Sk#x(ET6l zKQMp)p6CA$bmxJ9{2vYn0|w@l#1aJs25u7u1_o2`bqRkMU~B^h21f5MpAUhQkK!R7 z0u(2pQ3Hl_2w=_s3=AyAi8&<-3=Av<@_%@iY~c!nCG!ILKQfbl?!NT$p@8?*>lx>{ z>UV7}kpCkgV7ELQre>5LIw3Hm6Yr?wDGmWp{-6JW`8(1bO)U4SZN9-$uz>s@9&GnJ zSuij#SV9{HFgECZr=DGL7BIb|^xzKxiWAVN0Yf?jh|K@6{(uz&1A{d*+r!wP{y?S2 zh1$WN*hgK65duRx@s2v4;t(Jz|1&TMBo-9pWF{w;Waj6^L;D5-1@eCcR#=s0ASbE< z`9BOlb05!Jma}xxd66BTS}VKPfcggu7cqhFjTDgo!QsHbz*dl%r)OZG0Ak7i;Hq!S z4~Ljip#Ou(hJk^hjDdlnK>vqC)E?hs5SdYu79l`!0va`7NQc1U^rF;~qRiCdMaj8| z6&xu!sc9t~DWDu4P;FW1^qH;jtJu`G!|Ct8UrtF$EJ*`XOg!r?%*S)GM(OXh|+fOb@6uWm?0c^ka^dNu0v% ziGH+5$fIVG6#}sGAL*i9mT13%LYQID{vWLUXAf%ofiV9c1{fRE{+r%;ixH+}lpaDM zFr*8wQO8pp0z~D11_s`uymZ~-lEji!y`;=M1qKG*0{K6}<@tXr(9(K={2yaImo-y; zKMM3|^)FZ8NLZTdRmHH^B<)Yn*XOTWTrSCQ7Rdk6aPBY~k@sz*1=oOcDNaD61`O#C zfaQN%1_lN@1_lNL1_qY8k89;&2@_WT7pEqJ=7XIX7#Lij^*@Xas{h}nZQcsjA|U^V z6KVd~oq>VD1F9az2C2VN@eZOMtZ9@Oun-v1iFefT6o&v&`JaJ7A<4uzDa|6u+``h_ zz`{Jq+|bfA$s#e?)Ho$M$u!N-P=SF#0W==;G0)HvIWZT=|1n`;W?+PXuk>Vx-f zL+|_D`3oEs`)_{-*{9(AbE1I!53qeE=7xreiRP9`CKkpfsc9Cerly8z76z%NM#f2r z7AZy$`+f)*e|CI2{CK48B5mJCQLJoPhi}8`%A9HAKjgIb?jpc zMB7pi`Yg`kurgKXT6pX_$UYav?K_b5Vq-HgFfjao|NlM_ z;mrbyM?&GMz`(*{l$4U1W@wUVkZNd=Vq{@xX=rF>lxC4^XliMhVrppt@|y$y4-Qub z1_n1!og=`&aHUWn8sxqL`5!tUdxDN89Eyr~Xu@}%=Y{)$AG@}QRyH0{)aRO2d8|Pz z?3gRae;1~N`oPkQftjVTg;}z3vbnLTnT4f+nPFnGsbP{uQgWhYnxPqJq!FAx>!V(; z0NDe>pme~%#K3&zl3bMZx8#F=&9@%^66bRAkn)~_joYADeE!|chxz|aYvzxg9^=>E<>P$@7aApb+a!GM9OC|f~+ zfy;}5fx#QxJ@~-@V;e9qFtxN>sDqV{5;P8hk(c5}eT*CeON+8oE8|o1l8Y(}z>~Y# zsg(h2liLm-H_e!kxF&GNo|PXH3P5VWvp$)5>7Z$!ZxvF>`FX{u$)zQkWvTH6nR)TK znZ>z@CCM47#S9rBenw((#srC8iD?q^B;HHpNt}|nEOAI;mV}i=lEfs528m}9Z4&1* zOEPm)i%Sx73s4%lG*0uQ#v?+2sPf-{LBQN3(JVF5(#X&_+0ruEC{00uLBfZDfx#DC zdjDa7u|eZUE~2+yB5W9C4dxI)E(=E4BQFGq%Kr=u0tUtwDQU@OhGwQo<`zk*mI@3E z;PpTMZFj@lilB5}p#Mk0kAZ=q0owkPH(7wvPX@RDK{xclNvPNA%C z2ALPgz`#%iHIJXgeI?8;5DhcWFf}~A#lq6k$jHJR=HJcVch3Z=gJF<)K}hEP zzjpH;OpX@x$V>5~K1L3K#SBc0D;O3fWu|18rzRzqmSp7VW#*^kCFZ6g3otHD%1rTy zj0i1_j0h_LOQ$84>Lr$DW~XEp7vv;X`X%P3LWP(Zn7^{9u{JRTDBHH}KlE|h{~Cdw zPgWY*SJ|03zB2iE74FlPy)jek-O`iSXpyEz%_KeqNQr-+sBkyK#PG13lyEml8pupd zEX_#9-_M?jcsGx# zq+SS+692)-@gEhQlaUf03N8xr;K?90GqE%kxkx~hV&a4)h%MGXws#h^Z&}0qS{j)FhlCKuY|(MTO@WMh1eTJS8==G!Z$X!2(Rou;|sk z_tA?_;!@*8G5sFVnOA2(qIaUdRqngoJsV$pfAqlVq)`bvh5(82?`D_?i+{AbKLu0< zFtNho-|k=XltWxAg!oCCih=?IzYzligE0dGg9HB$1{m9bfq}QS z#^uI;0r?-S4h9S?X_+bc3JMH7W(*7r=1|2jwgCeJ!#d&ZH<0ZaWz!}E7)HTp2#kin zXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeD zjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mk zz>o-mrA67PmGP;0$wid~C7Jno@!6@B0c?}o4j(ton2@+8aL1mN9}@~dYRZce3kovx z(m^V|RY)c0=M|?WmzHFfrN$Rz=Edh`7Uw3GBxj@+GiHGJ8HvRi6C`>irb*0`crTGB zaZ2K{#36}U5>^sP5|bnvB%VpMNu19t$;?eHE=kNSV5QCS_EA#_ga8fVpJ6oq2?Y8e zk{&Ga&o+p{WF$FdF#{9h3Wh~VnJL-jsY!{YB^h~onfWPsiMgrB0*s53GE>~5!rcrL z1HqChsfneT*(sUD1v!b8eu=rMU;!pp=C3SjtW697cK?#69O7Cb)Th3=?2+2iZgwV) zuS`Du&!6~Y9V=>zG5maXB!%+e_3L2C|LlV|h=#SxXb}Howf{!re_)as4dS1y_TOmy z4@~@n_W%EX|Np*GQc7x?p-G}as-Z=Sk%gh9p`n>knnkjqsikF#silPi0|N^KGXrbT z(S$=$5f4rH&hxx*Kk#GM7SYPaBZ~T5vnr1@XoVefRbXIYF-}cOH8Zv}Nj5S_OtdgG zvPd;DPck+)OEoewOEk4ef|;fMx1xgOTi>+CB`chz-{v0l5p7F7=(9MB!^%{lYvHl$ z3Jg3fCgz5QiHYWxNhTJ?CaGx_sivleX%+^lrbfm|i54kF3JeSi4)R|(EEpIVEEyOW z3>X+#njZg}2@A~v`7atEcR!Zg{$bX$6Jpk8GnTBcO_*jFpTM~H_Lp3XKe{{b>e$B? z$bV6Iu4bkwApe2Ifq_9G$;3D*%_7O%!qVKp!aT{`(9$%?A~D(2I3+pBG|kWuWN(4| z2Lay`v!BB30?`HXA51{@?cOQAFaJ^BY1a6+mx@CYK7T%C&h0C*Y{?4wDEF4fe2E3} z9~6F{XSM?A8Av=N1}R1zNwW|bEagAPKxTpwY&R+WKOb=aFFY(KCETq5+zZSE^#W5< zOA}GLf(TJ2c36MVU2s+9mS(>nPXmAO1zE4S1nCcc__1qQMZkvr`~B>hMsOqypw|aW z{^uOPFc`^J(;)uI>i><#|G=a|8pJE@wSrE{tHHK|3!u8WTb?L zf}4SP@Md6YW@2e7^0WY&6cZ<`LAb^G$M(*G_U)3EYQ?J1|0k2Juf;`)@SAgVykFlQ1nyJ1Y1^Tr5mn(22EY0<* zV%Tev_NV9T^Vcmdmt;5#gB^zsLt(ty+yP9hQ7A}T!(`GS7@!&UU}%ee|28~N5R}P zOF?QTvq~nRIc=0nLT{*H7}6U)77n{TkBBOw2W2dO;(TW0IP z|Azs_2DJwyvaJt*wFt=n-~_2JPE7{2A8Z*I80^69haU_uHc0(rCdSeB13172m>86a za@0|D3jt=({eJKNzbZ&AD$Xn}NzE&PR{P0G`9%x{EaFAk3JMHdjtmS8P9R4qurO#d zFfeq2^0fXR2ADYLemBYb#_0bA`hR$Jpb84~|43w=ShsC}llZ9hctQYl|KESo;y(-; zy$)#czky|f6*&GSp$b6pU)QMuZpXo#01}fzl6Uu;^aLgcqCxV~Nb(v?=Jg5QO#rkUDcL<^897VXg=F{}>n)jEs#_EX~EzQ!>%##fbERxfV zj1!G4jFM7JA^Rc!2;|!?{0q|yq6_5zfcHc0nBpXwX@92Y#mxOL{vX=9L#pb7_iaP( z``!5q92NU-e=m^#qoCmYbE1I!AMpN512aow3$tY7WOHLvGYd-tGsDDWQ^O>Sq~t`) zG($53n0@t8uUCNVfnkt23``8nS1!p#NqMCl5Kl5#+7!ZmXGOwQz>Z z@jg&n7KRJt|5!MODjoruAt3*S1GN8>i2bk%1@d16mT6392I+(00{Jgs{}S3K3)*kW z64YJ}+iyz5o>>LZe$%I~lzU)yfoRx%Q$l-b!TU|;f2{=RLB^2w-|zcG#4mXNFQIq@ z?f)er?gU7UBM1IJpgqV8il9Bd0t^hcu{J32j_jvVHt`{Vt^B9({IAjafcW4aaFv54 z{uu{6Bu1tKVD&$N@m~RRlSH%BL`x$><77+AWTP|%1qKOc1_lNf&_EFX9|jm3bpC>J z`HJ}?Gc<>uuVHPVQF>&C08#m$fkD8)*diq@+04+)G|Ai|Db-SefkB`^{*S$(4bDp@D&c0mK%ZV6+ukUO@hbfCB@AfO)c!NlKEXsj;C^YGSgf8N|FF0&ym% zERfX~=>L!iWnf^a0-N_kqQKs96|y|cJj2xFq@=W@)D#O#OCuu-bC`LXzwe%jtR7^Z z43c?*o4Qes9ukoM0CrzuvW10ZqJfFAvAKz*xe?TT9|Y=B=UqcJ?}LOg0|P@B*nJ-) z1ZLk&MV5z|XK8McoRnx{l9HBcY-wQ*IzL7L)SiFoaJ39seS!W52@M7YhS^Z_R`bOz zL6)aBdt|2iQD4JCfRz289+45DrI8U~kh4G15=-^a&VYmpF)_e4c`Dns?LYK!+W#7X zo=;X9+E*c)JiQ9{Y0KW2sr7E@NtC=q?X*2=9^nueEbaf%<6j8J6)jZIApXgk4;YPq zTEs44Gieb2WR3rf#y{b>qJ@gV68|WJ=(O5;c#1{3{4BwXRsLw`2U^E0q zLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$( zGz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!n zMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ON rU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(aD)H=F!3`# literal 0 HcmV?d00001