(* Derivability Copyright (c) 2021 The MITRE Corporation This program is free software: you can redistribute it and/or modify it under the terms of the BSD License as published by the University of California. *) (** * Derivability *) Require Import List ListSet Bool Lia Alg Sem_tactics. (** [derives pub t] when [t] can be derived using the terms in [pub]. *) Inductive derives (pub: list alg): alg -> Prop := | Der_mem: forall x: alg, In x pub -> derives pub x | Der_tagg: forall s, derives pub (Tg s) | Der_pair: forall x y, derives pub x -> derives pub y -> derives pub (Pr x y) | Der_encr: forall x y, derives pub x -> derives pub y -> derives pub (En x y) | Der_hash: forall x, derives pub x -> derives pub (Hs x) | Der_frst: forall x y, derives pub (Pr x y) -> derives pub x | Der_scnd: forall x y, derives pub (Pr x y) -> derives pub y | Der_decr: forall x y, derives pub (En x y) -> derives pub (inv y) -> derives pub x. #[global] Hint Constructors derives : core. (* There is no good way to implement derives directly in code. There is an easy way to do it with analyze-then-synthesize. Here is the algorithm used in CPSA and in the role compiler: synth(T, t): bool := if t in T return true; if t = (t1, t2) return synth t1 && synth t2; if t = (enc t1 t2) return synth t1 && synth t2; if t = (hash t1) return synth t1; if t = "..." return true. analyze(T): set of terms := while T changes do let t = some element in T; if t = (t1, t2) then add t1 and t2 to T else if t = (enc t1 t2) and synth(T, invk(t2)) then add t1 to T; done; return T. *) (* synth pub t when t can be synthesized using the terms in pub. *) Inductive synth (pub: alg -> Prop): alg -> Prop := | Synth_mem: forall x: alg, pub x -> synth pub x | Synth_tag: forall i, synth pub (Tg i) | Synth_pair: forall x y, synth pub x -> synth pub y -> synth pub (Pr x y) | Synth_encr: forall x y, synth pub x -> synth pub y -> synth pub (En x y) | Synth_hash: forall x, synth pub x -> synth pub (Hs x). #[global] Hint Constructors synth : core. (* analyze pub t when t can be analyzed using the terms in pub. *) Inductive analyze (pub: list alg): alg -> Prop := | Analyze_mem: forall x: alg, In x pub -> analyze pub x | Analyze_frst: forall x y, analyze pub (Pr x y) -> analyze pub x | Analyze_scnd: forall x y, analyze pub (Pr x y) -> analyze pub y | Analyze_decr: forall x y, analyze pub (En x y) -> synth (analyze pub) (inv y) -> analyze pub x. Theorem derives_implies_analyze_then_synth: forall pub x, derives pub x -> synth (analyze pub) x. Proof. intros pub x H. induction H; auto. - apply Synth_mem; apply Analyze_mem; assumption. - inv IHderives; auto. apply Analyze_frst in H0. apply Synth_mem; assumption. - inv IHderives; auto. apply Analyze_scnd in H0. apply Synth_mem; assumption. - inv IHderives1; auto. apply Analyze_decr in H1; auto. Qed. (* Failed attempt that the final Theorem *) Theorem analyze_then_synth_implies_derives: forall pub x, synth (analyze pub) x -> derives pub x. Proof. intros pub x H. induction H; auto. induction H. - apply Der_mem; auto. - eapply Der_frst; eauto. - eapply Der_scnd; eauto. - eapply Der_decr; eauto. clear IHanalyze H x. (* HELP!!! *) give_up. Abort. (* Analyze stratified *) Inductive analyze_strat (pub: list alg): nat -> alg -> Prop := | Analyze_strat_mem: forall x, In x pub -> analyze_strat pub 0 x | Analyze_strat_incl: forall n x, analyze_strat pub n x -> analyze_strat pub (S n) x | Analyze_strat_frst: forall n x y, analyze_strat pub n (Pr x y) -> analyze_strat pub (S n) x | Analyze_strat_scnd: forall n x y, analyze_strat pub n (Pr x y) -> analyze_strat pub (S n) y | Analyze_strat_decr: forall n x y, analyze_strat pub n (En x y) -> synth (analyze_strat pub n) (inv y) -> analyze_strat pub (S n) x. #[global] Hint Constructors analyze_strat : core. Lemma analyze_strat_zero: forall pub t, analyze_strat pub 0 t <-> In t pub. Proof. split; intros. - inv H; auto. - apply Analyze_strat_mem; auto. Qed. Lemma analyze_strat_zero_then_synth: forall pub t, synth (analyze_strat pub 0) t <-> synth (fun y => In y pub) t. Proof. split; intros. - induction H; simpl; auto. rewrite analyze_strat_zero in H. apply Synth_mem; auto. - induction H; simpl; auto. Qed. Lemma synth_implies_derives: forall pub x, synth (fun y => In y pub) x -> derives pub x. Proof. intros pub x H. induction H; auto. Qed. Lemma analyze_strat_derives: forall pub n t, synth (analyze_strat pub n) t -> derives pub t. Proof. induction n; intros. - rewrite analyze_strat_zero_then_synth in H. apply synth_implies_derives; auto. - induction H; simpl; auto. inv H. + apply IHn. apply Synth_mem; auto. + apply Der_frst with (y := y); auto. + apply Der_scnd with (x := x0); auto. + apply IHn in H2. apply Der_decr with (y := y); auto. Qed. Lemma analyze_strat_monotonic_1: forall pub m t, synth (analyze_strat pub m) t -> synth (analyze_strat pub (S m)) t. Proof. intros. induction H; simpl; auto. Qed. Lemma analyze_strat_monotonic_2: forall pub m n t, synth (analyze_strat pub m) t -> synth (analyze_strat pub (n + m)) t. Proof. intros. induction n; simpl; auto. apply analyze_strat_monotonic_1; auto. Qed. Lemma analyze_strat_monotonic: forall pub m n t, m <= n -> synth (analyze_strat pub m) t -> synth (analyze_strat pub n) t. Proof. intros pub m n t H G. apply analyze_strat_monotonic_2 with (n := n - m) in G. assert (F: n - m + m = n). - lia. - rewrite F in G; auto. Qed. (* Reflection for synth *) Fixpoint synthb (pub: list alg) t: bool := set_mem alg_dec t pub || match t with | Pr x y => synthb pub x && synthb pub y | En x y => synthb pub x && synthb pub y | Hs x => synthb pub x | Tg _ => true | _ => false end. Lemma synthb_correct : forall pub x, synth (fun y => In y pub) x <-> synthb pub x = true. Proof. split. - intro H. induction H; try apply orb_true_iff; intuition auto with *. destruct x; apply orb_true_iff; left; apply set_mem_correct2; auto. - induction x; intro H; simpl in H; apply orb_true_iff in H; destruct H; auto; try match goal with | [ H: set_mem alg_dec _ pub = true |- _ ] => apply set_mem_correct1 in H; auto end; try intuition auto with *. + apply andb_true_iff in H. destruct H; auto. + apply andb_true_iff in H. destruct H; auto. Qed.