(* JFKr *)

set redundantHypElim = beginOnly.

(* Setting to prove the 4th query and disprove the last two *)
set nounifIgnoreAFewTimes = auto.
set nounifIgnoreNtimes = 3.

type G.
type texponent.
type skey.
type pkey.
type key.
type tag.
type nonce.
type grpinfo.
type sainfo.

fun G_to_key(G):key [data, typeConverter].

(* Exponential and Diffie-Hellman *)

const g: G.
fun exp(G, texponent): G.
equation forall y: texponent, z: texponent; exp(exp(g,y),z) = exp(exp(g,z),y).

(* Signature *)

fun S(skey, bitstring): bitstring.
fun Pk(skey): pkey.

fun V(bitstring, pkey, bitstring): bool
reduc forall k: skey, v: bitstring; V(S(k,v), Pk(k),v) = true
otherwise forall pk: pkey, s,v: bitstring; V(s, pk,v) = false.

fun RecoverKey(bitstring): pkey
reduc forall k: skey, v: bitstring; RecoverKey(S(k,v)) = Pk(k). (* For the attacker *)

fun RecoverText(bitstring): bitstring
reduc forall k: skey, v: bitstring; RecoverText(S(k,v)) = v.    (* For the attacker *)

(* Shared-key encryption *)

fun E(key, bitstring): bitstring.
fun D(key, bitstring): bitstring.
equation forall k: key, v: bitstring; D(k,E(k,v)) = v.

(* Keyed hash function *)

fun H(key, bitstring): key.

(* Sets *)

type keyset.
fun consset(key, keyset): keyset [data].
const emptyset: keyset [data].
pred member(key, keyset).
clauses
  forall x: key, y: keyset; member(x,consset(x,y));
  forall x: key, y: keyset, z: key; member(x,y) -> member(x,consset(z,y)).

type idset.
fun considset(pkey, idset): idset [data].
const emptyidset: idset [data].
pred memberid(pkey, idset).
clauses
  forall x: pkey, y: idset; memberid(x,considset(x,y));
  forall x: pkey, y: idset, z: pkey; memberid(x,y) -> memberid(x,considset(z,y)).

(* Tags *)

const tagE, tagA, tagV: tag [data].

(* Constructors for JFK's formatted messages
   Selectors are implicit when using "data" *)

fun cons1(nonce, G): bitstring [data].
fun cons2(nonce, nonce, G, grpinfo, key): bitstring [data] .
fun cons3(nonce, nonce, G, G, key, bitstring, key): bitstring [data].
fun cons4(bitstring, key): bitstring [data].

(* More constants *)

const constI, constR: tag [data].

(* Queries: properties to prove *)

(* Correspondence assertions *)

event princ(skey, pkey, channel, channel, channel, idset).
event enddosi(pkey, nonce).
event enddosr(pkey, nonce, nonce).
event initev(channel, pkey, sainfo).
event mess1(pkey, nonce, G, channel, pkey, sainfo).
event mess1rec(pkey, nonce, G).
event mess2(pkey, nonce, nonce, G, G, grpinfo, key).
event mess2rec(pkey, nonce, nonce, G, grpinfo, key, G, pkey, sainfo).
event mess3(pkey, nonce, nonce, G, G, key, bitstring, key, grpinfo, pkey, sainfo, key).
event mess3rec(pkey, nonce, nonce, G, G, key, bitstring, key).
event mess4(pkey, pkey, bitstring, key, nonce, nonce, G, G, key, bitstring, key).
event mess4rec(pkey, bitstring, key, channel, pkey, pkey, sainfo, sainfo, key).
event acceptev(channel, pkey, pkey, sainfo, sainfo, key).
event accepthonest(channel, pkey, pkey, sainfo, sainfo, key).
event connectev(channel, pkey, pkey, sainfo, sainfo, key).
event connecthonest(channel, pkey, pkey, sainfo, sainfo, key).





  (* To prove these injective correspondences, you need to replace the caching
     of message 3 with a version without caching *)

  (* Denial of service for R. *)
  query XkAminus: skey, XIDA: pkey, XinitA: channel, XacceptA: channel, XconnectA: channel, XSIA: idset, XNI: nonce, XNR: nonce, XxI: G, XxR: G, XtR: key, XeI: bitstring, XhI: key, XxIp: G, XgrpinfoR: grpinfo;
    inj-event(enddosr(XIDA, XNI, XNR)) ==>
     event(princ(XkAminus, XIDA, XinitA, XacceptA, XconnectA, XSIA))
  && (inj-event(mess3rec(XIDA, XNI, XNR, XxI, XxR, XtR, XeI, XhI)) ==>
    (inj-event(mess2(XIDA, XNI, XNR, XxIp, XxR, XgrpinfoR, XtR)) ==>
     inj-event(mess1rec(XIDA, XNI, XxIp)))).

  (* Second part of Property 1 of Theorem 3. *)
  query XkAminus: skey, XIDA: pkey, XinitA: channel, XacceptA: channel, XconnectA: channel, XSIA: idset, XkBminus: skey, XIDB: pkey, XinitB: channel, XacceptB: channel, XconnectB: channel, XSIB: idset, XIDRp: pkey, XsaI: sainfo, XsaR: sainfo, XKv: key;
    inj-event(accepthonest(XacceptB, XIDA, XIDRp, XsaI, XsaR, XKv)) ==>
		  inj-event(initev(XinitA, XIDRp, XsaI))
		&& event(princ(XkAminus, XIDA, XinitA, XacceptA, XconnectA, XSIA))
                && event(princ(XkBminus, XIDB, XinitB, XacceptB, XconnectB, XSIB)).

  (* Reordering *)
  query XkAminus: skey, XIDA: pkey, XinitA: channel, XacceptA: channel, XconnectA: channel, XSIA: idset, XkBminus: skey, XIDB: pkey, XinitB: channel, XacceptB: channel, XconnectB: channel, XSIB: idset, XIDRp: pkey, XsaI: sainfo, XsaR: sainfo, XKv: key, XeR: bitstring, XhR: key, XNI: nonce, XNR: nonce, XxI: G, XxR: G, XtR: key, XeI: bitstring, XhI: key, XtRp: key, XgR: grpinfo, XxIp: G;
    inj-event(connecthonest(XconnectA, XIDB, XIDRp, XsaI, XsaR, XKv)) ==>
                  event(princ(XkAminus, XIDA, XinitA, XacceptA, XconnectA, XSIA))
                && event(princ(XkBminus, XIDB, XinitB, XacceptB, XconnectB, XSIB))
		&&(inj-event(mess4rec(XIDA, XeR, XhR, XconnectA, XIDB, XIDRp, XsaI, XsaR, XKv)) ==>
                 (inj-event(mess4(XIDB, XIDA, XeR, XhR, XNI, XNR, XxI, XxR, XtR, XeI, XhI)) ==>
                 (inj-event(acceptev(XacceptB, XIDA, XIDRp, XsaI, XsaR, XKv)) ==>
	         (inj-event(mess3rec(XIDB, XNI, XNR, XxI, XxR, XtR, XeI, XhI)) ==>
		 (inj-event(mess3(XIDA, XNI, XNR, XxI, XxR, XtRp, XeI, XhI, XgR, XIDRp, XsaI, XKv)) ==>
		 (inj-event(mess2rec(XIDA, XNI, XNR, XxR, XgR, XtRp, XxI, XIDRp, XsaI)) ==>
		 (inj-event(mess2(XIDB, XNI, XNR, XxIp, XxR, XgR, XtR)) ==>
                  inj-event(mess1rec(XIDB, XNI, XxIp)))
		&&(inj-event(mess1(XIDA, XNI, XxI, XinitA, XIDRp, XsaI)) ==>
	          inj-event(initev(XinitA, XIDRp, XsaI))))))))).


(* ProVerif cannot prove the next nested query;
   it can be proved using a manual argument from the nested query above *)
  query XkAminus: skey, XIDA: pkey, XinitA: channel, XacceptA: channel, XconnectA: channel, XSIA: idset, XkBminus: skey, XIDB: pkey, XinitB: channel, XacceptB: channel, XconnectB: channel, XSIB: idset, XIDRp: pkey, XsaI: sainfo, XsaR: sainfo, XKv: key, XeR: bitstring, XhR: key, XNI: nonce, XNR: nonce, XxI: G, XxR: G, XtR: key, XeI: bitstring, XhI: key, XtRp: key, XgR: grpinfo, XxIp: G;
    inj-event(connecthonest(XconnectA, XIDB, XIDRp, XsaI, XsaR, XKv)) ==>
                  event(princ(XkAminus, XIDA, XinitA, XacceptA, XconnectA, XSIA))
                && event(princ(XkBminus, XIDB, XinitB, XacceptB, XconnectB, XSIB))
		&&(inj-event(mess4rec(XIDA, XeR, XhR, XconnectA, XIDB, XIDRp, XsaI, XsaR, XKv)) ==>
                 (inj-event(mess4(XIDB, XIDA, XeR, XhR, XNI, XNR, XxI, XxR, XtR, XeI, XhI)) ==>
                 (inj-event(acceptev(XacceptB, XIDA, XIDRp, XsaI, XsaR, XKv)) ==>
	         (inj-event(mess3rec(XIDB, XNI, XNR, XxI, XxR, XtR, XeI, XhI)) ==>
		 (inj-event(mess3(XIDA, XNI, XNR, XxI, XxR, XtRp, XeI, XhI, XgR, XIDRp, XsaI, XKv)) ==>
		 (inj-event(mess2rec(XIDA, XNI, XNR, XxR, XgR, XtRp, XxI, XIDRp, XsaI)) ==>
		 (inj-event(mess2(XIDB, XNI, XNR, XxIp, XxR, XgR, XtR)) ==>
                 (inj-event(mess1rec(XIDB, XNI, XxIp)) ==>
		 (inj-event(mess1(XIDA, XNI, XxI, XinitA, XIDRp, XsaI)) ==>
	          inj-event(initev(XinitA, XIDRp, XsaI))))))))))).

(* The next nested query is wrong. In fact, even the simplified non-nested, non-injective query
   is wrong.
   (The identities IDA and IDB have been swapped in mess4rec) *)

  query XkAminus: skey, XIDA: pkey, XinitA: channel, XacceptA: channel, XconnectA: channel, XSIA: idset, XkBminus: skey, XIDB: pkey, XinitB: channel, XacceptB: channel, XconnectB: channel, XSIB: idset, XIDRp: pkey, XsaI: sainfo, XsaR: sainfo, XKv: key, XeR: bitstring, XhR: key, XNI: nonce, XNR: nonce, XxI: G, XxR: G, XtR: key, XeI: bitstring, XhI: key, XtRp: key, XgR: grpinfo, XxIp: G;
    inj-event(connecthonest(XconnectA, XIDB, XIDRp, XsaI, XsaR, XKv)) ==>
                  event(princ(XkAminus, XIDA, XinitA, XacceptA, XconnectA, XSIA))
                && event(princ(XkBminus, XIDB, XinitB, XacceptB, XconnectB, XSIB))
		&&(inj-event(mess4rec(XIDB, XeR, XhR, XconnectA, XIDA, XIDRp, XsaI, XsaR, XKv)) ==>
                 (inj-event(mess4(XIDB, XIDA, XeR, XhR, XNI, XNR, XxI, XxR, XtR, XeI, XhI)) ==>
                 (inj-event(acceptev(XacceptB, XIDA, XIDRp, XsaI, XsaR, XKv)) ==>
	         (inj-event(mess3rec(XIDB, XNI, XNR, XxI, XxR, XtR, XeI, XhI)) ==>
		 (inj-event(mess3(XIDA, XNI, XNR, XxI, XxR, XtRp, XeI, XhI, XgR, XIDRp, XsaI, XKv)) ==>
		 (inj-event(mess2rec(XIDA, XNI, XNR, XxR, XgR, XtRp, XxI, XIDRp, XsaI)) ==>
		 (inj-event(mess2(XIDB, XNI, XNR, XxIp, XxR, XgR, XtR)) ==>
                 (inj-event(mess1rec(XIDB, XNI, XxIp)) ==>
		 (inj-event(mess1(XIDA, XNI, XxI, XinitA, XIDRp, XsaI)) ==>
	          inj-event(initev(XinitA, XIDRp, XsaI))))))))))).

(* The next nested query is wrong. In fact, even the simplified non-nested query
   is wrong. However, the simplified non-nested, non-injective query is true.
   (injectivity does not hold for princ) *)
  query XkAminus: skey, XIDA: pkey, XinitA: channel, XacceptA: channel, XconnectA: channel, XSIA: idset, XkBminus: skey, XIDB: pkey, XinitB: channel, XacceptB: channel, XconnectB: channel, XSIB: idset, XIDRp: pkey, XsaI: sainfo, XsaR: sainfo, XKv: key, XeR: bitstring, XhR: key, XNI: nonce, XNR: nonce, XxI: G, XxR: G, XtR: key, XeI: bitstring, XhI: key, XtRp: key, XgR: grpinfo, XxIp: G;
    inj-event(connecthonest(XconnectA, XIDB, XIDRp, XsaI, XsaR, XKv)) ==>
                  inj-event(princ(XkAminus, XIDA, XinitA, XacceptA, XconnectA, XSIA))
                && inj-event(princ(XkBminus, XIDB, XinitB, XacceptB, XconnectB, XSIB))
		&&(inj-event(mess4rec(XIDA, XeR, XhR, XconnectA, XIDB, XIDRp, XsaI, XsaR, XKv)) ==>
                 (inj-event(mess4(XIDB, XIDA, XeR, XhR, XNI, XNR, XxI, XxR, XtR, XeI, XhI)) ==>
                 (inj-event(acceptev(XacceptB, XIDA, XIDRp, XsaI, XsaR, XKv)) ==>
	         (inj-event(mess3rec(XIDB, XNI, XNR, XxI, XxR, XtR, XeI, XhI)) ==>
		 (inj-event(mess3(XIDA, XNI, XNR, XxI, XxR, XtRp, XeI, XhI, XgR, XIDRp, XsaI, XKv)) ==>
		 (inj-event(mess2rec(XIDA, XNI, XNR, XxR, XgR, XtRp, XxI, XIDRp, XsaI)) ==>
		 (inj-event(mess2(XIDB, XNI, XNR, XxIp, XxR, XgR, XtR)) ==>
                 (inj-event(mess1rec(XIDB, XNI, XxIp)) ==>
		 (inj-event(mess1(XIDA, XNI, XxI, XinitA, XIDRp, XsaI)) ==>
	          inj-event(initev(XinitA, XIDRp, XsaI))))))))))).


(* Note the presence of XtRp in events mess3 and mess2rec
     and XxIp in events mess2 and mess1rec, instead of
     XtR and XxI respectively *)






(* Secrecy *)



(* Identity protection.
   The predicate member must be removed, because it is not supported
   for observational equivalence proofs. So we use a version without cache.
   Only compliant principals are allowed to connect to R. *)




(* Secrecy assumptions *)

not attacker(new kAminus) phase 0.

not attacker(new d).


(* Initiator
   The process processI corresponds to I^A in the figure. *)

let processI(c: channel, exponent: channel, init: channel, connect: channel, honestC: channel, IDA: pkey, kAminus: skey) =
  !
  in(exponent, (dI: texponent, xI: G));
  !
  in(init, (IDRp: pkey, saI: sainfo));    (* Init message *)
  event initev(init, IDRp, saI);
  new NI: nonce;
  event mess1(IDA, NI, xI, init, IDRp, saI);
  out(c, cons1(NI, xI));
  in(c, cons2(=NI, NR, xR, grpinfoR, tR));
  event mess2rec(IDA, NI, NR, xR, grpinfoR, tR, xI, IDRp, saI);
  event enddosi(IDA, NI);
  let h = G_to_key(exp(xR, dI)) in
  let Ka = H(h, (NI, NR, tagA)) in
  let Ke = H(h, (NI, NR, tagE)) in
  let Kv = H(h, (NI, NR, tagV)) in
  let sI = S(kAminus, (NI, NR, xI, xR, grpinfoR)) in
  let eI = E(Ke, (IDA, IDRp, saI, sI)) in
  let hI = H(Ka, (constI, eI)) in
  event mess3(IDA, NI, NR, xI, xR, tR, eI, hI, grpinfoR, IDRp, saI, Kv);
  out(c, cons3(NI, NR, xI, xR, tR, eI, hI));
  in(c, cons4(eR, hR));
  if H(Ka, (constR, eR)) = hR then
  let (IDRl:pkey, saR: sainfo, sR: bitstring) = D(Ke, eR) in
  if V(sR, IDRl, (NI, NR, xI, xR)) then
  event mess4rec(IDA, eR, hR, connect, IDRl, IDRp, saI, saR, Kv);
  event connectev(connect, IDRl, IDRp, saI, saR, Kv);
  out(connect, (IDRl, IDRp, saI, saR, Kv));
  (
(
      in(honestC, =IDRl);
      event connecthonest(connect, IDRl, IDRp, saI, saR, Kv)
    )
  |

    (

      0
    )
  ).

(* Responder
   The process processR corresponds to R^A in the figure. *)

free grpinfoR: grpinfo.
const saR: sainfo [data].

let processR4(c: channel, accept: channel, honestC: channel, IDA: pkey, kAminus: skey, NI: nonce, NR: nonce, xI: G, xR: G, dR: texponent, tR: key, eI: bitstring, hI: key, SIA: idset) =
  event enddosr(IDA, NI, NR);
  let h = G_to_key(exp(xI,dR)) in
  let Ka = H(h, (NI, NR, tagA)) in
  let Ke = H(h, (NI, NR, tagE)) in
  let Kv = H(h, (NI, NR, tagV)) in
  if H(Ka, (constI, eI)) = hI then
  let (IDIl: pkey, IDRp: pkey, saI: sainfo, sI: bitstring) = D(Ke,eI) in

  if memberid(IDIl,SIA) then

  if V(sI, IDIl, (NI, NR, xI, xR, grpinfoR)) then
  event acceptev(accept, IDIl, IDRp, saI, saR, Kv);
  out(accept, (IDIl, IDRp, saI, saR, Kv));
  (
(
      in(honestC, =IDIl);
      event accepthonest(accept, IDIl, IDRp, saI, saR, Kv)
    )
  |

    (
      let sR = S(kAminus, (NI, NR, xI, xR)) in
      let eR = E(Ke, (IDA, saR, sR)) in
      let hR = H(Ka, (constR, eR)) in
      event mess4(IDA, IDIl, eR, hR, NI, NR, xI, xR, tR, eI, hI);
      out(c, cons4(eR, hR));

      0
    )
  ).




let processR(c: channel, exponent: channel, accept: channel, honestC: channel, IDA: pkey, kAminus: skey, SIA: idset) =
  new KR: key;
  !
  in(exponent, (dR: texponent, xR: G));
  !
  in(c, cons1(NI, xI));
  event mess1rec(IDA, NI, xI);
  new NR: nonce;
  new tR: key;
  event mess2(IDA, NI, NR, xI, xR, grpinfoR, tR);
  out(c, cons2(NI, NR, xR, grpinfoR, tR));
  new l: channel;
  (
    (
    !
    in(c, cons3(=NI,=NR,xI,=xR,=tR,eI,hI));
    out(l, (xI,eI,hI))
    )
  |
    (
    in(l, (xI: G,eI: bitstring,hI: key));
    event mess3rec(IDA, NI, NR, xI, xR, tR, eI, hI);
    processR4(c, accept, honestC, IDA, kAminus, NI, NR, xI, xR, dR, tR, eI, hI, SIA)
    )
  ).




(* Free names *)

free c: channel. (* Public channel *)
free pub, getprinc, getexponential, channelSIAR1, channelSIAR2: channel.

(* Whole JFK system. *)

(* Standard version of the process *)

process

  new exponent: channel;
  new honestC: channel;  (* private channel used to simulate the set C of honest principals *)
  ( ! new d: texponent; let x = exp(g,d) in out(getexponential, x); ! out(exponent, (d,x)) )
  |
  !
  new kAminus: skey;
  let IDA = Pk(kAminus) in
  new connect: channel; new accept: channel; new init: channel; new channelSIA: channel;
out(getprinc, (IDA, init, accept, connect, channelSIA));
  in(channelSIA, SIA: idset);
  event princ(kAminus, IDA, init, accept, connect, SIA);
  (
    (! out(honestC, IDA) )   (* IDA is in C *)
  | processI(c, exponent, init, connect, honestC, IDA, kAminus)
  | processR(c, exponent, accept, honestC, IDA, kAminus, SIA)
  )

(* EXPECTPV
RESULT inj-event(enddosr(XIDA,XNI,XNR)) ==> event(princ(XkAminus,XIDA,XinitA,XacceptA,XconnectA,XSIA)) && (inj-event(mess3rec(XIDA,XNI,XNR,XxI,XxR,XtR,XeI,XhI)) ==> (inj-event(mess2(XIDA,XNI,XNR,XxIp,XxR,XgrpinfoR,XtR)) ==> inj-event(mess1rec(XIDA,XNI,XxIp)))) is true.
RESULT inj-event(accepthonest(XacceptB,XIDA,XIDRp,XsaI,XsaR,XKv)) ==> inj-event(initev(XinitA,XIDRp,XsaI)) && event(princ(XkAminus,XIDA,XinitA,XacceptA,XconnectA,XSIA)) && event(princ(XkBminus,XIDB,XinitB,XacceptB,XconnectB,XSIB)) is true.
RESULT inj-event(connecthonest(XconnectA,XIDB,XIDRp,XsaI,XsaR,XKv)) ==> event(princ(XkAminus,XIDA,XinitA,XacceptA,XconnectA,XSIA)) && event(princ(XkBminus,XIDB,XinitB,XacceptB,XconnectB,XSIB)) && (inj-event(mess4rec(XIDA,XeR,XhR,XconnectA,XIDB,XIDRp,XsaI,XsaR,XKv)) ==> (inj-event(mess4(XIDB,XIDA,XeR,XhR,XNI,XNR,XxI,XxR,XtR,XeI,XhI)) ==> (inj-event(acceptev(XacceptB,XIDA,XIDRp,XsaI,XsaR,XKv)) ==> (inj-event(mess3rec(XIDB,XNI,XNR,XxI,XxR,XtR,XeI,XhI)) ==> (inj-event(mess3(XIDA,XNI,XNR,XxI,XxR,XtRp,XeI,XhI,XgR,XIDRp,XsaI,XKv)) ==> (inj-event(mess2rec(XIDA,XNI,XNR,XxR,XgR,XtRp,XxI,XIDRp,XsaI)) ==> (inj-event(mess2(XIDB,XNI,XNR,XxIp,XxR,XgR,XtR)) ==> inj-event(mess1rec(XIDB,XNI,XxIp))) && (inj-event(mess1(XIDA,XNI,XxI,XinitA,XIDRp,XsaI)) ==> inj-event(initev(XinitA,XIDRp,XsaI))))))))) is true.
RESULT inj-event(connecthonest(XconnectA,XIDB,XIDRp,XsaI,XsaR,XKv)) ==> event(princ(XkAminus,XIDA,XinitA,XacceptA,XconnectA,XSIA)) && event(princ(XkBminus,XIDB,XinitB,XacceptB,XconnectB,XSIB)) && (inj-event(mess4rec(XIDA,XeR,XhR,XconnectA,XIDB,XIDRp,XsaI,XsaR,XKv)) ==> (inj-event(mess4(XIDB,XIDA,XeR,XhR,XNI,XNR,XxI,XxR,XtR,XeI,XhI)) ==> (inj-event(acceptev(XacceptB,XIDA,XIDRp,XsaI,XsaR,XKv)) ==> (inj-event(mess3rec(XIDB,XNI,XNR,XxI,XxR,XtR,XeI,XhI)) ==> (inj-event(mess3(XIDA,XNI,XNR,XxI,XxR,XtRp,XeI,XhI,XgR,XIDRp,XsaI,XKv)) ==> (inj-event(mess2rec(XIDA,XNI,XNR,XxR,XgR,XtRp,XxI,XIDRp,XsaI)) ==> (inj-event(mess2(XIDB,XNI,XNR,XxIp,XxR,XgR,XtR)) ==> (inj-event(mess1rec(XIDB,XNI,XxIp)) ==> (inj-event(mess1(XIDA,XNI,XxI,XinitA,XIDRp,XsaI)) ==> inj-event(initev(XinitA,XIDRp,XsaI))))))))))) is true.
RESULT inj-event(connecthonest(XconnectA,XIDB,XIDRp,XsaI,XsaR,XKv)) ==> event(princ(XkAminus,XIDA,XinitA,XacceptA,XconnectA,XSIA)) && event(princ(XkBminus,XIDB,XinitB,XacceptB,XconnectB,XSIB)) && (inj-event(mess4rec(XIDB,XeR,XhR,XconnectA,XIDA,XIDRp,XsaI,XsaR,XKv)) ==> (inj-event(mess4(XIDB,XIDA,XeR,XhR,XNI,XNR,XxI,XxR,XtR,XeI,XhI)) ==> (inj-event(acceptev(XacceptB,XIDA,XIDRp,XsaI,XsaR,XKv)) ==> (inj-event(mess3rec(XIDB,XNI,XNR,XxI,XxR,XtR,XeI,XhI)) ==> (inj-event(mess3(XIDA,XNI,XNR,XxI,XxR,XtRp,XeI,XhI,XgR,XIDRp,XsaI,XKv)) ==> (inj-event(mess2rec(XIDA,XNI,XNR,XxR,XgR,XtRp,XxI,XIDRp,XsaI)) ==> (inj-event(mess2(XIDB,XNI,XNR,XxIp,XxR,XgR,XtR)) ==> (inj-event(mess1rec(XIDB,XNI,XxIp)) ==> (inj-event(mess1(XIDA,XNI,XxI,XinitA,XIDRp,XsaI)) ==> inj-event(initev(XinitA,XIDRp,XsaI))))))))))) is false.
RESULT (even event(connecthonest(XconnectA,XIDB,XIDRp,XsaI,XsaR,XKv)) ==> event(princ(XkAminus,XIDA,XinitA,XacceptA,XconnectA,XSIA)) && event(princ(XkBminus,XIDB,XinitB,XacceptB,XconnectB,XSIB)) && event(mess4rec(XIDB,XeR,XhR,XconnectA,XIDA,XIDRp,XsaI,XsaR,XKv)) && event(mess4(XIDB,XIDA,XeR,XhR,XNI,XNR,XxI,XxR,XtR,XeI,XhI)) && event(acceptev(XacceptB,XIDA,XIDRp,XsaI,XsaR,XKv)) && event(mess3rec(XIDB,XNI,XNR,XxI,XxR,XtR,XeI,XhI)) && event(mess3(XIDA,XNI,XNR,XxI,XxR,XtRp,XeI,XhI,XgR,XIDRp,XsaI,XKv)) && event(mess2rec(XIDA,XNI,XNR,XxR,XgR,XtRp,XxI,XIDRp,XsaI)) && event(mess2(XIDB,XNI,XNR,XxIp,XxR,XgR,XtR)) && event(mess1rec(XIDB,XNI,XxIp)) && event(mess1(XIDA,XNI,XxI,XinitA,XIDRp,XsaI)) && event(initev(XinitA,XIDRp,XsaI)) is false.)
RESULT inj-event(connecthonest(XconnectA,XIDB,XIDRp,XsaI,XsaR,XKv)) ==> inj-event(princ(XkAminus,XIDA,XinitA,XacceptA,XconnectA,XSIA)) && inj-event(princ(XkBminus,XIDB,XinitB,XacceptB,XconnectB,XSIB)) && (inj-event(mess4rec(XIDA,XeR,XhR,XconnectA,XIDB,XIDRp,XsaI,XsaR,XKv)) ==> (inj-event(mess4(XIDB,XIDA,XeR,XhR,XNI,XNR,XxI,XxR,XtR,XeI,XhI)) ==> (inj-event(acceptev(XacceptB,XIDA,XIDRp,XsaI,XsaR,XKv)) ==> (inj-event(mess3rec(XIDB,XNI,XNR,XxI,XxR,XtR,XeI,XhI)) ==> (inj-event(mess3(XIDA,XNI,XNR,XxI,XxR,XtRp,XeI,XhI,XgR,XIDRp,XsaI,XKv)) ==> (inj-event(mess2rec(XIDA,XNI,XNR,XxR,XgR,XtRp,XxI,XIDRp,XsaI)) ==> (inj-event(mess2(XIDB,XNI,XNR,XxIp,XxR,XgR,XtR)) ==> (inj-event(mess1rec(XIDB,XNI,XxIp)) ==> (inj-event(mess1(XIDA,XNI,XxI,XinitA,XIDRp,XsaI)) ==> inj-event(initev(XinitA,XIDRp,XsaI))))))))))) is false.
RESULT (even inj-event(connecthonest(XconnectA,XIDB,XIDRp,XsaI,XsaR,XKv)) ==> inj-event(princ(XkAminus,XIDA,XinitA,XacceptA,XconnectA,XSIA)) && inj-event(princ(XkBminus,XIDB,XinitB,XacceptB,XconnectB,XSIB)) && inj-event(mess4rec(XIDA,XeR,XhR,XconnectA,XIDB,XIDRp,XsaI,XsaR,XKv)) is false.)
37.624s (user 37.468s + system 0.156s), max rss 304404K
END *)
