From fe5751044d87fcf756e6d7460a8f6c034b00a1b2 Mon Sep 17 00:00:00 2001 From: swrup Date: Tue, 17 Feb 2026 11:11:46 +0100 Subject: [PATCH] + more secmod wip --- src/denomination.ml | 2 +- src/secmod.ml | 143 ++++++++++++++++++++++++-------------------- src/signkey.ml | 2 +- 3 files changed, 80 insertions(+), 67 deletions(-) diff --git a/src/denomination.ml b/src/denomination.ml index 7d94367d..25bbe52e 100644 --- a/src/denomination.ml +++ b/src/denomination.ml @@ -13,6 +13,6 @@ type t = { fee_refund: Amount.t; age_mask: int; h_pub: denomination_hash; - master_sig: Signatures.DenominationKeyValidity.t option; + master_sig: Signatures.DenominationKeyValidity.t; revoked_sig: Signatures.MasterDenominationKeyRevocation.t option; } diff --git a/src/secmod.ml b/src/secmod.ml index bcbe3174..a7fd2924 100644 --- a/src/secmod.ml +++ b/src/secmod.ml @@ -171,8 +171,7 @@ module Make (Conn : Pg.CONN) = struct Ok (Some t) | _, _, _ -> error_invalid_state - (* TODO *) - let sign_with_sm_key _ = assert false + let sign_with_sm_key t s = EddsaSignature.sign ~key:t.sm_key s let make_future_sk t = let start = Time.Absolute.of_ptime (Ptime_clock.now ()) in @@ -188,7 +187,7 @@ module Make (Conn : Pg.CONN) = struct let exchange_pub = pub in let anchor_time = stamp_start in let duration = Timestamp.diff stamp_start stamp_expire in - sign_f ~f:sign_with_sm_key { exchange_pub; anchor_time; duration } + sign_f ~f:(sign_with_sm_key t) { exchange_pub; anchor_time; duration } in let future_sk = Api.FutureSignKey. @@ -243,7 +242,7 @@ module Make (Conn : Pg.CONN) = struct let duration_withdraw = Timestamp.diff stamp_start stamp_expire_withdraw in - sign_f ~f:sign_with_sm_key + sign_f ~f:(sign_with_sm_key t) { h_denom_pub; h_section_name; anchor_time; duration_withdraw } in let future_dn = @@ -268,26 +267,24 @@ module Make (Conn : Pg.CONN) = struct () let make_new () = - let lock = Miou.Mutex.create () in - let sm_key_priv, sm_key_pub = Mirage_crypto_ec.Ed25519.generate () in - let sk_ht = - [ make_new_signkey () ] - |> List.map (fun v -> (v.sk_data.pub, v)) - |> List.to_seq - |> Hashtbl.of_seq + let sm_key, sm_pubkey = Mirage_crypto_ec.Ed25519.generate () in + let t = + { + sm_key; + sm_pubkey; + sk_ht= Hashtbl.create 0xff; + dn_ht= Hashtbl.create 0xff; + sk_key_ht= Hashtbl.create 0xff; + dn_key_ht= Hashtbl.create 0xff; + future_sk_ht= Hashtbl.create 0xff; + future_dn_ht= Hashtbl.create 0xff; + future_sk_key_ht= Hashtbl.create 0xff; + future_dn_key_ht= Hashtbl.create 0xff; + } in - let dn_section_name_ht = Hashtbl.create 0xff in - let dn_ht = - Config.Coin.all_coins - |> List.map (fun coin -> - let denom = make_new_denom coin in - Hashtbl.replace dn_section_name_ht denom.dn_data.h_pub - coin.section_name; - (denom.dn_data.h_pub, denom)) - |> List.to_seq - |> Hashtbl.of_seq - in - { lock; sm_key_priv; sm_key_pub; sk_ht; dn_ht; dn_section_name_ht } + make_future_sk t; + List.iter (make_future_dn t) Config.Coin.all_coins; + t let t = match load (module Conn) with @@ -300,59 +297,75 @@ module Make (Conn : Pg.CONN) = struct 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 - let verify_with_sm_key s ~msg = EddsaSignature.verify ~key:t.sm_key_pub s ~msg + 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 - let verify_with_master_key s ~msg = - EddsaSignature.verify ~key:Config.master_public_key s ~msg - - (* TODO - - do something to force `pub` to be one of the valid signkey - how to handle revocation? - raise exn for now *) let sign_with_signkey ~pub s = - Miou.Mutex.protect t.lock @@ fun () -> - match Hashtbl.find_opt t.sk_ht pub with - | None -> Fmt.failwith "secmod failure: public key not found." - | Some signkey -> - let v = EddsaSignature.sign ~key:signkey.priv s in - v + match Hashtbl.find_opt t.sk_key_ht pub with + | None -> Fmt.failwith "secmod failure: signkey not found." + | Some priv -> EddsaSignature.sign ~key:priv s + + let verify_with_master_key = + EddsaSignature.verify ~key:Config.master_public_key let verify_with_signkey ~pub s ~msg = - Miou.Mutex.protect t.lock @@ fun () -> + (* check that the key we are verifying with is one of our own *) match Hashtbl.find_opt t.sk_ht pub with - | None -> Error "secmod failure: public key not found." - | Some signkey -> EddsaSignature.verify ~key:signkey.sk_data.pub s ~msg + | None -> Fmt.failwith "secmod failure: signkey not found." + | Some _priv -> EddsaSignature.verify ~key:pub s ~msg - let get_sm_key_pub () = t.sm_key_pub + 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 - let get_signkeys () = - Miou.Mutex.protect t.lock @@ fun () -> - Hashtbl.to_seq_values t.sk_ht |> List.of_seq + let get_future_signkeys () = + t.future_sk_ht |> Hashtbl.to_seq_values |> List.of_seq - let get_denoms () = - Miou.Mutex.protect t.lock @@ fun () -> - Hashtbl.to_seq_values t.dn_ht |> List.of_seq + let get_future_denominations () = + t.future_dn_ht |> Hashtbl.to_seq_values |> List.of_seq - let find_signkey pub = - Miou.Mutex.protect t.lock @@ fun () -> Hashtbl.find_opt t.sk_ht pub + let find_signkey pub = Hashtbl.find_opt t.sk_ht pub + let find_denomination pub = Hashtbl.find_opt t.dn_ht pub - let find_denom h_denom = - Miou.Mutex.protect t.lock @@ fun () -> Hashtbl.find_opt t.dn_ht h_denom + let certify_future_signkey pub master_sig = + match + ( Hashtbl.find_opt t.future_sk_ht pub, + Hashtbl.find_opt t.future_sk_key_ht pub ) + with + | None, _ | _, None -> Error "secmod failure: future signkey not found." + | Some future_sk, Some priv -> ( + match Hashtbl.find_opt t.sk_ht pub with + | Some _sk -> + Error "secmod failure: this signkey already has a master signature" + | None -> + let Api.FutureSignKey. + { + key; + stamp_start; + stamp_expire; + stamp_end; + signkey_secmod_sig= _; + } = + future_sk + in + let sk = + Signkey. + { + pub= key; + stamp_start; + stamp_expire; + stamp_end; + master_sig; + revoked_sig= None; + } + in + Hashtbl.replace t.sk_ht pub sk; + Hashtbl.replace t.sk_key_ht pub priv; + Hashtbl.remove t.future_sk_ht pub; + Hashtbl.remove t.future_sk_key_ht pub; - let get_signkeys_data () = get_signkeys () |> List.map (fun v -> v.sk_data) - let get_denoms_data () = get_denoms () |> List.map (fun v -> v.dn_data) - - let find_signkey_data pub = - find_signkey pub |> Option.map (fun v -> v.sk_data) - - let find_denomination h_denom = - find_denom h_denom |> Option.map (fun v -> v.dn_data) - - let find_denom_section_name h_denom = - Miou.Mutex.protect t.lock @@ fun () -> - Hashtbl.find_opt t.dn_section_name_ht h_denom + let* () = Pg.insert_signkey (module Conn) sk |> unwrap_err_caqti in + Ok ()) let add_signkey_master_signatures l = Miou.Mutex.protect t.lock @@ fun () -> diff --git a/src/signkey.ml b/src/signkey.ml index 22a7a0cd..611b894c 100644 --- a/src/signkey.ml +++ b/src/signkey.ml @@ -5,6 +5,6 @@ type t = { stamp_start: Timestamp.t; stamp_expire: Timestamp.t; stamp_end: Timestamp.t; - master_sig: Signatures.ExchangeSigningKeyValidity.t option; + master_sig: Signatures.ExchangeSigningKeyValidity.t; revoked_sig: Signatures.MasterSigningKeyRevocation.t option; }