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.
{ 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))
~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,9 +80,6 @@ let denom_data =
revoked_sig;
}
->
match master_sig with
| None -> Error "denom_data master_sig is none"
| Some master_sig ->
Ok
( 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

View file

@ -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) ->
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
(* 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
| None -> Error "secmod failure: public key not found."
| Some signkey ->
let sk_data =
{ signkey.sk_data with master_sig= Some master_sig }
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
| 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;
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;
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;
(* 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
Hashtbl.to_seq t.dn_key_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
|> 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
(fname, key.priv))
Data_file.write_rsa fname priv)
in
list_iter (fun (fname, key) -> Data_file.write_rsa fname key) l
in
Logs.info (fun m -> m "stored secmod data to file");
Logs.info (fun m -> m "saved secmod private keys data");
Ok ()
end

View file

@ -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