This commit is contained in:
swrup 2026-02-17 12:40:36 +01:00
parent fe5751044d
commit c59cb116fc
3 changed files with 141 additions and 137 deletions

View file

@ -51,21 +51,10 @@ let signkey_data =
Signkey. Signkey.
{ pub; stamp_start; stamp_expire; stamp_end; master_sig; revoked_sig } { 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 ~decode:(fun
(pub, stamp_start, stamp_expire, stamp_end, master_sig, revoked_sig) -> (pub, stamp_start, stamp_expire, stamp_end, master_sig, revoked_sig) ->
Ok Ok { pub; stamp_start; stamp_expire; stamp_end; master_sig; revoked_sig })
{
pub;
stamp_start;
stamp_expire;
stamp_end;
master_sig= Some master_sig;
revoked_sig;
})
(t6 eddsa_pub time time time master_sig revoked_sig) (t6 eddsa_pub time time time master_sig revoked_sig)
let denom_data = let denom_data =
@ -91,9 +80,6 @@ let denom_data =
revoked_sig; revoked_sig;
} }
-> ->
match master_sig with
| None -> Error "denom_data master_sig is none"
| Some master_sig ->
Ok Ok
( pub, ( pub,
value, value,
@ -135,7 +121,7 @@ let denom_data =
fee_refund; fee_refund;
age_mask; age_mask;
h_pub; h_pub;
master_sig= Some master_sig; master_sig;
revoked_sig; revoked_sig;
}) })
(t12 rsa_pub amount time time time time amount amount amount amount int (t12 rsa_pub amount time time time time amount amount amount amount int

View file

@ -1,6 +1,7 @@
module type S = sig module type S = sig
open Crypto open Crypto
val sm_pubkey : eddsa_pub
val sign_with_sm_key : string -> eddsa_sig val sign_with_sm_key : string -> eddsa_sig
val sign_with_signkey : pub:eddsa_pub -> 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 val verify_with_master_key : eddsa_sig -> msg:string -> (unit, string) result
@ -9,26 +10,20 @@ module type S = sig
val verify_with_signkey : val verify_with_signkey :
pub:eddsa_pub -> eddsa_sig -> msg:string -> (unit, string) result pub:eddsa_pub -> eddsa_sig -> msg:string -> (unit, string) result
(* TODO query database instead? *) val get_signkeys : unit -> Signkey.t list
val get_sm_key_pub : unit -> eddsa_pub val get_denominations : unit -> Denomination.t list
val get_signkeys_data : unit -> Signkey.t list val get_future_signkeys : unit -> Api.FutureSignKey.t list
val get_denoms_data : unit -> Denomination.t list val get_future_denominations : unit -> Api.FutureDenom.t list
val find_signkey_data : eddsa_pub -> Signkey.t option val find_signkey : eddsa_pub -> Signkey.t option
val find_denomination : denomination_hash -> Denomination.t option val find_denomination : rsa_pub -> Denomination.t option
val find_denom_section_name : denomination_hash -> string option
(* - management operations - *) val certify_future_signkey :
(* TODO eddsa_pub ->
problem of keeping db and secmod state syncronized Signatures.ExchangeSigningKeyValidity.t ->
do db interaction from secmod? *)
val add_signkey_master_signatures :
(eddsa_pub * Signatures.ExchangeSigningKeyValidity.t) list ->
(unit, string) result (unit, string) result
val add_denom_master_signatures : val certify_future_denomination :
(denomination_hash * Signatures.DenominationKeyValidity.t) list -> rsa_pub -> Signatures.DenominationKeyValidity.t -> (unit, string) result
(unit, string) result
val revoke_signkey : val revoke_signkey :
eddsa_pub -> eddsa_pub ->
@ -36,11 +31,11 @@ module type S = sig
(unit, string) result (unit, string) result
val revoke_denomination : val revoke_denomination :
denomination_hash -> rsa_pub ->
Signatures.MasterDenominationKeyRevocation.t -> Signatures.MasterDenominationKeyRevocation.t ->
(unit, string) result (unit, string) result
val store : unit -> (unit, string) result val save : unit -> (unit, string) result
end end
module Make (Conn : Pg.CONN) = struct module Make (Conn : Pg.CONN) = struct
@ -52,7 +47,7 @@ module Make (Conn : Pg.CONN) = struct
type dn = Denomination.t type dn = Denomination.t
type future_dn = Api.FutureDenom.t type future_dn = Api.FutureDenom.t
(* TODO use lock *) (* TODO use lock! *)
type t = { type t = {
sm_key: eddsa_priv; sm_key: eddsa_priv;
sm_pubkey: eddsa_pub; sm_pubkey: eddsa_pub;
@ -64,6 +59,7 @@ module Make (Conn : Pg.CONN) = struct
future_dn_ht: (rsa_pub, future_dn) Hashtbl.t; future_dn_ht: (rsa_pub, future_dn) Hashtbl.t;
future_sk_key_ht: (eddsa_pub, eddsa_priv) Hashtbl.t; future_sk_key_ht: (eddsa_pub, eddsa_priv) Hashtbl.t;
future_dn_key_ht: (rsa_pub, rsa_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 = let database_find_sk conn fname pub =
@ -166,6 +162,7 @@ module Make (Conn : Pg.CONN) = struct
future_dn_ht= Hashtbl.create 0xff; future_dn_ht= Hashtbl.create 0xff;
future_sk_key_ht= Hashtbl.create 0xff; future_sk_key_ht= Hashtbl.create 0xff;
future_dn_key_ht= Hashtbl.create 0xff; future_dn_key_ht= Hashtbl.create 0xff;
dn_section_name_ht= Hashtbl.create 0xff;
} }
in in
Ok (Some t) Ok (Some t)
@ -280,6 +277,7 @@ module Make (Conn : Pg.CONN) = struct
future_dn_ht= Hashtbl.create 0xff; future_dn_ht= Hashtbl.create 0xff;
future_sk_key_ht= Hashtbl.create 0xff; future_sk_key_ht= Hashtbl.create 0xff;
future_dn_key_ht= Hashtbl.create 0xff; future_dn_key_ht= Hashtbl.create 0xff;
dn_section_name_ht= Hashtbl.create 0xff;
} }
in in
make_future_sk t; make_future_sk t;
@ -297,6 +295,7 @@ module Make (Conn : Pg.CONN) = struct
t t
| Error e -> Fmt.failwith "secmod init failure: %s." e | 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 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_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 EddsaSignature.verify ~key:Config.master_public_key
let verify_with_signkey ~pub s ~msg = 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 match Hashtbl.find_opt t.sk_ht pub with
| None -> Fmt.failwith "secmod failure: signkey not found." | None -> Fmt.failwith "secmod failure: signkey not found."
| Some _priv -> EddsaSignature.verify ~key:pub s ~msg | 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_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_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 let* () = Pg.insert_signkey (module Conn) sk |> unwrap_err_caqti in
Ok ()) Ok ())
let add_signkey_master_signatures l = let certify_future_denomination pub master_sig =
Miou.Mutex.protect t.lock @@ fun () -> match
list_iter ( Hashtbl.find_opt t.future_dn_ht pub,
(fun (pub, master_sig) -> 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
(* TODO dn hash
need to compute it from denom_pub *)
let h_pub =
Hash.DenominationHash.hash (RsaPublicKey.to_octets pub)
in
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* () = Pg.insert_denom (module Conn) dn |> unwrap_err_caqti in
Ok ())
let revoke_signkey pub revoked_sig =
match Hashtbl.find_opt t.sk_ht pub with match Hashtbl.find_opt t.sk_ht pub with
| None -> Error "secmod failure: public key not found." | None -> Error "secmod failure: signkey not found."
| Some signkey -> | Some sk ->
let sk_data = let sk = { sk with revoked_sig= Some revoked_sig } in
{ signkey.sk_data with master_sig= Some master_sig } Hashtbl.replace t.sk_ht pub sk;
in
let signkey = { signkey with sk_data } in
let* () =
Pg.insert_signkey (module Conn) sk_data |> unwrap_err_caqti
in
Hashtbl.replace t.sk_ht pub signkey;
Ok ())
l
let add_denom_master_signatures l = (* TODO revoke, apply to database *)
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;
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;
Ok () Ok ()
let revoke_denomination h_denom_pub revoked_sig = let revoke_denomination pub revoked_sig =
Miou.Mutex.protect t.lock @@ fun () -> match Hashtbl.find_opt t.dn_ht pub with
match Hashtbl.find_opt t.dn_ht h_denom_pub with | None -> Error "secmod failure: denomination not found."
| None -> Error "secmod failure: denomination hash not found." | Some dn ->
| Some denom -> let dn = { dn with revoked_sig= Some revoked_sig } in
let dn_data = { denom.dn_data with revoked_sig= Some revoked_sig } in Hashtbl.replace t.dn_ht pub dn;
let denom = { denom with dn_data } in
Hashtbl.replace t.dn_ht h_denom_pub denom; (* TODO revoke, apply to database *)
Ok () Ok ()
let store () = let save () =
Miou.Mutex.protect t.lock @@ fun () ->
let* () = 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 in
let* () = let* () =
Hashtbl.to_seq_values t.sk_ht Hashtbl.to_seq_values t.sk_key_ht
|> List.of_seq |> 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 let fname = Fpath.(Config.secrets_dir / Fmt.str "sk_%d" i) in
(fname, key.priv)) Data_file.write_eddsa fname priv)
|> list_iter (fun (fname, key) -> Data_file.write_eddsa fname key) |> list_iter Fun.id
in in
let* () = let* () =
let* l = Hashtbl.to_seq t.dn_key_ht
Hashtbl.to_seq_values t.dn_ht
|> List.of_seq |> List.of_seq
|> Syntax.list_map (fun (key : denom) -> |> list_iter (fun (pub, priv) ->
let+ section_name = let* section_name =
match Hashtbl.find_opt t.dn_section_name_ht key.dn_data.h_pub with match Hashtbl.find_opt t.dn_section_name_ht pub with
| None -> Error "invalid state, section_name not found" | None -> Error "invalid state, section_name not found"
| Some s -> Ok s | Some s -> Ok s
in in
let fname = Fpath.(Config.secrets_dir / section_name) in let fname = Fpath.(Config.secrets_dir / section_name) in
(fname, key.priv)) Data_file.write_rsa fname priv)
in in
list_iter (fun (fname, key) -> Data_file.write_rsa fname key) l Logs.info (fun m -> m "saved secmod private keys data");
in
Logs.info (fun m -> m "stored secmod data to file");
Ok () Ok ()
end end

View file

@ -1,6 +1,7 @@
module type S = sig module type S = sig
open Crypto open Crypto
val sm_pubkey : eddsa_pub
val sign_with_sm_key : string -> eddsa_sig val sign_with_sm_key : string -> eddsa_sig
val sign_with_signkey : pub:eddsa_pub -> 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 val verify_with_master_key : eddsa_sig -> msg:string -> (unit, string) result
@ -9,26 +10,20 @@ module type S = sig
val verify_with_signkey : val verify_with_signkey :
pub:eddsa_pub -> eddsa_sig -> msg:string -> (unit, string) result pub:eddsa_pub -> eddsa_sig -> msg:string -> (unit, string) result
(* TODO query database instead? *) val get_signkeys : unit -> Signkey.t list
val get_sm_key_pub : unit -> eddsa_pub val get_denominations : unit -> Denomination.t list
val get_signkeys_data : unit -> Signkey.t list val get_future_signkeys : unit -> Api.FutureSignKey.t list
val get_denoms_data : unit -> Denomination.t list val get_future_denominations : unit -> Api.FutureDenom.t list
val find_signkey_data : eddsa_pub -> Signkey.t option val find_signkey : eddsa_pub -> Signkey.t option
val find_denomination : denomination_hash -> Denomination.t option val find_denomination : rsa_pub -> Denomination.t option
val find_denom_section_name : denomination_hash -> string option
(* - management operations - *) val certify_future_signkey :
(* TODO eddsa_pub ->
problem of keeping db and secmod state syncronized Signatures.ExchangeSigningKeyValidity.t ->
do db interaction from secmod? *)
val add_signkey_master_signatures :
(eddsa_pub * Signatures.ExchangeSigningKeyValidity.t) list ->
(unit, string) result (unit, string) result
val add_denom_master_signatures : val certify_future_denomination :
(denomination_hash * Signatures.DenominationKeyValidity.t) list -> rsa_pub -> Signatures.DenominationKeyValidity.t -> (unit, string) result
(unit, string) result
val revoke_signkey : val revoke_signkey :
eddsa_pub -> eddsa_pub ->
@ -36,11 +31,11 @@ module type S = sig
(unit, string) result (unit, string) result
val revoke_denomination : val revoke_denomination :
denomination_hash -> rsa_pub ->
Signatures.MasterDenominationKeyRevocation.t -> Signatures.MasterDenominationKeyRevocation.t ->
(unit, string) result (unit, string) result
val store : unit -> (unit, string) result val save : unit -> (unit, string) result
end end
module Make (_ : Pg.CONN) : S module Make (_ : Pg.CONN) : S