From e08f97d604d2b5fd98a798b50401662b16567e39 Mon Sep 17 00:00:00 2001 From: swrup Date: Sat, 24 Jan 2026 06:12:52 +0100 Subject: [PATCH] --- data/secmod/kudo_1 | Bin 0 -> 1176 bytes data/secmod/kudo_2 | Bin 0 -> 1176 bytes data/secmod/sk_0 | 1 + data/secmod/sm_key | Bin 0 -> 32 bytes src/data_file.ml | 15 +++++---- src/secmod.ml | 74 ++++++++++++++++++++++++++------------------- 6 files changed, 53 insertions(+), 37 deletions(-) create mode 100644 data/secmod/kudo_1 create mode 100644 data/secmod/kudo_2 create mode 100644 data/secmod/sk_0 create mode 100644 data/secmod/sm_key diff --git a/data/secmod/kudo_1 b/data/secmod/kudo_1 new file mode 100644 index 0000000000000000000000000000000000000000..5b5889f9cf2073356d210b4e45c052719abf7707 GIT binary patch literal 1176 zcmZSJU}RuqU}%6t1_lNOMg~UvUCTPulQLw|E`L{HJyXMbZyQ(Svs`V9myBv^ff2Lr zwJ^W6-YeImv9rCtBxHTVbnbPB=CthRt$wa3UmHAooAWW>y^&v*uKLfgxNUj2@4dSF z8jU3%4wRo=%e}35^_6LF%wn9?O8MqCEy`T5TD&Oee13%CYIWJ_G?~j`tk*rQo|G|;gTC+nZ1J^X3m(1S2X8EEgr+%C^wVSl6@wfd4o-MONSF#73|5hda zbgkIEtRJqXj)5;9YW{S3)$yB+ZMQKL2q)Q?_n!dvjr_yW+J(MJ#|$Fb*8p|kTsCGFaL@C@!ZUfQXAqA z&%b*9WlM9a*>vylRd4ow`R;MmUGd8qy@__#HHQM8J>S0ImRdx@;@BfQuIhSd&gIo}clq*%iJhN*aVFoigsJsH*H;*FYl%i1 zRA>DSTK`3+A!$}a#C&Nv)9g8)Mc9@0eR-ZEx98-knu_Gzal6xtub+-=+vR)fzTxB- z^=__3nf2G%L)vziPk6uock;n%jiayo+g4eAJRPh)XKO6(Jk*UtMrXEVcWMYFcq5KUhzp|Zl07v-KhYhhRl+<%8ssu zM$60C)VFwE)NxC)xb}ou#PLET>olcpTFaUaI6VGz#(Unxbr0_z3D|GLks&kV!Lmt= zeCtl_Jbhnc#m>DKRIl3ciyw`3S{VEJ&NC*C)4u&1S1f&cxXg+rME2q0fJp_)!Lt?5 zs-=BfQ^Fj+)@GOBi}Iwh1BcROeLqO-T_BfSzI)xv*ILZaPUd7qS{Od<&}hzb-eIDW zzWjV;mD!hFrziYk)tsw#VDF(fWs8s9YfMx5ZW*`nsa(Q?WryaNIW7AeU%!c8wleD9 zIqR!4j31tMboh6&R_A6nV_MXc!j~*sMa8MDTr->}x?E4+IjOj}J2p2=e#YyK#`Ekx z&g@NPv^>{(_MT+>{iWH(whWiQ-FE-F>+Nbzj-H8A<6e~?c;}RUPcpT8Va4|8&Hw%# sxFPKz@V6wfU3>nQOPPOJRQxUd6Hggl)%sr>e)`Rq)nXIWABLv^0Qa0kjQ{`u literal 0 HcmV?d00001 diff --git a/data/secmod/kudo_2 b/data/secmod/kudo_2 new file mode 100644 index 0000000000000000000000000000000000000000..91412daa6e03f8897583f1b12f8b242c043120c1 GIT binary patch literal 1176 zcmZSJU}RuqU}%6t1_lNOMg~Sb=VekY>U>=e3}>tl@HbW`%G#YgypTC7`zB9xvZ55j z+>El$b1`4fSqUCU`N(J%E*$9aEUvuy&ca(BO;?ZXNq;LkZOU@hRW~=78nX+&_{?O# z`p`CS#!EL&?aDeJ)}TD)`nokyZW}@;-CyYu^xpj7tr;5`<6O`6m`FChPGJ6;B~Hxu4jAb=~&}DPp(P2a6)d^ zF@ZA@Z~er}SLzDSo2(wB7+>^Vc;9i)B{v*a3U0r5qGr}I^~r0eY+B{6uItfd+qwRq zp8QGif6C81Ixo1syvdMId|P*=eDa%Uzqkt#BKy9~j4v!rQ(fy+7k=k3{}heYzIH!; z&)Kl;o}jyu)7uXV>-cknQ@u7#<>!=ro+vG$$Nbh?^_NAP5u8$msL^PaBPX!{eHeQ}4s$-(X`B5%c}+FiJjJguVf z!<=vX-f;gtahKu71uv0{CGNKIcI@Z!7=p9rX*JktB+epCB~Bu$Z&+dD`RsxaK+-+-eYUqP2K7)fAZbex9!1J)sC6V%2}Uv zMEHGPp2E*AE~oLRHer&jd|k|Dr5^Q$Tl1f;+01Fz@a+0-!

B>#ZmMj;&Qbak-NiMw^3}7T&!6&EmwLxSKA#t*^{i z8vp)Y^<+2mL+-!x<@bGAJ-?Pg=tFCw-g1YABNtg#yH2Q&-Nz^@91(Q-^6}?q3{;gq z-uk<567xl8hB)TV%mW^*2j@()G}~#|QSs=XI#0w7p_Kf2?Y;*K8j|i6AJ6T!E&E?H zYlUOUv~PE=pUa^W?9KKMSf5m#aCYzTeO$`;U;Dje^yO*B>4ux;iL6&u z&D|)u!0)t?w#fg@FP81P%yax}=ReEY$BqR358uam^3~Y~hD(*|7cooC*2^@!H$VC5 zndwDJOorRGnU`F3zp>zKdPvf%(nD_(RBQc`)1Pzf3wmB#lQGBpo@lYsjHwGRL>F6` zy;-$@rJMhT{$hjB2kKmTa!)sM+I;@-ao4rA6_=TB2>F#bGJAN$IG5vwhO2>XeJ7Ti8DapjuYdn;Y%CZ1!uztntDK6%e{_~lbCd-D8;?6+ literal 0 HcmV?d00001 diff --git a/data/secmod/sk_0 b/data/secmod/sk_0 new file mode 100644 index 00000000..4a7e9973 --- /dev/null +++ b/data/secmod/sk_0 @@ -0,0 +1 @@ +ӝ*0O fS竛ስRa \ No newline at end of file diff --git a/data/secmod/sm_key b/data/secmod/sm_key new file mode 100644 index 0000000000000000000000000000000000000000..c0de84c6d42cdf78ae95e63c6c3ab42ecab6c8cf GIT binary patch literal 32 ocmXR;V(0qeFMj=m-SZjSswQVQd5X#2I5{;oy+>?WSRcby0P%VbqyPW_ literal 0 HcmV?d00001 diff --git a/src/data_file.ml b/src/data_file.ml index 44b98908..9fa34674 100644 --- a/src/data_file.ml +++ b/src/data_file.ml @@ -3,15 +3,18 @@ open Syntax open Crypto let read fname = - let* b = File.exists fname in + let* b = File.exists fname |> Syntax.unwrap_err_msg in match b with | false -> Ok None | true -> - let+ content = File.read fname in + let+ content = File.read fname |> Syntax.unwrap_err_msg in Some content -let write_eddsa fname priv = EddsaPrivateKey.to_octets priv |> File.write fname -let write_rsa fname priv = RsaPrivateKey.to_octets priv |> File.write fname +let write_eddsa fname priv = + EddsaPrivateKey.to_octets priv |> File.write fname |> Syntax.unwrap_err_msg + +let write_rsa fname priv = + RsaPrivateKey.to_octets priv |> File.write fname |> Syntax.unwrap_err_msg let read_eddsa fname = let* opt = read fname in @@ -19,7 +22,7 @@ let read_eddsa fname = | None -> Ok None | Some data -> ( EddsaPrivateKey.of_octets data |> function - | Error err -> Error (`Msg err) + | Error e -> Error e | Ok v -> Ok (Some v)) let read_rsa fname = @@ -28,5 +31,5 @@ let read_rsa fname = | None -> Ok None | Some data -> ( RsaPrivateKey.of_octets data |> function - | Error e -> Error (`Msg e) + | Error e -> Error e | Ok v -> Ok (Some v)) diff --git a/src/secmod.ml b/src/secmod.ml index d56a1c98..8ee41fdc 100644 --- a/src/secmod.ml +++ b/src/secmod.ml @@ -70,14 +70,14 @@ module Make (Conn : Pg.CONN) = struct dn_section_name_ht: (denomination_hash, string) Hashtbl.t; } - let dir = Fpath.(v "data" / "secmod ") + let dir = Fpath.(v "data" / "secmod") let db_lookup_signkey_data conn fname priv = let pub = EddsaPrivateKey.pub_of_priv priv in - let* opt = Pg.find_signkey conn pub in + let* opt = Pg.find_signkey conn pub |> unwrap_err_caqti in match opt with | None -> - Fmt.error_msg + Fmt.error "load_signkey error: no associated data found in database for \ signkey `%s`." (Fpath.to_string fname) @@ -86,10 +86,10 @@ module Make (Conn : Pg.CONN) = struct let db_lookup_denom_data conn ~section_name priv = let pub = RsaPrivateKey.pub_of_priv priv in let h_pub = Bin_type.DenominationHash.hash (RsaPublicKey.to_octets pub) in - let* opt = Pg.find_denom conn h_pub in + let* opt = Pg.find_denom conn h_pub |> unwrap_err_caqti in match opt with | None -> - Fmt.error_msg + Fmt.error "load_denom error no associated metadata found in database for \ denomination `%s`." section_name @@ -106,11 +106,11 @@ module Make (Conn : Pg.CONN) = struct let load conn = let error_invalid_state = - Fmt.error_msg "secmod load error: invalid store state." + Fmt.error "secmod load error: invalid store state." in let* sm_key_priv = Data_file.read_eddsa Fpath.(dir / "sm_key") in let* signkeys = - let l = List.init 1 (fun i -> Fpath.(dir / string_of_int i)) in + let l = List.init 1 (fun i -> Fpath.(dir / Fmt.str "sk_%d" i)) in let* l = list_map (fun fname -> load_signkey conn fname) l in match opt_list l with Error () -> error_invalid_state | Ok opt -> Ok opt in @@ -249,18 +249,49 @@ module Make (Conn : Pg.CONN) = struct in { lock; sm_key_priv; sm_key_pub; sk_ht; dn_ht; dn_section_name_ht } + let store t = + Miou.Mutex.protect t.lock @@ fun () -> + let* () = Data_file.write_eddsa Fpath.(dir / "sm_key") t.sm_key_priv in + let* () = + Hashtbl.to_seq_values t.sk_ht + |> List.of_seq + |> List.mapi (fun i (key : signkey) -> + let fname = Fpath.(dir / Fmt.str "sk_%d" i) in + (fname, key.priv)) + |> list_iter (fun (fname, key) -> Data_file.write_eddsa fname key) + in + let* () = + let* l = + Hashtbl.to_seq_values t.dn_ht + |> List.of_seq + |> Syntax.list_map (fun (key : denom) -> + let+ section_name = + match Hashtbl.find_opt t.dn_section_name_ht key.dn_data.h_pub with + | None -> Error "invalid state, section_name not found" + | Some s -> Ok s + in + let fname = Fpath.(dir / section_name) in + (fname, key.priv)) + in + list_iter (fun (fname, key) -> Data_file.write_rsa fname key) l + in + Ok () + let t = match load (module Conn) with | Ok None -> let t = make_new () in + let () = + match store t with + | Error e -> Fmt.failwith "secmod storage failure: %s." e + | Ok () -> () + in Logs.info (fun m -> m "secmod initialized with fresh keys"); t - | Ok (Some v) -> + | Ok (Some t) -> Logs.info (fun m -> m "secmod initialized from storage"); - v - | Error _ -> - (* TODO error: pretty print *) - Fmt.failwith "secmod init failure." + t + | Error e -> Fmt.failwith "secmod init failure: %s." e (* note: don't expose a signing function if we want a real "security module" one day *) let sign_with_sm_key s = EddsaSignature.sign ~key:t.sm_key_priv s @@ -369,23 +400,4 @@ module Make (Conn : Pg.CONN) = struct let denom = { denom with dn_data } in Hashtbl.replace t.dn_ht h_denom_pub denom; Ok () - - (* TODO *) - let _store t = - let* () = Data_file.write_eddsa Fpath.(dir / "sm_key") t.sm_key_priv in - let* () = - get_signkeys () - |> List.mapi (fun i (key : signkey) -> - let fname = Fpath.(dir / string_of_int i) in - (fname, key.priv)) - |> list_iter (fun (fname, key) -> Data_file.write_eddsa fname key) - in - let* () = - get_denoms () - |> List.mapi (fun i (key : denom) -> - let fname = Fpath.(dir / string_of_int i) in - (fname, key.priv)) - |> list_iter (fun (fname, key) -> Data_file.write_rsa fname key) - in - Ok () end