From 73f64e77be49b11a547e57f40c90ab93304ae1e9 Mon Sep 17 00:00:00 2001 From: swrup Date: Tue, 17 Feb 2026 12:40:36 +0100 Subject: [PATCH] ~~~ almost ok --- src/pg_type.ml | 46 ++++-------- src/secmod.ml | 199 +++++++++++++++++++++++++++---------------------- src/secmod.mli | 33 ++++---- 3 files changed, 141 insertions(+), 137 deletions(-) diff --git a/src/pg_type.ml b/src/pg_type.ml index 415bcf2d..4f818585 100644 --- a/src/pg_type.ml +++ b/src/pg_type.ml @@ -51,21 +51,10 @@ let signkey_data = Signkey. { pub; stamp_start; stamp_expire; stamp_end; master_sig; revoked_sig } -> - match master_sig with - | None -> Error "signkey_data master_sig is none" - | Some master_sig -> - Ok (pub, stamp_start, stamp_expire, stamp_end, master_sig, revoked_sig)) + Ok (pub, stamp_start, stamp_expire, stamp_end, master_sig, revoked_sig)) ~decode:(fun (pub, stamp_start, stamp_expire, stamp_end, master_sig, revoked_sig) -> - Ok - { - pub; - stamp_start; - stamp_expire; - stamp_end; - master_sig= Some master_sig; - revoked_sig; - }) + Ok { pub; stamp_start; stamp_expire; stamp_end; master_sig; revoked_sig }) (t6 eddsa_pub time time time master_sig revoked_sig) let denom_data = @@ -91,22 +80,19 @@ let denom_data = revoked_sig; } -> - match master_sig with - | None -> Error "denom_data master_sig is none" - | Some master_sig -> - Ok - ( pub, - value, - stamp_start, - stamp_expire_withdraw, - stamp_expire_deposit, - stamp_expire_legal, - fee_withdraw, - fee_deposit, - fee_refresh, - fee_refund, - age_mask, - (h_pub, master_sig, revoked_sig) )) + Ok + ( pub, + value, + stamp_start, + stamp_expire_withdraw, + stamp_expire_deposit, + stamp_expire_legal, + fee_withdraw, + fee_deposit, + fee_refresh, + fee_refund, + age_mask, + (h_pub, master_sig, revoked_sig) )) ~decode:(fun ( pub, value, @@ -135,7 +121,7 @@ let denom_data = fee_refund; age_mask; h_pub; - master_sig= Some master_sig; + master_sig; revoked_sig; }) (t12 rsa_pub amount time time time time amount amount amount amount int diff --git a/src/secmod.ml b/src/secmod.ml index a7fd2924..ee400d39 100644 --- a/src/secmod.ml +++ b/src/secmod.ml @@ -1,6 +1,7 @@ module type S = sig open Crypto + val sm_pubkey : eddsa_pub val sign_with_sm_key : string -> eddsa_sig val sign_with_signkey : pub:eddsa_pub -> string -> eddsa_sig val verify_with_master_key : eddsa_sig -> msg:string -> (unit, string) result @@ -9,26 +10,20 @@ module type S = sig val verify_with_signkey : pub:eddsa_pub -> eddsa_sig -> msg:string -> (unit, string) result - (* TODO query database instead? *) - val get_sm_key_pub : unit -> eddsa_pub - val get_signkeys_data : unit -> Signkey.t list - val get_denoms_data : unit -> Denomination.t list - val find_signkey_data : eddsa_pub -> Signkey.t option - val find_denomination : denomination_hash -> Denomination.t option - val find_denom_section_name : denomination_hash -> string option + val get_signkeys : unit -> Signkey.t list + val get_denominations : unit -> Denomination.t list + val get_future_signkeys : unit -> Api.FutureSignKey.t list + val get_future_denominations : unit -> Api.FutureDenom.t list + val find_signkey : eddsa_pub -> Signkey.t option + val find_denomination : rsa_pub -> Denomination.t option - (* - management operations - *) - (* TODO - problem of keeping db and secmod state syncronized - do db interaction from secmod? *) - - val add_signkey_master_signatures : - (eddsa_pub * Signatures.ExchangeSigningKeyValidity.t) list -> + val certify_future_signkey : + eddsa_pub -> + Signatures.ExchangeSigningKeyValidity.t -> (unit, string) result - val add_denom_master_signatures : - (denomination_hash * Signatures.DenominationKeyValidity.t) list -> - (unit, string) result + val certify_future_denomination : + rsa_pub -> Signatures.DenominationKeyValidity.t -> (unit, string) result val revoke_signkey : eddsa_pub -> @@ -36,11 +31,11 @@ module type S = sig (unit, string) result val revoke_denomination : - denomination_hash -> + rsa_pub -> Signatures.MasterDenominationKeyRevocation.t -> (unit, string) result - val store : unit -> (unit, string) result + val save : unit -> (unit, string) result end module Make (Conn : Pg.CONN) = struct @@ -52,7 +47,7 @@ module Make (Conn : Pg.CONN) = struct type dn = Denomination.t type future_dn = Api.FutureDenom.t - (* TODO use lock *) + (* TODO use lock! *) type t = { sm_key: eddsa_priv; sm_pubkey: eddsa_pub; @@ -64,6 +59,7 @@ module Make (Conn : Pg.CONN) = struct future_dn_ht: (rsa_pub, future_dn) Hashtbl.t; future_sk_key_ht: (eddsa_pub, eddsa_priv) Hashtbl.t; future_dn_key_ht: (rsa_pub, rsa_priv) Hashtbl.t; + dn_section_name_ht: (rsa_pub, string) Hashtbl.t; } let database_find_sk conn fname pub = @@ -166,6 +162,7 @@ module Make (Conn : Pg.CONN) = struct future_dn_ht= Hashtbl.create 0xff; future_sk_key_ht= Hashtbl.create 0xff; future_dn_key_ht= Hashtbl.create 0xff; + dn_section_name_ht= Hashtbl.create 0xff; } in Ok (Some t) @@ -280,6 +277,7 @@ module Make (Conn : Pg.CONN) = struct future_dn_ht= Hashtbl.create 0xff; future_sk_key_ht= Hashtbl.create 0xff; future_dn_key_ht= Hashtbl.create 0xff; + dn_section_name_ht= Hashtbl.create 0xff; } in make_future_sk t; @@ -297,6 +295,7 @@ module Make (Conn : Pg.CONN) = struct t | Error e -> Fmt.failwith "secmod init failure: %s." e + let sm_pubkey = t.sm_pubkey let sign_with_sm_key s = sign_with_sm_key t s let verify_with_sm_key s ~msg = EddsaSignature.verify ~key:t.sm_pubkey s ~msg @@ -309,12 +308,11 @@ module Make (Conn : Pg.CONN) = struct EddsaSignature.verify ~key:Config.master_public_key let verify_with_signkey ~pub s ~msg = - (* check that the key we are verifying with is one of our own *) + (* check that [pub] is one of our own keys *) match Hashtbl.find_opt t.sk_ht pub with | None -> Fmt.failwith "secmod failure: signkey not found." | Some _priv -> EddsaSignature.verify ~key:pub s ~msg - let sm_pubkey = t.sm_pubkey let get_signkeys () = t.sk_ht |> Hashtbl.to_seq_values |> List.of_seq let get_denominations () = t.dn_ht |> Hashtbl.to_seq_values |> List.of_seq @@ -367,88 +365,113 @@ module Make (Conn : Pg.CONN) = struct let* () = Pg.insert_signkey (module Conn) sk |> unwrap_err_caqti in Ok ()) - let add_signkey_master_signatures l = - Miou.Mutex.protect t.lock @@ fun () -> - list_iter - (fun (pub, master_sig) -> - match Hashtbl.find_opt t.sk_ht pub with - | None -> Error "secmod failure: public key not found." - | Some signkey -> - let sk_data = - { signkey.sk_data with master_sig= Some master_sig } + let certify_future_denomination pub master_sig = + match + ( Hashtbl.find_opt t.future_dn_ht pub, + Hashtbl.find_opt t.future_dn_key_ht pub ) + with + | None, _ | _, None -> Error "secmod failure: future signkey not found." + | Some future_dn, Some priv -> ( + match Hashtbl.find_opt t.dn_ht pub with + | Some _dn -> + Error + "secmod failure: this denomination already has a master signature" + | None -> + let Api.FutureDenom. + { + section_name; + value; + stamp_start; + stamp_expire_withdraw; + stamp_expire_deposit; + stamp_expire_legal; + denom_pub= _; + fee_withdraw; + fee_deposit; + fee_refresh; + fee_refund; + denom_secmod_sig= _; + } = + future_dn in - let signkey = { signkey with sk_data } in - let* () = - Pg.insert_signkey (module Conn) sk_data |> unwrap_err_caqti + (* TODO dn hash + need to compute it from denom_pub *) + let h_pub = + Hash.DenominationHash.hash (RsaPublicKey.to_octets pub) in - Hashtbl.replace t.sk_ht pub signkey; - Ok ()) - l + let dn = + Denomination. + { + pub; + value; + stamp_start; + stamp_expire_withdraw; + stamp_expire_deposit; + stamp_expire_legal; + fee_withdraw; + fee_deposit; + fee_refresh; + fee_refund; + age_mask= 0; + h_pub; + master_sig; + revoked_sig= None; + } + in + Hashtbl.replace t.dn_ht pub dn; + Hashtbl.replace t.dn_key_ht pub priv; + Hashtbl.replace t.dn_section_name_ht pub section_name; + Hashtbl.remove t.future_dn_ht pub; + Hashtbl.remove t.future_dn_key_ht pub; - let add_denom_master_signatures l = - Miou.Mutex.protect t.lock @@ fun () -> - list_iter - (fun (h_denom_pub, master_sig) -> - match Hashtbl.find_opt t.dn_ht h_denom_pub with - | None -> Error "secmod failure: denomination hash not found." - | Some denom -> - let dn_data = { denom.dn_data with master_sig= Some master_sig } in - let denom = { denom with dn_data } in - let* () = - Pg.insert_denom (module Conn) dn_data |> unwrap_err_caqti - in - Hashtbl.replace t.dn_ht h_denom_pub denom; + let* () = Pg.insert_denom (module Conn) dn |> unwrap_err_caqti in Ok ()) - l - let revoke_signkey exchange_pub revoked_sig = - Miou.Mutex.protect t.lock @@ fun () -> - match Hashtbl.find_opt t.sk_ht exchange_pub with - | None -> Error "secmod failure: denomination hash not found." - | Some signkey -> - let sk_data = { signkey.sk_data with revoked_sig= Some revoked_sig } in - let signkey = { signkey with sk_data } in - Hashtbl.replace t.sk_ht exchange_pub signkey; + let revoke_signkey pub revoked_sig = + match Hashtbl.find_opt t.sk_ht pub with + | None -> Error "secmod failure: signkey not found." + | Some sk -> + let sk = { sk with revoked_sig= Some revoked_sig } in + Hashtbl.replace t.sk_ht pub sk; + + (* TODO revoke, apply to database *) Ok () - let revoke_denomination h_denom_pub revoked_sig = - Miou.Mutex.protect t.lock @@ fun () -> - match Hashtbl.find_opt t.dn_ht h_denom_pub with - | None -> Error "secmod failure: denomination hash not found." - | Some denom -> - let dn_data = { denom.dn_data with revoked_sig= Some revoked_sig } in - let denom = { denom with dn_data } in - Hashtbl.replace t.dn_ht h_denom_pub denom; + let revoke_denomination pub revoked_sig = + match Hashtbl.find_opt t.dn_ht pub with + | None -> Error "secmod failure: denomination not found." + | Some dn -> + let dn = { dn with revoked_sig= Some revoked_sig } in + Hashtbl.replace t.dn_ht pub dn; + + (* TODO revoke, apply to database *) Ok () - let store () = - Miou.Mutex.protect t.lock @@ fun () -> + let save () = let* () = - Data_file.write_eddsa Fpath.(Config.secrets_dir / "sk_sm") t.sm_key_priv + let fname = Fpath.(Config.secrets_dir / "sk_sm") in + Data_file.write_eddsa fname t.sm_key in let* () = - Hashtbl.to_seq_values t.sk_ht + Hashtbl.to_seq_values t.sk_key_ht |> List.of_seq - |> List.mapi (fun i (key : signkey) -> + |> List.mapi (fun i priv -> let fname = Fpath.(Config.secrets_dir / Fmt.str "sk_%d" i) in - (fname, key.priv)) - |> list_iter (fun (fname, key) -> Data_file.write_eddsa fname key) + Data_file.write_eddsa fname priv) + |> list_iter Fun.id 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.(Config.secrets_dir / section_name) in - (fname, key.priv)) - in - list_iter (fun (fname, key) -> Data_file.write_rsa fname key) l + Hashtbl.to_seq t.dn_key_ht + |> List.of_seq + |> list_iter (fun (pub, priv) -> + let* section_name = + match Hashtbl.find_opt t.dn_section_name_ht pub with + | None -> Error "invalid state, section_name not found" + | Some s -> Ok s + in + let fname = Fpath.(Config.secrets_dir / section_name) in + Data_file.write_rsa fname priv) in - Logs.info (fun m -> m "stored secmod data to file"); + Logs.info (fun m -> m "saved secmod private keys data"); Ok () end diff --git a/src/secmod.mli b/src/secmod.mli index c1731cc0..6e1a90cb 100644 --- a/src/secmod.mli +++ b/src/secmod.mli @@ -1,6 +1,7 @@ module type S = sig open Crypto + val sm_pubkey : eddsa_pub val sign_with_sm_key : string -> eddsa_sig val sign_with_signkey : pub:eddsa_pub -> string -> eddsa_sig val verify_with_master_key : eddsa_sig -> msg:string -> (unit, string) result @@ -9,26 +10,20 @@ module type S = sig val verify_with_signkey : pub:eddsa_pub -> eddsa_sig -> msg:string -> (unit, string) result - (* TODO query database instead? *) - val get_sm_key_pub : unit -> eddsa_pub - val get_signkeys_data : unit -> Signkey.t list - val get_denoms_data : unit -> Denomination.t list - val find_signkey_data : eddsa_pub -> Signkey.t option - val find_denomination : denomination_hash -> Denomination.t option - val find_denom_section_name : denomination_hash -> string option + val get_signkeys : unit -> Signkey.t list + val get_denominations : unit -> Denomination.t list + val get_future_signkeys : unit -> Api.FutureSignKey.t list + val get_future_denominations : unit -> Api.FutureDenom.t list + val find_signkey : eddsa_pub -> Signkey.t option + val find_denomination : rsa_pub -> Denomination.t option - (* - management operations - *) - (* TODO - problem of keeping db and secmod state syncronized - do db interaction from secmod? *) - - val add_signkey_master_signatures : - (eddsa_pub * Signatures.ExchangeSigningKeyValidity.t) list -> + val certify_future_signkey : + eddsa_pub -> + Signatures.ExchangeSigningKeyValidity.t -> (unit, string) result - val add_denom_master_signatures : - (denomination_hash * Signatures.DenominationKeyValidity.t) list -> - (unit, string) result + val certify_future_denomination : + rsa_pub -> Signatures.DenominationKeyValidity.t -> (unit, string) result val revoke_signkey : eddsa_pub -> @@ -36,11 +31,11 @@ module type S = sig (unit, string) result val revoke_denomination : - denomination_hash -> + rsa_pub -> Signatures.MasterDenominationKeyRevocation.t -> (unit, string) result - val store : unit -> (unit, string) result + val save : unit -> (unit, string) result end module Make (_ : Pg.CONN) : S