free c:channel.
free ct:channel.
free cr:channel.
free error_mac:bitstring.
free init:bitstring.
free read:bitstring.
free ok:bitstring.

const g:bitstring [data].

free tokenR:bitstring.
free tokenP:bitstring.

fun gen(bitstring,bitstring):bitstring.
fun exp(bitstring,bitstring):bitstring.

equation forall x:bitstring,y:bitstring; exp(exp(g,x),y) = exp(exp(g,y),x).
equation forall x:bitstring,y:bitstring,a:bitstring,b:bitstring; exp(exp(gen(a,b),x),y) = exp(exp(gen(a,b),y),x).

fun enc(bitstring,bitstring):bitstring.
fun dec(bitstring,bitstring):bitstring.

equation forall x:bitstring,y:bitstring; dec(enc(x,y),y) = x.

fun mac(bitstring,bitstring):bitstring.

event Rin_1(bitstring,bitstring,bitstring).
event Rout_1(bitstring,bitstring,bitstring,bitstring).
event Rin_2(bitstring,bitstring,bitstring,bitstring,bitstring).
event Rtest_1(bitstring,bitstring,bitstring,bitstring,bitstring).
event Rout_2(bitstring,bitstring,bitstring,bitstring,bitstring,bitstring).
event Rin_3(bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring).
event Rtest_2(bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring).
event Rout_3(bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring).
event Rin_4(bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring).
event Rtest_3(bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring).
event Rout_4(bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring).
event Iout_1(bitstring,bitstring,bitstring).
event Iin_1(bitstring,bitstring,bitstring,bitstring).
event Iout_2(bitstring,bitstring,bitstring,bitstring,bitstring).
event Iin_2(bitstring,bitstring,bitstring,bitstring,bitstring,bitstring).
event Itest_1(bitstring,bitstring,bitstring,bitstring,bitstring,bitstring).
event Iout_3(bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring).
event Iin_3(bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring).
event Itest_2(bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring).
event Iout_4(bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring,bitstring).

type stamp.

free id:stamp [private].

not attacker(new dR).
not attacker(new dP).

set preciseActions = true.
event Counter(channel,stamp,stamp,nat).

event TermInput1(bitstring,nat).
event TermInput2(bitstring,nat).
event TermInput3(bitstring,nat).

event TermInput4(bitstring,nat).
event TermInput5(bitstring,nat).
event TermInput6(bitstring,nat).
event TermInput7(bitstring,nat).

axiom x:bitstring,k:bitstring,n1:bitstring,n2:bitstring,m1:bitstring,m2:bitstring,m3:bitstring,m4:bitstring,m5:bitstring,m6:bitstring,m7:bitstring,i:nat,i1:nat,st:stamp,st1:stamp,st2:stamp,d:channel;
  event(Counter(d,st2,st,i1)) && event(Counter(d,st2,st,i)) ==> i1 = i;
  event(Counter(d,st2,st,i1)) && event(Counter(d,st2,st1,i1)) ==> st = st1;
  event(TermInput1(x,i)) && subterm(new s[i=i1],x) ==> i1 <= i;
  event(TermInput1(x,i)) && subterm(new b1[i=i1],x) ==> i1 < i;
  event(TermInput1(x,i)) && subterm(new b2[i=i1],x) ==> i1 < i;
  event(TermInput2(x,i)) && subterm(new s[i=i1],x) ==> i1 <= i;
  event(TermInput2(x,i)) && subterm(new b1[i=i1],x) ==> i1 <= i;
  event(TermInput2(x,i)) && subterm(new b2[i=i1],x) ==> i1 < i;
  event(TermInput3(x,i)) && subterm(new s[i=i1],x) ==> i1 <= i;
  event(TermInput3(x,i)) && subterm(new b1[i=i1],x) ==> i1 <= i;
  event(TermInput3(x,i)) && subterm(new b2[i=i1],x) ==> i1 <= i;


  event(TermInput4(x,i)) && subterm(new a1[i'=i1],x) ==> i1 < i;
  event(TermInput4(x,i)) && subterm(new a2[i'=i1],x) ==> i1 < i;
  event(TermInput5(x,i)) && subterm(new a1[i'=i1],x) ==> i1 <= i;
  event(TermInput5(x,i)) && subterm(new a2[i'=i1],x) ==> i1 < i;
  event(TermInput6(x,i)) && subterm(new a1[i'=i1],x) ==> i1 <= i;
  event(TermInput6(x,i)) && subterm(new a2[i'=i1],x) ==> i1 <= i;
  event(TermInput7(x,i)) && subterm(new a1[i'=i1],x) ==> i1 <= i;
  event(TermInput7(x,i)) && subterm(new a2[i'=i1],x) ==> i1 <= i
  .

axiom d:channel, i:nat, st:stamp, st2:stamp;
  event(Counter(d,st2,st,i)) ==> is_nat(i).

query k:bitstring,n1:bitstring,n2:bitstring,m1:bitstring,m2:bitstring,m3:bitstring,m4:bitstring,m5:bitstring,m6:bitstring,m7:bitstring,i:nat,i1:nat,st:stamp,st1:stamp,st2:stamp,d:channel;
  event(Rtest_3(k,n2,m1,m2,m3,m4,m5,m6,m7)) ==>
    (event(Rin_4(k,n2,m1,m2,m3,m4,m5,m6,m7)) ==>
    (event(Iout_4(k,n1,m1,m2,m3,m4,m5,m6,m7)) ==>
    (event(Iin_3(k,n1,m1,m2,m3,m4,m5,m6)) ==>
    (event(Rout_3(k,n2,m1,m2,m3,m4,m5,m6)) ==>
    (event(Rin_3(k,n2,m1,m2,m3,m4,m5)) ==>
    (event(Iout_3(k,n1,m1,m2,m3,m4,m5)) ==>
    (event(Iin_2(k,n1,m1,m2,m3,m4)) ==>
    (event(Rout_2(k,n2,m1,m2,m3,m4)) ==>
    (event(Rin_2(k,n2,m1,m2,m3)) ==>
    (event(Iout_2(k,n1,m1,m2,m3)) ==>
    (event(Iin_1(k,n1,m1,m2)) ==>
    (event(Rout_1(k,n2,m1,m2)) ==>
    (event(Rin_1(k,n2,m1)) ==>
    (event(Iout_1(k,n1,m1))))))))))))))));

   (event(Rtest_2(k,n2,m1,m2,m3,m4,m5))  ==>
   (event(Rin_3(k,n2,m1,m2,m3,m4,m5))  ==>
   (event(Iout_3(k,n1,m1,m2,m3,m4,m5))  ==>
   (event(Iin_2(k,n1,m1,m2,m3,m4))  ==>
   (event(Rout_2(k,n2,m1,m2,m3,m4))  ==>
   (event(Rin_2(k,n2,m1,m2,m3))  ==>
   (event(Iout_2(k,n1,m1,m2,m3))  ==>
   (event(Iin_1(k,n1,m1,m2))  ==>
   (event(Rout_1(k,n2,m1,m2))  ==>
   (event(Rin_1(k,n2,m1))  ==>
   (event(Iout_1(k,n1,m1)))))))))))));

   (event(Rtest_1(k,n2,m1,m2,m3))  ==>
   (event(Rin_2(k,n2,m1,m2,m3))  ==>
   (event(Iout_2(k,n1,m1,m2,m3))  ==>
   (event(Iin_1(k,n1,m1,m2))  ==>
   (event(Rout_1(k,n2,m1,m2))  ==>
   (event(Rin_1(k,n2,m1))  ==>
   (event(Iout_1(k,n1,m1)))))))));

   (event(Itest_2(k,n1,m1,m2,m3,m4,m5,m6))  ==>
   (event(Iin_3(k,n1,m1,m2,m3,m4,m5,m6))  ==>
   (event(Rout_3(k,n2,m1,m2,m3,m4,m5,m6))  ==>
   (event(Rin_3(k,n2,m1,m2,m3,m4,m5))  ==>
   (event(Iout_3(k,n1,m1,m2,m3,m4,m5))  ==>
   (event(Iin_2(k,n1,m1,m2,m3,m4))  ==>
   (event(Rout_2(k,n2,m1,m2,m3,m4))  ==>
   (event(Rin_2(k,n2,m1,m2,m3))  ==>
   (event(Iout_2(k,n1,m1,m2,m3))  ==>
   (event(Iin_1(k,n1,m1,m2))  ==>
   (event(Rout_1(k,n2,m1,m2))  ==>
   (event(Rin_1(k,n2,m1))  ==>
   (event(Iout_1(k,n1,m1)))))))))))))));

   (event(Itest_1(k,n1,m1,m2,m3,m4))  ==>
   (event(Iin_2(k,n1,m1,m2,m3,m4))  ==>
   (event(Rout_2(k,n2,m1,m2,m3,m4))  ==>
   (event(Rin_2(k,n2,m1,m2,m3))  ==>
   (event(Iout_2(k,n1,m1,m2,m3))  ==>
   (event(Iin_1(k,n1,m1,m2))  ==>
   (event(Rout_1(k,n2,m1,m2))  ==>
   (event(Rin_1(k,n2,m1))  ==>
   (event(Iout_1(k,n1,m1))))))))))).

query m6:bitstring,m5:bitstring,m4:bitstring,m3:bitstring,m2:bitstring,m1:bitstring,i:nat,i1:nat,st:stamp,st1:stamp,st2:stamp,d:channel;
  event(Itest_1(m6,m5,m4,m3,m2,m1)).

query m5:bitstring,m4:bitstring,m3:bitstring,m2:bitstring,m1:bitstring,i:nat,i1:nat,st:stamp,st1:stamp,st2:stamp,d:channel;
  event(Rtest_1(m5,m4,m3,m2,m1)).

process
  (  (* Application of the process SYSTEM *)
  new k:bitstring;
  new dP:channel;
  new dR:channel;
  (
    out(dP,0);
    0
  ) | (
    out(dR,0);
    0
  ) | (
    !(
    (
      in(dP,i:nat);
      new st[]:stamp;
      event Counter(dP,id,st,i);
      new sess_I:bitstring;
      new s:bitstring;
      event Iout_1(k,sess_I,enc(s,k));
      out(ct,enc(s,k));
      in(ct,x1:bitstring);
      event TermInput1(x1,i);
      event Iin_1(k,sess_I,enc(s,k),x1);
      new b1:bitstring;
      event Iout_2(k,sess_I,enc(s,k),x1,exp(g,b1));
      out(ct,exp(g,b1));
      in(ct,x2:bitstring);
      event TermInput2(x2,i);
      event Iin_2(k,sess_I,enc(s,k),x1,exp(g,b1),x2);
      let newG:bitstring = gen(exp(g,s),exp(x1,b1)) in
      event Itest_1(k,sess_I,enc(s,k),x1,exp(g,b1),x2);
      new b2:bitstring;
      event Iout_3(k,sess_I,enc(s,k),x1,exp(g,b1),x2,exp(newG,b2));
      out(ct,exp(newG,b2));
      in(ct,x3:bitstring);
      event TermInput3(x3,i);
      event Iin_3(k,sess_I,enc(s,k),x1,exp(g,b1),x2,exp(newG,b2),x3);
      let newKey:bitstring = exp(x2,b2) in
      if mac(exp(newG,b2),newKey) = x3
      then
        event Itest_2(k,sess_I,enc(s,k),x1,exp(g,b1),x2,exp(newG,b2),x3);
        event Iout_4(k,sess_I,enc(s,k),x1,exp(g,b1),x2,exp(newG,b2),x3,mac(x2,newKey));
        out(cr,mac(x2,newKey));
        out(dP,i + 1);
        0
      else
        out(dP,i + 1);
        0
    ) | (
      in(dR,i':nat);
      new st[]:stamp;
      event Counter(dR,id,st,i');
      in(cr,y1:bitstring);
      event TermInput4(y1,i');
      new sess_R:bitstring;
      event Rin_1(k,sess_R,y1);
      new a1:bitstring;
      event Rout_1(k,sess_R,y1,exp(g,a1));
      out(cr,exp(g,a1));
      in(cr,y2:bitstring);
      event TermInput5(y2,i');
      event Rin_2(k,sess_R,y1,exp(g,a1),y2);
      let newG_58:bitstring = gen(exp(g,dec(y1,k)),exp(y2,a1)) in
      event Rtest_1(k,sess_R,y1,exp(g,a1),y2);
      new a2:bitstring;
      event Rout_2(k,sess_R,y1,exp(g,a1),y2,exp(newG_58,a2));
      out(cr,exp(newG_58,a2));
      in(cr,y3:bitstring);
      event TermInput6(y3,i');
      event Rin_3(k,sess_R,y1,exp(g,a1),y2,exp(newG_58,a2),y3);
      if y3 <> exp(newG_58,a2)
      then
        let newKey_59:bitstring = exp(y3,a2) in
        event Rtest_2(k,sess_R,y1,exp(g,a1),y2,exp(newG_58,a2),y3);
        event Rout_3(k,sess_R,y1,exp(g,a1),y2,exp(newG_58,a2),y3,mac(y3,newKey_59));
        out(cr,mac(y3,newKey_59));
        in(cr,y4:bitstring);
        event TermInput7(y4,i');
        event Rin_4(k,sess_R,y1,exp(g,a1),y2,exp(newG_58,a2),y3,mac(y3,newKey_59),y4);
        if mac(exp(newG_58,a2),newKey_59) = y4
        then
          event Rtest_3(k,sess_R,y1,exp(g,a1),y2,exp(newG_58,a2),y3,mac(y3,newKey_59),y4);
          event Rout_4(k,sess_R,y1,exp(g,a1),y2,exp(newG_58,a2),y3,mac(y3,newKey_59),y4,ok);
          out(cr,ok);
          out(dR,i' + 1);
          0
        else
          out(dR,i' + 1);
          0
      else
        out(dR,i' + 1);
        0
    )
    )  )
  )

(* EXPECTPV
RESULT event(Rtest_3(k_1,n2,m1,m2,m3,m4,m5,m6,m7)) ==> (event(Rin_4(k_1,n2,m1,m2,m3,m4,m5,m6,m7)) ==> (event(Iout_4(k_1,n1,m1,m2,m3,m4,m5,m6,m7)) ==> (event(Iin_3(k_1,n1,m1,m2,m3,m4,m5,m6)) ==> (event(Rout_3(k_1,n2,m1,m2,m3,m4,m5,m6)) ==> (event(Rin_3(k_1,n2,m1,m2,m3,m4,m5)) ==> (event(Iout_3(k_1,n1,m1,m2,m3,m4,m5)) ==> (event(Iin_2(k_1,n1,m1,m2,m3,m4)) ==> (event(Rout_2(k_1,n2,m1,m2,m3,m4)) ==> (event(Rin_2(k_1,n2,m1,m2,m3)) ==> (event(Iout_2(k_1,n1,m1,m2,m3)) ==> (event(Iin_1(k_1,n1,m1,m2)) ==> (event(Rout_1(k_1,n2,m1,m2)) ==> (event(Rin_1(k_1,n2,m1)) ==> event(Iout_1(k_1,n1,m1))))))))))))))) is true.
RESULT event(Rtest_2(k_1,n2,m1,m2,m3,m4,m5)) ==> (event(Rin_3(k_1,n2,m1,m2,m3,m4,m5)) ==> (event(Iout_3(k_1,n1,m1,m2,m3,m4,m5)) ==> (event(Iin_2(k_1,n1,m1,m2,m3,m4)) ==> (event(Rout_2(k_1,n2,m1,m2,m3,m4)) ==> (event(Rin_2(k_1,n2,m1,m2,m3)) ==> (event(Iout_2(k_1,n1,m1,m2,m3)) ==> (event(Iin_1(k_1,n1,m1,m2)) ==> (event(Rout_1(k_1,n2,m1,m2)) ==> (event(Rin_1(k_1,n2,m1)) ==> event(Iout_1(k_1,n1,m1))))))))))) is false.
RESULT (even event(Rtest_2(k_1,n2,m1,m2,m3,m4,m5)) ==> event(Rin_3(k_1,n2,m1,m2,m3,m4,m5)) && event(Iout_3(k_1,n1,m1,m2,m3,m4,m5)) && event(Iin_2(k_1,n1,m1,m2,m3,m4)) && event(Rout_2(k_1,n2,m1,m2,m3,m4)) && event(Rin_2(k_1,n2,m1,m2,m3)) && event(Iout_2(k_1,n1,m1,m2,m3)) && event(Iin_1(k_1,n1,m1,m2)) && event(Rout_1(k_1,n2,m1,m2)) && event(Rin_1(k_1,n2,m1)) && event(Iout_1(k_1,n1,m1)) is false.)
RESULT event(Rtest_1(k_1,n2,m1,m2,m3)) ==> (event(Rin_2(k_1,n2,m1,m2,m3)) ==> (event(Iout_2(k_1,n1,m1,m2,m3)) ==> (event(Iin_1(k_1,n1,m1,m2)) ==> (event(Rout_1(k_1,n2,m1,m2)) ==> (event(Rin_1(k_1,n2,m1)) ==> event(Iout_1(k_1,n1,m1))))))) is false.
RESULT (even event(Rtest_1(k_1,n2,m1,m2,m3)) ==> event(Rin_2(k_1,n2,m1,m2,m3)) && event(Iout_2(k_1,n1,m1,m2,m3)) && event(Iin_1(k_1,n1,m1,m2)) && event(Rout_1(k_1,n2,m1,m2)) && event(Rin_1(k_1,n2,m1)) && event(Iout_1(k_1,n1,m1)) is false.)
RESULT event(Itest_2(k_1,n1,m1,m2,m3,m4,m5,m6)) ==> (event(Iin_3(k_1,n1,m1,m2,m3,m4,m5,m6)) ==> (event(Rout_3(k_1,n2,m1,m2,m3,m4,m5,m6)) ==> (event(Rin_3(k_1,n2,m1,m2,m3,m4,m5)) ==> (event(Iout_3(k_1,n1,m1,m2,m3,m4,m5)) ==> (event(Iin_2(k_1,n1,m1,m2,m3,m4)) ==> (event(Rout_2(k_1,n2,m1,m2,m3,m4)) ==> (event(Rin_2(k_1,n2,m1,m2,m3)) ==> (event(Iout_2(k_1,n1,m1,m2,m3)) ==> (event(Iin_1(k_1,n1,m1,m2)) ==> (event(Rout_1(k_1,n2,m1,m2)) ==> (event(Rin_1(k_1,n2,m1)) ==> event(Iout_1(k_1,n1,m1))))))))))))) is true.
RESULT event(Itest_1(k_1,n1,m1,m2,m3,m4)) ==> (event(Iin_2(k_1,n1,m1,m2,m3,m4)) ==> (event(Rout_2(k_1,n2,m1,m2,m3,m4)) ==> (event(Rin_2(k_1,n2,m1,m2,m3)) ==> (event(Iout_2(k_1,n1,m1,m2,m3)) ==> (event(Iin_1(k_1,n1,m1,m2)) ==> (event(Rout_1(k_1,n2,m1,m2)) ==> (event(Rin_1(k_1,n2,m1)) ==> event(Iout_1(k_1,n1,m1))))))))) is false.
RESULT (even event(Itest_1(k_1,n1,m1,m2,m3,m4)) ==> event(Iin_2(k_1,n1,m1,m2,m3,m4)) && event(Rout_2(k_1,n2,m1,m2,m3,m4)) && event(Rin_2(k_1,n2,m1,m2,m3)) && event(Iout_2(k_1,n1,m1,m2,m3)) && event(Iin_1(k_1,n1,m1,m2)) && event(Rout_1(k_1,n2,m1,m2)) && event(Rin_1(k_1,n2,m1)) && event(Iout_1(k_1,n1,m1)) is false.)
RESULT not event(Itest_1(m6,m5,m4,m3,m2,m1)) is false.
RESULT not event(Rtest_1(m5,m4,m3,m2,m1)) is false.
119.132s (user 118.468s + system 0.664s), max rss 1403940K
END *)
