diff --git a/src/api_sig.ml b/src/api_sig.ml index 642369a5..79715dbf 100644 --- a/src/api_sig.ml +++ b/src/api_sig.ml @@ -48,6 +48,7 @@ end) : sig (* Ok () on verification success *) val verify : key:Crypto.EddsaPublicKey.t -> t -> r -> (unit, string) result val jsont : t Jsont.t + val caqti : t Caqti_type.t end = struct open Crypto @@ -64,6 +65,14 @@ end = struct | true -> Ok () let jsont = EddsaSignature.jsont + + let caqti : EddsaSignature.t Caqti_type.t = + let open Caqti_type in + let open EddsaSignature in + custom + ~encode:(fun v -> Ok (to_octets v)) + ~decode:(fun s -> Ok (of_octets s)) + octets end module DenominationKeyAnnouncementPS = struct diff --git a/src/database.ml b/src/database.ml index 7ee23436..2bc209bc 100644 --- a/src/database.ml +++ b/src/database.ml @@ -28,6 +28,5 @@ let test_activate req server _ = let db_conn = Vif.Server.device Devices.db_connection server in let secmod_signkey = Vif.Server.device Devices.secmod_signkey server in let sm_key = Secmod_signkey.get_sm_key secmod_signkey in - let sm_key = { sm_key with master_sig= dummy_master_sig } in let res = Pg.activate_signing_key db_conn sm_key in Result.fold ~ok:(on_ok req) ~error:(on_error req) res diff --git a/src/denomination.ml b/src/denomination.ml index 32eb469d..5a7c6202 100644 --- a/src/denomination.ml +++ b/src/denomination.ml @@ -15,7 +15,7 @@ type t = { fee_refund: Amount.t; age_mask: int; h_pub: Bin_type.DenominationHash.t; - master_sig: EddsaSignature.t option; + master_sig: Api_sig.DenominationKeyValidityPS.t option; } let make diff --git a/src/management.ml b/src/management.ml index 993024e7..d1ebb3ad 100644 --- a/src/management.ml +++ b/src/management.ml @@ -96,19 +96,16 @@ let mk_future_keys_response ~(sm_signkey : Secmod_signkey.t) (* - ** - *) -let verify_denom_signature ~sm_denoms DenomSignature.{ h_denom_pub; master_sig } +let verify_denom_signature ~sm_denom DenomSignature.{ h_denom_pub; master_sig } = let open Syntax in let denom_hash = Bin_type.DenominationHash.of_octets (HashCode.to_octets h_denom_pub) in let* denom = - let opt = - List.find_opt - (fun (denom : Denomination.t) -> denom.h_pub = denom_hash) - sm_denoms - in - match opt with + Secmod_denom.get_denoms sm_denom + |> List.find_opt (fun (denom : Denomination.t) -> denom.h_pub = denom_hash) + |> function | None -> Fmt.error "404 not found, One of the keys for which a signature was provided \ @@ -132,13 +129,12 @@ let verify_denom_signature ~sm_denoms DenomSignature.{ h_denom_pub; master_sig } in verify ~key:Config.master_public_key master_sig r -let verify_signkey_signature ~sm_signkeys SignKeySignature.{ key; master_sig } = +let verify_signkey_signature ~sm_signkey SignKeySignature.{ key; master_sig } = let open Syntax in let* signkey = - let opt = - List.find_opt (fun (signkey : Signkey.t) -> signkey.pub = key) sm_signkeys - in - match opt with + Secmod_signkey.get_signkeys sm_signkey + |> List.find_opt (fun (signkey : Signkey.t) -> signkey.pub = key) + |> function | None -> Fmt.error "404 not found, One of the keys for which a signature was provided \ @@ -156,11 +152,33 @@ let verify_signkey_signature ~sm_signkeys SignKeySignature.{ key; master_sig } = in verify ~key:Config.master_public_key master_sig r -let verify_master_signatures ~sm_signkeys ~sm_denoms +let verify_master_signatures ~sm_signkey ~sm_denom MasterSignatures.{ denom_sigs; signkey_sigs } = let open Syntax in - let* () = list_iter (verify_denom_signature ~sm_denoms) denom_sigs in - let* () = list_iter (verify_signkey_signature ~sm_signkeys) signkey_sigs in + let* () = list_iter (verify_denom_signature ~sm_denom) denom_sigs in + let* () = list_iter (verify_signkey_signature ~sm_signkey) signkey_sigs in + Ok () + +(* --- *) + +let update_master_signatures ~db_conn ~sm_signkey ~sm_denom + MasterSignatures.{ denom_sigs; signkey_sigs } = + let open Syntax in + let* () = + signkey_sigs + |> List.map (fun SignKeySignature.{ key; master_sig } -> (key, master_sig)) + |> Secmod_signkey.add_master_signatures db_conn sm_signkey + in + let* () = + denom_sigs + |> List.map (fun DenomSignature.{ h_denom_pub; master_sig } -> + (* TODO better denomination-hash type *) + let h_denom_pub = + Bin_type.DenominationHash.of_octets (HashCode.to_octets h_denom_pub) + in + (h_denom_pub, master_sig)) + |> Secmod_denom.add_master_signatures db_conn sm_denom + in Ok () (* --- *) @@ -198,6 +216,7 @@ let keys_get req server _env = let keys_post_jsont = MasterSignatures.jsont let keys_post req server _env = + let db_conn = Vif.Server.device Devices.db_connection server in let sm_signkey = Vif.Server.device Devices.secmod_signkey server in let sm_denom = Vif.Server.device Devices.secmod_denom server in let res = @@ -210,11 +229,11 @@ let keys_post req server _env = Error msg in let* () = - let sm_denoms = Secmod_denom.get_denoms sm_denom in - let sm_signkeys = Secmod_signkey.get_signkeys sm_signkey in - verify_master_signatures ~sm_signkeys ~sm_denoms master_signatures + verify_master_signatures ~sm_signkey ~sm_denom master_signatures + in + let* () = + update_master_signatures ~db_conn ~sm_signkey ~sm_denom master_signatures in - (* TODO let* () = update_master_signatures () in*) Ok "" in respond_with_res res req diff --git a/src/pg.ml b/src/pg.ml index b6f6264e..9da8a192 100644 --- a/src/pg.ml +++ b/src/pg.ml @@ -92,7 +92,8 @@ let lookup_signing_key = let activate_signing_key = let insert_signkey = - Caqti_type.(t5 eddsa_public time time time eddsa_signature ->. unit) + let master_sig = Api_sig.ExchangeSigningKeyValidityPS.caqti in + Caqti_type.(t5 eddsa_public time time time master_sig ->. unit) "INSERT INTO exchange_sign_keys (exchange_pub, valid_from, expire_sign, \ expire_legal, master_sig) VALUES ($1, $2, $3, $4, $5)" in @@ -118,9 +119,10 @@ let lookup_denomination_key = let add_denomination_key = let denomination_insert = + let master_sig = Api_sig.DenominationKeyValidityPS.caqti in Caqti_type.( - t12 denomination_hash rsa_public eddsa_signature time time time time - amount amount amount amount (t2 amount age_mask) + t12 denomination_hash rsa_public master_sig time time time time amount + amount amount amount (t2 amount age_mask) ->. unit) "INSERT INTO denominations (denom_pub_hash, denom_pub, master_sig, \ valid_from, expire_withdraw, expire_deposit, expire_legal, coin, \ diff --git a/src/secmod_denom.ml b/src/secmod_denom.ml index a2d6d6ea..3de76e66 100644 --- a/src/secmod_denom.ml +++ b/src/secmod_denom.ml @@ -12,12 +12,18 @@ let get_denoms t = Miou.Mutex.protect t.lock @@ fun () -> Hashtbl.to_seq_values t.denom_ht |> List.of_seq -(* TODO *) -let update_denoms _conn t denoms = +let add_master_signatures conn t l = Miou.Mutex.protect t.lock @@ fun () -> - List.iter - (fun denom -> Hashtbl.replace t.denom_ht denom.Denomination.h_pub denom) - denoms + list_iter + (fun (h_denom_pub, master_sig) -> + match Hashtbl.find_opt t.denom_ht h_denom_pub with + | None -> Error "secmod_denom failure: denomination hash not found." + | Some denom -> + let denom = { denom with master_sig= Some master_sig } in + let* () = Pg.add_denomination_key conn denom |> unwrap_err_caqti in + Hashtbl.replace t.denom_ht h_denom_pub denom; + Ok ()) + l let dir = Fpath.(v "data" / "secmod_signkey") diff --git a/src/secmod_denom.mli b/src/secmod_denom.mli index 9c5b2413..0c373086 100644 --- a/src/secmod_denom.mli +++ b/src/secmod_denom.mli @@ -2,5 +2,11 @@ type t val get_sm_key : t -> Signkey.t val get_denoms : t -> Denomination.t list -val update_denoms : (module Pg.CONN) -> t -> Denomination.t list -> unit + +val add_master_signatures : + (module Pg.CONN) -> + t -> + (Bin_type.DenominationHash.t * Api_sig.DenominationKeyValidityPS.t) list -> + (unit, string) result + val init : (module Pg.CONN) -> t diff --git a/src/secmod_signkey.ml b/src/secmod_signkey.ml index d1a6067c..ccff6894 100644 --- a/src/secmod_signkey.ml +++ b/src/secmod_signkey.ml @@ -16,12 +16,18 @@ let get_signkeys t = Miou.Mutex.protect t.lock @@ fun () -> Hashtbl.to_seq_values t.signkey_ht |> List.of_seq -(* TODO *) -let update_signkeys _conn t signkeys = +let add_master_signatures conn t l = Miou.Mutex.protect t.lock @@ fun () -> - List.iter - (fun signkey -> Hashtbl.replace t.signkey_ht signkey.Signkey.pub signkey) - signkeys + list_iter + (fun (pub, master_sig) -> + match Hashtbl.find_opt t.signkey_ht pub with + | None -> Error "secmod_signkey failure: public key not found." + | Some signkey -> + let signkey = { signkey with master_sig= Some master_sig } in + let* () = Pg.activate_signing_key conn signkey |> unwrap_err_caqti in + Hashtbl.replace t.signkey_ht pub signkey; + Ok ()) + l let dir = Fpath.(v "data" / "secmod_signkey") diff --git a/src/secmod_signkey.mli b/src/secmod_signkey.mli index a80b07de..40c19702 100644 --- a/src/secmod_signkey.mli +++ b/src/secmod_signkey.mli @@ -2,5 +2,11 @@ type t val get_sm_key : t -> Signkey.t val get_signkeys : t -> Signkey.t list -val update_signkeys : (module Pg.CONN) -> t -> Signkey.t list -> unit + +val add_master_signatures : + (module Pg.CONN) -> + t -> + (Crypto.EddsaPublicKey.t * Api_sig.ExchangeSigningKeyValidityPS.t) list -> + (unit, string) result + val init : (module Pg.CONN) -> t diff --git a/src/signkey.ml b/src/signkey.ml index 3c59043e..fbb29d72 100644 --- a/src/signkey.ml +++ b/src/signkey.ml @@ -8,8 +8,7 @@ type t = { stamp_start: Timestamp.t; stamp_expire: Timestamp.t; stamp_end: Timestamp.t; - (* signature of this key by offline master key *) - master_sig: EddsaSignature.t option; + master_sig: Api_sig.ExchangeSigningKeyValidityPS.t option; } let make () = diff --git a/src/syntax.ml b/src/syntax.ml index f354ca6c..c61aba15 100644 --- a/src/syntax.ml +++ b/src/syntax.ml @@ -4,6 +4,9 @@ let ( let+ ) o f = match o with Ok v -> Ok (f v) | Error _ as e -> e (* TODO use polymorphic variant for errors *) let unwrap_err_msg o = match o with Error (`Msg e) -> Error e | Ok v -> Ok v +let unwrap_err_caqti o = + match o with Error err -> Fmt.error "%a" Caqti_error.pp err | Ok v -> Ok v + let list_iter f l = let err = ref None in try